import { Container as InversifyContainer, interfaces } from "inversify"; export type AsyncModuleRegistry = (container: Container) => Promise; export type ModuleRegistry = (container: Container) => void; export class Container { protected container: InversifyContainer; constructor(protected parent?: Container) { this.container = new InversifyContainer(); if (this.parent != null) { this.container.parent = this.parent.container; } } bindConstant( serviceIdentifier: interfaces.ServiceIdentifier, value: T ): this { this.container.bind(serviceIdentifier).toConstantValue(value); return this; } bindDynamic( serviceIdentifier: interfaces.ServiceIdentifier, func: (context: interfaces.Context) => T ): this { this.container.bind(serviceIdentifier).toDynamicValue(func); return this; } bindTransient(constructor: { new (...args: any[]): T }): this; bindTransient( serviceIdentifier: interfaces.ServiceIdentifier, constructor: { new (...args: any[]): T } ): this; bindTransient( serviceIdentifierOrConstructor: | interfaces.ServiceIdentifier | { new (...args: any[]): T }, constructor?: { new (...args: any[]): T; } ): this { this.container .bind(serviceIdentifierOrConstructor) .to( constructor != null ? constructor : (serviceIdentifierOrConstructor as { new (...args: any[]): T }) ) .inTransientScope(); return this; } bindSingleton(constructor: { new (...args: any[]): T }): this; bindSingleton( serviceIdentifier: interfaces.ServiceIdentifier, constructor: { new (...args: any[]): T } ): this; bindSingleton( serviceIdentifierOrConstructor: | interfaces.ServiceIdentifier | { new (...args: any[]): T }, constructor?: { new (...args: any[]): T; } ): this { this.container .bind(serviceIdentifierOrConstructor) .to( constructor != null ? constructor : (serviceIdentifierOrConstructor as { new (...args: any[]): T }) ) .inSingletonScope(); return this; } associateWith( serviceIdentifierFrom: interfaces.ServiceIdentifier, serviceIdentifierTo: interfaces.ServiceIdentifier ): this { this.container.bind(serviceIdentifierFrom).toService(serviceIdentifierTo); return this; } load(...moduleRegistries: Array): void { moduleRegistries.forEach((registry) => registry(this)); } async loadAsync( ...asnycModuleRegistries: Array ): Promise { for (const registry of asnycModuleRegistries) { await registry(this); } } get(serviceIdentifier: interfaces.ServiceIdentifier): T { return this.container.get(serviceIdentifier); } getAll(serviceIdentifier: interfaces.ServiceIdentifier): Array { return this.container.getAll(serviceIdentifier); } takeSnapshot(): void { this.container.snapshot(); } restoreSnapshot(): void { this.container.restore(); } _diContainer(): interfaces.Container { return this.container; } }