| @@ -0,0 +1,10 | |||
|
|
1 | import { fluent } from "../di/traits"; | |
|
|
2 | import { Bar } from "./Bar"; | |
|
|
3 | import { ChildServices, Services } from "./services"; | |
|
|
4 | ||
|
|
5 | export default fluent<ChildServices>() | |
|
|
6 | .provided<keyof Services>() | |
|
|
7 | .configure({ | |
|
|
8 | bar: it => it | |
|
|
9 | .factory($ => new Bar({ foo: $("foo"), host: $("host") }, "bar")) | |
|
|
10 | }); | |
| @@ -5,11 +5,11 import { ServiceMap, Descriptor, Partial | |||
|
|
5 | 5 | import { TraceSource } from "../log/TraceSource"; |
|
|
6 | 6 | import { Configuration, RegistrationMap } from "./Configuration"; |
|
|
7 | 7 | import { Cancellation } from "../Cancellation"; |
|
|
8 |
import { |
|
|
|
8 | import { IDestroyable, PromiseOrValue, ICancellation } from "../interfaces"; | |
|
|
9 | 9 | import { isDescriptor } from "./traits"; |
|
|
10 | 10 | import { LifetimeManager } from "./LifetimeManager"; |
|
|
11 | import { each } from "../safe"; | |
|
|
12 | import { FluentRegistrations } from "./fluent/interfaces"; | |
|
|
11 | import { each, isString } from "../safe"; | |
|
|
12 | import { ContainerConfiguration, FluentRegistrations } from "./fluent/interfaces"; | |
|
|
13 | 13 | import { FluentConfiguration } from "./fluent/FluentConfiguration"; |
|
|
14 | 14 | |
|
|
15 | 15 | const trace = TraceSource.get("@implab/core/di/ActivationContext"); |
| @@ -134,6 +134,29 export class Container<S extends object | |||
|
|
134 | 134 | } |
|
|
135 | 135 | } |
|
|
136 | 136 | |
|
|
137 | applyConfig<S2 extends object>(config: Promise<{ default: ContainerConfiguration<S2>; }>, ct?: ICancellation): Promise<Container<S & S2>>; | |
|
|
138 | applyConfig<S2 extends object, P extends string>(config: Promise<{ [p in P]: ContainerConfiguration<S2>; }>, prop: P, ct?: ICancellation): Promise<Container<S & S2>>; | |
|
|
139 | async applyConfig<S2 extends object, P extends string>( | |
|
|
140 | config: Promise<{ [p in P | "default"]: ContainerConfiguration<S2>; }>, | |
|
|
141 | propOrCt?: P | ICancellation, | |
|
|
142 | ct?: ICancellation | |
|
|
143 | ): Promise<Container<S & S2>> { | |
|
|
144 | const mod = await config; | |
|
|
145 | ||
|
|
146 | let _ct: ICancellation; | |
|
|
147 | let _prop: P | "default"; | |
|
|
148 | ||
|
|
149 | if (isString(propOrCt)) { | |
|
|
150 | _prop = propOrCt; | |
|
|
151 | _ct = ct || Cancellation.none; | |
|
|
152 | } else { | |
|
|
153 | _ct = propOrCt || Cancellation.none; | |
|
|
154 | _prop = "default"; | |
|
|
155 | } | |
|
|
156 | ||
|
|
157 | return mod[_prop].apply(this, _ct); | |
|
|
158 | } | |
|
|
159 | ||
|
|
137 | 160 | async _applyLegacyConfig(config: RegistrationMap<S>, opts: { contextRequire: any; baseModule?: string }, ct = Cancellation.none) { |
|
|
138 | 161 | return new Configuration<S>(this).applyConfiguration(config, opts); |
|
|
139 | 162 | } |
| @@ -1,13 +1,17 | |||
|
|
1 | 1 | import { Container } from "../Container"; |
|
|
2 | 2 | import { argumentNotNull, each, isPrimitive, isPromise } from "../../safe"; |
|
|
3 | 3 | import { DescriptorBuilder } from "./DescriptorBuilder"; |
|
|
4 | import { RegistrationBuilder, FluentRegistrations } from "./interfaces"; | |
|
|
4 | import { RegistrationBuilder, FluentRegistrations, ContainerConfiguration } from "./interfaces"; | |
|
|
5 | 5 | import { Cancellation } from "../../Cancellation"; |
|
|
6 | 6 | |
|
|
7 | 7 | export class FluentConfiguration<S extends object, Y extends keyof S = keyof S> { |
|
|
8 | 8 | |
|
|
9 | 9 | _builders: { [k in keyof S]?: RegistrationBuilder<S, S[k]> } = {}; |
|
|
10 | 10 | |
|
|
11 | provided<K extends Y>(): FluentConfiguration<S, Exclude<Y, K>> { | |
|
|
12 | return this; | |
|
|
13 | } | |
|
|
14 | ||
|
|
11 | 15 | register<K extends Y>(name: K, builder: RegistrationBuilder<S, S[K]>): FluentConfiguration<S, Exclude<Y, K>>; |
|
|
12 | 16 | register<K extends Y>(config: FluentRegistrations<K, S>): FluentConfiguration<S, Exclude<Y, K>>; |
|
|
13 | 17 | register<K extends Y>(nameOrConfig: K | FluentRegistrations<K, S>, builder?: RegistrationBuilder<S, S[K]>): FluentConfiguration<S, Exclude<Y, K>> { |
| @@ -21,6 +25,10 export class FluentConfiguration<S exten | |||
|
|
21 | 25 | return this; |
|
|
22 | 26 | } |
|
|
23 | 27 | |
|
|
28 | configure(config: FluentRegistrations<Y, S>): ContainerConfiguration<S> { | |
|
|
29 | return this.register(config); | |
|
|
30 | } | |
|
|
31 | ||
|
|
24 | 32 | apply<SC extends object>(target: Container<SC>, ct = Cancellation.none) { |
|
|
25 | 33 | |
|
|
26 | 34 | let pending = 1; |
| @@ -1,6 +1,7 | |||
|
|
1 | 1 | import { primitive } from "../../safe"; |
|
|
2 | 2 | import { TypeOfService, ContainerKeys, ActivationType, ILifetime } from "../interfaces"; |
|
|
3 | 3 | import { ICancellation } from "../../interfaces"; |
|
|
4 | import { Container } from "../Container"; | |
|
|
4 | 5 | |
|
|
5 | 6 | export interface DependencyOptions { |
|
|
6 | 7 | optional?: boolean; |
| @@ -47,6 +48,10 export interface DescriptorBuilder<S ext | |||
|
|
47 | 48 | value(v: T): void; |
|
|
48 | 49 | } |
|
|
49 | 50 | |
|
|
51 | export interface ContainerConfiguration<S extends object> { | |
|
|
52 | apply<S2 extends object>(target: Container<S2>, ct: ICancellation): Promise<Container<S2 & S>>; | |
|
|
53 | } | |
|
|
54 | ||
|
|
50 | 55 | export type RegistrationBuilder<S extends object, T> = (d: DescriptorBuilder<S, T>, ct?: ICancellation) => void | Promise<void>; |
|
|
51 | 56 | |
|
|
52 | 57 | export type FluentRegistrations<K extends keyof S, S extends object> = { [k in K]: RegistrationBuilder<S, S[k]> }; |
| @@ -151,7 +151,7 export function each(obj: any, cb: any, | |||
|
|
151 | 151 | } |
|
|
152 | 152 | |
|
|
153 | 153 | /** Copies property values from a source object to the destination and returns |
|
|
154 |
* the destination o |
|
|
|
154 | * the destination object. | |
|
|
155 | 155 | * |
|
|
156 | 156 | * @param dest The destination object into which properties from the source |
|
|
157 | 157 | * object will be copied. |
| @@ -2,7 +2,7 import { Services } from "./services"; | |||
|
|
2 | 2 | import { fluent } from "../di/traits"; |
|
|
3 | 3 | import { Box } from "./Box"; |
|
|
4 | 4 | |
|
|
5 |
export default fluent<Services>().re |
|
|
|
5 | export default fluent<Services>().configure({ | |
|
|
6 | 6 | host: it => it.value("example.com"), |
|
|
7 | 7 | |
|
|
8 | 8 | foo: it => import("./Foo").then(({ Foo }) => it |
| @@ -1,6 +1,6 | |||
|
|
1 | 1 | import { Foo } from "./Foo"; |
|
|
2 | import { Box } from "./Box"; | |
|
|
2 | 3 | import { Bar } from "./Bar"; |
|
|
3 | import { Box } from "./Box"; | |
|
|
4 | 4 | |
|
|
5 | 5 | /** |
|
|
6 | 6 | * Сервисы доступные внутри контейнера |
| @@ -13,3 +13,10 export interface Services { | |||
|
|
13 | 13 | host: string; |
|
|
14 | 14 | |
|
|
15 | 15 | } |
|
|
16 | ||
|
|
17 | export interface ChildServices extends Services { | |
|
|
18 | ||
|
|
19 | foo2?: Foo; | |
|
|
20 | ||
|
|
21 | bar: Bar; | |
|
|
22 | } | |
| @@ -61,3 +61,9 test("Load fluent config", async t => { | |||
|
|
61 | 61 | |
|
|
62 | 62 | t.assert(container.resolve("host"), "Should resolve simple value"); |
|
|
63 | 63 | }); |
|
|
64 | ||
|
|
65 | test("Container applyConfig", async t => { | |
|
|
66 | const container = await new Container<{}>().applyConfig(import("../mock/config")); | |
|
|
67 | ||
|
|
68 | t.assert(container.resolve("host"), "Should resolve simple value"); | |
|
|
69 | }); | |
General Comments 0
You need to be logged in to leave comments.
Login now
