@codefast/di 0.5.0-canary.6 → 0.5.0-canary.7

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 (161) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +13 -4
  3. package/dist/binding.d.ts +36 -19
  4. package/dist/binding.d.ts.map +1 -1
  5. package/dist/binding.js +2 -2
  6. package/dist/binding.js.map +1 -1
  7. package/dist/container/binding-builders.d.ts +35 -0
  8. package/dist/container/binding-builders.d.ts.map +1 -0
  9. package/dist/container/binding-builders.js +247 -0
  10. package/dist/container/binding-builders.js.map +1 -0
  11. package/dist/{container.d.ts → container/container.d.ts} +2 -2
  12. package/dist/container/container.d.ts.map +1 -0
  13. package/dist/container/container.js +641 -0
  14. package/dist/container/container.js.map +1 -0
  15. package/dist/decorators/inject.d.ts +12 -1
  16. package/dist/decorators/inject.d.ts.map +1 -1
  17. package/dist/decorators/inject.js +2 -2
  18. package/dist/decorators/inject.js.map +1 -1
  19. package/dist/decorators/injectable.js +3 -3
  20. package/dist/decorators/injectable.js.map +1 -1
  21. package/dist/index.d.ts +12 -7
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +8 -4
  24. package/dist/index.js.map +1 -1
  25. package/dist/introspection/dependency-graph.d.ts.map +1 -0
  26. package/dist/{dependency-graph.js → introspection/dependency-graph.js} +1 -1
  27. package/dist/introspection/dependency-graph.js.map +1 -0
  28. package/dist/{graph-adapters → introspection/graph-adapters}/cytoscape.d.ts +1 -1
  29. package/dist/introspection/graph-adapters/cytoscape.d.ts.map +1 -0
  30. package/dist/introspection/graph-adapters/cytoscape.js.map +1 -0
  31. package/dist/introspection/graph-adapters/dot.d.ts +6 -0
  32. package/dist/introspection/graph-adapters/dot.d.ts.map +1 -0
  33. package/dist/introspection/graph-adapters/dot.js.map +1 -0
  34. package/dist/{graph-adapters → introspection/graph-adapters}/reactflow.d.ts +2 -2
  35. package/dist/introspection/graph-adapters/reactflow.d.ts.map +1 -0
  36. package/dist/{graph-adapters → introspection/graph-adapters}/reactflow.js +11 -1
  37. package/dist/introspection/graph-adapters/reactflow.js.map +1 -0
  38. package/dist/{inspector.d.ts → introspection/inspector.d.ts} +3 -8
  39. package/dist/introspection/inspector.d.ts.map +1 -0
  40. package/dist/{inspector.js → introspection/inspector.js} +23 -23
  41. package/dist/introspection/inspector.js.map +1 -0
  42. package/dist/metadata/symbol-metadata-reader.d.ts +1 -1
  43. package/dist/metadata/symbol-metadata-reader.d.ts.map +1 -1
  44. package/dist/metadata/symbol-metadata-reader.js +4 -4
  45. package/dist/metadata/symbol-metadata-reader.js.map +1 -1
  46. package/dist/module.d.ts +9 -2
  47. package/dist/module.d.ts.map +1 -1
  48. package/dist/module.js +9 -2
  49. package/dist/module.js.map +1 -1
  50. package/dist/registry.d.ts +5 -13
  51. package/dist/registry.d.ts.map +1 -1
  52. package/dist/registry.js +102 -61
  53. package/dist/registry.js.map +1 -1
  54. package/dist/resolution/binding-scope.d.ts.map +1 -0
  55. package/dist/resolution/binding-scope.js.map +1 -0
  56. package/dist/resolution/binding-select.d.ts.map +1 -0
  57. package/dist/{binding-select.js → resolution/binding-select.js} +16 -3
  58. package/dist/resolution/binding-select.js.map +1 -0
  59. package/dist/resolution/constraints.d.ts.map +1 -0
  60. package/dist/resolution/constraints.js.map +1 -0
  61. package/dist/{environment.d.ts → resolution/environment.d.ts} +2 -6
  62. package/dist/resolution/environment.d.ts.map +1 -0
  63. package/dist/resolution/environment.js +100 -0
  64. package/dist/resolution/environment.js.map +1 -0
  65. package/dist/resolution/instantiation-plan.d.ts +67 -0
  66. package/dist/resolution/instantiation-plan.d.ts.map +1 -0
  67. package/dist/resolution/instantiation-plan.js +163 -0
  68. package/dist/resolution/instantiation-plan.js.map +1 -0
  69. package/dist/{lifecycle.d.ts → resolution/lifecycle.d.ts} +3 -3
  70. package/dist/resolution/lifecycle.d.ts.map +1 -0
  71. package/dist/{lifecycle.js → resolution/lifecycle.js} +17 -13
  72. package/dist/resolution/lifecycle.js.map +1 -0
  73. package/dist/resolution/resolution-path.d.ts +31 -0
  74. package/dist/resolution/resolution-path.d.ts.map +1 -0
  75. package/dist/resolution/resolution-path.js +53 -0
  76. package/dist/resolution/resolution-path.js.map +1 -0
  77. package/dist/resolution/resolve-options.d.ts.map +1 -0
  78. package/dist/resolution/resolve-options.js.map +1 -0
  79. package/dist/resolution/resolver.d.ts +35 -0
  80. package/dist/resolution/resolver.d.ts.map +1 -0
  81. package/dist/resolution/resolver.js +1320 -0
  82. package/dist/resolution/resolver.js.map +1 -0
  83. package/dist/{scope.d.ts → resolution/scope.d.ts} +10 -3
  84. package/dist/resolution/scope.d.ts.map +1 -0
  85. package/dist/resolution/scope.js +76 -0
  86. package/dist/resolution/scope.js.map +1 -0
  87. package/dist/token.d.ts.map +1 -1
  88. package/dist/token.js +0 -3
  89. package/dist/token.js.map +1 -1
  90. package/package.json +80 -65
  91. package/src/binding.ts +38 -22
  92. package/src/container/binding-builders.ts +397 -0
  93. package/src/container/container.ts +838 -0
  94. package/src/decorators/inject.ts +16 -3
  95. package/src/decorators/injectable.ts +3 -3
  96. package/src/index.ts +14 -7
  97. package/src/{dependency-graph.ts → introspection/dependency-graph.ts} +1 -1
  98. package/src/{graph-adapters → introspection/graph-adapters}/cytoscape.ts +1 -1
  99. package/src/{graph-adapters → introspection/graph-adapters}/dot.ts +1 -1
  100. package/src/{graph-adapters → introspection/graph-adapters}/reactflow.ts +13 -2
  101. package/src/{inspector.ts → introspection/inspector.ts} +26 -21
  102. package/src/metadata/symbol-metadata-reader.ts +4 -4
  103. package/src/module.ts +14 -6
  104. package/src/registry.ts +115 -61
  105. package/src/{binding-select.ts → resolution/binding-select.ts} +16 -3
  106. package/src/{environment.ts → resolution/environment.ts} +35 -35
  107. package/src/resolution/instantiation-plan.ts +240 -0
  108. package/src/{lifecycle.ts → resolution/lifecycle.ts} +20 -13
  109. package/src/resolution/resolution-path.ts +77 -0
  110. package/src/resolution/resolver.ts +1755 -0
  111. package/src/{scope.ts → resolution/scope.ts} +35 -18
  112. package/src/token.ts +0 -3
  113. package/dist/binding-scope.d.ts.map +0 -1
  114. package/dist/binding-scope.js.map +0 -1
  115. package/dist/binding-select.d.ts.map +0 -1
  116. package/dist/binding-select.js.map +0 -1
  117. package/dist/constraints.d.ts.map +0 -1
  118. package/dist/constraints.js.map +0 -1
  119. package/dist/container.d.ts.map +0 -1
  120. package/dist/container.js +0 -853
  121. package/dist/container.js.map +0 -1
  122. package/dist/dependency-graph.d.ts.map +0 -1
  123. package/dist/dependency-graph.js.map +0 -1
  124. package/dist/environment.d.ts.map +0 -1
  125. package/dist/environment.js +0 -100
  126. package/dist/environment.js.map +0 -1
  127. package/dist/graph-adapters/cytoscape.d.ts.map +0 -1
  128. package/dist/graph-adapters/cytoscape.js.map +0 -1
  129. package/dist/graph-adapters/dot.d.ts +0 -6
  130. package/dist/graph-adapters/dot.d.ts.map +0 -1
  131. package/dist/graph-adapters/dot.js.map +0 -1
  132. package/dist/graph-adapters/reactflow.d.ts.map +0 -1
  133. package/dist/graph-adapters/reactflow.js.map +0 -1
  134. package/dist/inspector.d.ts.map +0 -1
  135. package/dist/inspector.js.map +0 -1
  136. package/dist/lifecycle.d.ts.map +0 -1
  137. package/dist/lifecycle.js.map +0 -1
  138. package/dist/resolve-options.d.ts.map +0 -1
  139. package/dist/resolve-options.js.map +0 -1
  140. package/dist/resolver.d.ts +0 -90
  141. package/dist/resolver.d.ts.map +0 -1
  142. package/dist/resolver.js +0 -1208
  143. package/dist/resolver.js.map +0 -1
  144. package/dist/scope.d.ts.map +0 -1
  145. package/dist/scope.js +0 -61
  146. package/dist/scope.js.map +0 -1
  147. package/src/container.ts +0 -1141
  148. package/src/resolver.ts +0 -1626
  149. /package/dist/{dependency-graph.d.ts → introspection/dependency-graph.d.ts} +0 -0
  150. /package/dist/{graph-adapters → introspection/graph-adapters}/cytoscape.js +0 -0
  151. /package/dist/{graph-adapters → introspection/graph-adapters}/dot.js +0 -0
  152. /package/dist/{binding-scope.d.ts → resolution/binding-scope.d.ts} +0 -0
  153. /package/dist/{binding-scope.js → resolution/binding-scope.js} +0 -0
  154. /package/dist/{binding-select.d.ts → resolution/binding-select.d.ts} +0 -0
  155. /package/dist/{constraints.d.ts → resolution/constraints.d.ts} +0 -0
  156. /package/dist/{constraints.js → resolution/constraints.js} +0 -0
  157. /package/dist/{resolve-options.d.ts → resolution/resolve-options.d.ts} +0 -0
  158. /package/dist/{resolve-options.js → resolution/resolve-options.js} +0 -0
  159. /package/src/{binding-scope.ts → resolution/binding-scope.ts} +0 -0
  160. /package/src/{constraints.ts → resolution/constraints.ts} +0 -0
  161. /package/src/{resolve-options.ts → resolution/resolve-options.ts} +0 -0
