@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.
Files changed (65) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +42 -26
  3. package/dist/binding-scope.d.mts +11 -0
  4. package/dist/binding-scope.mjs +19 -0
  5. package/dist/binding-select.d.mts +8 -26
  6. package/dist/binding-select.mjs +56 -49
  7. package/dist/binding.d.mts +107 -335
  8. package/dist/binding.mjs +19 -332
  9. package/dist/constraints.d.mts +11 -29
  10. package/dist/constraints.mjs +32 -36
  11. package/dist/constructor-type.d.mts +17 -0
  12. package/dist/constructor-type.mjs +1 -0
  13. package/dist/container.d.mts +43 -122
  14. package/dist/container.mjs +667 -482
  15. package/dist/decorators/inject.d.mts +19 -50
  16. package/dist/decorators/inject.mjs +131 -93
  17. package/dist/decorators/injectable.d.mts +16 -37
  18. package/dist/decorators/injectable.mjs +47 -66
  19. package/dist/decorators/lifecycle-decorators.d.mts +2 -22
  20. package/dist/decorators/lifecycle-decorators.mjs +81 -37
  21. package/dist/dependency-graph.d.mts +24 -54
  22. package/dist/dependency-graph.mjs +51 -153
  23. package/dist/environment.d.mts +38 -12
  24. package/dist/environment.mjs +82 -16
  25. package/dist/errors.d.mts +70 -189
  26. package/dist/errors.mjs +92 -219
  27. package/dist/graph-adapters/cytoscape.d.mts +21 -7
  28. package/dist/graph-adapters/cytoscape.mjs +18 -35
  29. package/dist/graph-adapters/dot.d.mts +1 -4
  30. package/dist/graph-adapters/dot.mjs +6 -86
  31. package/dist/graph-adapters/reactflow.d.mts +26 -7
  32. package/dist/graph-adapters/reactflow.mjs +21 -72
  33. package/dist/graph-adapters/types.d.mts +2 -91
  34. package/dist/index.d.mts +16 -8
  35. package/dist/index.mjs +8 -5
  36. package/dist/inspector.d.mts +35 -74
  37. package/dist/inspector.mjs +61 -88
  38. package/dist/lifecycle.d.mts +20 -53
  39. package/dist/lifecycle.mjs +129 -99
  40. package/dist/metadata/metadata-keys.d.mts +9 -26
  41. package/dist/metadata/metadata-keys.mjs +7 -28
  42. package/dist/metadata/metadata-reader-token.d.mts +7 -0
  43. package/dist/metadata/metadata-reader-token.mjs +5 -0
  44. package/dist/metadata/metadata-types.d.mts +26 -75
  45. package/dist/metadata/symbol-metadata-reader.d.mts +10 -26
  46. package/dist/metadata/symbol-metadata-reader.mjs +32 -45
  47. package/dist/module.d.mts +30 -96
  48. package/dist/module.mjs +26 -72
  49. package/dist/registry.d.mts +32 -63
  50. package/dist/registry.mjs +131 -82
  51. package/dist/resolve-options.d.mts +18 -0
  52. package/dist/resolve-options.mjs +22 -0
  53. package/dist/resolver.d.mts +67 -190
  54. package/dist/resolver.mjs +715 -424
  55. package/dist/scope.d.mts +19 -106
  56. package/dist/scope.mjs +37 -196
  57. package/dist/token.d.mts +8 -22
  58. package/dist/token.mjs +9 -11
  59. package/dist/types.d.mts +48 -0
  60. package/dist/types.mjs +1 -0
  61. package/package.json +36 -14
  62. package/dist/metadata/param-registry.d.mts +0 -16
  63. package/dist/metadata/param-registry.mjs +0 -31
  64. package/dist/scope-validation.d.mts +0 -21
  65. package/dist/scope-validation.mjs +0 -35
@@ -1,352 +1,124 @@
1
- import { Token, TokenValue } from "./token.mjs";
2
- import { RegistryKey } from "./registry.mjs";
1
+ import { Constructor } from "./constructor-type.mjs";
2
+ import { Token } from "./token.mjs";
3
+ import { ActivationHandler, BindingIdentifier, BindingScope, ConstraintContext, DeactivationHandler, DependencyKey, ResolutionContext, TokenValue } from "./types.mjs";
4
+ import { InjectionDescriptor } from "./decorators/inject.mjs";
3
5
 
