@codefast/di 0.3.14-canary.1 → 0.3.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/README.md +42 -26
- package/dist/binding-scope.d.mts +11 -0
- package/dist/binding-scope.mjs +19 -0
- package/dist/binding-select.d.mts +8 -26
- package/dist/binding-select.mjs +56 -49
- package/dist/binding.d.mts +107 -335
- package/dist/binding.mjs +19 -332
- package/dist/constraints.d.mts +11 -29
- package/dist/constraints.mjs +32 -36
- package/dist/constructor-type.d.mts +17 -0
- package/dist/constructor-type.mjs +1 -0
- package/dist/container.d.mts +43 -122
- package/dist/container.mjs +667 -482
- package/dist/decorators/inject.d.mts +19 -50
- package/dist/decorators/inject.mjs +131 -93
- package/dist/decorators/injectable.d.mts +16 -37
- package/dist/decorators/injectable.mjs +47 -66
- package/dist/decorators/lifecycle-decorators.d.mts +2 -22
- package/dist/decorators/lifecycle-decorators.mjs +81 -37
- package/dist/dependency-graph.d.mts +24 -54
- package/dist/dependency-graph.mjs +51 -153
- package/dist/environment.d.mts +38 -12
- package/dist/environment.mjs +82 -16
- package/dist/errors.d.mts +70 -189
- package/dist/errors.mjs +92 -219
- package/dist/graph-adapters/cytoscape.d.mts +21 -7
- package/dist/graph-adapters/cytoscape.mjs +18 -35
- package/dist/graph-adapters/dot.d.mts +1 -4
- package/dist/graph-adapters/dot.mjs +6 -86
- package/dist/graph-adapters/reactflow.d.mts +26 -7
- package/dist/graph-adapters/reactflow.mjs +21 -72
- package/dist/graph-adapters/types.d.mts +2 -91
- package/dist/index.d.mts +16 -8
- package/dist/index.mjs +8 -5
- package/dist/inspector.d.mts +35 -74
- package/dist/inspector.mjs +61 -88
- package/dist/lifecycle.d.mts +20 -53
- package/dist/lifecycle.mjs +129 -99
- package/dist/metadata/metadata-keys.d.mts +9 -26
- package/dist/metadata/metadata-keys.mjs +7 -28
- package/dist/metadata/metadata-reader-token.d.mts +7 -0
- package/dist/metadata/metadata-reader-token.mjs +5 -0
- package/dist/metadata/metadata-types.d.mts +26 -75
- package/dist/metadata/symbol-metadata-reader.d.mts +10 -26
- package/dist/metadata/symbol-metadata-reader.mjs +32 -45
- package/dist/module.d.mts +30 -96
- package/dist/module.mjs +26 -72
- package/dist/registry.d.mts +32 -63
- package/dist/registry.mjs +131 -82
- package/dist/resolve-options.d.mts +18 -0
- package/dist/resolve-options.mjs +22 -0
- package/dist/resolver.d.mts +67 -190
- package/dist/resolver.mjs +715 -424
- package/dist/scope.d.mts +19 -106
- package/dist/scope.mjs +37 -196
- package/dist/token.d.mts +8 -22
- package/dist/token.mjs +9 -11
- package/dist/types.d.mts +48 -0
- package/dist/types.mjs +1 -0
- package/package.json +36 -14
- package/dist/metadata/param-registry.d.mts +0 -16
- package/dist/metadata/param-registry.mjs +0 -31
- package/dist/scope-validation.d.mts +0 -21
- package/dist/scope-validation.mjs +0 -35
package/dist/container.mjs
CHANGED
|
@@ -1,540 +1,725 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { ContainerInspector } from "./inspector.mjs";
|
|
6
|
-
import { AsyncModule } from "./module.mjs";
|
|
1
|
+
import { effectiveBindingScope } from "./binding-scope.mjs";
|
|
2
|
+
import { DisposedContainerError, RebindUnboundTokenError, ScopeViolationError, SyncDisposalNotSupportedError } from "./errors.mjs";
|
|
3
|
+
import { DEFAULT_SLOT, generateBindingId } from "./binding.mjs";
|
|
4
|
+
import { tokenName } from "./token.mjs";
|
|
7
5
|
import { BindingRegistry } from "./registry.mjs";
|
|
8
|
-
import { DependencyResolver } from "./resolver.mjs";
|
|
9
|
-
import { validateScopeRules } from "./scope-validation.mjs";
|
|
10
6
|
import { ScopeManager } from "./scope.mjs";
|
|
11
|
-
import {
|
|
7
|
+
import { LifecycleManager } from "./lifecycle.mjs";
|
|
8
|
+
import { slotKeyToResolveOptions } from "./resolve-options.mjs";
|
|
9
|
+
import { DependencyResolver } from "./resolver.mjs";
|
|
10
|
+
import { Inspector } from "./inspector.mjs";
|
|
11
|
+
import { buildDependencyGraph } from "./dependency-graph.mjs";
|
|
12
|
+
import { defaultMetadataReader } from "./metadata/symbol-metadata-reader.mjs";
|
|
13
|
+
import { MetadataReaderToken } from "./metadata/metadata-reader-token.mjs";
|
|
14
|
+
import { normalizeToDescriptor } from "./decorators/inject.mjs";
|
|
15
|
+
import { isSyncModule } from "./module.mjs";
|
|
12
16
|
//#region src/container.ts
|
|
13
|
-
/**
|
|
14
|
-
* Derives a {@link ResolveHint} from a binding's name or first tag.
|
|
15
|
-
* Used by {@link DefaultContainer.initializeAsync} to re-resolve named/tagged singletons
|
|
16
|
-
* through the standard resolution path.
|
|
17
|
-
*/
|
|
18
|
-
function resolveHintForBinding(binding) {
|
|
19
|
-
if (binding.bindingName !== void 0) return { name: binding.bindingName };
|
|
20
|
-
for (const [tagKey, tagValue] of binding.tags) return { tag: [tagKey, tagValue] };
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Module {@link ModuleBuilder.bind}: append when the binding is disambiguated **at first
|
|
24
|
-
* registration** (`whenNamed` / `whenTagged` / `when` before `to*()`). Otherwise replace
|
|
25
|
-
* all bindings for the token (last-wins). Chaining `.whenNamed()` after `.to*()` only updates
|
|
26
|
-
* in place and does not enable multi-binding for subsequent module lines — use hint-before-`to*()`
|
|
27
|
-
* in modules (same style as `container.bind(...).whenNamed("x").to*(...)` in the package README).
|
|
28
|
-
*/
|
|
29
|
-
function moduleBindingUsesMultiSlot(built) {
|
|
30
|
-
return built.bindingName !== void 0 || built.tags.size > 0 || built.constraint !== void 0;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Default IoC container: registry + scoped caches + synchronous / asynchronous resolution.
|
|
34
|
-
* @internal Implementation of {@link Container}; not part of the public package contract.
|
|
35
|
-
*/
|
|
36
17
|
var DefaultContainer = class DefaultContainer {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
* Creates a root container with an empty registry and fresh singleton/scoped caches.
|
|
69
|
-
* Wires the circular container↔resolver reference via a mutable {@link ContainerRef} holder.
|
|
70
|
-
*/
|
|
71
|
-
static create() {
|
|
72
|
-
const ownRegistry = new BindingRegistry();
|
|
73
|
-
const ownScopeManager = ScopeManager.createRoot();
|
|
74
|
-
const metadataReader = new SymbolMetadataReader();
|
|
75
|
-
const holder = { current: void 0 };
|
|
76
|
-
const container = new DefaultContainer(ownRegistry, ownScopeManager, void 0, new DependencyResolver({
|
|
77
|
-
lookup: (token) => {
|
|
78
|
-
const current = holder.current;
|
|
79
|
-
if (current === void 0) throw new InternalError("container is not initialized");
|
|
80
|
-
return current.lookupBindings(token);
|
|
81
|
-
},
|
|
82
|
-
scopeManager: ownScopeManager,
|
|
83
|
-
metadataReader
|
|
84
|
-
}), metadataReader);
|
|
85
|
-
holder.current = container;
|
|
86
|
-
return container;
|
|
18
|
+
_disposed = false;
|
|
19
|
+
_registry;
|
|
20
|
+
_scope;
|
|
21
|
+
_lifecycle;
|
|
22
|
+
_resolver;
|
|
23
|
+
_inspector;
|
|
24
|
+
_parent;
|
|
25
|
+
_moduleRefs = /* @__PURE__ */ new Map();
|
|
26
|
+
_moduleBindingIds = /* @__PURE__ */ new Map();
|
|
27
|
+
constructor(parent) {
|
|
28
|
+
this._parent = parent;
|
|
29
|
+
this._registry = new BindingRegistry();
|
|
30
|
+
this._scope = new ScopeManager(parent !== void 0);
|
|
31
|
+
this._lifecycle = new LifecycleManager();
|
|
32
|
+
this._inspector = new Inspector(this._registry, this._scope, parent !== void 0, () => this._disposed);
|
|
33
|
+
this._initResolver();
|
|
34
|
+
}
|
|
35
|
+
_initResolver() {
|
|
36
|
+
const metadataReader = this._getMetadataReader();
|
|
37
|
+
const parentResolver = this._parent?._resolver;
|
|
38
|
+
this._resolver = new DependencyResolver(this._registry, this._scope, this._lifecycle, metadataReader, this, parentResolver);
|
|
39
|
+
}
|
|
40
|
+
_getMetadataReader() {
|
|
41
|
+
if (this._registry.getAll(MetadataReaderToken).length > 0) try {
|
|
42
|
+
return this._resolver.resolve(MetadataReaderToken, void 0, [], []);
|
|
43
|
+
} catch {}
|
|
44
|
+
if (this._parent !== void 0) return this._parent._getMetadataReader();
|
|
45
|
+
return defaultMetadataReader;
|
|
46
|
+
}
|
|
47
|
+
get isDisposed() {
|
|
48
|
+
return this._disposed;
|
|
87
49
|
}
|
|
88
|
-
/**
|
|
89
|
-
* Starts a fluent {@link BindingBuilder} for the given token or constructor.
|
|
90
|
-
* The binding is registered into this container's registry immediately when a
|
|
91
|
-
* `to*()` strategy method is called on the returned builder.
|
|
92
|
-
*/
|
|
93
50
|
bind(token) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
51
|
+
this._assertNotDisposed();
|
|
52
|
+
return this._createBindToBuilder(token);
|
|
53
|
+
}
|
|
54
|
+
_createBindToBuilder(token, moduleRef) {
|
|
55
|
+
const registry = this._registry;
|
|
56
|
+
const commitBinding = (b, previousId) => {
|
|
57
|
+
if (previousId !== void 0) {
|
|
58
|
+
registry.removeById(previousId);
|
|
59
|
+
if (moduleRef !== void 0) {
|
|
60
|
+
const ids = this._moduleBindingIds.get(moduleRef);
|
|
61
|
+
if (ids !== void 0) {
|
|
62
|
+
const idx = ids.indexOf(previousId);
|
|
63
|
+
if (idx !== -1) ids.splice(idx, 1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
102
66
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
has(token, hint) {
|
|
112
|
-
const list = this.lookupBindings(token);
|
|
113
|
-
if (list === void 0 || list.length === 0) return false;
|
|
114
|
-
if (hint === void 0) return true;
|
|
115
|
-
return list.some((binding) => {
|
|
116
|
-
if (hint.name !== void 0 && binding.bindingName !== hint.name) return false;
|
|
117
|
-
if (hint.tag !== void 0) {
|
|
118
|
-
const tag = hint.tag;
|
|
119
|
-
if (binding.tags.get(tag[0]) !== tag[1]) return false;
|
|
67
|
+
registry.add(b);
|
|
68
|
+
if (moduleRef !== void 0) {
|
|
69
|
+
let ids = this._moduleBindingIds.get(moduleRef);
|
|
70
|
+
if (ids === void 0) {
|
|
71
|
+
ids = [];
|
|
72
|
+
this._moduleBindingIds.set(moduleRef, ids);
|
|
73
|
+
}
|
|
74
|
+
ids.push(b.id);
|
|
120
75
|
}
|
|
121
|
-
return
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
* Removes bindings by token or by binding id and synchronously releases cached instances.
|
|
126
|
-
*
|
|
127
|
-
* - `binding id` path removes one binding and its cache entry.
|
|
128
|
-
* - `token` path removes all owned bindings for that key at once.
|
|
129
|
-
*/
|
|
76
|
+
return b.id;
|
|
77
|
+
};
|
|
78
|
+
return new BindToBuilderImpl(token, commitBinding);
|
|
79
|
+
}
|
|
130
80
|
unbind(tokenOrId) {
|
|
131
|
-
this.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
81
|
+
this._assertNotDisposed();
|
|
82
|
+
this._unbindSync(tokenOrId);
|
|
83
|
+
}
|
|
84
|
+
_unbindSync(tokenOrId) {
|
|
85
|
+
const bindings = this._getBindingsForTokenOrId(tokenOrId);
|
|
86
|
+
for (const binding of bindings) {
|
|
87
|
+
this._registry.removeById(binding.id);
|
|
88
|
+
if (this._scope.hasSingleton(binding.id)) {
|
|
89
|
+
const instance = this._scope.getSingleton(binding.id);
|
|
90
|
+
this._scope.deleteSingleton(binding.id);
|
|
91
|
+
this._lifecycle.runDeactivationSync(binding, instance, this._getMetadataReader());
|
|
92
|
+
}
|
|
136
93
|
}
|
|
137
|
-
const owned = this.ownRegistry.get(tokenOrId);
|
|
138
|
-
if (owned !== void 0) for (const binding of owned) this.ownScopeManager.releaseBinding(binding);
|
|
139
|
-
this.ownRegistry.remove(tokenOrId);
|
|
140
94
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Async counterpart of {@link unbind}; awaits deactivation hooks before registry removal.
|
|
143
|
-
*/
|
|
144
95
|
async unbindAsync(tokenOrId) {
|
|
145
|
-
this.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
this.
|
|
149
|
-
|
|
96
|
+
this._assertNotDisposed();
|
|
97
|
+
const bindings = this._getBindingsForTokenOrId(tokenOrId);
|
|
98
|
+
for (const binding of bindings) {
|
|
99
|
+
this._registry.removeById(binding.id);
|
|
100
|
+
if (this._scope.hasSingleton(binding.id)) {
|
|
101
|
+
const instance = this._scope.getSingleton(binding.id);
|
|
102
|
+
this._scope.deleteSingleton(binding.id);
|
|
103
|
+
await this._lifecycle.runDeactivation(binding, instance, this._getMetadataReader());
|
|
104
|
+
}
|
|
150
105
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
this.
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
106
|
+
}
|
|
107
|
+
unbindAll() {
|
|
108
|
+
this._assertNotDisposed();
|
|
109
|
+
const all = this._registry.clear();
|
|
110
|
+
for (const binding of all) if (this._scope.hasSingleton(binding.id)) {
|
|
111
|
+
const instance = this._scope.getSingleton(binding.id);
|
|
112
|
+
this._scope.deleteSingleton(binding.id);
|
|
113
|
+
this._lifecycle.runDeactivationSync(binding, instance, this._getMetadataReader());
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async unbindAllAsync() {
|
|
117
|
+
this._assertNotDisposed();
|
|
118
|
+
const all = this._registry.clear();
|
|
119
|
+
for (const binding of all) if (this._scope.hasSingleton(binding.id)) {
|
|
120
|
+
const instance = this._scope.getSingleton(binding.id);
|
|
121
|
+
this._scope.deleteSingleton(binding.id);
|
|
122
|
+
await this._lifecycle.runDeactivation(binding, instance, this._getMetadataReader());
|
|
123
|
+
}
|
|
124
|
+
}
|
|
160
125
|
rebind(token) {
|
|
161
|
-
this.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
this.
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
126
|
+
this._assertNotDisposed();
|
|
127
|
+
if (!this._registry.has(token)) throw new RebindUnboundTokenError(tokenName(token));
|
|
128
|
+
this._unbindSync(token);
|
|
129
|
+
return this._createBindToBuilder(token);
|
|
130
|
+
}
|
|
131
|
+
_getBindingsForTokenOrId(tokenOrId) {
|
|
132
|
+
if (typeof tokenOrId === "string") {
|
|
133
|
+
const b = this._registry.getById(tokenOrId);
|
|
134
|
+
return b !== void 0 ? [b] : [];
|
|
135
|
+
}
|
|
136
|
+
return [...this._registry.getAll(tokenOrId)];
|
|
137
|
+
}
|
|
172
138
|
load(...modules) {
|
|
173
|
-
this.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
139
|
+
this._assertNotDisposed();
|
|
140
|
+
this._loadSyncModules(modules);
|
|
141
|
+
}
|
|
142
|
+
_loadSyncModules(modules) {
|
|
143
|
+
const toLoad = this._collectModuleDeps(modules);
|
|
144
|
+
for (const mod of toLoad) {
|
|
145
|
+
const ref = mod;
|
|
146
|
+
const existing = this._moduleRefs.get(ref);
|
|
147
|
+
if (existing !== void 0) {
|
|
148
|
+
this._moduleRefs.set(ref, existing + 1);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
this._moduleRefs.set(ref, 1);
|
|
152
|
+
const builder = this._createModuleBuilder(ref);
|
|
153
|
+
mod._setup(builder);
|
|
177
154
|
}
|
|
178
|
-
this.maybeRunDevValidationOnce();
|
|
179
155
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
156
|
+
_collectModuleDeps(modules) {
|
|
157
|
+
const seen = /* @__PURE__ */ new Set();
|
|
158
|
+
const result = [];
|
|
159
|
+
const visit = (mod) => {
|
|
160
|
+
const ref = mod;
|
|
161
|
+
if (seen.has(ref)) return;
|
|
162
|
+
seen.add(ref);
|
|
163
|
+
result.push(mod);
|
|
164
|
+
};
|
|
165
|
+
for (const m of modules) visit(m);
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
183
168
|
async loadAsync(...modules) {
|
|
184
|
-
this.
|
|
185
|
-
for (const
|
|
186
|
-
|
|
187
|
-
|
|
169
|
+
this._assertNotDisposed();
|
|
170
|
+
for (const mod of modules) await this._loadOneModuleAsync(mod);
|
|
171
|
+
}
|
|
172
|
+
async _loadOneModuleAsync(mod) {
|
|
173
|
+
const ref = mod;
|
|
174
|
+
const existing = this._moduleRefs.get(ref);
|
|
175
|
+
if (existing !== void 0) {
|
|
176
|
+
this._moduleRefs.set(ref, existing + 1);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
this._moduleRefs.set(ref, 1);
|
|
180
|
+
if (isSyncModule(mod)) {
|
|
181
|
+
const builder = this._createModuleBuilder(ref);
|
|
182
|
+
mod._setup(builder);
|
|
183
|
+
} else {
|
|
184
|
+
const importPromises = [];
|
|
185
|
+
const builder = this._createAsyncModuleBuilder(ref, importPromises);
|
|
186
|
+
await mod._setup(builder);
|
|
187
|
+
if (importPromises.length > 0) await Promise.all(importPromises);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
_createModuleBuilder(moduleRef) {
|
|
191
|
+
return {
|
|
192
|
+
bind: (t) => this._createBindToBuilder(t, moduleRef),
|
|
193
|
+
import: (...mods) => {
|
|
194
|
+
this._loadSyncModules(mods);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
_createAsyncModuleBuilder(moduleRef, importPromises) {
|
|
199
|
+
return {
|
|
200
|
+
bind: (t) => this._createBindToBuilder(t, moduleRef),
|
|
201
|
+
import: (...mods) => {
|
|
202
|
+
for (const mod of mods) importPromises.push(this._loadOneModuleAsync(mod));
|
|
203
|
+
}
|
|
204
|
+
};
|
|
188
205
|
}
|
|
189
206
|
unload(...modules) {
|
|
190
|
-
this.
|
|
191
|
-
for (const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
207
|
+
this._assertNotDisposed();
|
|
208
|
+
for (const mod of modules) this._unloadModuleSync(mod);
|
|
209
|
+
}
|
|
210
|
+
_unloadModuleSync(ref) {
|
|
211
|
+
const count = this._moduleRefs.get(ref) ?? 0;
|
|
212
|
+
if (count <= 1) {
|
|
213
|
+
this._moduleRefs.delete(ref);
|
|
214
|
+
const ids = this._moduleBindingIds.get(ref) ?? [];
|
|
215
|
+
this._moduleBindingIds.delete(ref);
|
|
216
|
+
for (const id of ids) {
|
|
217
|
+
const binding = this._registry.getById(id);
|
|
218
|
+
if (binding !== void 0) {
|
|
219
|
+
this._registry.removeById(id);
|
|
220
|
+
if (this._scope.hasSingleton(id)) {
|
|
221
|
+
const instance = this._scope.getSingleton(id);
|
|
222
|
+
this._scope.deleteSingleton(id);
|
|
223
|
+
this._lifecycle.runDeactivationSync(binding, instance, this._getMetadataReader());
|
|
224
|
+
}
|
|
225
|
+
}
|
|
197
226
|
}
|
|
198
|
-
|
|
199
|
-
}
|
|
227
|
+
} else this._moduleRefs.set(ref, count - 1);
|
|
200
228
|
}
|
|
201
229
|
async unloadAsync(...modules) {
|
|
202
|
-
this.
|
|
203
|
-
for (const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
230
|
+
this._assertNotDisposed();
|
|
231
|
+
for (const mod of modules) await this._unloadModuleAsync(mod);
|
|
232
|
+
}
|
|
233
|
+
async _unloadModuleAsync(ref) {
|
|
234
|
+
const count = this._moduleRefs.get(ref) ?? 0;
|
|
235
|
+
if (count <= 1) {
|
|
236
|
+
this._moduleRefs.delete(ref);
|
|
237
|
+
const ids = this._moduleBindingIds.get(ref) ?? [];
|
|
238
|
+
this._moduleBindingIds.delete(ref);
|
|
239
|
+
for (const id of ids) {
|
|
240
|
+
const binding = this._registry.getById(id);
|
|
241
|
+
if (binding !== void 0) {
|
|
242
|
+
this._registry.removeById(id);
|
|
243
|
+
if (this._scope.hasSingleton(id)) {
|
|
244
|
+
const instance = this._scope.getSingleton(id);
|
|
245
|
+
this._scope.deleteSingleton(id);
|
|
246
|
+
await this._lifecycle.runDeactivation(binding, instance, this._getMetadataReader());
|
|
247
|
+
}
|
|
248
|
+
}
|
|
209
249
|
}
|
|
210
|
-
|
|
250
|
+
} else this._moduleRefs.set(ref, count - 1);
|
|
251
|
+
}
|
|
252
|
+
loadAutoRegistered(registry) {
|
|
253
|
+
this._assertNotDisposed();
|
|
254
|
+
const entries = registry.entries();
|
|
255
|
+
for (const { target, scope } of entries) {
|
|
256
|
+
const bb = this._createBindToBuilder(target).toSelf();
|
|
257
|
+
if (scope === "singleton") bb.singleton();
|
|
258
|
+
else if (scope === "scoped") bb.scoped();
|
|
259
|
+
else bb.transient();
|
|
211
260
|
}
|
|
261
|
+
return entries.length;
|
|
212
262
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
* successful resolution also triggers a one-time static {@link validate} when not in production.
|
|
217
|
-
*/
|
|
218
|
-
resolve(key, hint) {
|
|
219
|
-
try {
|
|
220
|
-
return this.resolver.resolveRoot(key, hint);
|
|
221
|
-
} finally {
|
|
222
|
-
this.maybeRunDevValidationOnce();
|
|
223
|
-
}
|
|
263
|
+
onActivation(token, handler) {
|
|
264
|
+
this._assertNotDisposed();
|
|
265
|
+
this._lifecycle.registerActivation(token, handler);
|
|
224
266
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
try {
|
|
239
|
-
return this.resolver.resolveOptionalRoot(key, hint);
|
|
240
|
-
} finally {
|
|
241
|
-
this.maybeRunDevValidationOnce();
|
|
242
|
-
}
|
|
267
|
+
onDeactivation(token, handler) {
|
|
268
|
+
this._assertNotDisposed();
|
|
269
|
+
this._lifecycle.registerDeactivation(token, handler);
|
|
270
|
+
}
|
|
271
|
+
resolve(token, hint) {
|
|
272
|
+
this._assertNotDisposed();
|
|
273
|
+
if (hint === void 0) return this._resolver.resolveFromContext(token, [], []);
|
|
274
|
+
return this._resolver.resolve(token, hint, [], []);
|
|
275
|
+
}
|
|
276
|
+
resolveAsync(token, hint) {
|
|
277
|
+
this._assertNotDisposed();
|
|
278
|
+
if (hint === void 0) return this._resolver.resolveAsyncFromContext(token, [], []);
|
|
279
|
+
return this._resolver.resolveAsync(token, hint, [], []);
|
|
243
280
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
281
|
+
resolveOptional(token, hint) {
|
|
282
|
+
this._assertNotDisposed();
|
|
283
|
+
return this._resolver.resolveOptional(token, hint, [], []);
|
|
284
|
+
}
|
|
285
|
+
resolveOptionalAsync(token, hint) {
|
|
286
|
+
this._assertNotDisposed();
|
|
287
|
+
return this._resolver.resolveOptionalAsync(token, hint, [], []);
|
|
288
|
+
}
|
|
289
|
+
resolveAll(token, hint) {
|
|
290
|
+
this._assertNotDisposed();
|
|
291
|
+
return this._resolver.resolveAll(token, hint, [], []);
|
|
292
|
+
}
|
|
293
|
+
resolveAllAsync(token, hint) {
|
|
294
|
+
this._assertNotDisposed();
|
|
295
|
+
return this._resolver.resolveAllAsync(token, hint, [], []);
|
|
296
|
+
}
|
|
297
|
+
createChild() {
|
|
298
|
+
this._assertNotDisposed();
|
|
299
|
+
return new DefaultContainer(this);
|
|
300
|
+
}
|
|
301
|
+
async dispose() {
|
|
302
|
+
if (this._disposed) return;
|
|
303
|
+
this._disposed = true;
|
|
304
|
+
const reader = this._getMetadataReader();
|
|
305
|
+
for (const [id, instance] of this._scope.getAllSingletons()) {
|
|
306
|
+
const binding = this._registry.getById(id);
|
|
307
|
+
if (binding !== void 0) await this._lifecycle.runDeactivation(binding, instance, reader);
|
|
253
308
|
}
|
|
309
|
+
this._scope.clearAll();
|
|
310
|
+
}
|
|
311
|
+
[Symbol.asyncDispose]() {
|
|
312
|
+
return this.dispose();
|
|
313
|
+
}
|
|
314
|
+
[Symbol.dispose]() {
|
|
315
|
+
throw new SyncDisposalNotSupportedError();
|
|
254
316
|
}
|
|
255
|
-
/**
|
|
256
|
-
* Async variant of {@link resolveAll}: safe for multi-bindings that mix sync and async factories
|
|
257
|
-
* (spec §5.2).
|
|
258
|
-
*/
|
|
259
|
-
resolveAllAsync(key, hint) {
|
|
260
|
-
return this.resolver.resolveAllAsyncRoot(key, hint).finally(() => {
|
|
261
|
-
this.maybeRunDevValidationOnce();
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
* Eagerly resolves every registered `singleton` binding, including `async-dynamic` factories.
|
|
266
|
-
*/
|
|
267
317
|
async initializeAsync() {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
318
|
+
this._assertNotDisposed();
|
|
319
|
+
const allBindings = this._registry.allBindings();
|
|
320
|
+
for (const binding of allBindings) {
|
|
321
|
+
if (binding.kind === "alias") continue;
|
|
322
|
+
if (effectiveBindingScope(binding) === "singleton" && !this._scope.hasSingleton(binding.id)) {
|
|
323
|
+
if (binding.predicate !== void 0) continue;
|
|
324
|
+
if (binding.kind === "constant" && binding.onActivation === void 0) continue;
|
|
325
|
+
const slotHint = slotKeyToResolveOptions(binding.slot);
|
|
326
|
+
await this.resolveAsync(binding.token, slotHint);
|
|
275
327
|
}
|
|
276
328
|
}
|
|
277
329
|
}
|
|
278
|
-
/**
|
|
279
|
-
* Marks the dev/test one-shot validation as stale so the next resolve or load triggers it again.
|
|
280
|
-
* Called on every registry mutation (bind, unbind, rebind, load, unload).
|
|
281
|
-
*/
|
|
282
|
-
invalidateDevValidationState() {
|
|
283
|
-
this.devValidationRan = false;
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Runs scope validation at most once per registry epoch when `NODE_ENV` is not `"production"`.
|
|
287
|
-
* Guards against repeated validation on successive resolves without intervening mutations.
|
|
288
|
-
*/
|
|
289
|
-
maybeRunDevValidationOnce() {
|
|
290
|
-
if (!isDevelopmentOrTestEnvironment()) return;
|
|
291
|
-
if (this.devValidationRan) return;
|
|
292
|
-
this.devValidationRan = true;
|
|
293
|
-
this.validate();
|
|
294
|
-
}
|
|
295
|
-
/**
|
|
296
|
-
* Validates static dependency scope rules: a singleton must not depend on scoped/transient
|
|
297
|
-
* class/factory/alias targets. Constant dependencies are always allowed.
|
|
298
|
-
*/
|
|
299
330
|
validate() {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
return this.createInspector().getSnapshot();
|
|
331
|
+
this._assertNotDisposed();
|
|
332
|
+
const reader = this._getMetadataReader();
|
|
333
|
+
const allBindings = this._registry.allBindings();
|
|
334
|
+
for (const binding of allBindings) {
|
|
335
|
+
if (binding.kind === "alias" || binding.kind === "constant" || binding.kind === "dynamic" || binding.kind === "dynamic-async") continue;
|
|
336
|
+
const scope = effectiveBindingScope(binding);
|
|
337
|
+
if (scope !== "singleton") continue;
|
|
338
|
+
const deps = this._getDepsForBinding(binding, reader);
|
|
339
|
+
for (const dep of deps) this._validateDep(tokenName(binding.token), scope, dep, [tokenName(binding.token)], reader);
|
|
340
|
+
}
|
|
311
341
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
loadAutoRegistered() {
|
|
323
|
-
const entries = getAutoRegistered();
|
|
324
|
-
let count = 0;
|
|
325
|
-
for (const { implementationClass, scope } of entries) {
|
|
326
|
-
const builder = this.bind(implementationClass).toSelf();
|
|
327
|
-
switch (scope) {
|
|
328
|
-
case "singleton":
|
|
329
|
-
builder.singleton();
|
|
330
|
-
break;
|
|
331
|
-
case "scoped":
|
|
332
|
-
builder.scoped();
|
|
333
|
-
break;
|
|
334
|
-
default: builder.transient();
|
|
342
|
+
_getDepsForBinding(binding, reader) {
|
|
343
|
+
const result = [];
|
|
344
|
+
if (binding.kind === "class") {
|
|
345
|
+
const meta = reader.getConstructorMetadata(binding.target);
|
|
346
|
+
if (meta !== void 0) for (const param of meta.params) {
|
|
347
|
+
const depBindings = this._registry.getAll(param.token);
|
|
348
|
+
for (const db of depBindings) if (db.kind !== "alias") result.push({
|
|
349
|
+
token: param.token,
|
|
350
|
+
scope: effectiveBindingScope(db)
|
|
351
|
+
});
|
|
335
352
|
}
|
|
336
|
-
|
|
353
|
+
} else if (binding.kind === "resolved" || binding.kind === "resolved-async") for (const dep of binding.deps) {
|
|
354
|
+
const depBindings = this._registry.getAll(dep.token);
|
|
355
|
+
for (const db of depBindings) if (db.kind !== "alias") result.push({
|
|
356
|
+
token: dep.token,
|
|
357
|
+
scope: effectiveBindingScope(db)
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
return result;
|
|
361
|
+
}
|
|
362
|
+
_validateDep(consumerToken, consumerScope, dep, path, _reader) {
|
|
363
|
+
if (consumerScope === "singleton") {
|
|
364
|
+
if (dep.scope === "scoped" || dep.scope === "transient") throw new ScopeViolationError({
|
|
365
|
+
consumerToken,
|
|
366
|
+
consumerScope,
|
|
367
|
+
dependencyToken: tokenName(dep.token),
|
|
368
|
+
dependencyScope: dep.scope,
|
|
369
|
+
path
|
|
370
|
+
});
|
|
337
371
|
}
|
|
338
|
-
return count;
|
|
339
372
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
collectAllRegistryKeys: () => this.collectAllRegistryKeysInHierarchy(),
|
|
349
|
-
lookupBindings: (token) => this.lookupBindings(token),
|
|
350
|
-
isBindingCached: (binding) => this.ownScopeManager.isBindingCached(binding),
|
|
351
|
-
metadataReader: this.metadataReader
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
* Collects the union of all registry keys from this container and every ancestor.
|
|
356
|
-
* Deduplicates by reference equality (tokens are objects).
|
|
357
|
-
*/
|
|
358
|
-
collectAllRegistryKeysInHierarchy() {
|
|
359
|
-
const keys = /* @__PURE__ */ new Set();
|
|
360
|
-
this.accumulateRegistryKeysFromHierarchy(keys, this);
|
|
361
|
-
return [...keys];
|
|
362
|
-
}
|
|
363
|
-
/**
|
|
364
|
-
* Recursive helper: walks the parent chain bottom-up, adding each level's registry keys.
|
|
365
|
-
*/
|
|
366
|
-
accumulateRegistryKeysFromHierarchy(keys, container) {
|
|
367
|
-
if (container === void 0) return;
|
|
368
|
-
for (const entry of container.ownRegistry.listEntries()) keys.add(entry.key);
|
|
369
|
-
this.accumulateRegistryKeysFromHierarchy(keys, container.parent);
|
|
370
|
-
}
|
|
371
|
-
/**
|
|
372
|
-
* Child inherits parent bindings via lookup fallback and shares singleton instances,
|
|
373
|
-
* but receives an isolated scoped cache.
|
|
374
|
-
*/
|
|
375
|
-
createChild() {
|
|
376
|
-
const childRegistry = new BindingRegistry();
|
|
377
|
-
const childScope = this.ownScopeManager.createChildScope();
|
|
378
|
-
const holder = { current: void 0 };
|
|
379
|
-
const resolver = new DependencyResolver({
|
|
380
|
-
lookup: (token) => {
|
|
381
|
-
const current = holder.current;
|
|
382
|
-
if (current === void 0) throw new InternalError("child container is not initialized");
|
|
383
|
-
return current.lookupBindings(token);
|
|
384
|
-
},
|
|
385
|
-
scopeManager: childScope,
|
|
386
|
-
metadataReader: this.metadataReader
|
|
387
|
-
});
|
|
388
|
-
const child = new DefaultContainer(childRegistry, childScope, this, resolver, this.metadataReader);
|
|
389
|
-
holder.current = child;
|
|
390
|
-
return child;
|
|
391
|
-
}
|
|
392
|
-
/**
|
|
393
|
-
* Lookup helper with parent fallback: own bindings take precedence over parent bindings.
|
|
394
|
-
*/
|
|
373
|
+
has(token, hint) {
|
|
374
|
+
this._assertNotDisposed();
|
|
375
|
+
return this._inspector.has(token, hint, () => this._parent?.has(token, hint) ?? false);
|
|
376
|
+
}
|
|
377
|
+
hasOwn(token, hint) {
|
|
378
|
+
this._assertNotDisposed();
|
|
379
|
+
return this._inspector.hasOwn(token, hint);
|
|
380
|
+
}
|
|
395
381
|
lookupBindings(token) {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
return this.parent?.lookupBindings(token);
|
|
382
|
+
this._assertNotDisposed();
|
|
383
|
+
return this._inspector.lookupBindings(token);
|
|
399
384
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
async dispose() {
|
|
404
|
-
await this.ownScopeManager.disposeAsync();
|
|
385
|
+
inspect() {
|
|
386
|
+
this._assertNotDisposed();
|
|
387
|
+
return this._inspector.inspect();
|
|
405
388
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
[Symbol.asyncDispose]() {
|
|
410
|
-
return this.dispose();
|
|
389
|
+
generateDependencyGraph(options) {
|
|
390
|
+
this._assertNotDisposed();
|
|
391
|
+
return buildDependencyGraph(this._registry, this._getMetadataReader(), options, this._parent?._registry);
|
|
411
392
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
* {@link loadedModules} for {@link unload}.
|
|
415
|
-
*
|
|
416
|
-
* - **Last-wins** (replaces every binding for that token): `bind(token).to*(...)` with no
|
|
417
|
-
* `whenNamed` / `whenTagged` / `when` **before** the `to*()` call.
|
|
418
|
-
* - **Multi-binding** (append): call `whenNamed`, `whenTagged`, and/or `when` **before** `to*()`
|
|
419
|
-
* so the disambiguator exists at registration time — supports `resolveAll` and per-binding
|
|
420
|
-
* hints in {@link Container.initializeAsync}.
|
|
421
|
-
*/
|
|
422
|
-
bindForModule(owner) {
|
|
423
|
-
return (token) => new BindingBuilder(token, owner.name, {
|
|
424
|
-
register: (built) => {
|
|
425
|
-
this.invalidateDevValidationState();
|
|
426
|
-
if (moduleBindingUsesMultiSlot(built)) this.ownRegistry.add(token, built);
|
|
427
|
-
else this.ownRegistry.replaceKeyLastWins(token, built, (removed) => {
|
|
428
|
-
this.ownScopeManager.releaseBinding(removed);
|
|
429
|
-
});
|
|
430
|
-
this.recordBindingForModule(owner, built.id);
|
|
431
|
-
},
|
|
432
|
-
update: (built) => {
|
|
433
|
-
this.invalidateDevValidationState();
|
|
434
|
-
this.ownRegistry.replaceById(built.id, built);
|
|
435
|
-
}
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
/**
|
|
439
|
-
* Appends a binding ID to the tracking list for `owner` so {@link unload} can remove it later.
|
|
440
|
-
*/
|
|
441
|
-
recordBindingForModule(owner, id) {
|
|
442
|
-
const list = this.loadedModules.get(owner);
|
|
443
|
-
if (list === void 0) {
|
|
444
|
-
this.loadedModules.set(owner, [id]);
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
list.push(id);
|
|
393
|
+
_assertNotDisposed() {
|
|
394
|
+
if (this._disposed) throw new DisposedContainerError();
|
|
448
395
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
396
|
+
};
|
|
397
|
+
var BindToBuilderImpl = class {
|
|
398
|
+
constructor(_token, _commit) {
|
|
399
|
+
this._token = _token;
|
|
400
|
+
this._commit = _commit;
|
|
401
|
+
}
|
|
402
|
+
to(type) {
|
|
403
|
+
return new BindingBuilderImpl(this._token, {
|
|
404
|
+
kind: "class",
|
|
405
|
+
target: type,
|
|
406
|
+
scope: "transient"
|
|
407
|
+
}, this._commit);
|
|
408
|
+
}
|
|
409
|
+
toSelf() {
|
|
410
|
+
if (typeof this._token !== "function") throw new Error("toSelf() requires token to be a Constructor");
|
|
411
|
+
return new BindingBuilderImpl(this._token, {
|
|
412
|
+
kind: "class",
|
|
413
|
+
target: this._token,
|
|
414
|
+
scope: "transient"
|
|
415
|
+
}, this._commit);
|
|
416
|
+
}
|
|
417
|
+
toConstantValue(value) {
|
|
418
|
+
return new ConstantBindingBuilderImpl(this._token, value, this._commit);
|
|
419
|
+
}
|
|
420
|
+
toDynamic(factory) {
|
|
421
|
+
return new BindingBuilderImpl(this._token, {
|
|
422
|
+
kind: "dynamic",
|
|
423
|
+
factory,
|
|
424
|
+
scope: "transient"
|
|
425
|
+
}, this._commit);
|
|
426
|
+
}
|
|
427
|
+
toDynamicAsync(factory) {
|
|
428
|
+
return new BindingBuilderImpl(this._token, {
|
|
429
|
+
kind: "dynamic-async",
|
|
430
|
+
factory,
|
|
431
|
+
scope: "transient"
|
|
432
|
+
}, this._commit);
|
|
433
|
+
}
|
|
434
|
+
toResolved(factory, deps) {
|
|
435
|
+
const normalizedDeps = deps.map((d) => normalizeToDescriptor(d));
|
|
436
|
+
return new BindingBuilderImpl(this._token, {
|
|
437
|
+
kind: "resolved",
|
|
438
|
+
factory,
|
|
439
|
+
deps: normalizedDeps,
|
|
440
|
+
scope: "transient"
|
|
441
|
+
}, this._commit);
|
|
442
|
+
}
|
|
443
|
+
toResolvedAsync(factory, deps) {
|
|
444
|
+
const normalizedDeps = deps.map((d) => normalizeToDescriptor(d));
|
|
445
|
+
return new BindingBuilderImpl(this._token, {
|
|
446
|
+
kind: "resolved-async",
|
|
447
|
+
factory,
|
|
448
|
+
deps: normalizedDeps,
|
|
449
|
+
scope: "transient"
|
|
450
|
+
}, this._commit);
|
|
451
|
+
}
|
|
452
|
+
toAlias(target) {
|
|
453
|
+
return new AliasBindingBuilderImpl(this._token, target, this._commit);
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
var BindingBuilderImpl = class {
|
|
457
|
+
_slot;
|
|
458
|
+
_predicate;
|
|
459
|
+
_committed;
|
|
460
|
+
constructor(_token, _partial, _commit) {
|
|
461
|
+
this._token = _token;
|
|
462
|
+
this._partial = _partial;
|
|
463
|
+
this._commit = _commit;
|
|
464
|
+
this._slot = {
|
|
465
|
+
...DEFAULT_SLOT,
|
|
466
|
+
tags: []
|
|
462
467
|
};
|
|
468
|
+
this._doCommit();
|
|
469
|
+
}
|
|
470
|
+
_doCommit() {
|
|
471
|
+
const previousId = this._committed;
|
|
472
|
+
const binding = {
|
|
473
|
+
...this._partial,
|
|
474
|
+
id: generateBindingId(),
|
|
475
|
+
token: this._token,
|
|
476
|
+
slot: this._slot,
|
|
477
|
+
predicate: this._predicate
|
|
478
|
+
};
|
|
479
|
+
this._committed = this._commit(binding, previousId);
|
|
463
480
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
import: (...deps) => {
|
|
474
|
-
for (const dep of deps) if (dep instanceof AsyncModule) pendingImports.push(this.ensureAsyncModuleLoaded(dep));
|
|
475
|
-
else this.ensureSyncModuleLoaded(dep);
|
|
476
|
-
},
|
|
477
|
-
bind: this.bindForModule(module)
|
|
478
|
-
},
|
|
479
|
-
awaitImports: async () => {
|
|
480
|
-
if (pendingImports.length === 0) return;
|
|
481
|
-
await Promise.all(pendingImports);
|
|
482
|
-
}
|
|
481
|
+
when(predicate) {
|
|
482
|
+
this._predicate = predicate;
|
|
483
|
+
this._doCommit();
|
|
484
|
+
return this;
|
|
485
|
+
}
|
|
486
|
+
whenNamed(name) {
|
|
487
|
+
this._slot = {
|
|
488
|
+
...this._slot,
|
|
489
|
+
name
|
|
483
490
|
};
|
|
491
|
+
this._doCommit();
|
|
492
|
+
return this;
|
|
493
|
+
}
|
|
494
|
+
whenTagged(tag, value) {
|
|
495
|
+
const existing = [...this._slot.tags];
|
|
496
|
+
const idx = existing.findIndex(([k]) => k === tag);
|
|
497
|
+
if (idx !== -1) existing[idx] = [tag, value];
|
|
498
|
+
else existing.push([tag, value]);
|
|
499
|
+
this._slot = {
|
|
500
|
+
...this._slot,
|
|
501
|
+
tags: existing
|
|
502
|
+
};
|
|
503
|
+
this._doCommit();
|
|
504
|
+
return this;
|
|
505
|
+
}
|
|
506
|
+
whenDefault() {
|
|
507
|
+
return this;
|
|
508
|
+
}
|
|
509
|
+
singleton() {
|
|
510
|
+
const previousId = this._committed;
|
|
511
|
+
this._committed = void 0;
|
|
512
|
+
return new ScopeBuilderImpl(this._token, {
|
|
513
|
+
...this._partial,
|
|
514
|
+
scope: "singleton"
|
|
515
|
+
}, this._slot, this._predicate, this._commit, "singleton", previousId);
|
|
516
|
+
}
|
|
517
|
+
transient() {
|
|
518
|
+
const previousId = this._committed;
|
|
519
|
+
this._committed = void 0;
|
|
520
|
+
return new ScopeBuilderImpl(this._token, {
|
|
521
|
+
...this._partial,
|
|
522
|
+
scope: "transient"
|
|
523
|
+
}, this._slot, this._predicate, this._commit, "transient", previousId);
|
|
524
|
+
}
|
|
525
|
+
scoped() {
|
|
526
|
+
const previousId = this._committed;
|
|
527
|
+
this._committed = void 0;
|
|
528
|
+
return new ScopeBuilderImpl(this._token, {
|
|
529
|
+
...this._partial,
|
|
530
|
+
scope: "scoped"
|
|
531
|
+
}, this._slot, this._predicate, this._commit, "scoped", previousId);
|
|
532
|
+
}
|
|
533
|
+
id() {
|
|
534
|
+
return this._committed;
|
|
484
535
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
this.
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
536
|
+
};
|
|
537
|
+
var ScopeBuilderImpl = class {
|
|
538
|
+
_onActivation;
|
|
539
|
+
_onDeactivation;
|
|
540
|
+
_committed;
|
|
541
|
+
constructor(_token, _partial, _slot, _predicate, _commit, _scope, _initialPreviousId) {
|
|
542
|
+
this._token = _token;
|
|
543
|
+
this._partial = _partial;
|
|
544
|
+
this._slot = _slot;
|
|
545
|
+
this._predicate = _predicate;
|
|
546
|
+
this._commit = _commit;
|
|
547
|
+
this._scope = _scope;
|
|
548
|
+
this._initialPreviousId = _initialPreviousId;
|
|
549
|
+
this._doCommit();
|
|
550
|
+
}
|
|
551
|
+
_doCommit() {
|
|
552
|
+
const previousId = this._committed ?? this._initialPreviousId;
|
|
553
|
+
const binding = {
|
|
554
|
+
...this._partial,
|
|
555
|
+
id: generateBindingId(),
|
|
556
|
+
token: this._token,
|
|
557
|
+
slot: this._slot,
|
|
558
|
+
predicate: this._predicate,
|
|
559
|
+
onActivation: this._onActivation,
|
|
560
|
+
onDeactivation: this._onDeactivation
|
|
561
|
+
};
|
|
562
|
+
this._committed = this._commit(binding, previousId);
|
|
501
563
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
this.
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
564
|
+
onActivation(fn) {
|
|
565
|
+
this._onActivation = fn;
|
|
566
|
+
this._doCommit();
|
|
567
|
+
return this;
|
|
568
|
+
}
|
|
569
|
+
onDeactivation(fn) {
|
|
570
|
+
this._onDeactivation = fn;
|
|
571
|
+
this._doCommit();
|
|
572
|
+
return this;
|
|
573
|
+
}
|
|
574
|
+
id() {
|
|
575
|
+
return this._committed;
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
var ConstantBindingBuilderImpl = class {
|
|
579
|
+
_slot;
|
|
580
|
+
_predicate;
|
|
581
|
+
_onActivation;
|
|
582
|
+
_onDeactivation;
|
|
583
|
+
_committed;
|
|
584
|
+
constructor(_token, _value, _commit) {
|
|
585
|
+
this._token = _token;
|
|
586
|
+
this._value = _value;
|
|
587
|
+
this._commit = _commit;
|
|
588
|
+
this._slot = {
|
|
589
|
+
...DEFAULT_SLOT,
|
|
590
|
+
tags: []
|
|
591
|
+
};
|
|
592
|
+
this._doCommit();
|
|
593
|
+
}
|
|
594
|
+
_doCommit() {
|
|
595
|
+
const previousId = this._committed;
|
|
596
|
+
const binding = {
|
|
597
|
+
kind: "constant",
|
|
598
|
+
id: generateBindingId(),
|
|
599
|
+
token: this._token,
|
|
600
|
+
slot: this._slot,
|
|
601
|
+
predicate: this._predicate,
|
|
602
|
+
value: this._value,
|
|
603
|
+
scope: "singleton",
|
|
604
|
+
onActivation: this._onActivation,
|
|
605
|
+
onDeactivation: this._onDeactivation
|
|
606
|
+
};
|
|
607
|
+
this._committed = this._commit(binding, previousId);
|
|
608
|
+
}
|
|
609
|
+
when(predicate) {
|
|
610
|
+
this._predicate = predicate;
|
|
611
|
+
this._doCommit();
|
|
612
|
+
return this;
|
|
613
|
+
}
|
|
614
|
+
whenNamed(name) {
|
|
615
|
+
this._slot = {
|
|
616
|
+
...this._slot,
|
|
617
|
+
name
|
|
618
|
+
};
|
|
619
|
+
this._doCommit();
|
|
620
|
+
return this;
|
|
621
|
+
}
|
|
622
|
+
whenTagged(tag, value) {
|
|
623
|
+
const existing = [...this._slot.tags];
|
|
624
|
+
const idx = existing.findIndex(([k]) => k === tag);
|
|
625
|
+
if (idx !== -1) existing[idx] = [tag, value];
|
|
626
|
+
else existing.push([tag, value]);
|
|
627
|
+
this._slot = {
|
|
628
|
+
...this._slot,
|
|
629
|
+
tags: existing
|
|
630
|
+
};
|
|
631
|
+
this._doCommit();
|
|
632
|
+
return this;
|
|
633
|
+
}
|
|
634
|
+
whenDefault() {
|
|
635
|
+
return this;
|
|
636
|
+
}
|
|
637
|
+
onActivation(fn) {
|
|
638
|
+
this._onActivation = fn;
|
|
639
|
+
this._doCommit();
|
|
640
|
+
return this;
|
|
641
|
+
}
|
|
642
|
+
onDeactivation(fn) {
|
|
643
|
+
this._onDeactivation = fn;
|
|
644
|
+
this._doCommit();
|
|
645
|
+
return this;
|
|
646
|
+
}
|
|
647
|
+
id() {
|
|
648
|
+
return this._committed;
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
var AliasBindingBuilderImpl = class {
|
|
652
|
+
_slot;
|
|
653
|
+
_predicate;
|
|
654
|
+
_committed;
|
|
655
|
+
constructor(_token, _target, _commit) {
|
|
656
|
+
this._token = _token;
|
|
657
|
+
this._target = _target;
|
|
658
|
+
this._commit = _commit;
|
|
659
|
+
this._slot = {
|
|
660
|
+
...DEFAULT_SLOT,
|
|
661
|
+
tags: []
|
|
662
|
+
};
|
|
663
|
+
this._doCommit();
|
|
664
|
+
}
|
|
665
|
+
_doCommit() {
|
|
666
|
+
const previousId = this._committed;
|
|
667
|
+
const binding = {
|
|
668
|
+
kind: "alias",
|
|
669
|
+
id: generateBindingId(),
|
|
670
|
+
token: this._token,
|
|
671
|
+
slot: this._slot,
|
|
672
|
+
predicate: this._predicate,
|
|
673
|
+
target: this._target
|
|
674
|
+
};
|
|
675
|
+
this._committed = this._commit(binding, previousId);
|
|
676
|
+
}
|
|
677
|
+
when(predicate) {
|
|
678
|
+
this._predicate = predicate;
|
|
679
|
+
this._doCommit();
|
|
680
|
+
return this;
|
|
681
|
+
}
|
|
682
|
+
whenNamed(name) {
|
|
683
|
+
this._slot = {
|
|
684
|
+
...this._slot,
|
|
685
|
+
name
|
|
686
|
+
};
|
|
687
|
+
this._doCommit();
|
|
688
|
+
return this;
|
|
689
|
+
}
|
|
690
|
+
whenTagged(tag, value) {
|
|
691
|
+
const existing = [...this._slot.tags];
|
|
692
|
+
const idx = existing.findIndex(([k]) => k === tag);
|
|
693
|
+
if (idx !== -1) existing[idx] = [tag, value];
|
|
694
|
+
else existing.push([tag, value]);
|
|
695
|
+
this._slot = {
|
|
696
|
+
...this._slot,
|
|
697
|
+
tags: existing
|
|
698
|
+
};
|
|
699
|
+
this._doCommit();
|
|
700
|
+
return this;
|
|
701
|
+
}
|
|
702
|
+
whenDefault() {
|
|
703
|
+
return this;
|
|
704
|
+
}
|
|
705
|
+
id() {
|
|
706
|
+
return this._committed;
|
|
518
707
|
}
|
|
519
708
|
};
|
|
520
|
-
|
|
521
|
-
(
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
function fromModules(...modules) {
|
|
527
|
-
const container = DefaultContainer.create();
|
|
709
|
+
const Container = {
|
|
710
|
+
create() {
|
|
711
|
+
return new DefaultContainer();
|
|
712
|
+
},
|
|
713
|
+
fromModules(...modules) {
|
|
714
|
+
const container = new DefaultContainer();
|
|
528
715
|
container.load(...modules);
|
|
529
716
|
return container;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
const container = DefaultContainer.create();
|
|
717
|
+
},
|
|
718
|
+
async fromModulesAsync(...modules) {
|
|
719
|
+
const container = new DefaultContainer();
|
|
534
720
|
await container.loadAsync(...modules);
|
|
535
721
|
return container;
|
|
536
722
|
}
|
|
537
|
-
|
|
538
|
-
})(Container || (Container = {}));
|
|
723
|
+
};
|
|
539
724
|
//#endregion
|
|
540
725
|
export { Container };
|