| @@ -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 | import { TraceSource } from "../log/TraceSource"; |
|
5 | import { TraceSource } from "../log/TraceSource"; | |
| 6 | import { Configuration, RegistrationMap } from "./Configuration"; |
|
6 | import { Configuration, RegistrationMap } from "./Configuration"; | |
| 7 | import { Cancellation } from "../Cancellation"; |
|
7 | import { Cancellation } from "../Cancellation"; | |
| 8 |
import { |
|
8 | import { IDestroyable, PromiseOrValue, ICancellation } from "../interfaces"; | |
| 9 | import { isDescriptor } from "./traits"; |
|
9 | import { isDescriptor } from "./traits"; | |
| 10 | import { LifetimeManager } from "./LifetimeManager"; |
|
10 | import { LifetimeManager } from "./LifetimeManager"; | |
| 11 | import { each } from "../safe"; |
|
11 | import { each, isString } from "../safe"; | |
| 12 | import { FluentRegistrations } from "./fluent/interfaces"; |
|
12 | import { ContainerConfiguration, FluentRegistrations } from "./fluent/interfaces"; | |
| 13 | import { FluentConfiguration } from "./fluent/FluentConfiguration"; |
|
13 | import { FluentConfiguration } from "./fluent/FluentConfiguration"; | |
| 14 |
|
14 | |||
| 15 | const trace = TraceSource.get("@implab/core/di/ActivationContext"); |
|
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 | async _applyLegacyConfig(config: RegistrationMap<S>, opts: { contextRequire: any; baseModule?: string }, ct = Cancellation.none) { |
|
160 | async _applyLegacyConfig(config: RegistrationMap<S>, opts: { contextRequire: any; baseModule?: string }, ct = Cancellation.none) { | |
| 138 | return new Configuration<S>(this).applyConfiguration(config, opts); |
|
161 | return new Configuration<S>(this).applyConfiguration(config, opts); | |
| 139 | } |
|
162 | } | |
| @@ -1,13 +1,17 | |||||
| 1 | import { Container } from "../Container"; |
|
1 | import { Container } from "../Container"; | |
| 2 | import { argumentNotNull, each, isPrimitive, isPromise } from "../../safe"; |
|
2 | import { argumentNotNull, each, isPrimitive, isPromise } from "../../safe"; | |
| 3 | import { DescriptorBuilder } from "./DescriptorBuilder"; |
|
3 | import { DescriptorBuilder } from "./DescriptorBuilder"; | |
| 4 | import { RegistrationBuilder, FluentRegistrations } from "./interfaces"; |
|
4 | import { RegistrationBuilder, FluentRegistrations, ContainerConfiguration } from "./interfaces"; | |
| 5 | import { Cancellation } from "../../Cancellation"; |
|
5 | import { Cancellation } from "../../Cancellation"; | |
| 6 |
|
6 | |||
| 7 | export class FluentConfiguration<S extends object, Y extends keyof S = keyof S> { |
|
7 | export class FluentConfiguration<S extends object, Y extends keyof S = keyof S> { | |
| 8 |
|
8 | |||
| 9 | _builders: { [k in keyof S]?: RegistrationBuilder<S, S[k]> } = {}; |
|
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 | register<K extends Y>(name: K, builder: RegistrationBuilder<S, S[K]>): FluentConfiguration<S, Exclude<Y, K>>; |
|
15 | register<K extends Y>(name: K, builder: RegistrationBuilder<S, S[K]>): FluentConfiguration<S, Exclude<Y, K>>; | |
| 12 | register<K extends Y>(config: FluentRegistrations<K, S>): FluentConfiguration<S, Exclude<Y, K>>; |
|
16 | register<K extends Y>(config: FluentRegistrations<K, S>): FluentConfiguration<S, Exclude<Y, K>>; | |
| 13 | register<K extends Y>(nameOrConfig: K | FluentRegistrations<K, S>, builder?: RegistrationBuilder<S, S[K]>): FluentConfiguration<S, Exclude<Y, K>> { |
|
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 | return this; |
|
25 | return this; | |
| 22 | } |
|
26 | } | |
| 23 |
|
27 | |||
|
|
28 | configure(config: FluentRegistrations<Y, S>): ContainerConfiguration<S> { | |||
|
|
29 | return this.register(config); | |||
|
|
30 | } | |||
|
|
31 | ||||
| 24 | apply<SC extends object>(target: Container<SC>, ct = Cancellation.none) { |
|
32 | apply<SC extends object>(target: Container<SC>, ct = Cancellation.none) { | |
| 25 |
|
33 | |||
| 26 | let pending = 1; |
|
34 | let pending = 1; | |
| @@ -1,6 +1,7 | |||||
| 1 | import { primitive } from "../../safe"; |
|
1 | import { primitive } from "../../safe"; | |
| 2 | import { TypeOfService, ContainerKeys, ActivationType, ILifetime } from "../interfaces"; |
|
2 | import { TypeOfService, ContainerKeys, ActivationType, ILifetime } from "../interfaces"; | |
| 3 | import { ICancellation } from "../../interfaces"; |
|
3 | import { ICancellation } from "../../interfaces"; | |
|
|
4 | import { Container } from "../Container"; | |||
| 4 |
|
5 | |||
| 5 | export interface DependencyOptions { |
|
6 | export interface DependencyOptions { | |
| 6 | optional?: boolean; |
|
7 | optional?: boolean; | |
| @@ -47,6 +48,10 export interface DescriptorBuilder<S ext | |||||
| 47 | value(v: T): void; |
|
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 | export type RegistrationBuilder<S extends object, T> = (d: DescriptorBuilder<S, T>, ct?: ICancellation) => void | Promise<void>; |
|
55 | export type RegistrationBuilder<S extends object, T> = (d: DescriptorBuilder<S, T>, ct?: ICancellation) => void | Promise<void>; | |
| 51 |
|
56 | |||
| 52 | export type FluentRegistrations<K extends keyof S, S extends object> = { [k in K]: RegistrationBuilder<S, S[k]> }; |
|
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 | /** Copies property values from a source object to the destination and returns |
|
153 | /** Copies property values from a source object to the destination and returns | |
| 154 |
* the destination o |
|
154 | * the destination object. | |
| 155 | * |
|
155 | * | |
| 156 | * @param dest The destination object into which properties from the source |
|
156 | * @param dest The destination object into which properties from the source | |
| 157 | * object will be copied. |
|
157 | * object will be copied. | |
| @@ -2,7 +2,7 import { Services } from "./services"; | |||||
| 2 | import { fluent } from "../di/traits"; |
|
2 | import { fluent } from "../di/traits"; | |
| 3 | import { Box } from "./Box"; |
|
3 | import { Box } from "./Box"; | |
| 4 |
|
4 | |||
| 5 |
export default fluent<Services>().re |
|
5 | export default fluent<Services>().configure({ | |
| 6 | host: it => it.value("example.com"), |
|
6 | host: it => it.value("example.com"), | |
| 7 |
|
7 | |||
| 8 | foo: it => import("./Foo").then(({ Foo }) => it |
|
8 | foo: it => import("./Foo").then(({ Foo }) => it | |
| @@ -1,6 +1,6 | |||||
| 1 | import { Foo } from "./Foo"; |
|
1 | import { Foo } from "./Foo"; | |
|
|
2 | import { Box } from "./Box"; | |||
| 2 | import { Bar } from "./Bar"; |
|
3 | import { Bar } from "./Bar"; | |
| 3 | import { Box } from "./Box"; |
|
|||
| 4 |
|
4 | |||
| 5 | /** |
|
5 | /** | |
| 6 | * Сервисы доступные внутри контейнера |
|
6 | * Сервисы доступные внутри контейнера | |
| @@ -13,3 +13,10 export interface Services { | |||||
| 13 | host: string; |
|
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 | t.assert(container.resolve("host"), "Should resolve simple value"); |
|
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 | }); | |||
| @@ -4,7 +4,7 | |||||
| 4 | "experimentalDecorators": true, |
|
4 | "experimentalDecorators": true, | |
| 5 | "noEmitOnError": true, |
|
5 | "noEmitOnError": true, | |
| 6 | "listFiles": true, |
|
6 | "listFiles": true, | |
| 7 | "strict": true, |
|
7 | //"strict": true, | |
| 8 | "types": [], |
|
8 | "types": [], | |
| 9 | "target": "ES5", |
|
9 | "target": "ES5", | |
| 10 | "lib": ["es5", "es2015.promise", "es2015.symbol", "es2015.iterable", "dom", "scripthost"] |
|
10 | "lib": ["es5", "es2015.promise", "es2015.symbol", "es2015.iterable", "dom", "scripthost"] | |
General Comments 0
You need to be logged in to leave comments.
Login now
