UNPKG

ts-ioc-container

Version:

Fast, lightweight TypeScript dependency injection container with a clean API, scoped lifecycles, decorators, tokens, hooks, lazy injection, customizable providers, and no global container objects.

48 lines (47 loc) 2.06 kB
import { Is } from '../utils/basic'; import { getProxyTarget, isProxy } from '../utils/proxy'; const isHookClassConstructor = (execute) => { return Is.constructor(execute) && execute.prototype.execute; }; export const toHookFn = (execute) => isHookClassConstructor(execute) ? (context) => context.scope.resolve(execute).execute(context) : execute; const getReflectionTarget = (target) => { return isProxy(target) ? getProxyTarget(target) : target; }; // Walk the constructor's prototype chain (most-derived first) collecting each class. const getConstructorChain = (ctor) => { const chain = []; let current = ctor; while (typeof current === 'function' && current !== Function.prototype) { chain.push(current); current = Object.getPrototypeOf(current); } return chain; }; // Get hooks metadata, merging hooks declared on parent (extended-from) classes. // Hooks are collected from base to derived so a derived class's hooks for the same // method name take precedence over (replace) the parent's. export function getHooks(target, key) { const reflectionTarget = getReflectionTarget(target); const merged = new Map(); for (const ctor of getConstructorChain(reflectionTarget.constructor).reverse()) { const ownHooks = Reflect.getOwnMetadata(key, ctor); if (ownHooks) { for (const [methodName, fns] of ownHooks) { merged.set(methodName, fns); } } } return merged; } export function hasHooks(target, key) { const reflectionTarget = getReflectionTarget(target); return getConstructorChain(reflectionTarget.constructor).some((ctor) => Reflect.hasOwnMetadata(key, ctor)); } // Hook decorator export const hook = (key, ...fns) => (target, propertyKey) => { const hooks = Reflect.hasOwnMetadata(key, target.constructor) ? Reflect.getOwnMetadata(key, target.constructor) : new Map(); hooks.set(propertyKey, (hooks.get(propertyKey) ?? []).concat(fns)); Reflect.defineMetadata(key, hooks, target.constructor); };