@antelopejs/core 1.4.6 → 1.4.8
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/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 +7 -1
- package/dist/core/module-lifecycle.js +47 -10
- package/dist/core/module-lifecycle.js.map +1 -1
- package/dist/core/module-manager.d.ts +21 -4
- package/dist/core/module-manager.js +333 -129
- 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 +3 -1
- 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/resolution/stub-interface-runtime.js +11 -1
- package/dist/core/resolution/stub-interface-runtime.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 +92 -25
- 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-context.d.ts +1 -1
- package/dist/core/test/test-context.js +1 -1
- package/dist/core/test/test-context.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/dist/types/module.types.d.ts +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,84 +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
|
-
catch (err) {
|
|
233
|
-
this.resolverDetour.detach();
|
|
234
|
-
throw err;
|
|
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;
|
|
235
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;
|
|
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
|
-
Logger.Error(` - Version: ${module.version}`);
|
|
244
|
-
Logger.Error(" - Error:", err);
|
|
245
|
-
throw err;
|
|
246
|
-
})));
|
|
247
|
-
}
|
|
248
|
-
startAll() {
|
|
249
|
-
for (const { module } of this.loaded.values()) {
|
|
250
|
-
module.start();
|
|
251
|
-
this.trackModuleStart(module.id);
|
|
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)));
|
|
252
255
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
catch (error) {
|
|
257
|
+
if (leaseAcquired) {
|
|
258
|
+
throw aggregateErrors([error, ...this.releaseRuntimeState()], "Failed to construct modules");
|
|
259
|
+
}
|
|
260
|
+
throw error;
|
|
258
261
|
}
|
|
259
262
|
}
|
|
260
|
-
async
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
const entry = this.loaded.get(id);
|
|
267
|
-
if (!entry) {
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
263
|
+
async startAll() {
|
|
264
|
+
try {
|
|
265
|
+
await this.startModules([...this.loaded.values()]);
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
let cleanupErrors = [];
|
|
270
269
|
try {
|
|
271
|
-
await
|
|
270
|
+
await this.destroyAll();
|
|
272
271
|
}
|
|
273
|
-
catch (
|
|
274
|
-
|
|
272
|
+
catch (cleanupError) {
|
|
273
|
+
cleanupErrors = unpackErrors(cleanupError);
|
|
275
274
|
}
|
|
275
|
+
throw new AggregateError([...unpackErrors(error), ...cleanupErrors], "Failed to start modules");
|
|
276
276
|
}
|
|
277
|
+
}
|
|
278
|
+
async startModules(modules) {
|
|
279
|
+
modules.forEach(({ module }) => {
|
|
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");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
async stopAll() {
|
|
289
|
+
const modules = this.getReverseLifecycleModules();
|
|
290
|
+
const errors = await runModuleOperations(modules, (module) => module.stop());
|
|
277
291
|
this.startupOrder = [];
|
|
292
|
+
if (errors.length > 0) {
|
|
293
|
+
throw new AggregateError(errors, "Failed to stop modules");
|
|
294
|
+
}
|
|
278
295
|
}
|
|
279
296
|
async destroyAll() {
|
|
280
|
-
const
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
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) {
|
|
284
306
|
try {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
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);
|
|
291
323
|
}
|
|
292
324
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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 {
|
|
297
356
|
this.resolverDetour.detach();
|
|
298
357
|
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
errors.push(error);
|
|
360
|
+
}
|
|
361
|
+
return errors;
|
|
299
362
|
}
|
|
300
363
|
trackModuleStart(moduleId) {
|
|
301
364
|
this.startupOrder = this.startupOrder.filter((id) => id !== moduleId);
|
|
@@ -304,13 +367,20 @@ class ModuleManager {
|
|
|
304
367
|
rebuildAssociations() {
|
|
305
368
|
const interfaceSources = this.collectInterfaceSources();
|
|
306
369
|
this.buildModuleAssociations(interfaceSources);
|
|
370
|
+
this.configureModuleContexts();
|
|
307
371
|
}
|
|
308
372
|
collectInterfaceSources() {
|
|
309
373
|
this.resolver.moduleByFolder.clear();
|
|
310
374
|
this.resolver.modulesById.clear();
|
|
311
375
|
this.resolver.interfacePackages.clear();
|
|
376
|
+
this.resolver.interfacePackageEntries.clear();
|
|
377
|
+
this.resolver.interfacePackageResolveFrom.clear();
|
|
378
|
+
this.interfacePackagePlans.clear();
|
|
312
379
|
this.resolvedAssociations.clear();
|
|
380
|
+
this.resolvedConnections.clear();
|
|
381
|
+
this.selectedProviders.clear();
|
|
313
382
|
this.moduleTracker.clear();
|
|
383
|
+
this.interfaceRegistry.clear();
|
|
314
384
|
const interfaceSources = new Map();
|
|
315
385
|
for (const { module, config } of this.loaded.values()) {
|
|
316
386
|
this.resolver.moduleByFolder.set(module.manifest.folder, module);
|
|
@@ -322,7 +392,7 @@ class ModuleManager {
|
|
|
322
392
|
});
|
|
323
393
|
for (const interfacePackage of module.manifest.implements ?? []) {
|
|
324
394
|
if (!config.disabledExports?.has(interfacePackage)) {
|
|
325
|
-
|
|
395
|
+
this.addInterfaceSource(interfaceSources, interfacePackage, module);
|
|
326
396
|
}
|
|
327
397
|
}
|
|
328
398
|
}
|
|
@@ -330,7 +400,7 @@ class ModuleManager {
|
|
|
330
400
|
this.resolver.modulesById.set(module.id, module);
|
|
331
401
|
for (const interfacePackage of module.manifest.implements ?? []) {
|
|
332
402
|
if (!config.disabledExports?.has(interfacePackage)) {
|
|
333
|
-
|
|
403
|
+
this.addInterfaceSource(interfaceSources, interfacePackage, module);
|
|
334
404
|
}
|
|
335
405
|
}
|
|
336
406
|
}
|
|
@@ -338,75 +408,209 @@ class ModuleManager {
|
|
|
338
408
|
return interfaceSources;
|
|
339
409
|
}
|
|
340
410
|
resolveInterfacePackagePaths(interfaceSources) {
|
|
341
|
-
for (const [ifacePkg,
|
|
342
|
-
|
|
343
|
-
|
|
411
|
+
for (const [ifacePkg, modules] of interfaceSources) {
|
|
412
|
+
const module = [...modules].sort((left, right) => left.id.localeCompare(right.id))[0];
|
|
413
|
+
if (!module) {
|
|
344
414
|
continue;
|
|
345
415
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
});
|
|
350
|
-
const pkgRoot = extractPackageRoot(mainPath, ifacePkg);
|
|
351
|
-
if (pkgRoot) {
|
|
352
|
-
this.resolver.interfacePackages.set(ifacePkg, pkgRoot);
|
|
353
|
-
}
|
|
416
|
+
const canonicalPackage = this.resolveImplementedPackage(ifacePkg, module);
|
|
417
|
+
if (!canonicalPackage) {
|
|
418
|
+
continue;
|
|
354
419
|
}
|
|
355
|
-
|
|
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;
|
|
356
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;
|
|
357
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;
|
|
456
|
+
}
|
|
457
|
+
consumers.push({
|
|
458
|
+
moduleId: module.id,
|
|
459
|
+
range,
|
|
460
|
+
resolvedPackage: (0, package_resolution_1.resolvePackage)(packageName, module.manifest.folder),
|
|
461
|
+
});
|
|
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
|
+
});
|
|
358
507
|
}
|
|
359
508
|
buildModuleAssociations(interfaceSources) {
|
|
360
509
|
for (const { module, config } of this.loaded.values()) {
|
|
361
|
-
const associations = new Map();
|
|
362
510
|
const connections = new Map();
|
|
363
|
-
|
|
364
|
-
this.
|
|
365
|
-
this.
|
|
366
|
-
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);
|
|
367
518
|
}
|
|
368
519
|
}
|
|
369
|
-
addDefaultAssociations(module,
|
|
520
|
+
addDefaultAssociations(module, connections, selected, interfaceSources) {
|
|
370
521
|
const dependencies = module.manifest.manifest.dependencies ?? {};
|
|
371
522
|
const optionalDependencies = module.manifest.manifest.optionalDependencies ?? {};
|
|
372
|
-
for (const [iface,
|
|
523
|
+
for (const [iface, providers] of interfaceSources) {
|
|
373
524
|
if (iface in dependencies || iface in optionalDependencies) {
|
|
374
|
-
|
|
375
|
-
|
|
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);
|
|
376
532
|
}
|
|
377
533
|
}
|
|
378
534
|
}
|
|
379
|
-
applyImportOverrides(importOverrides,
|
|
535
|
+
applyImportOverrides(moduleId, importOverrides, connections, selected) {
|
|
380
536
|
if (!importOverrides) {
|
|
381
537
|
return;
|
|
382
538
|
}
|
|
383
539
|
for (const [iface, overrides] of importOverrides.entries()) {
|
|
384
|
-
|
|
385
|
-
connections.set(iface,
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
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);
|
|
391
567
|
}
|
|
392
568
|
}
|
|
393
569
|
}
|
|
394
|
-
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
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);
|
|
399
583
|
}
|
|
400
|
-
|
|
584
|
+
}
|
|
585
|
+
isPathWithin(filePath, dirPath) {
|
|
586
|
+
return (0, package_resolution_1.isPathWithin)(filePath, dirPath);
|
|
401
587
|
}
|
|
402
588
|
}
|
|
403
589
|
exports.ModuleManager = ModuleManager;
|
|
404
|
-
function
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
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
|
+
}
|
|
409
613
|
}
|
|
410
|
-
return
|
|
614
|
+
return { errors, failed };
|
|
411
615
|
}
|
|
412
616
|
//# sourceMappingURL=module-manager.js.map
|