##// END OF EJS Templates
Corrected method signatures
cin -
r6:5683fe88e2a5 default
parent child
Show More
@@ -1,46 +1,46
1 import { Container } from "./Container";
1 import { Container } from "./Container";
2 import { DescriptorBuilder } from "./DescriptorBuilder";
2 import { DescriptorBuilder } from "./DescriptorBuilder";
3 import { Configurable, ConfigurableKeys, ContainerServices, Descriptor, IContainerBuilder, IDescriptorBuilder, RegistrationMap, ServiceContainer } from "./interfaces";
3 import { Configurable, ConfigurableKeys, ContainerServices, Descriptor, IContainerBuilder, IDescriptorBuilder, RegistrationMap, ServiceContainer } from "./interfaces";
4 import { LifetimeManager } from "./LifetimeManager";
4 import { LifetimeManager } from "./LifetimeManager";
5
5
6 export class ContainerBuilder<S extends Configurable<S>> implements IContainerBuilder<S>{
6 export class ContainerBuilder<S extends Configurable<S>> implements IContainerBuilder<S>{
7
7
8 private _pending = 1;
8 private _pending = 1;
9
9
10 private readonly _services: Partial<RegistrationMap<ContainerServices<S>>>;
10 private readonly _services: Partial<RegistrationMap<ContainerServices<S>>>;
11
11
12 private readonly _lifetimeManager = new LifetimeManager();
12 private readonly _lifetimeManager = new LifetimeManager();
13
13
14 constructor(parentServices?: object) {
14 constructor(parentServices?: object) {
15 this._services = Object.create(parentServices ? parentServices : null) as object;
15 this._services = Object.create(parentServices ? parentServices : null) as object;
16 }
16 }
17
17
18 createServiceBuilder<K extends keyof S>(name: K): IDescriptorBuilder<S, NonNullable<S[K]>, object> {
18 createServiceBuilder<K extends keyof S>(name: K): IDescriptorBuilder<ContainerServices<S>, NonNullable<S[K]>, object, keyof S> {
19 return new DescriptorBuilder(this._lifetimeManager, this._register(name), this._fail);
19 return new DescriptorBuilder(this._lifetimeManager, this._register(name), this._fail);
20 }
20 }
21
21
22 build(): ServiceContainer<S> {
22 build(): ServiceContainer<S> {
23 this._assertBuilding();
23 this._assertBuilding();
24 if(!this._complete())
24 if(!this._complete())
25 throw new Error("The configuration didn't complete.");
25 throw new Error("The configuration didn't complete.");
26 return new Container(this._services, this._lifetimeManager);
26 return new Container(this._services, this._lifetimeManager);
27 }
27 }
28
28
29 private readonly _register = <K extends ConfigurableKeys<S>>(name: K) => (descriptor: Descriptor<S, NonNullable<S[K]>>) => {
29 private readonly _register = <K extends ConfigurableKeys<S>>(name: K) => (descriptor: Descriptor<S, NonNullable<S[K]>>) => {
30 this._complete();
30 this._complete();
31 this._services[name] = descriptor;
31 this._services[name] = descriptor;
32 };
32 };
33
33
34 private readonly _fail = (ex: unknown) => {
34 private readonly _fail = (ex: unknown) => {
35
35
36 };
36 };
37
37
38 private _assertBuilding() {
38 private _assertBuilding() {
39 throw new Error("The descriptor builder is finalized");
39 throw new Error("The descriptor builder is finalized");
40 }
40 }
41
41
42 private _complete() {
42 private _complete() {
43 return !(--this._pending);
43 return !(--this._pending);
44 }
44 }
45
45
46 } No newline at end of file
46 }
@@ -1,189 +1,189
1 import { RegistrationBuilder, LifetimeContainer, ConfigurableKeys, IDescriptorBuilder, Ref, Resolved, DepsMap } from "./interfaces";
1 import { RegistrationBuilder, LifetimeContainer, ConfigurableKeys, IDescriptorBuilder, Ref, Resolved, DepsMap } from "./interfaces";
2 import { Descriptor, ILifetime, ActivationType } from "./interfaces";
2 import { Descriptor, ILifetime, ActivationType } from "./interfaces";
3 import { DescriptorImpl, RegistrationOverridesMap } from "./DescriptorImpl";
3 import { DescriptorImpl, RegistrationOverridesMap } from "./DescriptorImpl";
4 import { LifetimeManager } from "./LifetimeManager";
4 import { LifetimeManager } from "./LifetimeManager";
5 import { each, isKey, isPromise, isString, key, oid } from "./traits";
5 import { each, isKey, isPromise, isString, key, oid } from "./traits";
6
6
7 /**
7 /**
8 * @template {S} Карта доступных зависимостей, как правило `ContainerServices`
8 * @template {S} Карта доступных зависимостей, как правило `ContainerServices`
9 * @template {T} Тип сервиса
9 * @template {T} Тип сервиса
10 */
10 */
11 export class DescriptorBuilder<S extends object, T, R extends object = object> implements IDescriptorBuilder<S, T, R> {
11 export class DescriptorBuilder<S extends object, T, R extends object, O extends keyof S> implements IDescriptorBuilder<S, T, R, O> {
12 private readonly _lifetimeManager: LifetimeManager;
12 private readonly _lifetimeManager: LifetimeManager;
13 private readonly _cb: (d: Descriptor<S, T>) => void;
13 private readonly _cb: (d: Descriptor<S, T>) => void;
14
14
15 private readonly _eb: (err: unknown) => void;
15 private readonly _eb: (err: unknown) => void;
16
16
17 private readonly _refs: DepsMap<key, keyof S>;
17 private readonly _refs: DepsMap<key, keyof S>;
18
18
19 private _lifetime = LifetimeManager.empty<T>();
19 private _lifetime = LifetimeManager.empty<T>();
20
20
21 private _overrides: RegistrationOverridesMap<S>;
21 private _overrides: RegistrationOverridesMap<S>;
22
22
23 private _cleanup?: (item: T) => void;
23 private _cleanup?: (item: T) => void;
24
24
25 private _factory?: (refs: R) => T;
25 private _factory?: (refs: R) => T;
26
26
27 private _pending = 1;
27 private _pending = 1;
28
28
29 private _failed = false;
29 private _failed = false;
30
30
31 private _finalized = false;
31 private _finalized = false;
32
32
33 /**
33 /**
34 * Creates new DescriptorBuilder. Accepts a lifetime container for resolving "container"
34 * Creates new DescriptorBuilder. Accepts a lifetime container for resolving "container"
35 * lifetime.
35 * lifetime.
36 *
36 *
37 * @param lifetimeManager The lifetime container is the container where the service is to be registered.
37 * @param lifetimeManager The lifetime container is the container where the service is to be registered.
38 * @param cb The callback to receive the built service descriptor
38 * @param cb The callback to receive the built service descriptor
39 * @param eb The callback to receive the error due
39 * @param eb The callback to receive the error due
40 */
40 */
41 constructor(lifetimeManager: LifetimeManager, cb: (d: Descriptor<S, T>) => void, eb: (err: unknown) => void) {
41 constructor(lifetimeManager: LifetimeManager, cb: (d: Descriptor<S, T>) => void, eb: (err: unknown) => void) {
42 this._lifetimeManager = lifetimeManager;
42 this._lifetimeManager = lifetimeManager;
43 this._cb = cb;
43 this._cb = cb;
44 this._eb = eb;
44 this._eb = eb;
45 this._overrides = {};
45 this._overrides = {};
46 this._refs = {};
46 this._refs = {};
47 }
47 }
48 wants<X extends { [k in Exclude<key, keyof R>]: keyof S | Ref<keyof S, boolean, unknown>; }>(refs: X):
48 wants<X extends { [k in Exclude<key, keyof R>]: keyof S | Ref<keyof S, boolean, unknown>; }>(refs: X):
49 IDescriptorBuilder<S, T, R & {
49 IDescriptorBuilder<S, T, R & {
50 [k in keyof X]:
50 [k in keyof X]:
51 X[k] extends keyof S ? NonNullable<S[X[k]]> :
51 X[k] extends keyof S ? NonNullable<S[X[k]]> :
52 X[k] extends Ref<infer K, infer L, infer D> ? Resolved<S, K & keyof S, L, D> :
52 X[k] extends Ref<infer K, infer L, infer D> ? Resolved<S, K & keyof S, L, D> :
53 never;
53 never;
54 }> {
54 }, O> {
55
55
56 each(refs, (v, k) => this._refs[k] = v);
56 each(refs, (v, k) => this._refs[k] = v);
57
57
58 return this as IDescriptorBuilder<S, T, R & {
58 return this as IDescriptorBuilder<S, T, R & {
59 [k in keyof X]:
59 [k in keyof X]:
60 X[k] extends keyof S ? NonNullable<S[X[k]]> :
60 X[k] extends keyof S ? NonNullable<S[X[k]]> :
61 X[k] extends Ref<infer K, infer L, infer D> ? Resolved<S, K & keyof S, L, D> :
61 X[k] extends Ref<infer K, infer L, infer D> ? Resolved<S, K & keyof S, L, D> :
62 never;
62 never;
63 }>;
63 }, O>;
64 }
64 }
65 factory(f: (refs: R) => T): void {
65 factory(f: (refs: R) => T): void {
66 this._assertBuilding();
66 this._assertBuilding();
67 this._factory = f;
67 this._factory = f;
68 this._finalize();
68 this._finalize();
69 this._complete();
69 this._complete();
70 }
70 }
71
71
72
72
73 private _assertBuilding() {
73 private _assertBuilding() {
74 if (this._finalized)
74 if (this._finalized)
75 throw new Error("The descriptor builder is finalized");
75 throw new Error("The descriptor builder is finalized");
76 }
76 }
77
77
78 private _finalize() {
78 private _finalize() {
79 this._finalized = true;
79 this._finalized = true;
80 }
80 }
81
81
82 override<K extends ConfigurableKeys<S>>(name: K, builder: RegistrationBuilder<S, NonNullable<S[K]>>): this;
82 override<K extends O>(name: K, builder: RegistrationBuilder<S, NonNullable<S[K]>>): this;
83 override<K extends ConfigurableKeys<S>>(services: { [k in K]: RegistrationBuilder<S, NonNullable<S[k]>> }): this;
83 override<K extends O>(services: { [k in K]: RegistrationBuilder<S, NonNullable<S[k]>> }): this;
84 override<K extends ConfigurableKeys<S>>(nameOrServices: K | { [name in K]: RegistrationBuilder<S, NonNullable<S[K]>> }, builder?: RegistrationBuilder<S, NonNullable<S[K]>>): this {
84 override<K extends O>(nameOrServices: K | { [name in K]: RegistrationBuilder<S, NonNullable<S[K]>> }, builder?: RegistrationBuilder<S, NonNullable<S[K]>>): this {
85 this._assertBuilding();
85 this._assertBuilding();
86 const guard = (v: void | Promise<void>) => {
86 const guard = (v: void | Promise<void>) => {
87 if (isPromise(v))
87 if (isPromise(v))
88 v.catch(err => this._fail(err));
88 v.catch(err => this._fail(err));
89 };
89 };
90
90
91 if (isKey(nameOrServices)) {
91 if (isKey(nameOrServices)) {
92 if (builder) {
92 if (builder) {
93 this._defer();
93 this._defer();
94 const d = new DescriptorBuilder<S, NonNullable<S[K]>>(
94 const d = new DescriptorBuilder<S, NonNullable<S[K]>, object, O>(
95 this._lifetimeManager,
95 this._lifetimeManager,
96 result => {
96 result => {
97 this._overrides[nameOrServices] = result;
97 this._overrides[nameOrServices] = result;
98 this._complete();
98 this._complete();
99 },
99 },
100 err => this._fail(err)
100 err => this._fail(err)
101 );
101 );
102
102
103 try {
103 try {
104 guard(builder(d));
104 guard(builder(d));
105 } catch (err) {
105 } catch (err) {
106 this._fail(err);
106 this._fail(err);
107 }
107 }
108 }
108 }
109 } else {
109 } else {
110 each(nameOrServices, (v, k) => this.override(k, v));
110 each(nameOrServices, (v, k) => this.override(k, v));
111 }
111 }
112 return this;
112 return this;
113 }
113 }
114
114
115 lifetime(lifetime: "singleton", typeId: string): this;
115 lifetime(lifetime: "singleton", typeId: string): this;
116 lifetime(lifetime: ILifetime<T> | Exclude<ActivationType, "singleton">): this;
116 lifetime(lifetime: ILifetime<T> | Exclude<ActivationType, "singleton">): this;
117 lifetime(lifetime: ILifetime<T> | ActivationType, typeId?: string): this {
117 lifetime(lifetime: ILifetime<T> | ActivationType, typeId?: string): this {
118 this._assertBuilding();
118 this._assertBuilding();
119 if (isString(lifetime)) {
119 if (isString(lifetime)) {
120 this._lifetime = this._resolveLifetime(lifetime, typeId);
120 this._lifetime = this._resolveLifetime(lifetime, typeId);
121 } else {
121 } else {
122 this._lifetime = lifetime;
122 this._lifetime = lifetime;
123 }
123 }
124 return this;
124 return this;
125 }
125 }
126
126
127 cleanup(cb: (item: T) => void): this {
127 cleanup(cb: (item: T) => void): this {
128 this._assertBuilding();
128 this._assertBuilding();
129 this._cleanup = cb;
129 this._cleanup = cb;
130 return this;
130 return this;
131 }
131 }
132
132
133 value(v: T): void {
133 value(v: T): void {
134 this._assertBuilding();
134 this._assertBuilding();
135 this._cb({
135 this._cb({
136 activate() {
136 activate() {
137 return v;
137 return v;
138 }
138 }
139 });
139 });
140 this._finalize();
140 this._finalize();
141 }
141 }
142
142
143 _resolveLifetime<T>(activation: ActivationType, typeId?: string | object): ILifetime<T> {
143 _resolveLifetime<T>(activation: ActivationType, typeId?: string | object): ILifetime<T> {
144 switch (activation) {
144 switch (activation) {
145 case "container":
145 case "container":
146 return this._lifetimeManager.create();
146 return this._lifetimeManager.create();
147 case "hierarchy":
147 case "hierarchy":
148 return LifetimeManager.hierarchyLifetime();
148 return LifetimeManager.hierarchyLifetime();
149 case "context":
149 case "context":
150 return LifetimeManager.contextLifetime();
150 return LifetimeManager.contextLifetime();
151 case "singleton": {
151 case "singleton": {
152 if (!typeId)
152 if (!typeId)
153 throw Error("The singleton activation requires a typeId");
153 throw Error("The singleton activation requires a typeId");
154
154
155 const _oid = isString(typeId) ? typeId : oid(typeId);
155 const _oid = isString(typeId) ? typeId : oid(typeId);
156
156
157 return LifetimeManager.singletonLifetime(_oid);
157 return LifetimeManager.singletonLifetime(_oid);
158 }
158 }
159 default:
159 default:
160 return LifetimeManager.empty();
160 return LifetimeManager.empty();
161 }
161 }
162 }
162 }
163
163
164 _defer() {
164 _defer() {
165 this._pending++;
165 this._pending++;
166 }
166 }
167
167
168 _complete() {
168 _complete() {
169 if (--this._pending === 0) {
169 if (--this._pending === 0) {
170 if (!this._factory)
170 if (!this._factory)
171 throw new Error("The factory must be specified");
171 throw new Error("The factory must be specified");
172
172
173 this._cb(new DescriptorImpl<S, T>({
173 this._cb(new DescriptorImpl<S, T>({
174 lifetime: this._lifetime,
174 lifetime: this._lifetime,
175 factory: this._factory,
175 factory: this._factory,
176 overrides: this._overrides,
176 overrides: this._overrides,
177 cleanup: this._cleanup
177 cleanup: this._cleanup
178 }));
178 }));
179 }
179 }
180 }
180 }
181
181
182 _fail(err: unknown) {
182 _fail(err: unknown) {
183 if (!this._failed) {
183 if (!this._failed) {
184 this._failed = true;
184 this._failed = true;
185 this._eb.call(undefined, err);
185 this._eb.call(undefined, err);
186 }
186 }
187 }
187 }
188
188
189 }
189 }
@@ -1,83 +1,82
1 import { Descriptor, ILifetime, ConfigurableKeys, DepsMap, Ref, IActivationContext } from "./interfaces";
1 import { Descriptor, ILifetime, DepsMap, Ref, IActivationContext } from "./interfaces";
2 import { ActivationContext } from "./ActivationContext";
3 import { each, isKey, key } from "./traits";
2 import { each, isKey, key } from "./traits";
4
3
5 export type RegistrationOverridesMap<S extends object> = { [k in ConfigurableKeys<S>]?: Descriptor<S, NonNullable<S[k]>> };
4 export type RegistrationOverridesMap<S extends object> = { [k in keyof S]?: Descriptor<S, NonNullable<S[k]>> };
6
5
7 export interface DescriptorImplArgs<S extends object, T> {
6 export interface DescriptorImplArgs<S extends object, T> {
8 lifetime: ILifetime<T>;
7 lifetime: ILifetime<T>;
9
8
10 factory: (refs: Record<key, never>) => T;
9 factory: (refs: Record<key, never>) => T;
11
10
12 cleanup?: (item: T) => void;
11 cleanup?: (item: T) => void;
13
12
14 overrides?: RegistrationOverridesMap<S>;
13 overrides?: RegistrationOverridesMap<S>;
15
14
16 dependencies?: DepsMap<key, keyof S>;
15 dependencies?: DepsMap<key, keyof S>;
17 }
16 }
18
17
19
18
20 export class DescriptorImpl<S extends object, T> implements Descriptor<S, T> {
19 export class DescriptorImpl<S extends object, T> implements Descriptor<S, T> {
21
20
22 private readonly _overrides?: RegistrationOverridesMap<S>;
21 private readonly _overrides?: RegistrationOverridesMap<S>;
23
22
24 private readonly _lifetime: ILifetime<T>;
23 private readonly _lifetime: ILifetime<T>;
25
24
26 private readonly _factory: (refs: Record<key, never>) => T;
25 private readonly _factory: (refs: Record<key, never>) => T;
27
26
28 private readonly _cleanup?: (item: T) => void;
27 private readonly _cleanup?: (item: T) => void;
29
28
30 private readonly _deps?: DepsMap<key, keyof S>;
29 private readonly _deps?: DepsMap<key, keyof S>;
31
30
32 constructor({ lifetime, factory, cleanup, overrides, dependencies }: DescriptorImplArgs<S, T>) {
31 constructor({ lifetime, factory, cleanup, overrides, dependencies }: DescriptorImplArgs<S, T>) {
33 this._lifetime = lifetime;
32 this._lifetime = lifetime;
34 this._factory = factory;
33 this._factory = factory;
35 if (cleanup)
34 if (cleanup)
36 this._cleanup = cleanup;
35 this._cleanup = cleanup;
37 if (overrides)
36 if (overrides)
38 this._overrides = overrides;
37 this._overrides = overrides;
39 if (dependencies)
38 if (dependencies)
40 this._deps = dependencies;
39 this._deps = dependencies;
41 }
40 }
42
41
43 activate(context: IActivationContext<S>): T {
42 activate(context: IActivationContext<S>): T {
44
43
45 if (this._lifetime.has())
44 if (this._lifetime.has())
46 return this._lifetime.get();
45 return this._lifetime.get();
47
46
48 this._lifetime.initialize(context);
47 this._lifetime.initialize(context);
49
48
50 if (this._overrides)
49 if (this._overrides)
51 each(this._overrides, (v, k) => context.register(k, v));
50 each(this._overrides, (v, k) => context.register(k, v));
52
51
53 const resolve = <K extends keyof S, L extends boolean, D = never>({ name, lazy, ...opts }: Ref<K, L, D>) => {
52 const resolve = <K extends keyof S, L extends boolean, D = never>({ name, lazy, ...opts }: Ref<K, L, D>) => {
54 if (lazy) {
53 if (lazy) {
55 return () => "default" in opts ? context.resolve(name, opts.default) : context.resolve(name);
54 return () => "default" in opts ? context.resolve(name, opts.default) : context.resolve(name);
56 } else {
55 } else {
57 return "default" in opts ? context.resolve(name, opts.default) : context.resolve(name);
56 return "default" in opts ? context.resolve(name, opts.default) : context.resolve(name);
58 }
57 }
59 };
58 };
60
59
61 const makeRefs = (deps: typeof this._deps) => deps ?
60 const makeRefs = (deps: typeof this._deps) => deps ?
62 Object.keys(deps)
61 Object.keys(deps)
63 .map(k => {
62 .map(k => {
64 const ref = deps[k];
63 const ref = deps[k];
65 return isKey(ref) ?
64 return isKey(ref) ?
66 { [k]: resolve({ name: ref }) } :
65 { [k]: resolve({ name: ref }) } :
67 { [k]: resolve(ref) };
66 { [k]: resolve(ref) };
68 })
67 })
69 .reduce((a, p) => ({ ...a, ...p }), {} ) as Record<key, never>:
68 .reduce((a, p) => ({ ...a, ...p }), {} ) as Record<key, never>:
70 {} as Record<key, never>;
69 {} as Record<key, never>;
71
70
72 const instance = this._factory.call(undefined, makeRefs(this._deps));
71 const instance = this._factory.call(undefined, makeRefs(this._deps));
73
72
74 this._lifetime.store(instance, this._cleanup);
73 this._lifetime.store(instance, this._cleanup);
75
74
76 return instance;
75 return instance;
77 }
76 }
78
77
79
78
80 toString() {
79 toString() {
81 return `[object DescriptorImpl, lifetime=${String(this._lifetime)}]`;
80 return `[object DescriptorImpl, lifetime=${String(this._lifetime)}]`;
82 }
81 }
83 }
82 }
@@ -1,146 +1,143
1 import { ActivationContext } from "./ActivationContext";
2 import { key } from "./traits";
1 import { key } from "./traits";
3
2
4 export interface IDestroyable {
3 export interface IDestroyable {
5 destroy(): void;
4 destroy(): void;
6 }
5 }
7
6
8 /**
7 /**
9 * @template S Карта доступных зависимостей
8 * @template S Карта доступных зависимостей
10 */
9 */
11 export interface Resolver<S extends object> {
10 export interface Resolver<S extends object> {
12 /**
11 /**
13 * Функция для разрешения зависимостей, поддерживает создание фабричных методов,
12 * Функция для разрешения зависимостей, поддерживает создание фабричных методов,
14 * отложенную активацию и значение по-умолчанию для сервисов
13 * отложенную активацию и значение по-умолчанию для сервисов
15 * @template K Ключ сервиса из {@link S}
14 * @template K Ключ сервиса из {@link S}
16 * @template O Тип параметра {@link opts} используется для выведения типа
15 * @template O Тип параметра {@link opts} используется для выведения типа
17 * возвращаемого значения.
16 * возвращаемого значения.
18 * @param name Ключ сервиса, который будет разрешен.
17 * @param name Ключ сервиса, который будет разрешен.
19 * @param {boolean=} opts.lazy Признак того, что требуется отложенная активация,
18 * @param {boolean=} opts.lazy Признак того, что требуется отложенная активация,
20 * будет возвращен фабричный метод для получения зависимости. Если не указан,
19 * будет возвращен фабричный метод для получения зависимости. Если не указан,
21 * то считается `false`.
20 * то считается `false`.
22 * @param {any=} opts.default Значение по умолчанию, если в контейнере указанный
21 * @param {any=} opts.default Значение по умолчанию, если в контейнере указанный
23 * сервис не зарегистрирован
22 * сервис не зарегистрирован
24 * @returns Либо фабричный метод для получения зависимости, либо значение зависимости
23 * @returns Либо фабричный метод для получения зависимости, либо значение зависимости
25 * @throws Error Если зависимость не найдена и не предоставлено значение по-умолчанию
24 * @throws Error Если зависимость не найдена и не предоставлено значение по-умолчанию
26 */
25 */
27 <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]>;
28 <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]>;
29 }
28 }
30
29
31 export type DepsMap<K extends key, SK extends key> = { [k in K]: SK | Ref<SK, boolean, unknown> };
30 export type DepsMap<K extends key, SK extends key> = { [k in K]: SK | Ref<SK, boolean, unknown> };
32
31
33 export type Ref<K extends key, L extends boolean, D> = { name: K, lazy?: L } | { name: K, lazy?: L, default: D };
32 export type Ref<K extends key, L extends boolean, D> = { name: K, lazy?: L } | { name: K, lazy?: L, default: D };
34
33
35 export type Resolved<S, K extends keyof S, L, D> =
34 export type Resolved<S, K extends keyof S, L, D> =
36 L extends true ? () => NonNullable<S[K]> | (unknown extends D ? never : D) : NonNullable<S[K]> | (unknown extends D ? never : D);
35 L extends true ? () => NonNullable<S[K]> | (unknown extends D ? never : D) : NonNullable<S[K]> | (unknown extends D ? never : D);
37
36
38 export interface IDescriptorBuilder<S extends object, T, R extends object = object> {
37 export interface IDescriptorBuilder<S extends object, T, R extends object, O extends keyof S> {
39
38
40 /**
39 /**
41 *
40 *
42 * @param f
41 * @param f
43 */
42 */
44 factory(f: (refs: R) => T): void;
43 factory(f: (refs: R) => T): void;
45
44
46 wants<X extends DepsMap<Exclude<key, keyof R>, keyof S>>(refs: X):
45 wants<X extends DepsMap<Exclude<key, keyof R>, keyof S>>(refs: X):
47 IDescriptorBuilder<S, T, R & {
46 IDescriptorBuilder<S, T, R & {
48 [k in keyof X]:
47 [k in keyof X]:
49 X[k] extends keyof S ? NonNullable<S[X[k]]> :
48 X[k] extends keyof S ? NonNullable<S[X[k]]> :
50 X[k] extends Ref<infer K, infer L, infer D> ? Resolved<S, K & keyof S, L, D> :
49 X[k] extends Ref<infer K, infer L, infer D> ? Resolved<S, K & keyof S, L, D> :
51 never
50 never
52 }>
51 }, O>
53
52
54 override<K extends ConfigurableKeys<S>>(name: K, builder: RegistrationBuilder<S, NonNullable<S[K]>>): this;
53 override<K extends O>(name: K, builder: RegistrationBuilder<S, NonNullable<S[K]>>): this;
55 override<K extends ConfigurableKeys<S>>(services: { [name in K]: RegistrationBuilder<S, NonNullable<S[K]>> }): this;
54 override<K extends O>(services: { [name in K]: RegistrationBuilder<S, NonNullable<S[K]>> }): this;
56
55
57 lifetime(lifetime: "singleton", typeId: string | number | object): this;
56 lifetime(lifetime: "singleton", typeId: string | number | object): this;
58 lifetime(lifetime: ILifetime<T> | Exclude<ActivationType, "singleton">): this;
57 lifetime(lifetime: ILifetime<T> | Exclude<ActivationType, "singleton">): this;
59
58
60 cleanup(cb: (item: T) => void): this;
59 cleanup(cb: (item: T) => void): this;
61
60
62 value(v: T): void;
61 value(v: T): void;
63 }
62 }
64
63
65 export type RegistrationBuilder<S extends object, T> = (d: IDescriptorBuilder<S, T>) => void;
64 export type RegistrationBuilder<S extends object, T> = (d: IDescriptorBuilder<S, T, object, ConfigurableKeys<S>>) => void;
66
65
67 export type RegistrationBuildersMap<S extends object, K extends ConfigurableKeys<S> = ConfigurableKeys<S>> = {
66 export type RegistrationBuildersMap<S extends Configurable<S>, K extends keyof S = keyof S> = {
68 [k in K]-?: RegistrationBuilder<ContainerServices<S>, NonNullable<S[k]>>
67 [k in K]-?: RegistrationBuilder<ContainerServices<S>, NonNullable<S[k]>>
69 };
68 };
70
69
71 export interface Descriptor<S extends object, T> {
70 export interface Descriptor<S extends object, T> {
72 activate(context: IActivationContext<S>): T;
71 activate(context: IActivationContext<S>): T;
73 }
72 }
74
73
75 export interface IActivationContext<S extends object> extends ServiceLocator<S> {
74 export interface IActivationContext<S extends object> extends ServiceLocator<S> {
76 createLifetime<T>(): ILifetime<T>;
75 createLifetime<T>(): ILifetime<T>;
77
76
78 createContainerLifetime<T>(): ILifetime<T>;
77 createContainerLifetime<T>(): ILifetime<T>;
79 }
78 }
80
79
81 export type ConfigurableDescriptor<S extends object, K extends ConfigurableKeys<S>> = Descriptor<ContainerServices<S>, S[K]>;
82
83 export type RegistrationMap<S extends object, K extends keyof S = keyof S> = {
80 export type RegistrationMap<S extends object, K extends keyof S = keyof S> = {
84 [k in K]-?: Descriptor<S, S[k]>;
81 [k in K]-?: Descriptor<S, S[k]>;
85 };
82 };
86
83
87 export interface ContainerProvided<S extends Configurable<S>> {
84 export interface ContainerProvided<S extends Configurable<S>> {
88 container: ServiceLocator<ContainerServices<S>>;
85 container: ServiceLocator<ContainerServices<S>>;
89
86
90 childContainer: IContainerBuilder<S>;
87 childContainer: IContainerBuilder<S>;
91 }
88 }
92
89
93 export type Configurable<S> = { [k in keyof S & (keyof ContainerProvided<never>)]: never; };
90 export type Configurable<S> = { [k in keyof S & (keyof ContainerProvided<never>)]: never; };
94
91
95 export type ProvidedKeys = keyof ContainerProvided<never>;
92 export type ProvidedKeys = keyof ContainerProvided<never>;
96
93
97 export type ContainerServices<S extends Configurable<S>> = S & ContainerProvided<S>;
94 export type ContainerServices<S extends Configurable<S>> = S & ContainerProvided<S>;
98
95
99 export type ConfigurableKeys<S extends object> = Exclude<keyof S, ProvidedKeys>;
96 export type ConfigurableKeys<S extends object> = Exclude<keyof S, ProvidedKeys>;
100
97
101 export type ConfigurableServices<S extends object> = Pick<S, ConfigurableKeys<S>>;
98 export type ConfigurableServices<S extends object> = Pick<S, ConfigurableKeys<S>>;
102
99
103 export type ContainerKeys<S extends Configurable<S>> = keyof S | keyof ContainerProvided<never>;
100 export type ContainerKeys<S extends Configurable<S>> = keyof S | keyof ContainerProvided<never>;
104
101
105 export interface ServiceLocator<S extends object> {
102 export interface ServiceLocator<S extends object> {
106 resolve<K extends keyof S>(name: K): NonNullable<S[K]>;
103 resolve<K extends keyof S>(name: K): NonNullable<S[K]>;
107 resolve<K extends keyof S, T>(name: K, def: T): NonNullable<S[K]> | T;
104 resolve<K extends keyof S, T>(name: K, def: T): NonNullable<S[K]> | T;
108 }
105 }
109
106
110 export interface LifetimeContainer {
107 export interface LifetimeContainer {
111 createLifetime<T>(): ILifetime<T>;
108 createLifetime<T>(): ILifetime<T>;
112 }
109 }
113
110
114 export interface ServiceContainer<S extends Configurable<S>> extends
111 export interface ServiceContainer<S extends Configurable<S>> extends
115 ServiceLocator<ContainerServices<S>>,
112 ServiceLocator<ContainerServices<S>>,
116 IDestroyable {
113 IDestroyable {
117
114
118 createChildContainer(): IContainerBuilder<S>;
115 createChildContainer(): IContainerBuilder<S>;
119 }
116 }
120
117
121 export interface IContainerBuilder<S extends Configurable<S>> {
118 export interface IContainerBuilder<S extends Configurable<S>> {
122 createServiceBuilder<K extends keyof S>(name: K): IDescriptorBuilder<S, NonNullable<S[K]>>;
119 createServiceBuilder<K extends keyof S>(name: K): IDescriptorBuilder<S, NonNullable<S[K]>, object, keyof S>;
123
120
124 build(): ServiceContainer<S>;
121 build(): ServiceContainer<S>;
125 }
122 }
126
123
127
124
128 export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call";
125 export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call";
129
126
130 /**
127 /**
131 * Интерфейс для управления жизнью экземпляра объекта. Каждая регистрация имеет
128 * Интерфейс для управления жизнью экземпляра объекта. Каждая регистрация имеет
132 * свой собственный объект `ILifetime`, который создается при первой активации
129 * свой собственный объект `ILifetime`, который создается при первой активации
133 */
130 */
134 export interface ILifetime<T> {
131 export interface ILifetime<T> {
135 /** Проверяет, что уже создан экземпляр объекта */
132 /** Проверяет, что уже создан экземпляр объекта */
136 has(): boolean;
133 has(): boolean;
137
134
138 get(): T;
135 get(): T;
139
136
140 initialize(context: IActivationContext<object>): void;
137 initialize(context: IActivationContext<object>): void;
141
138
142 store(item: T, cleanup?: (item: T) => void): void;
139 store(item: T, cleanup?: (item: T) => void): void;
143 }
140 }
144
141
145 export type ExtractRequired<T, K extends keyof T = keyof T> = { [p in K as (undefined extends T[p] ? never : p)]-?: T[p] };
142 export type ExtractRequired<T, K extends keyof T = keyof T> = { [p in K as (undefined extends T[p] ? never : p)]-?: T[p] };
146
143
General Comments 0
You need to be logged in to leave comments. Login now