@@ -0,0 +1,397 @@
1
+ /**
2
+ * Fluent binding-builder chain behind `container.bind()` / `container.rebind()`.
3
+ *
4
+ * Every builder commits eagerly on construction and re-commits (replacing the
5
+ * previous binding by id) whenever a later fluent call refines the binding —
6
+ * so a chain left half-finished is still a valid registration.
7
+ */
8
+ import type {
9
+ AliasBindingBuilder,
10
+ Binding,
11
+ BindingBuilder,
12
+ BindingSlot,
13
+ BindToBuilder,
14
+ ConstantBindingBuilder,
15
+ PartialBinding,
16
+ ScopedBindingBuilder,
17
+ SingletonBindingBuilder,
18
+ SingletonLifecycleBuilder,
19
+ TransientBindingBuilder,
20
+ } from "#/binding";
21
+ import { DEFAULT_BINDING_SLOT, generateBindingId } from "#/binding";
22
+ import type { InjectableDependency, ResolvedDependencyValue } from "#/decorators/inject";
23
+ import { normalizeToDescriptor } from "#/decorators/inject";
24
+ import type { Token } from "#/token";
25
+ import type {
26
+ ActivationHandler,
27
+ BindingIdentifier,
28
+ ConstraintContext,
29
+ Constructor,
30
+ DeactivationHandler,
31
+ ResolutionContext,
32
+ } from "#/types";
33
+
34
+ // ── Shared builder helpers ────────────────────────────────────────────────────
35
+
36
+ /**
37
+ * @since 0.5.0-canary.7
38
+ */
39
+ export type CommitFn = <Value>(binding: Binding<Value>, previousId?: BindingIdentifier) => BindingIdentifier;
40
+
41
+ // Builder payloads that still accept a scope — alias/constant bindings never flow through ConstraintBuilder/ScopeBuilder.
42
+ type ScopedPartialBinding<Value> = Exclude<PartialBinding<Value>, { kind: "alias" } | { kind: "constant" }>;
43
+
44
+ function updateSlotTag(slot: BindingSlot, tag: string, value: unknown): BindingSlot {
45
+ const existing = [...slot.tags];
46
+ const idx = existing.findIndex(([k]) => k === tag);
47
+ if (idx !== -1) {
48
+ existing[idx] = [tag, value];
49
+ } else {
50
+ existing.push([tag, value]);
51
+ }
52
+ return { ...slot, tags: existing };
53
+ }
54
+
55
+ // ── SlotBuilder ───────────────────────────────────────────────────────────────
56
+
57
+ abstract class SlotBuilder {
58
+ protected slot: BindingSlot = DEFAULT_BINDING_SLOT; // ✓ T3-1: no redundant spread
59
+ protected predicate: ((ctx: ConstraintContext) => boolean) | undefined;
60
+ protected committedId: BindingIdentifier | undefined;
61
+
62
+ protected abstract commit(): void;
63
+
64
+ when(predicate: (ctx: ConstraintContext) => boolean): this {
65
+ this.predicate = predicate;
66
+ this.commit();
67
+ return this;
68
+ }
69
+
70
+ whenNamed(name: string): this {
71
+ this.slot = { ...this.slot, name };
72
+ this.commit();
73
+ return this;
74
+ }
75
+
76
+ whenTagged(tag: string, value: unknown): this {
77
+ this.slot = updateSlotTag(this.slot, tag, value);
78
+ this.commit();
79
+ return this;
80
+ }
81
+
82
+ whenDefault(): this {
83
+ return this;
84
+ }
85
+
86
+ id(): BindingIdentifier {
87
+ return this.committedId!;
88
+ }
89
+ }
90
+
91
+ // ── BindingEntry ──────────────────────────────────────────────────────────────
92
+
93
+ /**
94
+ * @since 0.5.0-canary.7
95
+ */
96
+ export class BindingEntry<Value> implements BindToBuilder<Value> {
97
+ readonly #token: Token<Value> | Constructor<Value>;
98
+ readonly #commitBinding: CommitFn;
99
+
100
+ constructor(token: Token<Value> | Constructor<Value>, commitBinding: CommitFn) {
101
+ this.#token = token;
102
+ this.#commitBinding = commitBinding;
103
+ }
104
+
105
+ to(type: Constructor<Value>): BindingBuilder<Value> {
106
+ return new ConstraintBuilder<Value>(
107
+ this.#token,
108
+ { kind: "class", target: type, scope: "transient" },
109
+ this.#commitBinding,
110
+ );
111
+ }
112
+
113
+ toSelf(): BindingBuilder<Value> {
114
+ if (typeof this.#token !== "function") {
115
+ throw new Error("toSelf() requires token to be a Constructor");
116
+ }
117
+ return new ConstraintBuilder<Value>(
118
+ this.#token,
119
+ { kind: "class", target: this.#token, scope: "transient" },
120
+ this.#commitBinding,
121
+ );
122
+ }
123
+
124
+ toConstantValue(value: Value): ConstantBindingBuilder<Value> {
125
+ return new ConstantBuilder<Value>(this.#token, value, this.#commitBinding);
126
+ }
127
+
128
+ toDynamic(factory: (ctx: ResolutionContext) => Value): BindingBuilder<Value> {
129
+ return new ConstraintBuilder<Value>(
130
+ this.#token,
131
+ { kind: "dynamic", factory, scope: "transient" },
132
+ this.#commitBinding,
133
+ );
134
+ }
135
+
136
+ toDynamicAsync(factory: (ctx: ResolutionContext) => Promise<Value>): BindingBuilder<Value> {
137
+ return new ConstraintBuilder<Value>(
138
+ this.#token,
139
+ { kind: "dynamic-async", factory, scope: "transient" },
140
+ this.#commitBinding,
141
+ );
142
+ }
143
+
144
+ toResolved<const Deps extends ReadonlyArray<InjectableDependency>>(
145
+ factory: (...args: { [K in keyof Deps]: ResolvedDependencyValue<NoInfer<Deps>[K]> }) => Value,
146
+ deps: Deps,
147
+ ): BindingBuilder<Value> {
148
+ const normalizedDeps = deps.map((dependency) => normalizeToDescriptor(dependency));
149
+ return new ConstraintBuilder<Value>(
150
+ this.#token,
151
+ {
152
+ kind: "resolved",
153
+ factory: factory as (...args: Array<unknown>) => Value,
154
+ deps: normalizedDeps,
155
+ scope: "transient",
156
+ },
157
+ this.#commitBinding,
158
+ );
159
+ }
160
+
161
+ toResolvedAsync<const Deps extends ReadonlyArray<InjectableDependency>>(
162
+ factory: (...args: { [K in keyof Deps]: ResolvedDependencyValue<NoInfer<Deps>[K]> }) => Promise<Value>,
163
+ deps: Deps,
164
+ ): BindingBuilder<Value> {
165
+ const normalizedDeps = deps.map((dependency) => normalizeToDescriptor(dependency));
166
+ return new ConstraintBuilder<Value>(
167
+ this.#token,
168
+ {
169
+ kind: "resolved-async",
170
+ factory: factory as (...args: Array<unknown>) => Promise<Value>,
171
+ deps: normalizedDeps,
172
+ scope: "transient",
173
+ },
174
+ this.#commitBinding,
175
+ );
176
+ }
177
+
178
+ toAlias(target: Token<Value> | Constructor<Value>): AliasBindingBuilder {
179
+ return new AliasBuilder<Value>(this.#token, target, this.#commitBinding);
180
+ }
181
+ }
182
+
183
+ // ── ConstraintBuilder ─────────────────────────────────────────────────────────
184
+
185
+ class ConstraintBuilder<Value> extends SlotBuilder implements BindingBuilder<Value> {
186
+ readonly #token: Token<Value> | Constructor<Value>;
187
+ readonly #partial: ScopedPartialBinding<Value>;
188
+ readonly #commitBinding: CommitFn;
189
+
190
+ constructor(token: Token<Value> | Constructor<Value>, partial: ScopedPartialBinding<Value>, commitBinding: CommitFn) {
191
+ super();
192
+ this.#token = token;
193
+ this.#partial = partial;
194
+ this.#commitBinding = commitBinding;
195
+ this.commit();
196
+ }
197
+
198
+ protected commit(): void {
199
+ const previousId = this.committedId;
200
+ const binding: Binding<Value> = {
201
+ ...this.#partial,
202
+ id: generateBindingId(),
203
+ inFlight: false,
204
+ token: this.#token,
205
+ slot: this.slot,
206
+ predicate: this.predicate,
207
+ };
208
+ this.committedId = this.#commitBinding(binding, previousId);
209
+ }
210
+
211
+ singleton(): SingletonBindingBuilder<Value> {
212
+ const previousId = this.committedId;
213
+ this.committedId = undefined;
214
+ return new ScopeBuilder<Value>(
215
+ this.#token,
216
+ { ...this.#partial, scope: "singleton" },
217
+ this.slot,
218
+ this.predicate,
219
+ this.#commitBinding,
220
+ previousId,
221
+ );
222
+ }
223
+
224
+ transient(): TransientBindingBuilder<Value> {
225
+ const previousId = this.committedId;
226
+ this.committedId = undefined;
227
+ return new ScopeBuilder<Value>(
228
+ this.#token,
229
+ { ...this.#partial, scope: "transient" },
230
+ this.slot,
231
+ this.predicate,
232
+ this.#commitBinding,
233
+ previousId,
234
+ );
235
+ }
236
+
237
+ scoped(): ScopedBindingBuilder<Value> {
238
+ const previousId = this.committedId;
239
+ this.committedId = undefined;
240
+ return new ScopeBuilder<Value>(
241
+ this.#token,
242
+ { ...this.#partial, scope: "scoped" },
243
+ this.slot,
244
+ this.predicate,
245
+ this.#commitBinding,
246
+ previousId,
247
+ );
248
+ }
249
+ }
250
+
251
+ // ── ScopeBuilder ─────────────────────────────────────────────────────────────
252
+
253
+ class ScopeBuilder<Value> implements SingletonBindingBuilder<Value>, TransientBindingBuilder<Value> {
254
+ #onActivation: ActivationHandler<Value> | undefined;
255
+ #onDeactivation: DeactivationHandler<Value> | undefined;
256
+ #committedId: BindingIdentifier | undefined;
257
+
258
+ readonly #token: Token<Value> | Constructor<Value>;
259
+ readonly #partial: ScopedPartialBinding<Value>;
260
+ readonly #slot: BindingSlot;
261
+ readonly #predicate: ((ctx: ConstraintContext) => boolean) | undefined;
262
+ readonly #commitBinding: CommitFn;
263
+ readonly #initialPreviousId: BindingIdentifier | undefined;
264
+
265
+ constructor(
266
+ token: Token<Value> | Constructor<Value>,
267
+ partial: ScopedPartialBinding<Value>,
268
+ slot: BindingSlot,
269
+ predicate: ((ctx: ConstraintContext) => boolean) | undefined,
270
+ commitBinding: CommitFn,
271
+ initialPreviousId?: BindingIdentifier,
272
+ ) {
273
+ this.#token = token;
274
+ this.#partial = partial;
275
+ this.#slot = slot;
276
+ this.#predicate = predicate;
277
+ this.#commitBinding = commitBinding;
278
+ this.#initialPreviousId = initialPreviousId;
279
+ this.#commit();
280
+ }
281
+
282
+ #commit(): void {
283
+ const previousId = this.#committedId ?? this.#initialPreviousId;
284
+ const binding: Binding<Value> = {
285
+ ...this.#partial,
286
+ id: generateBindingId(),
287
+ inFlight: false,
288
+ token: this.#token,
289
+ slot: this.#slot,
290
+ predicate: this.#predicate,
291
+ onActivation: this.#onActivation,
292
+ onDeactivation: this.#onDeactivation,
293
+ };
294
+ this.#committedId = this.#commitBinding(binding, previousId);
295
+ }
296
+
297
+ onActivation(fn: ActivationHandler<Value>): this {
298
+ this.#onActivation = fn;
299
+ this.#commit();
300
+ return this;
301
+ }
302
+
303
+ onDeactivation(fn: DeactivationHandler<Value>): this {
304
+ this.#onDeactivation = fn;
305
+ this.#commit();
306
+ return this;
307
+ }
308
+
309
+ id(): BindingIdentifier {
310
+ return this.#committedId!;
311
+ }
312
+ }
313
+
314
+ // ── ConstantBuilder ───────────────────────────────────────────────────────────
315
+
316
+ class ConstantBuilder<Value>
317
+ extends SlotBuilder
318
+ implements ConstantBindingBuilder<Value>, SingletonLifecycleBuilder<Value>
319
+ {
320
+ #onActivation: ActivationHandler<Value> | undefined;
321
+ #onDeactivation: DeactivationHandler<Value> | undefined;
322
+
323
+ readonly #token: Token<Value> | Constructor<Value>;
324
+ readonly #value: Value;
325
+ readonly #commitBinding: CommitFn;
326
+
327
+ constructor(token: Token<Value> | Constructor<Value>, value: Value, commitBinding: CommitFn) {
328
+ super();
329
+ this.#token = token;
330
+ this.#value = value;
331
+ this.#commitBinding = commitBinding;
332
+ this.commit();
333
+ }
334
+
335
+ protected commit(): void {
336
+ const previousId = this.committedId;
337
+ const binding: Binding<Value> = {
338
+ kind: "constant",
339
+ id: generateBindingId(),
340
+ inFlight: false,
341
+ token: this.#token,
342
+ slot: this.slot,
343
+ predicate: this.predicate,
344
+ value: this.#value,
345
+ scope: "singleton",
346
+ onActivation: this.#onActivation,
347
+ onDeactivation: this.#onDeactivation,
348
+ };
349
+ this.committedId = this.#commitBinding(binding, previousId);
350
+ }
351
+
352
+ onActivation(fn: ActivationHandler<Value>): this {
353
+ this.#onActivation = fn;
354
+ this.commit();
355
+ return this;
356
+ }
357
+
358
+ onDeactivation(fn: DeactivationHandler<Value>): this {
359
+ this.#onDeactivation = fn;
360
+ this.commit();
361
+ return this;
362
+ }
363
+ }
364
+
365
+ // ── AliasBuilder ──────────────────────────────────────────────────────────────
366
+
367
+ class AliasBuilder<Value> extends SlotBuilder implements AliasBindingBuilder {
368
+ readonly #token: Token<Value> | Constructor<Value>;
369
+ readonly #target: Token<Value> | Constructor<Value>;
370
+ readonly #commitBinding: CommitFn;
371
+
372
+ constructor(
373
+ token: Token<Value> | Constructor<Value>,
374
+ target: Token<Value> | Constructor<Value>,
375
+ commitBinding: CommitFn,
376
+ ) {
377
+ super();
378
+ this.#token = token;
379
+ this.#target = target;
380
+ this.#commitBinding = commitBinding;
381
+ this.commit();
382
+ }
383
+
384
+ protected commit(): void {
385
+ const previousId = this.committedId;
386
+ const binding: Binding<Value> = {
387
+ kind: "alias",
388
+ id: generateBindingId(),
389
+ inFlight: false,
390
+ token: this.#token,
391
+ slot: this.slot,
392
+ predicate: this.predicate,
393
+ target: this.#target,
394
+ };
395
+ this.committedId = this.#commitBinding(binding, previousId);
396
+ }
397
+ }