Refactor plugin retrieval (#695)

* plugins: refactor props decorators

* plugins: add missing plugin functions to notifier

* plugins: refactor reducer decorators

* bug: make sure reduceTermGroups are added from plugins
This commit is contained in:
Martin Ek 2016-10-08 17:38:47 -04:00 committed by Guillermo Rauch
parent aa285a8bc6
commit fe91b4c76e
2 changed files with 54 additions and 139 deletions

View file

@ -20,11 +20,18 @@ const path = resolve(homedir(), '.hyper_plugins');
const localPath = resolve(homedir(), '.hyper_plugins', 'local');
const availableExtensions = new Set([
'onApp', 'onWindow', 'onUnload', 'middleware',
'reduceUI', 'reduceSessions', 'decorateMenu',
'decorateTerm', 'decorateHyper', 'decorateTab',
'reduceUI', 'reduceSessions', 'reduceTermGroups',
'decorateMenu', 'decorateTerm', 'decorateHyper',
'decorateHyperTerm', // for backwards compatibility with hyperterm
'decorateTab',
'decorateNotification', 'decorateNotifications',
'decorateTabs', 'decorateConfig', 'decorateEnv'
'decorateTabs', 'decorateConfig', 'decorateEnv',
'decorateTermGroup', 'getTermProps',
'getTabProps', 'getTabsProps', 'getTermGroupProps',
'mapHyperTermState', 'mapTermsState',
'mapHeaderState', 'mapNotificationsState',
'mapHyperTermDispatch', 'mapTermsDispatch',
'mapHeaderDispatch', 'mapNotificationsDispatch'
]);
// init plugin directories if not present

View file

@ -35,6 +35,8 @@ let tabPropsDecorators;
let tabsPropsDecorators;
let termPropsDecorators;
let termGroupPropsDecorators;
let propsDecorators;
let reducersDecorators;
// the fs locations where usr plugins are stored
const {path, localPath} = plugins.getBasePaths();
@ -78,6 +80,19 @@ const loadModules = () => {
termPropsDecorators = [];
termGroupPropsDecorators = [];
propsDecorators = {
getTermProps: termPropsDecorators,
getTabProps: tabPropsDecorators,
getTabsProps: tabsPropsDecorators,
getTermGroupProps: termGroupPropsDecorators
};
reducersDecorators = {
reduceUI: uiReducers,
reduceSessions: sessionsReducers,
reduceTermGroups: termGroupsReducers
};
modules = paths.plugins.concat(paths.localPlugins)
.map(path => {
let mod;
@ -123,6 +138,10 @@ const loadModules = () => {
sessionsReducers.push(mod.reduceSessions);
}
if (mod.reduceTermGroups) {
termGroupsReducers.push(mod.reduceTermGroups);
}
if (mod.mapTermsState) {
connectors.Terms.state.push(mod.mapTermsState);
}
@ -191,10 +210,11 @@ export function reload() {
decorated = {};
}
export function getTermGroupProps(uid, parentProps, props) {
function getProps(name, props, ...fnArgs) {
const decorators = propsDecorators[name];
let props_;
termPropsDecorators.forEach(fn => {
decorators.forEach(fn => {
let ret_;
if (!props_) {
@ -202,109 +222,38 @@ export function getTermGroupProps(uid, parentProps, props) {
}
try {
ret_ = fn(uid, parentProps, props_);
ret_ = fn(...fnArgs, props_);
} catch (err) {
console.error(err.stack);
notify('Plugin error', `${fn._pluginName}: Error occurred in \`getTermGroupProps\`. Check Developer Tools for details.`);
notify('Plugin error', `${fn._pluginName}: Error occurred in \`${name}\`. Check Developer Tools for details.`);
return;
}
if (!ret_ || typeof ret_ !== 'object') {
notify('Plugin error', `${fn._pluginName}: Invalid return value of \`getTermGroupProps\` (object expected).`);
notify('Plugin error', `${fn._pluginName}: Invalid return value of \`${name}\` (object expected).`);
return;
}
props = ret_;
props_ = ret_;
});
return props_ || props;
}
export function getTermGroupProps(uid, parentProps, props) {
return getProps('getTermGroupProps', props, uid, parentProps);
}
export function getTermProps(uid, parentProps, props) {
let props_;
termPropsDecorators.forEach(fn => {
let ret_;
if (!props_) {
props_ = Object.assign({}, props);
}
try {
ret_ = fn(uid, parentProps, props_);
} catch (err) {
console.error(err.stack);
notify('Plugin error', `${fn._pluginName}: Error occurred in \`getTermProps\`. Check Developer Tools for details.`);
return;
}
if (!ret_ || typeof ret_ !== 'object') {
notify('Plugin error', `${fn._pluginName}: Invalid return value of \`getTermProps\` (object expected).`);
return;
}
props = ret_;
});
return props_ || props;
return getProps('getTermProps', props, uid, parentProps);
}
export function getTabsProps(parentProps, props) {
let props_;
tabsPropsDecorators.forEach(fn => {
let ret_;
if (!props_) {
props_ = Object.assign({}, props);
}
try {
ret_ = fn(parentProps, props_);
} catch (err) {
console.error(err.stack);
notify('Plugin error', `${fn._pluginName}: Error occurred in \`getTabsProps\`. Check Developer Tools for details.`);
return;
}
if (!ret_ || typeof ret_ !== 'object') {
notify('Plugin error', `${fn._pluginName}: Invalid return value of \`getTabsProps\` (object expected).`);
return;
}
props_ = ret_;
});
return props_ || props;
return getProps('getTabsProps', props, parentProps);
}
export function getTabProps(tab, parentProps, props) {
let props_;
tabPropsDecorators.forEach(fn => {
let ret_;
if (!props_) {
props_ = Object.assign({}, props);
}
try {
ret_ = fn(tab, parentProps, props_);
} catch (err) {
console.error(err.stack);
notify('Plugin error', `${fn._pluginName}: Error occurred in \`getTabProps\`. Check Developer Tools for details.`);
return;
}
if (!ret_ || typeof ret_ !== 'object') {
notify('Plugin error', `${fn._pluginName}: Invalid return value of \`getTabProps\` (object expected).`);
return;
}
props_ = ret_;
});
return props_ || props;
return getProps('getTabProps', props, tab, parentProps);
}
// connects + decorates a class
@ -363,23 +312,24 @@ export function connect(stateFn, dispatchFn, c, d = {}) {
};
}
export function decorateTermGroupsReducer(fn) {
function decorateReducer(name, fn) {
const reducers = reducersDecorators[name];
return (state, action) => {
let state_ = fn(state, action);
termGroupsReducers.forEach(pluginReducer => {
reducers.forEach(pluginReducer => {
let state__;
try {
state__ = pluginReducer(state_, action);
} catch (err) {
console.error(err.stack);
notify('Plugin error', `${fn._pluginName}: Error occurred in \`reduceTermGroups\`. Check Developer Tools for details.`);
notify('Plugin error', `${fn._pluginName}: Error occurred in \`${name}\`. Check Developer Tools for details.`);
return;
}
if (!state__ || typeof state__ !== 'object') {
notify('Plugin error', `${fn._pluginName}: Invalid return value of \`reduceTermGroups\`.`);
notify('Plugin error', `${fn._pluginName}: Invalid return value of \`${name}\`.`);
return;
}
@ -390,58 +340,16 @@ export function decorateTermGroupsReducer(fn) {
};
}
export function decorateTermGroupsReducer(fn) {
return decorateReducer('reduceTermGroups', fn);
}
export function decorateUIReducer(fn) {
return (state, action) => {
let state_ = fn(state, action);
uiReducers.forEach(pluginReducer => {
let state__;
try {
state__ = pluginReducer(state_, action);
} catch (err) {
console.error(err.stack);
notify('Plugin error', `${fn._pluginName}: Error occurred in \`reduceUI\`. Check Developer Tools for details.`);
return;
}
if (!state__ || typeof state__ !== 'object') {
notify('Plugin error', `${fn._pluginName}: Invalid return value of \`reduceUI\`.`);
return;
}
state_ = state__;
});
return state_;
};
return decorateReducer('reduceUI', fn);
}
export function decorateSessionsReducer(fn) {
return (state, action) => {
let state_ = fn(state, action);
sessionsReducers.forEach(pluginReducer => {
let state__;
try {
state__ = pluginReducer(state_, action);
} catch (err) {
console.error(err.stack);
notify('Plugin error', `${fn._pluginName}: Error occurred in \`reduceSessions\`. Check Developer Tools for details.`);
return;
}
if (!state__ || typeof state__ !== 'object') {
notify('Plugin error', `${fn._pluginName}: Invalid return value of \`reduceSessions\`.`);
return;
}
state_ = state__;
});
return state_;
};
return decorateReducer('reduceSessions', fn);
}
// redux middleware generator