##// END OF EJS Templates
intoruced initial work on ILifetimeSlot
cin -
r10:99a53d63fd6f default
parent child
Show More
@@ -1,217 +1,243
1 import { IActivationContext, ILifetime, ILifetimeManager } from "./interfaces";
1 import { IActivationContext, ILifetime, ILifetimeContext, ILifetimeManager, ILifetimeSlot } from "./interfaces";
2 import { ActivationContext } from "./ActivationContext";
2 import { ActivationContext } from "./ActivationContext";
3 import { argumentNotNull, isDestroyable } from "./traits";
3 import { argumentNotNull, isDestroyable } from "./traits";
4
4
5 const safeCall = (item: () => void) => {
5 const safeCall = (item: () => void) => {
6 try {
6 try {
7 item();
7 item();
8 } catch {
8 } catch {
9 // silence!
9 // silence!
10 }
10 }
11 };
11 };
12
12
13 const _emptyLifetime = Object.freeze({
13 const _emptySlot = Object.freeze({
14 has() {
14 has: () => false,
15 return false;
16 },
17
15
18 initialize() {
16 initialize: () => void (0),
19 },
20
17
21 get() {
18 get: () => {
22 throw new Error("The specified item isn't registered with this lifetime manager");
19 throw new Error("The specified item isn't registered with this lifetime manager");
23 },
20 },
24
21
25 store() {
22 store: () => void (0)
26 // does nothing
27 },
28
29 toString() {
30 return `[object EmptyLifetime]`;
31 }
32
33 });
23 });
34
24
35 const _unknownLifetime = Object.freeze({
25 const _unknonwSlot = Object.freeze({
36 has() {
26 has: () => false,
37 return false;
27
38 },
28 initialize: () => {
39 initialize() {
40 throw new Error("Can't call initialize on the unknown lifetime object");
29 throw new Error("Can't call initialize on the unknown lifetime object");
41 },
30 },
42 get() {
31 get: () => {
43 throw new Error("The lifetime object isn't initialized");
32 throw new Error("The lifetime object isn't initialized");
44 },
33 },
45 store() {
34 store: () => {
46 throw new Error("Can't store a value in the unknown lifetime object");
35 throw new Error("Can't store a value in the unknown lifetime object");
47 },
48
49 toString() {
50 return `[object UnknownLifetime]`;
51 }
36 }
52 });
37 });
53
38
54 let nextId = 0;
39 let nextId = 0;
55
40
56 const singletons: { [K: string]: unknown } = {};
41 const singletons: { [K: string]: unknown } = {};
57
42
58 export class LifetimeManager implements ILifetimeManager {
59 private _cleanup: (() => void)[] = [];
60 private readonly _cache: { [K: string]: unknown } = {};
61 private _destroyed = false;
62
43
63 private readonly _pending: { [K: string]: unknown } = {};
44 const pendingSlot = <T>(store: (item: T) => void) => ({
64
45 has: () => false,
65 create<T>(): ILifetime<T> & { remove(): void; } {
66 const id = ++nextId;
67 return {
68 has: () => id in this._cache,
69
46
70 get: () => {
47 get: () => {
71 const t = this._cache[id] as T;
48 throw new Error("The value in this slot doesn't exist");
72 if (t === undefined || t === null)
73 throw new Error(`The item with with the key ${id} isn't found`);
74 return t;
75 },
49 },
76
50
77 initialize: () => {
51 initialize: () => {
78 if (this._pending[id])
52 throw new Error("Cyclic reference detected");
79 throw Error(`Cyclic reference detected: the item with the key ${id} is already activating.`);
53 },
80 this._pending[id] = true;
54
55 store
56 });
57
58 const noop = () => void(0);
59
60 const valueSlot = <T>(value: T, cleanup: (item: T) => void) => ({
61 has: () => true,
62
63 get: () => value,
64
65 initialize: () => {
66 throw new Error("The slot already has a value");
81 },
67 },
82
68
83 store: (item: NonNullable<T>, cleanup?: (item: NonNullable<T>) => void) => {
69 store: () => {
84 if (id in this._cache)
70 throw new Error("The slot already has a value");
85 throw new Error(`The item with with the key ${id} already registered with this lifetime manager`);
71 }
86 if (this._destroyed)
72 });
87 throw new Error("Lifetime manager is destroyed");
88
73
89 delete this._pending[id];
74 export class LifetimeManager implements ILifetimeManager {
75 private _destroyed = false;
90
76
91 this._cache[id] = item;
77 private readonly _slots: Record<string, ILifetimeSlot<unknown>> = {};
78
79 slot<T>(cookie: string): ILifetimeSlot<T> {
80 if (cookie in this._slots)
81 return this._slots[cookie] as ILifetimeSlot<T>;
92
82
93 if (cleanup) {
83 const store = (item: T, cleanup?: (item: T) => void) => {
94 this._cleanup.push(() => cleanup(item));
84 this._assertNotDestroyed();
95 } else if (isDestroyable(item)) {
85 this._slots[cookie] = valueSlot(
96 this._cleanup.push(() => item.destroy());
86 item,
97 }
87 cleanup ?? isDestroyable(item) ? () => item.destroy() : noop
88 );
89 };
90
91 return {
92 has: () => false,
93 get: () => {
94 throw new Error("The value isn't stored in this slot");
98 },
95 },
99
96 store,
100 remove: () => {
97 initialize: () => {
101 if (this._pending[id])
98 this._assertNotDestroyed();
102 throw new Error(`The item '${id}' can't be removed before it has been stored`);
99 this._slots[cookie] = pendingSlot(store);
103 delete this._cache[id];
104 }
100 }
105 };
101 };
106 }
102 }
107
103
104 private _assertNotDestroyed() {
105 if (this._destroyed)
106 throw new Error("The lifetime manager is destroyed");
107
108 }
109
108 destroy() {
110 destroy() {
109 if (!this._destroyed) {
111 if (!this._destroyed) {
110 this._destroyed = true;
112 this._destroyed = true;
111 this._cleanup.forEach(safeCall);
113 this._cleanup.forEach(safeCall);
112 this._cleanup.length = 0;
114 this._cleanup.length = 0;
113 }
115 }
114 }
116 }
115
117
116 }
118 }
117
119
118 export const emptyLifetime = <T>(): ILifetime<T> => {
120 export const emptyLifetime = <T>(): ILifetime<T> => {
119 return _emptyLifetime;
121 return _emptyLifetime;
120 };
122 };
121
123
122 export const hierarchyLifetime = <T>(): ILifetime<T> => {
124 export const hierarchyLifetime = <T>(): ILifetime<T> => {
123 let _lifetime: ILifetime<T> = _unknownLifetime;
125 let _lifetime: ILifetime<T> = _unknownLifetime;
124 return {
126 return {
125 initialize(context: IActivationContext<object>) {
127 initialize(context: ILifetimeContext) {
126 if (_lifetime !== _unknownLifetime)
128 if (_lifetime !== _unknownLifetime)
127 throw new Error("Cyclic reference activation detected");
129 throw new Error("Cyclic reference activation detected");
128
130
129 _lifetime = context.createContainerLifetime<T>();
131 _lifetime = context.createContainerLifetime<T>();
130 },
132 },
131 get() {
133 get() {
132 return _lifetime.get();
134 return _lifetime.get();
133 },
135 },
134 has() {
136 has() {
135 return _lifetime.has();
137 return _lifetime.has();
136 },
138 },
137 store(item: NonNullable<T>, cleanup?: (item: NonNullable<T>) => void) {
139 store(item: NonNullable<T>, cleanup?: (item: NonNullable<T>) => void) {
138 return _lifetime.store(item, cleanup);
140 return _lifetime.store(item, cleanup);
139 },
141 },
140 toString() {
142 toString() {
141 return `[object HierarchyLifetime, has=${String(this.has())}]`;
143 return `[object HierarchyLifetime, has=${String(this.has())}]`;
142 }
144 }
143 };
145 };
144 };
146 };
145
147
148 /**
149 * Creates a lifetime instance bound to the current activation context. This
150 * lifetime will store the service instance per activation context. Every
151 * top level service resolution will create a new activation context. This
152 * context is propagated to subsequent service resolution thus all services
153 * with context lifetime will be shared among their consumers.
154 *
155 * @returns The instance of the lifetime.
156 */
146 export const contextLifetime = <T>(): ILifetime<T> => {
157 export const contextLifetime = <T>(): ILifetime<T> => {
147 let _lifetime: ILifetime<T> = _unknownLifetime;
158 let _lifetime: ILifetime<T> = _unknownLifetime;
148 return {
159 return {
149 initialize(context: ActivationContext<object>) {
160 initialize(context: ILifetimeContext) {
150 if (_lifetime !== _unknownLifetime)
161 if (_lifetime !== _unknownLifetime)
151 throw new Error("Cyclic reference detected");
162 throw new Error("Cyclic reference detected");
152 _lifetime = context.createLifetime();
163 _lifetime = context.createLifetime();
153 },
164 },
154 get() {
165 get() {
155 return _lifetime.get();
166 return _lifetime.get();
156 },
167 },
157 has() {
168 has() {
158 return _lifetime.has();
169 return _lifetime.has();
159 },
170 },
160 store(item: NonNullable<T>) {
171 store(item: NonNullable<T>) {
161 _lifetime.store(item);
172 _lifetime.store(item);
162 },
173 },
163 toString() {
174 toString() {
164 return `[object ContextLifetime, has=${String(this.has())}]`;
175 return `[object ContextLifetime, has=${String(this.has())}]`;
165 }
176 }
166 };
177 };
167 };
178 };
168
179
180 /**
181 * Creates the lifetime for the service which will allow existence only one
182 * instance with the specified {@linkcode typeId}. If there will be created
183 * several lifetime instances with same `typeId` in the runtime, they will
184 * share the same service instance.
185 *
186 * @param typeId The identified for the global instance, usually this is a
187 * fully qualified class name
188 * @returns The lifetime instance
189 */
169 export const singletonLifetime = <T>(typeId: string): ILifetime<T> => {
190 export const singletonLifetime = <T>(typeId: string): ILifetime<T> => {
170 argumentNotNull(typeId, "typeId");
191 argumentNotNull(typeId, "typeId");
171 let pending = false;
192 let pending = false;
172 return {
193 return {
173 has() {
194 has() {
174 return typeId in singletons;
195 return typeId in singletons;
175 },
196 },
176 get() {
197 get() {
177 if (!this.has())
198 if (!this.has())
178 throw new Error(`The instance ${typeId} doesn't exists`);
199 throw new Error(`The instance ${typeId} doesn't exists`);
179 return singletons[typeId] as NonNullable<T>;
200 return singletons[typeId] as NonNullable<T>;
180 },
201 },
181 initialize() {
202 initialize() {
182 if (pending)
203 if (pending)
183 throw new Error("Cyclic reference detected");
204 throw new Error("Cyclic reference detected");
184 pending = true;
205 pending = true;
185 },
206 },
186 store(item: NonNullable<T>) {
207 store(item: NonNullable<T>) {
187 singletons[typeId] = item;
208 singletons[typeId] = item;
188 pending = false;
209 pending = false;
189 },
210 },
190 toString() {
211 toString() {
191 return `[object SingletonLifetime, has=${String(this.has())}, typeId=${typeId}]`;
212 return `[object SingletonLifetime, has=${String(this.has())}, typeId=${typeId}]`;
192 }
213 }
193 };
214 };
194 };
215 };
195
216
217 /** Creates a lifetime bound to the specified container. Using this lifetime
218 * will create a single service instance per the specified container.
219 *
220 * @param container The container which will manage the lifetime for the service
221 */
196 export const containerLifetime = <T>(container: { createLifetime<X>(): ILifetime<X> }) => {
222 export const containerLifetime = <T>(container: { createLifetime<X>(): ILifetime<X> }) => {
197 let _lifetime: ILifetime<T> = _unknownLifetime;
223 let _lifetime: ILifetime<T> = _unknownLifetime;
198 return {
224 return {
199 initialize() {
225 initialize() {
200 if (_lifetime !== _unknownLifetime)
226 if (_lifetime !== _unknownLifetime)
201 throw new Error("Cyclic reference detected");
227 throw new Error("Cyclic reference detected");
202 _lifetime = container.createLifetime();
228 _lifetime = container.createLifetime();
203 },
229 },
204 get() {
230 get() {
205 return _lifetime.get();
231 return _lifetime.get();
206 },
232 },
207 has() {
233 has() {
208 return _lifetime.has();
234 return _lifetime.has();
209 },
235 },
210 store(item: NonNullable<T>) {
236 store(item: NonNullable<T>, cleanup?: (item: NonNullable<T>) => void) {
211 _lifetime.store(item);
237 _lifetime.store(item, cleanup);
212 },
238 },
213 toString() {
239 toString() {
214 return `[object ContainerLifetime, has=${String(_lifetime.has())}]`;
240 return `[object ContainerLifetime, has=${String(_lifetime.has())}]`;
215 }
241 }
216 };
242 };
217 };
243 };
@@ -1,258 +1,273
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> {
10 export interface Resolver<S> {
11 /**
11 /**
12 * Ѐункция для Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ зависимостСй, ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ созданиС Ρ„Π°Π±Ρ€ΠΈΡ‡Π½Ρ‹Ρ… ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ²,
12 * Ѐункция для Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ зависимостСй, ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ созданиС Ρ„Π°Π±Ρ€ΠΈΡ‡Π½Ρ‹Ρ… ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ²,
13 * ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΡƒΡŽ Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΡŽ ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ-ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для сСрвисов
13 * ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½Π½ΡƒΡŽ Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΡŽ ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ-ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для сСрвисов
14 * @template K ΠšΠ»ΡŽΡ‡ сСрвиса ΠΈΠ· {@linkcode S}
14 * @template K ΠšΠ»ΡŽΡ‡ сСрвиса ΠΈΠ· {@linkcode S}
15 * @template O Π’ΠΈΠΏ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° {@linkcode opts} ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для вывСдСния Ρ‚ΠΈΠΏΠ°
15 * @template O Π’ΠΈΠΏ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° {@linkcode 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; }>(name: K, opts?: O): () => NonNullable<S[K]> | InferDefault<O>;
26 <K extends keyof S, O extends { lazy: true; }>(name: K, opts?: O): () => NonNullable<S[K]> | InferDefault<O>;
27 <K extends keyof S, O extends { lazy?: false; }>(name: K, opts?: O): NonNullable<S[K]> | InferDefault<O>;
27 <K extends keyof S, O extends { lazy?: false; }>(name: K, opts?: O): NonNullable<S[K]> | InferDefault<O>;
28 }
28 }
29
29
30 export type DepsMap<S> = {
30 export type DepsMap<S> = {
31 [k in key]: Refs<S> | keyof S;
31 [k in key]: Refs<S> | keyof S;
32 };
32 };
33
33
34 export type Refs<S> = {
34 export type Refs<S> = {
35 [k in keyof S]: Ref<k, S[k]>;
35 [k in keyof S]: Ref<k, S[k]>;
36 }[keyof S];
36 }[keyof S];
37
37
38 export type Ref<K extends key, D> = {
38 export type Ref<K extends key, D> = {
39 /** The name of the service */
39 /** The name of the service */
40 name: K;
40 name: K;
41
41
42 /** Make a lazy reference, the resolved dependency will be a function */
42 /** Make a lazy reference, the resolved dependency will be a function */
43 lazy?: boolean;
43 lazy?: boolean;
44
44
45 /** The default value for the case where the service isn't defined.
45 /** The default value for the case where the service isn't defined.
46 * When specified the dependency becomes optional, the default value can be
46 * When specified the dependency becomes optional, the default value can be
47 * `null` or `undefined`
47 * `null` or `undefined`
48 */
48 */
49 default?: D | null
49 default?: D | null
50 };
50 };
51
51
52 export type Lazy<T, L extends boolean> = L extends true ? () => T : T;
52 export type Lazy<T, L extends boolean> = L extends true ? () => T : T;
53
53
54 /** Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ‚ΠΈΠΏ свойства `default` Π² Ρ‚ΠΈΠΏΠ΅ {@link T} */
54 /** Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ‚ΠΈΠΏ свойства `default` Π² Ρ‚ΠΈΠΏΠ΅ {@link T} */
55 export type InferDefault<T> = T extends { default: infer D } ? D : never;
55 export type InferDefault<T> = T extends { default: infer D } ? D : never;
56
56
57 export type InferLazy<R> = R extends { lazy: infer L } ?
57 export type InferLazy<R> = R extends { lazy: infer L } ?
58 L extends true ? true : false :
58 L extends true ? true : false :
59 false;
59 false;
60 export type Resolve<S, R> =
60 export type Resolve<S, R> =
61 R extends keyof S ? NonNullable<S[R]> :
61 R extends keyof S ? NonNullable<S[R]> :
62 R extends Ref<infer K, unknown> ?
62 R extends Ref<infer K, unknown> ?
63 K extends keyof S ?
63 K extends keyof S ?
64 Lazy<NonNullable<S[K]> | InferDefault<R>, InferLazy<R>> :
64 Lazy<NonNullable<S[K]> | InferDefault<R>, InferLazy<R>> :
65 never :
65 never :
66 never;
66 never;
67
67
68 /**
68 /**
69 * Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ для конфигурирования сСрвиса Π² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π΅. ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сСрвиса
69 * Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ для конфигурирования сСрвиса Π² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π΅. ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сСрвиса
70 * состоит ΠΈΠ· настройки Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² {@linkcode wants},
70 * состоит ΠΈΠ· настройки Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² {@linkcode wants},
71 * {@linkcode lifetime}, {@linkcode override}, {@linkcode cleanup}. Π—Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ настройки
71 * {@linkcode lifetime}, {@linkcode override}, {@linkcode cleanup}. Π—Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ настройки
72 * сСрвиса осущСствляСтся Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² {@linkcode factory} Π»ΠΈΠ±ΠΎ
72 * сСрвиса осущСствляСтся Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² {@linkcode factory} Π»ΠΈΠ±ΠΎ
73 * {@linkcode value}.
73 * {@linkcode value}.
74 *
74 *
75 * @template S ΠšΠ°Ρ€Ρ‚Π° сСрвисов ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°, доступных ΠΏΡ€ΠΈ описании дСскриптора
75 * @template S ΠšΠ°Ρ€Ρ‚Π° сСрвисов ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°, доступных ΠΏΡ€ΠΈ описании дСскриптора
76 * @template T Π’ΠΈΠΏ сСрвиса
76 * @template T Π’ΠΈΠΏ сСрвиса
77 * @template R ΠšΠ°Ρ€Ρ‚Π° зависимостСй, которая пСрСдаСтся ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ Ρ„Π°Π±Ρ€ΠΈΠΊΠ΅
77 * @template R ΠšΠ°Ρ€Ρ‚Π° зависимостСй, которая пСрСдаСтся ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ Ρ„Π°Π±Ρ€ΠΈΠΊΠ΅
78 * @template U ИмСна ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΡ… сСрвисов, доступных для пСрСопрСдСлСния
78 * @template U ИмСна ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΡ… сСрвисов, доступных для пСрСопрСдСлСния
79 */
79 */
80 export interface IDescriptorBuilder<S, T, R, U extends keyof S> {
80 export interface IDescriptorBuilder<S, T, R, U extends keyof S> {
81
81
82 /** Π£ΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ„Π°Π±Ρ€ΠΈΠΊΠ° для создания экзСмпляра сСрвиса, Ρ„Π°Π±Ρ€ΠΈΠΊΠ° пСрСдаСтся
82 /** Π£ΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ„Π°Π±Ρ€ΠΈΠΊΠ° для создания экзСмпляра сСрвиса, Ρ„Π°Π±Ρ€ΠΈΠΊΠ° пСрСдаСтся
83 * Π² Π²ΠΈΠ΄Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°. ΠŸΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„Π°Π±Ρ€ΠΈΠΊΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ с зависимостями,
83 * Π² Π²ΠΈΠ΄Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°. ΠŸΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„Π°Π±Ρ€ΠΈΠΊΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ с зависимостями,
84 * ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±Ρ‹Π»ΠΈ ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΡƒΠΊΠ°Π·Π°Π½Ρ‹ Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° `wants(...)`
84 * ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±Ρ‹Π»ΠΈ ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΡƒΠΊΠ°Π·Π°Π½Ρ‹ Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° `wants(...)`
85 *
85 *
86 * Π’Ρ‹Π·ΠΎΠ² Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сСрвиса.
86 * Π’Ρ‹Π·ΠΎΠ² Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ сСрвиса.
87 *
87 *
88 * @param f Π€Π°Π±Ρ€ΠΈΠΊΠ° для создания экзСмпляра сСрвиса.
88 * @param f Π€Π°Π±Ρ€ΠΈΠΊΠ° для создания экзСмпляра сСрвиса.
89 */
89 */
90 factory(f: (refs: R) => NonNullable<T>): void;
90 factory(f: (refs: R) => NonNullable<T>): void;
91
91
92 /**
92 /**
93 * Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для указания зависимостСй, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΡ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ΡΡ Ρ„Π°Π±Ρ€ΠΈΡ‡Π½ΠΎΠΌΡƒ
93 * Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для указания зависимостСй, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΡ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ΡΡ Ρ„Π°Π±Ρ€ΠΈΡ‡Π½ΠΎΠΌΡƒ
94 * ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ ΠΏΡ€ΠΈ создании Π½ΠΎΠ²ΠΎΠ³ΠΎ экзСмпляра сСрвиса. Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ
94 * ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ ΠΏΡ€ΠΈ создании Π½ΠΎΠ²ΠΎΠ³ΠΎ экзСмпляра сСрвиса. Π”Π°Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ
95 * Π²Ρ‹Π·Π²Π°Π½ нСсколько Ρ€Π°Π· подряд, ΠΏΡ€ΠΈ этом Π²Ρ‹Π·ΠΎΠ²Ρ‹ этого ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ΠΈΠΌΠ΅ΡŽΡ‚
95 * Π²Ρ‹Π·Π²Π°Π½ нСсколько Ρ€Π°Π· подряд, ΠΏΡ€ΠΈ этом Π²Ρ‹Π·ΠΎΠ²Ρ‹ этого ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ΠΈΠΌΠ΅ΡŽΡ‚
96 * кумулятивный эффСкт.
96 * кумулятивный эффСкт.
97 *
97 *
98 * @template X Π’ΠΈΠΏ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° с зависимостями, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ трСбуСтся ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΡ€ΠΈ
98 * @template X Π’ΠΈΠΏ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° с зависимостями, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ трСбуСтся ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΡ€ΠΈ
99 * создании экзСмпляра Ρ„Π°Π±Ρ€ΠΈΠΊΠΈ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ Ρ„Π°Π±Ρ€ΠΈΡ‡Π½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°.
99 * создании экзСмпляра Ρ„Π°Π±Ρ€ΠΈΠΊΠΈ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ Ρ„Π°Π±Ρ€ΠΈΡ‡Π½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°.
100 * @param refs ΠžΠ±ΡŠΠ΅ΠΊΡ‚ с описаниСм зависимостСй
100 * @param refs ΠžΠ±ΡŠΠ΅ΠΊΡ‚ с описаниСм зависимостСй
101 * @returns Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ дСскриптор сСрвиса, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΡƒΠΊΠ°Π·Π°Π½Ρ‹ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅
101 * @returns Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ дСскриптор сСрвиса, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΡƒΠΊΠ°Π·Π°Π½Ρ‹ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅
102 * зависимости
102 * зависимости
103 */
103 */
104 wants<X extends DepsMap<S> & Record<keyof R & keyof X, never>>(refs: X):
104 wants<X extends DepsMap<S> & Record<keyof R & keyof X, never>>(refs: X):
105 IDescriptorBuilder<S, T, R & {
105 IDescriptorBuilder<S, T, R & {
106 [k in keyof X]: Resolve<S, X[k]>;
106 [k in keyof X]: Resolve<S, X[k]>;
107 }, U>
107 }, U>
108
108
109 override<K extends U>(name: K, builder: BuildDescriptorFn<S, S[K], U>): this;
109 override<K extends U>(name: K, builder: BuildDescriptorFn<S, S[K], U>): this;
110 override<X extends ConfigurationMapConstraint<S, U, keyof X>>(services: X): this;
110 override<X extends ConfigurationMapConstraint<S, U, keyof X>>(services: X): this;
111
111
112 lifetime(lifetime: "singleton", typeId: string | number | object): this;
112 lifetime(lifetime: "singleton", typeId: string | number | object): this;
113 lifetime(lifetime: ILifetime<T> | Exclude<ActivationType, "singleton">): this;
113 lifetime(lifetime: ILifetime<T> | Exclude<ActivationType, "singleton">): this;
114
114
115 /** Π£ΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ для освобоТдСния экзСмпляра сСрвиса для случаСв, ΠΊΠΎΠ³Π΄Π°
115 /** Π£ΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ для освобоТдСния экзСмпляра сСрвиса для случаСв, ΠΊΠΎΠ³Π΄Π°
116 * врСмя ΠΆΠΈΠ·Π½ΠΈ привязано ΠΊ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρƒ.
116 * врСмя ΠΆΠΈΠ·Π½ΠΈ привязано ΠΊ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρƒ.
117 */
117 */
118 cleanup(cb: (item: T) => void): this;
118 cleanup(cb: (item: T) => void): this;
119
119
120 /**
120 /**
121 * РСгистрируСт Π² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π΅ постоянноС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² качСствС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ сСрвиса.
121 * РСгистрируСт Π² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π΅ постоянноС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² качСствС Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ сСрвиса.
122 *
122 *
123 * @param v ЭкзСмпляр Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ сСрвиса.
123 * @param v ЭкзСмпляр Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ сСрвиса.
124 */
124 */
125 value(v: NonNullable<T>): void;
125 value(v: NonNullable<T>): void;
126 }
126 }
127
127
128 export type BuildDescriptorFn<S, T, U extends keyof S> = (d: IDescriptorBuilder<S, T, Record<never, never>, U>) => void;
128 export type BuildDescriptorFn<S, T, U extends keyof S> = (d: IDescriptorBuilder<S, T, Record<never, never>, U>) => void;
129
129
130 /**
130 /**
131 * ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°, состоит ΠΈΠ· Π½Π°Π±ΠΎΡ€Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ.
131 * ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°, состоит ΠΈΠ· Π½Π°Π±ΠΎΡ€Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡŽ.
132 *
132 *
133 * ВсС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΡΠ²Π»ΡΡŽΡ‚ΡΡ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ, Ссли трСбуСтся ввСсти
133 * ВсС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ ΡΠ²Π»ΡΡŽΡ‚ΡΡ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ, Ссли трСбуСтся ввСсти
134 * Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹, Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΡ‚ΡŒ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Ρ‚ΠΈΠΏΠ° {@linkcode K}
134 * Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹, Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΡ‚ΡŒ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ Ρ‚ΠΈΠΏΠ° {@linkcode K}
135 *
135 *
136 * @template S БСрвисы доступныС Π² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π΅
136 * @template S БСрвисы доступныС Π² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π΅
137 * @template K БСрвисы ΡƒΡ‡Π°ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ Π² ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ
137 * @template K БСрвисы ΡƒΡ‡Π°ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ Π² ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ
138 */
138 */
139 export type ConfigurationMap<S, K extends keyof S, U extends keyof S> = {
139 export type ConfigurationMap<S, K extends keyof S, U extends keyof S> = {
140 [k in K]-?: BuildDescriptorFn<S, S[k], U>
140 [k in K]-?: BuildDescriptorFn<S, S[k], U>
141 };
141 };
142
142
143 export type ConfigurationMapConstraint<S, U extends keyof S, X extends string | number | symbol> = {
143 export type ConfigurationMapConstraint<S, U extends keyof S, X extends string | number | symbol> = {
144 [k in X]-?: k extends U ? BuildDescriptorFn<S, S[k], U> : never;
144 [k in X]-?: k extends U ? BuildDescriptorFn<S, S[k], U> : never;
145 };
145 };
146
146
147 /**
147 /**
148 * The type constraint useful to restrict type parameters to prevent defining
148 * The type constraint useful to restrict type parameters to prevent defining
149 * the services with the {@link ContainerKeys} names.
149 * the services with the {@link ContainerKeys} names.
150 *
150 *
151 * The constraint doesn't exclude using this keys but declares them as `never`
151 * The constraint doesn't exclude using this keys but declares them as `never`
152 * which effectively will lead using this keys to the error.
152 * which effectively will lead using this keys to the error.
153 */
153 */
154 export type ContainerServicesConstraint<S> = {
154 export type ContainerServicesConstraint<S> = {
155 [k in keyof S]: k extends ContainerKeys ? never : S[k];
155 [k in keyof S]: k extends ContainerKeys ? never : S[k];
156 };
156 };
157
157
158 export interface Descriptor<S, T> {
158 export interface Descriptor<S, T> {
159
159
160 /** This flags indicates that this registration can be replaced or overridden. */
160 /** This flags indicates that this registration can be replaced or overridden. */
161 readonly configurable?: boolean;
161 readonly configurable?: boolean;
162
162
163 /** If specified signals the activation context that a new service scope
163 /** If specified signals the activation context that a new service scope
164 * should be created to isolate service overrides.
164 * should be created to isolate service overrides.
165 */
165 */
166 readonly hasOverrides?: boolean;
166 readonly hasOverrides?: boolean;
167
167
168 activate(context: IActivationContext<S>): NonNullable<T>;
168 activate(context: IActivationContext<S>): NonNullable<T>;
169 }
169 }
170
170
171 export interface IActivationContext<S> extends ServiceLocator<S> {
171 /** The context used to initialize lifetime instance {@linkcode ILifetime} */
172 export interface ILifetimeContext {
172 createLifetime<T>(): ILifetime<T>;
173 createLifetime<T>(): ILifetime<T>;
173
174
174 createContainerLifetime<T>(): ILifetime<T>;
175 createContainerLifetime<T>(): ILifetime<T>;
175
176
177 }
178
179 export interface IActivationContext<S> extends ILifetimeContext, ServiceLocator<S> {
180
176 register<K extends keyof S>(name: K, service: DescriptorMap<S>[K]): void;
181 register<K extends keyof S>(name: K, service: DescriptorMap<S>[K]): void;
177 }
182 }
178
183
179 /**
184 /**
180 * Descriptors map for the specified services {@linkcode S}. All entries are
185 * Descriptors map for the specified services {@linkcode S}. All entries are
181 * optional regardless the required or optional services in the original map.
186 * optional regardless the required or optional services in the original map.
182 *
187 *
183 * @template S БСрвисы контСкста Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ
188 * @template S БСрвисы контСкста Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ
184 * @template U ΠšΠ°Ρ€Ρ‚Π° сСрвисов ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ дСскрипторами
189 * @template U ΠšΠ°Ρ€Ρ‚Π° сСрвисов ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ дСскрипторами
185 */
190 */
186 export type DescriptorMap<S> = {
191 export type DescriptorMap<S> = {
187 [k in keyof S]?: Descriptor<S, S[k]>;
192 [k in keyof S]?: Descriptor<S, S[k]>;
188 };
193 };
189
194
190 type ContainerKeys = keyof ContainerProvided<object>;
195 type ContainerKeys = keyof ContainerProvided<object>;
191
196
192 export type ContainerProvided<S extends ContainerServicesConstraint<S>> = {
197 export type ContainerProvided<S extends ContainerServicesConstraint<S>> = {
193 container: ServiceLocator<ContainerServices<S>>;
198 container: ServiceLocator<ContainerServices<S>>;
194
199
195 childContainer: IContainerBuilder<ContainerServices<S>, Exclude<keyof S, ContainerKeys>>;
200 childContainer: IContainerBuilder<ContainerServices<S>, Exclude<keyof S, ContainerKeys>>;
196 };
201 };
197
202
198
203
199 /**
204 /**
200 * Π’Π°Π±Π»ΠΈΡ†Π° сСрвисов, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ прСдоставляСт ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€.
205 * Π’Π°Π±Π»ΠΈΡ†Π° сСрвисов, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ прСдоставляСт ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€.
201 *
206 *
202 * БСрвисы, прСдоставляСмыС ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠΌ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ null ΠΈΠ»ΠΈ undefined.
207 * БСрвисы, прСдоставляСмыС ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠΌ Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ null ΠΈΠ»ΠΈ undefined.
203 */
208 */
204 export type ContainerServices<S extends ContainerServicesConstraint<S>> = {
209 export type ContainerServices<S extends ContainerServicesConstraint<S>> = {
205 [k in keyof S | ContainerKeys]:
210 [k in keyof S | ContainerKeys]:
206 k extends ContainerKeys ? ContainerProvided<S>[k] :
211 k extends ContainerKeys ? ContainerProvided<S>[k] :
207 k extends keyof S ? S[k] : never
212 k extends keyof S ? S[k] : never
208 };
213 };
209
214
210
215
211 /**
216 /**
212 * Returns the service declared in the type map {@link S}.
217 * Returns the service declared in the type map {@link S}.
213 *
218 *
214 *
219 *
215 */
220 */
216 export interface ServiceLocator<S> {
221 export interface ServiceLocator<S> {
217 resolve<K extends keyof S>(name: K): NonNullable<S[K]>;
222 resolve<K extends keyof S>(name: K): NonNullable<S[K]>;
218 resolve<K extends keyof S, T>(name: K, def: T): NonNullable<S[K]> | T;
223 resolve<K extends keyof S, T>(name: K, def: T): NonNullable<S[K]> | T;
219 }
224 }
220
225
221 export interface LifetimeContainer {
226 export interface LifetimeContainer {
222 createLifetime<T>(): ILifetime<T>;
227 createLifetime<T>(): ILifetime<T>;
223 }
228 }
224
229
225 export interface IContainerBuilder<S, U extends keyof S> {
230 export interface IContainerBuilder<S, U extends keyof S> {
226 createServiceBuilder<K extends U>(name: K):
231 createServiceBuilder<K extends U>(name: K):
227 IDescriptorBuilder<S, S[K], Record<never, never>, U>;
232 IDescriptorBuilder<S, S[K], Record<never, never>, U>;
228
233
229 build(): ServiceLocator<S>;
234 build(): ServiceLocator<S>;
230 }
235 }
231
236
232
237
233 export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call";
238 export type ActivationType = "singleton" | "container" | "hierarchy" | "context" | "call";
234
239
235 /**
240 /**
236 * Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ для управлСния Тизнью экзСмпляра ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. КаТдая рСгистрация ΠΈΠΌΠ΅Π΅Ρ‚
241 * Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ для управлСния Тизнью экзСмпляра ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. КаТдая рСгистрация ΠΈΠΌΠ΅Π΅Ρ‚
237 * свой собствСнный ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ `ILifetime`, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ создаСтся ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΉ Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ
242 * свой собствСнный ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ `ILifetime`, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ создаСтся ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΉ Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ
238 */
243 */
239 export interface ILifetime<T> {
244 export interface ILifetime<T> {
240 /** ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ ΡƒΠΆΠ΅ создан экзСмпляр ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° */
245 /** ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ ΡƒΠΆΠ΅ создан экзСмпляр ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° */
241 has(): boolean;
246 has(): boolean;
242
247
243 get(): NonNullable<T>;
248 get(): NonNullable<T>;
244
249
245 initialize(context: IActivationContext<unknown>): void;
250 initialize(context: ILifetimeContext): void;
246
251
247 store(item: NonNullable<T>, cleanup?: (item: NonNullable<T>) => void): void;
252 store(item: NonNullable<T>, cleanup?: (item: NonNullable<T>) => void): void;
248
253
249 toString(): string;
254 toString(): string;
250 }
255 }
251
256
257 export interface ILifetimeSlot<T> {
258 has: () => boolean;
259
260 get: () => T;
261
262 initialize: () => void;
263
264 store(item: T, cleanup?: (item: T) => void): void;
265 }
266
252 export interface ILifetimeManager extends IDestroyable {
267 export interface ILifetimeManager extends IDestroyable {
253 create<T>(): ILifetime<T>;
268 create<T>(): ILifetime<T>;
254 }
269 }
255
270
256 export type ExtractRequired<T, K extends keyof T = keyof T> = { [p in K as (undefined extends T[p] ? never : p)]-?: T[p] };
271 export type ExtractRequired<T, K extends keyof T = keyof T> = { [p in K as (undefined extends T[p] ? never : p)]-?: T[p] };
257
272
258 export type ExtractRequiredKeys<T, K extends keyof T = keyof T> = { [p in K]-?: undefined extends T[p] ? never : p }[K]; No newline at end of file
273 export type ExtractRequiredKeys<T, K extends keyof T = keyof T> = { [p in K]-?: undefined extends T[p] ? never : p }[K];
General Comments 0
You need to be logged in to leave comments. Login now