Files
Typescript-Dependency-Manager/dependency-manager.ts
Robin Chappatte b654a3b26f provider is key
2024-06-10 16:27:21 +02:00

59 lines
1.5 KiB
TypeScript

export type Provider<T = unknown> = (manager: DependencyManager) => T;
export type ProviderGroup = {
[key: string]: Provider | ProviderGroup;
};
export class DependencyManager {
private declarations = new Map<unknown, Provider>();
private instances = new Map();
private resolving = new Set();
register(dependency: Provider): void;
register(module: ProviderGroup): void;
register(dependencyOrModule: Provider | ProviderGroup): void;
register(dependencyOrModule: Provider | ProviderGroup) {
if (this.declarations.has(dependencyOrModule)) {
throw new Error('This dependency has already been registred');
}
if (typeof dependencyOrModule === 'function') {
this.declarations.set(dependencyOrModule, dependencyOrModule);
return;
}
const module = dependencyOrModule;
for (const key in module) {
this.register(module[key]);
}
}
resolve<T>(dependency: Provider<T>): T {
if (!this.declarations.has(dependency)) {
throw new Error('This dependency has not been registred');
}
if (this.instances.has(dependency)) {
return this.instances.get(dependency) as T;
}
if (this.resolving.has(dependency)) {
throw new Error('Circular dependency detected');
}
this.resolving.add(dependency);
const instance = this.instanciate(dependency);
this.resolving.delete(dependency);
return instance;
}
private instanciate<T>(dependency: Provider<T>): T {
const declaration = this.declarations.get(dependency) as Provider<T>;
const instance = declaration(this);
this.instances.set(dependency, instance);
return instance;
}
}