UNPKG

ts-ioc-container

Version:
67 lines (66 loc) 3.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.runOnDisposeHooks = exports.onDispose = exports.runOnConstructHooks = exports.onConstruct = exports.injectProp = exports.runHooksAsync = exports.runHooks = exports.hook = exports.toHookFn = void 0; exports.getHooks = getHooks; exports.hasHooks = hasHooks; const HookContext_1 = require("./HookContext"); const utils_1 = require("../utils"); const UnexpectedHookResultError_1 = require("../errors/UnexpectedHookResultError"); const inject_1 = require("../injector/inject"); const isHookClassConstructor = (execute) => { return (0, utils_1.isConstructor)(execute) && execute.prototype.execute; }; const toHookFn = (execute) => isHookClassConstructor(execute) ? (context) => context.scope.resolveOne(execute).execute(context) : execute; exports.toHookFn = toHookFn; const hook = (key, ...fns) => (target, propertyKey) => { const hooks = Reflect.hasMetadata(key, target.constructor) ? Reflect.getMetadata(key, target.constructor) : new Map(); hooks.set(propertyKey, (hooks.get(propertyKey) ?? []).concat(fns)); Reflect.defineMetadata(key, hooks, target.constructor); }; exports.hook = hook; function getHooks(target, key) { return Reflect.hasMetadata(key, target.constructor) ? Reflect.getMetadata(key, target.constructor) : new Map(); } function hasHooks(target, key) { return Reflect.hasMetadata(key, target.constructor); } const runHooks = (target, key, { scope, createContext = HookContext_1.createHookContext, predicate = () => true, }) => { const hooks = Array.from(getHooks(target, key).entries()).filter(([methodName]) => predicate(methodName)); const runMethodHooks = (methodName, executions) => { const context = createContext(target, scope, methodName); for (const execute of executions) { const result = execute(context); if (result instanceof Promise) { throw new UnexpectedHookResultError_1.UnexpectedHookResultError(`Hook ${methodName} returned a promise, use runHooksAsync instead`); } } }; for (const [methodName, executions] of hooks) { runMethodHooks(methodName, executions.map(exports.toHookFn)); } }; exports.runHooks = runHooks; const runHooksAsync = (target, key, { scope, createContext = HookContext_1.createHookContext, predicate = () => true, }) => { const hooks = Array.from(getHooks(target, key).entries()).filter(([methodName]) => predicate(methodName)); const runMethodHooks = async (methodName, executions) => { const context = createContext(target, scope, methodName); for (const execute of executions) { await (0, utils_1.promisify)(execute(context)); } }; return Promise.all(hooks.map(([methodName, executions]) => runMethodHooks(methodName, executions.map(exports.toHookFn)))); }; exports.runHooksAsync = runHooksAsync; const injectProp = (fn) => (context) => context.setProperty((0, inject_1.toInjectFn)(fn)); exports.injectProp = injectProp; const onConstruct = (fn) => (0, exports.hook)('onConstruct', fn); exports.onConstruct = onConstruct; const runOnConstructHooks = (target, scope) => (0, exports.runHooks)(target, 'onConstruct', { scope }); exports.runOnConstructHooks = runOnConstructHooks; exports.onDispose = (0, exports.hook)('onDispose', (context) => { context.invokeMethod({}); }); const runOnDisposeHooks = (target, scope) => (0, exports.runHooks)(target, 'onDispose', { scope }); exports.runOnDisposeHooks = runOnDisposeHooks;