@antelopejs/core 1.4.7 → 1.4.9
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/core/cli/commands/module/init.js +1 -1
- package/dist/core/cli/commands/module/init.js.map +1 -1
- package/dist/core/cli/commands/project/start.js +5 -1
- package/dist/core/cli/commands/project/start.js.map +1 -1
- package/dist/core/cli/full-cli.d.ts +3 -0
- package/dist/core/cli/full-cli.js +68 -0
- package/dist/core/cli/full-cli.js.map +1 -0
- package/dist/core/cli/index.d.ts +2 -3
- package/dist/core/cli/index.js +56 -69
- package/dist/core/cli/index.js.map +1 -1
- package/dist/core/cli/package-manager.d.ts +3 -1
- package/dist/core/cli/package-manager.js +50 -14
- package/dist/core/cli/package-manager.js.map +1 -1
- package/dist/core/cli/production-start.d.ts +10 -0
- package/dist/core/cli/production-start.js +87 -0
- package/dist/core/cli/production-start.js.map +1 -0
- package/dist/core/config/config-loader.js +5 -1
- package/dist/core/config/config-loader.js.map +1 -1
- package/dist/core/interface-registry.d.ts +6 -1
- package/dist/core/interface-registry.js +45 -2
- package/dist/core/interface-registry.js.map +1 -1
- package/dist/core/module-context.d.ts +7 -0
- package/dist/core/module-context.js +60 -0
- package/dist/core/module-context.js.map +1 -0
- package/dist/core/module-lifecycle.d.ts +5 -2
- package/dist/core/module-lifecycle.js +49 -32
- package/dist/core/module-lifecycle.js.map +1 -1
- package/dist/core/module-manager.d.ts +19 -2
- package/dist/core/module-manager.js +332 -127
- package/dist/core/module-manager.js.map +1 -1
- package/dist/core/module-registry.d.ts +1 -0
- package/dist/core/module-registry.js +3 -0
- package/dist/core/module-registry.js.map +1 -1
- package/dist/core/module-tracker.d.ts +1 -0
- package/dist/core/module-tracker.js +5 -1
- package/dist/core/module-tracker.js.map +1 -1
- package/dist/core/module.d.ts +2 -0
- package/dist/core/module.js +51 -28
- package/dist/core/module.js.map +1 -1
- package/dist/core/resolution/interface-resolution.js +7 -13
- package/dist/core/resolution/interface-resolution.js.map +1 -1
- package/dist/core/resolution/package-resolution.d.ts +14 -0
- package/dist/core/resolution/package-resolution.js +95 -0
- package/dist/core/resolution/package-resolution.js.map +1 -0
- package/dist/core/resolution/path-mapper.js +1 -1
- package/dist/core/resolution/path-mapper.js.map +1 -1
- package/dist/core/resolution/resolver-detour.d.ts +2 -2
- package/dist/core/resolution/resolver-detour.js +114 -22
- package/dist/core/resolution/resolver-detour.js.map +1 -1
- package/dist/core/resolution/resolver.d.ts +34 -0
- package/dist/core/resolution/resolver.js +233 -8
- package/dist/core/resolution/resolver.js.map +1 -1
- package/dist/core/runtime/dev-server-registry.js +4 -2
- package/dist/core/runtime/dev-server-registry.js.map +1 -1
- package/dist/core/runtime/launch-sequence.js +78 -11
- package/dist/core/runtime/launch-sequence.js.map +1 -1
- package/dist/core/runtime/module-loading.d.ts +1 -0
- package/dist/core/runtime/module-loading.js +89 -22
- package/dist/core/runtime/module-loading.js.map +1 -1
- package/dist/core/runtime/project-launch.d.ts +5 -0
- package/dist/core/runtime/project-launch.js +184 -0
- package/dist/core/runtime/project-launch.js.map +1 -0
- package/dist/core/runtime/runtime-bootstrap.d.ts +1 -0
- package/dist/core/runtime/runtime-bootstrap.js +11 -2
- package/dist/core/runtime/runtime-bootstrap.js.map +1 -1
- package/dist/core/shutdown/shutdown-manager.js +8 -2
- package/dist/core/shutdown/shutdown-manager.js.map +1 -1
- package/dist/core/test/test-module.js +18 -13
- package/dist/core/test/test-module.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +13 -113
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
|
@@ -36,10 +36,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.ModuleManager = void 0;
|
|
37
37
|
const path = __importStar(require("node:path"));
|
|
38
38
|
const logging_1 = require("@antelopejs/interface-core/logging");
|
|
39
|
+
const semver_1 = require("semver");
|
|
40
|
+
const types_1 = require("../types");
|
|
39
41
|
const interface_registry_1 = require("./interface-registry");
|
|
40
42
|
const module_1 = require("./module");
|
|
43
|
+
const module_context_1 = require("./module-context");
|
|
41
44
|
const module_registry_1 = require("./module-registry");
|
|
42
45
|
const module_tracker_1 = require("./module-tracker");
|
|
46
|
+
const package_resolution_1 = require("./resolution/package-resolution");
|
|
43
47
|
const path_mapper_1 = require("./resolution/path-mapper");
|
|
44
48
|
const resolver_1 = require("./resolution/resolver");
|
|
45
49
|
const resolver_detour_1 = require("./resolution/resolver-detour");
|
|
@@ -52,9 +56,13 @@ class ModuleManager {
|
|
|
52
56
|
moduleTracker;
|
|
53
57
|
resolverDetour;
|
|
54
58
|
resolvedAssociations = new Map();
|
|
59
|
+
resolvedConnections = new Map();
|
|
60
|
+
selectedProviders = new Map();
|
|
55
61
|
staticModules = [];
|
|
56
62
|
loaded = new Map();
|
|
57
|
-
|
|
63
|
+
stubbedInterfacePackages = new Map();
|
|
64
|
+
interfacePackagePlans = new Map();
|
|
65
|
+
pendingCleanup = [];
|
|
58
66
|
startupOrder = [];
|
|
59
67
|
constructor(deps = {}) {
|
|
60
68
|
this.registry = deps.registry ?? new module_registry_1.ModuleRegistry();
|
|
@@ -160,41 +168,37 @@ class ModuleManager {
|
|
|
160
168
|
return this.resolvedAssociations.get(moduleId)?.has(interfaceName) ?? false;
|
|
161
169
|
}
|
|
162
170
|
registerStubbedInterfaces(stubbed) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const consumerFolder = this.loaded.get(moduleId)?.module.manifest.folder;
|
|
168
|
-
if (!consumerFolder) {
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
const pkgRoot = this.resolveInterfacePackageRoot(interfacePackage, consumerFolder);
|
|
172
|
-
if (!pkgRoot) {
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
this.stubbedInterfacePaths.set(interfacePackage, pkgRoot);
|
|
176
|
-
this.resolver.interfacePackages.set(interfacePackage, pkgRoot);
|
|
177
|
-
(0, stub_interface_runtime_1.logStubInterfaceWarningOnce)(interfacePackage, standalone);
|
|
171
|
+
const packageNames = new Set(stubbed.map((entry) => entry.interfacePackage));
|
|
172
|
+
for (const packageName of packageNames) {
|
|
173
|
+
const entries = stubbed.filter((entry) => entry.interfacePackage === packageName);
|
|
174
|
+
this.registerStubbedInterfacePackage(packageName, entries);
|
|
178
175
|
}
|
|
179
176
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
catch {
|
|
186
|
-
return undefined;
|
|
177
|
+
registerStubbedInterfacePackage(packageName, entries) {
|
|
178
|
+
const consumers = this.collectInterfacePackageConsumers(packageName);
|
|
179
|
+
const canonicalPackage = consumers.find((consumer) => consumer.resolvedPackage)?.resolvedPackage;
|
|
180
|
+
if (!canonicalPackage) {
|
|
181
|
+
return;
|
|
187
182
|
}
|
|
183
|
+
this.stubbedInterfacePackages.set(packageName, canonicalPackage);
|
|
184
|
+
this.interfacePackagePlans.set(packageName, {
|
|
185
|
+
canonicalPackage,
|
|
186
|
+
consumers,
|
|
187
|
+
});
|
|
188
|
+
this.registerInterfacePackage(packageName, canonicalPackage);
|
|
189
|
+
(0, stub_interface_runtime_1.logStubInterfaceWarningOnce)(packageName, entries.some((entry) => entry.standalone));
|
|
188
190
|
}
|
|
189
191
|
applyInterfaceStubs() {
|
|
190
192
|
const implemented = this.collectImplementedInterfaces();
|
|
191
|
-
for (const [interfaceName,
|
|
193
|
+
for (const [interfaceName, resolvedPackage] of [
|
|
194
|
+
...this.stubbedInterfacePackages,
|
|
195
|
+
]) {
|
|
192
196
|
if (implemented.has(interfaceName)) {
|
|
193
|
-
this.
|
|
197
|
+
this.stubbedInterfacePackages.delete(interfaceName);
|
|
194
198
|
continue;
|
|
195
199
|
}
|
|
196
200
|
if (!this.resolver.interfacePackages.has(interfaceName)) {
|
|
197
|
-
this.
|
|
201
|
+
this.registerInterfacePackage(interfaceName, resolvedPackage);
|
|
198
202
|
}
|
|
199
203
|
try {
|
|
200
204
|
require(interfaceName);
|
|
@@ -203,7 +207,7 @@ class ModuleManager {
|
|
|
203
207
|
Logger.Error(`Failed to load interface '${interfaceName}':`, err);
|
|
204
208
|
continue;
|
|
205
209
|
}
|
|
206
|
-
(0, stub_interface_runtime_1.neutralizeInterfacePackage)(
|
|
210
|
+
(0, stub_interface_runtime_1.neutralizeInterfacePackage)(resolvedPackage.root, interfaceName);
|
|
207
211
|
}
|
|
208
212
|
}
|
|
209
213
|
collectImplementedInterfaces() {
|
|
@@ -218,83 +222,143 @@ class ModuleManager {
|
|
|
218
222
|
return implemented;
|
|
219
223
|
}
|
|
220
224
|
async constructAll() {
|
|
221
|
-
this.resolverDetour.attach();
|
|
222
|
-
this.
|
|
225
|
+
const leaseAcquired = this.resolverDetour.attach();
|
|
226
|
+
const modules = [...this.loaded.values()];
|
|
223
227
|
try {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
throw
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
228
|
+
this.validateInterfacePackages();
|
|
229
|
+
this.applyInterfaceStubs();
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
if (leaseAcquired) {
|
|
233
|
+
throw aggregateErrors([error, ...this.releaseRuntimeState()], "Failed to construct modules");
|
|
234
|
+
}
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
const results = await Promise.allSettled(modules.map(({ module, config }) => this.constructModule(module, config.config)));
|
|
238
|
+
const errors = collectRejectedErrors(results);
|
|
239
|
+
if (errors.length === 0) {
|
|
240
|
+
return;
|
|
235
241
|
}
|
|
242
|
+
const cleanupCandidates = modules.filter(({ module }) => module.state !== types_1.ModuleState.Loaded);
|
|
243
|
+
const cleanupErrors = await runModuleOperations(cleanupCandidates.reverse(), (module) => module.destroy());
|
|
244
|
+
if (leaseAcquired) {
|
|
245
|
+
cleanupErrors.push(...this.releaseRuntimeState());
|
|
246
|
+
}
|
|
247
|
+
throw new AggregateError([...errors, ...cleanupErrors], "Failed to construct modules");
|
|
236
248
|
}
|
|
237
249
|
async constructModules(modules) {
|
|
238
|
-
this.resolverDetour.attach();
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
250
|
+
const leaseAcquired = this.resolverDetour.attach();
|
|
251
|
+
try {
|
|
252
|
+
this.validateInterfacePackages();
|
|
253
|
+
this.applyInterfaceStubs();
|
|
254
|
+
await Promise.all(modules.map(({ module, config }) => this.constructModule(module, config.config)));
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
if (leaseAcquired) {
|
|
258
|
+
throw aggregateErrors([error, ...this.releaseRuntimeState()], "Failed to construct modules");
|
|
259
|
+
}
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
247
262
|
}
|
|
248
263
|
async startAll() {
|
|
249
|
-
|
|
264
|
+
try {
|
|
265
|
+
await this.startModules([...this.loaded.values()]);
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
let cleanupErrors = [];
|
|
269
|
+
try {
|
|
270
|
+
await this.destroyAll();
|
|
271
|
+
}
|
|
272
|
+
catch (cleanupError) {
|
|
273
|
+
cleanupErrors = unpackErrors(cleanupError);
|
|
274
|
+
}
|
|
275
|
+
throw new AggregateError([...unpackErrors(error), ...cleanupErrors], "Failed to start modules");
|
|
276
|
+
}
|
|
250
277
|
}
|
|
251
278
|
async startModules(modules) {
|
|
252
|
-
|
|
253
|
-
for (const { module } of modules) {
|
|
254
|
-
starting.push(module.start());
|
|
279
|
+
modules.forEach(({ module }) => {
|
|
255
280
|
this.trackModuleStart(module.id);
|
|
281
|
+
});
|
|
282
|
+
const results = await Promise.allSettled(modules.map(({ module }) => module.start()));
|
|
283
|
+
const errors = collectRejectedErrors(results);
|
|
284
|
+
if (errors.length > 0) {
|
|
285
|
+
throw new AggregateError(errors, "Failed to start modules");
|
|
256
286
|
}
|
|
257
|
-
await Promise.all(starting);
|
|
258
287
|
}
|
|
259
288
|
async stopAll() {
|
|
260
|
-
const
|
|
261
|
-
const
|
|
262
|
-
? reverseOrder
|
|
263
|
-
: [...this.loaded.keys()].reverse();
|
|
264
|
-
for (const id of idsToStop) {
|
|
265
|
-
const entry = this.loaded.get(id);
|
|
266
|
-
if (!entry) {
|
|
267
|
-
continue;
|
|
268
|
-
}
|
|
269
|
-
try {
|
|
270
|
-
await entry.module.stop();
|
|
271
|
-
}
|
|
272
|
-
catch (error) {
|
|
273
|
-
Logger.Error(`Failed to stop module ${id}:`, error);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
289
|
+
const modules = this.getReverseLifecycleModules();
|
|
290
|
+
const errors = await runModuleOperations(modules, (module) => module.stop());
|
|
276
291
|
this.startupOrder = [];
|
|
292
|
+
if (errors.length > 0) {
|
|
293
|
+
throw new AggregateError(errors, "Failed to stop modules");
|
|
294
|
+
}
|
|
277
295
|
}
|
|
278
296
|
async destroyAll() {
|
|
279
|
-
const
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
|
|
297
|
+
const modules = this.getReverseLifecycleModules();
|
|
298
|
+
const results = await runTrackedModuleOperations(modules, (module) => module.destroy());
|
|
299
|
+
this.pendingCleanup = results.failed.filter(({ module }) => module.state !== types_1.ModuleState.Loaded);
|
|
300
|
+
const errors = [...results.errors, ...this.clearManagedState()];
|
|
301
|
+
if (errors.length > 0) {
|
|
302
|
+
throw new AggregateError(errors, "Failed to destroy modules");
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
async constructModule(module, config) {
|
|
283
306
|
try {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
307
|
+
await module.construct(config);
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
Logger.Error(`Failed to construct module:`);
|
|
311
|
+
Logger.Error(` - ID: ${module.id}`);
|
|
312
|
+
Logger.Error(` - Version: ${module.version}`);
|
|
313
|
+
Logger.Error(" - Error:", error);
|
|
314
|
+
throw error;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
getReverseLifecycleModules() {
|
|
318
|
+
const orderedIds = [...this.startupOrder].reverse();
|
|
319
|
+
const seen = new Set(orderedIds);
|
|
320
|
+
for (const id of [...this.loaded.keys()].reverse()) {
|
|
321
|
+
if (!seen.has(id)) {
|
|
322
|
+
orderedIds.push(id);
|
|
290
323
|
}
|
|
291
324
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
325
|
+
const loadedModules = orderedIds.flatMap((id) => {
|
|
326
|
+
const entry = this.loaded.get(id);
|
|
327
|
+
return entry ? [entry] : [];
|
|
328
|
+
});
|
|
329
|
+
const loadedInstances = new Set(loadedModules.map(({ module }) => module));
|
|
330
|
+
return [
|
|
331
|
+
...loadedModules,
|
|
332
|
+
...this.pendingCleanup.filter(({ module }) => !loadedInstances.has(module)),
|
|
333
|
+
];
|
|
334
|
+
}
|
|
335
|
+
clearManagedState() {
|
|
336
|
+
this.loaded.clear();
|
|
337
|
+
this.staticModules.length = 0;
|
|
338
|
+
this.registry.clear();
|
|
339
|
+
this.resolvedAssociations.clear();
|
|
340
|
+
this.resolver.moduleByFolder.clear();
|
|
341
|
+
this.resolver.modulesById.clear();
|
|
342
|
+
this.resolver.interfacePackages.clear();
|
|
343
|
+
this.resolver.interfacePackageEntries.clear();
|
|
344
|
+
this.resolver.interfacePackageResolveFrom.clear();
|
|
345
|
+
this.interfacePackagePlans.clear();
|
|
346
|
+
this.startupOrder = [];
|
|
347
|
+
return this.releaseRuntimeState();
|
|
348
|
+
}
|
|
349
|
+
releaseRuntimeState() {
|
|
350
|
+
const errors = [];
|
|
351
|
+
this.stubbedInterfacePackages.clear();
|
|
352
|
+
(0, stub_interface_runtime_1.clearStubInterfaceWarnings)();
|
|
353
|
+
this.moduleTracker.clear();
|
|
354
|
+
this.interfaceRegistry.clear();
|
|
355
|
+
try {
|
|
296
356
|
this.resolverDetour.detach();
|
|
297
357
|
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
errors.push(error);
|
|
360
|
+
}
|
|
361
|
+
return errors;
|
|
298
362
|
}
|
|
299
363
|
trackModuleStart(moduleId) {
|
|
300
364
|
this.startupOrder = this.startupOrder.filter((id) => id !== moduleId);
|
|
@@ -303,13 +367,20 @@ class ModuleManager {
|
|
|
303
367
|
rebuildAssociations() {
|
|
304
368
|
const interfaceSources = this.collectInterfaceSources();
|
|
305
369
|
this.buildModuleAssociations(interfaceSources);
|
|
370
|
+
this.configureModuleContexts();
|
|
306
371
|
}
|
|
307
372
|
collectInterfaceSources() {
|
|
308
373
|
this.resolver.moduleByFolder.clear();
|
|
309
374
|
this.resolver.modulesById.clear();
|
|
310
375
|
this.resolver.interfacePackages.clear();
|
|
376
|
+
this.resolver.interfacePackageEntries.clear();
|
|
377
|
+
this.resolver.interfacePackageResolveFrom.clear();
|
|
378
|
+
this.interfacePackagePlans.clear();
|
|
311
379
|
this.resolvedAssociations.clear();
|
|
380
|
+
this.resolvedConnections.clear();
|
|
381
|
+
this.selectedProviders.clear();
|
|
312
382
|
this.moduleTracker.clear();
|
|
383
|
+
this.interfaceRegistry.clear();
|
|
313
384
|
const interfaceSources = new Map();
|
|
314
385
|
for (const { module, config } of this.loaded.values()) {
|
|
315
386
|
this.resolver.moduleByFolder.set(module.manifest.folder, module);
|
|
@@ -321,7 +392,7 @@ class ModuleManager {
|
|
|
321
392
|
});
|
|
322
393
|
for (const interfacePackage of module.manifest.implements ?? []) {
|
|
323
394
|
if (!config.disabledExports?.has(interfacePackage)) {
|
|
324
|
-
|
|
395
|
+
this.addInterfaceSource(interfaceSources, interfacePackage, module);
|
|
325
396
|
}
|
|
326
397
|
}
|
|
327
398
|
}
|
|
@@ -329,7 +400,7 @@ class ModuleManager {
|
|
|
329
400
|
this.resolver.modulesById.set(module.id, module);
|
|
330
401
|
for (const interfacePackage of module.manifest.implements ?? []) {
|
|
331
402
|
if (!config.disabledExports?.has(interfacePackage)) {
|
|
332
|
-
|
|
403
|
+
this.addInterfaceSource(interfaceSources, interfacePackage, module);
|
|
333
404
|
}
|
|
334
405
|
}
|
|
335
406
|
}
|
|
@@ -337,75 +408,209 @@ class ModuleManager {
|
|
|
337
408
|
return interfaceSources;
|
|
338
409
|
}
|
|
339
410
|
resolveInterfacePackagePaths(interfaceSources) {
|
|
340
|
-
for (const [ifacePkg,
|
|
341
|
-
|
|
342
|
-
|
|
411
|
+
for (const [ifacePkg, modules] of interfaceSources) {
|
|
412
|
+
const module = [...modules].sort((left, right) => left.id.localeCompare(right.id))[0];
|
|
413
|
+
if (!module) {
|
|
343
414
|
continue;
|
|
344
415
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
});
|
|
349
|
-
const pkgRoot = extractPackageRoot(mainPath, ifacePkg);
|
|
350
|
-
if (pkgRoot) {
|
|
351
|
-
this.resolver.interfacePackages.set(ifacePkg, pkgRoot);
|
|
352
|
-
}
|
|
416
|
+
const canonicalPackage = this.resolveImplementedPackage(ifacePkg, module);
|
|
417
|
+
if (!canonicalPackage) {
|
|
418
|
+
continue;
|
|
353
419
|
}
|
|
354
|
-
|
|
420
|
+
this.interfacePackagePlans.set(ifacePkg, {
|
|
421
|
+
canonicalPackage,
|
|
422
|
+
consumers: this.collectInterfacePackageConsumers(ifacePkg),
|
|
423
|
+
});
|
|
424
|
+
this.registerInterfacePackage(ifacePkg, canonicalPackage);
|
|
425
|
+
}
|
|
426
|
+
for (const [packageName, canonicalPackage] of this
|
|
427
|
+
.stubbedInterfacePackages) {
|
|
428
|
+
if (interfaceSources.has(packageName)) {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
this.interfacePackagePlans.set(packageName, {
|
|
432
|
+
canonicalPackage,
|
|
433
|
+
consumers: this.collectInterfacePackageConsumers(packageName),
|
|
434
|
+
});
|
|
435
|
+
this.registerInterfacePackage(packageName, canonicalPackage);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
resolveImplementedPackage(packageName, module) {
|
|
439
|
+
const resolvedPackage = (0, package_resolution_1.resolvePackage)(packageName, module.manifest.folder);
|
|
440
|
+
if (resolvedPackage) {
|
|
441
|
+
return resolvedPackage;
|
|
442
|
+
}
|
|
443
|
+
if (module.manifest.manifest.name !== packageName) {
|
|
444
|
+
return undefined;
|
|
445
|
+
}
|
|
446
|
+
return (0, package_resolution_1.resolvePackageAtRoot)(packageName, module.manifest.folder, module.manifest.version);
|
|
447
|
+
}
|
|
448
|
+
collectInterfacePackageConsumers(packageName) {
|
|
449
|
+
const consumers = [];
|
|
450
|
+
for (const { module } of this.loaded.values()) {
|
|
451
|
+
const manifest = module.manifest.manifest;
|
|
452
|
+
const range = manifest.dependencies?.[packageName] ??
|
|
453
|
+
manifest.optionalDependencies?.[packageName];
|
|
454
|
+
if (!range) {
|
|
455
|
+
continue;
|
|
355
456
|
}
|
|
457
|
+
consumers.push({
|
|
458
|
+
moduleId: module.id,
|
|
459
|
+
range,
|
|
460
|
+
resolvedPackage: (0, package_resolution_1.resolvePackage)(packageName, module.manifest.folder),
|
|
461
|
+
});
|
|
356
462
|
}
|
|
463
|
+
return consumers;
|
|
464
|
+
}
|
|
465
|
+
registerInterfacePackage(packageName, resolvedPackage) {
|
|
466
|
+
this.resolver.interfacePackages.set(packageName, resolvedPackage.root);
|
|
467
|
+
this.resolver.interfacePackageEntries.set(packageName, resolvedPackage.entry);
|
|
468
|
+
this.resolver.interfacePackageResolveFrom.set(packageName, resolvedPackage.resolveFrom);
|
|
469
|
+
}
|
|
470
|
+
validateInterfacePackages() {
|
|
471
|
+
const errors = [...this.interfacePackagePlans].flatMap(([name, plan]) => [
|
|
472
|
+
...this.findVersionErrors(name, plan),
|
|
473
|
+
...this.findPreloadedCopyErrors(name, plan),
|
|
474
|
+
]);
|
|
475
|
+
if (errors.length === 0) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
throw new Error(`Incompatible interface package resolution:\n${errors.join("\n")}`);
|
|
479
|
+
}
|
|
480
|
+
findVersionErrors(packageName, plan) {
|
|
481
|
+
return plan.consumers.flatMap((consumer) => {
|
|
482
|
+
const range = (0, semver_1.validRange)(consumer.range);
|
|
483
|
+
if (!range || (0, semver_1.satisfies)(plan.canonicalPackage.version, range)) {
|
|
484
|
+
return [];
|
|
485
|
+
}
|
|
486
|
+
const installed = consumer.resolvedPackage
|
|
487
|
+
? `${consumer.resolvedPackage.version} at ${consumer.resolvedPackage.root}`
|
|
488
|
+
: "not installed from the consumer";
|
|
489
|
+
return [
|
|
490
|
+
` - ${consumer.moduleId} requires ${packageName}@${consumer.range}, but the canonical package is ${plan.canonicalPackage.version} at ${plan.canonicalPackage.root} (consumer copy: ${installed})`,
|
|
491
|
+
];
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
findPreloadedCopyErrors(packageName, plan) {
|
|
495
|
+
const canonicalRoot = plan.canonicalPackage.realRoot;
|
|
496
|
+
const copies = plan.consumers
|
|
497
|
+
.map((consumer) => consumer.resolvedPackage)
|
|
498
|
+
.filter((resolvedPackage) => Boolean(resolvedPackage && resolvedPackage.realRoot !== canonicalRoot));
|
|
499
|
+
return copies.flatMap((copy) => {
|
|
500
|
+
const loadedFile = Object.keys(require.cache).find((filePath) => (0, package_resolution_1.isPathWithin)(filePath, copy.root));
|
|
501
|
+
return loadedFile
|
|
502
|
+
? [
|
|
503
|
+
` - ${packageName}@${copy.version} was loaded from ${copy.root} before the canonical copy at ${plan.canonicalPackage.root}; preloaded interface copies cannot be redirected (${loadedFile})`,
|
|
504
|
+
]
|
|
505
|
+
: [];
|
|
506
|
+
});
|
|
357
507
|
}
|
|
358
508
|
buildModuleAssociations(interfaceSources) {
|
|
359
509
|
for (const { module, config } of this.loaded.values()) {
|
|
360
|
-
const associations = new Map();
|
|
361
510
|
const connections = new Map();
|
|
362
|
-
|
|
363
|
-
this.
|
|
364
|
-
this.
|
|
365
|
-
this.
|
|
511
|
+
const selected = new Map();
|
|
512
|
+
this.addDefaultAssociations(module, connections, selected, interfaceSources);
|
|
513
|
+
this.applyImportOverrides(module.id, config.importOverrides, connections, selected);
|
|
514
|
+
this.resolvedAssociations.set(module.id, new Set(connections.keys()));
|
|
515
|
+
this.resolvedConnections.set(module.id, connections);
|
|
516
|
+
this.selectedProviders.set(module.id, selected);
|
|
517
|
+
this.interfaceRegistry.setConnections(module.id, connections, selected);
|
|
366
518
|
}
|
|
367
519
|
}
|
|
368
|
-
addDefaultAssociations(module,
|
|
520
|
+
addDefaultAssociations(module, connections, selected, interfaceSources) {
|
|
369
521
|
const dependencies = module.manifest.manifest.dependencies ?? {};
|
|
370
522
|
const optionalDependencies = module.manifest.manifest.optionalDependencies ?? {};
|
|
371
|
-
for (const [iface,
|
|
523
|
+
for (const [iface, providers] of interfaceSources) {
|
|
372
524
|
if (iface in dependencies || iface in optionalDependencies) {
|
|
373
|
-
|
|
374
|
-
|
|
525
|
+
const providerIds = providers.map(({ id }) => id).sort();
|
|
526
|
+
const defaultProvider = providerIds[0];
|
|
527
|
+
if (!defaultProvider) {
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
connections.set(iface, providerIds.map((provider) => ({ module: provider })));
|
|
531
|
+
selected.set(iface, defaultProvider);
|
|
375
532
|
}
|
|
376
533
|
}
|
|
377
534
|
}
|
|
378
|
-
applyImportOverrides(importOverrides,
|
|
535
|
+
applyImportOverrides(moduleId, importOverrides, connections, selected) {
|
|
379
536
|
if (!importOverrides) {
|
|
380
537
|
return;
|
|
381
538
|
}
|
|
382
539
|
for (const [iface, overrides] of importOverrides.entries()) {
|
|
383
|
-
|
|
384
|
-
connections.set(iface,
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
540
|
+
this.validateImportOverrides(moduleId, iface, overrides);
|
|
541
|
+
connections.set(iface, overrides);
|
|
542
|
+
selected.set(iface, overrides[0].module);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
addInterfaceSource(sources, interfaceName, module) {
|
|
546
|
+
const providers = sources.get(interfaceName) ?? [];
|
|
547
|
+
providers.push(module);
|
|
548
|
+
sources.set(interfaceName, providers);
|
|
549
|
+
}
|
|
550
|
+
validateImportOverrides(consumerId, interfaceName, overrides) {
|
|
551
|
+
if (overrides.length === 0) {
|
|
552
|
+
throw new Error(`Module '${consumerId}' has no providers in its '${interfaceName}' import override.`);
|
|
553
|
+
}
|
|
554
|
+
const connectionIds = new Set();
|
|
555
|
+
for (const override of overrides) {
|
|
556
|
+
const target = this.getModuleEntry(override.module);
|
|
557
|
+
const implementsInterface = target?.module.manifest.implements.includes(interfaceName) &&
|
|
558
|
+
!target.config.disabledExports?.has(interfaceName);
|
|
559
|
+
if (!implementsInterface) {
|
|
560
|
+
throw new Error(`Module '${consumerId}' routes '${interfaceName}' to '${override.module}', but that loaded module does not provide the interface.`);
|
|
561
|
+
}
|
|
562
|
+
if (override.id && connectionIds.has(override.id)) {
|
|
563
|
+
throw new Error(`Module '${consumerId}' has duplicate connection ID '${override.id}' for '${interfaceName}'.`);
|
|
564
|
+
}
|
|
565
|
+
if (override.id) {
|
|
566
|
+
connectionIds.add(override.id);
|
|
390
567
|
}
|
|
391
568
|
}
|
|
392
569
|
}
|
|
393
|
-
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
570
|
+
configureModuleContexts() {
|
|
571
|
+
for (const { module, config } of this.getAllManagedModules()) {
|
|
572
|
+
const selected = this.selectedProviders.get(module.id) ?? new Map();
|
|
573
|
+
const connections = this.resolvedConnections.get(module.id) ??
|
|
574
|
+
new Map();
|
|
575
|
+
const routes = [...selected].map(([interfaceName, provider]) => ({
|
|
576
|
+
interfaceName,
|
|
577
|
+
packageEntry: this.resolver.interfacePackageEntries.get(interfaceName),
|
|
578
|
+
provider,
|
|
579
|
+
providerCount: new Set(connections.get(interfaceName)?.map(({ module }) => module)).size,
|
|
580
|
+
}));
|
|
581
|
+
const isProvider = (module.manifest.implements ?? []).some((interfaceName) => !config.disabledExports?.has(interfaceName));
|
|
582
|
+
module.setProviderRoutes((0, module_context_1.buildProviderRoutes)(module.id, routes), isProvider);
|
|
398
583
|
}
|
|
399
|
-
|
|
584
|
+
}
|
|
585
|
+
isPathWithin(filePath, dirPath) {
|
|
586
|
+
return (0, package_resolution_1.isPathWithin)(filePath, dirPath);
|
|
400
587
|
}
|
|
401
588
|
}
|
|
402
589
|
exports.ModuleManager = ModuleManager;
|
|
403
|
-
function
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
590
|
+
function collectRejectedErrors(results) {
|
|
591
|
+
return results.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
592
|
+
}
|
|
593
|
+
function unpackErrors(error) {
|
|
594
|
+
return error instanceof AggregateError ? error.errors : [error];
|
|
595
|
+
}
|
|
596
|
+
function aggregateErrors(errors, message) {
|
|
597
|
+
return errors.length === 1 ? errors[0] : new AggregateError(errors, message);
|
|
598
|
+
}
|
|
599
|
+
async function runModuleOperations(modules, operation) {
|
|
600
|
+
return (await runTrackedModuleOperations(modules, operation)).errors;
|
|
601
|
+
}
|
|
602
|
+
async function runTrackedModuleOperations(modules, operation) {
|
|
603
|
+
const errors = [];
|
|
604
|
+
const failed = [];
|
|
605
|
+
for (const entry of modules) {
|
|
606
|
+
try {
|
|
607
|
+
await operation(entry.module);
|
|
608
|
+
}
|
|
609
|
+
catch (error) {
|
|
610
|
+
errors.push(...unpackErrors(error));
|
|
611
|
+
failed.push(entry);
|
|
612
|
+
}
|
|
408
613
|
}
|
|
409
|
-
return
|
|
614
|
+
return { errors, failed };
|
|
410
615
|
}
|
|
411
616
|
//# sourceMappingURL=module-manager.js.map
|