@lppedd/di-wise-neo 0.7.2 → 0.8.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/dist/cjs/index.d.ts +11 -2
- package/dist/cjs/index.js +82 -86
- package/dist/cjs/index.js.map +1 -1
- package/dist/es/index.d.mts +11 -2
- package/dist/es/index.mjs +82 -86
- package/dist/es/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/cjs/index.d.ts
CHANGED
@@ -187,8 +187,6 @@ interface RegistrationOptions {
|
|
187
187
|
* );
|
188
188
|
* }
|
189
189
|
* ```
|
190
|
-
*
|
191
|
-
* @__NO_SIDE_EFFECTS__
|
192
190
|
*/
|
193
191
|
declare function build<Value>(factory: (...args: []) => Value): Type<Value>;
|
194
192
|
|
@@ -811,6 +809,17 @@ interface Injector {
|
|
811
809
|
* or an empty array if the token is not registered in the container.
|
812
810
|
*/
|
813
811
|
optionalAll<Value>(token: Token<Value>): NonNullable<Value>[];
|
812
|
+
/**
|
813
|
+
* Runs a function inside the injection context of this injector.
|
814
|
+
*
|
815
|
+
* Note that injection functions (`inject`, `injectAll`, `optional`, `optionalAll`)
|
816
|
+
* are only usable synchronously: they cannot be called from asynchronous callbacks
|
817
|
+
* or after any `await` points.
|
818
|
+
*
|
819
|
+
* @param fn The function to be run in the context of this injector.
|
820
|
+
* @returns The return value of the function, if any.
|
821
|
+
*/
|
822
|
+
runInContext<ReturnType>(fn: () => ReturnType): ReturnType;
|
814
823
|
}
|
815
824
|
/**
|
816
825
|
* Injector token for dynamic injections.
|
package/dist/cjs/index.js
CHANGED
@@ -1,5 +1,32 @@
|
|
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
|
+
|
3
30
|
// @internal
|
4
31
|
function assert(condition, message) {
|
5
32
|
if (!condition) {
|
@@ -12,7 +39,8 @@ function expectNever(value) {
|
|
12
39
|
}
|
13
40
|
// @internal
|
14
41
|
function throwUnregisteredError(token) {
|
15
|
-
|
42
|
+
const type = isConstructor(token) ? "class" : "token";
|
43
|
+
throw new Error(tag(`unregistered ${type} ${token.name}`));
|
16
44
|
}
|
17
45
|
// @internal
|
18
46
|
function throwExistingUnregisteredError(sourceToken, targetTokenOrError) {
|
@@ -31,23 +59,6 @@ function untag(message) {
|
|
31
59
|
return message.startsWith("[di-wise-neo]") ? message.substring(13).trimStart() : message;
|
32
60
|
}
|
33
61
|
|
34
|
-
// @internal
|
35
|
-
function createInjectionContext() {
|
36
|
-
let current = null;
|
37
|
-
function provide(next) {
|
38
|
-
const prev = current;
|
39
|
-
current = next;
|
40
|
-
return ()=>current = prev;
|
41
|
-
}
|
42
|
-
function use() {
|
43
|
-
return current;
|
44
|
-
}
|
45
|
-
return [
|
46
|
-
provide,
|
47
|
-
use
|
48
|
-
];
|
49
|
-
}
|
50
|
-
|
51
62
|
// @internal
|
52
63
|
function invariant(condition) {
|
53
64
|
if (!condition) {
|
@@ -117,18 +128,33 @@ function createResolution() {
|
|
117
128
|
// @internal
|
118
129
|
const [provideInjectionContext, useInjectionContext] = createInjectionContext();
|
119
130
|
// @internal
|
120
|
-
function ensureInjectionContext(
|
131
|
+
function ensureInjectionContext(name) {
|
121
132
|
const context = useInjectionContext();
|
122
|
-
assert(context, `${
|
133
|
+
assert(context, `${name} can only be invoked within an injection context`);
|
123
134
|
return context;
|
124
135
|
}
|
136
|
+
function createInjectionContext() {
|
137
|
+
let current = null;
|
138
|
+
function provide(next) {
|
139
|
+
const prev = current;
|
140
|
+
current = next;
|
141
|
+
return ()=>current = prev;
|
142
|
+
}
|
143
|
+
function use() {
|
144
|
+
return current;
|
145
|
+
}
|
146
|
+
return [
|
147
|
+
provide,
|
148
|
+
use
|
149
|
+
];
|
150
|
+
}
|
125
151
|
|
126
152
|
function inject(token, name) {
|
127
|
-
const context = ensureInjectionContext(inject);
|
153
|
+
const context = ensureInjectionContext("inject()");
|
128
154
|
return context.container.resolve(token, name);
|
129
155
|
}
|
130
156
|
function injectBy(thisArg, token, name) {
|
131
|
-
const context = ensureInjectionContext(injectBy);
|
157
|
+
const context = ensureInjectionContext("injectBy()");
|
132
158
|
const resolution = context.resolution;
|
133
159
|
const currentFrame = resolution.stack.peek();
|
134
160
|
if (!currentFrame) {
|
@@ -146,7 +172,7 @@ function injectBy(thisArg, token, name) {
|
|
146
172
|
}
|
147
173
|
|
148
174
|
function injectAll(token) {
|
149
|
-
const context = ensureInjectionContext(injectAll);
|
175
|
+
const context = ensureInjectionContext("injectAll()");
|
150
176
|
return context.container.resolveAll(token);
|
151
177
|
}
|
152
178
|
|
@@ -242,11 +268,11 @@ const classIdentityMap = new WeakMap();
|
|
242
268
|
const metadataMap = new WeakMap();
|
243
269
|
|
244
270
|
function optional(token, name) {
|
245
|
-
const context = ensureInjectionContext(optional);
|
271
|
+
const context = ensureInjectionContext("optional()");
|
246
272
|
return context.container.resolve(token, true, name);
|
247
273
|
}
|
248
274
|
function optionalBy(thisArg, token, name) {
|
249
|
-
const context = ensureInjectionContext(optionalBy);
|
275
|
+
const context = ensureInjectionContext("optionalBy()");
|
250
276
|
const resolution = context.resolution;
|
251
277
|
const currentFrame = resolution.stack.peek();
|
252
278
|
if (!currentFrame) {
|
@@ -264,7 +290,7 @@ function optionalBy(thisArg, token, name) {
|
|
264
290
|
}
|
265
291
|
|
266
292
|
function optionalAll(token) {
|
267
|
-
const context = ensureInjectionContext(optionalAll);
|
293
|
+
const context = ensureInjectionContext("optionalAll()");
|
268
294
|
return context.container.resolveAll(token, true);
|
269
295
|
}
|
270
296
|
|
@@ -292,33 +318,6 @@ const Scope = {
|
|
292
318
|
Container: "Container"
|
293
319
|
};
|
294
320
|
|
295
|
-
/**
|
296
|
-
* Type API.
|
297
|
-
*/ /**
|
298
|
-
* Creates a type token.
|
299
|
-
*
|
300
|
-
* @example
|
301
|
-
* ```ts
|
302
|
-
* const ISpell = createType<Spell>("Spell");
|
303
|
-
* ```
|
304
|
-
*
|
305
|
-
* @__NO_SIDE_EFFECTS__
|
306
|
-
*/ function createType(typeName) {
|
307
|
-
const type = {
|
308
|
-
name: `Type<${typeName}>`,
|
309
|
-
inter: createType,
|
310
|
-
union: createType,
|
311
|
-
toString () {
|
312
|
-
return type.name;
|
313
|
-
}
|
314
|
-
};
|
315
|
-
return type;
|
316
|
-
}
|
317
|
-
// @internal
|
318
|
-
function isConstructor(token) {
|
319
|
-
return typeof token === "function";
|
320
|
-
}
|
321
|
-
|
322
321
|
// @internal
|
323
322
|
function getTypeName(value) {
|
324
323
|
switch(typeof value){
|
@@ -430,26 +429,9 @@ class TokenRegistry {
|
|
430
429
|
function isBuilder(provider) {
|
431
430
|
return builders.has(provider);
|
432
431
|
}
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
* @example
|
437
|
-
* ```ts
|
438
|
-
* class Wizard {
|
439
|
-
* wand = inject(
|
440
|
-
* build(() => {
|
441
|
-
* const wand = inject(Wand);
|
442
|
-
* wand.owner = this;
|
443
|
-
* // ...
|
444
|
-
* return wand;
|
445
|
-
* }),
|
446
|
-
* );
|
447
|
-
* }
|
448
|
-
* ```
|
449
|
-
*
|
450
|
-
* @__NO_SIDE_EFFECTS__
|
451
|
-
*/ function build(factory) {
|
452
|
-
const token = createType(`Build<${getTypeName(factory)}>`);
|
432
|
+
// @__NO_SIDE_EFFECTS__
|
433
|
+
function build(factory, name) {
|
434
|
+
const token = createType(name ?? `Build<${getTypeName(factory)}>`);
|
453
435
|
const provider = {
|
454
436
|
useFactory: factory
|
455
437
|
};
|
@@ -640,7 +622,7 @@ function isDisposable(value) {
|
|
640
622
|
if (isConstructor(token)) {
|
641
623
|
return this.instantiateClass(token, localOptional);
|
642
624
|
}
|
643
|
-
return
|
625
|
+
return localOptional ? undefined : throwUnregisteredError(token);
|
644
626
|
}
|
645
627
|
resolveAll(token, optional) {
|
646
628
|
this.checkDisposed();
|
@@ -1007,10 +989,22 @@ function updateParameterMetadata(decorator, target, propertyKey, parameterIndex,
|
|
1007
989
|
updateFn(dependency);
|
1008
990
|
}
|
1009
991
|
}
|
992
|
+
// Checks that a constructor or method parameter has only one injection decorator.
|
993
|
+
// For example, if both `@Inject` and `@Optional` are used, it becomes difficult to
|
994
|
+
// understand which one "wins", unless the user is aware of the decorator evaluation order.
|
995
|
+
//
|
996
|
+
// @internal
|
997
|
+
function checkSingleDecorator(dependency, target, propertyKey, parameterIndex) {
|
998
|
+
assert(!dependency.appliedBy, ()=>{
|
999
|
+
const where = propertyKey === undefined ? `${target.name} constructor` : `${target.constructor.name}.${String(propertyKey)}`;
|
1000
|
+
return `${where} parameter ${parameterIndex} declares multiple injection decorators, but only one is allowed`;
|
1001
|
+
});
|
1002
|
+
}
|
1010
1003
|
|
1011
1004
|
function Inject(token) {
|
1012
1005
|
return function(target, propertyKey, parameterIndex) {
|
1013
1006
|
updateParameterMetadata("Inject", target, propertyKey, parameterIndex, (dependency)=>{
|
1007
|
+
checkSingleDecorator(dependency, target, propertyKey, parameterIndex);
|
1014
1008
|
dependency.appliedBy = "Inject";
|
1015
1009
|
dependency.tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
1016
1010
|
});
|
@@ -1040,6 +1034,7 @@ function Inject(token) {
|
|
1040
1034
|
function InjectAll(token) {
|
1041
1035
|
return function(target, propertyKey, parameterIndex) {
|
1042
1036
|
updateParameterMetadata("InjectAll", target, propertyKey, parameterIndex, (dependency)=>{
|
1037
|
+
checkSingleDecorator(dependency, target, propertyKey, parameterIndex);
|
1043
1038
|
dependency.appliedBy = "InjectAll";
|
1044
1039
|
dependency.tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
1045
1040
|
});
|
@@ -1087,6 +1082,7 @@ function InjectAll(token) {
|
|
1087
1082
|
function Optional(token) {
|
1088
1083
|
return function(target, propertyKey, parameterIndex) {
|
1089
1084
|
updateParameterMetadata("Optional", target, propertyKey, parameterIndex, (dependency)=>{
|
1085
|
+
checkSingleDecorator(dependency, target, propertyKey, parameterIndex);
|
1090
1086
|
dependency.appliedBy = "Optional";
|
1091
1087
|
dependency.tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
1092
1088
|
});
|
@@ -1096,6 +1092,7 @@ function Optional(token) {
|
|
1096
1092
|
function OptionalAll(token) {
|
1097
1093
|
return function(target, propertyKey, parameterIndex) {
|
1098
1094
|
updateParameterMetadata("OptionalAll", target, propertyKey, parameterIndex, (dependency)=>{
|
1095
|
+
checkSingleDecorator(dependency, target, propertyKey, parameterIndex);
|
1099
1096
|
dependency.appliedBy = "OptionalAll";
|
1100
1097
|
dependency.tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
1101
1098
|
});
|
@@ -1156,12 +1153,12 @@ function OptionalAll(token) {
|
|
1156
1153
|
* const wizard = container.resolve(Wizard);
|
1157
1154
|
* wizard.getWand(); // => Wand
|
1158
1155
|
* ```
|
1159
|
-
*/ const Injector = /*@__PURE__*/ build(
|
1160
|
-
const context = ensureInjectionContext(Injector);
|
1156
|
+
*/ const Injector = /*@__PURE__*/ build(()=>{
|
1157
|
+
const context = ensureInjectionContext("Injector factory");
|
1161
1158
|
const resolution = context.resolution;
|
1162
1159
|
const dependentFrame = resolution.stack.peek();
|
1163
1160
|
const dependentRef = dependentFrame && resolution.dependents.get(dependentFrame.provider);
|
1164
|
-
|
1161
|
+
const runInContext = (fn)=>{
|
1165
1162
|
if (useInjectionContext()) {
|
1166
1163
|
return fn();
|
1167
1164
|
}
|
@@ -1173,18 +1170,17 @@ function OptionalAll(token) {
|
|
1173
1170
|
try {
|
1174
1171
|
return fn();
|
1175
1172
|
} finally{
|
1176
|
-
|
1177
|
-
cleanup?.();
|
1178
|
-
}
|
1173
|
+
cleanups.forEach((cleanup)=>cleanup?.());
|
1179
1174
|
}
|
1180
|
-
}
|
1175
|
+
};
|
1181
1176
|
return {
|
1182
|
-
inject: (token, name)=>
|
1183
|
-
injectAll: (token)=>
|
1184
|
-
optional: (token, name)=>
|
1185
|
-
optionalAll: (token)=>
|
1177
|
+
inject: (token, name)=>runInContext(()=>inject(token, name)),
|
1178
|
+
injectAll: (token)=>runInContext(()=>injectAll(token)),
|
1179
|
+
optional: (token, name)=>runInContext(()=>optional(token, name)),
|
1180
|
+
optionalAll: (token)=>runInContext(()=>optionalAll(token)),
|
1181
|
+
runInContext
|
1186
1182
|
};
|
1187
|
-
});
|
1183
|
+
}, "Injector");
|
1188
1184
|
|
1189
1185
|
/**
|
1190
1186
|
* Applies middleware functions to a container.
|