@lppedd/di-wise-neo 0.3.2 → 0.5.0

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/cjs/index.js CHANGED
@@ -209,10 +209,6 @@ function isClassProvider(provider) {
209
209
  return "useClass" in provider;
210
210
  }
211
211
  // @internal
212
- function isExistingProvider(provider) {
213
- return "useExisting" in provider;
214
- }
215
- // @internal
216
212
  function isFactoryProvider(provider) {
217
213
  return "useFactory" in provider;
218
214
  }
@@ -220,6 +216,10 @@ function isFactoryProvider(provider) {
220
216
  function isValueProvider(provider) {
221
217
  return "useValue" in provider;
222
218
  }
219
+ // @internal
220
+ function isExistingProvider(provider) {
221
+ return "useExisting" in provider;
222
+ }
223
223
 
224
224
  const Scope = {
225
225
  Inherited: "Inherited",
@@ -231,11 +231,11 @@ const Scope = {
231
231
  /**
232
232
  * Type API.
233
233
  */ /**
234
- * Create a type token.
234
+ * Creates a type token.
235
235
  *
236
236
  * @example
237
237
  * ```ts
238
- * const Spell = createType<Spell>("Spell");
238
+ * const ISpell = createType<Spell>("Spell");
239
239
  * ```
240
240
  *
241
241
  * @__NO_SIDE_EFFECTS__
@@ -281,8 +281,8 @@ function getTypeName(value) {
281
281
  // @internal
282
282
  class TokenRegistry {
283
283
  constructor(parent){
284
- this.parent = parent;
285
284
  this.myMap = new Map();
285
+ this.myParent = parent;
286
286
  }
287
287
  get(token) {
288
288
  // To clarify, at(-1) means we take the last added registration for this token
@@ -335,7 +335,7 @@ class TokenRegistry {
335
335
  }
336
336
  getAllFromParent(token) {
337
337
  const registrations = this.myMap.get(token);
338
- return registrations || this.parent?.getAllFromParent(token);
338
+ return registrations || this.myParent?.getAllFromParent(token);
339
339
  }
340
340
  }
341
341
  // @internal
@@ -386,12 +386,11 @@ function isDisposable(value) {
386
386
 
387
387
  /**
388
388
  * The default implementation of a di-wise-neo {@link Container}.
389
- */ class DefaultContainer {
390
- constructor(myParent, options){
391
- this.myParent = myParent;
392
- // eslint-disable-next-line no-use-before-define
389
+ */ class ContainerImpl {
390
+ constructor(parent, options){
393
391
  this.myChildren = new Set();
394
392
  this.myDisposed = false;
393
+ this.myParent = parent;
395
394
  this.myOptions = {
396
395
  autoRegister: false,
397
396
  defaultScope: Scope.Inherited,
@@ -415,7 +414,7 @@ function isDisposable(value) {
415
414
  }
416
415
  createChild(options) {
417
416
  this.checkDisposed();
418
- const container = new DefaultContainer(this, {
417
+ const container = new ContainerImpl(this, {
419
418
  ...this.myOptions,
420
419
  ...options
421
420
  });
@@ -462,20 +461,51 @@ function isDisposable(value) {
462
461
  this.checkDisposed();
463
462
  return this.myTokenRegistry.get(token) !== undefined;
464
463
  }
464
+ registerClass(token, Class, options) {
465
+ // This mess will go away once/if we remove the register method
466
+ // in favor of the multiple specialized ones
467
+ if (Class) {
468
+ const ctor = Class ?? token;
469
+ this.register(token, {
470
+ useClass: ctor
471
+ }, options);
472
+ } else {
473
+ this.register(token);
474
+ }
475
+ }
476
+ registerFactory(token, factory, options) {
477
+ this.register(token, {
478
+ useFactory: factory
479
+ }, options);
480
+ }
481
+ registerValue(token, value) {
482
+ this.register(token, {
483
+ useValue: value
484
+ });
485
+ }
486
+ registerAlias(targetToken, aliasTokens) {
487
+ // De-duplicate tokens
488
+ for (const alias of new Set(aliasTokens)){
489
+ this.register(alias, {
490
+ useExisting: targetToken
491
+ });
492
+ }
493
+ }
465
494
  register(...args) {
466
495
  this.checkDisposed();
467
496
  if (args.length == 1) {
468
497
  const Class = args[0];
469
498
  const metadata = getMetadata(Class);
470
- // Register the class itself
471
- this.myTokenRegistry.set(Class, {
499
+ const registration = {
472
500
  // The provider is of type ClassProvider, initialized by getMetadata
473
501
  provider: metadata.provider,
474
502
  options: {
475
- scope: metadata.scope
503
+ scope: metadata.scope ?? this.myOptions.defaultScope
476
504
  },
477
505
  dependencies: metadata.dependencies
478
- });
506
+ };
507
+ // Register the class itself
508
+ this.myTokenRegistry.set(Class, registration);
479
509
  // Register the additional tokens specified via class decorators.
480
510
  // These tokens will point to the original Class token and will have the same scope.
481
511
  for (const token of metadata.tokensRef.getRefTokens()){
@@ -485,21 +515,29 @@ function isDisposable(value) {
485
515
  }
486
516
  });
487
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
+ }
488
522
  } else {
489
523
  const [token, provider, options] = args;
490
524
  if (isClassProvider(provider)) {
491
- const Class = provider.useClass;
492
- const metadata = getMetadata(Class);
493
- this.myTokenRegistry.set(token, {
525
+ const metadata = getMetadata(provider.useClass);
526
+ const registration = {
494
527
  provider: metadata.provider,
495
528
  options: {
496
529
  // The explicit registration options override what is specified
497
530
  // via class decorators (e.g., @Scoped)
498
- scope: metadata.scope,
531
+ scope: metadata.scope ?? this.myOptions.defaultScope,
499
532
  ...options
500
533
  },
501
534
  dependencies: metadata.dependencies
502
- });
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
+ }
503
541
  } else {
504
542
  if (isExistingProvider(provider)) {
505
543
  assert(token !== provider.useExisting, `the useExisting token ${token.name} cannot be the same as the token being registered`);
@@ -787,16 +825,16 @@ function isDisposable(value) {
787
825
  autoRegister: false,
788
826
  defaultScope: Scope.Inherited
789
827
  }) {
790
- return new DefaultContainer(undefined, options);
828
+ return new ContainerImpl(undefined, options);
791
829
  }
792
830
 
793
831
  /**
794
- * Class decorator for enabling auto-registration of an unregistered class
795
- * when first resolving it from the container.
832
+ * Class decorator that enables auto-registration of an unregistered class,
833
+ * when the class is first resolved from the container.
796
834
  *
797
835
  * @example
798
836
  * ```ts
799
- * @AutoRegister()
837
+ * @AutoRegister
800
838
  * class Wizard {}
801
839
  *
802
840
  * const wizard = container.resolve(Wizard);
@@ -804,11 +842,32 @@ function isDisposable(value) {
804
842
  * ```
805
843
  *
806
844
  * @__NO_SIDE_EFFECTS__
807
- */ function AutoRegister(enable = true) {
808
- return function(Class) {
809
- const metadata = getMetadata(Class);
810
- metadata.autoRegister = enable;
811
- };
845
+ */ function AutoRegister(Class) {
846
+ const metadata = getMetadata(Class);
847
+ metadata.autoRegister = true;
848
+ }
849
+
850
+ /**
851
+ * Class decorator that enables eager instantiation of a class when it is registered
852
+ * in the container with `Scope.Container`.
853
+ *
854
+ * This causes the container to immediately create and cache the instance of the class,
855
+ * instead of deferring instantiation until the first resolution.
856
+ *
857
+ * @example
858
+ * ```ts
859
+ * @EagerInstantiate
860
+ * @Scoped(Scope.Container)
861
+ * class Wizard {}
862
+ *
863
+ * // A Wizard instance is immediately created and cached by the container
864
+ * const wizard = container.register(Wizard);
865
+ * ```
866
+ *
867
+ * @__NO_SIDE_EFFECTS__
868
+ */ function EagerInstantiate(Class) {
869
+ const metadata = getMetadata(Class);
870
+ metadata.eagerInstantiate = true;
812
871
  }
813
872
 
814
873
  function forwardRef(token) {
@@ -992,7 +1051,7 @@ function OptionalAll(token) {
992
1051
  });
993
1052
 
994
1053
  /**
995
- * Apply middleware functions to a container.
1054
+ * Applies middleware functions to a container.
996
1055
  *
997
1056
  * Middlewares are applied in array order, but execute in reverse order.
998
1057
  *
@@ -1036,6 +1095,7 @@ function OptionalAll(token) {
1036
1095
  }
1037
1096
 
1038
1097
  exports.AutoRegister = AutoRegister;
1098
+ exports.EagerInstantiate = EagerInstantiate;
1039
1099
  exports.Inject = Inject;
1040
1100
  exports.InjectAll = InjectAll;
1041
1101
  exports.Injectable = Injectable;