@miracledevs/paradigm-web-di
Version:
A minimal dependency injection library for the web
99 lines • 5.29 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DependencyCollection = void 0;
const object_type_1 = require("./object-type");
const dependency_life_time_1 = require("./dependency-life-time");
const dependency_descriptor_1 = require("./dependency-descriptor");
const dependency_container_1 = require("./dependency-container");
class DependencyCollection {
constructor() {
this._registeredTypes = new Map();
this.register(dependency_container_1.DependencyContainer, dependency_life_time_1.DependencyLifeTime.Transient);
}
static get globalCollection() {
if (!this._globalCollection)
this._globalCollection = new DependencyCollection();
return this._globalCollection;
}
register(objectType, lifeTime, dependencies, instance) {
if (this.contains(objectType))
throw new Error(`The type ${(0, object_type_1.getObjectTypeName)(objectType)} is already registered.`);
if (instance && lifeTime !== dependency_life_time_1.DependencyLifeTime.Singleton)
throw new Error(`Only the singletons can be registered with an existing instance.`);
this._registeredTypes.set(objectType, new dependency_descriptor_1.DependencyDescriptor(lifeTime || dependency_life_time_1.DependencyLifeTime.Transient, dependencies || [], instance || null));
}
registerTransient(objectType, dependencies) {
this.register(objectType, dependency_life_time_1.DependencyLifeTime.Transient, dependencies);
}
registerScoped(objectType, dependencies) {
this.register(objectType, dependency_life_time_1.DependencyLifeTime.Scoped, dependencies);
}
registerSingleton(objectType, dependencies, instance) {
this.register(objectType, dependency_life_time_1.DependencyLifeTime.Singleton, dependencies, instance);
}
get(objectType) {
if (!this._registeredTypes.has(objectType))
throw new Error(`The type ${(0, object_type_1.getObjectTypeName)(objectType)} is not registered.`);
return this._registeredTypes.get(objectType);
}
contains(objectType) {
return this._registeredTypes.has(objectType);
}
buildContainer(validate = false) {
if (validate) {
let errors = '';
for (const registeredType of this._registeredTypes.keys()) {
try {
this.validateCircularDependency(registeredType);
this.validateDependencyRegistration(registeredType);
this.validateScopedOnSingletons(registeredType);
}
catch (e) {
errors += ` - ${(e instanceof Error ? e.message : e)}\n`;
}
}
if (errors.length > 0) {
throw new Error("Errors found on the dependency configuration:\n" + errors);
}
}
return dependency_container_1.DependencyContainer.createFromCollection(this, "root");
}
validateDependencyRegistration(objectType) {
const descriptor = this.get(objectType);
for (const dependencyType of descriptor.dependencies) {
if (!this.contains(dependencyType)) {
throw new Error(`The type '${(0, object_type_1.getObjectTypeName)(objectType)}' depends on the type '${(0, object_type_1.getObjectTypeName)(dependencyType)}' but is not registered.`);
}
this.validateDependencyRegistration(dependencyType);
}
}
validateCircularDependency(objectType, hierarchy) {
if (!hierarchy)
hierarchy = [];
const descriptor = this.get(objectType);
const dependencies = descriptor.dependencies;
for (const dependencyType of dependencies) {
if (!this.contains(dependencyType))
continue;
if (hierarchy.find(x => x === dependencyType)) {
throw new Error(`Circular dependency found in service type '${(0, object_type_1.getObjectTypeName)(hierarchy[0])}': ${hierarchy.map(x => (0, object_type_1.getObjectTypeName)(x)).join(" -> ")} -> ${(0, object_type_1.getObjectTypeName)(dependencyType)}.`);
}
const newHierarchy = [...hierarchy];
newHierarchy.push(dependencyType);
this.validateCircularDependency(dependencyType, newHierarchy);
}
}
validateScopedOnSingletons(objectType) {
const descriptor = this.get(objectType);
for (const dependencyType of descriptor.dependencies) {
const dependencyDescriptor = this.get(dependencyType);
if (descriptor.lifeTime === dependency_life_time_1.DependencyLifeTime.Singleton &&
dependencyDescriptor.lifeTime === dependency_life_time_1.DependencyLifeTime.Scoped) {
throw new Error(`Cannot consume scoped type '${(0, object_type_1.getObjectTypeName)(dependencyType)}' from singleton '${(0, object_type_1.getObjectTypeName)(objectType)}'.`);
}
this.validateScopedOnSingletons(dependencyType);
}
}
}
exports.DependencyCollection = DependencyCollection;
//# sourceMappingURL=dependency-collection.js.map