@lppedd/di-wise-neo 0.6.0 → 0.7.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/README.md +29 -3
- package/dist/cjs/index.d.ts +107 -67
- package/dist/cjs/index.js +233 -158
- package/dist/cjs/index.js.map +1 -1
- package/dist/es/index.d.mts +107 -67
- package/dist/es/index.mjs +233 -159
- package/dist/es/index.mjs.map +1 -1
- package/package.json +6 -6
package/dist/es/index.mjs
CHANGED
@@ -127,23 +127,23 @@ function ensureInjectionContext(fn) {
|
|
127
127
|
return context;
|
128
128
|
}
|
129
129
|
|
130
|
-
function inject(token) {
|
130
|
+
function inject(token, name) {
|
131
131
|
const context = ensureInjectionContext(inject);
|
132
|
-
return context.container.resolve(token);
|
132
|
+
return context.container.resolve(token, name);
|
133
133
|
}
|
134
|
-
function injectBy(thisArg, token) {
|
134
|
+
function injectBy(thisArg, token, name) {
|
135
135
|
const context = ensureInjectionContext(injectBy);
|
136
136
|
const resolution = context.resolution;
|
137
137
|
const currentFrame = resolution.stack.peek();
|
138
138
|
if (!currentFrame) {
|
139
|
-
return inject(token);
|
139
|
+
return inject(token, name);
|
140
140
|
}
|
141
141
|
const currentRef = {
|
142
142
|
current: thisArg
|
143
143
|
};
|
144
144
|
const cleanup = resolution.dependents.set(currentFrame.provider, currentRef);
|
145
145
|
try {
|
146
|
-
return inject(token);
|
146
|
+
return inject(token, name);
|
147
147
|
} finally{
|
148
148
|
cleanup();
|
149
149
|
}
|
@@ -154,41 +154,59 @@ function injectAll(token) {
|
|
154
154
|
return context.container.resolveAll(token);
|
155
155
|
}
|
156
156
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
157
|
+
// @internal
|
158
|
+
class Metadata {
|
159
|
+
constructor(Class){
|
160
|
+
this.dependencies = {
|
161
|
+
constructor: [],
|
162
|
+
methods: new Map()
|
163
|
+
};
|
164
|
+
this.tokensRef = {
|
165
|
+
getRefTokens: ()=>new Set()
|
166
|
+
};
|
167
|
+
this.provider = {
|
168
|
+
useClass: Class
|
169
|
+
};
|
170
|
+
}
|
171
|
+
get name() {
|
172
|
+
return this.provider.name;
|
173
|
+
}
|
174
|
+
set name(name) {
|
175
|
+
this.provider.name = name;
|
176
|
+
}
|
177
|
+
getConstructorDependency(index) {
|
178
|
+
const i = this.dependencies.constructor.findIndex((d)=>d.index === index);
|
179
|
+
if (i > -1) {
|
180
|
+
return this.dependencies.constructor[i];
|
181
|
+
}
|
182
|
+
const dependency = {
|
183
|
+
index: index
|
184
|
+
};
|
185
|
+
this.dependencies.constructor.push(dependency);
|
186
|
+
return dependency;
|
187
|
+
}
|
188
|
+
getMethodDependency(method, index) {
|
189
|
+
let methodDeps = this.dependencies.methods.get(method);
|
190
|
+
if (!methodDeps) {
|
191
|
+
this.dependencies.methods.set(method, methodDeps = []);
|
192
|
+
}
|
193
|
+
const i = methodDeps.findIndex((d)=>d.index === index);
|
194
|
+
if (i > -1) {
|
195
|
+
return methodDeps[i];
|
196
|
+
}
|
197
|
+
const dependency = {
|
198
|
+
index: index
|
199
|
+
};
|
200
|
+
methodDeps.push(dependency);
|
201
|
+
return dependency;
|
202
|
+
}
|
174
203
|
}
|
175
204
|
// @internal
|
176
205
|
function getMetadata(Class) {
|
177
206
|
const originalClass = classIdentityMap.get(Class) ?? Class;
|
178
207
|
let metadata = metadataMap.get(originalClass);
|
179
208
|
if (!metadata) {
|
180
|
-
metadataMap.set(originalClass, metadata =
|
181
|
-
tokensRef: {
|
182
|
-
getRefTokens: ()=>new Set()
|
183
|
-
},
|
184
|
-
provider: {
|
185
|
-
useClass: originalClass
|
186
|
-
},
|
187
|
-
dependencies: {
|
188
|
-
constructor: [],
|
189
|
-
methods: new Map()
|
190
|
-
}
|
191
|
-
});
|
209
|
+
metadataMap.set(originalClass, metadata = new Metadata(originalClass));
|
192
210
|
}
|
193
211
|
if (metadata.provider.useClass !== Class) {
|
194
212
|
// This is part of the class identity mapping API (see setClassIdentityMapping).
|
@@ -202,32 +220,48 @@ function getMetadata(Class) {
|
|
202
220
|
// We must update useClass to be the extender class B so that instances created by the
|
203
221
|
// DI container match the consumer's registered class. Without this update, the DI
|
204
222
|
// system would instantiate the original class A, causing behavior inconsistencies.
|
205
|
-
//
|
206
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
207
223
|
metadata.provider.useClass = Class;
|
208
224
|
}
|
209
225
|
return metadata;
|
210
226
|
}
|
227
|
+
/**
|
228
|
+
* Registers a mapping between a generated (e.g., decorated or proxied) constructor
|
229
|
+
* and its original, underlying constructor.
|
230
|
+
*
|
231
|
+
* This allows libraries or consumers that manipulate constructors, such as through
|
232
|
+
* class decorators, to inform the DI system about the real "identity" of a class.
|
233
|
+
*
|
234
|
+
* @param transformedClass The constructor function returned by a class decorator or factory.
|
235
|
+
* @param originalClass The original constructor function.
|
236
|
+
*
|
237
|
+
* @remarks
|
238
|
+
* This API affects the core class identity resolution mechanism of the DI system.
|
239
|
+
* Incorrect usage may cause metadata to be misassociated, leading to subtle errors.
|
240
|
+
* Use only when manipulating constructors (e.g., via decorators or proxies),
|
241
|
+
* and ensure the mapping is correct.
|
242
|
+
*/ function setClassIdentityMapping(transformedClass, originalClass) {
|
243
|
+
classIdentityMap.set(transformedClass, originalClass);
|
244
|
+
}
|
211
245
|
const classIdentityMap = new WeakMap();
|
212
246
|
const metadataMap = new WeakMap();
|
213
247
|
|
214
|
-
function optional(token) {
|
248
|
+
function optional(token, name) {
|
215
249
|
const context = ensureInjectionContext(optional);
|
216
|
-
return context.container.resolve(token, true);
|
250
|
+
return context.container.resolve(token, true, name);
|
217
251
|
}
|
218
|
-
function optionalBy(thisArg, token) {
|
252
|
+
function optionalBy(thisArg, token, name) {
|
219
253
|
const context = ensureInjectionContext(optionalBy);
|
220
254
|
const resolution = context.resolution;
|
221
255
|
const currentFrame = resolution.stack.peek();
|
222
256
|
if (!currentFrame) {
|
223
|
-
return optional(token);
|
257
|
+
return optional(token, name);
|
224
258
|
}
|
225
259
|
const currentRef = {
|
226
260
|
current: thisArg
|
227
261
|
};
|
228
262
|
const cleanup = resolution.dependents.set(currentFrame.provider, currentRef);
|
229
263
|
try {
|
230
|
-
return optional(token);
|
264
|
+
return optional(token, name);
|
231
265
|
} finally{
|
232
266
|
cleanup();
|
233
267
|
}
|
@@ -286,28 +320,29 @@ const Scope = {
|
|
286
320
|
}
|
287
321
|
// @internal
|
288
322
|
function isConstructor(token) {
|
289
|
-
return typeof token
|
323
|
+
return typeof token === "function";
|
290
324
|
}
|
291
325
|
|
292
326
|
// @internal
|
293
327
|
function getTypeName(value) {
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
328
|
+
switch(typeof value){
|
329
|
+
case "string":
|
330
|
+
return `"${value}"`;
|
331
|
+
case "function":
|
332
|
+
return value.name && `typeof ${value.name}` || "Function";
|
333
|
+
case "object":
|
334
|
+
{
|
335
|
+
if (value === null) {
|
336
|
+
return "null";
|
337
|
+
}
|
338
|
+
const proto = Object.getPrototypeOf(value);
|
339
|
+
if (proto && proto !== Object.prototype) {
|
340
|
+
const constructor = proto.constructor;
|
341
|
+
if (typeof constructor === "function" && constructor.name) {
|
342
|
+
return constructor.name;
|
343
|
+
}
|
344
|
+
}
|
309
345
|
}
|
310
|
-
}
|
311
346
|
}
|
312
347
|
return typeof value;
|
313
348
|
}
|
@@ -318,28 +353,46 @@ class TokenRegistry {
|
|
318
353
|
this.myMap = new Map();
|
319
354
|
this.myParent = parent;
|
320
355
|
}
|
321
|
-
get(token) {
|
356
|
+
get(token, name) {
|
322
357
|
// To clarify, at(-1) means we take the last added registration for this token
|
323
|
-
return this.getAll(token)
|
358
|
+
return this.getAll(token, name).at(-1);
|
324
359
|
}
|
325
|
-
getAll(token) {
|
326
|
-
|
360
|
+
getAll(token, name) {
|
361
|
+
// Internal registrations cannot have a name
|
362
|
+
const internal = name !== undefined ? undefined : internals.get(token);
|
327
363
|
return internal && [
|
328
364
|
internal
|
329
|
-
] || this.getAllFromParent(token);
|
365
|
+
] || this.getAllFromParent(token, name);
|
330
366
|
}
|
331
367
|
set(token, registration) {
|
332
368
|
assert(!internals.has(token), `cannot register reserved token ${token.name}`);
|
333
369
|
let registrations = this.myMap.get(token);
|
334
370
|
if (!registrations) {
|
335
371
|
this.myMap.set(token, registrations = []);
|
372
|
+
} else if (registration.name !== undefined) {
|
373
|
+
const existing = registrations.filter((r)=>r.name === registration.name);
|
374
|
+
assert(existing.length === 0, `a ${token.name} token named '${registration.name}' is already registered`);
|
336
375
|
}
|
337
376
|
registrations.push(registration);
|
338
377
|
}
|
339
|
-
delete(token) {
|
378
|
+
delete(token, name) {
|
340
379
|
const registrations = this.myMap.get(token);
|
341
|
-
|
342
|
-
|
380
|
+
if (registrations) {
|
381
|
+
if (name !== undefined) {
|
382
|
+
const removedRegistrations = [];
|
383
|
+
const newRegistrations = [];
|
384
|
+
for (const registration of registrations){
|
385
|
+
const array = registration.name === name ? removedRegistrations : newRegistrations;
|
386
|
+
array.push(registration);
|
387
|
+
}
|
388
|
+
if (removedRegistrations.length > 0) {
|
389
|
+
this.myMap.set(token, newRegistrations);
|
390
|
+
return removedRegistrations;
|
391
|
+
}
|
392
|
+
}
|
393
|
+
this.myMap.delete(token);
|
394
|
+
}
|
395
|
+
return registrations ?? [];
|
343
396
|
}
|
344
397
|
deleteAll() {
|
345
398
|
const tokens = Array.from(this.myMap.keys());
|
@@ -367,9 +420,14 @@ class TokenRegistry {
|
|
367
420
|
}
|
368
421
|
return Array.from(values);
|
369
422
|
}
|
370
|
-
getAllFromParent(token) {
|
371
|
-
const
|
372
|
-
|
423
|
+
getAllFromParent(token, name) {
|
424
|
+
const thisRegistrations = this.myMap.get(token);
|
425
|
+
let registrations = thisRegistrations || this.myParent?.getAllFromParent(token, name);
|
426
|
+
if (registrations && name !== undefined) {
|
427
|
+
registrations = registrations.filter((r)=>r.name === name);
|
428
|
+
assert(registrations.length < 2, `internal error: more than one registration named '${name}'`);
|
429
|
+
}
|
430
|
+
return registrations ?? [];
|
373
431
|
}
|
374
432
|
}
|
375
433
|
// @internal
|
@@ -467,9 +525,6 @@ function isDisposable(value) {
|
|
467
525
|
getAllCached(token) {
|
468
526
|
this.checkDisposed();
|
469
527
|
const registrations = this.myTokenRegistry.getAll(token);
|
470
|
-
if (!registrations) {
|
471
|
-
return [];
|
472
|
-
}
|
473
528
|
const values = new Set();
|
474
529
|
for (const registration of registrations){
|
475
530
|
const value = registration.value;
|
@@ -491,46 +546,17 @@ function isDisposable(value) {
|
|
491
546
|
}
|
492
547
|
return Array.from(values);
|
493
548
|
}
|
494
|
-
isRegistered(token) {
|
549
|
+
isRegistered(token, name) {
|
495
550
|
this.checkDisposed();
|
496
|
-
return this.myTokenRegistry.get(token) !== undefined;
|
497
|
-
}
|
498
|
-
registerClass(token, Class, options) {
|
499
|
-
// This mess will go away once/if we remove the register method
|
500
|
-
// in favor of the multiple specialized ones
|
501
|
-
if (Class) {
|
502
|
-
const ctor = Class ?? token;
|
503
|
-
this.register(token, {
|
504
|
-
useClass: ctor
|
505
|
-
}, options);
|
506
|
-
} else {
|
507
|
-
this.register(token);
|
508
|
-
}
|
509
|
-
}
|
510
|
-
registerFactory(token, factory, options) {
|
511
|
-
this.register(token, {
|
512
|
-
useFactory: factory
|
513
|
-
}, options);
|
514
|
-
}
|
515
|
-
registerValue(token, value) {
|
516
|
-
this.register(token, {
|
517
|
-
useValue: value
|
518
|
-
});
|
519
|
-
}
|
520
|
-
registerAlias(targetToken, aliasTokens) {
|
521
|
-
// De-duplicate tokens
|
522
|
-
for (const alias of new Set(aliasTokens)){
|
523
|
-
this.register(alias, {
|
524
|
-
useExisting: targetToken
|
525
|
-
});
|
526
|
-
}
|
551
|
+
return this.myTokenRegistry.get(token, name) !== undefined;
|
527
552
|
}
|
528
553
|
register(...args) {
|
529
554
|
this.checkDisposed();
|
530
|
-
if (args.length
|
555
|
+
if (args.length === 1) {
|
531
556
|
const Class = args[0];
|
532
557
|
const metadata = getMetadata(Class);
|
533
558
|
const registration = {
|
559
|
+
name: metadata.name,
|
534
560
|
// The provider is of type ClassProvider, initialized by getMetadata
|
535
561
|
provider: metadata.provider,
|
536
562
|
options: {
|
@@ -558,10 +584,11 @@ function isDisposable(value) {
|
|
558
584
|
if (isClassProvider(provider)) {
|
559
585
|
const metadata = getMetadata(provider.useClass);
|
560
586
|
const registration = {
|
587
|
+
// An explicit provider name overrides what is specified via @Named
|
588
|
+
name: metadata.name ?? provider.name,
|
561
589
|
provider: metadata.provider,
|
562
590
|
options: {
|
563
|
-
//
|
564
|
-
// via class decorators (e.g., @Scoped)
|
591
|
+
// Explicit registration options override what is specified via class decorators (e.g., @Scoped)
|
565
592
|
scope: metadata.scope?.value ?? this.myOptions.defaultScope,
|
566
593
|
...options
|
567
594
|
},
|
@@ -573,10 +600,12 @@ function isDisposable(value) {
|
|
573
600
|
this.resolveProviderValue(registration, registration.provider);
|
574
601
|
}
|
575
602
|
} else {
|
576
|
-
|
603
|
+
const existingProvider = isExistingProvider(provider);
|
604
|
+
if (existingProvider) {
|
577
605
|
assert(token !== provider.useExisting, `the useExisting token ${token.name} cannot be the same as the token being registered`);
|
578
606
|
}
|
579
607
|
this.myTokenRegistry.set(token, {
|
608
|
+
name: existingProvider ? undefined : provider.name,
|
580
609
|
provider: provider,
|
581
610
|
options: options
|
582
611
|
});
|
@@ -584,12 +613,9 @@ function isDisposable(value) {
|
|
584
613
|
}
|
585
614
|
return this;
|
586
615
|
}
|
587
|
-
unregister(token) {
|
616
|
+
unregister(token, name) {
|
588
617
|
this.checkDisposed();
|
589
|
-
const registrations = this.myTokenRegistry.delete(token);
|
590
|
-
if (!registrations) {
|
591
|
-
return [];
|
592
|
-
}
|
618
|
+
const registrations = this.myTokenRegistry.delete(token, name);
|
593
619
|
const values = new Set();
|
594
620
|
for (const registration of registrations){
|
595
621
|
const value = registration.value;
|
@@ -599,22 +625,31 @@ function isDisposable(value) {
|
|
599
625
|
}
|
600
626
|
return Array.from(values);
|
601
627
|
}
|
602
|
-
resolve(token,
|
628
|
+
resolve(token, optionalOrName, name) {
|
603
629
|
this.checkDisposed();
|
604
|
-
|
630
|
+
let localOptional;
|
631
|
+
let localName;
|
632
|
+
if (typeof optionalOrName === "string") {
|
633
|
+
localName = optionalOrName;
|
634
|
+
} else {
|
635
|
+
localOptional = optionalOrName;
|
636
|
+
localName = name;
|
637
|
+
}
|
638
|
+
const registration = this.myTokenRegistry.get(token, localName);
|
605
639
|
if (registration) {
|
606
|
-
return this.resolveRegistration(token, registration);
|
640
|
+
return this.resolveRegistration(token, registration, localName);
|
607
641
|
}
|
608
642
|
if (isConstructor(token)) {
|
609
|
-
return this.instantiateClass(token,
|
643
|
+
return this.instantiateClass(token, localOptional);
|
610
644
|
}
|
611
|
-
return
|
645
|
+
return optionalOrName ? undefined : throwUnregisteredError(token);
|
612
646
|
}
|
613
647
|
resolveAll(token, optional) {
|
614
648
|
this.checkDisposed();
|
615
649
|
const registrations = this.myTokenRegistry.getAll(token);
|
616
|
-
if (registrations) {
|
617
|
-
return registrations
|
650
|
+
if (registrations.length > 0) {
|
651
|
+
return registrations //
|
652
|
+
.map((registration)=>this.resolveRegistration(token, registration)).filter((value)=>value != null);
|
618
653
|
}
|
619
654
|
if (isConstructor(token)) {
|
620
655
|
const instance = this.instantiateClass(token, optional);
|
@@ -650,12 +685,12 @@ function isDisposable(value) {
|
|
650
685
|
// Allow values to be GCed
|
651
686
|
disposedRefs.clear();
|
652
687
|
}
|
653
|
-
resolveRegistration(token, registration) {
|
688
|
+
resolveRegistration(token, registration, name) {
|
654
689
|
let currRegistration = registration;
|
655
690
|
let currProvider = currRegistration.provider;
|
656
691
|
while(isExistingProvider(currProvider)){
|
657
692
|
const targetToken = currProvider.useExisting;
|
658
|
-
currRegistration = this.myTokenRegistry.get(targetToken);
|
693
|
+
currRegistration = this.myTokenRegistry.get(targetToken, name);
|
659
694
|
if (!currRegistration) {
|
660
695
|
throwExistingUnregisteredError(token, targetToken);
|
661
696
|
}
|
@@ -786,7 +821,7 @@ function isDisposable(value) {
|
|
786
821
|
}
|
787
822
|
}
|
788
823
|
resolveScope(scope = this.myOptions.defaultScope, context = useInjectionContext()) {
|
789
|
-
if (scope
|
824
|
+
if (scope === Scope.Inherited) {
|
790
825
|
const dependentFrame = context?.resolution.stack.peek();
|
791
826
|
return dependentFrame?.scope || Scope.Transient;
|
792
827
|
}
|
@@ -796,7 +831,7 @@ function isDisposable(value) {
|
|
796
831
|
const dependencies = registration.dependencies;
|
797
832
|
if (dependencies) {
|
798
833
|
assert(isClassProvider(registration.provider), `internal error: not a ClassProvider`);
|
799
|
-
const ctorDeps = dependencies.constructor;
|
834
|
+
const ctorDeps = dependencies.constructor.filter((d)=>d.appliedBy);
|
800
835
|
if (ctorDeps.length > 0) {
|
801
836
|
// Let's check if all necessary constructor parameters are decorated.
|
802
837
|
// If not, we cannot safely create an instance.
|
@@ -807,13 +842,13 @@ function isDisposable(value) {
|
|
807
842
|
});
|
808
843
|
return ctorDeps.sort((a, b)=>a.index - b.index).map((dep)=>{
|
809
844
|
const token = dep.tokenRef.getRefToken();
|
810
|
-
switch(dep.
|
845
|
+
switch(dep.appliedBy){
|
811
846
|
case "Inject":
|
812
|
-
return this.resolve(token);
|
847
|
+
return this.resolve(token, dep.name);
|
813
848
|
case "InjectAll":
|
814
849
|
return this.resolveAll(token);
|
815
850
|
case "Optional":
|
816
|
-
return this.resolve(token, true);
|
851
|
+
return this.resolve(token, true, dep.name);
|
817
852
|
case "OptionalAll":
|
818
853
|
return this.resolveAll(token, true);
|
819
854
|
}
|
@@ -828,7 +863,9 @@ function isDisposable(value) {
|
|
828
863
|
assert(isClassProvider(registration.provider), `internal error: not a ClassProvider`);
|
829
864
|
const ctor = registration.provider.useClass;
|
830
865
|
// Perform method injection
|
831
|
-
for (const
|
866
|
+
for (const entry of dependencies.methods){
|
867
|
+
const key = entry[0];
|
868
|
+
const methodDeps = entry[1].filter((d)=>d.appliedBy);
|
832
869
|
// Let's check if all necessary method parameters are decorated.
|
833
870
|
// If not, we cannot safely invoke the method.
|
834
871
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
@@ -839,13 +876,13 @@ function isDisposable(value) {
|
|
839
876
|
});
|
840
877
|
const args = methodDeps.sort((a, b)=>a.index - b.index).map((dep)=>{
|
841
878
|
const token = dep.tokenRef.getRefToken();
|
842
|
-
switch(dep.
|
879
|
+
switch(dep.appliedBy){
|
843
880
|
case "Inject":
|
844
|
-
return injectBy(instance, token);
|
881
|
+
return injectBy(instance, token, dep.name);
|
845
882
|
case "InjectAll":
|
846
883
|
return injectAll(token);
|
847
884
|
case "Optional":
|
848
|
-
return optionalBy(instance, token);
|
885
|
+
return optionalBy(instance, token, dep.name);
|
849
886
|
case "OptionalAll":
|
850
887
|
return optionalAll(token);
|
851
888
|
}
|
@@ -905,7 +942,7 @@ function isDisposable(value) {
|
|
905
942
|
*
|
906
943
|
* // Wizard is registered with Container scope, and an instance
|
907
944
|
* // is immediately created and cached by the container
|
908
|
-
*
|
945
|
+
* container.register(Wizard);
|
909
946
|
* ```
|
910
947
|
*
|
911
948
|
* @__NO_SIDE_EFFECTS__
|
@@ -954,41 +991,31 @@ function isTokenRef(value) {
|
|
954
991
|
return value && typeof value === "object" && typeof value.getRefToken === "function";
|
955
992
|
}
|
956
993
|
|
957
|
-
|
958
|
-
|
959
|
-
//
|
994
|
+
// @internal
|
995
|
+
function updateParameterMetadata(decorator, target, propertyKey, parameterIndex, updateFn) {
|
996
|
+
// Error out immediately if the decorator has been applied to a static method
|
960
997
|
if (propertyKey !== undefined && typeof target === "function") {
|
961
|
-
assert(false, `@${decorator} cannot be used on static
|
998
|
+
assert(false, `@${decorator} cannot be used on static method ${target.name}.${String(propertyKey)}`);
|
962
999
|
}
|
963
|
-
const tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
964
1000
|
if (propertyKey === undefined) {
|
965
1001
|
// Constructor
|
966
1002
|
const metadata = getMetadata(target);
|
967
|
-
metadata.
|
968
|
-
|
969
|
-
tokenRef: tokenRef,
|
970
|
-
index: parameterIndex
|
971
|
-
});
|
1003
|
+
const dependency = metadata.getConstructorDependency(parameterIndex);
|
1004
|
+
updateFn(dependency);
|
972
1005
|
} else {
|
973
|
-
//
|
1006
|
+
// Instance method
|
974
1007
|
const metadata = getMetadata(target.constructor);
|
975
|
-
const
|
976
|
-
|
977
|
-
if (dep === undefined) {
|
978
|
-
dep = [];
|
979
|
-
methods.set(propertyKey, dep);
|
980
|
-
}
|
981
|
-
dep.push({
|
982
|
-
decorator: decorator,
|
983
|
-
tokenRef: tokenRef,
|
984
|
-
index: parameterIndex
|
985
|
-
});
|
1008
|
+
const dependency = metadata.getMethodDependency(propertyKey, parameterIndex);
|
1009
|
+
updateFn(dependency);
|
986
1010
|
}
|
987
1011
|
}
|
988
1012
|
|
989
1013
|
function Inject(token) {
|
990
1014
|
return function(target, propertyKey, parameterIndex) {
|
991
|
-
|
1015
|
+
updateParameterMetadata("Inject", target, propertyKey, parameterIndex, (dependency)=>{
|
1016
|
+
dependency.appliedBy = "Inject";
|
1017
|
+
dependency.tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
1018
|
+
});
|
992
1019
|
};
|
993
1020
|
}
|
994
1021
|
|
@@ -1014,19 +1041,66 @@ function Inject(token) {
|
|
1014
1041
|
|
1015
1042
|
function InjectAll(token) {
|
1016
1043
|
return function(target, propertyKey, parameterIndex) {
|
1017
|
-
|
1044
|
+
updateParameterMetadata("InjectAll", target, propertyKey, parameterIndex, (dependency)=>{
|
1045
|
+
dependency.appliedBy = "InjectAll";
|
1046
|
+
dependency.tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
1047
|
+
});
|
1048
|
+
};
|
1049
|
+
}
|
1050
|
+
|
1051
|
+
/**
|
1052
|
+
* Qualifies a class or an injected parameter with a unique name.
|
1053
|
+
*
|
1054
|
+
* This allows the container to distinguish between multiple implementations
|
1055
|
+
* of the same interface or type during registration and injection.
|
1056
|
+
*
|
1057
|
+
* @example
|
1058
|
+
* ```ts
|
1059
|
+
* @Named("dumbledore")
|
1060
|
+
* class Dumbledore implements Wizard {}
|
1061
|
+
*
|
1062
|
+
* // Register Dumbledore with Type<Wizard>
|
1063
|
+
* container.register(IWizard, { useClass: Dumbledore });
|
1064
|
+
* const dumbledore = container.resolve(IWizard, "dumbledore");
|
1065
|
+
* ```
|
1066
|
+
*
|
1067
|
+
* @__NO_SIDE_EFFECTS__
|
1068
|
+
*/ function Named(name) {
|
1069
|
+
if (!name.trim()) {
|
1070
|
+
assert(false, "the @Named qualifier cannot be empty or blank");
|
1071
|
+
}
|
1072
|
+
return function(target, propertyKey, parameterIndex) {
|
1073
|
+
if (parameterIndex === undefined) {
|
1074
|
+
// The decorator has been applied to the class
|
1075
|
+
const ctor = target;
|
1076
|
+
const metadata = getMetadata(ctor);
|
1077
|
+
assert(!metadata.name, `a @Named('${metadata.name}') qualifier has already been applied to ${ctor.name}`);
|
1078
|
+
metadata.name = name;
|
1079
|
+
} else {
|
1080
|
+
// The decorator has been applied to a method parameter
|
1081
|
+
updateParameterMetadata("Named", target, propertyKey, parameterIndex, (dependency)=>{
|
1082
|
+
assert(!dependency.name, `a @Named('${dependency.name}') qualifier has already been applied to the parameter`);
|
1083
|
+
dependency.name = name;
|
1084
|
+
});
|
1085
|
+
}
|
1018
1086
|
};
|
1019
1087
|
}
|
1020
1088
|
|
1021
1089
|
function Optional(token) {
|
1022
1090
|
return function(target, propertyKey, parameterIndex) {
|
1023
|
-
|
1091
|
+
updateParameterMetadata("Optional", target, propertyKey, parameterIndex, (dependency)=>{
|
1092
|
+
dependency.appliedBy = "Optional";
|
1093
|
+
dependency.tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
1094
|
+
});
|
1024
1095
|
};
|
1025
1096
|
}
|
1026
1097
|
|
1027
1098
|
function OptionalAll(token) {
|
1028
1099
|
return function(target, propertyKey, parameterIndex) {
|
1029
|
-
|
1100
|
+
updateParameterMetadata("OptionalAll", target, propertyKey, parameterIndex, (dependency)=>{
|
1101
|
+
dependency.appliedBy = "OptionalAll";
|
1102
|
+
dependency.tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
1103
|
+
});
|
1030
1104
|
};
|
1031
1105
|
}
|
1032
1106
|
|
@@ -1158,5 +1232,5 @@ function OptionalAll(token) {
|
|
1158
1232
|
return container;
|
1159
1233
|
}
|
1160
1234
|
|
1161
|
-
export { AutoRegister, EagerInstantiate, Inject, InjectAll, Injectable, Injector, Optional, OptionalAll, Scope, Scoped, applyMiddleware, build, createContainer, createType, forwardRef, inject, injectAll, injectBy, setClassIdentityMapping };
|
1235
|
+
export { AutoRegister, EagerInstantiate, Inject, InjectAll, Injectable, Injector, Named, Optional, OptionalAll, Scope, Scoped, applyMiddleware, build, createContainer, createType, forwardRef, inject, injectAll, injectBy, setClassIdentityMapping };
|
1162
1236
|
//# sourceMappingURL=index.mjs.map
|