@sigi/di
Version:
Dependencies injection library for sigi framework
177 lines • 7.62 kB
JavaScript
import { __read, __spreadArray, __values } from "tslib";
import { ReflectiveProvider } from './injector-provider';
import { InjectionProvider } from './provider';
var Injector = (function () {
function Injector(parent) {
if (parent === void 0) { parent = null; }
this.parent = parent;
this.provider = new InjectionProvider();
this.resolvedProviders = new Map();
this.providersCache = new Map();
}
Injector.prototype.addProvider = function (provider) {
return this.provider.addProvider(provider);
};
Injector.prototype.addProviders = function (providers) {
var e_1, _a;
try {
for (var providers_1 = __values(providers), providers_1_1 = providers_1.next(); !providers_1_1.done; providers_1_1 = providers_1.next()) {
var provider = providers_1_1.value;
this.provider.addProvider(provider);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (providers_1_1 && !providers_1_1.done && (_a = providers_1.return)) _a.call(providers_1);
}
finally { if (e_1) throw e_1.error; }
}
return this;
};
Injector.prototype.getInstance = function (provider) {
return this.getInstanceInternal(provider, true);
};
Injector.prototype.resolveAndInstantiate = function (provider) {
return this.getInstanceInternal(provider, false);
};
Injector.prototype.createChild = function (providers) {
var childInjector = new Injector(this);
childInjector.addProviders(providers);
return childInjector;
};
Injector.prototype.resolveReflectiveProvider = function (provider) {
var _a;
var reflectiveProvider = null;
if (this.provider.findProviderByToken((_a = provider.provide) !== null && _a !== void 0 ? _a : provider)) {
if (this.providersCache.has(provider)) {
return this.providersCache.get(provider);
}
reflectiveProvider = new ReflectiveProvider(provider);
this.providersCache.set(provider, reflectiveProvider);
}
return reflectiveProvider;
};
Injector.prototype.getInstanceInternal = function (provider, useCache) {
var injector = this;
var instance = null;
var reflectiveProvider = null;
var deps = this.findDeps(provider);
while (injector) {
reflectiveProvider = injector.resolveReflectiveProvider(provider);
if (!reflectiveProvider) {
injector = injector.parent;
continue;
}
if (injector.resolvedProviders.has(reflectiveProvider)) {
if (deps) {
if (useCache && (injector === this || this.checkDependenciesClean(injector, deps))) {
instance = injector.resolvedProviders.get(reflectiveProvider);
}
else {
instance = this.resolveByReflectiveProvider(reflectiveProvider, useCache, this);
if (useCache) {
this.provider.addProvider(provider);
this.providersCache.set(provider, reflectiveProvider);
this.resolvedProviders.set(reflectiveProvider, instance);
}
}
}
else {
instance = useCache
? injector.resolvedProviders.get(reflectiveProvider)
: this.resolveByReflectiveProvider(reflectiveProvider, false, this);
}
break;
}
instance = injector.resolveByReflectiveProvider(reflectiveProvider, useCache, this);
if (instance) {
if (useCache) {
this.provider.addProvider(provider);
this.providersCache.set(provider, reflectiveProvider);
this.resolvedProviders.set(reflectiveProvider, instance);
}
break;
}
injector = injector.parent;
}
if (!instance) {
reflectiveProvider = new ReflectiveProvider(provider);
throw new TypeError("No provider for ".concat(reflectiveProvider.name, "!"));
}
return instance;
};
Injector.prototype.resolveByReflectiveProvider = function (reflectiveProvider, useCache, leaf) {
var _a;
if (useCache === void 0) { useCache = true; }
if (leaf === void 0) { leaf = this; }
var instance = null;
var provider = reflectiveProvider.provider, name = reflectiveProvider.name;
if (typeof provider === 'function') {
var deps = (_a = Reflect.getMetadata('design:paramtypes', provider)) !== null && _a !== void 0 ? _a : [];
var depsInstance = deps.map(function (dep) { return leaf.getInstanceInternal(leaf.findExisting(dep), useCache); });
instance = new (provider.bind.apply(provider, __spreadArray([void 0], __read(depsInstance), false)))();
}
else if ('useValue' in provider) {
instance = provider.useValue;
}
else if ('useClass' in provider) {
instance = leaf.getInstanceInternal(provider.useClass, useCache);
}
else if ('useFactory' in provider) {
var deps = [];
if (provider.deps) {
deps = provider.deps.map(function (dep) { return leaf.getInstanceInternal(leaf.findExisting(dep), useCache); });
}
instance = provider.useFactory.apply(provider, __spreadArray([], __read(deps), false));
}
else if ('useExisting' in provider) {
instance = leaf.getInstanceInternal(this.findExisting(provider.useExisting), useCache);
}
if (!instance) {
throw new TypeError("Can not resolve ".concat(name, ", it's not a valid provider"));
}
return instance;
};
Injector.prototype.findExisting = function (token) {
var _a;
var provider = null;
var injector = this;
while (injector) {
provider = injector.provider.findProviderByToken(token);
if (provider) {
break;
}
injector = injector.parent;
}
if (!provider) {
throw new TypeError("No provider for ".concat((_a = token.name) !== null && _a !== void 0 ? _a : token.toString()));
}
return provider;
};
Injector.prototype.findDeps = function (provider) {
return typeof provider === 'function'
? Reflect.getMetadata('design:paramtypes', provider)
: provider.useClass
? Reflect.getMetadata('design:paramtypes', provider.useClass)
: provider.deps
? provider.deps
: null;
};
Injector.prototype.checkDependenciesClean = function (leaf, deps) {
var _this = this;
return deps.every(function (dep) {
var depInLeaf = leaf.findExisting(dep);
var depInRoot = _this.findExisting(dep);
var isEqual = depInLeaf === depInRoot;
var deps = _this.findDeps(depInLeaf);
if (deps) {
return _this.checkDependenciesClean(leaf, deps) && isEqual;
}
return isEqual;
});
};
return Injector;
}());
export { Injector };
//# sourceMappingURL=injector.js.map