UNPKG

epic-state

Version:

Reactive state management for frontend libraries.

63 lines (51 loc) 2.02 kB
import { type CallPluginOptions, type Plugin, PluginAction, type PluginActions, type ProxyObject } from './types' const globalPlugins: PluginActions[] = [] export function initializePlugins(state: ProxyObject, plugin: Plugin | Plugin[]) { if (!plugin) { return [] // Can also add plugins later using state.addPlugin(plugin) } const plugins = Array.isArray(plugin) ? plugin : [plugin] return plugins.map((item) => item('initialize', state)) } // NOTE accessing values in here can also lead to recursive calls. export function callPlugins({ type, target, initial = false, ...options }: CallPluginOptions) { // Current plugin. if (target._plugin) { for (const item of target._plugin) { const plugin = item[type] if (plugin && (item.all || options.leaf || type === PluginAction.Delete)) { // @ts-ignore Apply can also be used on arrow functions to override the this. plugin.call(item, options) } } } // TODO make plugin inheritance configurable. // Recursively invoke plugins found on parents (which are inherited). if (target.parent) { callPlugins({ type, target: target.parent, ...options }) } if (!initial) { return } // Global plugins. for (const item of globalPlugins) { const plugin = item[type] if (plugin && (item.all || options.leaf || type === PluginAction.Delete)) { // @ts-ignore plugin.call(item, options) } } } // Register global plugin. export function plugin(plugin: Plugin | PluginActions) { const initializedPlugin = typeof plugin === 'function' ? plugin('initialize') : plugin globalPlugins.push(initializedPlugin) return function removePlugin() { const remainingGlobalPlugins = globalPlugins.filter((currentPlugin) => initializedPlugin !== currentPlugin) globalPlugins.splice(0, globalPlugins.length, ...remainingGlobalPlugins) } } export function removeAllPlugins() { globalPlugins.length = 0 } // TODO destroy an existing state object and it's associated plugins.