@codefast/di 0.11.0 → 0.13.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/CHANGELOG.md +151 -0
- package/README.md +128 -31
- package/dist/container/{binding-builders.d.ts → binding-chain.d.ts} +21 -28
- package/dist/container/{binding-builders.js → binding-chain.js} +53 -163
- package/dist/container/container.d.ts +11 -3
- package/dist/container/container.js +176 -102
- package/dist/core/binding-builders.d.ts +117 -0
- package/dist/core/binding-declaration.d.ts +9 -2
- package/dist/core/binding-declaration.js +5 -4
- package/dist/core/binding.d.ts +21 -149
- package/dist/core/binding.js +15 -25
- package/dist/core/module.d.ts +1 -1
- package/dist/core/registry.d.ts +9 -24
- package/dist/core/registry.js +30 -155
- package/dist/core/tag.js +1 -1
- package/dist/decorators/inject.d.ts +3 -1
- package/dist/decorators/inject.js +5 -5
- package/dist/decorators/injectable.js +2 -2
- package/dist/decorators/lifecycle.d.ts +20 -0
- package/dist/decorators/{lifecycle-decorators.js → lifecycle.js} +7 -3
- package/dist/decorators/{decorator-metadata.js → metadata-record.js} +1 -1
- package/dist/{errors/errors.d.ts → errors.d.ts} +29 -19
- package/dist/{errors/errors.js → errors.js} +43 -25
- package/dist/index.d.ts +12 -10
- package/dist/index.js +6 -6
- package/dist/injection/descriptor.d.ts +1 -1
- package/dist/introspection/dependency-graph.d.ts +1 -1
- package/dist/introspection/dependency-graph.js +3 -4
- package/dist/introspection/explanation.d.ts +101 -0
- package/dist/introspection/explanation.js +169 -0
- package/dist/introspection/inspector.d.ts +9 -2
- package/dist/introspection/inspector.js +25 -20
- package/dist/lifecycle/{lifecycle-manager.d.ts → hooks.d.ts} +11 -2
- package/dist/lifecycle/{lifecycle-manager.js → hooks.js} +51 -28
- package/dist/lifecycle/{scope-manager.d.ts → scopes.d.ts} +23 -6
- package/dist/lifecycle/{scope-manager.js → scopes.js} +93 -20
- package/dist/metadata/{metadata-keys.d.ts → keys.d.ts} +1 -1
- package/dist/metadata/{metadata-keys.js → keys.js} +1 -1
- package/dist/metadata/{metadata-reader-token.d.ts → reader-token.d.ts} +1 -1
- package/dist/metadata/{symbol-metadata-reader.d.ts → symbol-reader.d.ts} +1 -1
- package/dist/metadata/{symbol-metadata-reader.js → symbol-reader.js} +1 -1
- package/dist/metadata/{metadata-types.d.ts → types.d.ts} +1 -1
- package/dist/metadata/types.js +1 -0
- package/dist/metadata/verify.d.ts +43 -0
- package/dist/metadata/verify.js +133 -0
- package/dist/metadata/{verifying-metadata-reader.d.ts → verifying-reader.d.ts} +1 -1
- package/dist/metadata/{verifying-metadata-reader.js → verifying-reader.js} +2 -2
- package/dist/resolution/cache/activation-need.d.ts +1 -1
- package/dist/resolution/cache/activation-need.js +5 -1
- package/dist/resolution/cache/class-introspector.d.ts +27 -36
- package/dist/resolution/cache/class-introspector.js +61 -159
- package/dist/resolution/cache/{binding-lookup-cache.d.ts → lookup.d.ts} +7 -2
- package/dist/resolution/cache/{binding-lookup-cache.js → lookup.js} +40 -8
- package/dist/resolution/context.d.ts +1 -1
- package/dist/resolution/context.js +1 -1
- package/dist/resolution/{path/resolution-path.d.ts → path.d.ts} +12 -2
- package/dist/resolution/{path/resolution-path.js → path.js} +23 -3
- package/dist/resolution/plan/{plan-codegen.d.ts → codegen.d.ts} +2 -4
- package/dist/resolution/plan/{plan-codegen.js → codegen.js} +2 -4
- package/dist/resolution/plan/{instantiation-plan.d.ts → compiler.d.ts} +1 -1
- package/dist/resolution/plan/{instantiation-plan.js → compiler.js} +4 -4
- package/dist/resolution/resolver.d.ts +19 -7
- package/dist/resolution/resolver.js +343 -125
- package/dist/resolution/select/{binding-select.d.ts → candidates.d.ts} +30 -0
- package/dist/resolution/select/{binding-select.js → candidates.js} +51 -10
- package/dist/resolution/select/constraints.js +1 -1
- package/package.json +80 -72
- package/dist/core/binding-scope.d.ts +0 -12
- package/dist/core/binding-scope.js +0 -12
- package/dist/decorators/lifecycle-decorators.d.ts +0 -14
- /package/dist/{ambient/active-container.d.ts → ambient-container.d.ts} +0 -0
- /package/dist/{ambient/active-container.js → ambient-container.js} +0 -0
- /package/dist/{metadata/metadata-types.js → core/binding-builders.js} +0 -0
- /package/dist/decorators/{decorator-metadata.d.ts → metadata-record.d.ts} +0 -0
- /package/dist/injection/{resolve-options.d.ts → dependency-slot.d.ts} +0 -0
- /package/dist/injection/{resolve-options.js → dependency-slot.js} +0 -0
- /package/dist/{errors → introspection}/diagnostics.d.ts +0 -0
- /package/dist/{errors → introspection}/diagnostics.js +0 -0
- /package/dist/metadata/{metadata-reader-token.js → reader-token.js} +0 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { clearBindingFrame, NO_ACTIVATION_STAMP, DEFAULT_BINDING_SLOT, generateBindingId, NO_INSTANCE,
|
|
1
|
+
import { clearBindingFrame, NO_ACTIVATION_STAMP, DEFAULT_BINDING_SLOT, generateBindingId, NO_INSTANCE, withSlotCriterion, } from "#core/binding";
|
|
2
2
|
import { mergingConstraintRequirements } from "#core/constraint-requirement";
|
|
3
3
|
import { slotName } from "#core/tag";
|
|
4
4
|
import { tokenName } from "#core/token";
|
|
5
|
-
import { ChainAlreadyRegisteredError, ChainNotRegisteredError, ManyBindingSlotError, SelfBindingRequiresClassError, } from "#errors
|
|
5
|
+
import { ChainAlreadyRegisteredError, ChainNotRegisteredError, ManyBindingSlotError, SelfBindingRequiresClassError, } from "#errors";
|
|
6
6
|
import { normalizeToDescriptor } from "#injection/descriptor";
|
|
7
7
|
// ── BindingChain ─────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
8
8
|
/**
|
|
9
9
|
* The one builder behind `bind()` and every `to*()` return type — and the binding it registers.
|
|
10
10
|
*
|
|
11
11
|
* @remarks The binding fields come first, in the order every binding shares, and the chain's own
|
|
12
|
-
* bookkeeping follows as private
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* bookkeeping follows as a private field. The slot steps write the fields before anything registers;
|
|
13
|
+
* `to*()` fills the strategy in place and hands this object to the registry once, so a bind is one
|
|
14
|
+
* allocation and one add. A scope or hook afterwards writes the registered object in place.
|
|
15
15
|
*
|
|
16
16
|
* @since 0.5.0-canary.8
|
|
17
17
|
*/
|
|
@@ -23,8 +23,8 @@ export class BindingChain {
|
|
|
23
23
|
frame = undefined;
|
|
24
24
|
rootContext = undefined;
|
|
25
25
|
activationStamp = NO_ACTIVATION_STAMP;
|
|
26
|
-
registrationOrder = UNREGISTERED_ORDER;
|
|
27
26
|
instance = NO_INSTANCE;
|
|
27
|
+
scopedCacheKey = this.identifier;
|
|
28
28
|
token;
|
|
29
29
|
slot = DEFAULT_BINDING_SLOT;
|
|
30
30
|
predicate = undefined;
|
|
@@ -38,10 +38,6 @@ export class BindingChain {
|
|
|
38
38
|
deactivationHook = undefined;
|
|
39
39
|
// The chain. Set by the first `to*()`, which is the only one a chain accepts.
|
|
40
40
|
#isRegistered = false;
|
|
41
|
-
// Allocated only by a chain that actually displaces something — most never do.
|
|
42
|
-
#displacedByChain;
|
|
43
|
-
// Registry version after this chain's last write — a mismatch means someone else wrote in between.
|
|
44
|
-
#versionAfterLastWrite = -1;
|
|
45
41
|
#registration;
|
|
46
42
|
constructor(token, registration) {
|
|
47
43
|
this.token = token;
|
|
@@ -51,13 +47,13 @@ export class BindingChain {
|
|
|
51
47
|
get #binding() {
|
|
52
48
|
return this;
|
|
53
49
|
}
|
|
54
|
-
/** Loud failure for a
|
|
50
|
+
/** Loud failure for a scope, a hook or `id()` before `to*()`. */
|
|
55
51
|
#requireRegistered() {
|
|
56
52
|
if (!this.#isRegistered) {
|
|
57
53
|
throw new ChainNotRegisteredError(tokenName(this.token));
|
|
58
54
|
}
|
|
59
55
|
}
|
|
60
|
-
/** Loud failure for a second `to*()
|
|
56
|
+
/** Loud failure for a slot step or a second `to*()` once registered, raised before a field is overwritten. */
|
|
61
57
|
#requireUnregistered() {
|
|
62
58
|
if (this.#isRegistered) {
|
|
63
59
|
throw new ChainAlreadyRegisteredError(tokenName(this.token));
|
|
@@ -67,32 +63,22 @@ export class BindingChain {
|
|
|
67
63
|
this.kind = kind;
|
|
68
64
|
this.scope = scope;
|
|
69
65
|
this.#isRegistered = true;
|
|
70
|
-
// A fresh registration parks nothing yet and restores nothing: one add, then the version.
|
|
71
66
|
const registration = this.#registration;
|
|
72
|
-
const
|
|
73
|
-
const displaced = registry.add(this.#binding);
|
|
67
|
+
const displaced = registration.registry.add(this.#binding);
|
|
74
68
|
if (displaced !== undefined) {
|
|
75
69
|
if (registration.deactivateDisplaced !== undefined) {
|
|
76
70
|
registration.deactivateDisplaced(displaced);
|
|
77
71
|
}
|
|
78
72
|
else {
|
|
79
|
-
this.#displacedByChain = [displaced];
|
|
80
73
|
registration.onDisplaced?.(displaced);
|
|
81
74
|
}
|
|
82
75
|
}
|
|
83
76
|
if (registration.moduleBindingIds !== undefined) {
|
|
84
77
|
registration.moduleBindingIds.push(this.identifier);
|
|
85
78
|
}
|
|
86
|
-
this.#versionAfterLastWrite = registry.version;
|
|
87
79
|
return this;
|
|
88
80
|
}
|
|
89
|
-
/**
|
|
90
|
-
* Registers a declared module's bindings in list order, each a chain of its own that no step
|
|
91
|
-
* will ever refine.
|
|
92
|
-
*
|
|
93
|
-
* @remarks A displaced binding is handled as `to*()` handles it, never parked: nothing refines the
|
|
94
|
-
* chain, so nothing could restore it.
|
|
95
|
-
*/
|
|
81
|
+
/** Registers a declared module's bindings in list order, each a chain of its own, handled as `to*()` handles one. */
|
|
96
82
|
static registerDeclared(declarations, registration) {
|
|
97
83
|
const { registry, moduleBindingIds, deactivateDisplaced, onDisplaced } = registration;
|
|
98
84
|
for (let index = 0; index < declarations.length; index += 1) {
|
|
@@ -177,102 +163,67 @@ export class BindingChain {
|
|
|
177
163
|
this.target = target;
|
|
178
164
|
return this.#register("alias", "transient");
|
|
179
165
|
}
|
|
180
|
-
// ──
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
*
|
|
184
|
-
* @remarks When it does, a refinement rewrites the live binding in place; otherwise `#reslot`
|
|
185
|
-
* re-checks liveness and restores what the new shape frees.
|
|
186
|
-
*/
|
|
187
|
-
get #isProvablyLive() {
|
|
188
|
-
return this.#registration.registry.version === this.#versionAfterLastWrite && this.#displacedByChain === undefined;
|
|
189
|
-
}
|
|
190
|
-
/** Stamps this chain's last-write version after a mutation it made in place. */
|
|
191
|
-
#recordWrite() {
|
|
192
|
-
this.#versionAfterLastWrite = this.#registration.registry.version;
|
|
193
|
-
}
|
|
194
|
-
/** Bumps the registry for an index-neutral mutation (scope, hook) and records this chain's write. */
|
|
195
|
-
#touchAndRecordWrite() {
|
|
196
|
-
this.#registration.registry.touch();
|
|
197
|
-
this.#recordWrite();
|
|
198
|
-
}
|
|
199
|
-
// Slot and predicate are what the registry indexes on, so a re-slot takes the binding out of the
|
|
200
|
-
// registry, rewrites the two fields while it is out, and registers it again — same object, same id.
|
|
201
|
-
#reslot(slot, predicate) {
|
|
202
|
-
this.#requireRegistered();
|
|
203
|
-
this.#commit(() => {
|
|
204
|
-
this.slot = slot;
|
|
205
|
-
this.predicate = predicate;
|
|
206
|
-
// The frame reports the slot, so a resolve before this call memoized the previous one.
|
|
207
|
-
clearBindingFrame(this.#binding);
|
|
208
|
-
});
|
|
209
|
-
return this;
|
|
210
|
-
}
|
|
211
|
-
#withScope(scope) {
|
|
212
|
-
this.#requireRegistered();
|
|
213
|
-
if (this.scope !== scope) {
|
|
214
|
-
// An instance cached under the old scope must not survive the change — a later flip back
|
|
215
|
-
// to that scope would resurrect it.
|
|
216
|
-
this.#registration.scope.deleteSingleton(this.#binding);
|
|
217
|
-
this.#registration.scope.deleteScoped(this.identifier);
|
|
218
|
-
this.scope = scope;
|
|
219
|
-
}
|
|
220
|
-
// The frame reports the scope, so a resolve before this call memoized the previous one.
|
|
221
|
-
clearBindingFrame(this.#binding);
|
|
222
|
-
this.#touchAndRecordWrite();
|
|
223
|
-
return this;
|
|
224
|
-
}
|
|
225
|
-
// SPEC calls a candidate a binding that passes *all* of a chain's predicates, and the chain type
|
|
226
|
-
// reads as refinement, so a second `when()` narrows rather than replaces.
|
|
166
|
+
// ── Slot ───────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
167
|
+
// SPEC calls a candidate a binding that passes *all* of a chain's predicates, so a second `when()`
|
|
168
|
+
// narrows rather than replaces.
|
|
227
169
|
when(predicate) {
|
|
228
|
-
this.#
|
|
170
|
+
this.#requireUnregistered();
|
|
229
171
|
const previous = this.predicate;
|
|
230
172
|
// The composite carries both sides' requirements, so validate() still sees them.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
this.#registration.registry.setPredicate(this.#binding, narrowed);
|
|
237
|
-
this.#recordWrite();
|
|
238
|
-
return this;
|
|
239
|
-
}
|
|
240
|
-
return this.#reslot(this.slot, narrowed);
|
|
173
|
+
this.predicate =
|
|
174
|
+
previous === undefined
|
|
175
|
+
? predicate
|
|
176
|
+
: mergingConstraintRequirements((ctx) => previous(ctx) && predicate(ctx), previous, predicate);
|
|
177
|
+
return this;
|
|
241
178
|
}
|
|
242
179
|
whenNamed(name) {
|
|
243
180
|
return this.whenTagged(slotName.of(name));
|
|
244
181
|
}
|
|
245
182
|
whenTagged(criterion) {
|
|
246
|
-
this.#
|
|
183
|
+
this.#requireUnregistered();
|
|
247
184
|
if (this.isMany) {
|
|
248
185
|
throw new ManyBindingSlotError(tokenName(this.token));
|
|
249
186
|
}
|
|
250
|
-
|
|
187
|
+
this.slot = withSlotCriterion(this.slot, criterion);
|
|
188
|
+
return this;
|
|
251
189
|
}
|
|
252
190
|
many() {
|
|
253
|
-
this.#
|
|
191
|
+
this.#requireUnregistered();
|
|
254
192
|
if (this.slot.tags.length !== 0) {
|
|
255
193
|
throw new ManyBindingSlotError(tokenName(this.token));
|
|
256
194
|
}
|
|
257
|
-
|
|
258
|
-
return this;
|
|
259
|
-
}
|
|
260
|
-
// A provably-live binding takes membership in place; the registry only moves it out of the lone
|
|
261
|
-
// map. Otherwise `#commit` re-checks liveness and restores what the freed slot lets back in.
|
|
262
|
-
if (this.#isProvablyLive) {
|
|
263
|
-
this.#registration.registry.setMany(this.#binding);
|
|
264
|
-
this.#recordWrite();
|
|
265
|
-
return this;
|
|
266
|
-
}
|
|
267
|
-
this.#commit(() => {
|
|
268
|
-
this.isMany = true;
|
|
269
|
-
});
|
|
195
|
+
this.isMany = true;
|
|
270
196
|
return this;
|
|
271
197
|
}
|
|
272
198
|
whenDefault() {
|
|
273
|
-
// The default slot is what a fresh
|
|
274
|
-
|
|
199
|
+
// The default slot is what a fresh chain already has; the check keeps it a slot step like the others.
|
|
200
|
+
this.#requireUnregistered();
|
|
201
|
+
return this;
|
|
202
|
+
}
|
|
203
|
+
// ── Scope and lifecycle ────────────────────────────────────────────────────────────────────────────────────────────
|
|
204
|
+
#withScope(scope) {
|
|
275
205
|
this.#requireRegistered();
|
|
206
|
+
// Nothing a cache, a frame or the version answers for depends on a scope that did not change.
|
|
207
|
+
if (this.scope === scope) {
|
|
208
|
+
return this;
|
|
209
|
+
}
|
|
210
|
+
// An instance cached under the old scope must not survive the change — a later flip back to that
|
|
211
|
+
// scope would resurrect it. A child's scoped cache is out of reach here, so leaving `scoped` retires
|
|
212
|
+
// the key every child filed its instance under.
|
|
213
|
+
const registration = this.#registration;
|
|
214
|
+
if (this.instance !== NO_INSTANCE) {
|
|
215
|
+
registration.scope.deleteSingleton(this.#binding);
|
|
216
|
+
}
|
|
217
|
+
if (this.scope === "scoped") {
|
|
218
|
+
registration.scope.deleteScoped(this.scopedCacheKey);
|
|
219
|
+
this.scopedCacheKey = generateBindingId();
|
|
220
|
+
}
|
|
221
|
+
this.scope = scope;
|
|
222
|
+
// The frame reports the scope, so a resolve before this call memoized the previous one.
|
|
223
|
+
if (this.frame !== undefined || this.rootContext !== undefined) {
|
|
224
|
+
clearBindingFrame(this.#binding);
|
|
225
|
+
}
|
|
226
|
+
registration.registry.touch();
|
|
276
227
|
return this;
|
|
277
228
|
}
|
|
278
229
|
singleton() {
|
|
@@ -287,78 +238,17 @@ export class BindingChain {
|
|
|
287
238
|
onActivation(fn) {
|
|
288
239
|
this.#requireRegistered();
|
|
289
240
|
this.activationHook = fn;
|
|
290
|
-
this.#
|
|
241
|
+
this.#registration.registry.touch();
|
|
291
242
|
return this;
|
|
292
243
|
}
|
|
293
244
|
onDeactivation(fn) {
|
|
294
245
|
this.#requireRegistered();
|
|
295
246
|
this.deactivationHook = fn;
|
|
296
|
-
this.#
|
|
247
|
+
this.#registration.registry.touch();
|
|
297
248
|
return this;
|
|
298
249
|
}
|
|
299
250
|
id() {
|
|
300
251
|
this.#requireRegistered();
|
|
301
252
|
return this.identifier;
|
|
302
253
|
}
|
|
303
|
-
// ── Registry ───────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
304
|
-
/**
|
|
305
|
-
* Registers this binding; with `rewrite` given, first takes the live binding out, rewrites it, and
|
|
306
|
-
* registers it again.
|
|
307
|
-
*
|
|
308
|
-
* @remarks A `when*()` that follows `to*()` re-slots an already-live binding and can displace one
|
|
309
|
-
* the final shape would never conflict with. Those stay parked in `#displacedByChain` until the
|
|
310
|
-
* chain settles, then get restored.
|
|
311
|
-
*/
|
|
312
|
-
#commit(rewrite) {
|
|
313
|
-
const { registry, moduleBindingIds } = this.#registration;
|
|
314
|
-
const registered = this.#binding;
|
|
315
|
-
if (rewrite !== undefined) {
|
|
316
|
-
// A registry someone else wrote since this chain's last write invalidates the parked
|
|
317
|
-
// snapshot: restoring it could undo an unbind or shadow a newer binding.
|
|
318
|
-
if (registry.version !== this.#versionAfterLastWrite) {
|
|
319
|
-
this.#displacedByChain = undefined;
|
|
320
|
-
}
|
|
321
|
-
if (!registry.reslot(registered, rewrite)) {
|
|
322
|
-
// The chain's binding is no longer live (unbound or displaced) — a refinement must not
|
|
323
|
-
// resurrect it, so the chain goes inert against the registry.
|
|
324
|
-
this.#displacedByChain = undefined;
|
|
325
|
-
this.#versionAfterLastWrite = registry.version;
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
// Each `to*()` starts its own registration, so anything a previous one displaced is not this
|
|
331
|
-
// registration's to restore.
|
|
332
|
-
this.#displacedByChain = undefined;
|
|
333
|
-
}
|
|
334
|
-
const displaced = registry.add(registered);
|
|
335
|
-
if (displaced !== undefined) {
|
|
336
|
-
if (this.#registration.deactivateDisplaced !== undefined && rewrite === undefined) {
|
|
337
|
-
this.#registration.deactivateDisplaced(displaced);
|
|
338
|
-
}
|
|
339
|
-
else {
|
|
340
|
-
(this.#displacedByChain ??= []).push(displaced);
|
|
341
|
-
this.#registration.onDisplaced?.(displaced);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
if (rewrite !== undefined && this.#displacedByChain !== undefined) {
|
|
345
|
-
this.#restoreNonConflicting(this.#displacedByChain);
|
|
346
|
-
}
|
|
347
|
-
if (rewrite === undefined && moduleBindingIds !== undefined) {
|
|
348
|
-
moduleBindingIds.push(this.identifier);
|
|
349
|
-
}
|
|
350
|
-
this.#versionAfterLastWrite = registry.version;
|
|
351
|
-
}
|
|
352
|
-
#restoreNonConflicting(displaced) {
|
|
353
|
-
for (let index = displaced.length - 1; index >= 0; index -= 1) {
|
|
354
|
-
const candidate = displaced[index];
|
|
355
|
-
// A restore must never displace: a slot that has been re-occupied keeps its occupant, and
|
|
356
|
-
// the candidate stays parked.
|
|
357
|
-
if (!this.#registration.registry.hasSlotOccupant(candidate)) {
|
|
358
|
-
this.#registration.registry.add(candidate);
|
|
359
|
-
this.#registration.onRestored?.(candidate);
|
|
360
|
-
displaced.splice(index, 1);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
254
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type { BindToBuilder } from "#core/binding";
|
|
1
|
+
import type { BindToBuilder } from "#core/binding-builders";
|
|
2
2
|
import type { AsyncModule, SyncModule } from "#core/module";
|
|
3
3
|
import type { Token } from "#core/token";
|
|
4
4
|
import type { ActivationHandler, BindingIdentifier, Constructor, DeactivationHandler, ResolveOptions } from "#core/types";
|
|
5
5
|
import type { AutoRegisterRegistry } from "#decorators/injectable";
|
|
6
6
|
import type { ContainerGraphJson, GraphOptions } from "#introspection/dependency-graph";
|
|
7
|
+
import type { ExplainOptions, ResolutionExplanation } from "#introspection/explanation";
|
|
7
8
|
import type { BindingSnapshot, ContainerSnapshot } from "#introspection/inspector";
|
|
8
|
-
import type { MetadataReader } from "#metadata/
|
|
9
|
+
import type { MetadataReader } from "#metadata/types";
|
|
9
10
|
/**
|
|
10
11
|
* The public surface: binding, resolving, modules, lifecycle hooks, child scopes, and disposal.
|
|
11
12
|
*
|
|
@@ -35,13 +36,20 @@ export interface Container {
|
|
|
35
36
|
createChild(): Container;
|
|
36
37
|
dispose(): Promise<void>;
|
|
37
38
|
[Symbol.asyncDispose](): Promise<void>;
|
|
38
|
-
[Symbol.dispose](): never;
|
|
39
39
|
initializeAsync(): Promise<void>;
|
|
40
40
|
validate(): void;
|
|
41
41
|
has<Names extends string = string>(token: Token<unknown, Names> | Constructor, options?: NoInfer<ResolveOptions<Names>>): boolean;
|
|
42
42
|
hasOwn<Names extends string = string>(token: Token<unknown, Names> | Constructor, options?: NoInfer<ResolveOptions<Names>>): boolean;
|
|
43
43
|
lookupBindings<Value>(token: Token<Value> | Constructor<Value>): ReadonlyArray<BindingSnapshot>;
|
|
44
44
|
inspect(): ContainerSnapshot;
|
|
45
|
+
/**
|
|
46
|
+
* Explains why a request selects the binding it does, reading each registry the way `resolve` does and deciding
|
|
47
|
+
* by the same rules, without instantiating anything.
|
|
48
|
+
*
|
|
49
|
+
* @remarks A `when()` predicate runs here as it would in `resolve`. `options.ancestors` names the resolutions the
|
|
50
|
+
* request is nested in, so a predicate that reads the parent sees the one it would.
|
|
51
|
+
*/
|
|
52
|
+
explain<Names extends string = string>(token: Token<unknown, Names> | Constructor, options?: NoInfer<ExplainOptions<Names>>): ResolutionExplanation;
|
|
45
53
|
generateDependencyGraph(options?: GraphOptions): ContainerGraphJson;
|
|
46
54
|
}
|
|
47
55
|
/**
|