##// 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 7 type Setter<T = any> = (v: T) => void;
8 8
9 type Injector<T> = {
10 [k in keyof T]: Setter;
11 };
12
13 9 type Compatible<T1, T2> = T1 extends T2 ? any : never;
14 10
15 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> {
20 new (...params: A): T;
21 prototype: T;
22 }
15 type ExtractDependency<D, S> = D extends { $dependency: infer K } ? D extends { lazy: true } ? () => ExtractService<K, S> : ExtractService<K, S> : VisitDependency<D, S>;
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 19 export class Builder<T, S> {
27 provides() {
28 return <C extends Constructor<T>>(constructor: C) => {
29 return constructor;
20 consume<P extends any[]>(...args: P) {
21 return <C extends new (...args: ExtractDependency<P, S>) => T>(constructor: C) => {
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 37 }
49
50 }
@@ -55,7 +55,7 export interface IActivatable {
55 55 * can be activated and manages the active state of the
56 56 * component
57 57 */
58 setActivationController(controller: IActivationController);
58 setActivationController(controller: IActivationController): void;
59 59
60 60 /**
61 61 * Gets the current activation controller for this component
@@ -1,18 +1,33
1 1 import { Foo } from "./Foo";
2 import { config } from "./config";
2 3
3 export class Bar {
4 name = "bar";
4 const service = config.build("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; }) {
9 if (_opts && _opts.foo)
10 this.foo = _opts.foo;
15 _v: Foo | undefined;
16
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 28 getFoo() {
14 if (this.foo === undefined)
29 if (this._v === undefined)
15 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 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 6 export class Box<T> {
7 7 private _value: T | undefined;
8 8
@@ -15,7 +15,6 export class Box<T> {
15 15 this._value = value;
16 16 }
17 17
18 @service.inject("foo")
19 18 setObj(value: object) {
20 19
21 20 }
@@ -26,4 +25,4 export class Box<T> {
26 25
27 26 return this._value;
28 27 }
29 } No newline at end of file
28 }
@@ -1,3 +1,3
1 1 export class Foo {
2 name = "foo";
2 fooName = "foo";
3 3 }
@@ -8,8 +8,27 interface RegistrationOptions {
8 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 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 34 interface ContainerServices {
@@ -26,4 +45,23 interface ContainerServices {
26 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 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 89 const b1 = container.resolve("bar") as Bar;
90 90
91 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