UNPKG

@miracledevs/paradigm-web-di

Version:

A minimal dependency injection library for the web

99 lines 5.29 kB
"use strict"; 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