| @@ -1,50 +1,37 | |||||
| 1 | import { Constructor } from "../interfaces"; |
|
1 | import { Constructor } from "../interfaces"; | |
| 2 |
|
2 | |||
| 3 | export interface InjectOptions { |
|
3 | export interface InjectOptions { | |
| 4 | lazy?: boolean; |
|
4 | lazy?: boolean; | |
| 5 | } |
|
5 | } | |
| 6 |
|
6 | |||
| 7 | type Setter<T = any> = (v: T) => void; |
|
7 | type Setter<T = any> = (v: T) => void; | |
| 8 |
|
8 | |||
| 9 | type Injector<T> = { |
|
|||
| 10 | [k in keyof T]: Setter; |
|
|||
| 11 | }; |
|
|||
| 12 |
|
||||
| 13 | type Compatible<T1, T2> = T1 extends T2 ? any : never; |
|
9 | type Compatible<T1, T2> = T1 extends T2 ? any : never; | |
| 14 |
|
10 | |||
| 15 | type SetterType<T> = T extends (v: infer V) => void ? V : never; |
|
11 | type SetterType<T> = T extends (v: infer V) => void ? V : never; | |
| 16 |
|
12 | |||
| 17 | type Tuple<T = any> = Parameters<(...args: T[]) => void>; |
|
13 | type ExtractService<K, S> = K extends keyof S ? S[K] : K; | |
| 18 |
|
14 | |||
| 19 | interface Newable<A extends Tuple, T> { |
|
15 | type ExtractDependency<D, S> = D extends { $dependency: infer K } ? D extends { lazy: true } ? () => ExtractService<K, S> : ExtractService<K, S> : VisitDependency<D, S>; | |
| 20 | new (...params: A): T; |
|
|||
| 21 | prototype: T; |
|
|||
| 22 | } |
|
|||
| 23 |
|
16 | |||
| 24 | type MapTuple<T, A extends (keyof T)[]> = { [K in keyof A] : K extends number ? T[ A[K] ] : A[K] }; |
|
17 | type VisitDependency<D, S> = D extends {} ? { [K in keyof D]: ExtractDependency<D[K], S> } : D; | |
| 25 |
|
18 | |||
| 26 | export class Builder<T, S> { |
|
19 | export class Builder<T, S> { | |
| 27 | provides() { |
|
20 | consume<P extends any[]>(...args: P) { | |
| 28 |
return <C extends |
|
21 | return <C extends new (...args: ExtractDependency<P, S>) => T>(constructor: C) => { | |
| 29 | return constructor; |
|
22 | // return constructor; | |
| 30 | }; |
|
23 | }; | |
| 31 | } |
|
24 | } | |
| 32 |
|
25 | |||
| 33 | inject<K extends keyof S>(dependency: K) { |
|
26 | inject<K extends keyof S>(dependency: K) { | |
| 34 | // K = "bar" |
|
27 | // K = "bar" | |
| 35 | // M = "setValue" |
|
28 | // M = "setValue" | |
| 36 | // S[K] = Bar |
|
29 | // S[K] = Bar | |
| 37 | // T[M] = (value: string) => void |
|
30 | // T[M] = (value: string) => void | |
| 38 | // P[m] = (value: V) => void |
|
31 | // P[m] = (value: V) => void | |
| 39 | return <P, M extends keyof (T | P)>(target: P, memberName: M, descriptor: TypedPropertyDescriptor<Compatible<T[M], Setter<S[K]>>>) => { |
|
32 | return <P, M extends keyof (T | P)>(target: P, memberName: M, descriptor: TypedPropertyDescriptor<Compatible<T[M], Setter<S[K]>>>) => { | |
| 40 |
|
33 | |||
| 41 | }; |
|
34 | }; | |
| 42 | } |
|
35 | } | |
| 43 |
|
36 | |||
| 44 | dependencies<D extends (keyof S)[]>(...deps: D) { |
|
|||
| 45 | return <C extends Constructor<T>>(constructor: MapTuple<S, D> extends ConstructorParameters<C> ? C : never) => { |
|
|||
| 46 | return constructor; |
|
|||
| 47 | } ; |
|
|||
| 48 | } |
|
|||
| 49 |
|
||||
| 50 | } |
|
37 | } | |
| @@ -1,111 +1,111 | |||||
| 1 | export interface Constructor<T = {}> { |
|
1 | export interface Constructor<T = {}> { | |
| 2 | new(...args: any[]): T; |
|
2 | new(...args: any[]): T; | |
| 3 | prototype: T; |
|
3 | prototype: T; | |
| 4 | } |
|
4 | } | |
| 5 |
|
5 | |||
| 6 | export type Factory<T = {}> = (...args: any[]) => T; |
|
6 | export type Factory<T = {}> = (...args: any[]) => T; | |
| 7 |
|
7 | |||
| 8 | export type Predicate<T = any> = (x: T) => boolean; |
|
8 | export type Predicate<T = any> = (x: T) => boolean; | |
| 9 |
|
9 | |||
| 10 | export interface MapOf<T> { |
|
10 | export interface MapOf<T> { | |
| 11 | [key: string]: T; |
|
11 | [key: string]: T; | |
| 12 | } |
|
12 | } | |
| 13 |
|
13 | |||
| 14 | export interface IDestroyable { |
|
14 | export interface IDestroyable { | |
| 15 | destroy(): void; |
|
15 | destroy(): void; | |
| 16 | } |
|
16 | } | |
| 17 |
|
17 | |||
| 18 | export interface IRemovable { |
|
18 | export interface IRemovable { | |
| 19 | remove(): void; |
|
19 | remove(): void; | |
| 20 | } |
|
20 | } | |
| 21 |
|
21 | |||
| 22 | export interface ICancellation { |
|
22 | export interface ICancellation { | |
| 23 | throwIfRequested(): void; |
|
23 | throwIfRequested(): void; | |
| 24 | isRequested(): boolean; |
|
24 | isRequested(): boolean; | |
| 25 | isSupported(): boolean; |
|
25 | isSupported(): boolean; | |
| 26 | register(cb: (e: any) => void): IDestroyable; |
|
26 | register(cb: (e: any) => void): IDestroyable; | |
| 27 | } |
|
27 | } | |
| 28 |
|
28 | |||
| 29 | /** |
|
29 | /** | |
| 30 | * ΠΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡΠΈΠΉ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΡ Π°ΠΊΡΠΈΠ²Π°ΡΠΈΡ |
|
30 | * ΠΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡΠΈΠΉ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΡ Π°ΠΊΡΠΈΠ²Π°ΡΠΈΡ | |
| 31 | */ |
|
31 | */ | |
| 32 | export interface IActivatable { |
|
32 | export interface IActivatable { | |
| 33 | /** |
|
33 | /** | |
| 34 | * @returns Boolean indicates the current state |
|
34 | * @returns Boolean indicates the current state | |
| 35 | */ |
|
35 | */ | |
| 36 | isActive(): boolean; |
|
36 | isActive(): boolean; | |
| 37 |
|
37 | |||
| 38 | /** |
|
38 | /** | |
| 39 | * Starts the component activation |
|
39 | * Starts the component activation | |
| 40 | * @param ct cancellation token for this operation |
|
40 | * @param ct cancellation token for this operation | |
| 41 | */ |
|
41 | */ | |
| 42 | activate(ct?: ICancellation): Promise<void>; |
|
42 | activate(ct?: ICancellation): Promise<void>; | |
| 43 |
|
43 | |||
| 44 | /** |
|
44 | /** | |
| 45 | * Starts the component deactivation |
|
45 | * Starts the component deactivation | |
| 46 | * @param ct cancellation token for this operation |
|
46 | * @param ct cancellation token for this operation | |
| 47 | */ |
|
47 | */ | |
| 48 | deactivate(ct?: ICancellation): Promise<void>; |
|
48 | deactivate(ct?: ICancellation): Promise<void>; | |
| 49 |
|
49 | |||
| 50 | /** |
|
50 | /** | |
| 51 | * Sets the activation controller for this component |
|
51 | * Sets the activation controller for this component | |
| 52 | * @param controller The activation controller |
|
52 | * @param controller The activation controller | |
| 53 | * |
|
53 | * | |
| 54 | * Activation controller checks whether this component |
|
54 | * Activation controller checks whether this component | |
| 55 | * can be activated and manages the active state of the |
|
55 | * can be activated and manages the active state of the | |
| 56 | * component |
|
56 | * component | |
| 57 | */ |
|
57 | */ | |
| 58 | setActivationController(controller: IActivationController); |
|
58 | setActivationController(controller: IActivationController): void; | |
| 59 |
|
59 | |||
| 60 | /** |
|
60 | /** | |
| 61 | * Gets the current activation controller for this component |
|
61 | * Gets the current activation controller for this component | |
| 62 | */ |
|
62 | */ | |
| 63 | getActivationController(): IActivationController; |
|
63 | getActivationController(): IActivationController; | |
| 64 | } |
|
64 | } | |
| 65 |
|
65 | |||
| 66 | export interface IActivationController { |
|
66 | export interface IActivationController { | |
| 67 | activating(component: IActivatable, ct?: ICancellation): Promise<void>; |
|
67 | activating(component: IActivatable, ct?: ICancellation): Promise<void>; | |
| 68 |
|
68 | |||
| 69 | activated(component: IActivatable, ct?: ICancellation): Promise<void>; |
|
69 | activated(component: IActivatable, ct?: ICancellation): Promise<void>; | |
| 70 |
|
70 | |||
| 71 | deactivating(component: IActivatable, ct?: ICancellation): Promise<void>; |
|
71 | deactivating(component: IActivatable, ct?: ICancellation): Promise<void>; | |
| 72 |
|
72 | |||
| 73 | deactivated(component: IActivatable, ct?: ICancellation): Promise<void>; |
|
73 | deactivated(component: IActivatable, ct?: ICancellation): Promise<void>; | |
| 74 |
|
74 | |||
| 75 | deactivate(ct?: ICancellation): Promise<void>; |
|
75 | deactivate(ct?: ICancellation): Promise<void>; | |
| 76 |
|
76 | |||
| 77 | activate(component: IActivatable, ct?: ICancellation): Promise<void>; |
|
77 | activate(component: IActivatable, ct?: ICancellation): Promise<void>; | |
| 78 |
|
78 | |||
| 79 | getActive(): IActivatable; |
|
79 | getActive(): IActivatable; | |
| 80 | } |
|
80 | } | |
| 81 |
|
81 | |||
| 82 | export interface IAsyncComponent { |
|
82 | export interface IAsyncComponent { | |
| 83 | getCompletion(): Promise<void>; |
|
83 | getCompletion(): Promise<void>; | |
| 84 | } |
|
84 | } | |
| 85 |
|
85 | |||
| 86 | export interface ICancellable { |
|
86 | export interface ICancellable { | |
| 87 | cancel(reason?: any): void; |
|
87 | cancel(reason?: any): void; | |
| 88 | } |
|
88 | } | |
| 89 |
|
89 | |||
| 90 | export interface IObservable<T> { |
|
90 | export interface IObservable<T> { | |
| 91 | on(next: (x: T) => void, error?: (e: any) => void, complete?: () => void): IDestroyable; |
|
91 | on(next: (x: T) => void, error?: (e: any) => void, complete?: () => void): IDestroyable; | |
| 92 | next(ct?: ICancellation): Promise<T>; |
|
92 | next(ct?: ICancellation): Promise<T>; | |
| 93 | } |
|
93 | } | |
| 94 |
|
94 | |||
| 95 | export interface IObserver<T> { |
|
95 | export interface IObserver<T> { | |
| 96 | next(event: T): void; |
|
96 | next(event: T): void; | |
| 97 |
|
97 | |||
| 98 | error(e: any): void; |
|
98 | error(e: any): void; | |
| 99 |
|
99 | |||
| 100 | complete(): void; |
|
100 | complete(): void; | |
| 101 | } |
|
101 | } | |
| 102 |
|
102 | |||
| 103 | export interface TextWriter { |
|
103 | export interface TextWriter { | |
| 104 | write(obj: any): void; |
|
104 | write(obj: any): void; | |
| 105 | write(format: string, ...args: any[]): void; |
|
105 | write(format: string, ...args: any[]): void; | |
| 106 |
|
106 | |||
| 107 | writeLine(obj?: any): void; |
|
107 | writeLine(obj?: any): void; | |
| 108 | writeLine(format: string, ...args: any[]): void; |
|
108 | writeLine(format: string, ...args: any[]): void; | |
| 109 |
|
109 | |||
| 110 | writeValue(value: any, spec?: string): void; |
|
110 | writeValue(value: any, spec?: string): void; | |
| 111 | } |
|
111 | } | |
| @@ -1,18 +1,33 | |||||
| 1 | import { Foo } from "./Foo"; |
|
1 | import { Foo } from "./Foo"; | |
|
|
2 | import { config } from "./config"; | |||
| 2 |
|
3 | |||
| 3 | export class Bar { |
|
4 | const service = config.build("bar"); | |
| 4 | name = "bar"; |
|
|||
| 5 |
|
5 | |||
| 6 | foo: Foo | undefined; |
|
6 | @service.consume({ | |
|
|
7 | f: config.dependency("foo"), | |||
|
|
8 | nested: { | |||
|
|
9 | lazy: config.lazy("foo") | |||
|
|
10 | } | |||
|
|
11 | }) | |||
|
|
12 | export class Bar { | |||
|
|
13 | barName = "bar"; | |||
| 7 |
|
14 | |||
| 8 | constructor(_opts?: { foo?: Foo; }) { |
|
15 | _v: Foo | undefined; | |
| 9 | if (_opts && _opts.foo) |
|
16 | ||
| 10 | this.foo = _opts.foo; |
|
17 | constructor(_opts: { | |
|
|
18 | f: Foo; | |||
|
|
19 | nested: { | |||
|
|
20 | lazy: () => Foo | |||
|
|
21 | } | |||
|
|
22 | }) { | |||
|
|
23 | ||||
|
|
24 | if (_opts && _opts.f) | |||
|
|
25 | this._v = _opts.f; | |||
| 11 | } |
|
26 | } | |
| 12 |
|
27 | |||
| 13 | getFoo() { |
|
28 | getFoo() { | |
| 14 |
if (this. |
|
29 | if (this._v === undefined) | |
| 15 | throw new Error("The foo isn't set"); |
|
30 | throw new Error("The foo isn't set"); | |
| 16 |
return this. |
|
31 | return this._v; | |
| 17 | } |
|
32 | } | |
| 18 | } |
|
33 | } | |
| @@ -1,29 +1,28 | |||||
| 1 | import { config } from "./config"; |
|
1 | import { config } from "./config"; | |
| 2 |
|
2 | |||
| 3 |
const service = config. |
|
3 | const service = config.build("barBox"); | |
| 4 |
|
4 | |||
| 5 | @service.provides() |
|
5 | @service.consume(config.dependency("bar")) | |
| 6 | export class Box<T> { |
|
6 | export class Box<T> { | |
| 7 | private _value: T | undefined; |
|
7 | private _value: T | undefined; | |
| 8 |
|
8 | |||
| 9 | constructor(value: T) { |
|
9 | constructor(value: T) { | |
| 10 | this._value = value; |
|
10 | this._value = value; | |
| 11 | } |
|
11 | } | |
| 12 |
|
12 | |||
| 13 | @service.inject("bar") |
|
13 | @service.inject("bar") | |
| 14 | setValue(value: T) { |
|
14 | setValue(value: T) { | |
| 15 | this._value = value; |
|
15 | this._value = value; | |
| 16 | } |
|
16 | } | |
| 17 |
|
17 | |||
| 18 | @service.inject("foo") |
|
|||
| 19 | setObj(value: object) { |
|
18 | setObj(value: object) { | |
| 20 |
|
19 | |||
| 21 | } |
|
20 | } | |
| 22 |
|
21 | |||
| 23 | getValue() { |
|
22 | getValue() { | |
| 24 | if (this._value === undefined) |
|
23 | if (this._value === undefined) | |
| 25 | throw new Error("Trying to get a value from the empty box"); |
|
24 | throw new Error("Trying to get a value from the empty box"); | |
| 26 |
|
25 | |||
| 27 | return this._value; |
|
26 | return this._value; | |
| 28 | } |
|
27 | } | |
| 29 | } No newline at end of file |
|
28 | } | |
| @@ -1,29 +1,67 | |||||
| 1 | import { Foo } from "./Foo"; |
|
1 | import { Foo } from "./Foo"; | |
| 2 | import { Bar } from "./Bar"; |
|
2 | import { Bar } from "./Bar"; | |
| 3 | import { ActivationType } from "../di/interfaces"; |
|
3 | import { ActivationType } from "../di/interfaces"; | |
| 4 | import { Builder } from "../di/Annotations"; |
|
4 | import { Builder } from "../di/Annotations"; | |
| 5 | import { Box } from "./Box"; |
|
5 | import { Box } from "./Box"; | |
| 6 |
|
6 | |||
| 7 | interface RegistrationOptions { |
|
7 | interface RegistrationOptions { | |
| 8 | activation?: ActivationType; |
|
8 | activation?: ActivationType; | |
| 9 | } |
|
9 | } | |
| 10 |
|
10 | |||
|
|
11 | interface Dependency<K extends keyof any> { | |||
|
|
12 | $dependency: K; | |||
|
|
13 | ||||
|
|
14 | lazy?: boolean; | |||
|
|
15 | } | |||
|
|
16 | ||||
|
|
17 | interface Lazy<K extends keyof any> extends Dependency<K> { | |||
|
|
18 | lazy: true; | |||
|
|
19 | } | |||
|
|
20 | ||||
|
|
21 | type PromiseOrValue<T> = T | PromiseLike<T>; | |||
|
|
22 | ||||
| 11 | interface ConfigBuilder<S> { |
|
23 | interface ConfigBuilder<S> { | |
| 12 |
|
|
24 | build<K extends keyof S, T = S[K]>(name: K): Builder<T, S>; | |
|
|
25 | ||||
|
|
26 | dependency<K extends keyof S>(name: K): Dependency<K>; | |||
|
|
27 | ||||
|
|
28 | lazy<K extends keyof S>(name: K): Lazy<K>; | |||
|
|
29 | ||||
|
|
30 | mapTo<K extends keyof S>(name: K, ctor: () => PromiseOrValue<new (...args: any[]) => S[K]>): ConfigBuilder<S>; | |||
|
|
31 | ||||
| 13 | } |
|
32 | } | |
| 14 |
|
33 | |||
| 15 | interface ContainerServices { |
|
34 | interface ContainerServices { | |
| 16 | barBox: Box<Bar>; |
|
35 | barBox: Box<Bar>; | |
| 17 |
|
36 | |||
| 18 | foo: Foo; |
|
37 | foo: Foo; | |
| 19 |
|
38 | |||
| 20 | bar: Bar; |
|
39 | bar: Bar; | |
| 21 |
|
40 | |||
| 22 | password: string; |
|
41 | password: string; | |
| 23 |
|
42 | |||
| 24 | user: string; |
|
43 | user: string; | |
| 25 |
|
44 | |||
| 26 | timeout: number; |
|
45 | timeout: number; | |
| 27 | } |
|
46 | } | |
| 28 |
|
47 | |||
|
|
48 | declare function load<M, C extends keyof M>(m: PromiseLike<M>, name: C): () => PromiseLike<M[C]>; | |||
|
|
49 | ||||
|
|
50 | const t = { | |||
|
|
51 | barBox: load(import("./Box"), "Box"), | |||
|
|
52 | ||||
|
|
53 | foo: async () => (await import("./Bar")).Bar, | |||
|
|
54 | ||||
|
|
55 | bar: Bar, | |||
|
|
56 | ||||
|
|
57 | password: String, | |||
|
|
58 | ||||
|
|
59 | user: String, | |||
|
|
60 | ||||
|
|
61 | timeout: Number | |||
|
|
62 | }; | |||
|
|
63 | ||||
| 29 | export declare const config: ConfigBuilder<ContainerServices>; |
|
64 | export declare const config: ConfigBuilder<ContainerServices>; | |
|
|
65 | config | |||
|
|
66 | .mapTo("bar", ) | |||
|
|
67 | .mapTo("barBox", ; | |||
| @@ -1,93 +1,93 | |||||
| 1 | import { test } from "./TestTraits"; |
|
1 | import { test } from "./TestTraits"; | |
| 2 | import { Container } from "../di/Container"; |
|
2 | import { Container } from "../di/Container"; | |
| 3 | import { ReferenceDescriptor } from "../di/ReferenceDescriptor"; |
|
3 | import { ReferenceDescriptor } from "../di/ReferenceDescriptor"; | |
| 4 | import { AggregateDescriptor } from "../di/AggregateDescriptor"; |
|
4 | import { AggregateDescriptor } from "../di/AggregateDescriptor"; | |
| 5 | import { ValueDescriptor } from "../di/ValueDescriptor"; |
|
5 | import { ValueDescriptor } from "../di/ValueDescriptor"; | |
| 6 | import { Foo } from "../mock/Foo"; |
|
6 | import { Foo } from "../mock/Foo"; | |
| 7 | import { Bar } from "../mock/Bar"; |
|
7 | import { Bar } from "../mock/Bar"; | |
| 8 | import { isNull } from "../safe"; |
|
8 | import { isNull } from "../safe"; | |
| 9 |
|
9 | |||
| 10 | test("Container register/resolve tests", async t => { |
|
10 | test("Container register/resolve tests", async t => { | |
| 11 | const container = new Container(); |
|
11 | const container = new Container(); | |
| 12 |
|
12 | |||
| 13 | const connection1 = "db://localhost"; |
|
13 | const connection1 = "db://localhost"; | |
| 14 |
|
14 | |||
| 15 | t.throws( |
|
15 | t.throws( | |
| 16 | () => container.register("bla-bla", "bla-bla"), |
|
16 | () => container.register("bla-bla", "bla-bla"), | |
| 17 | "Do not allow to register anything other than descriptors" |
|
17 | "Do not allow to register anything other than descriptors" | |
| 18 | ); |
|
18 | ); | |
| 19 |
|
19 | |||
| 20 | t.doesNotThrow( |
|
20 | t.doesNotThrow( | |
| 21 | () => container.register("connection", new ValueDescriptor(connection1)), |
|
21 | () => container.register("connection", new ValueDescriptor(connection1)), | |
| 22 | "register ValueDescriptor" |
|
22 | "register ValueDescriptor" | |
| 23 | ); |
|
23 | ); | |
| 24 |
|
24 | |||
| 25 | t.equals(container.resolve("connection"), connection1, "resolve string value"); |
|
25 | t.equals(container.resolve("connection"), connection1, "resolve string value"); | |
| 26 |
|
26 | |||
| 27 | t.doesNotThrow( |
|
27 | t.doesNotThrow( | |
| 28 | () => container.register( |
|
28 | () => container.register( | |
| 29 | "dbParams", |
|
29 | "dbParams", | |
| 30 | new AggregateDescriptor({ |
|
30 | new AggregateDescriptor({ | |
| 31 | timeout: 10, |
|
31 | timeout: 10, | |
| 32 | connection: new ReferenceDescriptor({ name: "connection" }) |
|
32 | connection: new ReferenceDescriptor({ name: "connection" }) | |
| 33 | }) |
|
33 | }) | |
| 34 | ), |
|
34 | ), | |
| 35 | "register AggregateDescriptor" |
|
35 | "register AggregateDescriptor" | |
| 36 | ); |
|
36 | ); | |
| 37 |
|
37 | |||
| 38 | const dbParams = container.resolve("dbParams"); |
|
38 | const dbParams = container.resolve("dbParams"); | |
| 39 | t.equals(dbParams.connection, connection1, "should get string value 'dbParams.connection'"); |
|
39 | t.equals(dbParams.connection, connection1, "should get string value 'dbParams.connection'"); | |
| 40 | }); |
|
40 | }); | |
| 41 |
|
41 | |||
| 42 | test("Container configure/resolve tests", async t => { |
|
42 | test("Container configure/resolve tests", async t => { | |
| 43 |
|
43 | |||
| 44 | const container = new Container(); |
|
44 | const container = new Container(); | |
| 45 |
|
45 | |||
| 46 | await container.configure({ |
|
46 | await container.configure({ | |
| 47 | foo: { |
|
47 | foo: { | |
| 48 | $type: Foo |
|
48 | $type: Foo | |
| 49 | }, |
|
49 | }, | |
| 50 |
|
50 | |||
| 51 | box: { |
|
51 | box: { | |
| 52 | $type: Bar, |
|
52 | $type: Bar, | |
| 53 | params: { |
|
53 | params: { | |
| 54 | $dependency: "foo" |
|
54 | $dependency: "foo" | |
| 55 | } |
|
55 | } | |
| 56 | }, |
|
56 | }, | |
| 57 |
|
57 | |||
| 58 | bar: { |
|
58 | bar: { | |
| 59 | $type: Bar, |
|
59 | $type: Bar, | |
| 60 | params: { |
|
60 | params: { | |
| 61 | db: { |
|
61 | db: { | |
| 62 | provider: { |
|
62 | provider: { | |
| 63 | $dependency: "db" |
|
63 | $dependency: "db" | |
| 64 | } |
|
64 | } | |
| 65 | } |
|
65 | } | |
| 66 | } |
|
66 | } | |
| 67 | } |
|
67 | } | |
| 68 | }); |
|
68 | }); | |
| 69 | t.pass("should configure from js object"); |
|
69 | t.pass("should configure from js object"); | |
| 70 |
|
70 | |||
| 71 | const f1 = container.resolve("foo"); |
|
71 | const f1 = container.resolve("foo"); | |
| 72 |
|
72 | |||
| 73 | t.assert(!isNull(f1), "foo should be not null"); |
|
73 | t.assert(!isNull(f1), "foo should be not null"); | |
| 74 |
|
74 | |||
| 75 | t.throws(() => container.resolve("bar"), "should not resolve dependency 'db'"); |
|
75 | t.throws(() => container.resolve("bar"), "should not resolve dependency 'db'"); | |
| 76 |
|
76 | |||
| 77 | }); |
|
77 | }); | |
| 78 |
|
78 | |||
| 79 | test("Load configuration from module", async t => { |
|
79 | test("Load configuration from module", async t => { | |
| 80 | const container = new Container(); |
|
80 | const container = new Container(); | |
| 81 |
|
81 | |||
| 82 | await container.configure("../mock/config1", { contextRequire: require }); |
|
82 | await container.configure("../mock/config1", { contextRequire: require }); | |
| 83 | t.pass("The configuration should load"); |
|
83 | t.pass("The configuration should load"); | |
| 84 |
|
84 | |||
| 85 | const f1 = container.resolve("foo"); |
|
85 | const f1 = container.resolve("foo"); | |
| 86 |
|
86 | |||
| 87 | t.assert(!isNull(f1), "foo should be not null"); |
|
87 | t.assert(!isNull(f1), "foo should be not null"); | |
| 88 |
|
88 | |||
| 89 | const b1 = container.resolve("bar") as Bar; |
|
89 | const b1 = container.resolve("bar") as Bar; | |
| 90 |
|
90 | |||
| 91 | t.assert(!isNull(b1), "bar should not be null"); |
|
91 | t.assert(!isNull(b1), "bar should not be null"); | |
| 92 |
t.assert(!isNull(b1. |
|
92 | t.assert(!isNull(b1._v), "bar.foo should not be null"); | |
| 93 | }); |
|
93 | }); | |
General Comments 0
You need to be logged in to leave comments.
Login now
