##// END OF EJS Templates
configuration draft-1
cin -
r119:86e3aa3c3eea ioc ts support
parent child
Show More
@@ -0,0 +1,23
1 import { Foo } from "./Foo";
2 import { Bar } from "./Bar";
3 import { Box } from "./Box";
4 import { declare } from "../di/Annotations";
5
6 /**
7 * Сервисы доступные внутри контейнера
8 */
9 export interface Services {
10 foo: Foo;
11
12 bar: Bar;
13
14 box: Box<Bar>;
15
16 host: string;
17
18 }
19
20 /**
21 * Экспортируем вспомогательные функции для описания сервисов и кинфогурации
22 */
23 export const { define, dependency, config } = declare<Services>();
@@ -1,75 +1,75
1 import { Constructor } from "../interfaces";
2 1 import { primitive } from "../safe";
2 import { TypeRegistration } from "./Configuration";
3 3
4 4 export interface InjectOptions {
5 5 lazy?: boolean;
6 6 }
7 7
8 interface Dependency<K extends keyof any> {
8 export interface Dependency<K extends keyof any> {
9 9 $dependency: K;
10 10
11 11 lazy?: boolean;
12 12 }
13 13
14 interface Lazy<K extends keyof any> extends Dependency<K> {
14 export interface Lazy<K extends keyof any> extends Dependency<K> {
15 15 lazy: true;
16 16 }
17 17
18 type Compatible<T1, T2> = T1 extends T2 ? any : never;
18 type Compatible<T1, T2> = T2 extends T1 ? any : never;
19 19
20 20 type ExtractService<K, S> = K extends keyof S ? S[K] : K;
21 21
22 22 type ExtractDependency<D, S> = D extends { $dependency: infer K } ?
23 23 D extends { lazy: true } ? () => ExtractService<K, S> : ExtractService<K, S> :
24 24 WalkDependencies<D, S>;
25 25
26 26 type WalkDependencies<D, S> = D extends primitive ? D :
27 27 { [K in keyof D]: ExtractDependency<D[K], S> };
28 28
29 interface Services<S> {
30 get<K extends keyof S>(name: K): Dependency<K>;
31
32 lazy<K extends keyof S>(name: K): Lazy<K>;
33
34 build<T extends object>(): Builder<T, S>;
35 }
36
37 export declare function services<S extends object>(): Services<S>;
38
39 export declare function build<T = never, S = any>(): Builder<T, S>;
40
41 29 export class Builder<T, S> {
42 consume<P extends any[]>(...args: P) {
30 declare<P extends any[]>(...args: P) {
43 31 return <C extends new (...args: ExtractDependency<P, S>) => T>(constructor: C) => {
32 return constructor as C & { service: Builder<T, S> };
44 33 };
45 34 }
46 35
47 36 inject<P extends any[]>(...args: P) {
48 37 // K = "bar"
49 38 // M = "setValue"
50 39 // S[K] = Bar
51 40 // T[M] = (value: string) => void
52 41 // P[m] = (value: V) => void
53 42 return <X extends { [m in M]: (...args: any) => any }, M extends keyof (T | X)>(
54 43 target: X,
55 44 memberName: M,
56 45 descriptor: TypedPropertyDescriptor<Compatible<(...args: ExtractDependency<P, S>) => any, T[M]>>
57 46 ) => {
58 47
59 48 };
60 49 }
61 50
62 cast<T2 extends T>(): Builder<T2, S> {
63 return this as Builder<T2, S>;
64 }
65
66 get<K extends keyof S>(name: K): Dependency<K> {
51 getDescriptor(): TypeRegistration<T, any, S> {
67 52 throw new Error();
68 53 }
69 54
70 lazy<K extends keyof S>(name: K): Lazy<K> {
71 throw new Error();
72 }
55 }
56
57 interface Declaration<S> {
58 define<T>(): Builder<T, S>;
59
60 dependency<K extends keyof S>(name: K, opts: { lazy: true }): Lazy<K>;
61 dependency<K extends keyof S>(name: K, opts?: any): Dependency<K>;
62
63 config(): Config<S>;
64 }
73 65
66 interface ServiceModule<T, S> {
67 service: Builder<T, S>;
68 }
74 69
70 interface Config<S> {
71 register<K extends keyof S>(name: K, builder: Builder<S[K], S>): Config<Omit<S, K>>;
72 register<K extends keyof S>(name: K, m: Promise<ServiceModule<S[K], S>>): Config<Omit<S, K>>;
75 73 }
74
75 export declare function declare<S extends object>(): Declaration<S>;
@@ -1,33 +1,33
1 1 import { Foo } from "./Foo";
2 import { build } from "./config";
2 import { define, dependency } from "./services";
3 3
4 const service = build<Bar>();
4 export const service = define<Bar>();
5 5
6 @service.consume({
7 foo: service.get("foo"),
6 @service.declare({
7 foo: dependency("foo"),
8 8 nested: {
9 lazy: service.lazy("foo")
9 lazy: dependency("foo", {lazy: true})
10 10 }
11 11 })
12 12 export class Bar {
13 13 barName = "bar";
14 14
15 15 _v: Foo | undefined;
16 16
17 17 constructor(_opts?: {
18 18 foo?: Foo;
19 19 nested?: {
20 20 lazy: () => Foo
21 21 }
22 22 }) {
23 23
24 24 if (_opts && _opts.foo)
25 25 this._v = _opts.foo;
26 26 }
27 27
28 28 getFoo() {
29 29 if (this._v === undefined)
30 30 throw new Error("The foo isn't set");
31 31 return this._v;
32 32 }
33 33 }
@@ -1,38 +1,33
1 import { services } from "../di/Annotations";
2 1 import { Bar } from "./Bar";
3 import { Foo } from "./Foo";
4
5 // declare required dependencies
6 const config = services<{
7 bar: Bar;
8 foo: Foo;
9 }>();
2 import { define, dependency } from "./services";
10 3
11 4 // export service descriptor
12 export const service = config.build<Box<Bar>>();
5 // через service передается информация о типе зависимости
6 // даже если это шаблон.
7 export const service = define<Box<Bar>>();
13 8
14 @service.consume(config.get("bar"))
9 @service.declare(dependency("bar"))
15 10 export class Box<T> {
16 11 private _value: T | undefined;
17 12
18 13 constructor(value: T) {
19 14 this._value = value;
20 15 }
21 16
22 @service.inject( config.get("bar"))
23 setValue(value?: T) {
17 @service.inject(dependency("bar"))
18 setValue(value: T) {
24 19 this._value = value;
25 20 return value;
26 21 }
27 22
28 setObj(value: object) {
23 setObj(value: any) {
29 24
30 25 }
31 26
32 27 getValue() {
33 28 if (this._value === undefined)
34 29 throw new Error("Trying to get a value from the empty box");
35 30
36 31 return this._value;
37 32 }
38 33 }
@@ -1,27 +1,6
1 import { Foo } from "./Foo";
2 import { Bar } from "./Bar";
3 import { Box } from "./Box";
4 import { Builder } from "../di/Annotations";
5
6 interface Services {
7 foo: Foo;
8
9 bar: Bar;
10
11 box: Box<Foo>;
12
13 host: string;
1 import { config } from "./services";
14 2
15 }
16
17 const services = {
18 build: <T>() => {
19 return new Builder<T, Services>();
20 }
21 };
22
23 namespace services {
24
25 }
26
27 export = services;
3 config()
4 .register("bar", import("./Bar"))
5 .register("box", import("./Box"))
6 .register("foo", import("./Foo"), "Foo");
General Comments 0
You need to be logged in to leave comments. Login now