@codefast/di 0.3.14-canary.1 → 0.3.14
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/CHANGELOG.md +58 -0
- package/README.md +42 -26
- package/dist/binding-scope.d.mts +11 -0
- package/dist/binding-scope.mjs +19 -0
- package/dist/binding-select.d.mts +8 -26
- package/dist/binding-select.mjs +56 -49
- package/dist/binding.d.mts +107 -335
- package/dist/binding.mjs +19 -332
- package/dist/constraints.d.mts +11 -29
- package/dist/constraints.mjs +32 -36
- package/dist/constructor-type.d.mts +17 -0
- package/dist/constructor-type.mjs +1 -0
- package/dist/container.d.mts +43 -122
- package/dist/container.mjs +667 -482
- package/dist/decorators/inject.d.mts +19 -50
- package/dist/decorators/inject.mjs +131 -93
- package/dist/decorators/injectable.d.mts +16 -37
- package/dist/decorators/injectable.mjs +47 -66
- package/dist/decorators/lifecycle-decorators.d.mts +2 -22
- package/dist/decorators/lifecycle-decorators.mjs +81 -37
- package/dist/dependency-graph.d.mts +24 -54
- package/dist/dependency-graph.mjs +51 -153
- package/dist/environment.d.mts +38 -12
- package/dist/environment.mjs +82 -16
- package/dist/errors.d.mts +70 -189
- package/dist/errors.mjs +92 -219
- package/dist/graph-adapters/cytoscape.d.mts +21 -7
- package/dist/graph-adapters/cytoscape.mjs +18 -35
- package/dist/graph-adapters/dot.d.mts +1 -4
- package/dist/graph-adapters/dot.mjs +6 -86
- package/dist/graph-adapters/reactflow.d.mts +26 -7
- package/dist/graph-adapters/reactflow.mjs +21 -72
- package/dist/graph-adapters/types.d.mts +2 -91
- package/dist/index.d.mts +16 -8
- package/dist/index.mjs +8 -5
- package/dist/inspector.d.mts +35 -74
- package/dist/inspector.mjs +61 -88
- package/dist/lifecycle.d.mts +20 -53
- package/dist/lifecycle.mjs +129 -99
- package/dist/metadata/metadata-keys.d.mts +9 -26
- package/dist/metadata/metadata-keys.mjs +7 -28
- package/dist/metadata/metadata-reader-token.d.mts +7 -0
- package/dist/metadata/metadata-reader-token.mjs +5 -0
- package/dist/metadata/metadata-types.d.mts +26 -75
- package/dist/metadata/symbol-metadata-reader.d.mts +10 -26
- package/dist/metadata/symbol-metadata-reader.mjs +32 -45
- package/dist/module.d.mts +30 -96
- package/dist/module.mjs +26 -72
- package/dist/registry.d.mts +32 -63
- package/dist/registry.mjs +131 -82
- package/dist/resolve-options.d.mts +18 -0
- package/dist/resolve-options.mjs +22 -0
- package/dist/resolver.d.mts +67 -190
- package/dist/resolver.mjs +715 -424
- package/dist/scope.d.mts +19 -106
- package/dist/scope.mjs +37 -196
- package/dist/token.d.mts +8 -22
- package/dist/token.mjs +9 -11
- package/dist/types.d.mts +48 -0
- package/dist/types.mjs +1 -0
- package/package.json +36 -14
- package/dist/metadata/param-registry.d.mts +0 -16
- package/dist/metadata/param-registry.mjs +0 -31
- package/dist/scope-validation.d.mts +0 -21
- package/dist/scope-validation.mjs +0 -35
package/dist/binding.mjs
CHANGED
|
@@ -1,337 +1,24 @@
|
|
|
1
|
-
import { InternalError } from "./errors.mjs";
|
|
2
1
|
//#region src/binding.ts
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return
|
|
2
|
+
function slotKeyEquals(a, b) {
|
|
3
|
+
if (a.name !== b.name) return false;
|
|
4
|
+
if (a.tags.length !== b.tags.length) return false;
|
|
5
|
+
for (const [tagKey, tagValue] of a.tags) if (!b.tags.some(([k, v]) => k === tagKey && Object.is(v, tagValue))) return false;
|
|
6
|
+
return true;
|
|
8
7
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* A builder has two phases:
|
|
13
|
-
* 1. **Strategy selection** — exactly one `to*()` call (`to`, `toSelf`, `toConstantValue`,
|
|
14
|
-
* `toDynamic`, `toDynamicAsync`, `toResolved`, `toAlias`) that determines how the value is produced.
|
|
15
|
-
* 2. **Refinement chain** — optional calls to `singleton()`, `transient()`, `scoped()`,
|
|
16
|
-
* `onActivation()`, `onDeactivation()`, `whenNamed()`, `whenTagged()`, `when()`, and `id()`.
|
|
17
|
-
*
|
|
18
|
-
* Calling a second `to*()` method throws {@link InternalError}.
|
|
19
|
-
*
|
|
20
|
-
* The builder is created by {@link Container.bind} or by `bind` on {@link ModuleBuilder}.
|
|
21
|
-
* The container injects {@link RegistryCallbacks} so that every strategy selection and
|
|
22
|
-
* refinement is immediately reflected in the live registry.
|
|
23
|
-
*/
|
|
24
|
-
var BindingBuilder = class {
|
|
25
|
-
/**
|
|
26
|
-
* Current resolution strategy; starts as `"unset"` until a `to*()` method is called.
|
|
27
|
-
*/
|
|
28
|
-
strategy = { type: "unset" };
|
|
29
|
-
/**
|
|
30
|
-
* Lifetime scope applied to the next binding snapshot; defaults to `"transient"`.
|
|
31
|
-
*/
|
|
32
|
-
scope = "transient";
|
|
33
|
-
/**
|
|
34
|
-
* True after an explicit `.singleton()` / `.transient()` / `.scoped()` call (prevents constant scope change).
|
|
35
|
-
*/
|
|
36
|
-
isScopeExplicit = false;
|
|
37
|
-
/**
|
|
38
|
-
* Pre-allocated binding ID set via `id(identifier)` before the first `to*()` call.
|
|
39
|
-
*/
|
|
40
|
-
explicitId;
|
|
41
|
-
/**
|
|
42
|
-
* Resolve-hint name filter set by `.whenNamed()`.
|
|
43
|
-
*/
|
|
44
|
-
bindingName;
|
|
45
|
-
/**
|
|
46
|
-
* Tag filters accumulated by successive `.whenTagged()` calls.
|
|
47
|
-
*/
|
|
48
|
-
tags = /* @__PURE__ */ new Map();
|
|
49
|
-
/**
|
|
50
|
-
* Custom constraint predicates accumulated by `.when()`; all must pass for this binding to be selected.
|
|
51
|
-
*/
|
|
52
|
-
constraintPredicates = [];
|
|
53
|
-
/**
|
|
54
|
-
* Latest `onActivation` hook provided by `.onActivation(...)`.
|
|
55
|
-
* Applied to emitted binding snapshots until replaced.
|
|
56
|
-
*/
|
|
57
|
-
onActivationHandler;
|
|
58
|
-
/**
|
|
59
|
-
* Latest `onDeactivation` hook provided by `.onDeactivation(...)`.
|
|
60
|
-
* Emitted only on builder variants that expose deactivation support.
|
|
61
|
-
*/
|
|
62
|
-
onDeactivationHandler;
|
|
63
|
-
/**
|
|
64
|
-
* Set when this binding was created inside a {@link Module} / {@link AsyncModule} setup callback.
|
|
65
|
-
*/
|
|
66
|
-
moduleId;
|
|
67
|
-
/**
|
|
68
|
-
* The most recently emitted {@link Binding} snapshot; `undefined` before the first `to*()` call.
|
|
69
|
-
*/
|
|
70
|
-
currentBinding;
|
|
71
|
-
/**
|
|
72
|
-
* Container-injected hooks that sync builder mutations into the live registry.
|
|
73
|
-
*/
|
|
74
|
-
callbacks;
|
|
75
|
-
constructor(bindingKey, moduleId, callbacks) {
|
|
76
|
-
this.bindingKey = bindingKey;
|
|
77
|
-
this.moduleId = moduleId;
|
|
78
|
-
this.callbacks = callbacks ?? {};
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Binds the token to a concrete implementation class; the container constructs it on demand.
|
|
82
|
-
*/
|
|
83
|
-
to(implementationClass) {
|
|
84
|
-
this.registerWithStrategy({
|
|
85
|
-
type: "class",
|
|
86
|
-
implementationClass
|
|
87
|
-
});
|
|
88
|
-
return this;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Binds the class key to itself — only valid when the key is a constructor.
|
|
92
|
-
*/
|
|
93
|
-
toSelf() {
|
|
94
|
-
if (typeof this.bindingKey !== "function") throw new InternalError("toSelf() requires the binding key to be a constructor; use bind(SomeClass) or call to(Class) instead.");
|
|
95
|
-
this.registerWithStrategy({
|
|
96
|
-
type: "class",
|
|
97
|
-
implementationClass: this.bindingKey
|
|
98
|
-
});
|
|
99
|
-
return this;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Binds the token to a pre-existing value; always resolved as singleton, no construction.
|
|
103
|
-
*/
|
|
104
|
-
toConstantValue(value) {
|
|
105
|
-
this.scope = "singleton";
|
|
106
|
-
this.registerWithStrategy({
|
|
107
|
-
type: "constant",
|
|
108
|
-
value
|
|
109
|
-
});
|
|
110
|
-
return this;
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Binds to a synchronous factory; `ctx` provides nested resolution within the same path.
|
|
114
|
-
*/
|
|
115
|
-
toDynamic(factory) {
|
|
116
|
-
this.registerWithStrategy({
|
|
117
|
-
type: "dynamic",
|
|
118
|
-
factory
|
|
119
|
-
});
|
|
120
|
-
return this;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Binds to an async factory; must be resolved via `resolveAsync` / `resolveAllAsync`.
|
|
124
|
-
*/
|
|
125
|
-
toDynamicAsync(factory) {
|
|
126
|
-
this.registerWithStrategy({
|
|
127
|
-
type: "async-dynamic",
|
|
128
|
-
factory
|
|
129
|
-
});
|
|
130
|
-
return this;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Binds to a factory whose dependencies are declared explicitly in `deps` and pre-resolved by
|
|
134
|
-
* the container before the factory is called — no `ResolutionContext` needed inside the factory.
|
|
135
|
-
*/
|
|
136
|
-
toResolved(factory, deps) {
|
|
137
|
-
this.registerWithStrategy({
|
|
138
|
-
type: "resolved",
|
|
139
|
-
factory,
|
|
140
|
-
dependencyTokens: deps
|
|
141
|
-
});
|
|
142
|
-
return this;
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Redirects resolution to `targetToken`; the container resolves whatever is bound there.
|
|
146
|
-
*/
|
|
147
|
-
toAlias(targetToken) {
|
|
148
|
-
this.registerWithStrategy({
|
|
149
|
-
type: "alias",
|
|
150
|
-
targetToken
|
|
151
|
-
});
|
|
152
|
-
return this;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* One instance per container; supports `onDeactivation`.
|
|
156
|
-
*/
|
|
157
|
-
singleton() {
|
|
158
|
-
this.assertScopeMutable();
|
|
159
|
-
this.scope = "singleton";
|
|
160
|
-
this.isScopeExplicit = true;
|
|
161
|
-
this.refreshRegisteredBinding();
|
|
162
|
-
return this;
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* New instance on every resolution (default scope).
|
|
166
|
-
*/
|
|
167
|
-
transient() {
|
|
168
|
-
this.assertScopeMutable();
|
|
169
|
-
this.scope = "transient";
|
|
170
|
-
this.isScopeExplicit = true;
|
|
171
|
-
this.refreshRegisteredBinding();
|
|
172
|
-
return this;
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* One instance per child container scope.
|
|
176
|
-
*/
|
|
177
|
-
scoped() {
|
|
178
|
-
this.assertScopeMutable();
|
|
179
|
-
this.scope = "scoped";
|
|
180
|
-
this.isScopeExplicit = true;
|
|
181
|
-
this.refreshRegisteredBinding();
|
|
182
|
-
return this;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Called with the resolved instance after construction; the return value replaces the instance.
|
|
186
|
-
*/
|
|
187
|
-
onActivation(handler) {
|
|
188
|
-
this.onActivationHandler = handler;
|
|
189
|
-
this.refreshRegisteredBinding();
|
|
190
|
-
return this;
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* @internal Keep public for runtime correctness; hidden from transient/scoped builders via type aliases.
|
|
194
|
-
*/
|
|
195
|
-
onDeactivation(handler) {
|
|
196
|
-
this.onDeactivationHandler = handler;
|
|
197
|
-
this.refreshRegisteredBinding();
|
|
198
|
-
return this;
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* This binding only resolves when the caller passes `{ name }` as the resolve hint.
|
|
202
|
-
*/
|
|
203
|
-
whenNamed(name) {
|
|
204
|
-
this.bindingName = name;
|
|
205
|
-
this.refreshRegisteredBinding();
|
|
206
|
-
return this;
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* This binding only resolves when the caller passes `{ tag: [tag, tagValue] }` as the resolve hint.
|
|
210
|
-
*/
|
|
211
|
-
whenTagged(tag, tagValue) {
|
|
212
|
-
this.tags.set(tag, tagValue);
|
|
213
|
-
this.refreshRegisteredBinding();
|
|
214
|
-
return this;
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Adds a custom predicate; all predicates must pass for the binding to be selected.
|
|
218
|
-
*/
|
|
219
|
-
when(constraint) {
|
|
220
|
-
this.constraintPredicates.push(constraint);
|
|
221
|
-
this.refreshRegisteredBinding();
|
|
222
|
-
return this;
|
|
223
|
-
}
|
|
224
|
-
id(identifier) {
|
|
225
|
-
if (this.currentBinding !== void 0) {
|
|
226
|
-
if (identifier !== void 0 && identifier !== this.currentBinding.id) throw new InternalError("Cannot change binding identifier after registration.");
|
|
227
|
-
return this.currentBinding.id;
|
|
228
|
-
}
|
|
229
|
-
if (identifier !== void 0) {
|
|
230
|
-
this.explicitId = identifier;
|
|
231
|
-
return this.explicitId;
|
|
232
|
-
}
|
|
233
|
-
this.explicitId = this.explicitId ?? createBindingIdentifier();
|
|
234
|
-
return this.explicitId;
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Records the chosen strategy and emits the first {@link Binding} snapshot.
|
|
238
|
-
* Throws {@link InternalError} if a strategy was already selected (double `to*()` call).
|
|
239
|
-
*/
|
|
240
|
-
registerWithStrategy(next) {
|
|
241
|
-
if (this.strategy.type !== "unset") throw new InternalError("A binding strategy was already selected; only one to*(...) chain is allowed per builder.");
|
|
242
|
-
this.strategy = next;
|
|
243
|
-
const bindingId = this.id();
|
|
244
|
-
const binding = this.createBinding(bindingId, next);
|
|
245
|
-
this.currentBinding = binding;
|
|
246
|
-
this.callbacks.register?.(binding);
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* Re-creates the {@link Binding} snapshot from the current builder state and pushes
|
|
250
|
-
* the update to the registry. No-op if no strategy has been set yet.
|
|
251
|
-
*/
|
|
252
|
-
refreshRegisteredBinding() {
|
|
253
|
-
if (this.currentBinding === void 0 || this.strategy.type === "unset") return;
|
|
254
|
-
const next = this.createBinding(this.currentBinding.id, this.strategy);
|
|
255
|
-
this.currentBinding = next;
|
|
256
|
-
this.callbacks.update?.(next);
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Guards against calling `.singleton()` / `.transient()` / `.scoped()` on a constant binding,
|
|
260
|
-
* which is locked to `"singleton"` scope by invariant.
|
|
261
|
-
*/
|
|
262
|
-
assertScopeMutable() {
|
|
263
|
-
if (this.strategy.type === "constant") throw new InternalError("Constant bindings are always singleton and do not support scope changes.");
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Produces an immutable {@link Binding} snapshot from the current builder fields.
|
|
267
|
-
* Called by both {@link registerWithStrategy} and {@link refreshRegisteredBinding}.
|
|
268
|
-
*/
|
|
269
|
-
createBinding(id, strategy) {
|
|
270
|
-
const constraint = this.constraintPredicates.length === 0 ? void 0 : (ctx) => this.constraintPredicates.every((predicate) => predicate(ctx));
|
|
271
|
-
const lifecycle = {
|
|
272
|
-
bindingName: this.bindingName,
|
|
273
|
-
tags: new Map(this.tags),
|
|
274
|
-
onActivation: this.onActivationHandler,
|
|
275
|
-
onDeactivation: this.onDeactivationHandler,
|
|
276
|
-
constraint
|
|
277
|
-
};
|
|
278
|
-
const moduleFields = this.moduleId === void 0 ? {} : { moduleId: this.moduleId };
|
|
279
|
-
switch (strategy.type) {
|
|
280
|
-
case "constant": return {
|
|
281
|
-
...lifecycle,
|
|
282
|
-
...moduleFields,
|
|
283
|
-
id,
|
|
284
|
-
scope: "singleton",
|
|
285
|
-
kind: "constant",
|
|
286
|
-
value: strategy.value
|
|
287
|
-
};
|
|
288
|
-
case "class": return {
|
|
289
|
-
...lifecycle,
|
|
290
|
-
...moduleFields,
|
|
291
|
-
id,
|
|
292
|
-
scope: this.scope,
|
|
293
|
-
kind: "class",
|
|
294
|
-
implementationClass: strategy.implementationClass
|
|
295
|
-
};
|
|
296
|
-
case "dynamic": return {
|
|
297
|
-
...lifecycle,
|
|
298
|
-
...moduleFields,
|
|
299
|
-
id,
|
|
300
|
-
scope: this.scope,
|
|
301
|
-
kind: "dynamic",
|
|
302
|
-
factory: strategy.factory
|
|
303
|
-
};
|
|
304
|
-
case "async-dynamic": return {
|
|
305
|
-
...lifecycle,
|
|
306
|
-
...moduleFields,
|
|
307
|
-
id,
|
|
308
|
-
scope: this.scope,
|
|
309
|
-
kind: "async-dynamic",
|
|
310
|
-
factory: strategy.factory
|
|
311
|
-
};
|
|
312
|
-
case "resolved": return {
|
|
313
|
-
...lifecycle,
|
|
314
|
-
...moduleFields,
|
|
315
|
-
id,
|
|
316
|
-
scope: this.scope,
|
|
317
|
-
kind: "resolved",
|
|
318
|
-
dependencyTokens: strategy.dependencyTokens,
|
|
319
|
-
factory: strategy.factory
|
|
320
|
-
};
|
|
321
|
-
case "alias": return {
|
|
322
|
-
...lifecycle,
|
|
323
|
-
...moduleFields,
|
|
324
|
-
id,
|
|
325
|
-
scope: this.scope,
|
|
326
|
-
kind: "alias",
|
|
327
|
-
targetToken: strategy.targetToken
|
|
328
|
-
};
|
|
329
|
-
default: return strategy;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
8
|
+
const DEFAULT_SLOT = {
|
|
9
|
+
name: void 0,
|
|
10
|
+
tags: []
|
|
332
11
|
};
|
|
333
|
-
function
|
|
334
|
-
|
|
12
|
+
function slotKeyToString(slot) {
|
|
13
|
+
if (slot.name === void 0 && slot.tags.length === 0) return "default";
|
|
14
|
+
const parts = [];
|
|
15
|
+
if (slot.name !== void 0) parts.push(`name:${slot.name}`);
|
|
16
|
+
for (const [k, v] of slot.tags) parts.push(`tag:${k}=${String(v)}`);
|
|
17
|
+
return parts.join(",");
|
|
18
|
+
}
|
|
19
|
+
let _idCounter = 0;
|
|
20
|
+
function generateBindingId() {
|
|
21
|
+
return String(++_idCounter);
|
|
335
22
|
}
|
|
336
23
|
//#endregion
|
|
337
|
-
export {
|
|
24
|
+
export { DEFAULT_SLOT, generateBindingId, slotKeyEquals, slotKeyToString };
|
package/dist/constraints.d.mts
CHANGED
|
@@ -1,33 +1,15 @@
|
|
|
1
|
+
import { Constructor } from "./constructor-type.mjs";
|
|
1
2
|
import { Token } from "./token.mjs";
|
|
2
|
-
import { ConstraintContext
|
|
3
|
+
import { ConstraintContext } from "./types.mjs";
|
|
3
4
|
|
|
4
5
|
//#region src/constraints.d.ts
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
declare function
|
|
13
|
-
/**
|
|
14
|
-
* Constraint predicate factory: matches when *any* ancestor on the materialization stack
|
|
15
|
-
* (not just the immediate parent) was registered under `registryKey`.
|
|
16
|
-
* Pass the result to {@link BindingBuilder.when}.
|
|
17
|
-
*
|
|
18
|
-
* @param registryKey - Token or constructor to search for across the full construction chain.
|
|
19
|
-
* @returns A predicate compatible with {@link BindingBuilder.when}.
|
|
20
|
-
*/
|
|
21
|
-
declare function whenAnyAncestorIs(registryKey: Token<unknown> | Constructor<unknown>): (ctx: ConstraintContext) => boolean;
|
|
22
|
-
/**
|
|
23
|
-
* Constraint predicate factory: matches when the immediate parent binding carries a tag
|
|
24
|
-
* whose key is `tag` and whose value is reference-equal to `tagValue` (`Object.is`).
|
|
25
|
-
* Pass the result to {@link BindingBuilder.when}.
|
|
26
|
-
*
|
|
27
|
-
* @param tag - Tag key to check on the parent binding.
|
|
28
|
-
* @param tagValue - Expected value; compared via `Object.is`.
|
|
29
|
-
* @returns A predicate compatible with {@link BindingBuilder.when}.
|
|
30
|
-
*/
|
|
31
|
-
declare function whenTargetTagged(tag: string, tagValue: unknown): (ctx: ConstraintContext) => boolean;
|
|
6
|
+
declare function whenParentIs(t: Token<unknown> | Constructor): (ctx: ConstraintContext) => boolean;
|
|
7
|
+
declare function whenNoParentIs(t: Token<unknown> | Constructor): (ctx: ConstraintContext) => boolean;
|
|
8
|
+
declare function whenAnyAncestorIs(t: Token<unknown> | Constructor): (ctx: ConstraintContext) => boolean;
|
|
9
|
+
declare function whenNoAncestorIs(t: Token<unknown> | Constructor): (ctx: ConstraintContext) => boolean;
|
|
10
|
+
declare function whenParentNamed(name: string): (ctx: ConstraintContext) => boolean;
|
|
11
|
+
declare function whenAnyAncestorNamed(name: string): (ctx: ConstraintContext) => boolean;
|
|
12
|
+
declare function whenParentTagged(tag: string, value: unknown): (ctx: ConstraintContext) => boolean;
|
|
13
|
+
declare function whenAnyAncestorTagged(tag: string, value: unknown): (ctx: ConstraintContext) => boolean;
|
|
32
14
|
//#endregion
|
|
33
|
-
export { whenAnyAncestorIs, whenParentIs,
|
|
15
|
+
export { whenAnyAncestorIs, whenAnyAncestorNamed, whenAnyAncestorTagged, whenNoAncestorIs, whenNoParentIs, whenParentIs, whenParentNamed, whenParentTagged };
|
package/dist/constraints.mjs
CHANGED
|
@@ -1,39 +1,35 @@
|
|
|
1
|
+
import { tokenName } from "./token.mjs";
|
|
1
2
|
//#region src/constraints.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
function whenTargetTagged(tag, tagValue) {
|
|
33
|
-
return (ctx) => {
|
|
34
|
-
if (ctx.parent === void 0) return false;
|
|
35
|
-
return Object.is(ctx.parent.tags.get(tag), tagValue);
|
|
36
|
-
};
|
|
3
|
+
function tokenNameOf(t) {
|
|
4
|
+
return tokenName(t);
|
|
5
|
+
}
|
|
6
|
+
function whenParentIs(t) {
|
|
7
|
+
const name = tokenNameOf(t);
|
|
8
|
+
return (ctx) => ctx.parent !== void 0 && ctx.parent.tokenName === name;
|
|
9
|
+
}
|
|
10
|
+
function whenNoParentIs(t) {
|
|
11
|
+
const name = tokenNameOf(t);
|
|
12
|
+
return (ctx) => ctx.parent === void 0 || ctx.parent.tokenName !== name;
|
|
13
|
+
}
|
|
14
|
+
function whenAnyAncestorIs(t) {
|
|
15
|
+
const name = tokenNameOf(t);
|
|
16
|
+
return (ctx) => ctx.ancestors.some((f) => f.tokenName === name);
|
|
17
|
+
}
|
|
18
|
+
function whenNoAncestorIs(t) {
|
|
19
|
+
const name = tokenNameOf(t);
|
|
20
|
+
return (ctx) => ctx.ancestors.every((f) => f.tokenName !== name);
|
|
21
|
+
}
|
|
22
|
+
function whenParentNamed(name) {
|
|
23
|
+
return (ctx) => ctx.parent !== void 0 && ctx.parent.slot.name === name;
|
|
24
|
+
}
|
|
25
|
+
function whenAnyAncestorNamed(name) {
|
|
26
|
+
return (ctx) => ctx.ancestors.some((f) => f.slot.name === name);
|
|
27
|
+
}
|
|
28
|
+
function whenParentTagged(tag, value) {
|
|
29
|
+
return (ctx) => ctx.parent !== void 0 && ctx.parent.slot.tags.some(([t, v]) => t === tag && Object.is(v, value));
|
|
30
|
+
}
|
|
31
|
+
function whenAnyAncestorTagged(tag, value) {
|
|
32
|
+
return (ctx) => ctx.ancestors.some((f) => f.slot.tags.some(([t, v]) => t === tag && Object.is(v, value)));
|
|
37
33
|
}
|
|
38
34
|
//#endregion
|
|
39
|
-
export { whenAnyAncestorIs, whenParentIs,
|
|
35
|
+
export { whenAnyAncestorIs, whenAnyAncestorNamed, whenAnyAncestorTagged, whenNoAncestorIs, whenNoParentIs, whenParentIs, whenParentNamed, whenParentTagged };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/constructor-type.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* A class (newable) that produces `Value`. Rest parameters are `never[]` so
|
|
4
|
+
* real classes with typed constructors remain assignable under
|
|
5
|
+
* `strictFunctionTypes` (unlike `unknown[]`, which is not assignable from
|
|
6
|
+
* narrower parameter types). Runtime construction still uses the real shape;
|
|
7
|
+
* this alias is the DI “class token” surface only.
|
|
8
|
+
*/
|
|
9
|
+
type Constructor<Value = unknown> = new (...args: never[]) => Value;
|
|
10
|
+
/**
|
|
11
|
+
* Class constructor as invoked by the resolver after metadata-driven
|
|
12
|
+
* resolution of `unknown[]` dependencies — separate from {@link Constructor},
|
|
13
|
+
* which is the public assignable class token.
|
|
14
|
+
*/
|
|
15
|
+
type ConstructorInvocation = new (...args: unknown[]) => unknown;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { Constructor, ConstructorInvocation };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/container.d.mts
CHANGED
|
@@ -1,132 +1,53 @@
|
|
|
1
|
+
import { Constructor } from "./constructor-type.mjs";
|
|
1
2
|
import { Token } from "./token.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { ActivationHandler, BindingIdentifier, DeactivationHandler, ResolveOptions } from "./types.mjs";
|
|
4
|
+
import { BindToBuilder } from "./binding.mjs";
|
|
5
|
+
import { AsyncModule, SyncModule } from "./module.mjs";
|
|
6
|
+
import { BindingSnapshot, ContainerSnapshot } from "./inspector.mjs";
|
|
7
|
+
import { ContainerGraphJson, GraphOptions } from "./dependency-graph.mjs";
|
|
8
|
+
import { AutoRegisterRegistry } from "./decorators/injectable.mjs";
|
|
6
9
|
|
|
7
10
|
//#region src/container.d.ts
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* Same as {@link unbind} but awaits async `onDeactivation` handlers before removing.
|
|
34
|
-
*/
|
|
35
|
-
unbindAsync(tokenOrId: RegistryKey | BindingIdentifier): Promise<void>;
|
|
36
|
-
/**
|
|
37
|
-
* Returns `true` if at least one binding exists for `token`, optionally filtered by `hint`.
|
|
38
|
-
*/
|
|
39
|
-
has(token: RegistryKey, hint?: ResolveHint): boolean;
|
|
40
|
-
/**
|
|
41
|
-
* Resolves the token synchronously. Throws {@link AsyncResolutionError} if any binding in the chain is async.
|
|
42
|
-
*/
|
|
43
|
-
resolve<Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveHint): Value;
|
|
44
|
-
/**
|
|
45
|
-
* Resolves the token, awaiting any async factory in the chain. Safe for both sync and async bindings.
|
|
46
|
-
*/
|
|
47
|
-
resolveAsync<Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveHint): Promise<Value>;
|
|
48
|
-
/**
|
|
49
|
-
* Resolves all bindings registered for the token (multi-binding). Throws {@link AsyncResolutionError} if any is async.
|
|
50
|
-
*/
|
|
51
|
-
resolveAll<Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveHint): Value[];
|
|
52
|
-
/**
|
|
53
|
-
* Async variant of {@link resolveAll} — safe when the multi-binding set contains async factories.
|
|
54
|
-
*/
|
|
55
|
-
resolveAllAsync<Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveHint): Promise<Value[]>;
|
|
56
|
-
/**
|
|
57
|
-
* Resolves the token or returns `undefined` if no binding is registered (never throws on missing).
|
|
58
|
-
*/
|
|
59
|
-
resolveOptional<Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveHint): Value | undefined;
|
|
60
|
-
/**
|
|
61
|
-
* Registers bindings from one or more synchronous modules. Re-loading a module already present is a no-op.
|
|
62
|
-
*/
|
|
63
|
-
load(...modules: Module[]): void;
|
|
64
|
-
/**
|
|
65
|
-
* Registers bindings from sync and/or async modules, awaiting each async setup in sequence.
|
|
66
|
-
*/
|
|
67
|
-
loadAsync(...modules: ModuleLike[]): Promise<void>;
|
|
68
|
-
/**
|
|
69
|
-
* Removes all bindings contributed by the given modules; runs sync deactivation on released singletons.
|
|
70
|
-
*/
|
|
71
|
-
unload(...modules: ModuleLike[]): void;
|
|
72
|
-
/**
|
|
73
|
-
* Same as {@link unload} but awaits async `onDeactivation` handlers.
|
|
74
|
-
*/
|
|
75
|
-
unloadAsync(...modules: ModuleLike[]): Promise<void>;
|
|
76
|
-
/**
|
|
77
|
-
* Eagerly constructs every singleton binding so the first request is never cold.
|
|
78
|
-
*/
|
|
11
|
+
interface Container {
|
|
12
|
+
readonly isDisposed: boolean;
|
|
13
|
+
bind<const Value>(token: Token<Value> | Constructor<Value>): BindToBuilder<Value>;
|
|
14
|
+
unbind(tokenOrId: Token<unknown> | Constructor | BindingIdentifier): void;
|
|
15
|
+
unbindAsync(tokenOrId: Token<unknown> | Constructor | BindingIdentifier): Promise<void>;
|
|
16
|
+
unbindAll(): void;
|
|
17
|
+
unbindAllAsync(): Promise<void>;
|
|
18
|
+
rebind<const Value>(token: Token<Value> | Constructor<Value>): BindToBuilder<Value>;
|
|
19
|
+
load(...modules: SyncModule[]): void;
|
|
20
|
+
loadAsync(...modules: Array<SyncModule | AsyncModule>): Promise<void>;
|
|
21
|
+
unload(...modules: SyncModule[]): void;
|
|
22
|
+
unloadAsync(...modules: Array<SyncModule | AsyncModule>): Promise<void>;
|
|
23
|
+
loadAutoRegistered(registry: AutoRegisterRegistry): number;
|
|
24
|
+
onActivation<const Value>(token: Token<Value> | Constructor<Value>, handler: ActivationHandler<Value>): void;
|
|
25
|
+
onDeactivation<const Value>(token: Token<Value> | Constructor<Value>, handler: DeactivationHandler<Value>): void;
|
|
26
|
+
resolve<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Value;
|
|
27
|
+
resolveAsync<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Promise<Value>;
|
|
28
|
+
resolveOptional<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Value | undefined;
|
|
29
|
+
resolveOptionalAsync<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Promise<Value | undefined>;
|
|
30
|
+
resolveAll<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Value[];
|
|
31
|
+
resolveAllAsync<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Promise<Value[]>;
|
|
32
|
+
createChild(): Container;
|
|
33
|
+
dispose(): Promise<void>;
|
|
34
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
35
|
+
[Symbol.dispose](): never;
|
|
79
36
|
initializeAsync(): Promise<void>;
|
|
80
|
-
/**
|
|
81
|
-
* Scans {@link getAutoRegistered} entries and binds each to its declared scope. Returns the count added.
|
|
82
|
-
*/
|
|
83
|
-
loadAutoRegistered(): number;
|
|
84
|
-
/**
|
|
85
|
-
* Checks for scope violations (captive dependencies). Throws {@link ScopeViolationError} on the first violation found.
|
|
86
|
-
*/
|
|
87
37
|
validate(): void;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
38
|
+
has(token: Token<unknown> | Constructor, hint?: ResolveOptions): boolean;
|
|
39
|
+
hasOwn(token: Token<unknown> | Constructor, hint?: ResolveOptions): boolean;
|
|
40
|
+
lookupBindings<const Value>(token: Token<Value> | Constructor<Value>): readonly BindingSnapshot[];
|
|
91
41
|
inspect(): ContainerSnapshot;
|
|
92
|
-
/**
|
|
93
|
-
* Returns the canonical dependency graph as typed JSON (`nodes` + `edges`).
|
|
94
|
-
*/
|
|
95
42
|
generateDependencyGraph(options?: GraphOptions): ContainerGraphJson;
|
|
96
|
-
/**
|
|
97
|
-
* Creates a child container that inherits bindings from this container without polluting its registry.
|
|
98
|
-
*/
|
|
99
|
-
createChild(): Container;
|
|
100
|
-
/**
|
|
101
|
-
* @throws Always — container disposal is async; use `await using` or `await container.dispose()`.
|
|
102
|
-
*/
|
|
103
|
-
[Symbol.dispose](): never;
|
|
104
|
-
/**
|
|
105
|
-
* Returns the raw binding list for a token without triggering resolution. `undefined` means no binding.
|
|
106
|
-
*/
|
|
107
|
-
lookupBindings(token: RegistryKey): readonly Binding<unknown>[] | undefined;
|
|
108
|
-
/**
|
|
109
|
-
* Runs all `onDeactivation` hooks on active singletons and releases all caches.
|
|
110
|
-
*/
|
|
111
|
-
dispose(): Promise<void>;
|
|
112
|
-
[Symbol.asyncDispose](): Promise<void>;
|
|
113
43
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Creates an empty container with no bindings.
|
|
120
|
-
*/
|
|
121
|
-
function create(): Container;
|
|
122
|
-
/**
|
|
123
|
-
* Creates a container and immediately loads the given sync modules.
|
|
124
|
-
*/
|
|
125
|
-
function fromModules(...modules: Module[]): Container;
|
|
126
|
-
/**
|
|
127
|
-
* Creates a container and awaits loading of sync and/or async modules.
|
|
128
|
-
*/
|
|
129
|
-
function fromModulesAsync(...modules: (Module | AsyncModule)[]): Promise<Container>;
|
|
44
|
+
interface ContainerStatic {
|
|
45
|
+
create(): Container;
|
|
46
|
+
fromModules(...modules: SyncModule[]): Container;
|
|
47
|
+
fromModulesAsync(...modules: Array<SyncModule | AsyncModule>): Promise<Container>;
|
|
130
48
|
}
|
|
49
|
+
declare const Container: ContainerStatic & {
|
|
50
|
+
create(): Container;
|
|
51
|
+
};
|
|
131
52
|
//#endregion
|
|
132
|
-
export { Container };
|
|
53
|
+
export { Container, ContainerStatic };
|