import { ServiceRegistration, TypeRegistration, FactoryRegistration, ServiceMap, Descriptor, isDescriptor, isDependencyRegistration, DependencyRegistration, ValueRegistration, ActivationType, isValueRegistration, isTypeRegistration, isFactoryRegistration } from "./interfaces"; import { isNullOrEmptyString, argumentNotEmptyString, isPrimitive } from "../safe"; import { AggregateDescriptor } from "./AggregateDescriptor"; import { ValueDescriptor } from "./ValueDescriptor"; import { ServiceDescriptorParams } from "./ServiceDescriptor"; import { Container } from "./Container"; import { Constructor } from "../interfaces"; interface MapOf { [key: string]: T; } type _key = string | number; export class Configuration { _hasInnerDescriptors = false; _container: Container; _path: Array<_key>; async _visitRegistrations(data, name: _key) { this._path.push(name); if (data.constructor && data.constructor.prototype !== Object.prototype) throw new Error("Configuration must be a simple object"); const o: ServiceMap = {}; const keys = Object.keys(data); const res = await Promise.all(keys.map(k => this._visit(data[k], k))); keys.forEach((k, i) => { o[k] = isDescriptor(res[i]) ? res[i] : new AggregateDescriptor(res[i]); }); this._path.pop(); return o; } async _visit(data, name: string): Promise { if (isPrimitive(data) || isDescriptor(data)) return data; if (isDependencyRegistration(data)) { return this._visitDependencyRegistration(data, name); } else if (isValueRegistration(data)) { return this._visitValueRegistration(data, name); } else if (isTypeRegistration(data)) { return this._visitTypeRegistration(data, name); } else if (isFactoryRegistration(data)) { return this._visitFactoryRegistration(data, name); } else if (data instanceof Array) { return this._visitArray(data, name); } return this._visitObject(data, name); } async _resolveType(moduleName: string, typeName: string): Promise { } async _visitObject(data: object, name: _key): Promise { this._path.push(name); this._path.pop(); } async _visitArray(data: any[], name: _key): Promise { this._path.push(name); this._path.pop(); } async _makeServiceParams(data: ServiceRegistration) { const opts: any = {}; if (data.services) opts.services = await this._visitRegistrations(data.services, "services"); if (data.inject) { if (data.inject instanceof Array) { this._path.push("inject"); opts.inject = Promise.all(data.inject.map((x, i) => this._visitObject(x, i))); this._path.pop(); } else { opts.inject = [this._visitObject(data.inject, "inject")]; } } if (data.params) opts.params = await this._visit(data.params, "params"); if (data.activation) { if (typeof (data.activation) === "string") { switch (data.activation.toLowerCase()) { case "singleton": opts.activation = ActivationType.Singleton; break; case "container": opts.activation = ActivationType.Container; break; case "hierarchy": opts.activation = ActivationType.Hierarchy; break; case "context": opts.activation = ActivationType.Context; break; case "call": opts.activation = ActivationType.Call; break; default: throw new Error("Unknown activation type: " + data.activation); } } else { opts.activation = Number(data.activation); } } if (data.cleanup) opts.cleanup = data.cleanup; } async _visitValueRegistration(item: ValueRegistration, name: _key) { this._path.push(name); this._path.pop(); } async _visitDependencyRegistration(item: DependencyRegistration, name: _key) { this._path.push(name); this._path.pop(); } async _visitTypeRegistration(item: TypeRegistration, name: _key) { argumentNotEmptyString(item.$type, "item.$type"); } async _visitFactoryRegistration(item: FactoryRegistration, name: _key) { argumentNotEmptyString(item.$factory, "item.$type"); } }