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.
81 lines (80 loc) • 2.86 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Provider = void 0;
const CannonSingletonApplyTwiceError_1 = require("../errors/CannonSingletonApplyTwiceError");
const ProviderDisposedError_1 = require("../errors/ProviderDisposedError");
class Provider {
resolveDependency;
static fromClass(Target) {
return new Provider((container, options) => container.resolve(Target, options));
}
static fromValue(value) {
return new Provider(() => value);
}
static fromKey(key) {
return new Provider((c) => c.resolve(key));
}
argsFnList = [];
accessRules = [];
mappers = [];
isLazy = false;
cache = new Map();
getKey;
isDisposed = false;
constructor(resolveDependency) {
this.resolveDependency = resolveDependency;
}
resolve(scope, options) {
ProviderDisposedError_1.ProviderDisposedError.assert(!this.isDisposed, 'Provider is already disposed');
if (!this.getKey) {
return this.resolveDep(scope, options);
}
const key = this.getKey(...(options.args ?? []));
if (!this.cache.has(key)) {
this.cache.set(key, this.resolveDep(scope, options));
}
return this.cache.get(key);
}
resolveDep(scope, { args = [], lazy } = {}) {
const dependency = this.resolveDependency(scope, {
args: this.argsFnList.reduce((acc, current) => current(scope, { args: acc }), args),
lazy: lazy ?? this.isLazy,
});
return this.mappers.reduce((acc, current) => current(acc, scope), dependency);
}
map(...mappers) {
this.mappers.push(...mappers);
return this;
}
addAccessRule(...rules) {
this.accessRules.push(...rules);
return this;
}
lazy() {
this.isLazy = true;
return this;
}
addArgsFn(...fns) {
this.argsFnList.push(...fns);
return this;
}
hasAccess(options) {
ProviderDisposedError_1.ProviderDisposedError.assert(!this.isDisposed, 'Provider is already disposed');
return this.accessRules.reduce((acc, rule) => rule(options, acc), true);
}
singleton(getCacheKey = () => '1') {
CannonSingletonApplyTwiceError_1.CannonSingletonApplyTwiceError.assert(!this.getKey, 'Provider is already singleton');
this.getKey = getCacheKey;
return this;
}
dispose() {
ProviderDisposedError_1.ProviderDisposedError.assert(!this.isDisposed, 'Provider is already disposed');
this.isDisposed = true;
this.getKey = undefined;
this.cache.clear();
this.accessRules.splice(0, this.accessRules.length);
this.mappers.splice(0, this.mappers.length);
this.argsFnList.splice(0, this.argsFnList.length);
}
}
exports.Provider = Provider;