@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/es/index.d.mts
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/es/index.mjs
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
/**
|
2
|
+
* Type API.
|
3
|
+
*/ /**
|
4
|
+
* Creates a type token.
|
5
|
+
*
|
6
|
+
* @example
|
7
|
+
* ```ts
|
8
|
+
* const ISpell = createType<Spell>("Spell");
|
9
|
+
* ```
|
10
|
+
*
|
11
|
+
* @__NO_SIDE_EFFECTS__
|
12
|
+
*/ function createType(typeName) {
|
13
|
+
const type = {
|
14
|
+
name: `Type<${typeName}>`,
|
15
|
+
inter: createType,
|
16
|
+
union: createType,
|
17
|
+
toString () {
|
18
|
+
return type.name;
|
19
|
+
}
|
20
|
+
};
|
21
|
+
return type;
|
22
|
+
}
|
23
|
+
// @internal
|
24
|
+
function isConstructor(token) {
|
25
|
+
return typeof token === "function";
|
26
|
+
}
|
27
|
+
|
1
28
|
// @internal
|
2
29
|
function assert(condition, message) {
|
3
30
|
if (!condition) {
|
@@ -10,7 +37,8 @@ function expectNever(value) {
|
|
10
37
|
}
|
11
38
|
// @internal
|
12
39
|
function throwUnregisteredError(token) {
|
13
|
-
|
40
|
+
const type = isConstructor(token) ? "class" : "token";
|
41
|
+
throw new Error(tag(`unregistered ${type} ${token.name}`));
|
14
42
|
}
|
15
43
|
// @internal
|
16
44
|
function throwExistingUnregisteredError(sourceToken, targetTokenOrError) {
|
@@ -29,23 +57,6 @@ function untag(message) {
|
|
29
57
|
return message.startsWith("[di-wise-neo]") ? message.substring(13).trimStart() : message;
|
30
58
|
}
|
31
59
|
|
32
|
-
// @internal
|
33
|
-
function createInjectionContext() {
|
34
|
-
let current = null;
|
35
|
-
function provide(next) {
|
36
|
-
const prev = current;
|
37
|
-
current = next;
|
38
|
-
return ()=>current = prev;
|
39
|
-
}
|
40
|
-
function use() {
|
41
|
-
return current;
|
42
|
-
}
|
43
|
-
return [
|
44
|
-
provide,
|
45
|
-
use
|
46
|
-
];
|
47
|
-
}
|
48
|
-
|
49
60
|
// @internal
|
50
61
|
function invariant(condition) {
|
51
62
|
if (!condition) {
|
@@ -115,18 +126,33 @@ function createResolution() {
|
|
115
126
|
// @internal
|
116
127
|
const [provideInjectionContext, useInjectionContext] = createInjectionContext();
|
117
128
|
// @internal
|
118
|
-
function ensureInjectionContext(
|
129
|
+
function ensureInjectionContext(name) {
|
119
130
|
const context = useInjectionContext();
|
120
|
-
assert(context, `${
|
131
|
+
assert(context, `${name} can only be invoked within an injection context`);
|
121
132
|
return context;
|
122
133
|
}
|
134
|
+
function createInjectionContext() {
|
135
|
+
let current = null;
|
136
|
+
function provide(next) {
|
137
|
+
const prev = current;
|
138
|
+
current = next;
|
139
|
+
return ()=>current = prev;
|
140
|
+
}
|
141
|
+
function use() {
|
142
|
+
return current;
|
143
|
+
}
|
144
|
+
return [
|
145
|
+
provide,
|
146
|
+
use
|
147
|
+
];
|
148
|
+
}
|
123
149
|
|
124
150
|
function inject(token, name) {
|
125
|
-
const context = ensureInjectionContext(inject);
|
151
|
+
const context = ensureInjectionContext("inject()");
|
126
152
|
return context.container.resolve(token, name);
|
127
153
|
}
|
128
154
|
function injectBy(thisArg, token, name) {
|
129
|
-
const context = ensureInjectionContext(injectBy);
|
155
|
+
const context = ensureInjectionContext("injectBy()");
|
130
156
|
const resolution = context.resolution;
|
131
157
|
const currentFrame = resolution.stack.peek();
|
132
158
|
if (!currentFrame) {
|
@@ -144,7 +170,7 @@ function injectBy(thisArg, token, name) {
|
|
144
170
|
}
|
145
171
|
|
146
172
|
function injectAll(token) {
|
147
|
-
const context = ensureInjectionContext(injectAll);
|
173
|
+
const context = ensureInjectionContext("injectAll()");
|
148
174
|
return context.container.resolveAll(token);
|
149
175
|
}
|
150
176
|
|
@@ -240,11 +266,11 @@ const classIdentityMap = new WeakMap();
|
|
240
266
|
const metadataMap = new WeakMap();
|
241
267
|
|
242
268
|
function optional(token, name) {
|
243
|
-
const context = ensureInjectionContext(optional);
|
269
|
+
const context = ensureInjectionContext("optional()");
|
244
270
|
return context.container.resolve(token, true, name);
|
245
271
|
}
|
246
272
|
function optionalBy(thisArg, token, name) {
|
247
|
-
const context = ensureInjectionContext(optionalBy);
|
273
|
+
const context = ensureInjectionContext("optionalBy()");
|
248
274
|
const resolution = context.resolution;
|
249
275
|
const currentFrame = resolution.stack.peek();
|
250
276
|
if (!currentFrame) {
|
@@ -262,7 +288,7 @@ function optionalBy(thisArg, token, name) {
|
|
262
288
|
}
|
263
289
|
|
264
290
|
function optionalAll(token) {
|
265
|
-
const context = ensureInjectionContext(optionalAll);
|
291
|
+
const context = ensureInjectionContext("optionalAll()");
|
266
292
|
return context.container.resolveAll(token, true);
|
267
293
|
}
|
268
294
|
|
@@ -290,33 +316,6 @@ const Scope = {
|
|
290
316
|
Container: "Container"
|
291
317
|
};
|
292
318
|
|
293
|
-
/**
|
294
|
-
* Type API.
|
295
|
-
*/ /**
|
296
|
-
* Creates a type token.
|
297
|
-
*
|
298
|
-
* @example
|
299
|
-
* ```ts
|
300
|
-
* const ISpell = createType<Spell>("Spell");
|
301
|
-
* ```
|
302
|
-
*
|
303
|
-
* @__NO_SIDE_EFFECTS__
|
304
|
-
*/ function createType(typeName) {
|
305
|
-
const type = {
|
306
|
-
name: `Type<${typeName}>`,
|
307
|
-
inter: createType,
|
308
|
-
union: createType,
|
309
|
-
toString () {
|
310
|
-
return type.name;
|
311
|
-
}
|
312
|
-
};
|
313
|
-
return type;
|
314
|
-
}
|
315
|
-
// @internal
|
316
|
-
function isConstructor(token) {
|
317
|
-
return typeof token === "function";
|
318
|
-
}
|
319
|
-
|
320
319
|
// @internal
|
321
320
|
function getTypeName(value) {
|
322
321
|
switch(typeof value){
|
@@ -428,26 +427,9 @@ class TokenRegistry {
|
|
428
427
|
function isBuilder(provider) {
|
429
428
|
return builders.has(provider);
|
430
429
|
}
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
* @example
|
435
|
-
* ```ts
|
436
|
-
* class Wizard {
|
437
|
-
* wand = inject(
|
438
|
-
* build(() => {
|
439
|
-
* const wand = inject(Wand);
|
440
|
-
* wand.owner = this;
|
441
|
-
* // ...
|
442
|
-
* return wand;
|
443
|
-
* }),
|
444
|
-
* );
|
445
|
-
* }
|
446
|
-
* ```
|
447
|
-
*
|
448
|
-
* @__NO_SIDE_EFFECTS__
|
449
|
-
*/ function build(factory) {
|
450
|
-
const token = createType(`Build<${getTypeName(factory)}>`);
|
430
|
+
// @__NO_SIDE_EFFECTS__
|
431
|
+
function build(factory, name) {
|
432
|
+
const token = createType(name ?? `Build<${getTypeName(factory)}>`);
|
451
433
|
const provider = {
|
452
434
|
useFactory: factory
|
453
435
|
};
|
@@ -638,7 +620,7 @@ function isDisposable(value) {
|
|
638
620
|
if (isConstructor(token)) {
|
639
621
|
return this.instantiateClass(token, localOptional);
|
640
622
|
}
|
641
|
-
return
|
623
|
+
return localOptional ? undefined : throwUnregisteredError(token);
|
642
624
|
}
|
643
625
|
resolveAll(token, optional) {
|
644
626
|
this.checkDisposed();
|
@@ -1005,10 +987,22 @@ function updateParameterMetadata(decorator, target, propertyKey, parameterIndex,
|
|
1005
987
|
updateFn(dependency);
|
1006
988
|
}
|
1007
989
|
}
|
990
|
+
// Checks that a constructor or method parameter has only one injection decorator.
|
991
|
+
// For example, if both `@Inject` and `@Optional` are used, it becomes difficult to
|
992
|
+
// understand which one "wins", unless the user is aware of the decorator evaluation order.
|
993
|
+
//
|
994
|
+
// @internal
|
995
|
+
function checkSingleDecorator(dependency, target, propertyKey, parameterIndex) {
|
996
|
+
assert(!dependency.appliedBy, ()=>{
|
997
|
+
const where = propertyKey === undefined ? `${target.name} constructor` : `${target.constructor.name}.${String(propertyKey)}`;
|
998
|
+
return `${where} parameter ${parameterIndex} declares multiple injection decorators, but only one is allowed`;
|
999
|
+
});
|
1000
|
+
}
|
1008
1001
|
|
1009
1002
|
function Inject(token) {
|
1010
1003
|
return function(target, propertyKey, parameterIndex) {
|
1011
1004
|
updateParameterMetadata("Inject", target, propertyKey, parameterIndex, (dependency)=>{
|
1005
|
+
checkSingleDecorator(dependency, target, propertyKey, parameterIndex);
|
1012
1006
|
dependency.appliedBy = "Inject";
|
1013
1007
|
dependency.tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
1014
1008
|
});
|
@@ -1038,6 +1032,7 @@ function Inject(token) {
|
|
1038
1032
|
function InjectAll(token) {
|
1039
1033
|
return function(target, propertyKey, parameterIndex) {
|
1040
1034
|
updateParameterMetadata("InjectAll", target, propertyKey, parameterIndex, (dependency)=>{
|
1035
|
+
checkSingleDecorator(dependency, target, propertyKey, parameterIndex);
|
1041
1036
|
dependency.appliedBy = "InjectAll";
|
1042
1037
|
dependency.tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
1043
1038
|
});
|
@@ -1085,6 +1080,7 @@ function InjectAll(token) {
|
|
1085
1080
|
function Optional(token) {
|
1086
1081
|
return function(target, propertyKey, parameterIndex) {
|
1087
1082
|
updateParameterMetadata("Optional", target, propertyKey, parameterIndex, (dependency)=>{
|
1083
|
+
checkSingleDecorator(dependency, target, propertyKey, parameterIndex);
|
1088
1084
|
dependency.appliedBy = "Optional";
|
1089
1085
|
dependency.tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
1090
1086
|
});
|
@@ -1094,6 +1090,7 @@ function Optional(token) {
|
|
1094
1090
|
function OptionalAll(token) {
|
1095
1091
|
return function(target, propertyKey, parameterIndex) {
|
1096
1092
|
updateParameterMetadata("OptionalAll", target, propertyKey, parameterIndex, (dependency)=>{
|
1093
|
+
checkSingleDecorator(dependency, target, propertyKey, parameterIndex);
|
1097
1094
|
dependency.appliedBy = "OptionalAll";
|
1098
1095
|
dependency.tokenRef = isTokenRef(token) ? token : forwardRef(()=>token);
|
1099
1096
|
});
|
@@ -1154,12 +1151,12 @@ function OptionalAll(token) {
|
|
1154
1151
|
* const wizard = container.resolve(Wizard);
|
1155
1152
|
* wizard.getWand(); // => Wand
|
1156
1153
|
* ```
|
1157
|
-
*/ const Injector = /*@__PURE__*/ build(
|
1158
|
-
const context = ensureInjectionContext(Injector);
|
1154
|
+
*/ const Injector = /*@__PURE__*/ build(()=>{
|
1155
|
+
const context = ensureInjectionContext("Injector factory");
|
1159
1156
|
const resolution = context.resolution;
|
1160
1157
|
const dependentFrame = resolution.stack.peek();
|
1161
1158
|
const dependentRef = dependentFrame && resolution.dependents.get(dependentFrame.provider);
|
1162
|
-
|
1159
|
+
const runInContext = (fn)=>{
|
1163
1160
|
if (useInjectionContext()) {
|
1164
1161
|
return fn();
|
1165
1162
|
}
|
@@ -1171,18 +1168,17 @@ function OptionalAll(token) {
|
|
1171
1168
|
try {
|
1172
1169
|
return fn();
|
1173
1170
|
} finally{
|
1174
|
-
|
1175
|
-
cleanup?.();
|
1176
|
-
}
|
1171
|
+
cleanups.forEach((cleanup)=>cleanup?.());
|
1177
1172
|
}
|
1178
|
-
}
|
1173
|
+
};
|
1179
1174
|
return {
|
1180
|
-
inject: (token, name)=>
|
1181
|
-
injectAll: (token)=>
|
1182
|
-
optional: (token, name)=>
|
1183
|
-
optionalAll: (token)=>
|
1175
|
+
inject: (token, name)=>runInContext(()=>inject(token, name)),
|
1176
|
+
injectAll: (token)=>runInContext(()=>injectAll(token)),
|
1177
|
+
optional: (token, name)=>runInContext(()=>optional(token, name)),
|
1178
|
+
optionalAll: (token)=>runInContext(()=>optionalAll(token)),
|
1179
|
+
runInContext
|
1184
1180
|
};
|
1185
|
-
});
|
1181
|
+
}, "Injector");
|
1186
1182
|
|
1187
1183
|
/**
|
1188
1184
|
* Applies middleware functions to a container.
|