4
6
  //#region src/binding.d.ts
5
- declare const bindingIdentifierBrand: unique symbol;
6
- /**
7
- * Stable, opaque identifier for a single binding entry inside the registry.
8
- */
9
- type BindingIdentifier = string & {
10
- readonly [bindingIdentifierBrand]: void;
11
- };
12
- /**
13
- * Allocates a new opaque binding identifier (used when `.id(...)` is not supplied).
14
- */
15
- declare function createBindingIdentifier(): BindingIdentifier;
16
- /**
17
- * Runtime constructor token used as a registry key (no reflection metadata).
18
- */
19
- type Constructor<Value> = abstract new (...args: never[]) => Value;
20
- /**
21
- * Lifetime strategy for a resolved instance.
22
- */
23
- type BindingScope = "singleton" | "transient" | "scoped";
24
- /**
25
- * Hint for disambiguating multi-bindings registered against the same token or constructor.
26
- */
27
- type ResolveHint = {
28
- /** Matches bindings configured with `.whenNamed(name)`. */readonly name?: string; /** Matches bindings configured with `.whenTagged(tagKey, value)`. */
29
- readonly tag?: readonly [tag: string, value: unknown];
30
- };
31
- /**
32
- * Public alias for {@link ResolveHint} — the `hint` parameter accepted by
33
- * `Container.resolve`, `Container.resolveAsync`, and related methods.
34
- * Passes `name` and/or `tag` to select among multi-bindings.
35
- */
36
- type ResolveOptions = ResolveHint;
37
- /**
38
- * Snapshot of a binding on the materialization stack (for {@link ConstraintContext}).
39
- */
40
- type ConstraintBindingKind = "constant" | "class" | "dynamic" | "async-dynamic" | "resolved" | "alias";
41
- /**
42
- * Snapshot of a single binding on the materialization stack during resolution.
43
- * Each frame captures enough identity to implement contextual constraints
44
- * ({@link whenParentIs}, {@link whenAnyAncestorIs}) and captive-dependency detection.
45
- */
46
- type ConstraintParentFrame = {
47
- /** Registry key (token/constructor) that selected this binding. */readonly registryKey: RegistryKey; /** Stable identifier of the materialized binding. */
48
- readonly bindingId: BindingIdentifier; /** Discriminant of the selected binding strategy. */
49
- readonly bindingKind: ConstraintBindingKind; /** Immutable tag map present on the selected binding. */
50
- readonly tags: ReadonlyMap<string, unknown>; /** Effective scope of the selected binding. */
51
- readonly scope: BindingScope;
52
- };
53
- /**
54
- * @alias {@link ConstraintParentFrame} — frame on the materialization stack during resolution.
55
- */
56
- type MaterializationFrame = ConstraintParentFrame;
57
- /**
58
- * Context for {@link BindingBuilder.when} predicates: path, ancestor metadata, and the current resolve hint.
59
- */
60
- type ConstraintContext = {
61
- /** Resolution labels from root request to current key. */readonly resolutionPath: readonly string[]; /** Full chain of materialized parent frames (oldest → newest). */
62
- readonly materializationStack: readonly ConstraintParentFrame[]; /** Immediate parent frame, if the current resolution has one. */
63
- readonly parent: ConstraintParentFrame | undefined; /** Parent chain excluding the immediate parent frame. */
64
- readonly ancestors: readonly ConstraintParentFrame[]; /** Name/tag hint used for the current lookup, if provided. */
65
- readonly currentResolveHint: ResolveHint | undefined;
66
- };
67
- /**
68
- * Context passed to factories and lifecycle hooks so nested dependencies resolve with the same path rules.
69
- *
70
- * `graph` exposes the current position in the dependency graph (resolution path, materialization
71
- * stack, parent/ancestor frames) — used by {@link BindingBuilder.when} predicates to implement
72
- * context-sensitive bindings such as `whenParentIs` or `whenAnyAncestorIs`.
73
- */
74
- type ResolutionContext = {
75
- /** Resolves one binding synchronously using current path/stack context. */readonly resolve: <Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions) => Value; /** Async variant of {@link ResolutionContext.resolve}. */
76
- readonly resolveAsync: <Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions) => Promise<Value>; /** Returns `undefined` when the requested root key is unbound. */
77
- readonly resolveOptional: <Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions) => Value | undefined; /** Resolves every binding registered for `token` (multi-binding). */
78
- readonly resolveAll: <Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions) => Value[]; /** Async variant of {@link ResolutionContext.resolveAll}. */
79
- readonly resolveAllAsync: <Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions) => Promise<Value[]>;
80
- /**
81
- * Dependency-graph navigation context — path, materialization stack, parent/ancestor frames.
82
- */
83
- readonly graph: ConstraintContext;
84
- };
85
- /**
86
- * Lifecycle and constraint fields shared by every concrete {@link Binding} variant.
87
- * Separated from {@link BindingBase} so the builder can accumulate them independently of `id` / `scope`.
88
- */
89
- type BindingLifecycle = {
90
- readonly bindingName?: string;
91
- readonly tags: ReadonlyMap<string, unknown>;
92
- readonly onActivation?: ActivationHandler<unknown>;
93
- readonly onDeactivation?: DeactivationHandler<unknown>;
94
- readonly constraint?: (ctx: ConstraintContext) => boolean;
95
- };
96
- /**
97
- * Called after an instance is constructed (and after `@postConstruct`).
98
- * The return value replaces the instance in the scope cache — use this to wrap with a proxy or
99
- * apply post-processing. May be async; async handlers require `resolveAsync`.
100
- */
101
- type ActivationHandler<Value> = (ctx: ResolutionContext, instance: Value) => Value | Promise<Value>;
102
- /**
103
- * Called before a singleton/scoped instance is evicted from the scope cache.
104
- * Runs after `@preDestroy`. May be async; async deactivation requires `disposeAsync` / `unloadAsync`.
105
- */
106
- type DeactivationHandler<Value> = (instance: Value) => void | Promise<void>;
107
- type BindingBase = BindingLifecycle & {
7
+ interface SlotKey {
8
+ readonly name: string | undefined;
9
+ readonly tags: ReadonlyArray<readonly [tag: string, value: unknown]>;
10
+ }
11
+ declare function slotKeyEquals(a: SlotKey, b: SlotKey): boolean;
12
+ declare const DEFAULT_SLOT: SlotKey;
13
+ declare function slotKeyToString(slot: SlotKey): string;
14
+ interface BindingBase<Value> {
108
15
  readonly id: BindingIdentifier;
109
- readonly scope: BindingScope;
110
- /**
111
- * Set when the binding was registered from {@link Module} / {@link AsyncModule} setup.
112
- */
113
- readonly moduleId?: string;
114
- };
115
- /**
116
- * Binding backed by a pre-existing constant value; always singleton, no construction cost.
117
- */
118
- type ConstantBinding<Value> = BindingBase & {
119
- readonly kind: "constant";
120
- readonly value: Value;
121
- };
122
- /**
123
- * Binding that constructs `implementationClass` via the container's metadata-driven instantiation.
124
- */
125
- type ClassBinding<Value> = BindingBase & {
16
+ readonly token: Token<Value> | Constructor<Value>;
17
+ readonly slot: SlotKey;
18
+ readonly predicate?: (ctx: ConstraintContext) => boolean;
19
+ }
20
+ interface ClassBinding<Value> extends BindingBase<Value> {
126
21
  readonly kind: "class";
127
- readonly implementationClass: Constructor<Value>;
128
- };
129
- /**
130
- * Binding backed by a synchronous factory that receives a {@link ResolutionContext}.
131
- */
132
- type DynamicBinding<Value> = BindingBase & {
22
+ readonly target: Constructor<Value>;
23
+ readonly scope: BindingScope;
24
+ readonly onActivation?: ActivationHandler<Value>;
25
+ readonly onDeactivation?: DeactivationHandler<Value>;
26
+ }
27
+ interface DynamicBinding<Value> extends BindingBase<Value> {
133
28
  readonly kind: "dynamic";
134
29
  readonly factory: (ctx: ResolutionContext) => Value;
135
- };
136
- /**
137
- * Binding backed by an async factory; must be resolved via `resolveAsync` / `resolveAllAsync`.
138
- */
139
- type AsyncDynamicBinding<Value> = BindingBase & {
140
- readonly kind: "async-dynamic";
30
+ readonly scope: BindingScope;
31
+ readonly onActivation?: ActivationHandler<Value>;
32
+ readonly onDeactivation?: DeactivationHandler<Value>;
33
+ }
34
+ interface DynamicAsyncBinding<Value> extends BindingBase<Value> {
35
+ readonly kind: "dynamic-async";
141
36
  readonly factory: (ctx: ResolutionContext) => Promise<Value>;
142
- };
143
- /**
144
- * Binding whose dependencies are declared statically and pre-resolved before the factory is called.
145
- */
146
- type ResolvedBinding<Value> = BindingBase & {
37
+ readonly scope: BindingScope;
38
+ readonly onActivation?: ActivationHandler<Value>;
39
+ readonly onDeactivation?: DeactivationHandler<Value>;
40
+ }
41
+ interface ResolvedBinding<Value> extends BindingBase<Value> {
147
42
  readonly kind: "resolved";
148
- readonly dependencyTokens: readonly (Token<unknown> | Constructor<unknown>)[];
149
43
  readonly factory: (...args: unknown[]) => Value;
150
- };
151
- /**
152
- * Binding that forwards resolution to `targetToken`; the container resolves whatever is bound there.
153
- */
154
- type AliasBinding<Value> = BindingBase & {
44
+ readonly deps: readonly InjectionDescriptor[];
45
+ readonly scope: BindingScope;
46
+ readonly onActivation?: ActivationHandler<Value>;
47
+ readonly onDeactivation?: DeactivationHandler<Value>;
48
+ }
49
+ interface ResolvedAsyncBinding<Value> extends BindingBase<Value> {
50
+ readonly kind: "resolved-async";
51
+ readonly factory: (...args: unknown[]) => Promise<Value>;
52
+ readonly deps: readonly InjectionDescriptor[];
53
+ readonly scope: BindingScope;
54
+ readonly onActivation?: ActivationHandler<Value>;
55
+ readonly onDeactivation?: DeactivationHandler<Value>;
56
+ }
57
+ interface ConstantBinding<Value> extends BindingBase<Value> {
58
+ readonly kind: "constant";
59
+ readonly value: Value;
60
+ readonly scope: "singleton";
61
+ readonly onActivation?: ActivationHandler<Value>;
62
+ readonly onDeactivation?: DeactivationHandler<Value>;
63
+ }
64
+ interface AliasBinding<Value> extends BindingBase<Value> {
155
65
  readonly kind: "alias";
156
- readonly targetToken: Token<Value>;
157
- };
158
- /**
159
- * Discriminated union of all binding strategies the container can resolve.
160
- */
161
- type Binding<Value> = ConstantBinding<Value> | ClassBinding<Value> | DynamicBinding<Value> | AsyncDynamicBinding<Value> | ResolvedBinding<Value> | AliasBinding<Value>;
162
- /**
163
- * Callbacks injected by the owning container to sync each builder mutation into the registry.
164
- * `register` fires once when a `to*(…)` strategy is selected; `update` fires on every
165
- * subsequent chain call (`.singleton()`, `.onActivation()`, …).
166
- */
167
- type RegistryCallbacks<Value> = {
168
- readonly register?: (binding: Binding<Value>) => void;
169
- readonly update?: (binding: Binding<Value>) => void;
170
- };
171
- /**
172
- * Fluent builder for registering a single binding against a {@link Token} or {@link Constructor}.
173
- *
174
- * A builder has two phases:
175
- * 1. **Strategy selection** — exactly one `to*()` call (`to`, `toSelf`, `toConstantValue`,
176
- * `toDynamic`, `toDynamicAsync`, `toResolved`, `toAlias`) that determines how the value is produced.
177
- * 2. **Refinement chain** — optional calls to `singleton()`, `transient()`, `scoped()`,
178
- * `onActivation()`, `onDeactivation()`, `whenNamed()`, `whenTagged()`, `when()`, and `id()`.
179
- *
180
- * Calling a second `to*()` method throws {@link InternalError}.
181
- *
182
- * The builder is created by {@link Container.bind} or by `bind` on {@link ModuleBuilder}.
183
- * The container injects {@link RegistryCallbacks} so that every strategy selection and
184
- * refinement is immediately reflected in the live registry.
185
- */
186
- declare class BindingBuilder<Value> {
187
- protected readonly bindingKey: Token<Value> | Constructor<Value>;
188
- /**
189
- * Current resolution strategy; starts as `"unset"` until a `to*()` method is called.
190
- */
191
- private strategy;
192
- /**
193
- * Lifetime scope applied to the next binding snapshot; defaults to `"transient"`.
194
- */
195
- private scope;
196
- /**
197
- * True after an explicit `.singleton()` / `.transient()` / `.scoped()` call (prevents constant scope change).
198
- */
199
- private isScopeExplicit;
200
- /**
201
- * Pre-allocated binding ID set via `id(identifier)` before the first `to*()` call.
202
- */
203
- private explicitId;
204
- /**
205
- * Resolve-hint name filter set by `.whenNamed()`.
206
- */
207
- private bindingName;
208
- /**
209
- * Tag filters accumulated by successive `.whenTagged()` calls.
210
- */
211
- private readonly tags;
212
- /**
213
- * Custom constraint predicates accumulated by `.when()`; all must pass for this binding to be selected.
214
- */
215
- private readonly constraintPredicates;
216
- /**
217
- * Latest `onActivation` hook provided by `.onActivation(...)`.
218
- * Applied to emitted binding snapshots until replaced.
219
- */
220
- private onActivationHandler;
221
- /**
222
- * Latest `onDeactivation` hook provided by `.onDeactivation(...)`.
223
- * Emitted only on builder variants that expose deactivation support.
224
- */
225
- private onDeactivationHandler;
226
- /**
227
- * Set when this binding was created inside a {@link Module} / {@link AsyncModule} setup callback.
228
- */
229
- private readonly moduleId;
230
- /**
231
- * The most recently emitted {@link Binding} snapshot; `undefined` before the first `to*()` call.
232
- */
233
- private currentBinding;
234
- /**
235
- * Container-injected hooks that sync builder mutations into the live registry.
236
- */
237
- private readonly callbacks;
238
- constructor(bindingKey: Token<Value> | Constructor<Value>, moduleId?: string, callbacks?: RegistryCallbacks<Value>);
239
- /**
240
- * Binds the token to a concrete implementation class; the container constructs it on demand.
241
- */
242
- to<C extends Constructor<Value>>(implementationClass: C): TransientBindingBuilder<Value>;
243
- /**
244
- * Binds the class key to itself — only valid when the key is a constructor.
245
- */
246
- toSelf(): TransientBindingBuilder<Value>;
247
- /**
248
- * Binds the token to a pre-existing value; always resolved as singleton, no construction.
249
- */
250
- toConstantValue<const ConcreteValue extends Value>(value: ConcreteValue): ConstantBindingBuilder<Value>;
251
- /**
252
- * Binds to a synchronous factory; `ctx` provides nested resolution within the same path.
253
- */
254
- toDynamic(factory: (ctx: ResolutionContext) => Value): TransientBindingBuilder<Value>;
255
- /**
256
- * Binds to an async factory; must be resolved via `resolveAsync` / `resolveAllAsync`.
257
- */
258
- toDynamicAsync(factory: (ctx: ResolutionContext) => Promise<Value>): TransientBindingBuilder<Value>;
259
- /**
260
- * Binds to a factory whose dependencies are declared explicitly in `deps` and pre-resolved by
261
- * the container before the factory is called — no `ResolutionContext` needed inside the factory.
262
- */
263
- toResolved<Deps extends readonly (Token<unknown> | Constructor<unknown>)[]>(factory: (...args: { [Index in keyof Deps]: TokenValue<Deps[Index]> }) => Value, deps: Deps): TransientBindingBuilder<Value>;
264
- /**
265
- * Redirects resolution to `targetToken`; the container resolves whatever is bound there.
266
- */
267
- toAlias(targetToken: Token<Value>): TransientBindingBuilder<Value>;
268
- /**
269
- * One instance per container; supports `onDeactivation`.
270
- */
66
+ readonly target: Token<Value> | Constructor<Value>;
67
+ }
68
+ type Binding<Value = unknown> = ClassBinding<Value> | DynamicBinding<Value> | DynamicAsyncBinding<Value> | ResolvedBinding<Value> | ResolvedAsyncBinding<Value> | ConstantBinding<Value> | AliasBinding<Value>;
69
+ /** Builder-only payload before `id`, `token`, `slot`, and `predicate` are applied. */
70
+ type PartialBinding<Value> = Omit<ClassBinding<Value>, "id" | "token" | "slot" | "predicate"> | Omit<DynamicBinding<Value>, "id" | "token" | "slot" | "predicate"> | Omit<DynamicAsyncBinding<Value>, "id" | "token" | "slot" | "predicate"> | Omit<ResolvedBinding<Value>, "id" | "token" | "slot" | "predicate"> | Omit<ResolvedAsyncBinding<Value>, "id" | "token" | "slot" | "predicate"> | Omit<ConstantBinding<Value>, "id" | "token" | "slot" | "predicate"> | Omit<AliasBinding<Value>, "id" | "token" | "slot" | "predicate">;
71
+ declare function generateBindingId(): BindingIdentifier;
72
+ interface BindToBuilder<Value> {
73
+ to(type: Constructor<Value>): BindingBuilder<Value>;
74
+ toSelf(): BindingBuilder<Value>;
75
+ toConstantValue(value: Value): ConstantBindingBuilder<Value>;
76
+ toDynamic(factory: (ctx: ResolutionContext) => Value): BindingBuilder<Value>;
77
+ toDynamicAsync(factory: (ctx: ResolutionContext) => Promise<Value>): BindingBuilder<Value>;
78
+ toResolved<const Deps extends readonly DependencyKey[]>(factory: (...args: { [K in keyof Deps]: TokenValue<NoInfer<Deps>[K]> }) => Value, deps: Deps): BindingBuilder<Value>;
79
+ toResolvedAsync<const Deps extends readonly DependencyKey[]>(factory: (...args: { [K in keyof Deps]: TokenValue<NoInfer<Deps>[K]> }) => Promise<Value>, deps: Deps): BindingBuilder<Value>;
80
+ toAlias(target: Token<Value> | Constructor<Value>): AliasBindingBuilder;
81
+ }
82
+ interface BindingBuilder<Value> {
83
+ when(predicate: (ctx: ConstraintContext) => boolean): this;
84
+ whenNamed(name: string): this;
85
+ whenTagged(tag: string, value: unknown): this;
86
+ whenDefault(): this;
271
87
  singleton(): SingletonBindingBuilder<Value>;
272
- /**
273
- * New instance on every resolution (default scope).
274
- */
275
88
  transient(): TransientBindingBuilder<Value>;
276
- /**
277
- * One instance per child container scope.
278
- */
279
89
  scoped(): ScopedBindingBuilder<Value>;
280
- /**
281
- * Called with the resolved instance after construction; the return value replaces the instance.
282
- */
283
- onActivation(handler: ActivationHandler<Value>): this;
284
- /**
285
- * @internal Keep public for runtime correctness; hidden from transient/scoped builders via type aliases.
286
- */
287
- onDeactivation(handler: DeactivationHandler<Value>): this;
288
- /**
289
- * This binding only resolves when the caller passes `{ name }` as the resolve hint.
290
- */
90
+ id(): BindingIdentifier;
91
+ }
92
+ interface ConstantBindingBuilder<Value> {
93
+ when(predicate: (ctx: ConstraintContext) => boolean): this;
94
+ whenNamed(name: string): this;
95
+ whenTagged(tag: string, value: unknown): this;
96
+ whenDefault(): this;
97
+ onActivation(fn: ActivationHandler<Value>): SingletonLifecycleBuilder<Value>;
98
+ onDeactivation(fn: DeactivationHandler<Value>): SingletonLifecycleBuilder<Value>;
99
+ id(): BindingIdentifier;
100
+ }
101
+ interface AliasBindingBuilder {
102
+ when(predicate: (ctx: ConstraintContext) => boolean): this;
291
103
  whenNamed(name: string): this;
292
- /**
293
- * This binding only resolves when the caller passes `{ tag: [tag, tagValue] }` as the resolve hint.
294
- */
295
- whenTagged(tag: string, tagValue: unknown): this;
296
- /**
297
- * Adds a custom predicate; all predicates must pass for the binding to be selected.
298
- */
299
- when(constraint: (ctx: ConstraintContext) => boolean): this;
300
- /**
301
- * Returns the binding's stable ID, allocating one if needed.
302
- * Passing an `identifier` pre-sets the ID before a `to*()` call — useful when modules need to
303
- * reference a binding ID before it is registered.
304
- */
104
+ whenTagged(tag: string, value: unknown): this;
105
+ whenDefault(): this;
106
+ id(): BindingIdentifier;
107
+ }
108
+ interface SingletonBindingBuilder<Value> {
109
+ onActivation(fn: ActivationHandler<Value>): this;
110
+ onDeactivation(fn: DeactivationHandler<Value>): this;
111
+ id(): BindingIdentifier;
112
+ }
113
+ interface TransientBindingBuilder<Value> {
114
+ onActivation(fn: ActivationHandler<Value>): this;
115
+ id(): BindingIdentifier;
116
+ }
117
+ interface ScopedBindingBuilder<Value> extends TransientBindingBuilder<Value> {}
118
+ interface SingletonLifecycleBuilder<Value> {
119
+ onActivation(fn: ActivationHandler<Value>): this;
120
+ onDeactivation(fn: DeactivationHandler<Value>): this;
305
121
  id(): BindingIdentifier;
306
- id(identifier: BindingIdentifier): BindingIdentifier;
307
- /**
308
- * Records the chosen strategy and emits the first {@link Binding} snapshot.
309
- * Throws {@link InternalError} if a strategy was already selected (double `to*()` call).
310
- */
311
- private registerWithStrategy;
312
- /**
313
- * Re-creates the {@link Binding} snapshot from the current builder state and pushes
314
- * the update to the registry. No-op if no strategy has been set yet.
315
- */
316
- private refreshRegisteredBinding;
317
- /**
318
- * Guards against calling `.singleton()` / `.transient()` / `.scoped()` on a constant binding,
319
- * which is locked to `"singleton"` scope by invariant.
320
- */
321
- private assertScopeMutable;
322
- /**
323
- * Produces an immutable {@link Binding} snapshot from the current builder fields.
324
- * Called by both {@link registerWithStrategy} and {@link refreshRegisteredBinding}.
325
- */
326
- private createBinding;
327
122
  }
328
- /**
329
- * Builder returned after calling `.singleton()` — exposes `onDeactivation`.
330
- */
331
- type SingletonBindingBuilder<Value> = BindingBuilder<Value>;
332
- /**
333
- * Builder returned after calling `.transient()`, or any strategy method before a scope is set.
334
- * Does NOT expose `onDeactivation` at the type level.
335
- */
336
- type TransientBindingBuilder<Value> = Omit<BindingBuilder<Value>, "onDeactivation">;
337
- /**
338
- * Builder returned after calling `.scoped()`.
339
- * Does NOT expose `onDeactivation` at the type level.
340
- */
341
- type ScopedBindingBuilder<Value> = Omit<BindingBuilder<Value>, "onDeactivation">;
342
- /**
343
- * Builder returned after calling `.toConstantValue()`.
344
- */
345
- type ConstantBindingBuilder<Value> = Omit<SingletonBindingBuilder<Value>, "singleton" | "transient" | "scoped">;
346
- /**
347
- * Starts a fluent binding for the given token or constructor key.
348
- */
349
- declare function bind<Value>(key: Token<Value>): BindingBuilder<Value>;
350
- declare function bind<Value>(key: Constructor<Value>): BindingBuilder<Value>;
351
123
  //#endregion
352
- export { ActivationHandler, AliasBinding, AsyncDynamicBinding, Binding, BindingBuilder, BindingIdentifier, BindingScope, ClassBinding, ConstantBinding, ConstantBindingBuilder, ConstraintBindingKind, ConstraintContext, ConstraintParentFrame, Constructor, DeactivationHandler, DynamicBinding, MaterializationFrame, ResolutionContext, ResolveHint, ResolveOptions, ResolvedBinding, ScopedBindingBuilder, SingletonBindingBuilder, TransientBindingBuilder, bind, createBindingIdentifier };
124
+ export { AliasBinding, AliasBindingBuilder, BindToBuilder, Binding, BindingBuilder, ClassBinding, ConstantBinding, ConstantBindingBuilder, DEFAULT_SLOT, DynamicAsyncBinding, DynamicBinding, PartialBinding, ResolvedAsyncBinding, ResolvedBinding, ScopedBindingBuilder, SingletonBindingBuilder, SingletonLifecycleBuilder, SlotKey, TransientBindingBuilder, generateBindingId, slotKeyEquals, slotKeyToString };