@codefast/di 0.3.16-canary.3 → 0.4.0-canary.5
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 +10 -0
- package/README.md +5 -17
- package/dist/container.d.mts +3 -3
- package/dist/container.mjs +7 -7
- package/dist/decorators/inject.mjs +2 -2
- package/dist/decorators/lifecycle-decorators.mjs +2 -2
- package/dist/dependency-graph.d.mts +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +1 -1
- package/dist/module.mjs +1 -1
- package/dist/resolver.d.mts +1 -1
- package/package.json +8 -8
- package/src/binding-select.ts +4 -13
- package/src/binding.ts +3 -7
- package/src/constraints.ts +16 -44
- package/src/container.ts +63 -141
- package/src/decorators/inject.ts +11 -22
- package/src/decorators/injectable.ts +2 -2
- package/src/decorators/lifecycle-decorators.ts +4 -8
- package/src/dependency-graph.ts +3 -3
- package/src/environment.ts +9 -34
- package/src/errors.ts +1 -3
- package/src/inspector.ts +9 -17
- package/src/lifecycle.ts +9 -30
- package/src/metadata/metadata-reader-token.ts +1 -1
- package/src/metadata/metadata-types.ts +3 -5
- package/src/metadata/symbol-metadata-reader.ts +4 -16
- package/src/module.ts +2 -2
- package/src/registry.ts +5 -14
- package/src/resolver.ts +76 -304
- package/src/scope.ts +1 -1
- package/src/types.ts +7 -29
package/src/container.ts
CHANGED
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ActivationHandler,
|
|
3
|
-
BindingIdentifier,
|
|
4
|
-
BindingScope,
|
|
5
|
-
ConstraintContext,
|
|
6
|
-
Constructor,
|
|
7
|
-
DeactivationHandler,
|
|
8
|
-
DependencyKey,
|
|
9
|
-
ResolutionContext,
|
|
10
|
-
ResolveOptions,
|
|
11
|
-
TokenValue,
|
|
12
|
-
} from "#/types";
|
|
13
1
|
import type {
|
|
14
2
|
AliasBindingBuilder,
|
|
15
3
|
Binding,
|
|
@@ -23,13 +11,12 @@ import type {
|
|
|
23
11
|
BindingSlot,
|
|
24
12
|
TransientBindingBuilder,
|
|
25
13
|
} from "#/binding";
|
|
26
|
-
import
|
|
27
|
-
import
|
|
28
|
-
import
|
|
29
|
-
import type { ContainerGraphJson, GraphOptions } from "#/dependency-graph";
|
|
30
|
-
import type { MetadataReader } from "#/metadata/metadata-types";
|
|
14
|
+
import { DEFAULT_BINDING_SLOT, generateBindingId } from "#/binding";
|
|
15
|
+
import { effectiveBindingScope } from "#/binding-scope";
|
|
16
|
+
import { normalizeToDescriptor } from "#/decorators/inject";
|
|
31
17
|
import type { AutoRegisterRegistry } from "#/decorators/injectable";
|
|
32
|
-
import type {
|
|
18
|
+
import type { ContainerGraphJson, GraphOptions } from "#/dependency-graph";
|
|
19
|
+
import { buildDependencyGraph } from "#/dependency-graph";
|
|
33
20
|
import {
|
|
34
21
|
AsyncModuleLoadError,
|
|
35
22
|
CircularDependencyError,
|
|
@@ -39,20 +26,33 @@ import {
|
|
|
39
26
|
ScopeViolationError,
|
|
40
27
|
SyncDisposalNotSupportedError,
|
|
41
28
|
} from "#/errors";
|
|
42
|
-
import {
|
|
43
|
-
import { BindingRegistry } from "#/registry";
|
|
44
|
-
import { ScopeManager } from "#/scope";
|
|
45
|
-
import { LifecycleManager } from "#/lifecycle";
|
|
46
|
-
import { DependencyResolver } from "#/resolver";
|
|
29
|
+
import type { BindingSnapshot, ContainerSnapshot } from "#/inspector";
|
|
47
30
|
import { Inspector } from "#/inspector";
|
|
48
|
-
import {
|
|
49
|
-
import { defaultMetadataReader } from "#/metadata/symbol-metadata-reader";
|
|
31
|
+
import { LifecycleManager } from "#/lifecycle";
|
|
50
32
|
import { MetadataReaderToken } from "#/metadata/metadata-reader-token";
|
|
51
|
-
import {
|
|
52
|
-
import {
|
|
33
|
+
import type { MetadataReader } from "#/metadata/metadata-types";
|
|
34
|
+
import { defaultMetadataReader } from "#/metadata/symbol-metadata-reader";
|
|
35
|
+
import type { AsyncModule, ModuleBuilder, SyncModule } from "#/module";
|
|
36
|
+
import type { AsyncModuleBuilder } from "#/module";
|
|
53
37
|
import { isSyncModule } from "#/module";
|
|
54
|
-
import {
|
|
38
|
+
import { BindingRegistry } from "#/registry";
|
|
55
39
|
import { injectionSlotToResolveOptions, bindingSlotToResolveOptions } from "#/resolve-options";
|
|
40
|
+
import { DependencyResolver } from "#/resolver";
|
|
41
|
+
import { ScopeManager } from "#/scope";
|
|
42
|
+
import type { Token } from "#/token";
|
|
43
|
+
import { tokenName } from "#/token";
|
|
44
|
+
import type {
|
|
45
|
+
ActivationHandler,
|
|
46
|
+
BindingIdentifier,
|
|
47
|
+
BindingScope,
|
|
48
|
+
ConstraintContext,
|
|
49
|
+
Constructor,
|
|
50
|
+
DeactivationHandler,
|
|
51
|
+
DependencyKey,
|
|
52
|
+
ResolutionContext,
|
|
53
|
+
ResolveOptions,
|
|
54
|
+
TokenValue,
|
|
55
|
+
} from "#/types";
|
|
56
56
|
|
|
57
57
|
// ── Container interface ────────────────────────────────────────────────────────
|
|
58
58
|
|
|
@@ -75,36 +75,18 @@ export interface Container {
|
|
|
75
75
|
unloadAsync(...modules: Array<SyncModule | AsyncModule>): Promise<void>;
|
|
76
76
|
loadAutoRegistered(registry: AutoRegisterRegistry): number;
|
|
77
77
|
|
|
78
|
-
onActivation<const Value>(
|
|
79
|
-
|
|
80
|
-
handler: ActivationHandler<Value>,
|
|
81
|
-
): void;
|
|
82
|
-
onDeactivation<const Value>(
|
|
83
|
-
token: Token<Value> | Constructor<Value>,
|
|
84
|
-
handler: DeactivationHandler<Value>,
|
|
85
|
-
): void;
|
|
78
|
+
onActivation<const Value>(token: Token<Value> | Constructor<Value>, handler: ActivationHandler<Value>): void;
|
|
79
|
+
onDeactivation<const Value>(token: Token<Value> | Constructor<Value>, handler: DeactivationHandler<Value>): void;
|
|
86
80
|
|
|
87
81
|
resolve<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Value;
|
|
88
|
-
resolveAsync<const Value>(
|
|
89
|
-
|
|
90
|
-
hint?: ResolveOptions,
|
|
91
|
-
): Promise<Value>;
|
|
92
|
-
resolveOptional<const Value>(
|
|
93
|
-
token: Token<Value> | Constructor<Value>,
|
|
94
|
-
hint?: ResolveOptions,
|
|
95
|
-
): Value | undefined;
|
|
82
|
+
resolveAsync<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Promise<Value>;
|
|
83
|
+
resolveOptional<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Value | undefined;
|
|
96
84
|
resolveOptionalAsync<const Value>(
|
|
97
85
|
token: Token<Value> | Constructor<Value>,
|
|
98
86
|
hint?: ResolveOptions,
|
|
99
87
|
): Promise<Value | undefined>;
|
|
100
|
-
resolveAll<const Value>(
|
|
101
|
-
|
|
102
|
-
hint?: ResolveOptions,
|
|
103
|
-
): Array<Value>;
|
|
104
|
-
resolveAllAsync<const Value>(
|
|
105
|
-
token: Token<Value> | Constructor<Value>,
|
|
106
|
-
hint?: ResolveOptions,
|
|
107
|
-
): Promise<Array<Value>>;
|
|
88
|
+
resolveAll<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Array<Value>;
|
|
89
|
+
resolveAllAsync<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Promise<Array<Value>>;
|
|
108
90
|
|
|
109
91
|
createChild(): Container;
|
|
110
92
|
|
|
@@ -117,9 +99,7 @@ export interface Container {
|
|
|
117
99
|
|
|
118
100
|
has(token: Token<unknown> | Constructor, hint?: ResolveOptions): boolean;
|
|
119
101
|
hasOwn(token: Token<unknown> | Constructor, hint?: ResolveOptions): boolean;
|
|
120
|
-
lookupBindings<const Value>(
|
|
121
|
-
token: Token<Value> | Constructor<Value>,
|
|
122
|
-
): ReadonlyArray<BindingSnapshot>;
|
|
102
|
+
lookupBindings<const Value>(token: Token<Value> | Constructor<Value>): ReadonlyArray<BindingSnapshot>;
|
|
123
103
|
inspect(): ContainerSnapshot;
|
|
124
104
|
generateDependencyGraph(options?: GraphOptions): ContainerGraphJson;
|
|
125
105
|
}
|
|
@@ -154,12 +134,7 @@ class DefaultContainer implements Container {
|
|
|
154
134
|
this._registry = new BindingRegistry();
|
|
155
135
|
this._scope = new ScopeManager(parent !== undefined);
|
|
156
136
|
this._lifecycle = new LifecycleManager();
|
|
157
|
-
this._inspector = new Inspector(
|
|
158
|
-
this._registry,
|
|
159
|
-
this._scope,
|
|
160
|
-
parent !== undefined,
|
|
161
|
-
() => this._disposed,
|
|
162
|
-
);
|
|
137
|
+
this._inspector = new Inspector(this._registry, this._scope, parent !== undefined, () => this._disposed);
|
|
163
138
|
this._initResolver();
|
|
164
139
|
}
|
|
165
140
|
|
|
@@ -310,15 +285,13 @@ class DefaultContainer implements Container {
|
|
|
310
285
|
return this._createBindToBuilder(token);
|
|
311
286
|
}
|
|
312
287
|
|
|
313
|
-
private _getBindingsForTokenOrId(
|
|
314
|
-
tokenOrId: Token<unknown> | Constructor | BindingIdentifier,
|
|
315
|
-
): Array<Binding> {
|
|
288
|
+
private _getBindingsForTokenOrId(tokenOrId: Token<unknown> | Constructor | BindingIdentifier): Array<Binding> {
|
|
316
289
|
if (typeof tokenOrId === "string") {
|
|
317
290
|
// It's a BindingIdentifier (string)
|
|
318
|
-
const binding = this._registry.getById(tokenOrId
|
|
291
|
+
const binding = this._registry.getById(tokenOrId);
|
|
319
292
|
return binding !== undefined ? [binding] : [];
|
|
320
293
|
}
|
|
321
|
-
return [...this._registry.getAll(tokenOrId
|
|
294
|
+
return [...this._registry.getAll(tokenOrId)];
|
|
322
295
|
}
|
|
323
296
|
|
|
324
297
|
// ── Module ────────────────────────────────────────────────────────────────
|
|
@@ -347,9 +320,7 @@ class DefaultContainer implements Container {
|
|
|
347
320
|
}
|
|
348
321
|
}
|
|
349
322
|
|
|
350
|
-
private _collectModuleDeps(
|
|
351
|
-
modules: Array<SyncModule | AsyncModule>,
|
|
352
|
-
): Array<SyncModule | AsyncModule> {
|
|
323
|
+
private _collectModuleDeps(modules: Array<SyncModule | AsyncModule>): Array<SyncModule | AsyncModule> {
|
|
353
324
|
const seen = new Set<object>();
|
|
354
325
|
const result: Array<SyncModule | AsyncModule> = [];
|
|
355
326
|
|
|
@@ -391,7 +362,7 @@ class DefaultContainer implements Container {
|
|
|
391
362
|
} else {
|
|
392
363
|
const importPromises: Array<Promise<void>> = [];
|
|
393
364
|
const builder = this._createAsyncModuleBuilder(moduleRef, importPromises);
|
|
394
|
-
await
|
|
365
|
+
await module._setup(builder);
|
|
395
366
|
// Await nested async imports triggered inside _setup
|
|
396
367
|
if (importPromises.length > 0) {
|
|
397
368
|
await Promise.all(importPromises);
|
|
@@ -409,10 +380,7 @@ class DefaultContainer implements Container {
|
|
|
409
380
|
};
|
|
410
381
|
}
|
|
411
382
|
|
|
412
|
-
private _createAsyncModuleBuilder(
|
|
413
|
-
moduleRef: object,
|
|
414
|
-
importPromises: Array<Promise<void>>,
|
|
415
|
-
): AsyncModuleBuilder {
|
|
383
|
+
private _createAsyncModuleBuilder(moduleRef: object, importPromises: Array<Promise<void>>): AsyncModuleBuilder {
|
|
416
384
|
return {
|
|
417
385
|
bind: <const Value>(token: Token<Value> | Constructor<Value>): BindToBuilder<Value> =>
|
|
418
386
|
this._createBindToBuilder(token, moduleRef),
|
|
@@ -485,7 +453,7 @@ class DefaultContainer implements Container {
|
|
|
485
453
|
this._assertNotDisposed();
|
|
486
454
|
const entries = registry.entries();
|
|
487
455
|
for (const { target, scope } of entries) {
|
|
488
|
-
const builder = this._createBindToBuilder(target
|
|
456
|
+
const builder = this._createBindToBuilder(target);
|
|
489
457
|
const bindingBuilder = builder.toSelf();
|
|
490
458
|
if (scope === "singleton") {
|
|
491
459
|
bindingBuilder.singleton();
|
|
@@ -500,18 +468,12 @@ class DefaultContainer implements Container {
|
|
|
500
468
|
|
|
501
469
|
// ── Lifecycle hooks ────────────────────────────────────────────────────────
|
|
502
470
|
|
|
503
|
-
onActivation<const Value>(
|
|
504
|
-
token: Token<Value> | Constructor<Value>,
|
|
505
|
-
handler: ActivationHandler<Value>,
|
|
506
|
-
): void {
|
|
471
|
+
onActivation<const Value>(token: Token<Value> | Constructor<Value>, handler: ActivationHandler<Value>): void {
|
|
507
472
|
this._assertNotDisposed();
|
|
508
473
|
this._lifecycle.registerActivation(token, handler);
|
|
509
474
|
}
|
|
510
475
|
|
|
511
|
-
onDeactivation<const Value>(
|
|
512
|
-
token: Token<Value> | Constructor<Value>,
|
|
513
|
-
handler: DeactivationHandler<Value>,
|
|
514
|
-
): void {
|
|
476
|
+
onDeactivation<const Value>(token: Token<Value> | Constructor<Value>, handler: DeactivationHandler<Value>): void {
|
|
515
477
|
this._assertNotDisposed();
|
|
516
478
|
this._lifecycle.registerDeactivation(token, handler);
|
|
517
479
|
}
|
|
@@ -526,10 +488,7 @@ class DefaultContainer implements Container {
|
|
|
526
488
|
return this._resolver.resolve(token, hint, [], []);
|
|
527
489
|
}
|
|
528
490
|
|
|
529
|
-
resolveAsync<const Value>(
|
|
530
|
-
token: Token<Value> | Constructor<Value>,
|
|
531
|
-
hint?: ResolveOptions,
|
|
532
|
-
): Promise<Value> {
|
|
491
|
+
resolveAsync<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Promise<Value> {
|
|
533
492
|
this._assertNotDisposed();
|
|
534
493
|
if (hint === undefined) {
|
|
535
494
|
return this._resolver.resolveAsyncFromContext(token, [], []);
|
|
@@ -537,10 +496,7 @@ class DefaultContainer implements Container {
|
|
|
537
496
|
return this._resolver.resolveAsync(token, hint, [], []);
|
|
538
497
|
}
|
|
539
498
|
|
|
540
|
-
resolveOptional<const Value>(
|
|
541
|
-
token: Token<Value> | Constructor<Value>,
|
|
542
|
-
hint?: ResolveOptions,
|
|
543
|
-
): Value | undefined {
|
|
499
|
+
resolveOptional<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Value | undefined {
|
|
544
500
|
this._assertNotDisposed();
|
|
545
501
|
return this._resolver.resolveOptional(token, hint, [], []);
|
|
546
502
|
}
|
|
@@ -553,18 +509,12 @@ class DefaultContainer implements Container {
|
|
|
553
509
|
return this._resolver.resolveOptionalAsync(token, hint, [], []);
|
|
554
510
|
}
|
|
555
511
|
|
|
556
|
-
resolveAll<const Value>(
|
|
557
|
-
token: Token<Value> | Constructor<Value>,
|
|
558
|
-
hint?: ResolveOptions,
|
|
559
|
-
): Array<Value> {
|
|
512
|
+
resolveAll<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Array<Value> {
|
|
560
513
|
this._assertNotDisposed();
|
|
561
514
|
return this._resolver.resolveAll(token, hint, [], []);
|
|
562
515
|
}
|
|
563
516
|
|
|
564
|
-
resolveAllAsync<const Value>(
|
|
565
|
-
token: Token<Value> | Constructor<Value>,
|
|
566
|
-
hint?: ResolveOptions,
|
|
567
|
-
): Promise<Array<Value>> {
|
|
517
|
+
resolveAllAsync<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Promise<Array<Value>> {
|
|
568
518
|
this._assertNotDisposed();
|
|
569
519
|
return this._resolver.resolveAllAsync(token, hint, [], []);
|
|
570
520
|
}
|
|
@@ -647,9 +597,7 @@ class DefaultContainer implements Container {
|
|
|
647
597
|
if (effectiveBindingScope(binding) !== "singleton") {
|
|
648
598
|
return false;
|
|
649
599
|
}
|
|
650
|
-
return
|
|
651
|
-
binding.kind === "class" || binding.kind === "resolved" || binding.kind === "resolved-async"
|
|
652
|
-
);
|
|
600
|
+
return binding.kind === "class" || binding.kind === "resolved" || binding.kind === "resolved-async";
|
|
653
601
|
}
|
|
654
602
|
|
|
655
603
|
/**
|
|
@@ -659,11 +607,7 @@ class DefaultContainer implements Container {
|
|
|
659
607
|
private _validateSingletonBindingGraph(root: Binding, reader: MetadataReader): void {
|
|
660
608
|
const rootName = tokenName(root.token as Token<unknown>);
|
|
661
609
|
|
|
662
|
-
const dfs = (
|
|
663
|
-
current: Binding,
|
|
664
|
-
pathNames: Array<string>,
|
|
665
|
-
pathBindingIds: Set<BindingIdentifier>,
|
|
666
|
-
): void => {
|
|
610
|
+
const dfs = (current: Binding, pathNames: Array<string>, pathBindingIds: Set<BindingIdentifier>): void => {
|
|
667
611
|
if (pathBindingIds.has(current.id)) {
|
|
668
612
|
return;
|
|
669
613
|
}
|
|
@@ -685,11 +629,7 @@ class DefaultContainer implements Container {
|
|
|
685
629
|
path: [...pathNames, depTokenName],
|
|
686
630
|
});
|
|
687
631
|
}
|
|
688
|
-
if (
|
|
689
|
-
terminal.kind === "class" ||
|
|
690
|
-
terminal.kind === "resolved" ||
|
|
691
|
-
terminal.kind === "resolved-async"
|
|
692
|
-
) {
|
|
632
|
+
if (terminal.kind === "class" || terminal.kind === "resolved" || terminal.kind === "resolved-async") {
|
|
693
633
|
dfs(terminal, [...pathNames, depTokenName], extendedPathIds);
|
|
694
634
|
}
|
|
695
635
|
}
|
|
@@ -718,10 +658,7 @@ class DefaultContainer implements Container {
|
|
|
718
658
|
}
|
|
719
659
|
}
|
|
720
660
|
|
|
721
|
-
private _followAliasChainToTerminal(
|
|
722
|
-
binding: Binding,
|
|
723
|
-
hint: ResolveOptions | undefined,
|
|
724
|
-
): Binding | undefined {
|
|
661
|
+
private _followAliasChainToTerminal(binding: Binding, hint: ResolveOptions | undefined): Binding | undefined {
|
|
725
662
|
const cyclePath: Array<string> = [];
|
|
726
663
|
const seenAliasIds = new Set<BindingIdentifier>();
|
|
727
664
|
let current: Binding | undefined = binding;
|
|
@@ -765,7 +702,7 @@ class DefaultContainer implements Container {
|
|
|
765
702
|
if (param.optional) {
|
|
766
703
|
continue;
|
|
767
704
|
}
|
|
768
|
-
const tokenRef = param.token
|
|
705
|
+
const tokenRef = param.token;
|
|
769
706
|
if (param.multi) {
|
|
770
707
|
const candidates = this._resolver.peekCandidateBindingsForValidate(tokenRef, paramHint);
|
|
771
708
|
for (const cand of candidates) {
|
|
@@ -829,9 +766,7 @@ class DefaultContainer implements Container {
|
|
|
829
766
|
return this._inspector.hasOwn(token, hint);
|
|
830
767
|
}
|
|
831
768
|
|
|
832
|
-
lookupBindings<const Value>(
|
|
833
|
-
token: Token<Value> | Constructor<Value>,
|
|
834
|
-
): ReadonlyArray<BindingSnapshot> {
|
|
769
|
+
lookupBindings<const Value>(token: Token<Value> | Constructor<Value>): ReadonlyArray<BindingSnapshot> {
|
|
835
770
|
this._assertNotDisposed();
|
|
836
771
|
return this._inspector.lookupBindings(token);
|
|
837
772
|
}
|
|
@@ -843,12 +778,7 @@ class DefaultContainer implements Container {
|
|
|
843
778
|
|
|
844
779
|
generateDependencyGraph(options?: GraphOptions): ContainerGraphJson {
|
|
845
780
|
this._assertNotDisposed();
|
|
846
|
-
return buildDependencyGraph(
|
|
847
|
-
this._registry,
|
|
848
|
-
this._getMetadataReader(),
|
|
849
|
-
options,
|
|
850
|
-
this._parent?._registry,
|
|
851
|
-
);
|
|
781
|
+
return buildDependencyGraph(this._registry, this._getMetadataReader(), options, this._parent?._registry);
|
|
852
782
|
}
|
|
853
783
|
|
|
854
784
|
// ── Internal ──────────────────────────────────────────────────────────────
|
|
@@ -920,11 +850,7 @@ class BindingEntry<Value> implements BindToBuilder<Value> {
|
|
|
920
850
|
) {}
|
|
921
851
|
|
|
922
852
|
to(type: Constructor<Value>): BindingBuilder<Value> {
|
|
923
|
-
return new ConstraintBuilder<Value>(
|
|
924
|
-
this._token,
|
|
925
|
-
{ kind: "class", target: type, scope: "transient" },
|
|
926
|
-
this._commit,
|
|
927
|
-
);
|
|
853
|
+
return new ConstraintBuilder<Value>(this._token, { kind: "class", target: type, scope: "transient" }, this._commit);
|
|
928
854
|
}
|
|
929
855
|
|
|
930
856
|
toSelf(): BindingBuilder<Value> {
|
|
@@ -933,7 +859,7 @@ class BindingEntry<Value> implements BindToBuilder<Value> {
|
|
|
933
859
|
}
|
|
934
860
|
return new ConstraintBuilder<Value>(
|
|
935
861
|
this._token,
|
|
936
|
-
{ kind: "class", target: this._token
|
|
862
|
+
{ kind: "class", target: this._token, scope: "transient" },
|
|
937
863
|
this._commit,
|
|
938
864
|
);
|
|
939
865
|
}
|
|
@@ -943,11 +869,7 @@ class BindingEntry<Value> implements BindToBuilder<Value> {
|
|
|
943
869
|
}
|
|
944
870
|
|
|
945
871
|
toDynamic(factory: (ctx: ResolutionContext) => Value): BindingBuilder<Value> {
|
|
946
|
-
return new ConstraintBuilder<Value>(
|
|
947
|
-
this._token,
|
|
948
|
-
{ kind: "dynamic", factory, scope: "transient" },
|
|
949
|
-
this._commit,
|
|
950
|
-
);
|
|
872
|
+
return new ConstraintBuilder<Value>(this._token, { kind: "dynamic", factory, scope: "transient" }, this._commit);
|
|
951
873
|
}
|
|
952
874
|
|
|
953
875
|
toDynamicAsync(factory: (ctx: ResolutionContext) => Promise<Value>): BindingBuilder<Value> {
|
|
@@ -1018,7 +940,7 @@ class ConstraintBuilder<Value> extends SlotBuilder implements BindingBuilder<Val
|
|
|
1018
940
|
slot: this._slot,
|
|
1019
941
|
predicate: this._predicate,
|
|
1020
942
|
} as Binding<Value>;
|
|
1021
|
-
this._committed = this._commit(binding as Binding
|
|
943
|
+
this._committed = this._commit(binding as Binding, previousId);
|
|
1022
944
|
}
|
|
1023
945
|
|
|
1024
946
|
singleton(): SingletonBindingBuilder<Value> {
|
|
@@ -1096,7 +1018,7 @@ class ScopeBuilder<Value, Scope extends BindingScope>
|
|
|
1096
1018
|
onActivation: this._onActivation,
|
|
1097
1019
|
onDeactivation: this._onDeactivation,
|
|
1098
1020
|
} as Binding<Value>;
|
|
1099
|
-
this._committed = this._commit(binding as Binding
|
|
1021
|
+
this._committed = this._commit(binding as Binding, previousId);
|
|
1100
1022
|
}
|
|
1101
1023
|
|
|
1102
1024
|
onActivation(fn: ActivationHandler<Value>): this {
|
|
@@ -1147,7 +1069,7 @@ class ConstantBuilder<Value>
|
|
|
1147
1069
|
onActivation: this._onActivation,
|
|
1148
1070
|
onDeactivation: this._onDeactivation,
|
|
1149
1071
|
} as unknown as Binding<Value>;
|
|
1150
|
-
this._committed = this._commit(binding as Binding
|
|
1072
|
+
this._committed = this._commit(binding as Binding, previousId);
|
|
1151
1073
|
}
|
|
1152
1074
|
|
|
1153
1075
|
onActivation(fn: ActivationHandler<Value>): this {
|
|
@@ -1185,7 +1107,7 @@ class AliasBuilder<Value> extends SlotBuilder implements AliasBindingBuilder {
|
|
|
1185
1107
|
predicate: this._predicate,
|
|
1186
1108
|
target: this._target,
|
|
1187
1109
|
} as unknown as Binding<Value>;
|
|
1188
|
-
this._committed = this._commit(binding as Binding
|
|
1110
|
+
this._committed = this._commit(binding as Binding, previousId);
|
|
1189
1111
|
}
|
|
1190
1112
|
}
|
|
1191
1113
|
|
package/src/decorators/inject.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { BindingTag, Constructor } from "#/types";
|
|
2
|
-
import type { Token } from "#/token";
|
|
3
|
-
import { INJECT_ACCESSOR_KEY } from "#/metadata/metadata-keys";
|
|
4
|
-
import { InternalError, MissingContainerContextError } from "#/errors";
|
|
5
1
|
import { getActiveContainer } from "#/environment";
|
|
2
|
+
import { InternalError, MissingContainerContextError } from "#/errors";
|
|
3
|
+
import { INJECT_ACCESSOR_KEY } from "#/metadata/metadata-keys";
|
|
6
4
|
import { injectionSlotToResolveOptions } from "#/resolve-options";
|
|
5
|
+
import type { Token } from "#/token";
|
|
6
|
+
import type { BindingTag, Constructor } from "#/types";
|
|
7
7
|
|
|
8
8
|
// ── InjectionDescriptor ───────────────────────────────────────────────────────
|
|
9
9
|
|
|
@@ -29,10 +29,7 @@ export interface InjectionDescriptor<Value = unknown> {
|
|
|
29
29
|
/**
|
|
30
30
|
* @since 0.3.16-canary.0
|
|
31
31
|
*/
|
|
32
|
-
export type InjectableDependency<Value = unknown> =
|
|
33
|
-
| Token<Value>
|
|
34
|
-
| Constructor<Value>
|
|
35
|
-
| InjectionDescriptor<Value>;
|
|
32
|
+
export type InjectableDependency<Value = unknown> = Token<Value> | Constructor<Value> | InjectionDescriptor<Value>;
|
|
36
33
|
|
|
37
34
|
/**
|
|
38
35
|
* @since 0.3.16-canary.0
|
|
@@ -74,17 +71,14 @@ function materializeInjectionDescriptor(dependency: InjectionDescriptor): Inject
|
|
|
74
71
|
return dependency;
|
|
75
72
|
}
|
|
76
73
|
const dualRole = dependency as InjectionDescriptor & ((...args: Array<unknown>) => unknown);
|
|
77
|
-
const base: Pick<InjectionDescriptor
|
|
74
|
+
const base: Pick<InjectionDescriptor, "token" | "optional" | "multi"> = {
|
|
78
75
|
token: dualRole.token,
|
|
79
76
|
optional: dualRole.optional,
|
|
80
77
|
multi: dualRole.multi,
|
|
81
78
|
};
|
|
82
79
|
const nameDesc = Object.getOwnPropertyDescriptor(dualRole, "name");
|
|
83
80
|
const tagsDesc = Object.getOwnPropertyDescriptor(dualRole, "tags");
|
|
84
|
-
const explicitName =
|
|
85
|
-
nameDesc?.enumerable === true && typeof nameDesc.value === "string"
|
|
86
|
-
? nameDesc.value
|
|
87
|
-
: undefined;
|
|
81
|
+
const explicitName = nameDesc?.enumerable === true && typeof nameDesc.value === "string" ? nameDesc.value : undefined;
|
|
88
82
|
const explicitTags = tagsDesc?.enumerable === true ? tagsDesc.value : undefined;
|
|
89
83
|
|
|
90
84
|
if (explicitName !== undefined && explicitTags !== undefined) {
|
|
@@ -146,7 +140,7 @@ export function inject<const Value>(
|
|
|
146
140
|
_target: ClassAccessorDecoratorTarget<unknown, Value>,
|
|
147
141
|
context: ClassAccessorDecoratorContext<unknown, Value>,
|
|
148
142
|
): ClassAccessorDecoratorResult<unknown, Value> => {
|
|
149
|
-
if (context.static
|
|
143
|
+
if (context.static) {
|
|
150
144
|
throw new InternalError(
|
|
151
145
|
"@inject() on static accessors is not supported; only instance accessors participate in runWithContainer-based property injection.",
|
|
152
146
|
);
|
|
@@ -155,9 +149,7 @@ export function inject<const Value>(
|
|
|
155
149
|
if (!Array.isArray(meta[INJECT_ACCESSOR_KEY])) {
|
|
156
150
|
meta[INJECT_ACCESSOR_KEY] = [];
|
|
157
151
|
}
|
|
158
|
-
(
|
|
159
|
-
meta[INJECT_ACCESSOR_KEY] as Array<{ key: string | symbol; descriptor: InjectionDescriptor }>
|
|
160
|
-
).push({
|
|
152
|
+
(meta[INJECT_ACCESSOR_KEY] as Array<{ key: string | symbol; descriptor: InjectionDescriptor }>).push({
|
|
161
153
|
key: context.name,
|
|
162
154
|
descriptor,
|
|
163
155
|
});
|
|
@@ -174,9 +166,7 @@ export function inject<const Value>(
|
|
|
174
166
|
...(options.name !== undefined ? { name: options.name } : {}),
|
|
175
167
|
...(options.tags !== undefined ? { tags: options.tags } : {}),
|
|
176
168
|
});
|
|
177
|
-
const value = descriptor.optional
|
|
178
|
-
? container.resolveOptional(token, hint)
|
|
179
|
-
: container.resolve(token, hint);
|
|
169
|
+
const value = descriptor.optional ? container.resolveOptional(token, hint) : container.resolve(token, hint);
|
|
180
170
|
context.access.set(this, value as Value);
|
|
181
171
|
});
|
|
182
172
|
|
|
@@ -190,8 +180,7 @@ export function inject<const Value>(
|
|
|
190
180
|
}
|
|
191
181
|
Object.defineProperties(decoratorFn, props);
|
|
192
182
|
|
|
193
|
-
return decoratorFn as unknown as InjectionDescriptor<Value> &
|
|
194
|
-
ClassAccessorDecorator<unknown, Value>;
|
|
183
|
+
return decoratorFn as unknown as InjectionDescriptor<Value> & ClassAccessorDecorator<unknown, Value>;
|
|
195
184
|
}
|
|
196
185
|
|
|
197
186
|
// ── optional() ────────────────────────────────────────────────────────────────
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { BindingScope, Constructor } from "#/types";
|
|
2
|
-
import type { ParamMetadata } from "#/metadata/metadata-types";
|
|
3
1
|
import type { InjectableDependency } from "#/decorators/inject";
|
|
4
2
|
import { normalizeToDescriptor } from "#/decorators/inject";
|
|
5
3
|
import { INJECTABLE_KEY } from "#/metadata/metadata-keys";
|
|
4
|
+
import type { ParamMetadata } from "#/metadata/metadata-types";
|
|
5
|
+
import type { BindingScope, Constructor } from "#/types";
|
|
6
6
|
|
|
7
7
|
// ── AutoRegisterRegistry ──────────────────────────────────────────────────────
|
|
8
8
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { MutableLifecycleMetadata } from "#/metadata/metadata-types";
|
|
2
1
|
import { InternalError } from "#/errors";
|
|
3
2
|
import { LIFECYCLE_KEY } from "#/metadata/metadata-keys";
|
|
3
|
+
import type { MutableLifecycleMetadata } from "#/metadata/metadata-types";
|
|
4
4
|
|
|
5
5
|
function appendUniqueMethod(
|
|
6
6
|
metadata: MutableLifecycleMetadata,
|
|
@@ -17,7 +17,7 @@ function appendUniqueMethod(
|
|
|
17
17
|
*/
|
|
18
18
|
export function postConstruct(): (target: unknown, context: ClassMethodDecoratorContext) => void {
|
|
19
19
|
return function (target: unknown, context: ClassMethodDecoratorContext): void {
|
|
20
|
-
if (context.static
|
|
20
|
+
if (context.static) {
|
|
21
21
|
throw new InternalError(
|
|
22
22
|
"@postConstruct() applies to instance methods only; static methods are not invoked during instance lifecycle.",
|
|
23
23
|
);
|
|
@@ -27,11 +27,7 @@ export function postConstruct(): (target: unknown, context: ClassMethodDecorator
|
|
|
27
27
|
if (!meta[LIFECYCLE_KEY]) {
|
|
28
28
|
meta[LIFECYCLE_KEY] = { postConstruct: [], preDestroy: [] };
|
|
29
29
|
}
|
|
30
|
-
appendUniqueMethod(
|
|
31
|
-
meta[LIFECYCLE_KEY] as MutableLifecycleMetadata,
|
|
32
|
-
"postConstruct",
|
|
33
|
-
methodName,
|
|
34
|
-
);
|
|
30
|
+
appendUniqueMethod(meta[LIFECYCLE_KEY] as MutableLifecycleMetadata, "postConstruct", methodName);
|
|
35
31
|
};
|
|
36
32
|
}
|
|
37
33
|
|
|
@@ -40,7 +36,7 @@ export function postConstruct(): (target: unknown, context: ClassMethodDecorator
|
|
|
40
36
|
*/
|
|
41
37
|
export function preDestroy(): (target: unknown, context: ClassMethodDecoratorContext) => void {
|
|
42
38
|
return function (target: unknown, context: ClassMethodDecoratorContext): void {
|
|
43
|
-
if (context.static
|
|
39
|
+
if (context.static) {
|
|
44
40
|
throw new InternalError(
|
|
45
41
|
"@preDestroy() applies to instance methods only; static methods are not invoked during instance teardown.",
|
|
46
42
|
);
|
package/src/dependency-graph.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { effectiveBindingScope } from "#/binding-scope";
|
|
2
2
|
import type { MetadataReader } from "#/metadata/metadata-types";
|
|
3
|
-
import type {
|
|
3
|
+
import type { BindingRegistry } from "#/registry";
|
|
4
4
|
import { tokenName } from "#/token";
|
|
5
|
-
import {
|
|
5
|
+
import type { BindingScope, Constructor } from "#/types";
|
|
6
6
|
|
|
7
7
|
// ── Types ─────────────────────────────────────────────────────────────────────
|
|
8
8
|
|
package/src/environment.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Container } from "#/container";
|
|
2
|
+
import type { Token } from "#/token";
|
|
1
3
|
import type {
|
|
2
4
|
BindingIdentifier,
|
|
3
5
|
BindingKind,
|
|
@@ -8,8 +10,6 @@ import type {
|
|
|
8
10
|
ResolutionContext,
|
|
9
11
|
ResolveOptions,
|
|
10
12
|
} from "#/types";
|
|
11
|
-
import type { Token } from "#/token";
|
|
12
|
-
import type { Container } from "#/container";
|
|
13
13
|
|
|
14
14
|
// ── Active container ──────────────────────────────────────────────────────────
|
|
15
15
|
|
|
@@ -114,11 +114,7 @@ export class DefaultResolutionContext implements ResolutionContext {
|
|
|
114
114
|
|
|
115
115
|
get graph(): ConstraintContext {
|
|
116
116
|
if (this._graph === undefined) {
|
|
117
|
-
this._graph = new DefaultConstraintContext(
|
|
118
|
-
this._resolutionPath,
|
|
119
|
-
this._resolutionStack,
|
|
120
|
-
this._currentHint,
|
|
121
|
-
);
|
|
117
|
+
this._graph = new DefaultConstraintContext(this._resolutionPath, this._resolutionStack, this._currentHint);
|
|
122
118
|
}
|
|
123
119
|
return this._graph;
|
|
124
120
|
}
|
|
@@ -143,24 +139,14 @@ export class DefaultResolutionContext implements ResolutionContext {
|
|
|
143
139
|
return this._resolver.resolve(token, hint, this._resolutionPath, this._resolutionStack);
|
|
144
140
|
}
|
|
145
141
|
|
|
146
|
-
resolveAsync<const Value>(
|
|
147
|
-
token: Token<Value> | Constructor<Value>,
|
|
148
|
-
hint?: ResolveOptions,
|
|
149
|
-
): Promise<Value> {
|
|
142
|
+
resolveAsync<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Promise<Value> {
|
|
150
143
|
if (hint === undefined) {
|
|
151
|
-
return this._resolver.resolveAsyncFromContext(
|
|
152
|
-
token,
|
|
153
|
-
this._resolutionPath,
|
|
154
|
-
this._resolutionStack,
|
|
155
|
-
);
|
|
144
|
+
return this._resolver.resolveAsyncFromContext(token, this._resolutionPath, this._resolutionStack);
|
|
156
145
|
}
|
|
157
146
|
return this._resolver.resolveAsync(token, hint, this._resolutionPath, this._resolutionStack);
|
|
158
147
|
}
|
|
159
148
|
|
|
160
|
-
resolveOptional<const Value>(
|
|
161
|
-
token: Token<Value> | Constructor<Value>,
|
|
162
|
-
hint?: ResolveOptions,
|
|
163
|
-
): Value | undefined {
|
|
149
|
+
resolveOptional<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Value | undefined {
|
|
164
150
|
return this._resolver.resolveOptional(token, hint, this._resolutionPath, this._resolutionStack);
|
|
165
151
|
}
|
|
166
152
|
|
|
@@ -168,25 +154,14 @@ export class DefaultResolutionContext implements ResolutionContext {
|
|
|
168
154
|
token: Token<Value> | Constructor<Value>,
|
|
169
155
|
hint?: ResolveOptions,
|
|
170
156
|
): Promise<Value | undefined> {
|
|
171
|
-
return this._resolver.resolveOptionalAsync(
|
|
172
|
-
token,
|
|
173
|
-
hint,
|
|
174
|
-
this._resolutionPath,
|
|
175
|
-
this._resolutionStack,
|
|
176
|
-
);
|
|
157
|
+
return this._resolver.resolveOptionalAsync(token, hint, this._resolutionPath, this._resolutionStack);
|
|
177
158
|
}
|
|
178
159
|
|
|
179
|
-
resolveAll<const Value>(
|
|
180
|
-
token: Token<Value> | Constructor<Value>,
|
|
181
|
-
hint?: ResolveOptions,
|
|
182
|
-
): Array<Value> {
|
|
160
|
+
resolveAll<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Array<Value> {
|
|
183
161
|
return this._resolver.resolveAll(token, hint, this._resolutionPath, this._resolutionStack);
|
|
184
162
|
}
|
|
185
163
|
|
|
186
|
-
resolveAllAsync<const Value>(
|
|
187
|
-
token: Token<Value> | Constructor<Value>,
|
|
188
|
-
hint?: ResolveOptions,
|
|
189
|
-
): Promise<Array<Value>> {
|
|
164
|
+
resolveAllAsync<const Value>(token: Token<Value> | Constructor<Value>, hint?: ResolveOptions): Promise<Array<Value>> {
|
|
190
165
|
return this._resolver.resolveAllAsync(token, hint, this._resolutionPath, this._resolutionStack);
|
|
191
166
|
}
|
|
192
167
|
}
|
package/src/errors.ts
CHANGED
|
@@ -31,9 +31,7 @@ export class TokenNotBoundError extends DiError {
|
|
|
31
31
|
readonly tokenName: string;
|
|
32
32
|
|
|
33
33
|
constructor(tokenName: string) {
|
|
34
|
-
super(
|
|
35
|
-
`No binding found for token '${tokenName}'. Did you forget container.bind(${tokenName})?`,
|
|
36
|
-
);
|
|
34
|
+
super(`No binding found for token '${tokenName}'. Did you forget container.bind(${tokenName})?`);
|
|
37
35
|
this.tokenName = tokenName;
|
|
38
36
|
}
|
|
39
37
|
}
|