##// 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 import { primitive } from "../safe";
1 import { primitive } from "../safe";
2 import { TypeRegistration } from "./Configuration";
3
3
4 export interface InjectOptions {
4 export interface InjectOptions {
5 lazy?: boolean;
5 lazy?: boolean;
6 }
6 }
7
7
8 interface Dependency<K extends keyof any> {
8 export interface Dependency<K extends keyof any> {
9 $dependency: K;
9 $dependency: K;
10
10
11 lazy?: boolean;
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 lazy: true;
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 type ExtractService<K, S> = K extends keyof S ? S[K] : K;
20 type ExtractService<K, S> = K extends keyof S ? S[K] : K;
21
21
22 type ExtractDependency<D, S> = D extends { $dependency: infer K } ?
22 type ExtractDependency<D, S> = D extends { $dependency: infer K } ?
23 D extends { lazy: true } ? () => ExtractService<K, S> : ExtractService<K, S> :
23 D extends { lazy: true } ? () => ExtractService<K, S> : ExtractService<K, S> :
24 WalkDependencies<D, S>;
24 WalkDependencies<D, S>;
25
25
26 type WalkDependencies<D, S> = D extends primitive ? D :
26 type WalkDependencies<D, S> = D extends primitive ? D :
27 { [K in keyof D]: ExtractDependency<D[K], S> };
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 export class Builder<T, S> {
29 export class Builder<T, S> {
42 consume<P extends any[]>(...args: P) {
30 declare<P extends any[]>(...args: P) {
43 return <C extends new (...args: ExtractDependency<P, S>) => T>(constructor: C) => {
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 inject<P extends any[]>(...args: P) {
36 inject<P extends any[]>(...args: P) {
48 // K = "bar"
37 // K = "bar"
49 // M = "setValue"
38 // M = "setValue"
50 // S[K] = Bar
39 // S[K] = Bar
51 // T[M] = (value: string) => void
40 // T[M] = (value: string) => void
52 // P[m] = (value: V) => void
41 // P[m] = (value: V) => void
53 return <X extends { [m in M]: (...args: any) => any }, M extends keyof (T | X)>(
42 return <X extends { [m in M]: (...args: any) => any }, M extends keyof (T | X)>(
54 target: X,
43 target: X,
55 memberName: M,
44 memberName: M,
56 descriptor: TypedPropertyDescriptor<Compatible<(...args: ExtractDependency<P, S>) => any, T[M]>>
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> {
51 getDescriptor(): TypeRegistration<T, any, S> {
63 return this as Builder<T2, S>;
64 }
65
66 get<K extends keyof S>(name: K): Dependency<K> {
67 throw new Error();
52 throw new Error();
68 }
53 }
69
54
70 lazy<K extends keyof S>(name: K): Lazy<K> {
55 }
71 throw new Error();
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>;
72 }
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 import { Foo } from "./Foo";
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({
6 @service.declare({
7 foo: service.get("foo"),
7 foo: dependency("foo"),
8 nested: {
8 nested: {
9 lazy: service.lazy("foo")
9 lazy: dependency("foo", {lazy: true})
10 }
10 }
11 })
11 })
12 export class Bar {
12 export class Bar {
13 barName = "bar";
13 barName = "bar";
14
14
15 _v: Foo | undefined;
15 _v: Foo | undefined;
16
16
17 constructor(_opts?: {
17 constructor(_opts?: {
18 foo?: Foo;
18 foo?: Foo;
19 nested?: {
19 nested?: {
20 lazy: () => Foo
20 lazy: () => Foo
21 }
21 }
22 }) {
22 }) {
23
23
24 if (_opts && _opts.foo)
24 if (_opts && _opts.foo)
25 this._v = _opts.foo;
25 this._v = _opts.foo;
26 }
26 }
27
27
28 getFoo() {
28 getFoo() {
29 if (this._v === undefined)
29 if (this._v === undefined)
30 throw new Error("The foo isn't set");
30 throw new Error("The foo isn't set");
31 return this._v;
31 return this._v;
32 }
32 }
33 }
33 }
@@ -1,38 +1,33
1 import { services } from "../di/Annotations";
2 import { Bar } from "./Bar";
1 import { Bar } from "./Bar";
3 import { Foo } from "./Foo";
2 import { define, dependency } from "./services";
4
5 // declare required dependencies
6 const config = services<{
7 bar: Bar;
8 foo: Foo;
9 }>();
10
3
11 // export service descriptor
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 export class Box<T> {
10 export class Box<T> {
16 private _value: T | undefined;
11 private _value: T | undefined;
17
12
18 constructor(value: T) {
13 constructor(value: T) {
19 this._value = value;
14 this._value = value;
20 }
15 }
21
16
22 @service.inject( config.get("bar"))
17 @service.inject(dependency("bar"))
23 setValue(value?: T) {
18 setValue(value: T) {
24 this._value = value;
19 this._value = value;
25 return value;
20 return value;
26 }
21 }
27
22
28 setObj(value: object) {
23 setObj(value: any) {
29
24
30 }
25 }
31
26
32 getValue() {
27 getValue() {
33 if (this._value === undefined)
28 if (this._value === undefined)
34 throw new Error("Trying to get a value from the empty box");
29 throw new Error("Trying to get a value from the empty box");
35
30
36 return this._value;
31 return this._value;
37 }
32 }
38 }
33 }
@@ -1,27 +1,6
1 import { Foo } from "./Foo";
1 import { config } from "./services";
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;
14
2
15 }
3 config()
16
4 .register("bar", import("./Bar"))
17 const services = {
5 .register("box", import("./Box"))
18 build: <T>() => {
6 .register("foo", import("./Foo"), "Foo");
19 return new Builder<T, Services>();
20 }
21 };
22
23 namespace services {
24
25 }
26
27 export = services;
General Comments 0
You need to be logged in to leave comments. Login now