@lppedd/di-wise-neo 0.3.1 → 0.4.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.
@@ -1,46 +1,30 @@
1
- /**
2
- * Constructor type.
3
- */
4
- interface Constructor<Instance extends object> {
5
- new (...args: any[]): Instance;
6
- readonly name: string;
7
- readonly length: number;
8
- }
9
- /**
10
- * Token type.
11
- */
12
- type Token<Value = any> = [Value] extends [object] ? Type<Value> | Constructor<Value> : Type<Value>;
13
- /**
14
- * Describes a {@link Token} array with at least one element.
15
- */
16
- type Tokens<Value = any> = [Token<Value>, ...Token<Value>[]];
17
1
  /**
18
2
  * Type API.
19
3
  */
20
4
  interface Type<A> {
21
5
  /**
22
- * Name of the type.
6
+ * The name of the type.
23
7
  */
24
8
  readonly name: string;
25
9
  /**
26
- * Create an intersection type from another type.
10
+ * Creates an intersection type from another type.
27
11
  *
28
12
  * @example
29
13
  * ```ts
30
- * const A = Type<A>("A");
31
- * const B = Type<B>("B");
14
+ * const A = createType<A>("A");
15
+ * const B = createType<B>("B");
32
16
  *
33
17
  * A.inter("I", B); // => Type<A & B>
34
18
  * ```
35
19
  */
36
20
  inter<B>(typeName: string, B: Type<B>): Type<A & B>;
37
21
  /**
38
- * Create a union type from another type.
22
+ * Creates a union type from another type.
39
23
  *
40
24
  * @example
41
25
  * ```ts
42
- * const A = Type<A>("A");
43
- * const B = Type<B>("B");
26
+ * const A = createType<A>("A");
27
+ * const B = createType<B>("B");
44
28
  *
45
29
  * A.union("U", B); // => Type<A | B>
46
30
  * ```
@@ -48,16 +32,31 @@ interface Type<A> {
48
32
  union<B>(typeName: string, B: Type<B>): Type<A | B>;
49
33
  }
50
34
  /**
51
- * Create a type token.
35
+ * Constructor type.
36
+ */
37
+ interface Constructor<Instance extends object> {
38
+ new (...args: any[]): Instance;
39
+ readonly name: string;
40
+ }
41
+ /**
42
+ * Token type.
43
+ */
44
+ type Token<Value = any> = [Value] extends [object] ? Type<Value> | Constructor<Value> : Type<Value>;
45
+ /**
46
+ * Describes a {@link Token} array with at least one element.
47
+ */
48
+ type Tokens<Value = any> = [Token<Value>, ...Token<Value>[]];
49
+ /**
50
+ * Creates a type token.
52
51
  *
53
52
  * @example
54
53
  * ```ts
55
- * const Spell = Type<Spell>("Spell");
54
+ * const ISpell = createType<Spell>("Spell");
56
55
  * ```
57
56
  *
58
57
  * @__NO_SIDE_EFFECTS__
59
58
  */
60
- declare function Type<T>(typeName: string): Type<T>;
59
+ declare function createType<T>(typeName: string): Type<T>;
61
60
 
62
61
  /**
63
62
  * Provides a class instance for a token via a class constructor.
@@ -65,31 +64,33 @@ declare function Type<T>(typeName: string): Type<T>;
65
64
  interface ClassProvider<Instance extends object> {
66
65
  readonly useClass: Constructor<Instance>;
67
66
  }
68
- /**
69
- * Provides a value for a token via another existing token.
70
- */
71
- interface ExistingProvider<Value> {
72
- readonly useExisting: Token<Value>;
73
- }
74
67
  /**
75
68
  * Provides a value for a token via a factory function.
76
69
  *
77
- * The factory function runs inside the injection context
78
- * and can thus access dependencies via {@link inject}.
70
+ * The factory function runs inside the injection context and can
71
+ * thus access dependencies via {@link inject}-like functions.
79
72
  */
80
73
  interface FactoryProvider<Value> {
81
74
  readonly useFactory: (...args: []) => Value;
82
75
  }
83
76
  /**
84
- * Provides a direct - already constructed - value for a token.
77
+ * Provides a static - already constructed - value for a token.
85
78
  */
86
79
  interface ValueProvider<T> {
87
80
  readonly useValue: T;
88
81
  }
82
+ /**
83
+ * Aliases another registered token.
84
+ *
85
+ * Resolving this token will return the value of the aliased one.
86
+ */
87
+ interface ExistingProvider<Value> {
88
+ readonly useExisting: Token<Value>;
89
+ }
89
90
  /**
90
91
  * A token provider.
91
92
  */
92
- type Provider<Value = any> = ClassProvider<Value & object> | ExistingProvider<Value> | FactoryProvider<Value> | ValueProvider<Value>;
93
+ type Provider<Value = any> = ClassProvider<Value & object> | FactoryProvider<Value> | ValueProvider<Value> | ExistingProvider<Value>;
93
94
 
94
95
  declare const Scope: {
95
96
  readonly Inherited: "Inherited";
@@ -115,7 +116,7 @@ interface RegistrationOptions {
115
116
  * ```ts
116
117
  * class Wizard {
117
118
  * wand = inject(
118
- * Build(() => {
119
+ * build(() => {
119
120
  * const wand = inject(Wand);
120
121
  * wand.owner = this;
121
122
  * // ...
@@ -127,7 +128,7 @@ interface RegistrationOptions {
127
128
  *
128
129
  * @__NO_SIDE_EFFECTS__
129
130
  */
130
- declare function Build<Value>(factory: (...args: []) => Value): Type<Value>;
131
+ declare function build<Value>(factory: (...args: []) => Value): Type<Value>;
131
132
 
132
133
  /**
133
134
  * Container creation options.
@@ -212,35 +213,87 @@ interface Container {
212
213
  * Returns whether the token is registered in this container or in parent containers, if any.
213
214
  */
214
215
  isRegistered(token: Token): boolean;
216
+ /**
217
+ * Registers a concrete class, where the class acts as its own token.
218
+ *
219
+ * Tokens provided via the {@link Injectable} decorator applied to the class
220
+ * are also registered as aliases.
221
+ *
222
+ * The default registration scope is determined by the {@link Scoped} decorator,
223
+ * if present.
224
+ */
225
+ registerClass<Instance extends object>(Class: Constructor<Instance>): void;
226
+ /**
227
+ * Registers a concrete class with a token.
228
+ *
229
+ * The default registration scope is determined by the {@link Scoped} decorator
230
+ * applied to the class, if present, but it can be overridden by passing explicit
231
+ * registration options.
232
+ */
233
+ registerClass<Instance extends object, ProvidedInstance extends Instance>(token: Token<Instance>, Class: Constructor<ProvidedInstance>, options?: RegistrationOptions): void;
234
+ /**
235
+ * Registers a token whose value is produced by a factory function.
236
+ *
237
+ * The factory function runs inside the injection context and can
238
+ * thus access dependencies via {@link inject}-like functions.
239
+ */
240
+ registerFactory<Value, ProvidedValue extends Value>(token: Token<Value>, factory: (...args: []) => ProvidedValue, options?: RegistrationOptions): void;
241
+ /**
242
+ * Registers a token with a fixed value.
243
+ *
244
+ * The provided value is returned as-is when the token is resolved (scopes do not apply).
245
+ */
246
+ registerValue<Value, ProvidedValue extends Value>(token: Token<Value>, value: ProvidedValue): void;
247
+ /**
248
+ * Registers one or more tokens as aliases for a target token.
249
+ *
250
+ * When an alias is resolved, the target token is resolved instead.
251
+ */
252
+ registerAlias<Value, ProvidedValue extends Value>(targetToken: Token<ProvidedValue>, aliasTokens: Tokens<Value>): void;
215
253
  /**
216
254
  * Registers a {@link ClassProvider}, using the class itself as its token.
217
255
  *
218
- * Tokens provided to the {@link Injectable} decorator applied to the class
219
- * are also registered as aliases. The scope is determined by the {@link Scoped}
220
- * decorator, if present.
256
+ * Tokens provided via the {@link Injectable} decorator applied to the class
257
+ * are also registered as aliases.
258
+ *
259
+ * The scope is determined by the {@link Scoped} decorator, if present.
260
+ *
261
+ * @see registerClass
221
262
  */
222
- register<Instance extends object>(Class: Constructor<Instance>): this;
263
+ register<Instance extends object>(Class: Constructor<Instance>): Container;
223
264
  /**
224
265
  * Registers a {@link ClassProvider} with a token.
266
+ *
267
+ * The default registration scope is determined by the {@link Scoped} decorator
268
+ * applied to the provided class, if present, but it can be overridden by
269
+ * passing explicit registration options.
270
+ *
271
+ * @see registerClass
225
272
  */
226
- register<Instance extends object, ProviderInstance extends Instance>(token: Token<Instance>, provider: ClassProvider<ProviderInstance>, options?: RegistrationOptions): this;
273
+ register<Instance extends object, ProviderInstance extends Instance>(token: Token<Instance>, provider: ClassProvider<ProviderInstance>, options?: RegistrationOptions): Container;
227
274
  /**
228
275
  * Registers a {@link FactoryProvider} with a token.
276
+ *
277
+ * @see registerFactory
229
278
  */
230
- register<Value, ProviderValue extends Value>(token: Token<Value>, provider: FactoryProvider<ProviderValue>, options?: RegistrationOptions): this;
279
+ register<Value, ProviderValue extends Value>(token: Token<Value>, provider: FactoryProvider<ProviderValue>, options?: RegistrationOptions): Container;
231
280
  /**
232
281
  * Registers an {@link ExistingProvider} with a token.
233
282
  *
234
283
  * The token will alias the one set in `useExisting`.
284
+ *
285
+ * @see registerAlias
235
286
  */
236
- register<Value, ProviderValue extends Value>(token: Token<Value>, provider: ExistingProvider<ProviderValue>): this;
287
+ register<Value, ProviderValue extends Value>(token: Token<Value>, provider: ExistingProvider<ProviderValue>): Container;
237
288
  /**
238
289
  * Registers a {@link ValueProvider} with a token.
239
290
  *
240
291
  * Values provided via `useValue` are never cached (scopes do not apply)
241
292
  * and are simply returned as-is.
293
+ *
294
+ * @see registerValue
242
295
  */
243
- register<Value, ProviderValue extends Value>(token: Token<Value>, provider: ValueProvider<ProviderValue>): this;
296
+ register<Value, ProviderValue extends Value>(token: Token<Value>, provider: ValueProvider<ProviderValue>): Container;
244
297
  /**
245
298
  * Removes all registrations for the given token from the container's internal registry.
246
299
  *
@@ -364,8 +417,8 @@ interface Container {
364
417
  declare function createContainer(options?: Partial<ContainerOptions>): Container;
365
418
 
366
419
  /**
367
- * Class decorator for enabling auto-registration of an unregistered class
368
- * when first resolving it from the container.
420
+ * Class decorator that enables auto-registration of an unregistered class,
421
+ * when the class is first resolved from the container.
369
422
  *
370
423
  * @example
371
424
  * ```ts
@@ -387,9 +440,14 @@ interface TokenRef<Value = any> {
387
440
  readonly getRefToken: () => Token<Value>;
388
441
  }
389
442
  /**
390
- * Allows referencing a token that is declared later in the file by wrapping it in a function.
443
+ * Allows referencing tokens that are declared later in the file by wrapping them
444
+ * in a lazily evaluated function.
391
445
  */
392
446
  declare function forwardRef<Value>(token: () => Tokens<Value>): TokensRef<Value>;
447
+ /**
448
+ * Allows referencing a token that is declared later in the file by wrapping it
449
+ * in a lazily evaluated function.
450
+ */
393
451
  declare function forwardRef<Value>(token: () => Token<Value>): TokenRef<Value>;
394
452
 
395
453
  /**
@@ -424,8 +482,8 @@ declare function Inject<Value>(token: Token<Value>): ParameterDecorator;
424
482
  declare function Inject<Value>(tokens: TokenRef<Value>): ParameterDecorator;
425
483
 
426
484
  /**
427
- * Class decorator for registering additional aliasing tokens for the decorated type
428
- * when registering it.
485
+ * Class decorator that registers additional aliasing tokens for the decorated type,
486
+ * when the type is first registered in the container.
429
487
  *
430
488
  * The container uses {@link ExistingProvider} under the hood.
431
489
  *
@@ -437,8 +495,8 @@ declare function Inject<Value>(tokens: TokenRef<Value>): ParameterDecorator;
437
495
  */
438
496
  declare function Injectable<This extends object, Value extends This>(...tokens: Tokens<Value>): ClassDecorator;
439
497
  /**
440
- * Class decorator for registering additional aliasing tokens for the decorated type
441
- * when registering it.
498
+ * Class decorator that registers additional aliasing tokens for the decorated type,
499
+ * when the type is first registered in the container.
442
500
  *
443
501
  * The container uses {@link ExistingProvider} under the hood.
444
502
  *
@@ -718,7 +776,7 @@ declare const Injector: Type<Injector>;
718
776
  */
719
777
  interface MiddlewareComposer {
720
778
  /**
721
- * Add a middleware function to the composer.
779
+ * Adds a middleware function to the composer.
722
780
  */
723
781
  use<MethodKey extends keyof Container>(key: MethodKey, wrap: Container[MethodKey] extends Function ? (next: Container[MethodKey]) => Container[MethodKey] : never): MiddlewareComposer;
724
782
  }
@@ -744,7 +802,7 @@ interface Middleware {
744
802
  (composer: MiddlewareComposer, api: Readonly<Container>): void;
745
803
  }
746
804
  /**
747
- * Apply middleware functions to a container.
805
+ * Applies middleware functions to a container.
748
806
  *
749
807
  * Middlewares are applied in array order, but execute in reverse order.
750
808
  *
@@ -768,5 +826,5 @@ interface Middleware {
768
826
  */
769
827
  declare function applyMiddleware(container: Container, middlewares: Middleware[]): Container;
770
828
 
771
- export { AutoRegister, Build, Inject, InjectAll, Injectable, Injector, Optional, OptionalAll, Scope, Scoped, Type, applyMiddleware, createContainer, forwardRef, inject, injectAll, injectBy };
772
- export type { ClassProvider, Constructor, Container, ContainerOptions, ExistingProvider, FactoryProvider, Middleware, MiddlewareComposer, Provider, RegistrationOptions, Token, TokenRef, Tokens, TokensRef, ValueProvider };
829
+ export { AutoRegister, Inject, InjectAll, Injectable, Injector, Optional, OptionalAll, Scope, Scoped, applyMiddleware, build, createContainer, createType, forwardRef, inject, injectAll, injectBy };
830
+ export type { ClassProvider, Constructor, Container, ContainerOptions, ExistingProvider, FactoryProvider, Middleware, MiddlewareComposer, Provider, RegistrationOptions, Token, TokenRef, Tokens, TokensRef, Type, ValueProvider };
package/dist/es/index.mjs CHANGED
@@ -207,10 +207,6 @@ function isClassProvider(provider) {
207
207
  return "useClass" in provider;
208
208
  }
209
209
  // @internal
210
- function isExistingProvider(provider) {
211
- return "useExisting" in provider;
212
- }
213
- // @internal
214
210
  function isFactoryProvider(provider) {
215
211
  return "useFactory" in provider;
216
212
  }
@@ -218,6 +214,10 @@ function isFactoryProvider(provider) {
218
214
  function isValueProvider(provider) {
219
215
  return "useValue" in provider;
220
216
  }
217
+ // @internal
218
+ function isExistingProvider(provider) {
219
+ return "useExisting" in provider;
220
+ }
221
221
 
222
222
  const Scope = {
223
223
  Inherited: "Inherited",
@@ -229,19 +229,19 @@ const Scope = {
229
229
  /**
230
230
  * Type API.
231
231
  */ /**
232
- * Create a type token.
232
+ * Creates a type token.
233
233
  *
234
234
  * @example
235
235
  * ```ts
236
- * const Spell = Type<Spell>("Spell");
236
+ * const ISpell = createType<Spell>("Spell");
237
237
  * ```
238
238
  *
239
239
  * @__NO_SIDE_EFFECTS__
240
- */ function Type(typeName) {
240
+ */ function createType(typeName) {
241
241
  const type = {
242
242
  name: `Type<${typeName}>`,
243
- inter: Type,
244
- union: Type,
243
+ inter: createType,
244
+ union: createType,
245
245
  toString () {
246
246
  return type.name;
247
247
  }
@@ -279,8 +279,8 @@ function getTypeName(value) {
279
279
  // @internal
280
280
  class TokenRegistry {
281
281
  constructor(parent){
282
- this.parent = parent;
283
282
  this.myMap = new Map();
283
+ this.myParent = parent;
284
284
  }
285
285
  get(token) {
286
286
  // To clarify, at(-1) means we take the last added registration for this token
@@ -333,7 +333,7 @@ class TokenRegistry {
333
333
  }
334
334
  getAllFromParent(token) {
335
335
  const registrations = this.myMap.get(token);
336
- return registrations || this.parent?.getAllFromParent(token);
336
+ return registrations || this.myParent?.getAllFromParent(token);
337
337
  }
338
338
  }
339
339
  // @internal
@@ -347,7 +347,7 @@ function isBuilder(provider) {
347
347
  * ```ts
348
348
  * class Wizard {
349
349
  * wand = inject(
350
- * Build(() => {
350
+ * build(() => {
351
351
  * const wand = inject(Wand);
352
352
  * wand.owner = this;
353
353
  * // ...
@@ -358,8 +358,8 @@ function isBuilder(provider) {
358
358
  * ```
359
359
  *
360
360
  * @__NO_SIDE_EFFECTS__
361
- */ function Build(factory) {
362
- const token = Type(`Build<${getTypeName(factory)}>`);
361
+ */ function build(factory) {
362
+ const token = createType(`Build<${getTypeName(factory)}>`);
363
363
  const provider = {
364
364
  useFactory: factory
365
365
  };
@@ -384,12 +384,11 @@ function isDisposable(value) {
384
384
 
385
385
  /**
386
386
  * The default implementation of a di-wise-neo {@link Container}.
387
- */ class DefaultContainer {
388
- constructor(myParent, options){
389
- this.myParent = myParent;
390
- // eslint-disable-next-line no-use-before-define
387
+ */ class ContainerImpl {
388
+ constructor(parent, options){
391
389
  this.myChildren = new Set();
392
390
  this.myDisposed = false;
391
+ this.myParent = parent;
393
392
  this.myOptions = {
394
393
  autoRegister: false,
395
394
  defaultScope: Scope.Inherited,
@@ -413,7 +412,7 @@ function isDisposable(value) {
413
412
  }
414
413
  createChild(options) {
415
414
  this.checkDisposed();
416
- const container = new DefaultContainer(this, {
415
+ const container = new ContainerImpl(this, {
417
416
  ...this.myOptions,
418
417
  ...options
419
418
  });
@@ -460,6 +459,36 @@ function isDisposable(value) {
460
459
  this.checkDisposed();
461
460
  return this.myTokenRegistry.get(token) !== undefined;
462
461
  }
462
+ registerClass(token, Class, options) {
463
+ // This mess will go away once/if we remove the register method
464
+ // in favor of the multiple specialized ones
465
+ if (Class) {
466
+ const ctor = Class ?? token;
467
+ this.register(token, {
468
+ useClass: ctor
469
+ }, options);
470
+ } else {
471
+ this.register(token);
472
+ }
473
+ }
474
+ registerFactory(token, factory, options) {
475
+ this.register(token, {
476
+ useFactory: factory
477
+ }, options);
478
+ }
479
+ registerValue(token, value) {
480
+ this.register(token, {
481
+ useValue: value
482
+ });
483
+ }
484
+ registerAlias(targetToken, aliasTokens) {
485
+ // De-duplicate tokens
486
+ for (const alias of new Set(aliasTokens)){
487
+ this.register(alias, {
488
+ useExisting: targetToken
489
+ });
490
+ }
491
+ }
463
492
  register(...args) {
464
493
  this.checkDisposed();
465
494
  if (args.length == 1) {
@@ -785,12 +814,12 @@ function isDisposable(value) {
785
814
  autoRegister: false,
786
815
  defaultScope: Scope.Inherited
787
816
  }) {
788
- return new DefaultContainer(undefined, options);
817
+ return new ContainerImpl(undefined, options);
789
818
  }
790
819
 
791
820
  /**
792
- * Class decorator for enabling auto-registration of an unregistered class
793
- * when first resolving it from the container.
821
+ * Class decorator that enables auto-registration of an unregistered class,
822
+ * when the class is first resolved from the container.
794
823
  *
795
824
  * @example
796
825
  * ```ts
@@ -959,7 +988,7 @@ function OptionalAll(token) {
959
988
  * const wizard = container.resolve(Wizard);
960
989
  * wizard.getWand(); // => Wand
961
990
  * ```
962
- */ const Injector = /*@__PURE__*/ Build(function Injector() {
991
+ */ const Injector = /*@__PURE__*/ build(function Injector() {
963
992
  const context = ensureInjectionContext(Injector);
964
993
  const resolution = context.resolution;
965
994
  const dependentFrame = resolution.stack.peek();
@@ -990,7 +1019,7 @@ function OptionalAll(token) {
990
1019
  });
991
1020
 
992
1021
  /**
993
- * Apply middleware functions to a container.
1022
+ * Applies middleware functions to a container.
994
1023
  *
995
1024
  * Middlewares are applied in array order, but execute in reverse order.
996
1025
  *
@@ -1033,5 +1062,5 @@ function OptionalAll(token) {
1033
1062
  return container;
1034
1063
  }
1035
1064
 
1036
- export { AutoRegister, Build, Inject, InjectAll, Injectable, Injector, Optional, OptionalAll, Scope, Scoped, Type, applyMiddleware, createContainer, forwardRef, inject, injectAll, injectBy };
1065
+ export { AutoRegister, Inject, InjectAll, Injectable, Injector, Optional, OptionalAll, Scope, Scoped, applyMiddleware, build, createContainer, createType, forwardRef, inject, injectAll, injectBy };
1037
1066
  //# sourceMappingURL=index.mjs.map