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.
26 lines (25 loc) • 1.44 kB
JavaScript
import { Injector } from './IInjector.js';
import { Is } from '../utils/basic.js';
import { getParamMeta, addParamMeta } from '../metadata/parameter.js';
import { argToToken, toToken } from '../token/toToken.js';
import { FunctionToken } from '../token/FunctionToken.js';
export class MetadataInjector extends Injector {
createInstance(scope, Target, { args: deps = [] } = {}) {
const args = resolveArgs(Target)(scope, { args: deps });
return new Target(...args);
}
}
const hookMetaKey = (methodName = 'constructor') => `inject:${methodName}`;
export const inject = (fn, selectFn = (instance) => instance) => (target, propertyKey, parameterIndex) => {
const toSelectedToken = () => {
const token = toToken(fn);
return new FunctionToken((scope, options) => selectFn(token.resolve(scope, options)));
};
addParamMeta(hookMetaKey(propertyKey), toSelectedToken)(Is.instance(target) ? target.constructor : target, propertyKey, parameterIndex);
};
export const argsFn = (predicate) => (c, { args = [] }) => args.find((value, index) => predicate(value, index));
export const args = (index) => argsFn((value, i) => i === index);
export const resolveArgs = (Target, methodName) => {
const tokens = getParamMeta(hookMetaKey(methodName), Target);
return (scope, { args = [], lazy }) => tokens.map((fn) => fn.resolve(scope, { args: args.map(argToToken).map((t) => t.resolve(scope)), lazy }));
};