# HG changeset patch # User cin # Date 2020-09-15 22:46:35 # Node ID be7edf08a115bd3905e28d58158ef0aa7abf5308 # Parent 64dfb0328301711c6a83211773e11c50eb4d62bc added provided and configure methods to the fluent container configuration, added applyConfig method to the container diff --git a/src/main/ts/di/Container.ts b/src/main/ts/di/Container.ts --- a/src/main/ts/di/Container.ts +++ b/src/main/ts/di/Container.ts @@ -5,11 +5,11 @@ import { ServiceMap, Descriptor, Partial import { TraceSource } from "../log/TraceSource"; import { Configuration, RegistrationMap } from "./Configuration"; import { Cancellation } from "../Cancellation"; -import { MapOf, IDestroyable } from "../interfaces"; +import { IDestroyable, PromiseOrValue, ICancellation } from "../interfaces"; import { isDescriptor } from "./traits"; import { LifetimeManager } from "./LifetimeManager"; -import { each } from "../safe"; -import { FluentRegistrations } from "./fluent/interfaces"; +import { each, isString } from "../safe"; +import { ContainerConfiguration, FluentRegistrations } from "./fluent/interfaces"; import { FluentConfiguration } from "./fluent/FluentConfiguration"; const trace = TraceSource.get("@implab/core/di/ActivationContext"); @@ -134,6 +134,29 @@ export class Container(config: Promise<{ default: ContainerConfiguration; }>, ct?: ICancellation): Promise>; + applyConfig(config: Promise<{ [p in P]: ContainerConfiguration; }>, prop: P, ct?: ICancellation): Promise>; + async applyConfig( + config: Promise<{ [p in P | "default"]: ContainerConfiguration; }>, + propOrCt?: P | ICancellation, + ct?: ICancellation + ): Promise> { + const mod = await config; + + let _ct: ICancellation; + let _prop: P | "default"; + + if (isString(propOrCt)) { + _prop = propOrCt; + _ct = ct || Cancellation.none; + } else { + _ct = propOrCt || Cancellation.none; + _prop = "default"; + } + + return mod[_prop].apply(this, _ct); + } + async _applyLegacyConfig(config: RegistrationMap, opts: { contextRequire: any; baseModule?: string }, ct = Cancellation.none) { return new Configuration(this).applyConfiguration(config, opts); } diff --git a/src/main/ts/di/fluent/FluentConfiguration.ts b/src/main/ts/di/fluent/FluentConfiguration.ts --- a/src/main/ts/di/fluent/FluentConfiguration.ts +++ b/src/main/ts/di/fluent/FluentConfiguration.ts @@ -1,13 +1,17 @@ import { Container } from "../Container"; import { argumentNotNull, each, isPrimitive, isPromise } from "../../safe"; import { DescriptorBuilder } from "./DescriptorBuilder"; -import { RegistrationBuilder, FluentRegistrations } from "./interfaces"; +import { RegistrationBuilder, FluentRegistrations, ContainerConfiguration } from "./interfaces"; import { Cancellation } from "../../Cancellation"; export class FluentConfiguration { _builders: { [k in keyof S]?: RegistrationBuilder } = {}; + provided(): FluentConfiguration> { + return this; + } + register(name: K, builder: RegistrationBuilder): FluentConfiguration>; register(config: FluentRegistrations): FluentConfiguration>; register(nameOrConfig: K | FluentRegistrations, builder?: RegistrationBuilder): FluentConfiguration> { @@ -21,6 +25,10 @@ export class FluentConfiguration): ContainerConfiguration { + return this.register(config); + } + apply(target: Container, ct = Cancellation.none) { let pending = 1; diff --git a/src/main/ts/di/fluent/interfaces.ts b/src/main/ts/di/fluent/interfaces.ts --- a/src/main/ts/di/fluent/interfaces.ts +++ b/src/main/ts/di/fluent/interfaces.ts @@ -1,6 +1,7 @@ import { primitive } from "../../safe"; import { TypeOfService, ContainerKeys, ActivationType, ILifetime } from "../interfaces"; import { ICancellation } from "../../interfaces"; +import { Container } from "../Container"; export interface DependencyOptions { optional?: boolean; @@ -47,6 +48,10 @@ export interface DescriptorBuilder { + apply(target: Container, ct: ICancellation): Promise>; +} + export type RegistrationBuilder = (d: DescriptorBuilder, ct?: ICancellation) => void | Promise; export type FluentRegistrations = { [k in K]: RegistrationBuilder }; diff --git a/src/main/ts/safe.ts b/src/main/ts/safe.ts --- a/src/main/ts/safe.ts +++ b/src/main/ts/safe.ts @@ -151,7 +151,7 @@ export function each(obj: any, cb: any, } /** Copies property values from a source object to the destination and returns - * the destination onject. + * the destination object. * * @param dest The destination object into which properties from the source * object will be copied. diff --git a/src/test/ts/mock/config.ts b/src/test/ts/mock/config.ts --- a/src/test/ts/mock/config.ts +++ b/src/test/ts/mock/config.ts @@ -2,7 +2,7 @@ import { Services } from "./services"; import { fluent } from "../di/traits"; import { Box } from "./Box"; -export default fluent().register({ +export default fluent().configure({ host: it => it.value("example.com"), foo: it => import("./Foo").then(({ Foo }) => it diff --git a/src/test/ts/mock/config2.ts b/src/test/ts/mock/config2.ts new file mode 100644 --- /dev/null +++ b/src/test/ts/mock/config2.ts @@ -0,0 +1,10 @@ +import { fluent } from "../di/traits"; +import { Bar } from "./Bar"; +import { ChildServices, Services } from "./services"; + +export default fluent() + .provided() + .configure({ + bar: it => it + .factory($ => new Bar({ foo: $("foo"), host: $("host") }, "bar")) + }); diff --git a/src/test/ts/mock/services.ts b/src/test/ts/mock/services.ts --- a/src/test/ts/mock/services.ts +++ b/src/test/ts/mock/services.ts @@ -1,6 +1,6 @@ import { Foo } from "./Foo"; +import { Box } from "./Box"; import { Bar } from "./Bar"; -import { Box } from "./Box"; /** * Сервисы доступные внутри контейнера @@ -13,3 +13,10 @@ export interface Services { host: string; } + +export interface ChildServices extends Services { + + foo2?: Foo; + + bar: Bar; +} diff --git a/src/test/ts/tests/FluentContainerTests.ts b/src/test/ts/tests/FluentContainerTests.ts --- a/src/test/ts/tests/FluentContainerTests.ts +++ b/src/test/ts/tests/FluentContainerTests.ts @@ -61,3 +61,9 @@ test("Load fluent config", async t => { t.assert(container.resolve("host"), "Should resolve simple value"); }); + +test("Container applyConfig", async t => { + const container = await new Container<{}>().applyConfig(import("../mock/config")); + + t.assert(container.resolve("host"), "Should resolve simple value"); +}); diff --git a/src/tsconfig.json b/src/tsconfig.json --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -4,7 +4,7 @@ "experimentalDecorators": true, "noEmitOnError": true, "listFiles": true, - "strict": true, + //"strict": true, "types": [], "target": "ES5", "lib": ["es5", "es2015.promise", "es2015.symbol", "es2015.iterable", "dom", "scripthost"]