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.

82 lines (81 loc) 2.7 kB
import { isDependencyKey } from '../container/IContainer'; import { Provider } from '../provider/Provider'; import { DependencyMissingKeyError } from '../errors/DependencyMissingKeyError'; import { isProviderPipe } from './IRegistration'; import { getTransformers } from './IRegistration'; import { SingleToken } from '../token/SingleToken'; import { pipe } from '../utils/fp'; import { Is } from '../utils/basic'; export class Registration { createProvider; key; scopeRules; static fromClass(Target, { name } = {}) { const transform = pipe(...getTransformers(Target)); return transform(new Registration(() => Provider.fromClass(Target), name ?? Target.name)); } static fromValue(value) { if (Is.constructor(value)) { const transform = pipe(...getTransformers(value)); return transform(new Registration(() => Provider.fromValue(value), value.name)); } return new Registration(() => Provider.fromValue(value)); } static fromFn(fn) { return new Registration(() => new Provider(fn)); } static fromKey(key) { return new Registration(() => Provider.fromKey(key)); } mappers = []; aliases = new Set(); constructor(createProvider, key, scopeRules = []) { this.createProvider = createProvider; this.key = key; this.scopeRules = scopeRules; } bindToKey(key) { this.key = key; return this; } bindToAlias(alias) { this.aliases.add(alias); return this; } pipe(...mappers) { const fns = mappers.map((m) => (isProviderPipe(m) ? m.mapProvider.bind(m) : m)); this.mappers.push(...fns); return this; } when(...predicates) { this.scopeRules.push(...predicates); return this; } bindTo(key) { if (isDependencyKey(key)) { new SingleToken(key).bindTo(this); return this; } key.bindTo(this); return this; } matchScope(container) { return this.scopeRules.reduce((prev, curr) => curr(container, prev), true); } applyTo(container) { if (!this.matchScope(container)) { return; } if (!this.key) { throw new DependencyMissingKeyError('No key provided for registration'); } const provider = this.mappers.reduce((p, m) => m(p), this.createProvider()); container.register(this.key, provider, { aliases: [...this.aliases] }); } getKeyOrFail() { if (!this.key) { throw new DependencyMissingKeyError('No key provided for registration'); } return this.key; } }