##// END OF EJS Templates
Working on IoC container configuration
cin -
r111:33420a95f637 ioc ts support
parent child
Show More
@@ -6,27 +6,20 export interface InjectOptions {
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 Constructor<T>>(constructor: C) => {
21 return <C extends new (...args: ExtractDependency<P, S>) => T>(constructor: C) => {
29 return constructor;
22 // return constructor;
30 };
23 };
31 }
24 }
32
25
@@ -41,10 +34,4 export class Builder<T, S> {
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 }
@@ -55,7 +55,7 export interface IActivatable {
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
@@ -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.foo === undefined)
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.foo;
31 return this._v;
17 }
32 }
18 }
33 }
@@ -1,8 +1,8
1 import { config } from "./config";
1 import { config } from "./config";
2
2
3 const service = config.service("barBox");
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
@@ -15,7 +15,6 export class Box<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 }
@@ -26,4 +25,4 export class Box<T> {
26
25
27 return this._value;
26 return this._value;
28 }
27 }
29 } No newline at end of file
28 }
@@ -1,3 +1,3
1 export class Foo {
1 export class Foo {
2 name = "foo";
2 fooName = "foo";
3 }
3 }
@@ -8,8 +8,27 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 service<K extends keyof S>(name: K): Builder<S[K], S>;
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 {
@@ -26,4 +45,23 interface ContainerServices {
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", ;
@@ -89,5 +89,5 test("Load configuration from module", a
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.foo), "bar.foo should not be null");
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