@softarc/native-federation-orchestrator 4.5.1 → 4.5.3
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 +405 -159
- package/fesm2022/@softarc/native-federation-orchestrator.mjs.map +4 -4
- package/fesm2022/module-federation.mjs +25 -20
- package/fesm2022/module-federation.mjs.map +2 -2
- package/fesm2022/node.mjs +401 -156
- package/fesm2022/node.mjs.map +3 -3
- package/fesm2022/options.mjs +5 -10
- package/fesm2022/options.mjs.map +2 -2
- package/package.json +2 -2
- package/quickstart.mjs +15 -13
- package/types/lib/core/1.domain/externals/basis.d.ts +7 -0
- package/types/lib/core/1.domain/remote-entry/remote-entry.contract.d.ts +1 -0
- package/types/lib/core/2.app/config/mode.contract.d.ts +2 -0
- package/types/lib/core/2.app/driving-ports/for-shared-externals-storage.port.d.ts +1 -1
- package/types/lib/core/2.app/steps/pooling/pool.types.d.ts +1 -20
- package/types/lib/core/2.app/steps/pooling/pool.util.d.ts +1 -2
- package/types/lib/core/2.app/steps/store-remote-entry.d.ts +15 -7
package/fesm2022/node.mjs
CHANGED
|
@@ -1490,16 +1490,21 @@ var createRemoteInfoRepository = (config) => {
|
|
|
1490
1490
|
const STORAGE = config.storage("remotes", {});
|
|
1491
1491
|
if (config.clearStorage) STORAGE.clear();
|
|
1492
1492
|
const _cache = STORAGE.get() ?? {};
|
|
1493
|
+
let _dirty = false;
|
|
1493
1494
|
return {
|
|
1494
1495
|
contains: function(remoteName) {
|
|
1495
1496
|
return !!_cache[remoteName];
|
|
1496
1497
|
},
|
|
1497
1498
|
remove: function(remoteName) {
|
|
1498
|
-
|
|
1499
|
+
if (remoteName in _cache) {
|
|
1500
|
+
delete _cache[remoteName];
|
|
1501
|
+
_dirty = true;
|
|
1502
|
+
}
|
|
1499
1503
|
return this;
|
|
1500
1504
|
},
|
|
1501
1505
|
addOrUpdate: function(remoteName, remote) {
|
|
1502
1506
|
_cache[remoteName] = remote;
|
|
1507
|
+
_dirty = true;
|
|
1503
1508
|
return this;
|
|
1504
1509
|
},
|
|
1505
1510
|
tryGet: function(remoteName) {
|
|
@@ -1514,7 +1519,9 @@ var createRemoteInfoRepository = (config) => {
|
|
|
1514
1519
|
return _cache;
|
|
1515
1520
|
},
|
|
1516
1521
|
commit: function() {
|
|
1522
|
+
if (!_dirty) return this;
|
|
1517
1523
|
STORAGE.set(_cache);
|
|
1524
|
+
_dirty = false;
|
|
1518
1525
|
return this;
|
|
1519
1526
|
}
|
|
1520
1527
|
};
|
|
@@ -1525,14 +1532,19 @@ var createScopedExternalsRepository = (config) => {
|
|
|
1525
1532
|
const STORAGE = config.storage("scoped-externals", {});
|
|
1526
1533
|
if (config.clearStorage) STORAGE.clear();
|
|
1527
1534
|
const _cache = STORAGE.get() ?? {};
|
|
1535
|
+
let _dirty = false;
|
|
1528
1536
|
return {
|
|
1529
1537
|
addExternal: function(remoteName, external, version) {
|
|
1530
1538
|
if (!_cache[remoteName]) _cache[remoteName] = {};
|
|
1531
1539
|
_cache[remoteName][external] = version;
|
|
1540
|
+
_dirty = true;
|
|
1532
1541
|
return this;
|
|
1533
1542
|
},
|
|
1534
1543
|
remove: function(remoteName) {
|
|
1535
|
-
|
|
1544
|
+
if (remoteName in _cache) {
|
|
1545
|
+
delete _cache[remoteName];
|
|
1546
|
+
_dirty = true;
|
|
1547
|
+
}
|
|
1536
1548
|
return this;
|
|
1537
1549
|
},
|
|
1538
1550
|
getAll: function() {
|
|
@@ -1542,7 +1554,9 @@ var createScopedExternalsRepository = (config) => {
|
|
|
1542
1554
|
return Optional.of(_cache[remoteName]);
|
|
1543
1555
|
},
|
|
1544
1556
|
commit: function() {
|
|
1557
|
+
if (!_dirty) return this;
|
|
1545
1558
|
STORAGE.set(_cache);
|
|
1559
|
+
_dirty = false;
|
|
1546
1560
|
return this;
|
|
1547
1561
|
}
|
|
1548
1562
|
};
|
|
@@ -1559,8 +1573,9 @@ var createSharedExternalsRepository = (config) => {
|
|
|
1559
1573
|
{ [GLOBAL_SCOPE]: {} }
|
|
1560
1574
|
);
|
|
1561
1575
|
if (config.clearStorage) STORAGE.clear();
|
|
1562
|
-
const _cache = STORAGE.get();
|
|
1576
|
+
const _cache = STORAGE.get() ?? { [GLOBAL_SCOPE]: {} };
|
|
1563
1577
|
let _sawPoolTag = false;
|
|
1578
|
+
let _dirty = false;
|
|
1564
1579
|
return {
|
|
1565
1580
|
markPoolTagPresent: function() {
|
|
1566
1581
|
_sawPoolTag = true;
|
|
@@ -1574,28 +1589,38 @@ var createSharedExternalsRepository = (config) => {
|
|
|
1574
1589
|
addOrUpdate: function(externalName, external, shareScope) {
|
|
1575
1590
|
if (!_cache[shareScope ?? GLOBAL_SCOPE]) _cache[shareScope ?? GLOBAL_SCOPE] = {};
|
|
1576
1591
|
_cache[shareScope ?? GLOBAL_SCOPE][externalName] = external;
|
|
1592
|
+
_dirty = true;
|
|
1577
1593
|
return this;
|
|
1578
1594
|
},
|
|
1579
1595
|
getScopes: function(o = { includeGlobal: true }) {
|
|
1580
1596
|
if (o.includeGlobal) return Object.keys(_cache);
|
|
1581
1597
|
return Object.keys(_cache).filter((s) => s !== GLOBAL_SCOPE);
|
|
1582
1598
|
},
|
|
1583
|
-
|
|
1599
|
+
// Batched: one traversal of the graph per init instead of one per overridden remote.
|
|
1600
|
+
removeFromAllScopes: function(remoteNames) {
|
|
1601
|
+
if (remoteNames.size === 0) return;
|
|
1584
1602
|
Object.values(_cache).forEach((scope) => {
|
|
1585
1603
|
const removeExternals = [];
|
|
1586
1604
|
Object.entries(scope).forEach(([name, external]) => {
|
|
1587
|
-
|
|
1588
|
-
external.versions.
|
|
1589
|
-
const
|
|
1590
|
-
|
|
1591
|
-
|
|
1605
|
+
let removedVersion = false;
|
|
1606
|
+
for (let i = external.versions.length - 1; i >= 0; i--) {
|
|
1607
|
+
const remotes = external.versions[i].remotes;
|
|
1608
|
+
let keep = 0;
|
|
1609
|
+
for (let r = 0; r < remotes.length; r++) {
|
|
1610
|
+
if (remoteNames.has(remotes[r].name)) continue;
|
|
1611
|
+
remotes[keep++] = remotes[r];
|
|
1592
1612
|
}
|
|
1593
|
-
if (
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1613
|
+
if (keep !== remotes.length) {
|
|
1614
|
+
remotes.length = keep;
|
|
1615
|
+
_dirty = true;
|
|
1616
|
+
}
|
|
1617
|
+
if (remotes.length === 0) {
|
|
1618
|
+
external.versions.splice(i, 1);
|
|
1619
|
+
removedVersion = true;
|
|
1620
|
+
_dirty = true;
|
|
1598
1621
|
}
|
|
1622
|
+
}
|
|
1623
|
+
if (removedVersion) {
|
|
1599
1624
|
external.dirty = true;
|
|
1600
1625
|
if (external.versions.length === 0) removeExternals.push(name);
|
|
1601
1626
|
}
|
|
@@ -1619,7 +1644,9 @@ var createSharedExternalsRepository = (config) => {
|
|
|
1619
1644
|
return Optional.of(_cache[shareScope ?? GLOBAL_SCOPE]?.[external]);
|
|
1620
1645
|
},
|
|
1621
1646
|
commit: function() {
|
|
1647
|
+
if (!_dirty) return this;
|
|
1622
1648
|
STORAGE.set(_cache);
|
|
1649
|
+
_dirty = false;
|
|
1623
1650
|
return this;
|
|
1624
1651
|
}
|
|
1625
1652
|
};
|
|
@@ -1630,17 +1657,21 @@ var createChunkRepository = (config) => {
|
|
|
1630
1657
|
const STORAGE = config.storage("shared-chunks", {});
|
|
1631
1658
|
if (config.clearStorage) STORAGE.clear();
|
|
1632
1659
|
const _cache = STORAGE.get() ?? {};
|
|
1660
|
+
let _dirty = false;
|
|
1633
1661
|
return {
|
|
1634
1662
|
addOrReplace: function(remoteName, bundleName, chunks) {
|
|
1635
1663
|
if (!_cache[remoteName]) _cache[remoteName] = {};
|
|
1636
1664
|
_cache[remoteName][bundleName] = chunks;
|
|
1665
|
+
_dirty = true;
|
|
1637
1666
|
return this;
|
|
1638
1667
|
},
|
|
1639
1668
|
tryGet: function(remoteName, bundleName) {
|
|
1640
1669
|
return Optional.of(_cache[remoteName]?.[bundleName]);
|
|
1641
1670
|
},
|
|
1642
1671
|
commit: function() {
|
|
1672
|
+
if (!_dirty) return this;
|
|
1643
1673
|
STORAGE.set(_cache);
|
|
1674
|
+
_dirty = false;
|
|
1644
1675
|
return this;
|
|
1645
1676
|
}
|
|
1646
1677
|
};
|
|
@@ -1830,10 +1861,9 @@ var globalThisStorageEntry = (namespace) => (key, initialValue) => {
|
|
|
1830
1861
|
globalThis[namespace] = {};
|
|
1831
1862
|
}
|
|
1832
1863
|
const storage = globalThis[namespace];
|
|
1833
|
-
if (!storage[key]) storage[key] = initialValue;
|
|
1834
1864
|
const entry = {
|
|
1835
1865
|
get() {
|
|
1836
|
-
return cloneEntry(key, storage[key]);
|
|
1866
|
+
return cloneEntry(key, key in storage ? storage[key] : initialValue);
|
|
1837
1867
|
},
|
|
1838
1868
|
set(value) {
|
|
1839
1869
|
storage[key] = cloneEntry(key, value);
|
|
@@ -1857,6 +1887,7 @@ var createStorageConfig = (override) => ({
|
|
|
1857
1887
|
var defaultProfile = {
|
|
1858
1888
|
latestSharedExternal: false,
|
|
1859
1889
|
skipInvalidExternalVersions: false,
|
|
1890
|
+
scopeUncoveredEntrypoints: false,
|
|
1860
1891
|
overrideCachedRemotes: "init-only",
|
|
1861
1892
|
overrideCachedRemotesIfURLMatches: false
|
|
1862
1893
|
};
|
|
@@ -1868,13 +1899,15 @@ var createModeConfig = (override) => {
|
|
|
1868
1899
|
strictExternalCompatibility: override.strict,
|
|
1869
1900
|
strictExternalSameVersionCompatibility: override.strict,
|
|
1870
1901
|
strictExternalVersion: override.strict,
|
|
1871
|
-
strictImportMap: override.strict
|
|
1902
|
+
strictImportMap: override.strict,
|
|
1903
|
+
strictEntryPointCoverage: override.strict
|
|
1872
1904
|
} : {
|
|
1873
1905
|
strictRemoteEntry: override.strict?.strictRemoteEntry ?? false,
|
|
1874
1906
|
strictExternalCompatibility: override.strict?.strictExternalCompatibility ?? false,
|
|
1875
1907
|
strictExternalSameVersionCompatibility: override.strict?.strictExternalSameVersionCompatibility ?? false,
|
|
1876
1908
|
strictExternalVersion: override.strict?.strictExternalVersion ?? false,
|
|
1877
|
-
strictImportMap: override.strict?.strictImportMap ?? false
|
|
1909
|
+
strictImportMap: override.strict?.strictImportMap ?? false,
|
|
1910
|
+
strictEntryPointCoverage: override.strict?.strictEntryPointCoverage ?? false
|
|
1878
1911
|
};
|
|
1879
1912
|
return {
|
|
1880
1913
|
strict: strictnessConfig,
|
|
@@ -2020,19 +2053,71 @@ function createGetRemoteEntries(config, ports) {
|
|
|
2020
2053
|
}
|
|
2021
2054
|
}
|
|
2022
2055
|
|
|
2056
|
+
// src/lib/core/1.domain/externals/basis.ts
|
|
2057
|
+
var coverage = (remote) => Object.keys(remote.entries).length;
|
|
2058
|
+
function isBetterBasis(candidate, basis) {
|
|
2059
|
+
if (basis.cached !== candidate.cached) return candidate.cached;
|
|
2060
|
+
return coverage(candidate) > coverage(basis);
|
|
2061
|
+
}
|
|
2062
|
+
function addRemoteToVersion(version, remote, isHost = false) {
|
|
2063
|
+
if (isHost) {
|
|
2064
|
+
version.host = true;
|
|
2065
|
+
version.remotes.unshift(remote);
|
|
2066
|
+
return;
|
|
2067
|
+
}
|
|
2068
|
+
const basis = version.remotes[0];
|
|
2069
|
+
if (basis && !version.host && isBetterBasis(remote, basis)) {
|
|
2070
|
+
version.remotes.unshift(remote);
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
version.remotes.push(remote);
|
|
2074
|
+
}
|
|
2075
|
+
function versionDemands(version) {
|
|
2076
|
+
if (version.remotes.length < 2) return version.remotes;
|
|
2077
|
+
const distinct = /* @__PURE__ */ new Map();
|
|
2078
|
+
for (const remote of version.remotes) {
|
|
2079
|
+
const key = `${remote.requiredVersion}|${remote.strictVersion}|${remote.cached}`;
|
|
2080
|
+
if (!distinct.has(key)) distinct.set(key, remote);
|
|
2081
|
+
}
|
|
2082
|
+
return Array.from(distinct.values());
|
|
2083
|
+
}
|
|
2084
|
+
function findVersionForTag(versions, tag) {
|
|
2085
|
+
let scoped;
|
|
2086
|
+
for (const version of versions) {
|
|
2087
|
+
if (version.tag !== tag) continue;
|
|
2088
|
+
if (version.action !== "scope") return version;
|
|
2089
|
+
scoped ??= version;
|
|
2090
|
+
}
|
|
2091
|
+
return scoped;
|
|
2092
|
+
}
|
|
2093
|
+
function uncoveredEntrypoints(remote, basis) {
|
|
2094
|
+
return Object.keys(remote.entries).filter((entrypoint) => !(entrypoint in basis));
|
|
2095
|
+
}
|
|
2096
|
+
function countUncoveredEntrypoints(remote, basis) {
|
|
2097
|
+
let uncovered = 0;
|
|
2098
|
+
for (const entrypoint in remote.entries) {
|
|
2099
|
+
if (!(entrypoint in basis)) uncovered++;
|
|
2100
|
+
}
|
|
2101
|
+
return uncovered;
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2023
2104
|
// src/lib/core/2.app/steps/store-remote-entry.ts
|
|
2105
|
+
function createRemoveCachedRemoteEntries(ports) {
|
|
2106
|
+
return (remoteNames) => {
|
|
2107
|
+
if (remoteNames.size === 0) return;
|
|
2108
|
+
for (const remoteName of remoteNames) {
|
|
2109
|
+
ports.remoteInfoRepo.remove(remoteName);
|
|
2110
|
+
ports.scopedExternalsRepo.remove(remoteName);
|
|
2111
|
+
}
|
|
2112
|
+
ports.sharedExternalsRepo.removeFromAllScopes(remoteNames);
|
|
2113
|
+
};
|
|
2114
|
+
}
|
|
2024
2115
|
function createStoreRemoteEntry(config, ports, logStep) {
|
|
2025
2116
|
return (remoteEntry, onSharedExternal) => {
|
|
2026
|
-
if (remoteEntry?.override) removeCachedRemoteEntry(remoteEntry);
|
|
2027
2117
|
addRemoteInfoToStorage(remoteEntry);
|
|
2028
2118
|
addExternalsToStorage(remoteEntry, onSharedExternal);
|
|
2029
2119
|
addSharedChunksToStorage(remoteEntry);
|
|
2030
2120
|
};
|
|
2031
|
-
function removeCachedRemoteEntry(remoteEntry) {
|
|
2032
|
-
ports.remoteInfoRepo.remove(remoteEntry.name);
|
|
2033
|
-
ports.scopedExternalsRepo.remove(remoteEntry.name);
|
|
2034
|
-
ports.sharedExternalsRepo.removeFromAllScopes(remoteEntry.name);
|
|
2035
|
-
}
|
|
2036
2121
|
function addRemoteInfoToStorage({ name, url, exposes, integrity }) {
|
|
2037
2122
|
ports.remoteInfoRepo.addOrUpdate(name, {
|
|
2038
2123
|
scopeUrl: getScope(url),
|
|
@@ -2132,14 +2217,35 @@ function createStoreRemoteEntry(config, ports, logStep) {
|
|
|
2132
2217
|
// src/lib/core/2.app/steps/process-remote-entries.ts
|
|
2133
2218
|
function createProcessRemoteEntries(config, ports) {
|
|
2134
2219
|
const storeRemoteEntry = createStoreRemoteEntry(config, ports, 2);
|
|
2220
|
+
const removeCachedRemoteEntries = createRemoveCachedRemoteEntries(ports);
|
|
2135
2221
|
return (remoteEntries) => {
|
|
2136
2222
|
try {
|
|
2137
|
-
|
|
2223
|
+
const evictPerEntry = evictOverriddenRemotes(remoteEntries);
|
|
2224
|
+
remoteEntries.forEach((remoteEntry) => {
|
|
2225
|
+
if (remoteEntry?.override && evictPerEntry.has(remoteEntry.name)) {
|
|
2226
|
+
removeCachedRemoteEntries(/* @__PURE__ */ new Set([remoteEntry.name]));
|
|
2227
|
+
}
|
|
2228
|
+
storeRemoteEntry(remoteEntry, addSharedExternal);
|
|
2229
|
+
});
|
|
2138
2230
|
return Promise.resolve(remoteEntries);
|
|
2139
2231
|
} catch (e) {
|
|
2140
2232
|
return Promise.reject(e);
|
|
2141
2233
|
}
|
|
2142
2234
|
};
|
|
2235
|
+
function evictOverriddenRemotes(remoteEntries) {
|
|
2236
|
+
const batched = /* @__PURE__ */ new Set();
|
|
2237
|
+
const repeated = /* @__PURE__ */ new Set();
|
|
2238
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2239
|
+
for (const remoteEntry of remoteEntries) {
|
|
2240
|
+
if (!remoteEntry) continue;
|
|
2241
|
+
if (seen.has(remoteEntry.name)) repeated.add(remoteEntry.name);
|
|
2242
|
+
seen.add(remoteEntry.name);
|
|
2243
|
+
if (remoteEntry.override) batched.add(remoteEntry.name);
|
|
2244
|
+
}
|
|
2245
|
+
for (const remoteName of repeated) batched.delete(remoteName);
|
|
2246
|
+
removeCachedRemoteEntries(batched);
|
|
2247
|
+
return repeated;
|
|
2248
|
+
}
|
|
2143
2249
|
function addSharedExternal(remoteEntry, _sharedInfo, {
|
|
2144
2250
|
tag,
|
|
2145
2251
|
remote,
|
|
@@ -2148,15 +2254,12 @@ function createProcessRemoteEntries(config, ports) {
|
|
|
2148
2254
|
assertSameVersionCompatibility,
|
|
2149
2255
|
commit
|
|
2150
2256
|
}) {
|
|
2151
|
-
|
|
2257
|
+
if (scopeType !== "strict") cached2.dirty = true;
|
|
2258
|
+
const matchingVersion = findVersionForTag(cached2.versions, tag);
|
|
2152
2259
|
if (matchingVersion) {
|
|
2153
2260
|
assertSameVersionCompatibility(matchingVersion);
|
|
2154
|
-
|
|
2155
|
-
matchingVersion.host = true;
|
|
2156
|
-
matchingVersion.remotes.unshift(remote);
|
|
2157
|
-
} else matchingVersion.remotes.push(remote);
|
|
2261
|
+
addRemoteToVersion(matchingVersion, remote, !matchingVersion.host && !!remoteEntry?.host);
|
|
2158
2262
|
} else {
|
|
2159
|
-
if (scopeType !== "strict") cached2.dirty = true;
|
|
2160
2263
|
cached2.versions.push({
|
|
2161
2264
|
tag,
|
|
2162
2265
|
action: scopeType === "strict" ? "share" : "skip",
|
|
@@ -2171,13 +2274,23 @@ function createProcessRemoteEntries(config, ports) {
|
|
|
2171
2274
|
// src/lib/core/2.app/steps/determine-shared-externals.ts
|
|
2172
2275
|
function createDetermineSharedExternals(config, ports) {
|
|
2173
2276
|
return () => {
|
|
2277
|
+
const memo = /* @__PURE__ */ new Map();
|
|
2278
|
+
const isCompatible = (tag, requiredVersion) => {
|
|
2279
|
+
const key = `${tag}|${requiredVersion}`;
|
|
2280
|
+
let hit = memo.get(key);
|
|
2281
|
+
if (hit === void 0) {
|
|
2282
|
+
hit = ports.versionCheck.isCompatible(tag, requiredVersion);
|
|
2283
|
+
memo.set(key, hit);
|
|
2284
|
+
}
|
|
2285
|
+
return hit;
|
|
2286
|
+
};
|
|
2174
2287
|
for (const shareScope of ports.sharedExternalsRepo.getScopes()) {
|
|
2175
2288
|
const sharedExternals = ports.sharedExternalsRepo.getFromScope(shareScope);
|
|
2176
2289
|
try {
|
|
2177
2290
|
Object.entries(sharedExternals).filter(([_, e]) => e.dirty).forEach(
|
|
2178
2291
|
([name, external]) => ports.sharedExternalsRepo.addOrUpdate(
|
|
2179
2292
|
name,
|
|
2180
|
-
setVersionActions(name, external),
|
|
2293
|
+
setVersionActions(name, external, isCompatible),
|
|
2181
2294
|
shareScope
|
|
2182
2295
|
)
|
|
2183
2296
|
);
|
|
@@ -2200,24 +2313,47 @@ function createDetermineSharedExternals(config, ports) {
|
|
|
2200
2313
|
}
|
|
2201
2314
|
return Promise.resolve();
|
|
2202
2315
|
};
|
|
2203
|
-
function
|
|
2316
|
+
function uncoveredTears(external, winner, accepts) {
|
|
2317
|
+
const basis = winner.remotes[0].entries;
|
|
2318
|
+
return external.versions.reduce((sum, v) => {
|
|
2319
|
+
if (v === winner) return sum;
|
|
2320
|
+
if (!accepts(v, winner.tag)) return sum;
|
|
2321
|
+
return sum + v.remotes.reduce((n, r) => n + countUncoveredEntrypoints(r, basis), 0);
|
|
2322
|
+
}, 0);
|
|
2323
|
+
}
|
|
2324
|
+
function setVersionActions(externalName, external, isCompatible) {
|
|
2204
2325
|
if (external.versions.length === 1) {
|
|
2205
2326
|
external.versions[0].action = "share";
|
|
2327
|
+
applyEntrypointCoveragePolicy(externalName, external);
|
|
2206
2328
|
external.dirty = false;
|
|
2207
2329
|
return external;
|
|
2208
2330
|
}
|
|
2331
|
+
const demands = new Map(
|
|
2332
|
+
external.versions.map((v) => [v, versionDemands(v)])
|
|
2333
|
+
);
|
|
2334
|
+
const accepts = (version, tag) => demands.get(version).every((d) => isCompatible(tag, d.requiredVersion));
|
|
2335
|
+
const objector = (version, tag) => demands.get(version).find((d) => d.strictVersion && !isCompatible(tag, d.requiredVersion));
|
|
2209
2336
|
let sharedVersion = external.versions.find((v) => v.host);
|
|
2210
2337
|
if (!sharedVersion && config.profile.latestSharedExternal) {
|
|
2211
2338
|
sharedVersion = external.versions[0];
|
|
2212
2339
|
}
|
|
2213
2340
|
if (!sharedVersion) {
|
|
2214
2341
|
let leastExtraDownloads = Number.MAX_VALUE;
|
|
2342
|
+
let leastTears = Number.MAX_VALUE;
|
|
2215
2343
|
external.versions.forEach((vA) => {
|
|
2216
2344
|
const extraDownloads = external.versions.filter(
|
|
2217
|
-
(vB) =>
|
|
2345
|
+
(vB) => demands.get(vB).some((d) => !d.cached && d.strictVersion && !isCompatible(vA.tag, d.requiredVersion))
|
|
2218
2346
|
).length;
|
|
2219
2347
|
if (extraDownloads < leastExtraDownloads) {
|
|
2220
2348
|
leastExtraDownloads = extraDownloads;
|
|
2349
|
+
leastTears = uncoveredTears(external, vA, accepts);
|
|
2350
|
+
sharedVersion = vA;
|
|
2351
|
+
return;
|
|
2352
|
+
}
|
|
2353
|
+
if (extraDownloads > leastExtraDownloads) return;
|
|
2354
|
+
const tears = uncoveredTears(external, vA, accepts);
|
|
2355
|
+
if (tears < leastTears) {
|
|
2356
|
+
leastTears = tears;
|
|
2221
2357
|
sharedVersion = vA;
|
|
2222
2358
|
}
|
|
2223
2359
|
});
|
|
@@ -2226,23 +2362,81 @@ function createDetermineSharedExternals(config, ports) {
|
|
|
2226
2362
|
throw new NFError(`[${externalName}] Could not determine shared version!`);
|
|
2227
2363
|
}
|
|
2228
2364
|
external.versions.forEach((v) => {
|
|
2229
|
-
if (
|
|
2365
|
+
if (accepts(v, sharedVersion.tag)) {
|
|
2230
2366
|
v.action = "skip";
|
|
2231
2367
|
return;
|
|
2232
2368
|
}
|
|
2233
|
-
|
|
2369
|
+
const strict = objector(v, sharedVersion.tag);
|
|
2370
|
+
if (config.strict.strictExternalCompatibility && strict) {
|
|
2234
2371
|
config.log.error(
|
|
2235
2372
|
3,
|
|
2236
|
-
`[${
|
|
2373
|
+
`[${strict.name}][${externalName}@${v.tag}] Is not compatible with requiredRange '${strict.requiredVersion}' of shared ${externalName}@${sharedVersion.tag}.`
|
|
2237
2374
|
);
|
|
2238
2375
|
throw new NFError(`External ${externalName}@${v.tag} could not be shared.`);
|
|
2239
2376
|
}
|
|
2240
|
-
v.action =
|
|
2377
|
+
v.action = strict ? "scope" : "skip";
|
|
2241
2378
|
});
|
|
2242
2379
|
sharedVersion.action = "share";
|
|
2380
|
+
applyEntrypointCoveragePolicy(externalName, external);
|
|
2243
2381
|
external.dirty = false;
|
|
2244
2382
|
return external;
|
|
2245
2383
|
}
|
|
2384
|
+
function applyEntrypointCoveragePolicy(externalName, external) {
|
|
2385
|
+
const { strictEntryPointCoverage } = config.strict;
|
|
2386
|
+
if (!strictEntryPointCoverage && !config.profile.scopeUncoveredEntrypoints) return;
|
|
2387
|
+
const tears = findTears(external);
|
|
2388
|
+
if (tears.length === 0) return;
|
|
2389
|
+
if (strictEntryPointCoverage) {
|
|
2390
|
+
const { version, remote, uncovered } = tears[0];
|
|
2391
|
+
config.log.error(
|
|
2392
|
+
3,
|
|
2393
|
+
`[${externalName}@${version.tag}][${remote.name}] Entrypoints not covered by the shared version: ${uncovered.join(", ")}.`
|
|
2394
|
+
);
|
|
2395
|
+
throw new NFError(
|
|
2396
|
+
`External ${externalName} could not be shared without tearing entrypoints.`
|
|
2397
|
+
);
|
|
2398
|
+
}
|
|
2399
|
+
scopeTornRemotes(externalName, external, tears);
|
|
2400
|
+
}
|
|
2401
|
+
function findTears(external) {
|
|
2402
|
+
const shared = external.versions.find((v) => v.action === "share");
|
|
2403
|
+
if (!shared) return [];
|
|
2404
|
+
const basis = shared.remotes[0].entries;
|
|
2405
|
+
const tears = [];
|
|
2406
|
+
for (const version of external.versions) {
|
|
2407
|
+
if (version.action === "scope") continue;
|
|
2408
|
+
version.remotes.forEach((remote, index) => {
|
|
2409
|
+
if (version === shared && index === 0) return;
|
|
2410
|
+
const uncovered = uncoveredEntrypoints(remote, basis);
|
|
2411
|
+
if (uncovered.length > 0) tears.push({ version, remote, uncovered });
|
|
2412
|
+
});
|
|
2413
|
+
}
|
|
2414
|
+
return tears;
|
|
2415
|
+
}
|
|
2416
|
+
function scopeTornRemotes(externalName, external, tears) {
|
|
2417
|
+
const torn = new Set(tears.map((t) => t.remote));
|
|
2418
|
+
const demotedByTag = /* @__PURE__ */ new Map();
|
|
2419
|
+
for (const { version, remote, uncovered } of tears) {
|
|
2420
|
+
const group = demotedByTag.get(version.tag);
|
|
2421
|
+
if (group) group.push(remote);
|
|
2422
|
+
else demotedByTag.set(version.tag, [remote]);
|
|
2423
|
+
config.log.debug(
|
|
2424
|
+
3,
|
|
2425
|
+
`[${externalName}@${version.tag}][${remote.name}] Scoped: entrypoints not covered by the shared version: ${uncovered.join(", ")}.`
|
|
2426
|
+
);
|
|
2427
|
+
}
|
|
2428
|
+
for (const version of external.versions) {
|
|
2429
|
+
if (version.remotes.some((r) => torn.has(r))) {
|
|
2430
|
+
version.remotes = version.remotes.filter((r) => !torn.has(r));
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
external.versions = external.versions.filter((v) => v.remotes.length > 0);
|
|
2434
|
+
for (const [tag, remotes] of demotedByTag) {
|
|
2435
|
+
const scoped = external.versions.find((v) => v.tag === tag && v.action === "scope");
|
|
2436
|
+
if (scoped) scoped.remotes.push(...remotes);
|
|
2437
|
+
else external.versions.push({ tag, host: false, action: "scope", remotes });
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2246
2440
|
}
|
|
2247
2441
|
|
|
2248
2442
|
// src/lib/core/2.app/steps/pooling/pool-graph.ts
|
|
@@ -2347,9 +2541,6 @@ function buildPools(sharedExternals, useAutoExternalPooling, log) {
|
|
|
2347
2541
|
}
|
|
2348
2542
|
|
|
2349
2543
|
// 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
2544
|
function remotesInPool(members) {
|
|
2354
2545
|
return [
|
|
2355
2546
|
...new Set(members.flatMap((m) => m.external.versions.flatMap((v) => v.remotes.map((r) => r.name))))
|
|
@@ -2357,57 +2548,12 @@ function remotesInPool(members) {
|
|
|
2357
2548
|
}
|
|
2358
2549
|
|
|
2359
2550
|
// src/lib/core/2.app/steps/pooling/pool-shared-externals.ts
|
|
2360
|
-
function
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
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;
|
|
2551
|
+
function islandedRemotes(members) {
|
|
2552
|
+
const islanded = /* @__PURE__ */ new Set();
|
|
2553
|
+
for (const member of members)
|
|
2554
|
+
for (const version of member.external.versions)
|
|
2555
|
+
if (version.action === "scope") for (const remote of version.remotes) islanded.add(remote.name);
|
|
2556
|
+
return islanded;
|
|
2411
2557
|
}
|
|
2412
2558
|
function createPoolSharedExternals(config, ports) {
|
|
2413
2559
|
return () => {
|
|
@@ -2443,73 +2589,57 @@ function createPoolSharedExternals(config, ports) {
|
|
|
2443
2589
|
if (members.length < 2) return;
|
|
2444
2590
|
const allRemotes = remotesInPool(members);
|
|
2445
2591
|
if (allRemotes.length < 2) return;
|
|
2446
|
-
const
|
|
2447
|
-
if (!anchor) return;
|
|
2448
|
-
const classification = classifyPoolConservative(members, anchor);
|
|
2592
|
+
const islanded = islandedRemotes(members);
|
|
2449
2593
|
config.log.debug(
|
|
2450
2594
|
3,
|
|
2451
|
-
`[${scope}][pool:${poolName}]
|
|
2595
|
+
`[${scope}][pool:${poolName}] ${members.length} members across ${allRemotes.length} remotes, islanded={${[...islanded].join(", ") || "\u2205"}}
|
|
2596
|
+
` + members.map((m) => ` - ${m.name}`).join("\n")
|
|
2452
2597
|
);
|
|
2453
|
-
|
|
2454
|
-
if (incompatForced && config.strict.strictExternalCompatibility) {
|
|
2598
|
+
if (islanded.size > 0 && config.strict.strictExternalCompatibility) {
|
|
2455
2599
|
config.log.error(
|
|
2456
2600
|
3,
|
|
2457
|
-
`[${scope}][pool:${poolName}]
|
|
2601
|
+
`[${scope}][pool:${poolName}] version-incompatible remotes cannot be pooled: {${[...islanded].join(", ")}}.`
|
|
2458
2602
|
);
|
|
2459
2603
|
throw new NFError(`Could not pool '${poolName}' in scope ${scope}.`);
|
|
2460
2604
|
}
|
|
2461
2605
|
for (const member of members) {
|
|
2462
|
-
const rebuilt = rebuildMember(member,
|
|
2606
|
+
const rebuilt = rebuildMember(member, islanded);
|
|
2463
2607
|
warnIfScopedOnly(poolName, member.name, rebuilt, scope);
|
|
2464
2608
|
ports.sharedExternalsRepo.addOrUpdate(member.name, rebuilt, scope);
|
|
2465
2609
|
}
|
|
2466
2610
|
}
|
|
2467
2611
|
function warnIfScopedOnly(poolName, memberName, rebuilt, scope) {
|
|
2468
2612
|
if (rebuilt.versions.some((v) => v.action === "share")) return;
|
|
2469
|
-
const
|
|
2613
|
+
const consumers = new Set(rebuilt.versions.flatMap((v) => v.remotes.map((r) => r.name))).size;
|
|
2614
|
+
if (consumers < 2) return;
|
|
2470
2615
|
config.log.warn(
|
|
2471
2616
|
3,
|
|
2472
|
-
`[${scope}][pool:${poolName}] '${memberName}' is scoped-only \u2014 no coherent shared build provides it; ${
|
|
2617
|
+
`[${scope}][pool:${poolName}] '${memberName}' is scoped-only \u2014 no coherent shared build provides it; ${consumers} remotes download their own copy.`
|
|
2473
2618
|
);
|
|
2474
2619
|
}
|
|
2475
|
-
function rebuildMember(member,
|
|
2476
|
-
const anchorTag = anchor.tagPerMember[member.name];
|
|
2620
|
+
function rebuildMember(member, islanded) {
|
|
2477
2621
|
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)
|
|
2622
|
+
(v) => v.remotes.map((meta) => ({ remote: meta.name, tag: v.tag, host: v.host, action: v.action, meta }))
|
|
2503
2623
|
);
|
|
2504
|
-
const
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2624
|
+
const isScoped = (e) => islanded.has(e.remote) || e.action === "scope";
|
|
2625
|
+
let scoped = entries.filter(isScoped);
|
|
2626
|
+
let clean = entries.filter((e) => !isScoped(e));
|
|
2627
|
+
if (!clean.some((e) => e.action === "share")) {
|
|
2628
|
+
scoped = [...scoped, ...clean];
|
|
2629
|
+
clean = [];
|
|
2630
|
+
}
|
|
2631
|
+
const shareEntries = clean.filter((e) => e.action === "share");
|
|
2632
|
+
const shareVersion = shareEntries.length > 0 ? [
|
|
2633
|
+
{
|
|
2634
|
+
tag: shareEntries[0].tag,
|
|
2635
|
+
host: shareEntries[0].host,
|
|
2636
|
+
action: "share",
|
|
2637
|
+
remotes: shareEntries.map((e) => e.meta)
|
|
2638
|
+
}
|
|
2639
|
+
] : [];
|
|
2510
2640
|
const skipByTag = /* @__PURE__ */ new Map();
|
|
2511
|
-
for (const e of
|
|
2512
|
-
if (e.
|
|
2641
|
+
for (const e of clean) {
|
|
2642
|
+
if (e.action !== "skip") continue;
|
|
2513
2643
|
const version = skipByTag.get(e.tag) ?? {
|
|
2514
2644
|
tag: e.tag,
|
|
2515
2645
|
host: e.host,
|
|
@@ -2519,16 +2649,25 @@ function createPoolSharedExternals(config, ports) {
|
|
|
2519
2649
|
version.remotes.push(e.meta);
|
|
2520
2650
|
skipByTag.set(e.tag, version);
|
|
2521
2651
|
}
|
|
2522
|
-
const
|
|
2523
|
-
const
|
|
2652
|
+
const scopeByTag = /* @__PURE__ */ new Map();
|
|
2653
|
+
for (const e of scoped) {
|
|
2654
|
+
const version = scopeByTag.get(e.tag) ?? {
|
|
2655
|
+
tag: e.tag,
|
|
2656
|
+
host: false,
|
|
2657
|
+
action: "scope",
|
|
2658
|
+
remotes: []
|
|
2659
|
+
};
|
|
2660
|
+
version.remotes.push(e.meta);
|
|
2661
|
+
scopeByTag.set(e.tag, version);
|
|
2662
|
+
}
|
|
2524
2663
|
return {
|
|
2525
2664
|
dirty: false,
|
|
2526
|
-
versions: [shareVersion, ...skipByTag.values(), ...
|
|
2665
|
+
versions: [...shareVersion, ...skipByTag.values(), ...scopeByTag.values()]
|
|
2527
2666
|
};
|
|
2528
2667
|
}
|
|
2529
2668
|
}
|
|
2530
2669
|
|
|
2531
|
-
// node_modules/.pnpm/@softarc+native-federation@4.3.
|
|
2670
|
+
// node_modules/.pnpm/@softarc+native-federation@4.3.2_typescript@6.0.3/node_modules/@softarc/native-federation/dist/lib/domain/core/chunk.js
|
|
2532
2671
|
var CHUNK_PREFIX = "@nf-internal";
|
|
2533
2672
|
function toChunkImport(fileName) {
|
|
2534
2673
|
if (fileName.startsWith("./")) {
|
|
@@ -2592,6 +2731,7 @@ function createGenerateImportMap(config, ports) {
|
|
|
2592
2731
|
for (const [externalName, external] of Object.entries(sharedExternals)) {
|
|
2593
2732
|
let override = void 0;
|
|
2594
2733
|
let overrideScope = void 0;
|
|
2734
|
+
const cachedBefore = cachedFingerprint(external);
|
|
2595
2735
|
for (const version of external.versions) {
|
|
2596
2736
|
if (version.action === "scope") {
|
|
2597
2737
|
for (const remote of version.remotes) {
|
|
@@ -2635,14 +2775,30 @@ function createGenerateImportMap(config, ports) {
|
|
|
2635
2775
|
for (const m of mappings) {
|
|
2636
2776
|
addToScope(importMap, rScope, { [m.packageName]: m.url });
|
|
2637
2777
|
}
|
|
2778
|
+
for (const [packageName, file] of Object.entries(r.entries)) {
|
|
2779
|
+
if (packageName in source.entries) continue;
|
|
2780
|
+
if (config.strict.strictEntryPointCoverage || config.profile.scopeUncoveredEntrypoints) {
|
|
2781
|
+
warnUncoveredEntrypoint(shareScope, externalName, r.name, packageName);
|
|
2782
|
+
continue;
|
|
2783
|
+
}
|
|
2784
|
+
const url = join(rScope, file);
|
|
2785
|
+
addToScope(importMap, rScope, { [packageName]: url });
|
|
2786
|
+
addIntegrity(importMap, url, r.name, file);
|
|
2787
|
+
r.cached = true;
|
|
2788
|
+
}
|
|
2638
2789
|
});
|
|
2639
2790
|
for (const m of mappings) {
|
|
2640
2791
|
addIntegrity(importMap, m.url, m.name, m.file);
|
|
2641
2792
|
}
|
|
2642
2793
|
}
|
|
2643
|
-
|
|
2794
|
+
if (cachedFingerprint(external) !== cachedBefore) {
|
|
2795
|
+
ports.sharedExternalsRepo.addOrUpdate(externalName, external, shareScope);
|
|
2796
|
+
}
|
|
2644
2797
|
}
|
|
2645
2798
|
}
|
|
2799
|
+
function cachedFingerprint(external) {
|
|
2800
|
+
return external.versions.map((v) => v.remotes.map((r) => r.cached ? 1 : 0).join("")).join("|");
|
|
2801
|
+
}
|
|
2646
2802
|
function findOverride(external, shareScope, externalName) {
|
|
2647
2803
|
const sharedVersions = external.versions.filter((v) => v.action === "share");
|
|
2648
2804
|
const scopedExternalName = `${shareScope}.${externalName}`;
|
|
@@ -2674,6 +2830,7 @@ function createGenerateImportMap(config, ports) {
|
|
|
2674
2830
|
function addGlobalSharedExternals(importMap, chunkBundles) {
|
|
2675
2831
|
const sharedExternals = ports.sharedExternalsRepo.getFromScope();
|
|
2676
2832
|
for (const [externalName, external] of Object.entries(sharedExternals)) {
|
|
2833
|
+
const cachedBefore = cachedFingerprint(external);
|
|
2677
2834
|
for (const version of external.versions) {
|
|
2678
2835
|
if (version.action === "skip") continue;
|
|
2679
2836
|
if (version.action === "scope") {
|
|
@@ -2701,11 +2858,44 @@ function createGenerateImportMap(config, ports) {
|
|
|
2701
2858
|
}
|
|
2702
2859
|
registerBundleChunks(chunkBundles, version.remotes[0].name, version.remotes[0].bundle);
|
|
2703
2860
|
version.remotes[0].cached = true;
|
|
2861
|
+
selfFillUncovered(importMap, chunkBundles, externalName, version.remotes, 1);
|
|
2862
|
+
}
|
|
2863
|
+
for (const version of external.versions) {
|
|
2864
|
+
if (version.action !== "skip") continue;
|
|
2865
|
+
selfFillUncovered(importMap, chunkBundles, externalName, version.remotes);
|
|
2866
|
+
}
|
|
2867
|
+
if (cachedFingerprint(external) !== cachedBefore) {
|
|
2868
|
+
ports.sharedExternalsRepo.addOrUpdate(externalName, external);
|
|
2704
2869
|
}
|
|
2705
|
-
ports.sharedExternalsRepo.addOrUpdate(externalName, external);
|
|
2706
2870
|
}
|
|
2707
2871
|
return importMap;
|
|
2708
2872
|
}
|
|
2873
|
+
function selfFillUncovered(importMap, chunkBundles, externalName, remotes, from = 0) {
|
|
2874
|
+
for (let i = from; i < remotes.length; i++) {
|
|
2875
|
+
const remote = remotes[i];
|
|
2876
|
+
for (const [packageName, file] of Object.entries(remote.entries)) {
|
|
2877
|
+
if (importMap.imports[packageName]) continue;
|
|
2878
|
+
if (config.strict.strictEntryPointCoverage || config.profile.scopeUncoveredEntrypoints) {
|
|
2879
|
+
warnUncoveredEntrypoint(GLOBAL_SCOPE, externalName, remote.name, packageName);
|
|
2880
|
+
continue;
|
|
2881
|
+
}
|
|
2882
|
+
const scope = getScope2(GLOBAL_SCOPE, remote.name, externalName);
|
|
2883
|
+
const url = join(scope, file);
|
|
2884
|
+
addToGlobal(importMap, { [packageName]: url });
|
|
2885
|
+
addIntegrity(importMap, url, remote.name, file);
|
|
2886
|
+
registerBundleChunks(chunkBundles, remote.name, remote.bundle);
|
|
2887
|
+
remote.cached = true;
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2891
|
+
function warnUncoveredEntrypoint(scope, externalName, remoteName, packageName) {
|
|
2892
|
+
const msg = `[${scope}][${externalName}][${remoteName}] Entrypoint '${packageName}' is not covered by the shared version.`;
|
|
2893
|
+
if (config.strict.strictEntryPointCoverage || config.strict.strictImportMap) {
|
|
2894
|
+
config.log.error(4, msg);
|
|
2895
|
+
throw new NFError("Could not create ImportMap.");
|
|
2896
|
+
}
|
|
2897
|
+
config.log.warn(4, msg);
|
|
2898
|
+
}
|
|
2709
2899
|
function notifyDuplicateGlobalExternal(externalName) {
|
|
2710
2900
|
if (config.strict.strictImportMap) {
|
|
2711
2901
|
config.log.error(4, `[${externalName}] Shared external has multiple shared versions.`);
|
|
@@ -2889,18 +3079,23 @@ function createGetRemoteEntry(config, ports) {
|
|
|
2889
3079
|
// src/lib/core/2.app/steps/update-cache.ts
|
|
2890
3080
|
function createUpdateCache(config, ports) {
|
|
2891
3081
|
const storeRemoteEntry = createStoreRemoteEntry(config, ports, 8);
|
|
3082
|
+
const removeCachedRemoteEntries = createRemoveCachedRemoteEntries(ports);
|
|
2892
3083
|
return (remoteEntry) => {
|
|
2893
3084
|
try {
|
|
2894
3085
|
const actions = {};
|
|
3086
|
+
if (remoteEntry?.override) removeCachedRemoteEntries(/* @__PURE__ */ new Set([remoteEntry.name]));
|
|
2895
3087
|
storeRemoteEntry(remoteEntry, (entry, external, ctx) => {
|
|
2896
3088
|
const { action, sharedVersion } = resolveSharedExternal(entry, external, ctx);
|
|
2897
3089
|
actions[external.packageName] = { action };
|
|
2898
|
-
if (action === "skip" &&
|
|
2899
|
-
actions[external.packageName].
|
|
2900
|
-
|
|
2901
|
-
external
|
|
2902
|
-
|
|
2903
|
-
|
|
3090
|
+
if (action === "skip" && sharedVersion?.remotes[0]?.entries) {
|
|
3091
|
+
actions[external.packageName].covered = Object.keys(sharedVersion.remotes[0].entries);
|
|
3092
|
+
if (external.shareScope) {
|
|
3093
|
+
actions[external.packageName].override = resolveOverrideEntries(
|
|
3094
|
+
entry,
|
|
3095
|
+
external,
|
|
3096
|
+
sharedVersion
|
|
3097
|
+
);
|
|
3098
|
+
}
|
|
2904
3099
|
}
|
|
2905
3100
|
});
|
|
2906
3101
|
return Promise.resolve({ entry: remoteEntry, actions });
|
|
@@ -2928,10 +3123,29 @@ function createUpdateCache(config, ports) {
|
|
|
2928
3123
|
}
|
|
2929
3124
|
config.log.warn(8, errorMsg);
|
|
2930
3125
|
}
|
|
2931
|
-
|
|
2932
|
-
|
|
3126
|
+
if (action === "skip" && sharedVersion) {
|
|
3127
|
+
const uncovered = uncoveredEntrypoints(remote, sharedVersion.remotes[0].entries);
|
|
3128
|
+
if (uncovered.length > 0) {
|
|
3129
|
+
const msg = `[${sharedInfo.shareScope ?? GLOBAL_SCOPE}][${remoteEntry.name}][${sharedInfo.packageName}] Entrypoints not covered by the shared version: ${uncovered.join(", ")}.`;
|
|
3130
|
+
if (config.strict.strictEntryPointCoverage) {
|
|
3131
|
+
config.log.error(8, msg);
|
|
3132
|
+
throw new NFError(`Could not process remote '${remoteEntry.name}'`);
|
|
3133
|
+
}
|
|
3134
|
+
if (config.profile.scopeUncoveredEntrypoints) {
|
|
3135
|
+
config.log.debug(8, msg);
|
|
3136
|
+
action = "scope";
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
}
|
|
3140
|
+
const matchingVersion = findVersionForTag(cached2.versions, tag);
|
|
3141
|
+
if (action === "scope") {
|
|
3142
|
+
remote.cached = true;
|
|
3143
|
+
const scoped = cached2.versions.find((v) => v.tag === tag && v.action === "scope");
|
|
3144
|
+
if (scoped) scoped.remotes.push(remote);
|
|
3145
|
+
else cached2.versions.push({ tag, action, host: false, remotes: [remote] });
|
|
3146
|
+
} else if (matchingVersion) {
|
|
2933
3147
|
assertSameVersionCompatibility(matchingVersion);
|
|
2934
|
-
matchingVersion
|
|
3148
|
+
addRemoteToVersion(matchingVersion, remote);
|
|
2935
3149
|
} else {
|
|
2936
3150
|
if (!sharedVersion) action = "share";
|
|
2937
3151
|
remote.cached = action !== "skip";
|
|
@@ -2992,8 +3206,6 @@ function createPoolDynamicExternals(config) {
|
|
|
2992
3206
|
const memberActions = members.map((name) => actions[name].action);
|
|
2993
3207
|
if (memberActions.includes("scope")) {
|
|
2994
3208
|
members.forEach(scope);
|
|
2995
|
-
} else if (memberActions.includes("share") && memberActions.includes("skip")) {
|
|
2996
|
-
members.filter((name) => actions[name].action === "share").forEach(scope);
|
|
2997
3209
|
}
|
|
2998
3210
|
}
|
|
2999
3211
|
}
|
|
@@ -3036,12 +3248,24 @@ function createConvertToImportMap(config, ports) {
|
|
|
3036
3248
|
return;
|
|
3037
3249
|
}
|
|
3038
3250
|
if (actions[external.packageName].action === "skip") {
|
|
3039
|
-
const override = actions[external.packageName]
|
|
3040
|
-
if (!external.shareScope)
|
|
3251
|
+
const { override, covered } = actions[external.packageName];
|
|
3252
|
+
if (!external.shareScope) {
|
|
3253
|
+
if (covered) {
|
|
3254
|
+
serveUncovered(remoteEntry, external, covered, remoteEntryScope, importMap);
|
|
3255
|
+
}
|
|
3256
|
+
return;
|
|
3257
|
+
}
|
|
3041
3258
|
if (override) {
|
|
3042
3259
|
Object.entries(override).forEach(([packageName, url]) => {
|
|
3043
3260
|
addToScopes(remoteEntryScope, packageName, url, importMap);
|
|
3044
3261
|
});
|
|
3262
|
+
serveUncovered(
|
|
3263
|
+
remoteEntry,
|
|
3264
|
+
external,
|
|
3265
|
+
covered ?? Object.keys(override),
|
|
3266
|
+
remoteEntryScope,
|
|
3267
|
+
importMap
|
|
3268
|
+
);
|
|
3045
3269
|
return;
|
|
3046
3270
|
}
|
|
3047
3271
|
log.error(
|
|
@@ -3108,6 +3332,27 @@ function createConvertToImportMap(config, ports) {
|
|
|
3108
3332
|
});
|
|
3109
3333
|
return importMap;
|
|
3110
3334
|
}
|
|
3335
|
+
function serveUncovered(remoteEntry, external, covered, remoteEntryScope, importMap) {
|
|
3336
|
+
const provided = new Set(covered);
|
|
3337
|
+
Object.entries(external.entries).forEach(([packageName, fileName]) => {
|
|
3338
|
+
if (provided.has(packageName)) return;
|
|
3339
|
+
if (config.strict.strictEntryPointCoverage || config.profile.scopeUncoveredEntrypoints) {
|
|
3340
|
+
warnUncoveredEntrypoint(remoteEntry.name, external.packageName, packageName);
|
|
3341
|
+
return;
|
|
3342
|
+
}
|
|
3343
|
+
const url = join(remoteEntryScope, fileName);
|
|
3344
|
+
addToScopes(remoteEntryScope, packageName, url, importMap);
|
|
3345
|
+
addIntegrity(importMap, url, remoteEntry.integrity, fileName);
|
|
3346
|
+
});
|
|
3347
|
+
}
|
|
3348
|
+
function warnUncoveredEntrypoint(remoteName, externalName, packageName) {
|
|
3349
|
+
const msg = `[${remoteName}][${externalName}] Entrypoint '${packageName}' is not covered by the override.`;
|
|
3350
|
+
if (config.strict.strictEntryPointCoverage || config.strict.strictImportMap) {
|
|
3351
|
+
log.error(9, msg);
|
|
3352
|
+
throw new NFError("Could not create ImportMap.");
|
|
3353
|
+
}
|
|
3354
|
+
log.warn(9, msg);
|
|
3355
|
+
}
|
|
3111
3356
|
function addIntegrity(importMap, url, integrityMap, file) {
|
|
3112
3357
|
const hash = integrityMap?.[file];
|
|
3113
3358
|
if (!hash) return;
|