##// END OF EJS Templates
working on typings
cin -
r8:80cb5668e4a7 default
parent child
Show More
@@ -1,71 +1,71
1 import { DescriptorBuilder } from "./DescriptorBuilder";
1 import { DescriptorBuilder } from "./DescriptorBuilder";
2 import { ConfigurableKeys, ContainerServices, RegistrationBuildersMap, ExtractRequired, IContainerBuilder } from "./interfaces";
2 import { ConfigurableKeys, ContainerServices, RegistrationBuildersMap, ExtractRequired, IContainerBuilder } from "./interfaces";
3 import { ServiceContainer } from "./interfaces";
3 import { ServiceContainer } from "./interfaces";
4 import { argumentNotNull, each, isKey } from "./traits";
4 import { argumentNotNull, each, isKey } from "./traits";
5
5
6 export class FluentConfiguration<S extends object, Y extends ConfigurableKeys<S> = ConfigurableKeys<S>> {
6 export class FluentConfiguration<S, Y extends ConfigurableKeys<S> = ConfigurableKeys<S>> {
7
7
8 private _builders: Partial<RegistrationBuildersMap<S>> = {};
8 private _builders: Partial<RegistrationBuildersMap<S>> = {};
9
9
10 /** Adds a declaration of the services to the current config.
10 /** Adds a declaration of the services to the current config.
11 *
11 *
12 * @template D The map of the services
12 * @template D The map of the services
13 * @returns self
13 * @returns self
14 */
14 */
15 declare<D extends Partial<Pick<S, keyof D & keyof S>>>(): FluentConfiguration<S & D, Y | ConfigurableKeys<D>> {
15 declare<D extends Pick<S, keyof D & keyof S>>(): FluentConfiguration<S & D, Y | ConfigurableKeys<D>> {
16 return this as FluentConfiguration<S & D, Y | ConfigurableKeys<D>>;
16 return this as FluentConfiguration<S & D, Y | ConfigurableKeys<D>>;
17 }
17 }
18
18
19 /** Adds compile-time information about the already provided services
19 /** Adds compile-time information about the already provided services
20 *
20 *
21 * @template P The map of the provided services
21 * @template P The map of the provided services
22 * @returns self
22 * @returns self
23 */
23 */
24 provided<P extends Pick<S, keyof P & keyof S>>(): FluentConfiguration<S & P, Exclude<Y, keyof P>> {
24 provided<P extends Pick<S, keyof P & keyof S>>(): FluentConfiguration<S & P, Exclude<Y, keyof P>> {
25 return this as FluentConfiguration<S & P, Exclude<Y, keyof P>>;
25 return this as FluentConfiguration<S & P, Exclude<Y, keyof P>>;
26 }
26 }
27
27
28 /** Register the service.
28 /** Register the service.
29 *
29 *
30 * @param name The name of the service
30 * @param name The name of the service
31 * @param builder The service builder
31 * @param builder The service builder
32 * @returns self
32 * @returns self
33 */
33 */
34 register<K extends Y>(name: K, builder: RegistrationBuildersMap<S>[K]): FluentConfiguration<S, Exclude<Y, K>>;
34 register<K extends Y>(name: K, builder: RegistrationBuildersMap<S>[K]): FluentConfiguration<S, Exclude<Y, K>>;
35 /** Registers the collection of services
35 /** Registers the collection of services
36 * @param config The collection of services to register.
36 * @param config The collection of services to register.
37 * @returns self
37 * @returns self
38 */
38 */
39 register<K extends Y>(config: RegistrationBuildersMap<S, K>): FluentConfiguration<S, Exclude<Y, K>>;
39 register<K extends Y>(config: RegistrationBuildersMap<S, K>): FluentConfiguration<S, Exclude<Y, K>>;
40 register<K extends Y>(nameOrConfig: K | RegistrationBuildersMap<S, K>, builder?: RegistrationBuildersMap<S>[K]) {
40 register<K extends Y>(nameOrConfig: K | RegistrationBuildersMap<S, K>, builder?: RegistrationBuildersMap<S>[K]) {
41 if (isKey(nameOrConfig)) {
41 if (isKey(nameOrConfig)) {
42 argumentNotNull(builder, "builder");
42 argumentNotNull(builder, "builder");
43 this._builders[nameOrConfig] = builder;
43 this._builders[nameOrConfig] = builder;
44 } else {
44 } else {
45 each(nameOrConfig, (v, k) => this.register(k, v));
45 each(nameOrConfig, (v, k) => this.register(k, v));
46 }
46 }
47
47
48 return this as FluentConfiguration<S, Exclude<Y, K>>;
48 return this as FluentConfiguration<S, Exclude<Y, K>>;
49 }
49 }
50
50
51 /**
51 /**
52 * This method is used to enable a compile time check of the configuration.
52 * This method is used to enable a compile time check of the configuration.
53 * If there are not configured services in the configuration the compiler
53 * If there are not configured services in the configuration the compiler
54 * will trigger the error.
54 * will trigger the error.
55 *
55 *
56 * @param missing Empty object literal should always be specified.
56 * @param missing Empty object literal should always be specified.
57 * @returns self
57 * @returns self
58 */
58 */
59 // eslint-disable-next-line @typescript-eslint/no-unused-vars
59 // eslint-disable-next-line @typescript-eslint/no-unused-vars
60 done<M extends ExtractRequired<S,Y>>(missing: M) {
60 done<M extends ExtractRequired<S,Y>>(missing: M) {
61 return this;
61 return this;
62 }
62 }
63
63
64 configure<T extends IContainerBuilder<S>>(builder: T) {
64 configure<T extends IContainerBuilder<S>>(builder: T) {
65 each(this._builders, (v, k) => {
65 each(this._builders, (v, k) => {
66 v(builder.createServiceBuilder(k));
66 v(builder.createServiceBuilder(k));
67 });
67 });
68 builder.build() as T & ServiceContainer<S>;
68 builder.build() as T & ServiceContainer<S>;
69 }
69 }
70
70
71 }
71 }
@@ -1,154 +1,183
1 import { key } from "./traits";
1 import { key } from "./traits";
2
2
3 export interface IDestroyable {
3 export interface IDestroyable {
4 destroy(): void;
4 destroy(): void;
5 }
5 }
6
6
7 /**
7 /**
8 * @template S Карта доступных зависимостей
8 * @template S Карта доступных зависимостей
9 */
9 */
10 export interface Resolver<S extends object> {
10 export interface Resolver<S> {
11 /**
11 /**
12 * Функция для разрешения зависимостей, поддерживает создание фабричных методов,
12 * Функция для разрешения зависимостей, поддерживает создание фабричных методов,
13 * отложенную активацию и значение по-умолчанию для сервисов
13 * отложенную активацию и значение по-умолчанию для сервисов
14 * @template K Ключ сервиса из {@link S}
14 * @template K Ключ сервиса из {@link S}
15 * @template O Тип параметра {@link opts} используется для выведения типа
15 * @template O Тип параметра {@link opts} используется для выведения типа
16 * возвращаемого значения.
16 * возвращаемого значения.
17 * @param name Ключ сервиса, который будет разрешен.
17 * @param name Ключ сервиса, который будет разрешен.
18 * @param {boolean=} opts.lazy Признак того, что требуется отложенная активация,
18 * @param {boolean=} opts.lazy Признак того, что требуется отложенная активация,
19 * будет возвращен фабричный метод для получения зависимости. Если не указан,
19 * будет возвращен фабричный метод для получения зависимости. Если не указан,
20 * то считается `false`.
20 * то считается `false`.
21 * @param {any=} opts.default Значение по умолчанию, если в контейнере указанный
21 * @param {any=} opts.default Значение по умолчанию, если в контейнере указанный
22 * сервис не зарегистрирован
22 * сервис не зарегистрирован
23 * @returns Либо фабричный метод для получения зависимости, либо значение зависимости
23 * @returns Либо фабричный метод для получения зависимости, либо значение зависимости
24 * @throws Error Если зависимость не найдена и не предоставлено значение по-умолчанию
24 * @throws Error Если зависимость не найдена и не предоставлено значение по-умолчанию
25 */
25 */
26 <K extends keyof S, O extends { lazy: true; default?: unknown }>(name: K, opts?: O): () => (O extends { default: infer T } ? T : never) | NonNullable<S[K]>;
26 <K extends keyof S, O extends { lazy: true; default?: unknown }>(name: K, opts?: O): () => (O extends { default: infer T } ? T : never) | NonNullable<S[K]>;
27 <K extends keyof S, O extends { lazy?: false; default?: unknown }>(name: K, opts?: O): (O extends { default: infer T } ? T : never) | NonNullable<S[K]>;
27 <K extends keyof S, O extends { lazy?: false; default?: unknown }>(name: K, opts?: O): (O extends { default: infer T } ? T : never) | NonNullable<S[K]>;
28 }
28 }
29
29
30 export type DepsMap<S extends object> = {
30 export type DepsMap<S> = {
31 [k in key]: Refs<S>
31 [k in key]: Refs<S> | keyof S;
32 };
32 };
33
33
34 export type Refs<S extends object> = {
34 export type Refs<S> = {
35 [k in keyof S]: Ref<k, boolean, S[k]>;
35 [k in keyof S]: Ref<k, boolean, S[k]>;
36 }[keyof S] | keyof S;
36 }[keyof S];
37
37
38 export type Ref<K extends key, L extends boolean, D> = { name: K, lazy?: L, default?: D | null };
38 export type Ref<K extends key, L extends boolean, D> = { name: K, lazy?: L, default?: D | null };
39
39
40 export type Lazy<T, L extends boolean> = L extends true ? () => T : T;
40 export type Lazy<T, L extends boolean> = L extends true ? () => T : T;
41
41
42 export type InferDefault<T> = T extends { default: infer D } ? D : never;
42 export type InferDefault<T> = T extends { default: infer D } ? D : never;
43
43
44 export type Resolve<S extends object, R> =
44 export type Resolve<S, R> =
45 R extends keyof S ? NonNullable<S[R]> :
45 R extends keyof S ? NonNullable<S[R]> :
46 R extends Ref<infer K, infer L, unknown> ?
46 R extends Ref<infer K, infer L, unknown> ?
47 K extends keyof S ? Lazy<NonNullable<S[K]> | InferDefault<R>, L> :
47 K extends keyof S ? Lazy<NonNullable<S[K]> | InferDefault<R>, L> :
48 never:
48 never :
49 never;
49 never;
50
50
51 export interface IDescriptorBuilder<S extends object, T, R extends object, O extends keyof S> {
51 /**
52 * Интерфейс для конфигурирования сервиса в контейнере
53 */
54 export interface IDescriptorBuilder<S, T, R, O extends keyof S> {
52
55
53 /**
56 /** Указывает фабрика для создания экземпляра сервиса, фабрика передается
57 * в виде параметра. При вызове фабрике будет передан объект с зависимостями,
58 * которые были предварительно указаны вызовами метода `wants(...)`
54 *
59 *
55 * @param f
60 * Вызов данного метода завершает конфигурирование сервиса.
61 *
62 * @param f Фабрика для создания экземпляра сервиса
56 */
63 */
57 factory(f: (refs: R) => T): void;
64 factory(f: (refs: R) => T): void;
58
65
66 /**
67 * Используется для указания зависимостей, которые потребуются фабричному
68 * методу при создании нового экземпляра сервиса. Данный метод может быть
69 * вызван несколько раз подряд, при этом вызовы этого метода имеют
70 * кумулятивный эффект.
71 *
72 * @template X Тип объекта с зависимостями, которые требуется получить при
73 * создании экземпляра фабрики при помощи фабричного метода.
74 * @param refs Объект с описанием зависимостей
75 * @returns Возвращает дескриптор сервиса, в котором указаны необходимые
76 * зависимости
77 */
59 wants<X extends DepsMap<S> & Record<keyof R & keyof X, never>>(refs: X):
78 wants<X extends DepsMap<S> & Record<keyof R & keyof X, never>>(refs: X):
60 IDescriptorBuilder<S, T, R & {
79 IDescriptorBuilder<S, T, R & {
61 [k in keyof X]: Resolve<S, X[k]>;
80 [k in keyof X]: Resolve<S, X[k]>;
62 }, O>
81 }, O>
63
82
64 override<K extends O>(name: K, builder: RegistrationBuilder<S, NonNullable<S[K]>>): this;
83 override<K extends O>(name: K, builder: RegistrationBuilder<S, NonNullable<S[K]>>): this;
65 override<K extends O>(services: { [name in K]: RegistrationBuilder<S, NonNullable<S[K]>> }): this;
84 override<K extends O>(services: { [name in K]: RegistrationBuilder<S, NonNullable<S[K]>> }): this;
66
85
67 lifetime(lifetime: "singleton", typeId: string | number | object): this;
86 lifetime(lifetime: "singleton", typeId: string | number | object): this;
68 lifetime(lifetime: ILifetime<T> | Exclude<ActivationType, "singleton">): this;
87 lifetime(lifetime: ILifetime<T> | Exclude<ActivationType, "singleton">): this;
69
88
89 /** Указывает функцию для освобождения экземпляра сервиса для случаев, когда
90 * время жизни привязано к контейнеру.
91 */
70 cleanup(cb: (item: T) => void): this;
92 cleanup(cb: (item: T) => void): this;
71
93
94 /**
95 * Регистрирует в контейнере постоянное значение в качестве реализации сервиса.
96 *
97 * @param v Экземпляр реализации сервиса.
98 */
72 value(v: T): void;
99 value(v: T): void;
73 }
100 }
74
101
75 export type RegistrationBuilder<S extends object, T> = (d: IDescriptorBuilder<S, T, object, ConfigurableKeys<S>>) => void;
102 export type RegistrationBuilder<S, T> = (d: IDescriptorBuilder<S, T, object, ConfigurableKeys<S>>) => void;
76
103
77 export type RegistrationBuildersMap<S extends Configurable<S>, K extends keyof S = keyof S> = {
104 export type RegistrationBuildersMap<S extends Configurable<S>, K extends keyof S = keyof S> = {
78 [k in K]-?: RegistrationBuilder<ContainerServices<S>, NonNullable<S[k]>>
105 [k in K]-?: RegistrationBuilder<ContainerServices<S>, NonNullable<S[k]>>
79 };
106 };
80
107
81 export interface Descriptor<S extends object, T> {
108 export interface Descriptor<S, T> {
82 activate(context: IActivationContext<S>): T;
109 activate(context: IActivationContext<S>): T;
83 }
110 }
84
111
85 export interface IActivationContext<S extends object> extends ServiceLocator<S> {
112 export interface IActivationContext<S> extends ServiceLocator<S> {
86 createLifetime<T>(): ILifetime<T>;
113 createLifetime<T>(): ILifetime<T>;
87
114
88 createContainerLifetime<T>(): ILifetime<T>;
115 createContainerLifetime<T>(): ILifetime<T>;
89 }
116 }
90
117
91 export type RegistrationMap<S extends object, K extends keyof S = keyof S> = {
118 export type RegistrationMap<S, K extends keyof S = keyof S> = {
92 [k in K]-?: Descriptor<S, S[k]>;
119 [k in K]-?: Descriptor<S, S[k]>;
93 };
120 };
94
121
95 export interface ContainerProvided<S extends Configurable<S>> {
122 export interface ContainerProvided<S> {
96 container: ServiceLocator<ContainerServices<S>>;
123 container: ServiceLocator<ContainerServices<S>>;
97
124
98 childContainer: IContainerBuilder<S>;
125 childContainer: IContainerBuilder<S>;
99 }
126 }
100
127
101 export type Configurable<S> = { [k in keyof S & (keyof ContainerProvided<never>)]: never; };
128 export type Configurable<S> = { [k in keyof S]: k extends ProvidedKeys ? never : S[k]; };
102
129
103 export type ProvidedKeys = keyof ContainerProvided<never>;
130 export type ProvidedKeys = keyof ContainerProvided<never>;
104
131
105 export type ContainerServices<S extends Configurable<S>> = S & ContainerProvided<S>;
132 export type ContainerServices<S> =
133 { [k in keyof S as k extends ProvidedKeys ? never: k]: S[k] } &
134 ContainerProvided<S>;
106
135
107 export type ConfigurableKeys<S extends object> = Exclude<keyof S, ProvidedKeys>;
136 export type ConfigurableKeys<S> = Exclude<keyof S, ProvidedKeys>;
108
137
109 export type ConfigurableServices<S extends object> = Pick<S, ConfigurableKeys<S>>;
138 export type ConfigurableServices<S> = Pick<S, ConfigurableKeys<S>>;
110
139
111 export type ContainerKeys<S extends Configurable<S>> = keyof S | keyof ContainerProvided<never>;
140 export type ContainerKeys<S> = keyof S | ProvidedKeys;
112
141
113 export interface ServiceLocator<S extends object> {
142 export interface ServiceLocator<S> {
114 resolve<K extends keyof S>(name: K): NonNullable<S[K]>;
143 resolve<K extends keyof S>(name: K): NonNullable<S[K]>;
115 resolve<K extends keyof S, T>(name: K, def: T): NonNullable<S[K]> | T;
144 resolve<K extends keyof S, T>(name: K, def: T): NonNullable<S[K]> | T;
116 }
145 }
117
146
118 export interface LifetimeContainer {
147 export interface LifetimeContainer {
119 createLifetime<T>(): ILifetime<T>;
148 createLifetime<T>(): ILifetime<T>;
120 }
149 }
121
150
122 export interface ServiceContainer<S extends Configurable<S>> extends
151 export interface ServiceContainer<S> extends
123 ServiceLocator<ContainerServices<S>>,
152 ServiceLocator<ContainerServices<S>>,
124 IDestroyable {
153 IDestroyable {
125
154
126 createChildContainer(): IContainerBuilder<S>;
155 createChildContainer(): IContainerBuilder<S>;
127 }
156 }
128
157
129 export interface IContainerBuilder<S extends Configurable<S>> {
158 export interface IContainerBuilder<S> {
130 createServiceBuilder<K extends keyof S>(name: K): IDescriptorBuilder<S, NonNullable<S[K]>, object, keyof S>;
159 createServiceBuilder<K extends keyof S>(name: K): IDescriptorBuilder<S, NonNullable<S[K]>, object, keyof S>;
131
160
132 build(): ServiceContainer<S>;
161 build(): ServiceContainer<S>;
133 }
162 }
134
163
135
164
136 export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call";
165 export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call";
137
166
138 /**
167 /**
139 * Интерфейс для управления жизнью экземпляра объекта. Каждая регистрация имеет
168 * Интерфейс для управления жизнью экземпляра объекта. Каждая регистрация имеет
140 * свой собственный объект `ILifetime`, который создается при первой активации
169 * свой собственный объект `ILifetime`, который создается при первой активации
141 */
170 */
142 export interface ILifetime<T> {
171 export interface ILifetime<T> {
143 /** Проверяет, что уже создан экземпляр объекта */
172 /** Проверяет, что уже создан экземпляр объекта */
144 has(): boolean;
173 has(): boolean;
145
174
146 get(): T;
175 get(): T;
147
176
148 initialize(context: IActivationContext<object>): void;
177 initialize(context: IActivationContext<object>): void;
149
178
150 store(item: T, cleanup?: (item: T) => void): void;
179 store(item: T, cleanup?: (item: T) => void): void;
151 }
180 }
152
181
153 export type ExtractRequired<T, K extends keyof T = keyof T> = { [p in K as (undefined extends T[p] ? never : p)]-?: T[p] };
182 export type ExtractRequired<T, K extends keyof T = keyof T> = { [p in K as (undefined extends T[p] ? never : p)]-?: T[p] };
154
183
@@ -1,49 +1,49
1 import { FluentConfiguration } from "./FluentConfiguration";
1 import { FluentConfiguration } from "./FluentConfiguration";
2 import { IDestroyable } from "./interfaces";
2 import { IDestroyable } from "./interfaces";
3
3
4 export function fluent<S extends object = object>() {
4 export function fluent<S = {}>() {
5 return new FluentConfiguration<S>();
5 return new FluentConfiguration<S>();
6 }
6 }
7
7
8 export type key = string | number | symbol;
8 export type key = string | number | symbol;
9
9
10 export const isKey = (v: unknown): v is key =>
10 export const isKey = (v: unknown): v is key =>
11 typeof v === "string" || typeof v === "number" || typeof v === "symbol";
11 typeof v === "string" || typeof v === "number" || typeof v === "symbol";
12
12
13 export const isString = (v: unknown): v is string =>
13 export const isString = (v: unknown): v is string =>
14 typeof v === "string";
14 typeof v === "string";
15
15
16
16
17 export const isNotNull = <T>(v: T): v is NonNullable<T> => v !== null && v !== undefined;
17 export const isNotNull = <T>(v: T): v is NonNullable<T> => v !== null && v !== undefined;
18
18
19 export const each = <T extends object>(obj: T, cb: <X extends Extract<keyof T, string>>(v: NonNullable<T[X]>, k: X) => void) =>
19 export const each = <T extends object>(obj: T, cb: <X extends Extract<keyof T, string>>(v: NonNullable<T[X]>, k: X) => void) =>
20 (Object.keys(obj) as (Extract<keyof T, string>)[])
20 (Object.keys(obj) as (Extract<keyof T, string>)[])
21 .forEach(k => {
21 .forEach(k => {
22 const v = obj[k];
22 const v = obj[k];
23 isNotNull(v) && cb(v, k);
23 isNotNull(v) && cb(v, k);
24 });
24 });
25
25
26 export const argumentNotNull = (arg: unknown, name: string) => {
26 export const argumentNotNull = (arg: unknown, name: string) => {
27 if (arg === null || arg === undefined)
27 if (arg === null || arg === undefined)
28 throw new Error("The argument " + name + " can't be null or undefined");
28 throw new Error("The argument " + name + " can't be null or undefined");
29 };
29 };
30
30
31 export const isPromise = <T = unknown>(val: unknown): val is PromiseLike<T> =>
31 export const isPromise = <T = unknown>(val: unknown): val is PromiseLike<T> =>
32 isNotNull(val) && typeof (val as PromiseLike<T>).then === "function";
32 isNotNull(val) && typeof (val as PromiseLike<T>).then === "function";
33
33
34 export const isDestroyable = (d: unknown): d is IDestroyable =>
34 export const isDestroyable = (d: unknown): d is IDestroyable =>
35 isNotNull(d) && typeof (d as IDestroyable).destroy === "function";
35 isNotNull(d) && typeof (d as IDestroyable).destroy === "function";
36
36
37 let _nextOid = 0;
37 let _nextOid = 0;
38 const _oid = typeof Symbol === "function" ?
38 const _oid = typeof Symbol === "function" ?
39 Symbol.for("__implab__oid__") :
39 Symbol.for("__implab__oid__") :
40 "__implab__oid__";
40 "__implab__oid__";
41
41
42 type OidSlot = { [k in typeof _oid]?: string };
42 type OidSlot = { [k in typeof _oid]?: string };
43
43
44 export const oid = <T extends object>(instance: T): string => {
44 export const oid = <T extends object>(instance: T): string => {
45 argumentNotNull(instance, "instance");
45 argumentNotNull(instance, "instance");
46 const val = (instance as OidSlot)[_oid];
46 const val = (instance as OidSlot)[_oid];
47
47
48 return val ? val : ((instance as OidSlot)[_oid] = `oid_${++_nextOid}`);
48 return val ? val : ((instance as OidSlot)[_oid] = `oid_${++_nextOid}`);
49 }; No newline at end of file
49 };
@@ -1,87 +1,100
1 /* eslint max-classes-per-file: ["error", 20] */
1 /* eslint max-classes-per-file: ["error", 20] */
2 import { describe, it } from "mocha";
2 import { describe, it } from "mocha";
3 import { Container } from "../Container";
3 import { Container } from "../Container";
4 import { ContainerServices, DepsMap, Refs, Resolver } from "../interfaces";
4 import { ContainerBuilder } from "../ContainerBuilder";
5 import { ConfigurableKeys, ContainerProvided, ContainerServices, DepsMap, Refs, Resolver } from "../interfaces";
5 import { fluent } from "../traits";
6 import { fluent } from "../traits";
6
7
7 class Foo {
8 class Foo {
8 foo = "foo";
9 foo = "foo";
9 }
10 }
10
11
11 class Bar {
12 class Bar {
12 bar = "bar";
13 bar = "bar";
13
14
14 constructor(foo?: () => Foo) { }
15 constructor(foo?: () => Foo) { }
15 }
16 }
16
17
17 interface Services {
18 interface Services {
18 foo: Foo;
19 foo: Foo;
19
20
20 bar?: Bar;
21 bar?: Bar;
21
22
22 baz: Foo;
23 baz: Foo;
24
25 container: string;
23 }
26 }
24
27
25 interface ServicesB {
28 interface ServicesB {
26 // will give errors
29 // will give errors
27 // baz: Bar;
30 // baz: Bar;
28
31
29 baz: Foo;
32 baz: Foo;
30
33
31 zoo?: Foo;
34 zoo?: Foo;
32 }
35 }
33
36
34 declare const resolver: Resolver<Services>;
37 declare const resolver: Resolver<Services>;
35
38
36 const foo = resolver("foo", {lazy: true});
39 const foo = resolver("foo", {lazy: true});
37
40
38 const mmap = <X extends DepsMap<Services, string>>(m: X) => {};
41 const mmap = <X extends DepsMap<Services>>(m: X) => {};
42
43 declare const refs: Refs<Services>;
39
44
40 const refs: Refs<Services> = {name: "bar", default: undefined};
45 if (refs && refs.name === "foo") {
46 refs.default;
47 }
48
49 declare const x: ContainerServices<Services>;
50
51 x.container.resolve("container");
52
41
53
42 mmap({
54 mmap({
43 fooz: {name: "foo", lazy: false, default: undefined },
55 fooz: {name: "foo", lazy: false, default: undefined },
44 ooz: "bar"
56 ooz: "bar"
45 });
57 });
46
58
47 interface SharedServices {
59 interface SharedServices {
48 foo: Foo;
60 foo: Foo;
49
61
50 bar?: Bar;
62 bar?: Bar;
51
63
52 baz: Bar;
64 baz: Bar;
53 }
65 }
54
66
55 const config = fluent()
67 const config = fluent()
56 .declare<Services>()
68 .declare<Services>()
57 .declare<ServicesB>()
69 .declare<ServicesB>()
58 .register({
70 .register({
71 zoo: it => {},
59 bar: it => it
72 bar: it => it
60 .lifetime("context") // тип активации, время жизни
73 .lifetime("context") // тип активации, время жизни
61 .wants({
74 .wants({
62 zoo: "zoo", // зависимость
75 zoo: "zoo", // зависимость
63 bar: "bar",
76 bar: "bar",
64
77
65 $zoo: { name: "foo", lazy: true, } // отложенная активация,
78 $zoo: { name: "foo", lazy: true, } // отложенная активация,
66 //фабричный метод
79 //фабричный метод
67 })
80 })
68 .wants({
81 .wants({
69 zoom: "bar"
82 zoom: "bar"
70 })
83 })
71 .factory(({ $zoo, zoo }) => // фабрика получает объект с именованными зависимостями
84 .factory(({ $zoo, zoo }) => // фабрика получает объект с именованными зависимостями
72 // удобно для деструктурирования
85 // удобно для деструктурирования
73 new Bar($zoo) // создается экземпляр сервиса
86 new Bar($zoo) // создается экземпляр сервиса
74 ),
87 ),
75 foo: it => it.factory(() => new Foo()),
88 foo: it => it.factory(() => new Foo()),
76 baz: it => it.value(new Foo())
89 baz: it => it.value(new Foo())
77 })
90 })
78 .done({});
91 .done({});
79
92
80 declare const container: Container<object>;
93 declare const container: ContainerBuilder<{}>;
81 const c2 = config.configure(container);
94 const c2 = config.configure(container);
82
95
83 c2.resolve("foo");
96 c2.resolve("foo");
84
97
85 declare const m :ContainerServices<{foo: Foo}>["container"];
98 declare const m :ContainerServices<{foo: Foo}>["container"];
86
99
87 m.resolve("container").resolve("container"); No newline at end of file
100 m.resolve("container").resolve("container").resolve("foo"); No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now