@aponiajs/core 0.3.16 → 0.3.18
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/dist/index.mjs +63 -25
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -4,10 +4,15 @@ var ModuleGraph = class {
|
|
|
4
4
|
root;
|
|
5
5
|
modules;
|
|
6
6
|
#moduleSet;
|
|
7
|
+
#providersByModule;
|
|
8
|
+
#exportsByModule;
|
|
9
|
+
#locationsByModule = /* @__PURE__ */ new Map();
|
|
7
10
|
constructor(root, modules) {
|
|
8
11
|
this.root = root;
|
|
9
12
|
this.modules = Object.freeze([...modules]);
|
|
10
13
|
this.#moduleSet = new Set(modules);
|
|
14
|
+
this.#providersByModule = new Map(modules.map((module) => [module, new Map(module.providers.map((provider) => [provider.provide, provider]))]));
|
|
15
|
+
this.#exportsByModule = new Map(modules.map((module) => [module, new Set(module.exports)]));
|
|
11
16
|
}
|
|
12
17
|
inspect() {
|
|
13
18
|
return Object.freeze({
|
|
@@ -26,31 +31,54 @@ var ModuleGraph = class {
|
|
|
26
31
|
module: module.id,
|
|
27
32
|
token: tokenName(token)
|
|
28
33
|
});
|
|
29
|
-
|
|
34
|
+
const cached = this.#locationsByModule.get(module)?.get(token);
|
|
35
|
+
if (cached) return cached;
|
|
36
|
+
const location = this.#locate(module, token, /* @__PURE__ */ new Set());
|
|
37
|
+
this.#cacheLocation(module, token, location);
|
|
38
|
+
return location;
|
|
30
39
|
}
|
|
31
40
|
#locate(module, token, visited) {
|
|
32
|
-
const
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
const cached = this.#locationsByModule.get(module)?.get(token);
|
|
42
|
+
if (cached) return cached;
|
|
43
|
+
const own = this.#providersByModule.get(module)?.get(token);
|
|
44
|
+
if (own) {
|
|
45
|
+
const location = Object.freeze({
|
|
46
|
+
module,
|
|
47
|
+
provider: own
|
|
48
|
+
});
|
|
49
|
+
this.#cacheLocation(module, token, location);
|
|
50
|
+
return location;
|
|
51
|
+
}
|
|
37
52
|
if (visited.has(module)) throw missingProvider(module, token);
|
|
38
53
|
visited.add(module);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
54
|
+
try {
|
|
55
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
56
|
+
for (const imported of module.imports) {
|
|
57
|
+
if (!this.#exportsByModule.get(imported)?.has(token)) continue;
|
|
58
|
+
const location = this.#locate(imported, token, visited);
|
|
59
|
+
candidates.set(location.module, location);
|
|
60
|
+
}
|
|
61
|
+
if (candidates.size === 0) throw missingProvider(module, token);
|
|
62
|
+
if (candidates.size > 1) throw new AponiaError("AMBIGUOUS_PROVIDER", `Token "${tokenName(token)}" is exported by multiple imports of module "${module.id}".`, {
|
|
63
|
+
module: module.id,
|
|
64
|
+
token: tokenName(token),
|
|
65
|
+
candidates: [...candidates.values()].map((item) => item.module.id)
|
|
66
|
+
});
|
|
67
|
+
const location = candidates.values().next().value;
|
|
68
|
+
if (!location) throw missingProvider(module, token);
|
|
69
|
+
this.#cacheLocation(module, token, location);
|
|
70
|
+
return location;
|
|
71
|
+
} finally {
|
|
72
|
+
visited.delete(module);
|
|
44
73
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return location;
|
|
74
|
+
}
|
|
75
|
+
#cacheLocation(module, token, location) {
|
|
76
|
+
let moduleLocations = this.#locationsByModule.get(module);
|
|
77
|
+
if (!moduleLocations) {
|
|
78
|
+
moduleLocations = /* @__PURE__ */ new Map();
|
|
79
|
+
this.#locationsByModule.set(module, moduleLocations);
|
|
80
|
+
}
|
|
81
|
+
moduleLocations.set(token, location);
|
|
54
82
|
}
|
|
55
83
|
};
|
|
56
84
|
function compileModuleGraph(root) {
|
|
@@ -154,15 +182,17 @@ var AponiaContainer = class {
|
|
|
154
182
|
});
|
|
155
183
|
}
|
|
156
184
|
instantiateController(module, controller) {
|
|
157
|
-
|
|
185
|
+
const moduleControllers = this.#controllers.get(module);
|
|
186
|
+
if (moduleControllers?.has(controller)) return moduleControllers.get(controller);
|
|
158
187
|
const dependencies = controller.inject.map((dependency) => this.#resolve(this.graph.locate(module, dependency)));
|
|
159
188
|
const instance = Reflect.construct(controller.useClass, dependencies);
|
|
160
|
-
this.#controllers.set(controller, instance);
|
|
189
|
+
this.#moduleCache(this.#controllers, module).set(controller, instance);
|
|
161
190
|
return instance;
|
|
162
191
|
}
|
|
163
192
|
#resolve(location) {
|
|
164
|
-
|
|
165
|
-
|
|
193
|
+
const moduleInstances = this.#instances.get(location.module);
|
|
194
|
+
if (moduleInstances?.has(location.provider)) return moduleInstances.get(location.provider);
|
|
195
|
+
const cycleIndex = this.#resolving.findIndex((item) => item.module === location.module && item.provider === location.provider);
|
|
166
196
|
if (cycleIndex >= 0) {
|
|
167
197
|
const cycle = [...this.#resolving.slice(cycleIndex), location].map((item) => `${item.module.id}:${tokenName(item.provider.provide)}`);
|
|
168
198
|
throw new AponiaError("PROVIDER_CYCLE", `Provider dependency cycle detected: ${cycle.join(" -> ")}.`, { cycle });
|
|
@@ -171,12 +201,20 @@ var AponiaContainer = class {
|
|
|
171
201
|
try {
|
|
172
202
|
const dependencies = providerDependencies(location.provider).map((dependency) => this.#resolve(this.graph.locate(location.module, dependency)));
|
|
173
203
|
const instance = instantiate(location.provider, dependencies);
|
|
174
|
-
this.#instances.set(location.provider, instance);
|
|
204
|
+
this.#moduleCache(this.#instances, location.module).set(location.provider, instance);
|
|
175
205
|
return instance;
|
|
176
206
|
} finally {
|
|
177
207
|
this.#resolving.pop();
|
|
178
208
|
}
|
|
179
209
|
}
|
|
210
|
+
#moduleCache(cache, module) {
|
|
211
|
+
let moduleCache = cache.get(module);
|
|
212
|
+
if (!moduleCache) {
|
|
213
|
+
moduleCache = /* @__PURE__ */ new Map();
|
|
214
|
+
cache.set(module, moduleCache);
|
|
215
|
+
}
|
|
216
|
+
return moduleCache;
|
|
217
|
+
}
|
|
180
218
|
};
|
|
181
219
|
function createContainer(root) {
|
|
182
220
|
return new AponiaContainer(compileModuleGraph(root));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aponiajs/core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.18",
|
|
4
4
|
"description": "Module graph and dependency injection runtime for Aponia.",
|
|
5
5
|
"homepage": "https://github.com/aponiajs/aponiajs#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -33,6 +33,6 @@
|
|
|
33
33
|
"prepublishOnly": "bun run build"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@aponiajs/common": "0.3.
|
|
36
|
+
"@aponiajs/common": "0.3.18"
|
|
37
37
|
}
|
|
38
38
|
}
|