UNPKG

genji-core

Version:

The core lightweight library for genji, based on redux and redux-saga.

90 lines (81 loc) 1.94 kB
import invariant from 'invariant'; import { isPlainObject } from './utils'; const hooks = [ 'onError', 'onStateChange', 'onHmr', 'onMutation', 'onAction', 'extraMiddlewares', 'extraModels', 'extraEnhancers', 'extraReducers', ]; export function filterHooks(obj) { return Object.keys(obj).reduce((memo, key) => { if (hooks.indexOf(key) > -1) { memo[key] = obj[key]; } return memo; }, {}); } export default class Plugin { constructor() { this._handleActions = null; this.hooks = hooks.reduce((memo, key) => { memo[key] = []; return memo; }, {}); } use(plugin) { invariant( isPlainObject(plugin), 'plugin.use: plugin should be plain object' ); const hooks = this.hooks; for (const key in plugin) { if (Object.prototype.hasOwnProperty.call(plugin, key)) { invariant(hooks[key], `plugin.use: unknown plugin property: ${key}`); if (key === 'extraEnhancers') { hooks[key] = plugin[key]; } else { hooks[key].push(plugin[key]); } } } } apply(key, defaultHandler) { const hooks = this.hooks; const validApplyHooks = ['onError', 'onHmr']; invariant( validApplyHooks.indexOf(key) > -1, `plugin.apply: hook ${key} cannot be applied` ); const fns = hooks[key]; return (...args) => { if (fns.length) { for (const fn of fns) { fn(...args); } } else if (defaultHandler) { defaultHandler(...args); } }; } get(key) { const hooks = this.hooks; invariant(key in hooks, `plugin.get: hook ${key} cannot be got`); if (key === 'extraReducers') { return getExtraReducers(hooks[key]); } else { return hooks[key]; } } } function getExtraReducers(hook) { let ret = {}; for (const reducerObj of hook) { ret = { ...ret, ...reducerObj }; } return ret; }