@codefast/di 0.3.14-canary.0 → 0.3.14-canary.2
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 +28 -0
- package/README.md +54 -29
- 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 -327
- package/dist/binding.mjs +19 -324
- 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 +44 -128
- package/dist/container.mjs +664 -433
- 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 +69 -188
- package/dist/errors.mjs +92 -219
- package/dist/graph-adapters/cytoscape.d.mts +24 -0
- package/dist/graph-adapters/cytoscape.mjs +23 -0
- package/dist/graph-adapters/dot.d.mts +6 -0
- package/dist/graph-adapters/dot.mjs +17 -0
- package/dist/graph-adapters/reactflow.d.mts +29 -0
- package/dist/graph-adapters/reactflow.mjs +29 -0
- package/dist/graph-adapters/types.d.mts +2 -0
- package/dist/graph-adapters/types.mjs +1 -0
- package/dist/index.d.mts +16 -9
- package/dist/index.mjs +8 -5
- package/dist/inspector.d.mts +34 -95
- package/dist/inspector.mjs +57 -256
- 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 +22 -71
- 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 -84
- 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 -102
- package/dist/scope.mjs +37 -192
- 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 +52 -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,494 +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
|
-
this.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
this.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const ownRegistry = new BindingRegistry();
|
|
69
|
-
const ownScopeManager = ScopeManager.createRoot();
|
|
70
|
-
const metadataReader = new SymbolMetadataReader();
|
|
71
|
-
const holder = { current: void 0 };
|
|
72
|
-
const container = new DefaultContainer(ownRegistry, ownScopeManager, void 0, new DependencyResolver({
|
|
73
|
-
lookup: (token) => {
|
|
74
|
-
const current = holder.current;
|
|
75
|
-
if (current === void 0) throw new InternalError("container is not initialized");
|
|
76
|
-
return current.lookupBindings(token);
|
|
77
|
-
},
|
|
78
|
-
scopeManager: ownScopeManager,
|
|
79
|
-
metadataReader
|
|
80
|
-
}), metadataReader);
|
|
81
|
-
holder.current = container;
|
|
82
|
-
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;
|
|
83
49
|
}
|
|
84
|
-
/**
|
|
85
|
-
* Starts a fluent {@link BindingBuilder} for the given token or constructor.
|
|
86
|
-
* The binding is registered into this container's registry immediately when a
|
|
87
|
-
* `to*()` strategy method is called on the returned builder.
|
|
88
|
-
*/
|
|
89
50
|
bind(token) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
+
}
|
|
98
66
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (hint.tag !== void 0) {
|
|
108
|
-
const tag = hint.tag;
|
|
109
|
-
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);
|
|
110
75
|
}
|
|
111
|
-
return
|
|
112
|
-
}
|
|
76
|
+
return b.id;
|
|
77
|
+
};
|
|
78
|
+
return new BindToBuilderImpl(token, commitBinding);
|
|
113
79
|
}
|
|
114
80
|
unbind(tokenOrId) {
|
|
115
|
-
this.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
+
}
|
|
120
93
|
}
|
|
121
|
-
const owned = this.ownRegistry.get(tokenOrId);
|
|
122
|
-
if (owned !== void 0) for (const binding of owned) this.ownScopeManager.releaseBinding(binding);
|
|
123
|
-
this.ownRegistry.remove(tokenOrId);
|
|
124
94
|
}
|
|
125
95
|
async unbindAsync(tokenOrId) {
|
|
126
|
-
this.
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
this.
|
|
130
|
-
|
|
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
|
+
}
|
|
105
|
+
}
|
|
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());
|
|
131
123
|
}
|
|
132
|
-
const owned = this.ownRegistry.get(tokenOrId);
|
|
133
|
-
if (owned !== void 0) for (const binding of owned) await this.ownScopeManager.releaseBindingAsync(binding);
|
|
134
|
-
this.ownRegistry.remove(tokenOrId);
|
|
135
124
|
}
|
|
136
125
|
rebind(token) {
|
|
137
|
-
this.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
this.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
+
}
|
|
148
138
|
load(...modules) {
|
|
149
|
-
this.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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);
|
|
153
154
|
}
|
|
154
|
-
this.maybeRunDevValidationOnce();
|
|
155
155
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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
|
+
}
|
|
159
168
|
async loadAsync(...modules) {
|
|
160
|
-
this.
|
|
161
|
-
for (const
|
|
162
|
-
|
|
163
|
-
|
|
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
|
+
};
|
|
164
205
|
}
|
|
165
206
|
unload(...modules) {
|
|
166
|
-
this.
|
|
167
|
-
for (const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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
|
+
}
|
|
173
226
|
}
|
|
174
|
-
|
|
175
|
-
}
|
|
227
|
+
} else this._moduleRefs.set(ref, count - 1);
|
|
176
228
|
}
|
|
177
229
|
async unloadAsync(...modules) {
|
|
178
|
-
this.
|
|
179
|
-
for (const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
+
}
|
|
185
249
|
}
|
|
186
|
-
|
|
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();
|
|
187
260
|
}
|
|
261
|
+
return entries.length;
|
|
188
262
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
* successful resolution also triggers a one-time static {@link validate} when not in production.
|
|
193
|
-
*/
|
|
194
|
-
resolve(key, hint) {
|
|
195
|
-
try {
|
|
196
|
-
return this.resolver.resolveRoot(key, hint);
|
|
197
|
-
} finally {
|
|
198
|
-
this.maybeRunDevValidationOnce();
|
|
199
|
-
}
|
|
263
|
+
onActivation(token, handler) {
|
|
264
|
+
this._assertNotDisposed();
|
|
265
|
+
this._lifecycle.registerActivation(token, handler);
|
|
200
266
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
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, [], []);
|
|
215
280
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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);
|
|
221
308
|
}
|
|
309
|
+
this._scope.clearAll();
|
|
310
|
+
}
|
|
311
|
+
[Symbol.asyncDispose]() {
|
|
312
|
+
return this.dispose();
|
|
313
|
+
}
|
|
314
|
+
[Symbol.dispose]() {
|
|
315
|
+
throw new SyncDisposalNotSupportedError();
|
|
222
316
|
}
|
|
223
|
-
/**
|
|
224
|
-
* Async variant of {@link resolveAll}: safe for multi-bindings that mix sync and async factories
|
|
225
|
-
* (spec §5.2).
|
|
226
|
-
*/
|
|
227
|
-
resolveAllAsync(key, hint) {
|
|
228
|
-
return this.resolver.resolveAllAsyncRoot(key, hint).finally(() => {
|
|
229
|
-
this.maybeRunDevValidationOnce();
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Eagerly resolves every registered `singleton` binding, including `async-dynamic` factories.
|
|
234
|
-
*/
|
|
235
317
|
async initializeAsync() {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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);
|
|
243
327
|
}
|
|
244
328
|
}
|
|
245
329
|
}
|
|
246
|
-
/**
|
|
247
|
-
* Marks the dev/test one-shot validation as stale so the next resolve or load triggers it again.
|
|
248
|
-
* Called on every registry mutation (bind, unbind, rebind, load, unload).
|
|
249
|
-
*/
|
|
250
|
-
invalidateDevValidationState() {
|
|
251
|
-
this.devValidationRan = false;
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* Runs scope validation at most once per registry epoch when `NODE_ENV` is not `"production"`.
|
|
255
|
-
* Guards against repeated validation on successive resolves without intervening mutations.
|
|
256
|
-
*/
|
|
257
|
-
maybeRunDevValidationOnce() {
|
|
258
|
-
if (!isDevelopmentOrTestEnvironment()) return;
|
|
259
|
-
if (this.devValidationRan) return;
|
|
260
|
-
this.devValidationRan = true;
|
|
261
|
-
this.validate();
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Validates static dependency scope rules: a singleton must not depend on scoped/transient
|
|
265
|
-
* class/factory/alias targets. Constant dependencies are always allowed.
|
|
266
|
-
*/
|
|
267
330
|
validate() {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
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
|
+
}
|
|
279
341
|
}
|
|
280
|
-
|
|
281
|
-
const
|
|
282
|
-
if (
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
switch (scope) {
|
|
291
|
-
case "singleton":
|
|
292
|
-
builder.singleton();
|
|
293
|
-
break;
|
|
294
|
-
case "scoped":
|
|
295
|
-
builder.scoped();
|
|
296
|
-
break;
|
|
297
|
-
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
|
+
});
|
|
298
352
|
}
|
|
299
|
-
|
|
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
|
+
});
|
|
300
371
|
}
|
|
301
|
-
return count;
|
|
302
372
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
return new ContainerInspector({
|
|
311
|
-
collectAllRegistryKeys: () => this.collectAllRegistryKeysInHierarchy(),
|
|
312
|
-
lookupBindings: (token) => this.lookupBindings(token),
|
|
313
|
-
isBindingCached: (binding) => this.ownScopeManager.isBindingCached(binding),
|
|
314
|
-
metadataReader: this.metadataReader
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* Collects the union of all registry keys from this container and every ancestor.
|
|
319
|
-
* Deduplicates by reference equality (tokens are objects).
|
|
320
|
-
*/
|
|
321
|
-
collectAllRegistryKeysInHierarchy() {
|
|
322
|
-
const keys = /* @__PURE__ */ new Set();
|
|
323
|
-
this.accumulateRegistryKeysFromHierarchy(keys, this);
|
|
324
|
-
return [...keys];
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Recursive helper: walks the parent chain bottom-up, adding each level's registry keys.
|
|
328
|
-
*/
|
|
329
|
-
accumulateRegistryKeysFromHierarchy(keys, container) {
|
|
330
|
-
if (container === void 0) return;
|
|
331
|
-
for (const entry of container.ownRegistry.listEntries()) keys.add(entry.key);
|
|
332
|
-
this.accumulateRegistryKeysFromHierarchy(keys, container.parent);
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Child inherits parent bindings via lookup fallback and shares singleton instances,
|
|
336
|
-
* but receives an isolated scoped cache.
|
|
337
|
-
*/
|
|
338
|
-
createChild() {
|
|
339
|
-
const childRegistry = new BindingRegistry();
|
|
340
|
-
const childScope = this.ownScopeManager.createChildScope();
|
|
341
|
-
const holder = { current: void 0 };
|
|
342
|
-
const resolver = new DependencyResolver({
|
|
343
|
-
lookup: (token) => {
|
|
344
|
-
const current = holder.current;
|
|
345
|
-
if (current === void 0) throw new InternalError("child container is not initialized");
|
|
346
|
-
return current.lookupBindings(token);
|
|
347
|
-
},
|
|
348
|
-
scopeManager: childScope,
|
|
349
|
-
metadataReader: this.metadataReader
|
|
350
|
-
});
|
|
351
|
-
const child = new DefaultContainer(childRegistry, childScope, this, resolver, this.metadataReader);
|
|
352
|
-
holder.current = child;
|
|
353
|
-
return child;
|
|
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);
|
|
354
380
|
}
|
|
355
381
|
lookupBindings(token) {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
return this.parent?.lookupBindings(token);
|
|
382
|
+
this._assertNotDisposed();
|
|
383
|
+
return this._inspector.lookupBindings(token);
|
|
359
384
|
}
|
|
360
|
-
|
|
361
|
-
|
|
385
|
+
inspect() {
|
|
386
|
+
this._assertNotDisposed();
|
|
387
|
+
return this._inspector.inspect();
|
|
362
388
|
}
|
|
363
|
-
|
|
364
|
-
|
|
389
|
+
generateDependencyGraph(options) {
|
|
390
|
+
this._assertNotDisposed();
|
|
391
|
+
return buildDependencyGraph(this._registry, this._getMetadataReader(), options, this._parent?._registry);
|
|
365
392
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
* {@link loadedModules} for {@link unload}.
|
|
369
|
-
*
|
|
370
|
-
* - **Last-wins** (replaces every binding for that token): `bind(token).to*(...)` with no
|
|
371
|
-
* `whenNamed` / `whenTagged` / `when` **before** the `to*()` call.
|
|
372
|
-
* - **Multi-binding** (append): call `whenNamed`, `whenTagged`, and/or `when` **before** `to*()`
|
|
373
|
-
* so the disambiguator exists at registration time — supports `resolveAll` and per-binding
|
|
374
|
-
* hints in {@link Container.initializeAsync}.
|
|
375
|
-
*/
|
|
376
|
-
bindForModule(owner) {
|
|
377
|
-
return (token) => new BindingBuilder(token, owner.name, {
|
|
378
|
-
register: (built) => {
|
|
379
|
-
this.invalidateDevValidationState();
|
|
380
|
-
if (moduleBindingUsesMultiSlot(built)) this.ownRegistry.add(token, built);
|
|
381
|
-
else this.ownRegistry.replaceKeyLastWins(token, built, (removed) => {
|
|
382
|
-
this.ownScopeManager.releaseBinding(removed);
|
|
383
|
-
});
|
|
384
|
-
this.recordBindingForModule(owner, built.id);
|
|
385
|
-
},
|
|
386
|
-
update: (built) => {
|
|
387
|
-
this.invalidateDevValidationState();
|
|
388
|
-
this.ownRegistry.replaceById(built.id, built);
|
|
389
|
-
}
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
/**
|
|
393
|
-
* Appends a binding ID to the tracking list for `owner` so {@link unload} can remove it later.
|
|
394
|
-
*/
|
|
395
|
-
recordBindingForModule(owner, id) {
|
|
396
|
-
const list = this.loadedModules.get(owner);
|
|
397
|
-
if (list === void 0) {
|
|
398
|
-
this.loadedModules.set(owner, [id]);
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
list.push(id);
|
|
393
|
+
_assertNotDisposed() {
|
|
394
|
+
if (this._disposed) throw new DisposedContainerError();
|
|
402
395
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
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: []
|
|
416
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);
|
|
417
480
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
import: (...deps) => {
|
|
428
|
-
for (const dep of deps) if (dep instanceof AsyncModule) pendingImports.push(this.ensureAsyncModuleLoaded(dep));
|
|
429
|
-
else this.ensureSyncModuleLoaded(dep);
|
|
430
|
-
},
|
|
431
|
-
bind: this.bindForModule(module)
|
|
432
|
-
},
|
|
433
|
-
awaitImports: async () => {
|
|
434
|
-
if (pendingImports.length === 0) return;
|
|
435
|
-
await Promise.all(pendingImports);
|
|
436
|
-
}
|
|
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
|
|
437
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;
|
|
438
535
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
this.
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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);
|
|
455
563
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
this.
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
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;
|
|
472
707
|
}
|
|
473
708
|
};
|
|
474
|
-
|
|
475
|
-
(
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
function fromModules(...modules) {
|
|
481
|
-
const container = DefaultContainer.create();
|
|
709
|
+
const Container = {
|
|
710
|
+
create() {
|
|
711
|
+
return new DefaultContainer();
|
|
712
|
+
},
|
|
713
|
+
fromModules(...modules) {
|
|
714
|
+
const container = new DefaultContainer();
|
|
482
715
|
container.load(...modules);
|
|
483
716
|
return container;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
const container = DefaultContainer.create();
|
|
717
|
+
},
|
|
718
|
+
async fromModulesAsync(...modules) {
|
|
719
|
+
const container = new DefaultContainer();
|
|
488
720
|
await container.loadAsync(...modules);
|
|
489
721
|
return container;
|
|
490
722
|
}
|
|
491
|
-
|
|
492
|
-
})(Container || (Container = {}));
|
|
723
|
+
};
|
|
493
724
|
//#endregion
|
|
494
725
|
export { Container };
|