import { ConfigurationHooks, DazzleContext } from './types'; import { logger } from './logger'; export type ApplyHookFunction = ( hook: THook, action: (plugin: PluginSupportingHook) => Promise ) => Promise; type PluginSupportingHook = Required>; type NamedThingWithHooks = ConfigurationHooks & { name: string }; function hasHook(hook: THook) { return function (plugin: NamedThingWithHooks): plugin is PluginSupportingHook & NamedThingWithHooks { logger.debug(`Checking if ${plugin.name} has hook ${hook} ${typeof plugin[hook]}`); return typeof plugin[hook] === 'function'; }; } export const applyHook: ApplyHookFunction = async function (this: DazzleContext, hook, action) { logger.debug('Applying hook', hook); const pluginsWithHooks = (this.plugins as NamedThingWithHooks[]).filter(hasHook(hook)); for (const plugin of pluginsWithHooks) { await action(plugin); } if (hasHook(hook)(this)) { await action(this); } };