@lppedd/di-wise-neo 0.9.1 → 0.9.3

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
@@ -1,32 +1,5 @@
1
1
  Object.defineProperty(exports, '__esModule', { value: true });
2
2
 
3
- /**
4
- * Type API.
5
- */ /**
6
- * Creates a type token.
7
- *
8
- * @example
9
- * ```ts
10
- * const ISpell = createType<Spell>("Spell");
11
- * ```
12
- *
13
- * @__NO_SIDE_EFFECTS__
14
- */ function createType(typeName) {
15
- const type = {
16
- name: `Type<${typeName}>`,
17
- inter: createType,
18
- union: createType,
19
- toString () {
20
- return type.name;
21
- }
22
- };
23
- return type;
24
- }
25
- // @internal
26
- function isConstructor(token) {
27
- return typeof token === "function";
28
- }
29
-
30
3
  // @internal
31
4
  function check(condition, message) {
32
5
  if (!condition) {
@@ -39,18 +12,35 @@ function expectNever(value) {
39
12
  }
40
13
  // @internal
41
14
  function throwUnregisteredError(token, name) {
42
- const type = isConstructor(token) ? "class" : "token";
43
15
  const spec = name !== undefined ? `[name=${name}]` : "";
44
- throw new Error(tag(`unregistered ${type} ${token.name}${spec}`));
16
+ throw new Error(tag(`unregistered token ${getTokenName(token)}${spec}`));
45
17
  }
46
18
  // @internal
47
- function throwExistingUnregisteredError(sourceToken, targetTokenOrError) {
48
- let message = tag(`token resolution error encountered while resolving ${sourceToken.name}`);
49
- message += isError(targetTokenOrError) ? `\n [cause] ${untag(targetTokenOrError.message)}` : `\n [cause] the aliased token ${targetTokenOrError.name} is not registered`;
50
- throw new Error(message);
19
+ function throwExistingUnregisteredError(token, cause) {
20
+ const message = tag(`failed to resolve token ${getTokenName(token)}`);
21
+ throw isError(cause) ? new Error(`${message}\n [cause] ${untag(cause.message)}`, {
22
+ cause
23
+ }) : new Error(`${message}\n [cause] the aliased token ${getTokenName(cause)} is not registered`);
24
+ }
25
+ // @internal
26
+ function throwParameterResolutionError(ctor, methodKey, dependency, cause) {
27
+ const location = getLocation(ctor, methodKey);
28
+ const token = dependency.tokenRef.getRefToken();
29
+ const message = tag(`failed to resolve dependency for ${location}(parameter #${dependency.index}: ${token.name})`);
30
+ throw new Error(`${message}\n [cause] ${untag(cause.message)}`, {
31
+ cause
32
+ });
33
+ }
34
+ // @internal
35
+ function getLocation(ctor, methodKey) {
36
+ const ctorName = ctor.name || "<unnamed>";
37
+ return methodKey ? `${ctorName}.${String(methodKey)}` : ctorName;
38
+ }
39
+ // @internal
40
+ function getTokenName(token) {
41
+ return token.name || "<unnamed>";
51
42
  }
52
43
  function isError(value) {
53
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
54
44
  return value && value.stack && value.message && typeof value.message === "string";
55
45
  }
56
46
  function tag(message) {
@@ -82,7 +72,7 @@ class KeyedStack {
82
72
  };
83
73
  }
84
74
  constructor(){
85
- this.myEntries = new Array();
75
+ this.myEntries = [];
86
76
  this.myKeys = new WeakSet();
87
77
  }
88
78
  }
@@ -115,6 +105,7 @@ class WeakRefMap {
115
105
  // @internal
116
106
  function createResolution() {
117
107
  return {
108
+ tokenStack: [],
118
109
  stack: new KeyedStack(),
119
110
  values: new WeakRefMap(),
120
111
  dependents: new WeakRefMap()
@@ -175,7 +166,7 @@ function injectAll(token) {
175
166
  class Metadata {
176
167
  constructor(Class){
177
168
  this.dependencies = {
178
- constructor: [],
169
+ ctor: [],
179
170
  methods: new Map()
180
171
  };
181
172
  this.tokensRef = {
@@ -191,15 +182,15 @@ class Metadata {
191
182
  set name(name) {
192
183
  this.provider.name = name;
193
184
  }
194
- getConstructorDependency(index) {
195
- const i = this.dependencies.constructor.findIndex((d)=>d.index === index);
185
+ getCtorDependency(index) {
186
+ const i = this.dependencies.ctor.findIndex((d)=>d.index === index);
196
187
  if (i > -1) {
197
- return this.dependencies.constructor[i];
188
+ return this.dependencies.ctor[i];
198
189
  }
199
190
  const dependency = {
200
191
  index: index
201
192
  };
202
- this.dependencies.constructor.push(dependency);
193
+ this.dependencies.ctor.push(dependency);
203
194
  return dependency;
204
195
  }
205
196
  getMethodDependency(method, index) {
@@ -313,6 +304,33 @@ const Scope = {
313
304
  Container: "Container"
314
305
  };
315
306
 
307
+ /**
308
+ * Type API.
309
+ */ /**
310
+ * Creates a type token.
311
+ *
312
+ * @example
313
+ * ```ts
314
+ * const ISpell = createType<Spell>("Spell");
315
+ * ```
316
+ *
317
+ * @__NO_SIDE_EFFECTS__
318
+ */ function createType(typeName) {
319
+ const type = {
320
+ name: `Type<${typeName}>`,
321
+ inter: createType,
322
+ union: createType,
323
+ toString () {
324
+ return type.name;
325
+ }
326
+ };
327
+ return type;
328
+ }
329
+ // @internal
330
+ function isConstructor(token) {
331
+ return typeof token === "function";
332
+ }
333
+
316
334
  // @internal
317
335
  function getTypeName(value) {
318
336
  switch(typeof value){
@@ -327,9 +345,9 @@ function getTypeName(value) {
327
345
  }
328
346
  const proto = Object.getPrototypeOf(value);
329
347
  if (proto && proto !== Object.prototype) {
330
- const constructor = proto.constructor;
331
- if (typeof constructor === "function" && constructor.name) {
332
- return constructor.name;
348
+ const ctor = proto.constructor;
349
+ if (typeof ctor === "function" && ctor.name) {
350
+ return ctor.name;
333
351
  }
334
352
  }
335
353
  }
@@ -445,7 +463,6 @@ const builders = new WeakSet();
445
463
  // @internal
446
464
  // @internal
447
465
  function isDisposable(value) {
448
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
449
466
  return value && typeof value === "object" && typeof value.dispose === "function";
450
467
  }
451
468
 
@@ -550,13 +567,13 @@ function isDisposable(value) {
550
567
  }
551
568
  // Eager-instantiate only if the class is container-scoped
552
569
  if (metadata.eagerInstantiate && registration.options?.scope === Scope.Container) {
553
- this.resolveProviderValue(registration, registration.provider);
570
+ this.resolveProviderValue(Class, registration);
554
571
  }
555
572
  } else {
556
573
  const [token, provider, options] = args;
557
574
  const existingProvider = isExistingProvider(provider);
558
575
  const name = existingProvider ? undefined : provider.name;
559
- check(name === undefined || name.trim(), "the provider name qualifier cannot be empty or blank");
576
+ check(name === undefined || name.trim(), `the name qualifier for token ${getTokenName(token)} must not be empty`);
560
577
  if (isClassProvider(provider)) {
561
578
  const metadata = getMetadata(provider.useClass);
562
579
  const registration = {
@@ -573,7 +590,7 @@ function isDisposable(value) {
573
590
  this.myTokenRegistry.set(token, registration);
574
591
  // Eager-instantiate only if the provided class is container-scoped
575
592
  if (metadata.eagerInstantiate && registration.options?.scope === Scope.Container) {
576
- this.resolveProviderValue(registration, registration.provider);
593
+ this.resolveProviderValue(token, registration);
577
594
  }
578
595
  } else {
579
596
  if (existingProvider) {
@@ -663,17 +680,15 @@ function isDisposable(value) {
663
680
  }
664
681
  resolveRegistration(token, registration, name) {
665
682
  let currRegistration = registration;
666
- let currProvider = currRegistration.provider;
667
- while(isExistingProvider(currProvider)){
668
- const targetToken = currProvider.useExisting;
683
+ while(isExistingProvider(currRegistration.provider)){
684
+ const targetToken = currRegistration.provider.useExisting;
669
685
  currRegistration = this.myTokenRegistry.get(targetToken, name);
670
686
  if (!currRegistration) {
671
687
  throwExistingUnregisteredError(token, targetToken);
672
688
  }
673
- currProvider = currRegistration.provider;
674
689
  }
675
690
  try {
676
- return this.resolveProviderValue(currRegistration, currProvider);
691
+ return this.resolveProviderValue(token, currRegistration);
677
692
  } catch (e) {
678
693
  // If we were trying to resolve a token registered via ExistingProvider,
679
694
  // we must add the cause of the error to the message
@@ -700,16 +715,15 @@ function isDisposable(value) {
700
715
  }
701
716
  return undefined;
702
717
  }
703
- resolveProviderValue(registration, provider) {
704
- check(registration.provider === provider, "internal error: mismatching provider");
718
+ resolveProviderValue(token, registration) {
719
+ const provider = registration.provider;
705
720
  if (isClassProvider(provider)) {
706
721
  const Class = provider.useClass;
707
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
708
- return this.resolveScopedValue(registration, (args)=>new Class(...args));
722
+ return this.resolveScopedValue(token, registration, (args)=>new Class(...args));
709
723
  }
710
724
  if (isFactoryProvider(provider)) {
711
725
  const factory = provider.useFactory;
712
- return this.resolveScopedValue(registration, factory);
726
+ return this.resolveScopedValue(token, registration, factory);
713
727
  }
714
728
  if (isValueProvider(provider)) {
715
729
  return provider.useValue;
@@ -717,7 +731,7 @@ function isDisposable(value) {
717
731
  check(!isExistingProvider(provider), "internal error: unexpected ExistingProvider");
718
732
  expectNever(provider);
719
733
  }
720
- resolveScopedValue(registration, factory) {
734
+ resolveScopedValue(token, registration, factory) {
721
735
  let context = useInjectionContext();
722
736
  if (!context || context.container !== this) {
723
737
  context = {
@@ -730,12 +744,16 @@ function isDisposable(value) {
730
744
  const options = registration.options;
731
745
  if (resolution.stack.has(provider)) {
732
746
  const dependentRef = resolution.dependents.get(provider);
733
- check(dependentRef, "circular dependency detected");
747
+ check(dependentRef, ()=>{
748
+ const path = resolution.tokenStack.map((t)=>t.name).join(" → ");
749
+ return `circular dependency detected while resolving ${path} → ${token.name}`;
750
+ });
734
751
  return dependentRef.current;
735
752
  }
736
753
  const scope = this.resolveScope(options?.scope, context);
737
754
  const cleanups = [
738
755
  provideInjectionContext(context),
756
+ resolution.tokenStack.push(token) && (()=>resolution.tokenStack.pop()),
739
757
  !isBuilder(provider) && resolution.stack.push(provider, {
740
758
  provider,
741
759
  scope
@@ -749,8 +767,8 @@ function isDisposable(value) {
749
767
  if (valueRef) {
750
768
  return valueRef.current;
751
769
  }
752
- const args = this.resolveConstructorDependencies(registration);
753
- const value = this.injectDependencies(registration, factory(args));
770
+ const args = this.resolveCtorDependencies(registration);
771
+ const value = this.injectMethodDependencies(registration, factory(args));
754
772
  registration.value = {
755
773
  current: value
756
774
  };
@@ -762,8 +780,8 @@ function isDisposable(value) {
762
780
  if (valueRef) {
763
781
  return valueRef.current;
764
782
  }
765
- const args = this.resolveConstructorDependencies(registration);
766
- const value = this.injectDependencies(registration, factory(args));
783
+ const args = this.resolveCtorDependencies(registration);
784
+ const value = this.injectMethodDependencies(registration, factory(args));
767
785
  resolution.values.set(provider, {
768
786
  current: value
769
787
  });
@@ -771,8 +789,8 @@ function isDisposable(value) {
771
789
  }
772
790
  case Scope.Transient:
773
791
  {
774
- const args = this.resolveConstructorDependencies(registration);
775
- return this.injectDependencies(registration, factory(args));
792
+ const args = this.resolveCtorDependencies(registration);
793
+ return this.injectMethodDependencies(registration, factory(args));
776
794
  }
777
795
  }
778
796
  } finally{
@@ -786,72 +804,74 @@ function isDisposable(value) {
786
804
  }
787
805
  return scope;
788
806
  }
789
- resolveConstructorDependencies(registration) {
807
+ resolveCtorDependencies(registration) {
790
808
  const dependencies = registration.dependencies;
791
809
  if (dependencies) {
792
810
  check(isClassProvider(registration.provider), `internal error: not a ClassProvider`);
793
- const ctorDeps = dependencies.constructor.filter((d)=>d.appliedBy);
811
+ const ctorDeps = dependencies.ctor.filter((d)=>d.appliedBy);
794
812
  if (ctorDeps.length > 0) {
795
813
  // Let's check if all necessary constructor parameters are decorated.
796
814
  // If not, we cannot safely create an instance.
797
815
  const ctor = registration.provider.useClass;
798
816
  check(ctor.length === ctorDeps.length, ()=>{
799
- const msg = `expected ${ctor.length} decorated constructor parameters in ${ctor.name}`;
817
+ const location = getLocation(ctor);
818
+ const msg = `${location} expected ${ctor.length} decorated constructor parameters`;
800
819
  return msg + `, but found ${ctorDeps.length}`;
801
820
  });
802
- return ctorDeps.sort((a, b)=>a.index - b.index).map((dep)=>{
803
- const token = dep.tokenRef.getRefToken();
804
- switch(dep.appliedBy){
805
- case "Inject":
806
- return this.resolve(token, dep.name);
807
- case "InjectAll":
808
- return this.resolveAll(token);
809
- case "Optional":
810
- return this.resolve(token, true, dep.name);
811
- case "OptionalAll":
812
- return this.resolveAll(token, true);
813
- }
814
- });
821
+ return this.resolveArgs(ctorDeps, ctor);
815
822
  }
816
823
  }
817
824
  return [];
818
825
  }
819
- injectDependencies(registration, instance) {
826
+ injectMethodDependencies(registration, instance) {
820
827
  const dependencies = registration.dependencies;
821
828
  if (dependencies) {
822
829
  check(isClassProvider(registration.provider), `internal error: not a ClassProvider`);
823
830
  const ctor = registration.provider.useClass;
824
831
  // Perform method injection
825
832
  for (const entry of dependencies.methods){
826
- const key = entry[0];
833
+ const methodKey = entry[0];
827
834
  const methodDeps = entry[1].filter((d)=>d.appliedBy);
828
835
  // Let's check if all necessary method parameters are decorated.
829
836
  // If not, we cannot safely invoke the method.
830
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
831
- const method = instance[key];
837
+ const method = instance[methodKey];
832
838
  check(methodDeps.length === method.length, ()=>{
833
- const msg = `expected ${method.length} decorated method parameters`;
834
- return msg + ` in ${ctor.name}.${String(key)}, but found ${methodDeps.length}`;
835
- });
836
- const args = methodDeps.sort((a, b)=>a.index - b.index).map((dep)=>{
837
- const token = dep.tokenRef.getRefToken();
838
- switch(dep.appliedBy){
839
- case "Inject":
840
- return injectBy(instance, token, dep.name);
841
- case "InjectAll":
842
- return injectAll(token);
843
- case "Optional":
844
- return optionalBy(instance, token, dep.name);
845
- case "OptionalAll":
846
- return optionalAll(token);
847
- }
839
+ const location = getLocation(ctor, methodKey);
840
+ const msg = `${location} expected ${method.length} decorated method parameters`;
841
+ return msg + `, but found ${methodDeps.length}`;
848
842
  });
849
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call
843
+ const args = this.resolveArgs(methodDeps, ctor, instance, methodKey);
850
844
  method.bind(instance)(...args);
851
845
  }
852
846
  }
853
847
  return instance;
854
848
  }
849
+ resolveArgs(deps, ctor, instance, methodKey) {
850
+ const sortedDeps = deps.sort((a, b)=>a.index - b.index);
851
+ const args = [];
852
+ for (const dep of sortedDeps){
853
+ try {
854
+ args.push(this.resolveDependency(dep, instance));
855
+ } catch (e) {
856
+ throwParameterResolutionError(ctor, methodKey, dep, e);
857
+ }
858
+ }
859
+ return args;
860
+ }
861
+ resolveDependency(dependency, instance) {
862
+ const token = dependency.tokenRef.getRefToken();
863
+ const name = dependency.name;
864
+ switch(dependency.appliedBy){
865
+ case "Inject":
866
+ return instance ? injectBy(instance, token, name) : this.resolve(token, name);
867
+ case "InjectAll":
868
+ return instance ? injectAll(token) : this.resolveAll(token);
869
+ case "Optional":
870
+ return instance ? optionalBy(instance, token, name) : this.resolve(token, true, name);
871
+ case "OptionalAll":
872
+ return instance ? optionalAll(token) : this.resolveAll(token, true);
873
+ }
874
+ }
855
875
  checkDisposed() {
856
876
  check(!this.myDisposed, "the container is disposed");
857
877
  }
@@ -907,11 +927,13 @@ function isDisposable(value) {
907
927
  * @__NO_SIDE_EFFECTS__
908
928
  */ function EagerInstantiate() {
909
929
  return function(Class) {
910
- const metadata = getMetadata(Class);
930
+ const ctor = Class;
931
+ const metadata = getMetadata(ctor);
911
932
  const currentScope = metadata.scope;
912
933
  check(!currentScope || currentScope.value === Scope.Container, ()=>{
913
934
  const { value, appliedBy } = currentScope;
914
- return `class ${Class.name}: Scope.${value} was already set by @${appliedBy},\n ` + `but @EagerInstantiate is trying to set a conflicting Scope.Container.\n ` + `Only one decorator should set the class scope, or all must agree on the same value.`;
935
+ const className = getTokenName(ctor);
936
+ return `class ${className}: Scope.${value} was already set by @${appliedBy},\n ` + `but @EagerInstantiate is trying to set a conflicting Scope.Container.\n ` + `Only one decorator should set the class scope, or all must agree on the same value.`;
915
937
  });
916
938
  metadata.eagerInstantiate = true;
917
939
  metadata.scope = {
@@ -941,30 +963,28 @@ function forwardRef(token) {
941
963
  }
942
964
  // @internal
943
965
  function isTokensRef(value) {
944
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
945
966
  return value && typeof value === "object" && typeof value.getRefTokens === "function";
946
967
  }
947
968
  // @internal
948
969
  function isTokenRef(value) {
949
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
950
970
  return value && typeof value === "object" && typeof value.getRefToken === "function";
951
971
  }
952
972
 
953
973
  // @internal
954
- function updateParameterMetadata(decorator, target, propertyKey, parameterIndex, updateFn) {
974
+ function updateParameterMetadata(decorator, target, methodKey, parameterIndex, updateFn) {
955
975
  // Error out immediately if the decorator has been applied to a static method
956
- if (propertyKey !== undefined && typeof target === "function") {
957
- check(false, `@${decorator} cannot be used on static method ${target.name}.${String(propertyKey)}`);
976
+ if (methodKey !== undefined && typeof target === "function") {
977
+ check(false, `@${decorator} cannot be used on static method ${target.name}.${String(methodKey)}`);
958
978
  }
959
- if (propertyKey === undefined) {
979
+ if (methodKey === undefined) {
960
980
  // Constructor
961
981
  const metadata = getMetadata(target);
962
- const dependency = metadata.getConstructorDependency(parameterIndex);
982
+ const dependency = metadata.getCtorDependency(parameterIndex);
963
983
  updateFn(dependency);
964
984
  } else {
965
985
  // Instance method
966
986
  const metadata = getMetadata(target.constructor);
967
- const dependency = metadata.getMethodDependency(propertyKey, parameterIndex);
987
+ const dependency = metadata.getMethodDependency(methodKey, parameterIndex);
968
988
  updateFn(dependency);
969
989
  }
970
990
  }
@@ -973,30 +993,30 @@ function updateParameterMetadata(decorator, target, propertyKey, parameterIndex,
973
993
  // understand which one "wins", unless the user is aware of the decorator evaluation order.
974
994
  //
975
995
  // @internal
976
- function checkSingleDecorator(dependency, target, propertyKey, parameterIndex) {
996
+ function checkSingleDecorator(dependency, target, methodKey, parameterIndex) {
977
997
  check(dependency.appliedBy === undefined, ()=>{
978
- const location = getLocation(target, propertyKey, parameterIndex);
979
- return `multiple injection decorators on ${location}, but only one is allowed`;
998
+ const param = describeParam(target, methodKey, parameterIndex);
999
+ return `multiple injection decorators on ${param}, but only one is allowed`;
980
1000
  });
981
1001
  }
982
1002
  // Checks that the `@Named` decorator is not used in combination with
983
1003
  // `@InjectAll` or `@OptionalAll`, which ignore the name qualification.
984
1004
  //
985
1005
  // @internal
986
- function checkNamedDecorator(dependency, target, propertyKey, parameterIndex) {
1006
+ function checkNamedDecorator(dependency, target, methodKey, parameterIndex) {
987
1007
  const { appliedBy, name } = dependency;
988
1008
  check(name === undefined || appliedBy !== "InjectAll" && appliedBy !== "OptionalAll", ()=>{
989
- const location = getLocation(target, propertyKey, parameterIndex);
990
- return `@Named has no effect on ${location} when used with @${appliedBy}`;
1009
+ const param = describeParam(target, methodKey, parameterIndex);
1010
+ return `@Named has no effect on ${param} when used with @${appliedBy}`;
991
1011
  });
992
1012
  }
993
1013
  // Returns a human-readable description of the parameter location.
994
1014
  // For example: "Wizard constructor parameter 2" or "Wizard.set parameter 0"
995
1015
  //
996
1016
  // @internal
997
- function getLocation(target, propertyKey, parameterIndex) {
998
- const location = propertyKey === undefined ? `${target.name} constructor` : `${target.constructor.name}.${String(propertyKey)}`;
999
- return `${location} parameter ${parameterIndex}`;
1017
+ function describeParam(target, methodKey, parameterIndex) {
1018
+ const location = methodKey === undefined ? target.name : `${target.constructor.name}.${String(methodKey)}`;
1019
+ return `${location}(parameter #${parameterIndex})`;
1000
1020
  }
1001
1021
 
1002
1022
  function Inject(token) {
@@ -1058,20 +1078,21 @@ function InjectAll(token) {
1058
1078
  *
1059
1079
  * @__NO_SIDE_EFFECTS__
1060
1080
  */ function Named(name) {
1061
- check(name.trim(), "the @Named qualifier cannot be empty or blank");
1081
+ check(name.trim(), "the @Named qualifier must not be empty");
1062
1082
  return function(target, propertyKey, parameterIndex) {
1063
1083
  if (parameterIndex === undefined) {
1064
1084
  // The decorator has been applied to the class
1065
1085
  const ctor = target;
1066
1086
  const metadata = getMetadata(ctor);
1067
- check(metadata.name === undefined, `multiple @Named decorators on class ${ctor.name}, but only one is allowed`);
1087
+ const className = getTokenName(ctor);
1088
+ check(metadata.name === undefined, `multiple @Named decorators on class ${className}, but only one is allowed`);
1068
1089
  metadata.name = name;
1069
1090
  } else {
1070
1091
  // The decorator has been applied to a method parameter
1071
1092
  updateParameterMetadata("Named", target, propertyKey, parameterIndex, (dependency)=>{
1072
1093
  check(dependency.name === undefined, ()=>{
1073
- const location = getLocation(target, propertyKey, parameterIndex);
1074
- return `multiple @Named decorators on ${location}, but only one is allowed`;
1094
+ const param = describeParam(target, propertyKey, parameterIndex);
1095
+ return `multiple @Named decorators on ${param}, but only one is allowed`;
1075
1096
  });
1076
1097
  dependency.name = name;
1077
1098
  checkNamedDecorator(dependency, target, propertyKey, parameterIndex);
@@ -1124,12 +1145,14 @@ function OptionalAll(token) {
1124
1145
  * @__NO_SIDE_EFFECTS__
1125
1146
  */ function Scoped(scope) {
1126
1147
  return function(Class) {
1127
- const metadata = getMetadata(Class);
1148
+ const ctor = Class;
1149
+ const metadata = getMetadata(ctor);
1128
1150
  const currentScope = metadata.scope;
1129
1151
  check(!currentScope || currentScope.value === scope, ()=>{
1130
1152
  const { value, appliedBy } = currentScope;
1131
1153
  const by = appliedBy === "Scoped" ? `another @${appliedBy} decorator` : `@${appliedBy}`;
1132
- return `class ${Class.name}: Scope.${value} was already set by ${by},\n ` + `but @Scoped is trying to set a conflicting Scope.${scope}.\n ` + `Only one decorator should set the class scope, or all must agree on the same value.`;
1154
+ const className = getTokenName(ctor);
1155
+ return `class ${className}: Scope.${value} was already set by ${by},\n ` + `but @Scoped is trying to set a conflicting Scope.${scope}.\n ` + `Only one decorator should set the class scope, or all must agree on the same value.`;
1133
1156
  });
1134
1157
  metadata.scope = {
1135
1158
  value: scope,
@@ -1211,10 +1234,7 @@ function OptionalAll(token) {
1211
1234
  use (key, wrap) {
1212
1235
  // We need to bind the 'this' context of the function to the container
1213
1236
  // before passing it to the middleware wrapper.
1214
- //
1215
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-call
1216
1237
  const fn = container[key].bind(container);
1217
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
1218
1238
  container[key] = wrap(fn);
1219
1239
  return composer;
1220
1240
  }