@lppedd/di-wise-neo 0.4.0 → 0.5.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/README.md +24 -2
- package/dist/cjs/index.d.ts +24 -3
- package/dist/cjs/index.js +56 -17
- package/dist/cjs/index.js.map +1 -1
- package/dist/es/index.d.mts +24 -3
- package/dist/es/index.mjs +56 -18
- package/dist/es/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
@@ -442,7 +442,7 @@ export class ExtensionContext {
|
|
442
442
|
|
443
443
|
## Behavioral decorators
|
444
444
|
|
445
|
-
The library includes
|
445
|
+
The library includes three behavioral decorators that influence how classes are registered in the container.
|
446
446
|
These decorators attach metadata to the class type, which is then interpreted by the container during registration.
|
447
447
|
|
448
448
|
### `@Scoped`
|
@@ -476,7 +476,7 @@ In this example, `ExtensionContext` will be registered with **Resolution** scope
|
|
476
476
|
Enables automatic registration of the decorated class if it has not been registered explicitly.
|
477
477
|
|
478
478
|
```ts
|
479
|
-
@AutoRegister
|
479
|
+
@AutoRegister
|
480
480
|
export class ExtensionContext {
|
481
481
|
/* ... */
|
482
482
|
}
|
@@ -485,6 +485,28 @@ export class ExtensionContext {
|
|
485
485
|
container.resolve(ExtensionContext);
|
486
486
|
```
|
487
487
|
|
488
|
+
### `@EagerInstantiate`
|
489
|
+
|
490
|
+
Marks a class for eager instantiation when registered with **Container** scope.
|
491
|
+
|
492
|
+
This causes the container to immediately create and cache the instance of the class
|
493
|
+
at registration time, instead of deferring instantiation until the first resolution.
|
494
|
+
|
495
|
+
```ts
|
496
|
+
@EagerInstantiate
|
497
|
+
@Scoped(Scope.Container)
|
498
|
+
export class ExtensionContext {
|
499
|
+
/* ... */
|
500
|
+
}
|
501
|
+
|
502
|
+
// The container immediately creates and caches the instance
|
503
|
+
container.register(ExtensionContext);
|
504
|
+
```
|
505
|
+
|
506
|
+
> [!WARNING]
|
507
|
+
> Eager instantiation requires that all dependencies of the class are already registered in the container.
|
508
|
+
> If they are not, registration will fail.
|
509
|
+
|
488
510
|
## Testing support
|
489
511
|
|
490
512
|
Testing is an important part of software development, and dependency injection is meant to make it easier.
|
package/dist/cjs/index.d.ts
CHANGED
@@ -422,7 +422,7 @@ declare function createContainer(options?: Partial<ContainerOptions>): Container
|
|
422
422
|
*
|
423
423
|
* @example
|
424
424
|
* ```ts
|
425
|
-
* @AutoRegister
|
425
|
+
* @AutoRegister
|
426
426
|
* class Wizard {}
|
427
427
|
*
|
428
428
|
* const wizard = container.resolve(Wizard);
|
@@ -431,7 +431,28 @@ declare function createContainer(options?: Partial<ContainerOptions>): Container
|
|
431
431
|
*
|
432
432
|
* @__NO_SIDE_EFFECTS__
|
433
433
|
*/
|
434
|
-
declare function AutoRegister(
|
434
|
+
declare function AutoRegister<Ctor extends Constructor<any>>(Class: Ctor): void;
|
435
|
+
|
436
|
+
/**
|
437
|
+
* Class decorator that enables eager instantiation of a class when it is registered
|
438
|
+
* in the container with `Scope.Container`.
|
439
|
+
*
|
440
|
+
* This causes the container to immediately create and cache the instance of the class,
|
441
|
+
* instead of deferring instantiation until the first resolution.
|
442
|
+
*
|
443
|
+
* @example
|
444
|
+
* ```ts
|
445
|
+
* @EagerInstantiate
|
446
|
+
* @Scoped(Scope.Container)
|
447
|
+
* class Wizard {}
|
448
|
+
*
|
449
|
+
* // A Wizard instance is immediately created and cached by the container
|
450
|
+
* const wizard = container.register(Wizard);
|
451
|
+
* ```
|
452
|
+
*
|
453
|
+
* @__NO_SIDE_EFFECTS__
|
454
|
+
*/
|
455
|
+
declare function EagerInstantiate<Ctor extends Constructor<any>>(Class: Ctor): void;
|
435
456
|
|
436
457
|
interface TokensRef<Value = any> {
|
437
458
|
readonly getRefTokens: () => Set<Token<Value>>;
|
@@ -826,5 +847,5 @@ interface Middleware {
|
|
826
847
|
*/
|
827
848
|
declare function applyMiddleware(container: Container, middlewares: Middleware[]): Container;
|
828
849
|
|
829
|
-
export { AutoRegister, Inject, InjectAll, Injectable, Injector, Optional, OptionalAll, Scope, Scoped, applyMiddleware, build, createContainer, createType, forwardRef, inject, injectAll, injectBy };
|
850
|
+
export { AutoRegister, EagerInstantiate, Inject, InjectAll, Injectable, Injector, Optional, OptionalAll, Scope, Scoped, applyMiddleware, build, createContainer, createType, forwardRef, inject, injectAll, injectBy };
|
830
851
|
export type { ClassProvider, Constructor, Container, ContainerOptions, ExistingProvider, FactoryProvider, Middleware, MiddlewareComposer, Provider, RegistrationOptions, Token, TokenRef, Tokens, TokensRef, Type, ValueProvider };
|
package/dist/cjs/index.js
CHANGED
@@ -496,15 +496,16 @@ function isDisposable(value) {
|
|
496
496
|
if (args.length == 1) {
|
497
497
|
const Class = args[0];
|
498
498
|
const metadata = getMetadata(Class);
|
499
|
-
|
500
|
-
this.myTokenRegistry.set(Class, {
|
499
|
+
const registration = {
|
501
500
|
// The provider is of type ClassProvider, initialized by getMetadata
|
502
501
|
provider: metadata.provider,
|
503
502
|
options: {
|
504
|
-
scope: metadata.scope
|
503
|
+
scope: metadata.scope ?? this.myOptions.defaultScope
|
505
504
|
},
|
506
505
|
dependencies: metadata.dependencies
|
507
|
-
}
|
506
|
+
};
|
507
|
+
// Register the class itself
|
508
|
+
this.myTokenRegistry.set(Class, registration);
|
508
509
|
// Register the additional tokens specified via class decorators.
|
509
510
|
// These tokens will point to the original Class token and will have the same scope.
|
510
511
|
for (const token of metadata.tokensRef.getRefTokens()){
|
@@ -514,21 +515,29 @@ function isDisposable(value) {
|
|
514
515
|
}
|
515
516
|
});
|
516
517
|
}
|
518
|
+
// Eager-instantiate only if the class is container-scoped
|
519
|
+
if (metadata.eagerInstantiate && registration.options?.scope === Scope.Container) {
|
520
|
+
this.resolve(Class);
|
521
|
+
}
|
517
522
|
} else {
|
518
523
|
const [token, provider, options] = args;
|
519
524
|
if (isClassProvider(provider)) {
|
520
|
-
const
|
521
|
-
const
|
522
|
-
this.myTokenRegistry.set(token, {
|
525
|
+
const metadata = getMetadata(provider.useClass);
|
526
|
+
const registration = {
|
523
527
|
provider: metadata.provider,
|
524
528
|
options: {
|
525
529
|
// The explicit registration options override what is specified
|
526
530
|
// via class decorators (e.g., @Scoped)
|
527
|
-
scope: metadata.scope,
|
531
|
+
scope: metadata.scope ?? this.myOptions.defaultScope,
|
528
532
|
...options
|
529
533
|
},
|
530
534
|
dependencies: metadata.dependencies
|
531
|
-
}
|
535
|
+
};
|
536
|
+
this.myTokenRegistry.set(token, registration);
|
537
|
+
// Eager-instantiate only if the provided class is container-scoped
|
538
|
+
if (metadata.eagerInstantiate && registration.options?.scope === Scope.Container) {
|
539
|
+
this.resolve(token);
|
540
|
+
}
|
532
541
|
} else {
|
533
542
|
if (isExistingProvider(provider)) {
|
534
543
|
assert(token !== provider.useExisting, `the useExisting token ${token.name} cannot be the same as the token being registered`);
|
@@ -632,8 +641,16 @@ function isDisposable(value) {
|
|
632
641
|
instantiateClass(Class, optional) {
|
633
642
|
const metadata = getMetadata(Class);
|
634
643
|
if (metadata.autoRegister ?? this.myOptions.autoRegister) {
|
635
|
-
|
636
|
-
|
644
|
+
// Temporarily set eagerInstantiate to false to avoid resolving the class two times:
|
645
|
+
// one inside register(), and the other just below
|
646
|
+
const eagerInstantiate = metadata.eagerInstantiate;
|
647
|
+
metadata.eagerInstantiate = false;
|
648
|
+
try {
|
649
|
+
this.register(Class);
|
650
|
+
return this.resolve(Class);
|
651
|
+
} finally{
|
652
|
+
metadata.eagerInstantiate = eagerInstantiate;
|
653
|
+
}
|
637
654
|
}
|
638
655
|
const scope = this.resolveScope(metadata.scope);
|
639
656
|
if (optional && scope === Scope.Container) {
|
@@ -825,7 +842,7 @@ function isDisposable(value) {
|
|
825
842
|
*
|
826
843
|
* @example
|
827
844
|
* ```ts
|
828
|
-
* @AutoRegister
|
845
|
+
* @AutoRegister
|
829
846
|
* class Wizard {}
|
830
847
|
*
|
831
848
|
* const wizard = container.resolve(Wizard);
|
@@ -833,11 +850,32 @@ function isDisposable(value) {
|
|
833
850
|
* ```
|
834
851
|
*
|
835
852
|
* @__NO_SIDE_EFFECTS__
|
836
|
-
*/ function AutoRegister(
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
853
|
+
*/ function AutoRegister(Class) {
|
854
|
+
const metadata = getMetadata(Class);
|
855
|
+
metadata.autoRegister = true;
|
856
|
+
}
|
857
|
+
|
858
|
+
/**
|
859
|
+
* Class decorator that enables eager instantiation of a class when it is registered
|
860
|
+
* in the container with `Scope.Container`.
|
861
|
+
*
|
862
|
+
* This causes the container to immediately create and cache the instance of the class,
|
863
|
+
* instead of deferring instantiation until the first resolution.
|
864
|
+
*
|
865
|
+
* @example
|
866
|
+
* ```ts
|
867
|
+
* @EagerInstantiate
|
868
|
+
* @Scoped(Scope.Container)
|
869
|
+
* class Wizard {}
|
870
|
+
*
|
871
|
+
* // A Wizard instance is immediately created and cached by the container
|
872
|
+
* const wizard = container.register(Wizard);
|
873
|
+
* ```
|
874
|
+
*
|
875
|
+
* @__NO_SIDE_EFFECTS__
|
876
|
+
*/ function EagerInstantiate(Class) {
|
877
|
+
const metadata = getMetadata(Class);
|
878
|
+
metadata.eagerInstantiate = true;
|
841
879
|
}
|
842
880
|
|
843
881
|
function forwardRef(token) {
|
@@ -1065,6 +1103,7 @@ function OptionalAll(token) {
|
|
1065
1103
|
}
|
1066
1104
|
|
1067
1105
|
exports.AutoRegister = AutoRegister;
|
1106
|
+
exports.EagerInstantiate = EagerInstantiate;
|
1068
1107
|
exports.Inject = Inject;
|
1069
1108
|
exports.InjectAll = InjectAll;
|
1070
1109
|
exports.Injectable = Injectable;
|