import { Container } from "./Container"; import { DescriptorBuilder } from "./DescriptorBuilder"; import { Descriptor, IContainerBuilder, IDescriptorBuilder, DescriptorMap, ServiceLocator, ILifetimeManager } from "../typings/interfaces"; /** * Container builder used to prepare service descriptors and create a IoC container */ export class ContainerBuilder implements IContainerBuilder { private _pending = 1; private readonly _services: DescriptorMap; private readonly _scope: ILifetimeManager[]; private readonly _level: number; constructor(parentServices: DescriptorMap | null, scope: ILifetimeManager[] = []) { this._services = { ...parentServices }; // create a copy this._level = scope.length; this._scope = scope; } createServiceBuilder(name: K): IDescriptorBuilder, U> { return new DescriptorBuilder(this._level, String(name), this._register(name), this._fail); } build(): ServiceLocator { this._assertBuilding(); if (!this._complete()) throw new Error("The configuration didn't complete."); return new Container(this._services, this._scope); } private readonly _register = (name: K) => (descriptor: Descriptor) => { this._complete(); this._services[name] = descriptor; }; private readonly _fail = (ex: unknown) => { throw ex; }; private _assertBuilding() { if (!this._pending) throw new Error("The descriptor builder is finalized"); } private _complete() { return !(--this._pending); } }