@vercube/di 1.1.7 → 1.2.1
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/dist/index.d.mts +110 -1
- package/dist/index.mjs +78 -20
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -72,6 +72,17 @@ declare class Container {
|
|
|
72
72
|
* @returns {Array} array of service keys
|
|
73
73
|
*/
|
|
74
74
|
get servicesKeys(): IOC.ServiceKey[];
|
|
75
|
+
/**
|
|
76
|
+
* Returns a read-only view of all service definitions without instantiating them.
|
|
77
|
+
* @returns {ReadonlyMap} map of service key to its definition
|
|
78
|
+
*/
|
|
79
|
+
get services(): ReadonlyMap<IOC.ServiceKey, Readonly<IOC.ServiceDef>>;
|
|
80
|
+
/**
|
|
81
|
+
* Checks whether a singleton instance for a given key has already been constructed.
|
|
82
|
+
* @param key service key to check
|
|
83
|
+
* @returns {boolean} true when a singleton instance already exists
|
|
84
|
+
*/
|
|
85
|
+
hasInstance(key: IOC.ServiceKey): boolean;
|
|
75
86
|
/**
|
|
76
87
|
* Returns events handler.
|
|
77
88
|
*/
|
|
@@ -189,6 +200,13 @@ declare class Container {
|
|
|
189
200
|
* @returns class instance
|
|
190
201
|
*/
|
|
191
202
|
protected internalResolve(serviceDef: IOC.ServiceDef): IOC.Instance;
|
|
203
|
+
/**
|
|
204
|
+
* Constructs a new instance for a service def and injects its dependencies.
|
|
205
|
+
* @param serviceDef service def to construct
|
|
206
|
+
* @param singleton whether resulting instance should be cached as a singleton
|
|
207
|
+
* @returns newly created class instance
|
|
208
|
+
*/
|
|
209
|
+
protected internalConstruct(serviceDef: IOC.ServiceDef, singleton: boolean): IOC.Instance;
|
|
192
210
|
/**
|
|
193
211
|
* Internally inject deps for particular class..
|
|
194
212
|
* @param instance instance to inject
|
|
@@ -366,6 +384,97 @@ declare function Destroy(): Function;
|
|
|
366
384
|
*/
|
|
367
385
|
declare function Injectable(): ClassDecorator;
|
|
368
386
|
//#endregion
|
|
387
|
+
//#region src/Domain/DevtoolsHook.d.ts
|
|
388
|
+
/**
|
|
389
|
+
* Global property name for the IOC devtools hook.
|
|
390
|
+
*/
|
|
391
|
+
declare const IOC_DEVTOOLS_HOOK_KEY = "__VERCUBE_DEVTOOLS_HOOK__";
|
|
392
|
+
/**
|
|
393
|
+
* A single service resolution record emitted when the container constructs an instance.
|
|
394
|
+
*/
|
|
395
|
+
interface IOCResolveRecord {
|
|
396
|
+
/** Service key that was resolved. */
|
|
397
|
+
key: IOC.ServiceKey;
|
|
398
|
+
/** Human readable name of the service key. */
|
|
399
|
+
name: string;
|
|
400
|
+
/** Factory type used to build the instance. */
|
|
401
|
+
type: IOC.ServiceFactoryType;
|
|
402
|
+
/** Context of the container that performed the resolution. */
|
|
403
|
+
context: string | undefined;
|
|
404
|
+
/** Timestamp (ms) before construction. */
|
|
405
|
+
start: number;
|
|
406
|
+
/** Timestamp (ms) after construction and injection. */
|
|
407
|
+
end: number;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Optional hook for observing the IOC container.
|
|
411
|
+
*/
|
|
412
|
+
interface IOCDevtoolsHook {
|
|
413
|
+
/** Called once for every {@link Container} instance after construction. */
|
|
414
|
+
onContainerCreated?: (container: Container) => void;
|
|
415
|
+
/** Called whenever the container constructs a new service instance. */
|
|
416
|
+
onResolved?: (record: IOCResolveRecord) => void;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Installs or replaces the devtools hook.
|
|
420
|
+
* @param hook hook implementation, or `undefined` to uninstall
|
|
421
|
+
*/
|
|
422
|
+
declare function setIOCDevtoolsHook(hook: IOCDevtoolsHook | undefined): void;
|
|
423
|
+
/**
|
|
424
|
+
* Returns the currently installed devtools hook, if any.
|
|
425
|
+
*/
|
|
426
|
+
declare function getIOCDevtoolsHook(): IOCDevtoolsHook | undefined;
|
|
427
|
+
//#endregion
|
|
428
|
+
//#region src/Domain/Engine.d.ts
|
|
429
|
+
/**
|
|
430
|
+
* This is a struct that holds information about class dependency - what dependency, which field to inject,etc.
|
|
431
|
+
*/
|
|
432
|
+
interface IClassDep {
|
|
433
|
+
propertyName: string;
|
|
434
|
+
dependency: IOC.ServiceKey;
|
|
435
|
+
type: IOC.DependencyType;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* This holds single "metadata" entry for particular class. It holds all @Inject stuff for class.
|
|
439
|
+
*/
|
|
440
|
+
interface IClassMapEntry {
|
|
441
|
+
deps: IClassDep[];
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* This method registers @Inject() in particular class.
|
|
445
|
+
* @param prototype class prototype for which we register @Inject()
|
|
446
|
+
* @param propertyName name of property that is inejcted
|
|
447
|
+
* @param dependency what we should inject there
|
|
448
|
+
* @param type type of dependency (standard or optional dependency)
|
|
449
|
+
*/
|
|
450
|
+
declare function registerInject(prototype: IOC.Prototype, propertyName: string, dependency: IOC.ServiceKey, type: IOC.DependencyType): void;
|
|
451
|
+
/**
|
|
452
|
+
* Returns classmap entry for particular class. It holds information about @Injects for this particular class.
|
|
453
|
+
* @param classType type of class to check
|
|
454
|
+
* @returns class map entry or null if cannot be found
|
|
455
|
+
*/
|
|
456
|
+
declare function getEntryForClass(classType: IOC.Newable<unknown>): IClassMapEntry | null;
|
|
457
|
+
/**
|
|
458
|
+
* Returns array of dependencies for particular class instance.
|
|
459
|
+
* @param instance class instance
|
|
460
|
+
* @returns array of @Inject dependencies defined for this class
|
|
461
|
+
*/
|
|
462
|
+
declare function getDeps(instance: IOC.Instance): IClassDep[];
|
|
463
|
+
/**
|
|
464
|
+
* This method injects stuff into class, using container passed as first argument. We need container as
|
|
465
|
+
* inject execution is always context based.
|
|
466
|
+
* @param container container instance that is providing dependencies
|
|
467
|
+
* @param instance class instance to inject
|
|
468
|
+
* @param method inject method, "lazy" queries dep during property access while "static" injects during class creation
|
|
469
|
+
*/
|
|
470
|
+
declare function injectDeps(container: Container, instance: IOC.Instance, method: IOC.InjectMethod): void;
|
|
471
|
+
declare const IOCEngine: {
|
|
472
|
+
registerInject: typeof registerInject;
|
|
473
|
+
getEntryForClass: typeof getEntryForClass;
|
|
474
|
+
injectDeps: typeof injectDeps;
|
|
475
|
+
getDeps: typeof getDeps;
|
|
476
|
+
};
|
|
477
|
+
//#endregion
|
|
369
478
|
//#region src/Utils/Utils.d.ts
|
|
370
479
|
/**
|
|
371
480
|
* This function generates new service key for particular service. Providing
|
|
@@ -441,4 +550,4 @@ declare function initializeContainer(container: Container): void;
|
|
|
441
550
|
*/
|
|
442
551
|
declare function destroyContainer(container: Container): void;
|
|
443
552
|
//#endregion
|
|
444
|
-
export { BaseDecorator, Container, Destroy, IClassType, IDecoratedInstance, IDecoratedPrototype, IDecoratorEntry, IOC, Identity, Init, Inject, InjectOptional, Injectable, createDecorator, destroyContainer, destroyDecorators, initializeContainer, initializeDecorators };
|
|
553
|
+
export { BaseDecorator, Container, ContainerEvents, Destroy, type IClassDep, type IClassMapEntry, IClassType, IDecoratedInstance, IDecoratedPrototype, IDecoratorEntry, IOC, IOCDevtoolsHook, IOCEngine, IOCResolveRecord, IOC_DEVTOOLS_HOOK_KEY, Identity, Init, Inject, InjectOptional, Injectable, OnExpandedEvent, createDecorator, destroyContainer, destroyDecorators, getIOCDevtoolsHook, initializeContainer, initializeDecorators, setIOCDevtoolsHook };
|
package/dist/index.mjs
CHANGED
|
@@ -152,6 +152,27 @@ var ContainerEvents = class {
|
|
|
152
152
|
}
|
|
153
153
|
};
|
|
154
154
|
//#endregion
|
|
155
|
+
//#region src/Domain/DevtoolsHook.ts
|
|
156
|
+
/**
|
|
157
|
+
* Global property name for the IOC devtools hook.
|
|
158
|
+
*/
|
|
159
|
+
const IOC_DEVTOOLS_HOOK_KEY = "__VERCUBE_DEVTOOLS_HOOK__";
|
|
160
|
+
let devtoolsHook = globalThis[IOC_DEVTOOLS_HOOK_KEY];
|
|
161
|
+
/**
|
|
162
|
+
* Installs or replaces the devtools hook.
|
|
163
|
+
* @param hook hook implementation, or `undefined` to uninstall
|
|
164
|
+
*/
|
|
165
|
+
function setIOCDevtoolsHook(hook) {
|
|
166
|
+
devtoolsHook = hook;
|
|
167
|
+
globalThis[IOC_DEVTOOLS_HOOK_KEY] = hook;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Returns the currently installed devtools hook, if any.
|
|
171
|
+
*/
|
|
172
|
+
function getIOCDevtoolsHook() {
|
|
173
|
+
return devtoolsHook;
|
|
174
|
+
}
|
|
175
|
+
//#endregion
|
|
155
176
|
//#region src/Domain/Container.ts
|
|
156
177
|
/**
|
|
157
178
|
* This is new implementation of IOC Container. It mimics Inversify.js container a little bit but its
|
|
@@ -180,6 +201,7 @@ var Container = class Container {
|
|
|
180
201
|
this.fDefaultParams = Object.assign(this.fDefaultParams, params);
|
|
181
202
|
this.fInjectMethod = params?.injectMethod ?? IOC.InjectMethod.STATIC;
|
|
182
203
|
this.bindInstance(Container, this);
|
|
204
|
+
getIOCDevtoolsHook()?.onContainerCreated?.(this);
|
|
183
205
|
}
|
|
184
206
|
/**
|
|
185
207
|
* Returns array of all service keys. This basically returns keys from all .bindXXX calls.
|
|
@@ -189,6 +211,21 @@ var Container = class Container {
|
|
|
189
211
|
return [...this.fServices.keys()];
|
|
190
212
|
}
|
|
191
213
|
/**
|
|
214
|
+
* Returns a read-only view of all service definitions without instantiating them.
|
|
215
|
+
* @returns {ReadonlyMap} map of service key to its definition
|
|
216
|
+
*/
|
|
217
|
+
get services() {
|
|
218
|
+
return this.fServices;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Checks whether a singleton instance for a given key has already been constructed.
|
|
222
|
+
* @param key service key to check
|
|
223
|
+
* @returns {boolean} true when a singleton instance already exists
|
|
224
|
+
*/
|
|
225
|
+
hasInstance(key) {
|
|
226
|
+
return this.fSingletonInstances.has(key);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
192
229
|
* Returns events handler.
|
|
193
230
|
*/
|
|
194
231
|
get events() {
|
|
@@ -377,7 +414,10 @@ var Container = class Container {
|
|
|
377
414
|
*/
|
|
378
415
|
internalGet(key, parent) {
|
|
379
416
|
const serviceDef = this.fServices.get(key);
|
|
380
|
-
if (!serviceDef)
|
|
417
|
+
if (!serviceDef) {
|
|
418
|
+
const owner = parent?.constructor?.name;
|
|
419
|
+
throw new Error(`Unresolved dependency for [${this.getKeyDescription(key)}]${owner ? ` required by [${owner}]` : ""}`);
|
|
420
|
+
}
|
|
381
421
|
return this.internalResolve(serviceDef);
|
|
382
422
|
}
|
|
383
423
|
/**
|
|
@@ -400,24 +440,41 @@ var Container = class Container {
|
|
|
400
440
|
switch (serviceDef.type) {
|
|
401
441
|
case IOC.ServiceFactoryType.INSTANCE: return serviceDef.serviceValue;
|
|
402
442
|
case IOC.ServiceFactoryType.CLASS_SINGLETON:
|
|
403
|
-
if (!this.fSingletonInstances.has(serviceDef.serviceKey))
|
|
404
|
-
const constructor = serviceDef.serviceValue;
|
|
405
|
-
const instance = new constructor();
|
|
406
|
-
this.fSingletonInstances.set(serviceDef.serviceKey, instance);
|
|
407
|
-
this.internalProcessInjects(instance, this.fInjectMethod);
|
|
408
|
-
return instance;
|
|
409
|
-
}
|
|
443
|
+
if (!this.fSingletonInstances.has(serviceDef.serviceKey)) return this.internalConstruct(serviceDef, true);
|
|
410
444
|
return this.fSingletonInstances.get(serviceDef.serviceKey);
|
|
411
|
-
case IOC.ServiceFactoryType.CLASS:
|
|
412
|
-
const constructor = serviceDef.serviceValue;
|
|
413
|
-
const instance = new constructor();
|
|
414
|
-
this.internalProcessInjects(instance, this.fInjectMethod);
|
|
415
|
-
return instance;
|
|
416
|
-
}
|
|
445
|
+
case IOC.ServiceFactoryType.CLASS: return this.internalConstruct(serviceDef, false);
|
|
417
446
|
default: throw new Error(`Container - invalid factory type: ${serviceDef.type}`);
|
|
418
447
|
}
|
|
419
448
|
}
|
|
420
449
|
/**
|
|
450
|
+
* Constructs a new instance for a service def and injects its dependencies.
|
|
451
|
+
* @param serviceDef service def to construct
|
|
452
|
+
* @param singleton whether resulting instance should be cached as a singleton
|
|
453
|
+
* @returns newly created class instance
|
|
454
|
+
*/
|
|
455
|
+
internalConstruct(serviceDef, singleton) {
|
|
456
|
+
const onResolved = getIOCDevtoolsHook()?.onResolved;
|
|
457
|
+
const start = onResolved ? performance.now() : 0;
|
|
458
|
+
const constructor = serviceDef.serviceValue;
|
|
459
|
+
const instance = new constructor();
|
|
460
|
+
if (singleton) this.fSingletonInstances.set(serviceDef.serviceKey, instance);
|
|
461
|
+
try {
|
|
462
|
+
this.internalProcessInjects(instance, this.fInjectMethod);
|
|
463
|
+
} catch (error) {
|
|
464
|
+
if (singleton) this.fSingletonInstances.delete(serviceDef.serviceKey);
|
|
465
|
+
throw error;
|
|
466
|
+
}
|
|
467
|
+
if (onResolved) onResolved({
|
|
468
|
+
key: serviceDef.serviceKey,
|
|
469
|
+
name: this.getKeyDescription(serviceDef.serviceKey),
|
|
470
|
+
type: serviceDef.type,
|
|
471
|
+
context: this.fContext,
|
|
472
|
+
start,
|
|
473
|
+
end: performance.now()
|
|
474
|
+
});
|
|
475
|
+
return instance;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
421
478
|
* Internally inject deps for particular class..
|
|
422
479
|
* @param instance instance to inject
|
|
423
480
|
* @param method method for injecting dependencies, either lazy or static
|
|
@@ -437,7 +494,7 @@ var Container = class Container {
|
|
|
437
494
|
const deps = IOCEngine.getDeps(element);
|
|
438
495
|
for (const inj of deps) if (!elementSet.has(inj.dependency)) {
|
|
439
496
|
const isOptional = inj.type === IOC.DependencyType.OPTIONAL;
|
|
440
|
-
const childInstance = isOptional ? this.internalGetOptional(inj.dependency) : this.internalGet(inj.dependency,
|
|
497
|
+
const childInstance = isOptional ? this.internalGetOptional(inj.dependency) : this.internalGet(inj.dependency, element);
|
|
441
498
|
elementSet.add(inj.dependency);
|
|
442
499
|
if (!isOptional) {
|
|
443
500
|
processQueue.push(childInstance);
|
|
@@ -474,10 +531,11 @@ var Container = class Container {
|
|
|
474
531
|
* @returns string representation of service key
|
|
475
532
|
*/
|
|
476
533
|
getKeyDescription(key) {
|
|
477
|
-
if (typeof key === "symbol") return key.description;
|
|
478
|
-
else if (typeof key === "
|
|
479
|
-
else if (typeof key === "
|
|
480
|
-
return "Unknown";
|
|
534
|
+
if (typeof key === "symbol") return key.description ?? "Symbol()";
|
|
535
|
+
else if (typeof key === "string") return key;
|
|
536
|
+
else if (typeof key === "function") return key.name || "AnonymousClass";
|
|
537
|
+
else if (typeof key === "object" && key !== null) return key.constructor?.name ?? "Unknown object";
|
|
538
|
+
return `Unknown (${typeof key})`;
|
|
481
539
|
}
|
|
482
540
|
};
|
|
483
541
|
//#endregion
|
|
@@ -712,4 +770,4 @@ function Injectable() {
|
|
|
712
770
|
return () => {};
|
|
713
771
|
}
|
|
714
772
|
//#endregion
|
|
715
|
-
export { BaseDecorator, Container, Destroy, IOC, Identity, Init, Inject, InjectOptional, Injectable, createDecorator, destroyContainer, destroyDecorators, initializeContainer, initializeDecorators };
|
|
773
|
+
export { BaseDecorator, Container, ContainerEvents, Destroy, IOC, IOCEngine, IOC_DEVTOOLS_HOOK_KEY, Identity, Init, Inject, InjectOptional, Injectable, createDecorator, destroyContainer, destroyDecorators, getIOCDevtoolsHook, initializeContainer, initializeDecorators, setIOCDevtoolsHook };
|