@softarc/native-federation-orchestrator 4.4.1 → 4.5.1
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/README.md +2 -2
- package/fesm2022/@softarc/native-federation-orchestrator.mjs +517 -76
- package/fesm2022/@softarc/native-federation-orchestrator.mjs.map +4 -4
- package/fesm2022/module-federation.mjs +21 -17
- package/fesm2022/module-federation.mjs.map +2 -2
- package/fesm2022/node.mjs +439 -72
- package/fesm2022/node.mjs.map +4 -4
- package/package.json +1 -1
- package/quickstart.mjs +13 -13
- package/types/lib/core/1.domain/externals/version.contract.d.ts +3 -2
- package/types/lib/core/1.domain/remote-entry/remote-entry.contract.d.ts +6 -4
- package/types/lib/core/2.app/config/mode.contract.d.ts +6 -0
- package/types/lib/core/2.app/driver-ports/init/drivers.contract.d.ts +4 -0
- package/types/lib/core/2.app/driver-ports/init/for-pooling-dynamic-externals.port.d.ts +8 -0
- package/types/lib/core/2.app/driver-ports/init/for-pooling-shared-externals.port.d.ts +1 -0
- package/types/lib/core/2.app/driver-ports/init/index.d.ts +2 -0
- package/types/lib/core/2.app/driving-ports/for-shared-externals-storage.port.d.ts +2 -0
- package/types/lib/core/2.app/steps/convert-to-import-map.d.ts +2 -1
- package/types/lib/core/2.app/steps/pooling/pool-dynamic-externals.d.ts +3 -0
- package/types/lib/core/2.app/steps/pooling/pool-graph.d.ts +25 -0
- package/types/lib/core/2.app/steps/pooling/pool-shared-externals.d.ts +5 -0
- package/types/lib/core/2.app/steps/pooling/pool.types.d.ts +25 -0
- package/types/lib/core/2.app/steps/pooling/pool.util.d.ts +4 -0
- package/types/lib/core/2.app/steps/store-remote-entry.d.ts +2 -2
- package/types/lib/core/3.adapters/http/remote-entry-provider.d.ts +2 -1
package/fesm2022/node.mjs
CHANGED
|
@@ -1560,7 +1560,14 @@ var createSharedExternalsRepository = (config) => {
|
|
|
1560
1560
|
);
|
|
1561
1561
|
if (config.clearStorage) STORAGE.clear();
|
|
1562
1562
|
const _cache = STORAGE.get();
|
|
1563
|
+
let _sawPoolTag = false;
|
|
1563
1564
|
return {
|
|
1565
|
+
markPoolTagPresent: function() {
|
|
1566
|
+
_sawPoolTag = true;
|
|
1567
|
+
},
|
|
1568
|
+
hasPoolTag: function() {
|
|
1569
|
+
return _sawPoolTag;
|
|
1570
|
+
},
|
|
1564
1571
|
getFromScope: function(shareScope) {
|
|
1565
1572
|
return { ..._cache[shareScope ?? GLOBAL_SCOPE] };
|
|
1566
1573
|
},
|
|
@@ -1871,7 +1878,11 @@ var createModeConfig = (override) => {
|
|
|
1871
1878
|
};
|
|
1872
1879
|
return {
|
|
1873
1880
|
strict: strictnessConfig,
|
|
1874
|
-
profile: { ...defaultProfile, ...override.profile ?? {} }
|
|
1881
|
+
profile: { ...defaultProfile, ...override.profile ?? {} },
|
|
1882
|
+
feature: {
|
|
1883
|
+
convertFlatSharedInfo: override.feature?.convertFlatSharedInfo ?? false,
|
|
1884
|
+
useAutoExternalPooling: override.feature?.useAutoExternalPooling ?? false
|
|
1885
|
+
}
|
|
1875
1886
|
};
|
|
1876
1887
|
};
|
|
1877
1888
|
|
|
@@ -1890,7 +1901,7 @@ var createInitFlow = ({
|
|
|
1890
1901
|
adapters,
|
|
1891
1902
|
config
|
|
1892
1903
|
}) => {
|
|
1893
|
-
return (remotesOrManifestUrl) => flow.getRemoteEntries(remotesOrManifestUrl).then(flow.processRemoteEntries).then(flow.determineSharedExternals).then(flow.generateImportMap).then((importMap) => flow.commitChanges(importMap, { override: true })).then(flow.exposeModuleLoader).then((loadRemoteModule) => ({
|
|
1904
|
+
return (remotesOrManifestUrl) => flow.getRemoteEntries(remotesOrManifestUrl).then(flow.processRemoteEntries).then(flow.determineSharedExternals).then(flow.poolSharedExternals).then(flow.generateImportMap).then((importMap) => flow.commitChanges(importMap, { override: true })).then(flow.exposeModuleLoader).then((loadRemoteModule) => ({
|
|
1894
1905
|
config,
|
|
1895
1906
|
adapters,
|
|
1896
1907
|
loadRemoteModule
|
|
@@ -1901,7 +1912,7 @@ var createInitFlow = ({
|
|
|
1901
1912
|
var createInitRemoteEntryFlow = ({
|
|
1902
1913
|
flow
|
|
1903
1914
|
}) => {
|
|
1904
|
-
const processDynamicRemoteEntry = (remoteEntry) => flow.updateCache(remoteEntry).then(flow.convertToImportMap).then(flow.commitChanges);
|
|
1915
|
+
const processDynamicRemoteEntry = (remoteEntry) => flow.updateCache(remoteEntry).then(flow.poolDynamicExternals).then(flow.convertToImportMap).then(flow.commitChanges);
|
|
1905
1916
|
return (remoteEntryUrl, remote) => flow.getRemoteEntry(remoteEntryUrl, remote).then((entry) => entry.map(processDynamicRemoteEntry).orElse(Promise.resolve())).then(() => void 0);
|
|
1906
1917
|
};
|
|
1907
1918
|
|
|
@@ -2037,6 +2048,7 @@ function createStoreRemoteEntry(config, ports, logStep) {
|
|
|
2037
2048
|
const tag = resolveVersion(remoteEntry, external);
|
|
2038
2049
|
if (tag === null) return;
|
|
2039
2050
|
if (external.singleton) {
|
|
2051
|
+
if (external.pool?.trim()) ports.sharedExternalsRepo.markPoolTagPresent();
|
|
2040
2052
|
onSharedExternal(remoteEntry, external, sharedExternalContext(remoteEntry, external, tag));
|
|
2041
2053
|
} else {
|
|
2042
2054
|
addScopedExternal(remoteEntry, external, tag);
|
|
@@ -2056,8 +2068,8 @@ function createStoreRemoteEntry(config, ports, logStep) {
|
|
|
2056
2068
|
function addScopedExternal(remoteEntry, sharedInfo, tag) {
|
|
2057
2069
|
ports.scopedExternalsRepo.addExternal(remoteEntry.name, sharedInfo.packageName, {
|
|
2058
2070
|
tag,
|
|
2059
|
-
|
|
2060
|
-
|
|
2071
|
+
bundle: sharedInfo.bundle,
|
|
2072
|
+
entries: sharedInfo.entries
|
|
2061
2073
|
});
|
|
2062
2074
|
}
|
|
2063
2075
|
function resolveVersion(remoteEntry, external) {
|
|
@@ -2079,12 +2091,13 @@ function createStoreRemoteEntry(config, ports, logStep) {
|
|
|
2079
2091
|
function sharedExternalContext(remoteEntry, sharedInfo, tag) {
|
|
2080
2092
|
const scopeType = ports.sharedExternalsRepo.scopeType(sharedInfo.shareScope);
|
|
2081
2093
|
const remote = {
|
|
2082
|
-
file: sharedInfo.outFileName,
|
|
2083
2094
|
name: remoteEntry.name,
|
|
2084
2095
|
bundle: sharedInfo.bundle,
|
|
2085
2096
|
strictVersion: sharedInfo.strictVersion,
|
|
2086
2097
|
cached: false,
|
|
2087
|
-
requiredVersion: scopeType === "strict" ? tag : sharedInfo.requiredVersion || tag
|
|
2098
|
+
requiredVersion: scopeType === "strict" ? tag : sharedInfo.requiredVersion || tag,
|
|
2099
|
+
...sharedInfo.pool?.trim() ? { pool: sharedInfo.pool } : {},
|
|
2100
|
+
entries: sharedInfo.entries
|
|
2088
2101
|
};
|
|
2089
2102
|
const cached2 = ports.sharedExternalsRepo.tryGet(sharedInfo.packageName, sharedInfo.shareScope).orElse({ dirty: false, versions: [] });
|
|
2090
2103
|
return {
|
|
@@ -2232,7 +2245,290 @@ function createDetermineSharedExternals(config, ports) {
|
|
|
2232
2245
|
}
|
|
2233
2246
|
}
|
|
2234
2247
|
|
|
2235
|
-
//
|
|
2248
|
+
// src/lib/core/2.app/steps/pooling/pool-graph.ts
|
|
2249
|
+
var SCOPED_PACKAGE = /^@([^/]+)\//;
|
|
2250
|
+
function createDSU() {
|
|
2251
|
+
const ids = /* @__PURE__ */ new Map();
|
|
2252
|
+
const parent = [];
|
|
2253
|
+
const size = [];
|
|
2254
|
+
const intern = (key) => {
|
|
2255
|
+
let id = ids.get(key);
|
|
2256
|
+
if (id === void 0) {
|
|
2257
|
+
id = parent.length;
|
|
2258
|
+
ids.set(key, id);
|
|
2259
|
+
parent.push(id);
|
|
2260
|
+
size.push(1);
|
|
2261
|
+
}
|
|
2262
|
+
return id;
|
|
2263
|
+
};
|
|
2264
|
+
const findRoot = (x) => {
|
|
2265
|
+
while (parent[x] !== x) {
|
|
2266
|
+
parent[x] = parent[parent[x]];
|
|
2267
|
+
x = parent[x];
|
|
2268
|
+
}
|
|
2269
|
+
return x;
|
|
2270
|
+
};
|
|
2271
|
+
return {
|
|
2272
|
+
union(a, b) {
|
|
2273
|
+
let rootA = findRoot(intern(a));
|
|
2274
|
+
let rootB = findRoot(intern(b));
|
|
2275
|
+
if (rootA === rootB) return;
|
|
2276
|
+
if (size[rootA] < size[rootB]) [rootA, rootB] = [rootB, rootA];
|
|
2277
|
+
parent[rootB] = rootA;
|
|
2278
|
+
size[rootA] = size[rootA] + size[rootB];
|
|
2279
|
+
},
|
|
2280
|
+
// Interns the key if unseen — an isolated key is its own component.
|
|
2281
|
+
component(key) {
|
|
2282
|
+
return findRoot(intern(key));
|
|
2283
|
+
}
|
|
2284
|
+
};
|
|
2285
|
+
}
|
|
2286
|
+
var extNode = (name) => `ext\0${name}`;
|
|
2287
|
+
var tagNode = (remote, tag) => `tag\0${remote}\0${tag}`;
|
|
2288
|
+
var scopeNode = (scope) => `scope\0${scope}`;
|
|
2289
|
+
function autoScope(name, useAutoExternalPooling) {
|
|
2290
|
+
return useAutoExternalPooling ? SCOPED_PACKAGE.exec(name)?.[1] : void 0;
|
|
2291
|
+
}
|
|
2292
|
+
function groupByMembership(candidates, log) {
|
|
2293
|
+
const dsu = createDSU();
|
|
2294
|
+
const tagged = /* @__PURE__ */ new Set();
|
|
2295
|
+
const poolable = [];
|
|
2296
|
+
for (const candidate of candidates) {
|
|
2297
|
+
let joined = false;
|
|
2298
|
+
if (candidate.scope !== void 0) {
|
|
2299
|
+
dsu.union(extNode(candidate.name), scopeNode(candidate.scope));
|
|
2300
|
+
joined = true;
|
|
2301
|
+
}
|
|
2302
|
+
for (const edge of candidate.tags) {
|
|
2303
|
+
dsu.union(extNode(candidate.name), tagNode(edge.remote, edge.tag));
|
|
2304
|
+
tagged.add(candidate.name);
|
|
2305
|
+
joined = true;
|
|
2306
|
+
}
|
|
2307
|
+
if (joined) poolable.push({ name: candidate.name, value: candidate.value });
|
|
2308
|
+
}
|
|
2309
|
+
const byComponent = /* @__PURE__ */ new Map();
|
|
2310
|
+
for (const entry of poolable) {
|
|
2311
|
+
const root = dsu.component(extNode(entry.name));
|
|
2312
|
+
(byComponent.get(root) ?? byComponent.set(root, []).get(root)).push(entry);
|
|
2313
|
+
}
|
|
2314
|
+
const pools = [];
|
|
2315
|
+
for (const members of byComponent.values()) {
|
|
2316
|
+
members.sort((a, b) => a.name.localeCompare(b.name));
|
|
2317
|
+
if (members.length < 2) {
|
|
2318
|
+
const only = members[0];
|
|
2319
|
+
if (tagged.has(only.name)) {
|
|
2320
|
+
log?.warn(
|
|
2321
|
+
3,
|
|
2322
|
+
`[${only.name}] declares a 'pool' tag but no other external joined its pool; likely a typo or a missing sibling.`
|
|
2323
|
+
);
|
|
2324
|
+
}
|
|
2325
|
+
continue;
|
|
2326
|
+
}
|
|
2327
|
+
pools.push(members);
|
|
2328
|
+
}
|
|
2329
|
+
pools.sort((a, b) => a[0].name.localeCompare(b[0].name));
|
|
2330
|
+
return new Map(pools.map((members) => [members[0].name, members.map((m) => m.value)]));
|
|
2331
|
+
}
|
|
2332
|
+
function buildPools(sharedExternals, useAutoExternalPooling, log) {
|
|
2333
|
+
const candidates = Object.entries(sharedExternals).map(
|
|
2334
|
+
([name, external]) => ({
|
|
2335
|
+
name,
|
|
2336
|
+
scope: autoScope(name, useAutoExternalPooling),
|
|
2337
|
+
tags: external.versions.flatMap(
|
|
2338
|
+
(v) => v.remotes.flatMap((r) => {
|
|
2339
|
+
const tag = r.pool?.trim();
|
|
2340
|
+
return tag ? [{ remote: r.name, tag }] : [];
|
|
2341
|
+
})
|
|
2342
|
+
),
|
|
2343
|
+
value: { name, external }
|
|
2344
|
+
})
|
|
2345
|
+
);
|
|
2346
|
+
return groupByMembership(candidates, log);
|
|
2347
|
+
}
|
|
2348
|
+
|
|
2349
|
+
// src/lib/core/2.app/steps/pooling/pool.util.ts
|
|
2350
|
+
function versionForRemote(member, remote) {
|
|
2351
|
+
return member.external.versions.find((v) => v.remotes.some((r) => r.name === remote));
|
|
2352
|
+
}
|
|
2353
|
+
function remotesInPool(members) {
|
|
2354
|
+
return [
|
|
2355
|
+
...new Set(members.flatMap((m) => m.external.versions.flatMap((v) => v.remotes.map((r) => r.name))))
|
|
2356
|
+
];
|
|
2357
|
+
}
|
|
2358
|
+
|
|
2359
|
+
// src/lib/core/2.app/steps/pooling/pool-shared-externals.ts
|
|
2360
|
+
function poolWinners(members) {
|
|
2361
|
+
return members.map((member) => {
|
|
2362
|
+
const share = member.external.versions.find((v) => v.action === "share");
|
|
2363
|
+
return {
|
|
2364
|
+
member,
|
|
2365
|
+
tag: share?.tag ?? "",
|
|
2366
|
+
providers: new Set((share?.remotes ?? []).map((r) => r.name))
|
|
2367
|
+
};
|
|
2368
|
+
});
|
|
2369
|
+
}
|
|
2370
|
+
function selectCoverageAnchor(winners) {
|
|
2371
|
+
const coverage = /* @__PURE__ */ new Map();
|
|
2372
|
+
for (const winner of winners)
|
|
2373
|
+
for (const remote of winner.providers) coverage.set(remote, (coverage.get(remote) ?? 0) + 1);
|
|
2374
|
+
if (coverage.size === 0) return void 0;
|
|
2375
|
+
const anchorRemote = [...coverage.keys()].sort(
|
|
2376
|
+
(a, b) => coverage.get(b) - coverage.get(a) || a.localeCompare(b)
|
|
2377
|
+
)[0];
|
|
2378
|
+
return {
|
|
2379
|
+
anchorRemote,
|
|
2380
|
+
tagPerMember: Object.fromEntries(
|
|
2381
|
+
winners.filter((w) => w.providers.has(anchorRemote)).map((w) => [w.member.name, w.tag])
|
|
2382
|
+
)
|
|
2383
|
+
};
|
|
2384
|
+
}
|
|
2385
|
+
function classifyPoolConservative(members, anchor) {
|
|
2386
|
+
const classification = /* @__PURE__ */ new Map();
|
|
2387
|
+
for (const remote of remotesInPool(members)) {
|
|
2388
|
+
let coverageForced = false;
|
|
2389
|
+
let verdict = "follow";
|
|
2390
|
+
for (const member of members) {
|
|
2391
|
+
const version = versionForRemote(member, remote);
|
|
2392
|
+
if (!version) continue;
|
|
2393
|
+
const anchorTag = anchor.tagPerMember[member.name];
|
|
2394
|
+
if (!anchorTag) {
|
|
2395
|
+
coverageForced = true;
|
|
2396
|
+
continue;
|
|
2397
|
+
}
|
|
2398
|
+
if (version.tag === anchorTag) continue;
|
|
2399
|
+
if (version.action === "scope") {
|
|
2400
|
+
verdict = "scope-incompat";
|
|
2401
|
+
break;
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
classification.set(
|
|
2405
|
+
remote,
|
|
2406
|
+
verdict === "scope-incompat" ? "scope-incompat" : coverageForced ? "scope-coverage" : "follow"
|
|
2407
|
+
);
|
|
2408
|
+
}
|
|
2409
|
+
classification.set(anchor.anchorRemote, "follow");
|
|
2410
|
+
return classification;
|
|
2411
|
+
}
|
|
2412
|
+
function createPoolSharedExternals(config, ports) {
|
|
2413
|
+
return () => {
|
|
2414
|
+
const { useAutoExternalPooling } = config.feature;
|
|
2415
|
+
if (!useAutoExternalPooling && !ports.sharedExternalsRepo.hasPoolTag()) {
|
|
2416
|
+
return Promise.resolve();
|
|
2417
|
+
}
|
|
2418
|
+
for (const scope of ports.sharedExternalsRepo.getScopes()) {
|
|
2419
|
+
if (ports.sharedExternalsRepo.scopeType(scope) === "strict") continue;
|
|
2420
|
+
const sharedExternals = ports.sharedExternalsRepo.getFromScope(scope);
|
|
2421
|
+
try {
|
|
2422
|
+
for (const [poolName, members] of buildPools(
|
|
2423
|
+
sharedExternals,
|
|
2424
|
+
useAutoExternalPooling,
|
|
2425
|
+
config.log
|
|
2426
|
+
)) {
|
|
2427
|
+
poolFamily(poolName, members, scope);
|
|
2428
|
+
}
|
|
2429
|
+
} catch (error) {
|
|
2430
|
+
if (error instanceof NFError) return Promise.reject(error);
|
|
2431
|
+
config.log.error(3, `[${scope}] failed to pool shared externals.`, {
|
|
2432
|
+
sharedExternals,
|
|
2433
|
+
error
|
|
2434
|
+
});
|
|
2435
|
+
return Promise.reject(
|
|
2436
|
+
new NFError(`Could not pool shared externals in scope ${scope}.`, error)
|
|
2437
|
+
);
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
return Promise.resolve();
|
|
2441
|
+
};
|
|
2442
|
+
function poolFamily(poolName, members, scope) {
|
|
2443
|
+
if (members.length < 2) return;
|
|
2444
|
+
const allRemotes = remotesInPool(members);
|
|
2445
|
+
if (allRemotes.length < 2) return;
|
|
2446
|
+
const anchor = selectCoverageAnchor(poolWinners(members));
|
|
2447
|
+
if (!anchor) return;
|
|
2448
|
+
const classification = classifyPoolConservative(members, anchor);
|
|
2449
|
+
config.log.debug(
|
|
2450
|
+
3,
|
|
2451
|
+
`[${scope}][pool:${poolName}] members=[${members.map((m) => m.name).join(", ")}], anchor=${anchor.anchorRemote}, remotes={${allRemotes.map((r) => `${r}:${classification.get(r)}`).join(", ")}}`
|
|
2452
|
+
);
|
|
2453
|
+
const incompatForced = allRemotes.some((r) => classification.get(r) === "scope-incompat");
|
|
2454
|
+
if (incompatForced && config.strict.strictExternalCompatibility) {
|
|
2455
|
+
config.log.error(
|
|
2456
|
+
3,
|
|
2457
|
+
`[${scope}][pool:${poolName}] A remote is version-incompatible with anchor '${anchor.anchorRemote}'.`
|
|
2458
|
+
);
|
|
2459
|
+
throw new NFError(`Could not pool '${poolName}' in scope ${scope}.`);
|
|
2460
|
+
}
|
|
2461
|
+
for (const member of members) {
|
|
2462
|
+
const rebuilt = rebuildMember(member, anchor, classification);
|
|
2463
|
+
warnIfScopedOnly(poolName, member.name, rebuilt, scope);
|
|
2464
|
+
ports.sharedExternalsRepo.addOrUpdate(member.name, rebuilt, scope);
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
function warnIfScopedOnly(poolName, memberName, rebuilt, scope) {
|
|
2468
|
+
if (rebuilt.versions.some((v) => v.action === "share")) return;
|
|
2469
|
+
const copies = rebuilt.versions.reduce((n, v) => n + v.remotes.length, 0);
|
|
2470
|
+
config.log.warn(
|
|
2471
|
+
3,
|
|
2472
|
+
`[${scope}][pool:${poolName}] '${memberName}' is scoped-only \u2014 no coherent shared build provides it; ${copies} remotes download their own copy.`
|
|
2473
|
+
);
|
|
2474
|
+
}
|
|
2475
|
+
function rebuildMember(member, anchor, classification) {
|
|
2476
|
+
const anchorTag = anchor.tagPerMember[member.name];
|
|
2477
|
+
const entries = member.external.versions.flatMap(
|
|
2478
|
+
(v) => v.remotes.map((meta) => ({ remote: meta.name, tag: v.tag, host: v.host, meta }))
|
|
2479
|
+
);
|
|
2480
|
+
if (!anchorTag) {
|
|
2481
|
+
return {
|
|
2482
|
+
dirty: false,
|
|
2483
|
+
versions: entries.length > 0 ? [
|
|
2484
|
+
{
|
|
2485
|
+
tag: entries[0].tag,
|
|
2486
|
+
host: false,
|
|
2487
|
+
action: "scope",
|
|
2488
|
+
remotes: entries.map((e) => e.meta)
|
|
2489
|
+
}
|
|
2490
|
+
] : []
|
|
2491
|
+
};
|
|
2492
|
+
}
|
|
2493
|
+
const anchorMeta = entries.find(
|
|
2494
|
+
(e) => e.remote === anchor.anchorRemote && e.tag === anchorTag
|
|
2495
|
+
).meta;
|
|
2496
|
+
const anchorHost = member.external.versions.find((v) => v.tag === anchorTag)?.host ?? false;
|
|
2497
|
+
const scopes = (e) => {
|
|
2498
|
+
const cls = classification.get(e.remote);
|
|
2499
|
+
return cls === "scope-incompat" || cls === "scope-coverage" && e.tag !== anchorTag;
|
|
2500
|
+
};
|
|
2501
|
+
const shareOnAnchor = entries.filter(
|
|
2502
|
+
(e) => e.remote !== anchor.anchorRemote && e.tag === anchorTag && !scopes(e)
|
|
2503
|
+
);
|
|
2504
|
+
const shareVersion = {
|
|
2505
|
+
tag: anchorTag,
|
|
2506
|
+
host: anchorHost,
|
|
2507
|
+
action: "share",
|
|
2508
|
+
remotes: [anchorMeta, ...shareOnAnchor.map((e) => e.meta)]
|
|
2509
|
+
};
|
|
2510
|
+
const skipByTag = /* @__PURE__ */ new Map();
|
|
2511
|
+
for (const e of entries) {
|
|
2512
|
+
if (e.tag === anchorTag || scopes(e)) continue;
|
|
2513
|
+
const version = skipByTag.get(e.tag) ?? {
|
|
2514
|
+
tag: e.tag,
|
|
2515
|
+
host: e.host,
|
|
2516
|
+
action: "skip",
|
|
2517
|
+
remotes: []
|
|
2518
|
+
};
|
|
2519
|
+
version.remotes.push(e.meta);
|
|
2520
|
+
skipByTag.set(e.tag, version);
|
|
2521
|
+
}
|
|
2522
|
+
const scoped = entries.filter((e) => scopes(e));
|
|
2523
|
+
const scopeVersion = scoped.length > 0 ? [{ tag: anchorTag, host: false, action: "scope", remotes: scoped.map((e) => e.meta) }] : [];
|
|
2524
|
+
return {
|
|
2525
|
+
dirty: false,
|
|
2526
|
+
versions: [shareVersion, ...skipByTag.values(), ...scopeVersion]
|
|
2527
|
+
};
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
// node_modules/.pnpm/@softarc+native-federation@4.3.1_typescript@6.0.3/node_modules/@softarc/native-federation/dist/lib/domain/core/chunk.js
|
|
2236
2532
|
var CHUNK_PREFIX = "@nf-internal";
|
|
2237
2533
|
function toChunkImport(fileName) {
|
|
2238
2534
|
if (fileName.startsWith("./")) {
|
|
@@ -2267,12 +2563,9 @@ function createGenerateImportMap(config, ports) {
|
|
|
2267
2563
|
});
|
|
2268
2564
|
addToScope(importMap, remote.scopeUrl, createScopeModules(externals, remote.scopeUrl));
|
|
2269
2565
|
for (const version of Object.values(externals)) {
|
|
2270
|
-
|
|
2271
|
-
importMap,
|
|
2272
|
-
|
|
2273
|
-
remoteName,
|
|
2274
|
-
version.file
|
|
2275
|
-
);
|
|
2566
|
+
for (const file of Object.values(version.entries)) {
|
|
2567
|
+
addIntegrity(importMap, join(remote.scopeUrl, file), remoteName, file);
|
|
2568
|
+
}
|
|
2276
2569
|
}
|
|
2277
2570
|
Object.values(externals).filter((e) => !!e.bundle).forEach((e) => registerBundleChunks(chunkBundles, remoteName, e.bundle));
|
|
2278
2571
|
}
|
|
@@ -2280,8 +2573,10 @@ function createGenerateImportMap(config, ports) {
|
|
|
2280
2573
|
}
|
|
2281
2574
|
function createScopeModules(externals, scope) {
|
|
2282
2575
|
const modules = {};
|
|
2283
|
-
for (const
|
|
2284
|
-
|
|
2576
|
+
for (const version of Object.values(externals)) {
|
|
2577
|
+
for (const [packageName, file] of Object.entries(version.entries)) {
|
|
2578
|
+
modules[packageName] = join(scope, file);
|
|
2579
|
+
}
|
|
2285
2580
|
}
|
|
2286
2581
|
return modules;
|
|
2287
2582
|
}
|
|
@@ -2301,47 +2596,49 @@ function createGenerateImportMap(config, ports) {
|
|
|
2301
2596
|
if (version.action === "scope") {
|
|
2302
2597
|
for (const remote of version.remotes) {
|
|
2303
2598
|
const remoteScope = getScope2(shareScope, remote.name, externalName);
|
|
2304
|
-
const
|
|
2305
|
-
|
|
2306
|
-
[
|
|
2307
|
-
|
|
2308
|
-
|
|
2599
|
+
for (const [packageName, file] of Object.entries(remote.entries)) {
|
|
2600
|
+
const url = join(remoteScope, file);
|
|
2601
|
+
addToScope(importMap, remoteScope, { [packageName]: url });
|
|
2602
|
+
addIntegrity(importMap, url, remote.name, file);
|
|
2603
|
+
}
|
|
2309
2604
|
registerBundleChunks(chunkBundles, remote.name, remote.bundle);
|
|
2310
2605
|
remote.cached = true;
|
|
2311
2606
|
}
|
|
2312
2607
|
continue;
|
|
2313
2608
|
}
|
|
2314
|
-
const scope = getScope2(shareScope, version.remotes[0].name, externalName);
|
|
2315
|
-
let targetFileUrl = join(scope, version.remotes[0].file);
|
|
2316
|
-
let targetFileSource = {
|
|
2317
|
-
name: version.remotes[0].name,
|
|
2318
|
-
file: version.remotes[0].file
|
|
2319
|
-
};
|
|
2320
2609
|
version.remotes[0].cached = true;
|
|
2610
|
+
let source = version.remotes[0];
|
|
2611
|
+
let sourceScope = getScope2(shareScope, source.name, externalName);
|
|
2321
2612
|
if (version.action === "share") {
|
|
2322
|
-
registerBundleChunks(chunkBundles,
|
|
2323
|
-
}
|
|
2324
|
-
if (version.action === "skip") {
|
|
2613
|
+
registerBundleChunks(chunkBundles, source.name, source.bundle);
|
|
2614
|
+
} else if (version.action === "skip") {
|
|
2325
2615
|
if (!override) {
|
|
2326
2616
|
override = findOverride(external, shareScope, externalName) ?? "NOT_AVAILABLE";
|
|
2327
2617
|
}
|
|
2328
2618
|
if (override !== "NOT_AVAILABLE") {
|
|
2329
2619
|
if (!overrideScope)
|
|
2330
2620
|
overrideScope = getScope2(shareScope, override.remotes[0].name, externalName);
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
name: override.remotes[0].name,
|
|
2334
|
-
file: override.remotes[0].file
|
|
2335
|
-
};
|
|
2621
|
+
source = override.remotes[0];
|
|
2622
|
+
sourceScope = overrideScope;
|
|
2336
2623
|
override.remotes[0].cached = true;
|
|
2337
2624
|
version.remotes[0].cached = false;
|
|
2338
2625
|
}
|
|
2339
2626
|
}
|
|
2627
|
+
const mappings = Object.entries(source.entries).map(([packageName, file]) => ({
|
|
2628
|
+
packageName,
|
|
2629
|
+
url: join(sourceScope, file),
|
|
2630
|
+
name: source.name,
|
|
2631
|
+
file
|
|
2632
|
+
}));
|
|
2340
2633
|
version.remotes.forEach((r) => {
|
|
2341
|
-
const
|
|
2342
|
-
|
|
2634
|
+
const rScope = getScope2(shareScope, r.name, externalName);
|
|
2635
|
+
for (const m of mappings) {
|
|
2636
|
+
addToScope(importMap, rScope, { [m.packageName]: m.url });
|
|
2637
|
+
}
|
|
2343
2638
|
});
|
|
2344
|
-
|
|
2639
|
+
for (const m of mappings) {
|
|
2640
|
+
addIntegrity(importMap, m.url, m.name, m.file);
|
|
2641
|
+
}
|
|
2345
2642
|
}
|
|
2346
2643
|
ports.sharedExternalsRepo.addOrUpdate(externalName, external, shareScope);
|
|
2347
2644
|
}
|
|
@@ -2382,11 +2679,11 @@ function createGenerateImportMap(config, ports) {
|
|
|
2382
2679
|
if (version.action === "scope") {
|
|
2383
2680
|
for (const remote of version.remotes) {
|
|
2384
2681
|
const remoteScope = getScope2(GLOBAL_SCOPE, remote.name, externalName);
|
|
2385
|
-
const
|
|
2386
|
-
|
|
2387
|
-
[
|
|
2388
|
-
|
|
2389
|
-
|
|
2682
|
+
for (const [packageName, file] of Object.entries(remote.entries)) {
|
|
2683
|
+
const url = join(remoteScope, file);
|
|
2684
|
+
addToScope(importMap, remoteScope, { [packageName]: url });
|
|
2685
|
+
addIntegrity(importMap, url, remote.name, file);
|
|
2686
|
+
}
|
|
2390
2687
|
remote.cached = true;
|
|
2391
2688
|
registerBundleChunks(chunkBundles, remote.name, remote.bundle);
|
|
2392
2689
|
}
|
|
@@ -2397,9 +2694,11 @@ function createGenerateImportMap(config, ports) {
|
|
|
2397
2694
|
continue;
|
|
2398
2695
|
}
|
|
2399
2696
|
const scope = getScope2(GLOBAL_SCOPE, version.remotes[0].name, externalName);
|
|
2400
|
-
const
|
|
2401
|
-
|
|
2402
|
-
|
|
2697
|
+
for (const [packageName, file] of Object.entries(version.remotes[0].entries)) {
|
|
2698
|
+
const url = join(scope, file);
|
|
2699
|
+
addToGlobal(importMap, { [packageName]: url });
|
|
2700
|
+
addIntegrity(importMap, url, version.remotes[0].name, file);
|
|
2701
|
+
}
|
|
2403
2702
|
registerBundleChunks(chunkBundles, version.remotes[0].name, version.remotes[0].bundle);
|
|
2404
2703
|
version.remotes[0].cached = true;
|
|
2405
2704
|
}
|
|
@@ -2596,8 +2895,8 @@ function createUpdateCache(config, ports) {
|
|
|
2596
2895
|
storeRemoteEntry(remoteEntry, (entry, external, ctx) => {
|
|
2597
2896
|
const { action, sharedVersion } = resolveSharedExternal(entry, external, ctx);
|
|
2598
2897
|
actions[external.packageName] = { action };
|
|
2599
|
-
if (action === "skip" && external.shareScope && sharedVersion?.remotes[0]?.
|
|
2600
|
-
actions[external.packageName].override =
|
|
2898
|
+
if (action === "skip" && external.shareScope && sharedVersion?.remotes[0]?.entries) {
|
|
2899
|
+
actions[external.packageName].override = resolveOverrideEntries(
|
|
2601
2900
|
entry,
|
|
2602
2901
|
external,
|
|
2603
2902
|
sharedVersion
|
|
@@ -2641,8 +2940,15 @@ function createUpdateCache(config, ports) {
|
|
|
2641
2940
|
commit();
|
|
2642
2941
|
return { action, sharedVersion };
|
|
2643
2942
|
}
|
|
2644
|
-
function
|
|
2645
|
-
return ports.remoteInfoRepo.tryGet(sharedVersion.remotes[0].name).map(
|
|
2943
|
+
function resolveOverrideEntries(remoteEntry, external, sharedVersion) {
|
|
2944
|
+
return ports.remoteInfoRepo.tryGet(sharedVersion.remotes[0].name).map(
|
|
2945
|
+
(remote) => Object.fromEntries(
|
|
2946
|
+
Object.entries(sharedVersion.remotes[0].entries).map(([packageName, file]) => [
|
|
2947
|
+
packageName,
|
|
2948
|
+
join(remote.scopeUrl, file)
|
|
2949
|
+
])
|
|
2950
|
+
)
|
|
2951
|
+
).orThrow(() => {
|
|
2646
2952
|
config.log.error(
|
|
2647
2953
|
8,
|
|
2648
2954
|
`[${external.shareScope ?? GLOBAL_SCOPE}][${remoteEntry.name}][${external.packageName}@${external.version}][override] Remote name not found in cache.`
|
|
@@ -2654,14 +2960,56 @@ function createUpdateCache(config, ports) {
|
|
|
2654
2960
|
}
|
|
2655
2961
|
}
|
|
2656
2962
|
|
|
2657
|
-
// src/lib/core/2.app/steps/
|
|
2658
|
-
function
|
|
2963
|
+
// src/lib/core/2.app/steps/pooling/pool-dynamic-externals.ts
|
|
2964
|
+
function createPoolDynamicExternals(config) {
|
|
2659
2965
|
return ({ entry, actions }) => {
|
|
2966
|
+
const { useAutoExternalPooling } = config.feature;
|
|
2967
|
+
if (!useAutoExternalPooling && !(entry.shared ?? []).some((e) => e.pool?.trim())) {
|
|
2968
|
+
return Promise.resolve({ entry, actions });
|
|
2969
|
+
}
|
|
2970
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
2971
|
+
for (const external of entry.shared ?? []) {
|
|
2972
|
+
const name = external.packageName;
|
|
2973
|
+
if (!external.singleton || !actions[name]) continue;
|
|
2974
|
+
if (external.shareScope === STRICT_SCOPE) continue;
|
|
2975
|
+
const tag = external.pool?.trim();
|
|
2976
|
+
const shareScope = external.shareScope ?? GLOBAL_SCOPE;
|
|
2977
|
+
const candidates = byScope.get(shareScope) ?? [];
|
|
2978
|
+
candidates.push({
|
|
2979
|
+
name,
|
|
2980
|
+
scope: autoScope(name, useAutoExternalPooling),
|
|
2981
|
+
tags: tag ? [{ remote: entry.name, tag }] : [],
|
|
2982
|
+
value: name
|
|
2983
|
+
});
|
|
2984
|
+
byScope.set(shareScope, candidates);
|
|
2985
|
+
}
|
|
2986
|
+
const scope = (name) => {
|
|
2987
|
+
actions[name].action = "scope";
|
|
2988
|
+
delete actions[name].override;
|
|
2989
|
+
};
|
|
2990
|
+
for (const candidates of byScope.values()) {
|
|
2991
|
+
for (const members of groupByMembership(candidates).values()) {
|
|
2992
|
+
const memberActions = members.map((name) => actions[name].action);
|
|
2993
|
+
if (memberActions.includes("scope")) {
|
|
2994
|
+
members.forEach(scope);
|
|
2995
|
+
} else if (memberActions.includes("share") && memberActions.includes("skip")) {
|
|
2996
|
+
members.filter((name) => actions[name].action === "share").forEach(scope);
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
return Promise.resolve({ entry, actions });
|
|
3001
|
+
};
|
|
3002
|
+
}
|
|
3003
|
+
|
|
3004
|
+
// src/lib/core/2.app/steps/convert-to-import-map.ts
|
|
3005
|
+
function createConvertToImportMap(config, ports) {
|
|
3006
|
+
const { log } = config;
|
|
3007
|
+
return async ({ entry, actions }) => {
|
|
2660
3008
|
const importMap = { imports: {} };
|
|
2661
3009
|
addExternals(entry, actions, importMap);
|
|
2662
3010
|
addRemoteInfos(entry, importMap);
|
|
2663
3011
|
log.debug(9, `[${entry.name}] Processed actions:`, actions);
|
|
2664
|
-
return
|
|
3012
|
+
return importMap;
|
|
2665
3013
|
};
|
|
2666
3014
|
function addExternals(remoteEntry, actions, importMap) {
|
|
2667
3015
|
if (!remoteEntry.shared) {
|
|
@@ -2672,9 +3020,11 @@ function createConvertToImportMap({ log }, ports) {
|
|
|
2672
3020
|
const chunkBundles = /* @__PURE__ */ new Set(["mapping-or-exposed"]);
|
|
2673
3021
|
remoteEntry.shared.forEach((external) => {
|
|
2674
3022
|
if (!external.singleton) {
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
3023
|
+
Object.entries(external.entries).forEach(([packageName, fileName]) => {
|
|
3024
|
+
const url = join(remoteEntryScope, fileName);
|
|
3025
|
+
addToScopes(remoteEntryScope, packageName, url, importMap);
|
|
3026
|
+
addIntegrity(importMap, url, integrityMap, fileName);
|
|
3027
|
+
});
|
|
2678
3028
|
if (external?.bundle) chunkBundles.add(external?.bundle);
|
|
2679
3029
|
return;
|
|
2680
3030
|
}
|
|
@@ -2686,33 +3036,48 @@ function createConvertToImportMap({ log }, ports) {
|
|
|
2686
3036
|
return;
|
|
2687
3037
|
}
|
|
2688
3038
|
if (actions[external.packageName].action === "skip") {
|
|
3039
|
+
const override = actions[external.packageName].override;
|
|
2689
3040
|
if (!external.shareScope) return;
|
|
2690
|
-
if (
|
|
2691
|
-
|
|
2692
|
-
remoteEntryScope,
|
|
2693
|
-
|
|
2694
|
-
actions[external.packageName].override,
|
|
2695
|
-
importMap
|
|
2696
|
-
);
|
|
3041
|
+
if (override) {
|
|
3042
|
+
Object.entries(override).forEach(([packageName, url]) => {
|
|
3043
|
+
addToScopes(remoteEntryScope, packageName, url, importMap);
|
|
3044
|
+
});
|
|
2697
3045
|
return;
|
|
2698
3046
|
}
|
|
3047
|
+
log.error(
|
|
3048
|
+
9,
|
|
3049
|
+
`[${remoteEntry.name}][${external.packageName}] shareScope skip has no override.`
|
|
3050
|
+
);
|
|
3051
|
+
if (config.strict.strictImportMap) throw new NFError("Could not create ImportMap.");
|
|
3052
|
+
Object.entries(external.entries).forEach(([packageName, fileName]) => {
|
|
3053
|
+
const url = join(remoteEntryScope, fileName);
|
|
3054
|
+
addToScopes(remoteEntryScope, packageName, url, importMap);
|
|
3055
|
+
addIntegrity(importMap, url, integrityMap, fileName);
|
|
3056
|
+
});
|
|
3057
|
+
return;
|
|
2699
3058
|
}
|
|
2700
3059
|
if (external?.bundle) chunkBundles.add(external?.bundle);
|
|
2701
3060
|
if (actions[external.packageName].action === "scope") {
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
3061
|
+
Object.entries(external.entries).forEach(([packageName, fileName]) => {
|
|
3062
|
+
const url = join(remoteEntryScope, fileName);
|
|
3063
|
+
addToScopes(remoteEntryScope, packageName, url, importMap);
|
|
3064
|
+
addIntegrity(importMap, url, integrityMap, fileName);
|
|
3065
|
+
});
|
|
2705
3066
|
return;
|
|
2706
3067
|
}
|
|
2707
3068
|
if (external.shareScope) {
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
3069
|
+
Object.entries(external.entries).forEach(([packageName, fileName]) => {
|
|
3070
|
+
const url = join(remoteEntryScope, fileName);
|
|
3071
|
+
addToScopes(remoteEntryScope, packageName, url, importMap);
|
|
3072
|
+
addIntegrity(importMap, url, integrityMap, fileName);
|
|
3073
|
+
});
|
|
2711
3074
|
return;
|
|
2712
3075
|
}
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
3076
|
+
Object.entries(external.entries).forEach(([packageName, fileName]) => {
|
|
3077
|
+
const url = join(remoteEntryScope, fileName);
|
|
3078
|
+
importMap.imports[packageName] = url;
|
|
3079
|
+
addIntegrity(importMap, url, integrityMap, fileName);
|
|
3080
|
+
});
|
|
2716
3081
|
});
|
|
2717
3082
|
addChunkImports(importMap, remoteEntry, remoteEntryScope, chunkBundles);
|
|
2718
3083
|
}
|
|
@@ -2759,11 +3124,13 @@ var createInitDrivers = ({
|
|
|
2759
3124
|
getRemoteEntries: createGetRemoteEntries(config, adapters),
|
|
2760
3125
|
processRemoteEntries: createProcessRemoteEntries(config, adapters),
|
|
2761
3126
|
determineSharedExternals: createDetermineSharedExternals(config, adapters),
|
|
3127
|
+
poolSharedExternals: createPoolSharedExternals(config, adapters),
|
|
2762
3128
|
generateImportMap: createGenerateImportMap(config, adapters),
|
|
2763
3129
|
commitChanges: createCommitChanges(config, adapters),
|
|
2764
3130
|
exposeModuleLoader: createExposeModuleLoader(config, adapters),
|
|
2765
3131
|
getRemoteEntry: createGetRemoteEntry(config, adapters),
|
|
2766
3132
|
updateCache: createUpdateCache(config, adapters),
|
|
3133
|
+
poolDynamicExternals: createPoolDynamicExternals(config),
|
|
2767
3134
|
convertToImportMap: createConvertToImportMap(config, adapters)
|
|
2768
3135
|
});
|
|
2769
3136
|
var INIT_FLOW_FACTORY = ({
|