| @@ -1,37 +1,41 | |||
|
|
1 | 1 | import { Constructor } from "../interfaces"; |
|
|
2 | 2 | |
|
|
3 | 3 | export interface InjectOptions { |
|
|
4 | 4 | lazy?: boolean; |
|
|
5 | 5 | } |
|
|
6 | 6 | |
|
|
7 | 7 | type Setter<T = any> = (v: T) => void; |
|
|
8 | 8 | |
|
|
9 | 9 | type Compatible<T1, T2> = T1 extends T2 ? any : never; |
|
|
10 | 10 | |
|
|
11 | 11 | type SetterType<T> = T extends (v: infer V) => void ? V : never; |
|
|
12 | 12 | |
|
|
13 | 13 | type ExtractService<K, S> = K extends keyof S ? S[K] : K; |
|
|
14 | 14 | |
|
|
15 | 15 | type ExtractDependency<D, S> = D extends { $dependency: infer K } ? D extends { lazy: true } ? () => ExtractService<K, S> : ExtractService<K, S> : VisitDependency<D, S>; |
|
|
16 | 16 | |
|
|
17 | 17 | type VisitDependency<D, S> = D extends {} ? { [K in keyof D]: ExtractDependency<D[K], S> } : D; |
|
|
18 | 18 | |
|
|
19 | 19 | export class Builder<T, S> { |
|
|
20 | 20 | consume<P extends any[]>(...args: P) { |
|
|
21 | 21 | return <C extends new (...args: ExtractDependency<P, S>) => T>(constructor: C) => { |
|
|
22 | // return constructor; | |
|
|
22 | return constructor as typeof constructor & { service: () => T }; | |
|
|
23 | 23 |
|
|
|
24 | 24 | } |
|
|
25 | 25 | |
|
|
26 | 26 | inject<K extends keyof S>(dependency: K) { |
|
|
27 | 27 | // K = "bar" |
|
|
28 | 28 | // M = "setValue" |
|
|
29 | 29 | // S[K] = Bar |
|
|
30 | 30 | // T[M] = (value: string) => void |
|
|
31 | 31 | // P[m] = (value: V) => void |
|
|
32 | 32 | return <P, M extends keyof (T | P)>(target: P, memberName: M, descriptor: TypedPropertyDescriptor<Compatible<T[M], Setter<S[K]>>>) => { |
|
|
33 | 33 | |
|
|
34 | 34 | }; |
|
|
35 | 35 | } |
|
|
36 | 36 | |
|
|
37 | cast<T2 extends T>(): Builder<T2, S> { | |
|
|
38 | return this as Builder<T2, S>; | |
|
|
39 | } | |
|
|
40 | ||
|
|
37 | 41 | } |
| @@ -1,28 +1,28 | |||
|
|
1 | 1 | import { config } from "./config"; |
|
|
2 | 2 | |
|
|
3 | 3 | const service = config.build("barBox"); |
|
|
4 | 4 | |
|
|
5 | 5 | @service.consume(config.dependency("bar")) |
|
|
6 | 6 | export class Box<T> { |
|
|
7 | 7 | private _value: T | undefined; |
|
|
8 | 8 | |
|
|
9 | 9 | constructor(value: T) { |
|
|
10 | 10 | this._value = value; |
|
|
11 | 11 | } |
|
|
12 | 12 | |
|
|
13 | 13 | @service.inject("bar") |
|
|
14 | 14 | setValue(value: T) { |
|
|
15 | 15 | this._value = value; |
|
|
16 | 16 | } |
|
|
17 | 17 | |
|
|
18 | 18 | setObj(value: object) { |
|
|
19 | 19 | |
|
|
20 | 20 | } |
|
|
21 | 21 | |
|
|
22 | 22 | getValue() { |
|
|
23 | 23 | if (this._value === undefined) |
|
|
24 | 24 | throw new Error("Trying to get a value from the empty box"); |
|
|
25 | 25 | |
|
|
26 | 26 | return this._value; |
|
|
27 | 27 | } |
|
|
28 |
} |
|
|
|
28 | } No newline at end of file | |
| @@ -1,67 +1,68 | |||
|
|
1 | 1 | import { Foo } from "./Foo"; |
|
|
2 | 2 | import { Bar } from "./Bar"; |
|
|
3 | 3 | import { ActivationType } from "../di/interfaces"; |
|
|
4 | 4 | import { Builder } from "../di/Annotations"; |
|
|
5 | 5 | import { Box } from "./Box"; |
|
|
6 | 6 | |
|
|
7 | 7 | interface RegistrationOptions { |
|
|
8 | 8 | activation?: ActivationType; |
|
|
9 | 9 | } |
|
|
10 | 10 | |
|
|
11 | 11 | interface Dependency<K extends keyof any> { |
|
|
12 | 12 | $dependency: K; |
|
|
13 | 13 | |
|
|
14 | 14 | lazy?: boolean; |
|
|
15 | 15 | } |
|
|
16 | 16 | |
|
|
17 | 17 | interface Lazy<K extends keyof any> extends Dependency<K> { |
|
|
18 | 18 | lazy: true; |
|
|
19 | 19 | } |
|
|
20 | 20 | |
|
|
21 | 21 | type PromiseOrValue<T> = T | PromiseLike<T>; |
|
|
22 | 22 | |
|
|
23 | 23 | interface ConfigBuilder<S> { |
|
|
24 | 24 | build<K extends keyof S, T = S[K]>(name: K): Builder<T, S>; |
|
|
25 | 25 | |
|
|
26 | 26 | dependency<K extends keyof S>(name: K): Dependency<K>; |
|
|
27 | 27 | |
|
|
28 | 28 | lazy<K extends keyof S>(name: K): Lazy<K>; |
|
|
29 | 29 | |
|
|
30 | 30 | mapTo<K extends keyof S>(name: K, ctor: () => PromiseOrValue<new (...args: any[]) => S[K]>): ConfigBuilder<S>; |
|
|
31 | 31 | |
|
|
32 | 32 | } |
|
|
33 | 33 | |
|
|
34 | 34 | interface ContainerServices { |
|
|
35 | 35 | barBox: Box<Bar>; |
|
|
36 | 36 | |
|
|
37 | 37 | foo: Foo; |
|
|
38 | 38 | |
|
|
39 | 39 | bar: Bar; |
|
|
40 | 40 | |
|
|
41 | 41 | password: string; |
|
|
42 | 42 | |
|
|
43 | 43 | user: string; |
|
|
44 | 44 | |
|
|
45 | 45 | timeout: number; |
|
|
46 | 46 | } |
|
|
47 | 47 | |
|
|
48 | 48 | declare function load<M, C extends keyof M>(m: PromiseLike<M>, name: C): () => PromiseLike<M[C]>; |
|
|
49 | 49 | |
|
|
50 | 50 | const t = { |
|
|
51 | 51 | barBox: load(import("./Box"), "Box"), |
|
|
52 | 52 | |
|
|
53 | 53 | foo: async () => (await import("./Bar")).Bar, |
|
|
54 | 54 | |
|
|
55 | 55 | bar: Bar, |
|
|
56 | 56 | |
|
|
57 | 57 | password: String, |
|
|
58 | 58 | |
|
|
59 | 59 | user: String, |
|
|
60 | 60 | |
|
|
61 | 61 | timeout: Number |
|
|
62 | 62 | }; |
|
|
63 | 63 | |
|
|
64 | declare const bc: typeof Box; | |
|
|
65 | ||
|
|
66 | const x = new bc(); | |
|
|
67 | ||
|
|
64 | 68 | export declare const config: ConfigBuilder<ContainerServices>; |
|
|
65 | config | |
|
|
66 | .mapTo("bar", ) | |
|
|
67 | .mapTo("barBox", ; | |
General Comments 0
You need to be logged in to leave comments.
Login now
