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.

55 lines (54 loc) 2.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.hook = exports.toHookFn = void 0; exports.getHooks = getHooks; exports.hasHooks = hasHooks; const basic_1 = require("../utils/basic"); const proxy_1 = require("../utils/proxy"); const isHookClassConstructor = (execute) => { return basic_1.Is.constructor(execute) && execute.prototype.execute; }; const toHookFn = (execute) => isHookClassConstructor(execute) ? (context) => context.scope.resolve(execute).execute(context) : execute; exports.toHookFn = toHookFn; const getReflectionTarget = (target) => { return (0, proxy_1.isProxy)(target) ? (0, proxy_1.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. 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; } function hasHooks(target, key) { const reflectionTarget = getReflectionTarget(target); return getConstructorChain(reflectionTarget.constructor).some((ctor) => Reflect.hasOwnMetadata(key, ctor)); } // Hook decorator 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); }; exports.hook = hook;