@vercube/di 0.0.21 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -6
- package/dist/index.mjs +237 -241
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
<br>
|
|
4
4
|
<br>
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
# Vercube
|
|
7
|
+
|
|
8
|
+
Next generation HTTP framework
|
|
9
|
+
|
|
10
10
|
<a href="https://www.npmjs.com/package/@vercube/cli">
|
|
11
11
|
<img src="https://img.shields.io/npm/v/%40vercube%2Fdi?style=for-the-badge&logo=npm&color=%23767eff" alt="npm"/>
|
|
12
12
|
</a>
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
<a href="https://github.com/vercube/vercube/blob/main/LICENSE" target="_blank">
|
|
17
17
|
<img src="https://img.shields.io/npm/l/%40vercube%2Fdi?style=for-the-badge&color=%23767eff" alt="License"/>
|
|
18
18
|
</a>
|
|
19
|
+
<a href="https://codecov.io/gh/vercube/vercube" target="_blank">
|
|
20
|
+
<img src="https://img.shields.io/codecov/c/github/vercube/vercube?style=for-the-badge&color=%23767eff" alt="Coverage"/>
|
|
21
|
+
</a>
|
|
19
22
|
<br/>
|
|
20
23
|
<br/>
|
|
21
24
|
</div>
|
|
@@ -23,8 +26,9 @@
|
|
|
23
26
|
An ultra-efficient JavaScript server framework that runs anywhere - Node.js, Bun, or Deno - with unmatched flexibility and complete configurability for developers who refuse to sacrifice speed or control.
|
|
24
27
|
|
|
25
28
|
## <a name="module">Dependencie Injection Module</a>
|
|
26
|
-
The Dependency Injection (DI) module provides a powerful and flexible dependency injection system for Vercube applications. It enables loose coupling between components and makes your application more maintainable and testable.
|
|
27
29
|
|
|
30
|
+
The Dependency Injection (DI) module provides a powerful and flexible dependency injection system for Vercube applications. It enables loose coupling between components and makes your application more maintainable and testable.
|
|
28
31
|
|
|
29
32
|
## <a name="documentation">📖 Documentation</a>
|
|
30
|
-
|
|
33
|
+
|
|
34
|
+
Comprehensive documentation is available at [vercube.dev](https://vercube.dev). There you'll find detailed module descriptions, project information, guides, and everything else you need to know about Vercube.
|
package/dist/index.mjs
CHANGED
|
@@ -28,243 +28,6 @@ var BaseDecorator = class {
|
|
|
28
28
|
destroyed() {}
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
//#endregion
|
|
32
|
-
//#region src/Types/IOCTypes.ts
|
|
33
|
-
let IOC;
|
|
34
|
-
(function(_IOC) {
|
|
35
|
-
let ServiceFactoryType = /* @__PURE__ */ function(ServiceFactoryType$1) {
|
|
36
|
-
ServiceFactoryType$1["CLASS"] = "CLASS";
|
|
37
|
-
ServiceFactoryType$1["CLASS_SINGLETON"] = "CLASS_SINGLETON";
|
|
38
|
-
ServiceFactoryType$1["INSTANCE"] = "INSTANCE";
|
|
39
|
-
return ServiceFactoryType$1;
|
|
40
|
-
}({});
|
|
41
|
-
_IOC.ServiceFactoryType = ServiceFactoryType;
|
|
42
|
-
let InjectMethod = /* @__PURE__ */ function(InjectMethod$1) {
|
|
43
|
-
InjectMethod$1["LAZY"] = "LAZY";
|
|
44
|
-
InjectMethod$1["STATIC"] = "STATIC";
|
|
45
|
-
return InjectMethod$1;
|
|
46
|
-
}({});
|
|
47
|
-
_IOC.InjectMethod = InjectMethod;
|
|
48
|
-
let DependencyType = /* @__PURE__ */ function(DependencyType$1) {
|
|
49
|
-
DependencyType$1[DependencyType$1["STANDARD"] = 0] = "STANDARD";
|
|
50
|
-
DependencyType$1[DependencyType$1["OPTIONAL"] = 1] = "OPTIONAL";
|
|
51
|
-
return DependencyType$1;
|
|
52
|
-
}({});
|
|
53
|
-
_IOC.DependencyType = DependencyType;
|
|
54
|
-
})(IOC || (IOC = {}));
|
|
55
|
-
|
|
56
|
-
//#endregion
|
|
57
|
-
//#region src/Domain/Engine.ts
|
|
58
|
-
/**
|
|
59
|
-
* This map holds metadata for ALL classes in system along with their dependencies. Original idea was
|
|
60
|
-
* to store those informations in object prototype, but accessing this map is blazing fast with Map
|
|
61
|
-
* container (<1ms).
|
|
62
|
-
*/
|
|
63
|
-
const classMap = /* @__PURE__ */ new Map();
|
|
64
|
-
const ROOT_PROTO = Object.getPrototypeOf({});
|
|
65
|
-
/**
|
|
66
|
-
* This method registers @Inject() in particular class.
|
|
67
|
-
* @param prototype class prototype for which we register @Inject()
|
|
68
|
-
* @param propertyName name of property that is inejcted
|
|
69
|
-
* @param dependency what we should inject there
|
|
70
|
-
* @param type type of dependency (standard or optional dependency)
|
|
71
|
-
*/
|
|
72
|
-
function registerInject(prototype, propertyName, dependency, type) {
|
|
73
|
-
let entry = classMap.get(prototype);
|
|
74
|
-
if (!entry) {
|
|
75
|
-
const newEntry = { deps: [] };
|
|
76
|
-
entry = newEntry;
|
|
77
|
-
classMap.set(prototype, entry);
|
|
78
|
-
}
|
|
79
|
-
const newDep = {
|
|
80
|
-
propertyName,
|
|
81
|
-
dependency,
|
|
82
|
-
type
|
|
83
|
-
};
|
|
84
|
-
entry.deps.push(newDep);
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Returns classmap entry for particular class. It holds information about @Injects for this particular class.
|
|
88
|
-
* @param classType type of class to check
|
|
89
|
-
* @returns class map entry or null if cannot be found
|
|
90
|
-
*/
|
|
91
|
-
function getEntryForClass(classType) {
|
|
92
|
-
const entry = classMap.get(classType.prototype);
|
|
93
|
-
return entry === void 0 ? null : entry;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Returns array of dependencies for particular class instance.
|
|
97
|
-
* @param instance class instance
|
|
98
|
-
* @returns array of @Inject dependencies defined for this class
|
|
99
|
-
*/
|
|
100
|
-
function getDeps(instance) {
|
|
101
|
-
const prototype = Object.getPrototypeOf(instance);
|
|
102
|
-
if (!prototype) return [];
|
|
103
|
-
const entry = classMap.get(prototype);
|
|
104
|
-
return entry !== void 0 && entry.deps !== void 0 ? entry.deps : [];
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* This method injects stuff into class, using container passed as first argument. We need container as
|
|
108
|
-
* inject execution is always context based.
|
|
109
|
-
* @param container container instance that is providing dependencies
|
|
110
|
-
* @param instance class instance to inject
|
|
111
|
-
* @param method inject method, "lazy" queries dep during property access while "static" injects during class creation
|
|
112
|
-
*/
|
|
113
|
-
function injectDeps(container, instance, method) {
|
|
114
|
-
let prototype = Object.getPrototypeOf(instance);
|
|
115
|
-
if (!prototype) return;
|
|
116
|
-
/**
|
|
117
|
-
* Here we will traverse through prototype chain until we hit dead end (ROOT_PROTO). This is because we
|
|
118
|
-
* must process inject for current class and also for every base class.
|
|
119
|
-
*
|
|
120
|
-
* So we will use "do" loop to iterate full prototype chain.
|
|
121
|
-
*/
|
|
122
|
-
do {
|
|
123
|
-
const entry = classMap.get(prototype);
|
|
124
|
-
if (entry) for (const iter of entry.deps) {
|
|
125
|
-
const propertyName = iter.propertyName;
|
|
126
|
-
const dependency = iter.dependency;
|
|
127
|
-
const type = iter.type;
|
|
128
|
-
if (Object.prototype.hasOwnProperty.call(instance, propertyName) && instance[propertyName] !== void 0) continue;
|
|
129
|
-
if (type === IOC.DependencyType.OPTIONAL) {
|
|
130
|
-
Object.defineProperty(instance, propertyName, { get: function() {
|
|
131
|
-
return container.getOptional(dependency);
|
|
132
|
-
} });
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
switch (method) {
|
|
136
|
-
case IOC.InjectMethod.LAZY: {
|
|
137
|
-
Object.defineProperty(instance, propertyName, { get: function() {
|
|
138
|
-
return container.get(dependency);
|
|
139
|
-
} });
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
case IOC.InjectMethod.STATIC: {
|
|
143
|
-
instance[propertyName] = container.get(dependency);
|
|
144
|
-
break;
|
|
145
|
-
}
|
|
146
|
-
default: throw new Error(`IOCEngine.injectDeps() - invalid inject method ${method}`);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
prototype = Object.getPrototypeOf(prototype);
|
|
150
|
-
} while (prototype && prototype !== ROOT_PROTO);
|
|
151
|
-
}
|
|
152
|
-
const IOCEngine = {
|
|
153
|
-
registerInject,
|
|
154
|
-
getEntryForClass,
|
|
155
|
-
injectDeps,
|
|
156
|
-
getDeps
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
//#endregion
|
|
160
|
-
//#region src/Decorators/Inject.ts
|
|
161
|
-
/**
|
|
162
|
-
* Injects a dependency with particular key to service.
|
|
163
|
-
* @param key key to inject
|
|
164
|
-
* @returns decorator
|
|
165
|
-
*/
|
|
166
|
-
function Inject(key) {
|
|
167
|
-
return (target, propertyName) => {
|
|
168
|
-
IOCEngine.registerInject(target, propertyName, key, IOC.DependencyType.STANDARD);
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
//#endregion
|
|
173
|
-
//#region src/Decorators/InjectOptional.ts
|
|
174
|
-
/**
|
|
175
|
-
* Injects a dependency with particular key to service.
|
|
176
|
-
* @param key key to inject
|
|
177
|
-
* @returns decorator
|
|
178
|
-
*/
|
|
179
|
-
function InjectOptional(key) {
|
|
180
|
-
return (target, propertyName) => {
|
|
181
|
-
IOCEngine.registerInject(target, propertyName, key, IOC.DependencyType.OPTIONAL);
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
//#endregion
|
|
186
|
-
//#region src/Decorators/Init.ts
|
|
187
|
-
/**
|
|
188
|
-
* This decorator fires the decorated function as soon as decorators are injected. You
|
|
189
|
-
* can use this for initialization logic in runtime-loaded container deps.
|
|
190
|
-
*/
|
|
191
|
-
var InitDecorator = class extends BaseDecorator {
|
|
192
|
-
/**
|
|
193
|
-
* Called when decorator is initialized.
|
|
194
|
-
*/
|
|
195
|
-
created() {
|
|
196
|
-
if (typeof this.instance[this.propertyName] === "function") this.instance[this.propertyName]();
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
/**
|
|
200
|
-
* Decorator that automatically executes the decorated method when dependencies are injected.
|
|
201
|
-
* Use this decorator to run initialization logic for runtime-loaded container dependencies.
|
|
202
|
-
* @returns {Function} Decorator function that creates an InitDecorator instance
|
|
203
|
-
*/
|
|
204
|
-
function Init() {
|
|
205
|
-
return createDecorator(InitDecorator, {});
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
//#endregion
|
|
209
|
-
//#region src/Decorators/Destroy.ts
|
|
210
|
-
/**
|
|
211
|
-
* Decorator that handles cleanup tasks when a service or component is destroyed.
|
|
212
|
-
* This decorator class extends BaseDecorator and executes the decorated method
|
|
213
|
-
* during the destruction phase.
|
|
214
|
-
*/
|
|
215
|
-
var DestroyDecorator = class extends BaseDecorator {
|
|
216
|
-
/**
|
|
217
|
-
* Called when decorator is destroyed. Executes the decorated method if it exists
|
|
218
|
-
* as a function on the instance. Used for cleanup tasks like unregistering
|
|
219
|
-
* listeners or clearing timers.
|
|
220
|
-
*/
|
|
221
|
-
destroyed() {
|
|
222
|
-
if (typeof this.instance[this.propertyName] === "function") this.instance[this.propertyName]();
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
/**
|
|
226
|
-
* Decorator that automatically executes the decorated method when the service or component
|
|
227
|
-
* is destroyed. Use this decorator to run cleanup logic like unregistering event listeners
|
|
228
|
-
* or clearing timers.
|
|
229
|
-
*
|
|
230
|
-
* @example
|
|
231
|
-
* ```typescript
|
|
232
|
-
* class MyService {
|
|
233
|
-
* @Destroy()
|
|
234
|
-
* cleanup() {
|
|
235
|
-
* // Cleanup logic here
|
|
236
|
-
* }
|
|
237
|
-
* }
|
|
238
|
-
* ```
|
|
239
|
-
* @returns {Function} Decorator function that creates a DestroyDecorator instance
|
|
240
|
-
*/
|
|
241
|
-
function Destroy() {
|
|
242
|
-
return createDecorator(DestroyDecorator, {});
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
//#endregion
|
|
246
|
-
//#region src/Domain/ContainerEvents.ts
|
|
247
|
-
/**
|
|
248
|
-
* This class allows for container to listen on various IOC events.
|
|
249
|
-
*/
|
|
250
|
-
var ContainerEvents = class {
|
|
251
|
-
fOnExpanded = [];
|
|
252
|
-
/**
|
|
253
|
-
* Registers to container "onExpanded" event.
|
|
254
|
-
* @param handler event handler
|
|
255
|
-
*/
|
|
256
|
-
onExpanded(handler) {
|
|
257
|
-
this.fOnExpanded.push(handler);
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Calls on expanded event.
|
|
261
|
-
* @param serviceKeys key of service we have installed
|
|
262
|
-
*/
|
|
263
|
-
callOnExpanded(serviceKeys) {
|
|
264
|
-
for (const handler of this.fOnExpanded) handler(serviceKeys);
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
|
|
268
31
|
//#endregion
|
|
269
32
|
//#region src/Utils/Utils.ts
|
|
270
33
|
/**
|
|
@@ -368,6 +131,29 @@ function destroyContainer(container) {
|
|
|
368
131
|
containerMap.delete(container);
|
|
369
132
|
}
|
|
370
133
|
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/Domain/ContainerEvents.ts
|
|
136
|
+
/**
|
|
137
|
+
* This class allows for container to listen on various IOC events.
|
|
138
|
+
*/
|
|
139
|
+
var ContainerEvents = class {
|
|
140
|
+
fOnExpanded = [];
|
|
141
|
+
/**
|
|
142
|
+
* Registers to container "onExpanded" event.
|
|
143
|
+
* @param handler event handler
|
|
144
|
+
*/
|
|
145
|
+
onExpanded(handler) {
|
|
146
|
+
this.fOnExpanded.push(handler);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Calls on expanded event.
|
|
150
|
+
* @param serviceKeys key of service we have installed
|
|
151
|
+
*/
|
|
152
|
+
callOnExpanded(serviceKeys) {
|
|
153
|
+
for (const handler of this.fOnExpanded) handler(serviceKeys);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
371
157
|
//#endregion
|
|
372
158
|
//#region src/Domain/Container.ts
|
|
373
159
|
/**
|
|
@@ -604,7 +390,7 @@ var Container = class Container {
|
|
|
604
390
|
internalResolve(serviceDef) {
|
|
605
391
|
switch (serviceDef.type) {
|
|
606
392
|
case IOC.ServiceFactoryType.INSTANCE: return serviceDef.serviceValue;
|
|
607
|
-
case IOC.ServiceFactoryType.CLASS_SINGLETON:
|
|
393
|
+
case IOC.ServiceFactoryType.CLASS_SINGLETON:
|
|
608
394
|
if (!this.fSingletonInstances.has(serviceDef.serviceKey)) {
|
|
609
395
|
const constructor = serviceDef.serviceValue;
|
|
610
396
|
const instance = new constructor();
|
|
@@ -613,7 +399,6 @@ var Container = class Container {
|
|
|
613
399
|
return instance;
|
|
614
400
|
}
|
|
615
401
|
return this.fSingletonInstances.get(serviceDef.serviceKey);
|
|
616
|
-
}
|
|
617
402
|
case IOC.ServiceFactoryType.CLASS: {
|
|
618
403
|
const constructor = serviceDef.serviceValue;
|
|
619
404
|
const instance = new constructor();
|
|
@@ -659,10 +444,9 @@ var Container = class Container {
|
|
|
659
444
|
*/
|
|
660
445
|
internalDispose(def) {
|
|
661
446
|
switch (def.type) {
|
|
662
|
-
case IOC.ServiceFactoryType.INSTANCE:
|
|
447
|
+
case IOC.ServiceFactoryType.INSTANCE:
|
|
663
448
|
destroyDecorators(def.serviceValue, this);
|
|
664
449
|
break;
|
|
665
|
-
}
|
|
666
450
|
case IOC.ServiceFactoryType.CLASS_SINGLETON: {
|
|
667
451
|
const existingInstance = this.fSingletonInstances.get(def.serviceKey);
|
|
668
452
|
if (existingInstance) {
|
|
@@ -688,5 +472,217 @@ var Container = class Container {
|
|
|
688
472
|
}
|
|
689
473
|
};
|
|
690
474
|
|
|
475
|
+
//#endregion
|
|
476
|
+
//#region src/Types/IOCTypes.ts
|
|
477
|
+
let IOC;
|
|
478
|
+
(function(_IOC) {
|
|
479
|
+
let ServiceFactoryType = /* @__PURE__ */ function(ServiceFactoryType$1) {
|
|
480
|
+
ServiceFactoryType$1["CLASS"] = "CLASS";
|
|
481
|
+
ServiceFactoryType$1["CLASS_SINGLETON"] = "CLASS_SINGLETON";
|
|
482
|
+
ServiceFactoryType$1["INSTANCE"] = "INSTANCE";
|
|
483
|
+
return ServiceFactoryType$1;
|
|
484
|
+
}({});
|
|
485
|
+
_IOC.ServiceFactoryType = ServiceFactoryType;
|
|
486
|
+
let InjectMethod = /* @__PURE__ */ function(InjectMethod$1) {
|
|
487
|
+
InjectMethod$1["LAZY"] = "LAZY";
|
|
488
|
+
InjectMethod$1["STATIC"] = "STATIC";
|
|
489
|
+
return InjectMethod$1;
|
|
490
|
+
}({});
|
|
491
|
+
_IOC.InjectMethod = InjectMethod;
|
|
492
|
+
let DependencyType = /* @__PURE__ */ function(DependencyType$1) {
|
|
493
|
+
DependencyType$1[DependencyType$1["STANDARD"] = 0] = "STANDARD";
|
|
494
|
+
DependencyType$1[DependencyType$1["OPTIONAL"] = 1] = "OPTIONAL";
|
|
495
|
+
return DependencyType$1;
|
|
496
|
+
}({});
|
|
497
|
+
_IOC.DependencyType = DependencyType;
|
|
498
|
+
})(IOC || (IOC = {}));
|
|
499
|
+
|
|
500
|
+
//#endregion
|
|
501
|
+
//#region src/Domain/Engine.ts
|
|
502
|
+
/**
|
|
503
|
+
* This map holds metadata for ALL classes in system along with their dependencies. Original idea was
|
|
504
|
+
* to store those informations in object prototype, but accessing this map is blazing fast with Map
|
|
505
|
+
* container (<1ms).
|
|
506
|
+
*/
|
|
507
|
+
const classMap = /* @__PURE__ */ new Map();
|
|
508
|
+
const ROOT_PROTO = Object.getPrototypeOf({});
|
|
509
|
+
/**
|
|
510
|
+
* This method registers @Inject() in particular class.
|
|
511
|
+
* @param prototype class prototype for which we register @Inject()
|
|
512
|
+
* @param propertyName name of property that is inejcted
|
|
513
|
+
* @param dependency what we should inject there
|
|
514
|
+
* @param type type of dependency (standard or optional dependency)
|
|
515
|
+
*/
|
|
516
|
+
function registerInject(prototype, propertyName, dependency, type) {
|
|
517
|
+
let entry = classMap.get(prototype);
|
|
518
|
+
if (!entry) {
|
|
519
|
+
const newEntry = { deps: [] };
|
|
520
|
+
entry = newEntry;
|
|
521
|
+
classMap.set(prototype, entry);
|
|
522
|
+
}
|
|
523
|
+
const newDep = {
|
|
524
|
+
propertyName,
|
|
525
|
+
dependency,
|
|
526
|
+
type
|
|
527
|
+
};
|
|
528
|
+
entry.deps.push(newDep);
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Returns classmap entry for particular class. It holds information about @Injects for this particular class.
|
|
532
|
+
* @param classType type of class to check
|
|
533
|
+
* @returns class map entry or null if cannot be found
|
|
534
|
+
*/
|
|
535
|
+
function getEntryForClass(classType) {
|
|
536
|
+
const entry = classMap.get(classType.prototype);
|
|
537
|
+
return entry === void 0 ? null : entry;
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Returns array of dependencies for particular class instance.
|
|
541
|
+
* @param instance class instance
|
|
542
|
+
* @returns array of @Inject dependencies defined for this class
|
|
543
|
+
*/
|
|
544
|
+
function getDeps(instance) {
|
|
545
|
+
const prototype = Object.getPrototypeOf(instance);
|
|
546
|
+
if (!prototype) return [];
|
|
547
|
+
const entry = classMap.get(prototype);
|
|
548
|
+
return entry !== void 0 && entry.deps !== void 0 ? entry.deps : [];
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* This method injects stuff into class, using container passed as first argument. We need container as
|
|
552
|
+
* inject execution is always context based.
|
|
553
|
+
* @param container container instance that is providing dependencies
|
|
554
|
+
* @param instance class instance to inject
|
|
555
|
+
* @param method inject method, "lazy" queries dep during property access while "static" injects during class creation
|
|
556
|
+
*/
|
|
557
|
+
function injectDeps(container, instance, method) {
|
|
558
|
+
let prototype = Object.getPrototypeOf(instance);
|
|
559
|
+
if (!prototype) return;
|
|
560
|
+
/**
|
|
561
|
+
* Here we will traverse through prototype chain until we hit dead end (ROOT_PROTO). This is because we
|
|
562
|
+
* must process inject for current class and also for every base class.
|
|
563
|
+
*
|
|
564
|
+
* So we will use "do" loop to iterate full prototype chain.
|
|
565
|
+
*/
|
|
566
|
+
do {
|
|
567
|
+
const entry = classMap.get(prototype);
|
|
568
|
+
if (entry) for (const iter of entry.deps) {
|
|
569
|
+
const propertyName = iter.propertyName;
|
|
570
|
+
const dependency = iter.dependency;
|
|
571
|
+
const type = iter.type;
|
|
572
|
+
if (Object.prototype.hasOwnProperty.call(instance, propertyName) && instance[propertyName] !== void 0) continue;
|
|
573
|
+
if (type === IOC.DependencyType.OPTIONAL) {
|
|
574
|
+
Object.defineProperty(instance, propertyName, { get: function() {
|
|
575
|
+
return container.getOptional(dependency);
|
|
576
|
+
} });
|
|
577
|
+
continue;
|
|
578
|
+
}
|
|
579
|
+
switch (method) {
|
|
580
|
+
case IOC.InjectMethod.LAZY:
|
|
581
|
+
Object.defineProperty(instance, propertyName, { get: function() {
|
|
582
|
+
return container.get(dependency);
|
|
583
|
+
} });
|
|
584
|
+
break;
|
|
585
|
+
case IOC.InjectMethod.STATIC:
|
|
586
|
+
instance[propertyName] = container.get(dependency);
|
|
587
|
+
break;
|
|
588
|
+
default: throw new Error(`IOCEngine.injectDeps() - invalid inject method ${method}`);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
592
|
+
} while (prototype && prototype !== ROOT_PROTO);
|
|
593
|
+
}
|
|
594
|
+
const IOCEngine = {
|
|
595
|
+
registerInject,
|
|
596
|
+
getEntryForClass,
|
|
597
|
+
injectDeps,
|
|
598
|
+
getDeps
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
//#endregion
|
|
602
|
+
//#region src/Decorators/Inject.ts
|
|
603
|
+
/**
|
|
604
|
+
* Injects a dependency with particular key to service.
|
|
605
|
+
* @param key key to inject
|
|
606
|
+
* @returns decorator
|
|
607
|
+
*/
|
|
608
|
+
function Inject(key) {
|
|
609
|
+
return (target, propertyName) => {
|
|
610
|
+
IOCEngine.registerInject(target, propertyName, key, IOC.DependencyType.STANDARD);
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
//#endregion
|
|
615
|
+
//#region src/Decorators/InjectOptional.ts
|
|
616
|
+
/**
|
|
617
|
+
* Injects a dependency with particular key to service.
|
|
618
|
+
* @param key key to inject
|
|
619
|
+
* @returns decorator
|
|
620
|
+
*/
|
|
621
|
+
function InjectOptional(key) {
|
|
622
|
+
return (target, propertyName) => {
|
|
623
|
+
IOCEngine.registerInject(target, propertyName, key, IOC.DependencyType.OPTIONAL);
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
//#endregion
|
|
628
|
+
//#region src/Decorators/Init.ts
|
|
629
|
+
/**
|
|
630
|
+
* This decorator fires the decorated function as soon as decorators are injected. You
|
|
631
|
+
* can use this for initialization logic in runtime-loaded container deps.
|
|
632
|
+
*/
|
|
633
|
+
var InitDecorator = class extends BaseDecorator {
|
|
634
|
+
/**
|
|
635
|
+
* Called when decorator is initialized.
|
|
636
|
+
*/
|
|
637
|
+
created() {
|
|
638
|
+
if (typeof this.instance[this.propertyName] === "function") this.instance[this.propertyName]();
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
/**
|
|
642
|
+
* Decorator that automatically executes the decorated method when dependencies are injected.
|
|
643
|
+
* Use this decorator to run initialization logic for runtime-loaded container dependencies.
|
|
644
|
+
* @returns {Function} Decorator function that creates an InitDecorator instance
|
|
645
|
+
*/
|
|
646
|
+
function Init() {
|
|
647
|
+
return createDecorator(InitDecorator, {});
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
//#endregion
|
|
651
|
+
//#region src/Decorators/Destroy.ts
|
|
652
|
+
/**
|
|
653
|
+
* Decorator that handles cleanup tasks when a service or component is destroyed.
|
|
654
|
+
* This decorator class extends BaseDecorator and executes the decorated method
|
|
655
|
+
* during the destruction phase.
|
|
656
|
+
*/
|
|
657
|
+
var DestroyDecorator = class extends BaseDecorator {
|
|
658
|
+
/**
|
|
659
|
+
* Called when decorator is destroyed. Executes the decorated method if it exists
|
|
660
|
+
* as a function on the instance. Used for cleanup tasks like unregistering
|
|
661
|
+
* listeners or clearing timers.
|
|
662
|
+
*/
|
|
663
|
+
destroyed() {
|
|
664
|
+
if (typeof this.instance[this.propertyName] === "function") this.instance[this.propertyName]();
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
/**
|
|
668
|
+
* Decorator that automatically executes the decorated method when the service or component
|
|
669
|
+
* is destroyed. Use this decorator to run cleanup logic like unregistering event listeners
|
|
670
|
+
* or clearing timers.
|
|
671
|
+
*
|
|
672
|
+
* @example
|
|
673
|
+
* ```typescript
|
|
674
|
+
* class MyService {
|
|
675
|
+
* @Destroy()
|
|
676
|
+
* cleanup() {
|
|
677
|
+
* // Cleanup logic here
|
|
678
|
+
* }
|
|
679
|
+
* }
|
|
680
|
+
* ```
|
|
681
|
+
* @returns {Function} Decorator function that creates a DestroyDecorator instance
|
|
682
|
+
*/
|
|
683
|
+
function Destroy() {
|
|
684
|
+
return createDecorator(DestroyDecorator, {});
|
|
685
|
+
}
|
|
686
|
+
|
|
691
687
|
//#endregion
|
|
692
688
|
export { BaseDecorator, Container, Destroy, IOC, Identity, Init, Inject, InjectOptional, createDecorator, destroyContainer, destroyDecorators, initializeContainer, initializeDecorators };
|