@softarc/native-federation-orchestrator 4.6.0 → 4.7.0
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 +340 -111
- package/fesm2022/@softarc/native-federation-orchestrator.mjs.map +4 -4
- package/fesm2022/node.mjs +231 -72
- package/fesm2022/node.mjs.map +4 -4
- package/fesm2022/options.mjs +6 -0
- package/fesm2022/options.mjs.map +2 -2
- package/fesm2022/sdk.mjs.map +1 -1
- package/node-loader/loader.mjs +26 -6
- package/node-loader/loader.mjs.map +2 -2
- package/package.json +1 -1
- package/quickstart.mjs +15 -15
- package/types/lib/core/1.domain/externals/external.contract.d.ts +1 -0
- package/types/lib/core/1.domain/externals/version.contract.d.ts +2 -0
- package/types/lib/core/2.app/config/index.d.ts +2 -1
- package/types/lib/core/2.app/config/mode.contract.d.ts +0 -1
- package/types/lib/core/2.app/config/orchestrator-global.contract.d.ts +15 -0
- package/types/lib/core/2.app/config/storage.contract.d.ts +14 -2
- 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-graph.d.ts +7 -12
- package/types/lib/core/2.app/steps/pooling/pool.util.d.ts +12 -11
- package/types/lib/core/3.adapters/browser/sse-handler.d.ts +0 -8
- package/types/lib/core/3.adapters/storage/chunk.repository.d.ts +1 -1
- package/types/lib/core/3.adapters/storage/remote-info.repository.d.ts +1 -1
- package/types/lib/core/3.adapters/storage/scoped-externals.repository.d.ts +1 -1
- package/types/lib/core/3.adapters/storage/shared-externals.repository.d.ts +1 -1
- package/types/lib/core/4.config/storage/publish-storage-info.d.ts +9 -0
- package/types/lib/testing/pooling/tag-by-npm-scope.d.ts +9 -0
- package/types/scripts/node-loader.d.ts +1 -0
package/fesm2022/node.mjs
CHANGED
|
@@ -1430,6 +1430,14 @@ var createNoopSSE = () => ({
|
|
|
1430
1430
|
}
|
|
1431
1431
|
});
|
|
1432
1432
|
|
|
1433
|
+
// src/lib/core/2.app/config/storage.contract.ts
|
|
1434
|
+
var STORAGE_KEYS = {
|
|
1435
|
+
remotes: "remotes",
|
|
1436
|
+
sharedExternals: "shared-externals",
|
|
1437
|
+
scopedExternals: "scoped-externals",
|
|
1438
|
+
sharedChunks: "shared-chunks"
|
|
1439
|
+
};
|
|
1440
|
+
|
|
1433
1441
|
// src/lib/utils/path.ts
|
|
1434
1442
|
function join(pathA, pathB) {
|
|
1435
1443
|
pathA = pathA.endsWith("/") ? pathA.slice(0, -1) : pathA;
|
|
@@ -1487,7 +1495,7 @@ var Optional = class _Optional {
|
|
|
1487
1495
|
|
|
1488
1496
|
// src/lib/core/3.adapters/storage/remote-info.repository.ts
|
|
1489
1497
|
var createRemoteInfoRepository = (config) => {
|
|
1490
|
-
const STORAGE = config.storage(
|
|
1498
|
+
const STORAGE = config.storage(STORAGE_KEYS.remotes, {});
|
|
1491
1499
|
if (config.clearStorage) STORAGE.clear();
|
|
1492
1500
|
const _cache = STORAGE.get() ?? {};
|
|
1493
1501
|
let _dirty = false;
|
|
@@ -1529,7 +1537,7 @@ var createRemoteInfoRepository = (config) => {
|
|
|
1529
1537
|
|
|
1530
1538
|
// src/lib/core/3.adapters/storage/scoped-externals.repository.ts
|
|
1531
1539
|
var createScopedExternalsRepository = (config) => {
|
|
1532
|
-
const STORAGE = config.storage(
|
|
1540
|
+
const STORAGE = config.storage(STORAGE_KEYS.scopedExternals, {});
|
|
1533
1541
|
if (config.clearStorage) STORAGE.clear();
|
|
1534
1542
|
const _cache = STORAGE.get() ?? {};
|
|
1535
1543
|
let _dirty = false;
|
|
@@ -1569,7 +1577,7 @@ var STRICT_SCOPE = "strict";
|
|
|
1569
1577
|
// src/lib/core/3.adapters/storage/shared-externals.repository.ts
|
|
1570
1578
|
var createSharedExternalsRepository = (config) => {
|
|
1571
1579
|
const STORAGE = config.storage(
|
|
1572
|
-
|
|
1580
|
+
STORAGE_KEYS.sharedExternals,
|
|
1573
1581
|
{ [GLOBAL_SCOPE]: {} }
|
|
1574
1582
|
);
|
|
1575
1583
|
if (config.clearStorage) STORAGE.clear();
|
|
@@ -1579,12 +1587,17 @@ var createSharedExternalsRepository = (config) => {
|
|
|
1579
1587
|
// Read from the cache rather than remembered from this init's entries: a warm init may not refetch
|
|
1580
1588
|
// the tagged remote at all, and pooling has to coordinate its pool anyway. Exits on the first hit.
|
|
1581
1589
|
// Per share scope, because a pool never spans one: a tag in another scope is no reason to pool here.
|
|
1582
|
-
|
|
1590
|
+
// Stored pool results count too, since a scope whose last tag left still has pool state to clear.
|
|
1591
|
+
hasPoolState: function(shareScope) {
|
|
1583
1592
|
const scope = _cache[shareScope ?? GLOBAL_SCOPE];
|
|
1584
1593
|
if (!scope) return false;
|
|
1585
|
-
for (const external of Object.values(scope))
|
|
1594
|
+
for (const external of Object.values(scope)) {
|
|
1595
|
+
if (external.poolName !== void 0) return true;
|
|
1586
1596
|
for (const version of external.versions)
|
|
1587
|
-
for (const remote of version.remotes)
|
|
1597
|
+
for (const remote of version.remotes)
|
|
1598
|
+
if (remote.pool?.trim() || remote.servedBy !== void 0 || remote.poolCause !== void 0)
|
|
1599
|
+
return true;
|
|
1600
|
+
}
|
|
1588
1601
|
return false;
|
|
1589
1602
|
},
|
|
1590
1603
|
getFromScope: function(shareScope) {
|
|
@@ -1661,7 +1674,7 @@ var createSharedExternalsRepository = (config) => {
|
|
|
1661
1674
|
|
|
1662
1675
|
// src/lib/core/3.adapters/storage/chunk.repository.ts
|
|
1663
1676
|
var createChunkRepository = (config) => {
|
|
1664
|
-
const STORAGE = config.storage(
|
|
1677
|
+
const STORAGE = config.storage(STORAGE_KEYS.sharedChunks, {});
|
|
1665
1678
|
if (config.clearStorage) STORAGE.clear();
|
|
1666
1679
|
const _cache = STORAGE.get() ?? {};
|
|
1667
1680
|
let _dirty = false;
|
|
@@ -1891,12 +1904,55 @@ var globalThisStorageEntry = (namespace) => (key, initialValue) => {
|
|
|
1891
1904
|
};
|
|
1892
1905
|
return entry;
|
|
1893
1906
|
};
|
|
1907
|
+
globalThisStorageEntry.type = "globalThis";
|
|
1908
|
+
Object.freeze(globalThisStorageEntry);
|
|
1909
|
+
|
|
1910
|
+
// src/lib/core/4.config/storage/publish-storage-info.ts
|
|
1911
|
+
var VERSION = true ? "4.7.0" : "dev";
|
|
1912
|
+
var KEYS = Object.freeze(Object.values(STORAGE_KEYS));
|
|
1913
|
+
var isStorageKey = (key) => KEYS.includes(key);
|
|
1914
|
+
var createStorageInfo = ({
|
|
1915
|
+
type,
|
|
1916
|
+
namespace,
|
|
1917
|
+
storage,
|
|
1918
|
+
exposeGetter
|
|
1919
|
+
}) => {
|
|
1920
|
+
const info = { version: VERSION, type, namespace, keys: KEYS };
|
|
1921
|
+
if (!exposeGetter) return Object.freeze(info);
|
|
1922
|
+
return Object.freeze({
|
|
1923
|
+
...info,
|
|
1924
|
+
// Cloned again because custom storages may hand out live references.
|
|
1925
|
+
get: (key) => isStorageKey(key) ? cloneEntry(key, storage(key, void 0).get()) : void 0
|
|
1926
|
+
});
|
|
1927
|
+
};
|
|
1928
|
+
var publishStorageInfo = (options) => {
|
|
1929
|
+
try {
|
|
1930
|
+
globalThis.__NF_ORCHESTRATOR__ = Object.freeze({
|
|
1931
|
+
storage: Object.freeze({
|
|
1932
|
+
...globalThis.__NF_ORCHESTRATOR__?.storage,
|
|
1933
|
+
[options.namespace]: createStorageInfo(options)
|
|
1934
|
+
})
|
|
1935
|
+
});
|
|
1936
|
+
} catch {
|
|
1937
|
+
}
|
|
1938
|
+
};
|
|
1894
1939
|
|
|
1895
1940
|
// src/lib/core/4.config/storage/storage.config.ts
|
|
1896
|
-
var createStorageConfig = (override) =>
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1941
|
+
var createStorageConfig = (override) => {
|
|
1942
|
+
const creator = override.storage ?? globalThisStorageEntry;
|
|
1943
|
+
const namespace = override.storageNamespace ?? "__NATIVE_FEDERATION__";
|
|
1944
|
+
const storage = creator(namespace);
|
|
1945
|
+
publishStorageInfo({
|
|
1946
|
+
type: creator.type ?? "custom",
|
|
1947
|
+
namespace,
|
|
1948
|
+
storage,
|
|
1949
|
+
exposeGetter: override.exposeStorageGetter ?? true
|
|
1950
|
+
});
|
|
1951
|
+
return {
|
|
1952
|
+
storage,
|
|
1953
|
+
clearStorage: override.clearStorage ?? false
|
|
1954
|
+
};
|
|
1955
|
+
};
|
|
1900
1956
|
|
|
1901
1957
|
// src/lib/core/4.config/mode/default.profile.ts
|
|
1902
1958
|
var defaultProfile = {
|
|
@@ -1928,8 +1984,7 @@ var createModeConfig = (override) => {
|
|
|
1928
1984
|
strict: strictnessConfig,
|
|
1929
1985
|
profile: { ...defaultProfile, ...override.profile ?? {} },
|
|
1930
1986
|
feature: {
|
|
1931
|
-
convertFlatSharedInfo: override.feature?.convertFlatSharedInfo ?? false
|
|
1932
|
-
useAutoExternalPooling: override.feature?.useAutoExternalPooling ?? false
|
|
1987
|
+
convertFlatSharedInfo: override.feature?.convertFlatSharedInfo ?? false
|
|
1933
1988
|
}
|
|
1934
1989
|
};
|
|
1935
1990
|
};
|
|
@@ -2219,7 +2274,7 @@ function createStoreRemoteEntry(config, ports, logStep) {
|
|
|
2219
2274
|
...sharedInfo.pool?.trim() ? { pool: sharedInfo.pool } : {},
|
|
2220
2275
|
entries: sharedInfo.entries
|
|
2221
2276
|
};
|
|
2222
|
-
const cached2 = ports.sharedExternalsRepo.tryGet(sharedInfo.packageName, sharedInfo.shareScope).
|
|
2277
|
+
const cached2 = ports.sharedExternalsRepo.tryGet(sharedInfo.packageName, sharedInfo.shareScope).get() ?? { dirty: false, versions: [] };
|
|
2223
2278
|
return {
|
|
2224
2279
|
tag,
|
|
2225
2280
|
remote,
|
|
@@ -2240,6 +2295,7 @@ function createStoreRemoteEntry(config, ports, logStep) {
|
|
|
2240
2295
|
sharedInfo.packageName,
|
|
2241
2296
|
{
|
|
2242
2297
|
dirty: cached2.dirty,
|
|
2298
|
+
...cached2.poolName !== void 0 && { poolName: cached2.poolName },
|
|
2243
2299
|
versions: cached2.versions.sort((a, b) => ports.versionCheck.compare(b.tag, a.tag))
|
|
2244
2300
|
},
|
|
2245
2301
|
sharedInfo.shareScope
|
|
@@ -2837,7 +2893,6 @@ function assignAnchors(input) {
|
|
|
2837
2893
|
}
|
|
2838
2894
|
|
|
2839
2895
|
// src/lib/core/2.app/steps/pooling/pool-graph.ts
|
|
2840
|
-
var SCOPED_PACKAGE = /^@([^/]+)\//;
|
|
2841
2896
|
function createDSU() {
|
|
2842
2897
|
const ids = /* @__PURE__ */ new Map();
|
|
2843
2898
|
const parent = [];
|
|
@@ -2876,10 +2931,6 @@ function createDSU() {
|
|
|
2876
2931
|
}
|
|
2877
2932
|
var extNode = (name) => `ext\0${name}`;
|
|
2878
2933
|
var tagNode = (remote, tag) => `tag\0${remote}\0${tag}`;
|
|
2879
|
-
var scopeNode = (remote, scope) => `scope\0${remote}\0${scope}`;
|
|
2880
|
-
function autoScope(name, useAutoExternalPooling) {
|
|
2881
|
-
return useAutoExternalPooling ? SCOPED_PACKAGE.exec(name)?.[1] : void 0;
|
|
2882
|
-
}
|
|
2883
2934
|
function owningPackage(name) {
|
|
2884
2935
|
const depth = name.startsWith("@") ? 2 : 1;
|
|
2885
2936
|
let cut = -1;
|
|
@@ -2892,23 +2943,10 @@ function owningPackage(name) {
|
|
|
2892
2943
|
function groupByMembership(candidates, log) {
|
|
2893
2944
|
const dsu = createDSU();
|
|
2894
2945
|
const tagged = /* @__PURE__ */ new Set();
|
|
2895
|
-
const joined = /* @__PURE__ */ new Set();
|
|
2896
|
-
const tagRules = /* @__PURE__ */ new Set();
|
|
2897
|
-
for (const candidate of candidates) {
|
|
2898
|
-
if (candidate.scope === void 0) continue;
|
|
2899
|
-
for (const edge of candidate.tags) tagRules.add(`${edge.remote}\0${candidate.scope}`);
|
|
2900
|
-
}
|
|
2901
2946
|
for (const candidate of candidates) {
|
|
2902
2947
|
for (const edge of candidate.tags) {
|
|
2903
2948
|
dsu.union(extNode(candidate.name), tagNode(edge.remote, edge.tag));
|
|
2904
2949
|
tagged.add(candidate.name);
|
|
2905
|
-
joined.add(candidate.name);
|
|
2906
|
-
}
|
|
2907
|
-
if (candidate.scope === void 0) continue;
|
|
2908
|
-
for (const remote of candidate.remotes) {
|
|
2909
|
-
if (tagRules.has(`${remote}\0${candidate.scope}`)) continue;
|
|
2910
|
-
dsu.union(extNode(candidate.name), scopeNode(remote, candidate.scope));
|
|
2911
|
-
joined.add(candidate.name);
|
|
2912
2950
|
}
|
|
2913
2951
|
}
|
|
2914
2952
|
const declared = new Set(candidates.map((c) => c.name));
|
|
@@ -2921,11 +2959,11 @@ function groupByMembership(candidates, log) {
|
|
|
2921
2959
|
for (const candidate of candidates) {
|
|
2922
2960
|
const root = dsu.component(extNode(candidate.name));
|
|
2923
2961
|
const members = byComponent.get(root) ?? byComponent.set(root, []).get(root);
|
|
2924
|
-
members.push(
|
|
2962
|
+
members.push(candidate);
|
|
2925
2963
|
}
|
|
2926
2964
|
const pools = [];
|
|
2927
2965
|
for (const members of byComponent.values()) {
|
|
2928
|
-
if (!members.some((m) =>
|
|
2966
|
+
if (!members.some((m) => tagged.has(m.name))) continue;
|
|
2929
2967
|
members.sort((a, b) => a.name.localeCompare(b.name));
|
|
2930
2968
|
if (members.length < 2) {
|
|
2931
2969
|
const only = members[0];
|
|
@@ -2940,20 +2978,39 @@ function groupByMembership(candidates, log) {
|
|
|
2940
2978
|
pools.push(members);
|
|
2941
2979
|
}
|
|
2942
2980
|
pools.sort((a, b) => a[0].name.localeCompare(b[0].name));
|
|
2943
|
-
|
|
2981
|
+
const named = /* @__PURE__ */ new Map();
|
|
2982
|
+
for (const members of pools) {
|
|
2983
|
+
const label = mostDeclaredTag(members) ?? members[0].name;
|
|
2984
|
+
let name = label;
|
|
2985
|
+
for (let n = 2; named.has(name); n++) name = `${label}~${n}`;
|
|
2986
|
+
named.set(
|
|
2987
|
+
name,
|
|
2988
|
+
members.map((m) => m.value)
|
|
2989
|
+
);
|
|
2990
|
+
}
|
|
2991
|
+
return named;
|
|
2944
2992
|
}
|
|
2945
|
-
function
|
|
2993
|
+
function mostDeclaredTag(members) {
|
|
2994
|
+
const counts = /* @__PURE__ */ new Map();
|
|
2995
|
+
for (const member of members)
|
|
2996
|
+
for (const edge of member.tags) counts.set(edge.tag, (counts.get(edge.tag) ?? 0) + 1);
|
|
2997
|
+
let best;
|
|
2998
|
+
for (const [tag, count] of counts) {
|
|
2999
|
+
const top = best === void 0 ? 0 : counts.get(best);
|
|
3000
|
+
if (count > top || count === top && tag.localeCompare(best) < 0) best = tag;
|
|
3001
|
+
}
|
|
3002
|
+
return best;
|
|
3003
|
+
}
|
|
3004
|
+
function buildPools(sharedExternals, log) {
|
|
2946
3005
|
const candidates = Object.entries(sharedExternals).map(
|
|
2947
3006
|
([name, external]) => ({
|
|
2948
3007
|
name,
|
|
2949
|
-
scope: autoScope(name, useAutoExternalPooling),
|
|
2950
3008
|
tags: external.versions.flatMap(
|
|
2951
3009
|
(v) => v.remotes.flatMap((r) => {
|
|
2952
3010
|
const tag = r.pool?.trim();
|
|
2953
3011
|
return tag ? [{ remote: r.name, tag }] : [];
|
|
2954
3012
|
})
|
|
2955
3013
|
),
|
|
2956
|
-
remotes: external.versions.flatMap((v) => v.remotes.map((r) => r.name)),
|
|
2957
3014
|
value: { name, external }
|
|
2958
3015
|
})
|
|
2959
3016
|
);
|
|
@@ -2970,14 +3027,29 @@ function remotesInPool(members) {
|
|
|
2970
3027
|
...new Set(members.flatMap((m) => m.external.versions.flatMap((v) => v.remotes.map((r) => r.name))))
|
|
2971
3028
|
];
|
|
2972
3029
|
}
|
|
2973
|
-
function poolableScopes(
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
3030
|
+
function poolableScopes(repo) {
|
|
3031
|
+
return repo.getScopes().filter((scope) => repo.scopeType(scope) !== "strict" && repo.hasPoolState(scope));
|
|
3032
|
+
}
|
|
3033
|
+
function syncPoolNames(sharedExternals, pools, repo, scope, skip = /* @__PURE__ */ new Set()) {
|
|
3034
|
+
const named = /* @__PURE__ */ new Map();
|
|
3035
|
+
for (const [name, members] of pools) for (const member of members) named.set(member.name, name);
|
|
3036
|
+
for (const [name, external] of Object.entries(sharedExternals)) {
|
|
3037
|
+
const pool = named.get(name);
|
|
3038
|
+
if (pool !== void 0 && skip.has(pool)) continue;
|
|
3039
|
+
if (external.poolName === pool) continue;
|
|
3040
|
+
const { poolName: _stale, ...rest } = external;
|
|
3041
|
+
repo.addOrUpdate(
|
|
3042
|
+
name,
|
|
3043
|
+
pool !== void 0 ? { ...rest, poolName: pool } : {
|
|
3044
|
+
...rest,
|
|
3045
|
+
versions: external.versions.map((v) => ({
|
|
3046
|
+
...v,
|
|
3047
|
+
remotes: v.remotes.map(({ poolCause: _cause, ...meta }) => meta)
|
|
3048
|
+
}))
|
|
3049
|
+
},
|
|
3050
|
+
scope
|
|
3051
|
+
);
|
|
3052
|
+
}
|
|
2981
3053
|
}
|
|
2982
3054
|
|
|
2983
3055
|
// src/lib/core/2.app/steps/pooling/pool-shared-externals.ts
|
|
@@ -3011,7 +3083,11 @@ function servedPerRemote(consumed, serving, basis) {
|
|
|
3011
3083
|
}
|
|
3012
3084
|
return served;
|
|
3013
3085
|
}
|
|
3014
|
-
var
|
|
3086
|
+
var anyVerdictStored = (members) => members.some(
|
|
3087
|
+
(m) => m.external.versions.some(
|
|
3088
|
+
(v) => v.remotes.some((r) => r.servedBy !== void 0 || r.poolCause !== void 0)
|
|
3089
|
+
)
|
|
3090
|
+
);
|
|
3015
3091
|
function findTornRemotes(members, islanded, basis, served, hosts) {
|
|
3016
3092
|
const { suspect, selfServed } = movedRemotes(members, islanded, basis, served, hosts);
|
|
3017
3093
|
if (suspect.size === 0) return [];
|
|
@@ -3082,20 +3158,18 @@ function movedRemotes(members, islanded, basis, served, hosts) {
|
|
|
3082
3158
|
}
|
|
3083
3159
|
function createPoolSharedExternals(config, ports) {
|
|
3084
3160
|
return (touched) => {
|
|
3085
|
-
const
|
|
3086
|
-
for (const scope of scopes) {
|
|
3161
|
+
for (const scope of poolableScopes(ports.sharedExternalsRepo)) {
|
|
3087
3162
|
const touchedInScope = touched?.get(scope);
|
|
3088
3163
|
if (touched && !touchedInScope) continue;
|
|
3089
3164
|
const sharedExternals = ports.sharedExternalsRepo.getFromScope(scope);
|
|
3090
3165
|
try {
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
config.log
|
|
3095
|
-
)) {
|
|
3166
|
+
const pools = buildPools(sharedExternals, config.log);
|
|
3167
|
+
const rebuilt = /* @__PURE__ */ new Set();
|
|
3168
|
+
for (const [poolName, members] of pools) {
|
|
3096
3169
|
if (touchedInScope && !members.some((m) => touchedInScope.has(m.name))) continue;
|
|
3097
|
-
poolFamily(poolName, members, scope);
|
|
3170
|
+
if (poolFamily(poolName, members, scope)) rebuilt.add(poolName);
|
|
3098
3171
|
}
|
|
3172
|
+
syncPoolNames(sharedExternals, pools, ports.sharedExternalsRepo, scope, rebuilt);
|
|
3099
3173
|
} catch (error) {
|
|
3100
3174
|
if (error instanceof NFError) return Promise.reject(error);
|
|
3101
3175
|
config.log.error(3, `[${scope}] failed to pool shared externals.`, {
|
|
@@ -3110,9 +3184,19 @@ function createPoolSharedExternals(config, ports) {
|
|
|
3110
3184
|
return Promise.resolve();
|
|
3111
3185
|
};
|
|
3112
3186
|
function poolFamily(poolName, members, scope) {
|
|
3113
|
-
if (members.length < 2) return;
|
|
3187
|
+
if (members.length < 2) return false;
|
|
3114
3188
|
const allRemotes = remotesInPool(members);
|
|
3115
|
-
if (allRemotes.length < 2)
|
|
3189
|
+
if (allRemotes.length < 2) {
|
|
3190
|
+
if (!anyVerdictStored(members)) return false;
|
|
3191
|
+
const basis2 = basisFor(members, /* @__PURE__ */ new Map(), /* @__PURE__ */ new Map());
|
|
3192
|
+
for (const member of members)
|
|
3193
|
+
ports.sharedExternalsRepo.addOrUpdate(
|
|
3194
|
+
member.name,
|
|
3195
|
+
rebuildMember(poolName, member, /* @__PURE__ */ new Map(), /* @__PURE__ */ new Map(), basis2.get(member.name)),
|
|
3196
|
+
scope
|
|
3197
|
+
);
|
|
3198
|
+
return true;
|
|
3199
|
+
}
|
|
3116
3200
|
const islanded = islandedRemotes(members);
|
|
3117
3201
|
const consumed = consumedMembers(members);
|
|
3118
3202
|
const hosts = hostRemotes(members);
|
|
@@ -3132,7 +3216,7 @@ function createPoolSharedExternals(config, ports) {
|
|
|
3132
3216
|
return { serving: serving2, basis: basis2, served: servedPerRemote(consumed, serving2, basis2) };
|
|
3133
3217
|
};
|
|
3134
3218
|
let { serving, basis, served } = assign();
|
|
3135
|
-
if (islanded.size === 0 && serving.size === 0 && !
|
|
3219
|
+
if (islanded.size === 0 && serving.size === 0 && !anyVerdictStored(members)) return false;
|
|
3136
3220
|
for (; ; ) {
|
|
3137
3221
|
const torn = findTornRemotes(members, islanded, basis, served, hosts);
|
|
3138
3222
|
if (torn.length === 0) break;
|
|
@@ -3153,10 +3237,11 @@ function createPoolSharedExternals(config, ports) {
|
|
|
3153
3237
|
config.log.warn(3, `[${scope}][pool:${poolName}] ${islandWarning(remote, cause, scoped)}`);
|
|
3154
3238
|
}
|
|
3155
3239
|
for (const member of members) {
|
|
3156
|
-
const rebuilt = rebuildMember(member, islanded, served, basis.get(member.name));
|
|
3240
|
+
const rebuilt = rebuildMember(poolName, member, islanded, served, basis.get(member.name));
|
|
3157
3241
|
warnIfScopedOnly(poolName, member, rebuilt, islanded, scope);
|
|
3158
3242
|
ports.sharedExternalsRepo.addOrUpdate(member.name, rebuilt, scope);
|
|
3159
3243
|
}
|
|
3244
|
+
return true;
|
|
3160
3245
|
}
|
|
3161
3246
|
function assignServingBuilds(members, islanded, consumed, hosts, views) {
|
|
3162
3247
|
for (; ; ) {
|
|
@@ -3220,7 +3305,7 @@ function createPoolSharedExternals(config, ports) {
|
|
|
3220
3305
|
`[${scope}][pool:${poolName}] '${member.name}' is scoped-only \u2014 no coherent shared build provides it; ${consumers} remotes download their own copy.`
|
|
3221
3306
|
);
|
|
3222
3307
|
}
|
|
3223
|
-
function rebuildMember(member, islanded, served, basis) {
|
|
3308
|
+
function rebuildMember(poolName, member, islanded, served, basis) {
|
|
3224
3309
|
let scoped = [];
|
|
3225
3310
|
let clean = [];
|
|
3226
3311
|
for (const version of member.external.versions) {
|
|
@@ -3240,11 +3325,14 @@ function createPoolSharedExternals(config, ports) {
|
|
|
3240
3325
|
const build = served.get(entry.remote)?.get(member.name);
|
|
3241
3326
|
if (build !== void 0) entry.meta.servedBy = build;
|
|
3242
3327
|
else delete entry.meta.servedBy;
|
|
3328
|
+
delete entry.meta.poolCause;
|
|
3243
3329
|
}
|
|
3244
3330
|
if (basis === void 0) {
|
|
3245
3331
|
scoped = [...scoped, ...clean.filter((e) => e.meta.servedBy === void 0)];
|
|
3246
3332
|
clean = clean.filter((e) => e.meta.servedBy !== void 0).map((e) => ({ ...e, action: "skip" }));
|
|
3247
3333
|
}
|
|
3334
|
+
for (const entry of scoped)
|
|
3335
|
+
entry.meta.poolCause = islanded.get(entry.remote)?.kind ?? "unshared";
|
|
3248
3336
|
const shareEntries = clean.filter((e) => e.action === "share").sort((a, b) => Number(b.remote === basis) - Number(a.remote === basis));
|
|
3249
3337
|
const shareVersion = shareEntries.length > 0 ? [
|
|
3250
3338
|
{
|
|
@@ -3270,6 +3358,7 @@ function createPoolSharedExternals(config, ports) {
|
|
|
3270
3358
|
};
|
|
3271
3359
|
return {
|
|
3272
3360
|
dirty: false,
|
|
3361
|
+
poolName,
|
|
3273
3362
|
versions: [
|
|
3274
3363
|
...shareVersion,
|
|
3275
3364
|
...byTag(
|
|
@@ -3295,14 +3384,27 @@ function islandWarning(remote, cause, scoped) {
|
|
|
3295
3384
|
}
|
|
3296
3385
|
|
|
3297
3386
|
// src/lib/core/2.app/steps/pooling/mark-pools-for-reelection.ts
|
|
3387
|
+
function clearPoolState(external) {
|
|
3388
|
+
let cleared = external.poolName !== void 0;
|
|
3389
|
+
delete external.poolName;
|
|
3390
|
+
for (const version of external.versions)
|
|
3391
|
+
for (const meta of version.remotes) {
|
|
3392
|
+
if (meta.servedBy !== void 0 || meta.poolCause !== void 0) cleared = true;
|
|
3393
|
+
delete meta.servedBy;
|
|
3394
|
+
delete meta.poolCause;
|
|
3395
|
+
}
|
|
3396
|
+
return cleared;
|
|
3397
|
+
}
|
|
3298
3398
|
function createMarkPoolsForReelection(config, ports) {
|
|
3299
3399
|
return () => {
|
|
3300
|
-
const
|
|
3301
|
-
for (const scope of scopes) {
|
|
3400
|
+
for (const scope of poolableScopes(ports.sharedExternalsRepo)) {
|
|
3302
3401
|
const sharedExternals = ports.sharedExternalsRepo.getFromScope(scope);
|
|
3303
3402
|
if (!Object.values(sharedExternals).some((external) => external.dirty)) continue;
|
|
3304
3403
|
let spread = 0;
|
|
3305
|
-
|
|
3404
|
+
let unpooled = 0;
|
|
3405
|
+
const pooled = /* @__PURE__ */ new Set();
|
|
3406
|
+
for (const [, members] of buildPools(sharedExternals)) {
|
|
3407
|
+
for (const member of members) pooled.add(member.name);
|
|
3306
3408
|
if (!members.some((m) => m.external.dirty)) continue;
|
|
3307
3409
|
for (const member of members)
|
|
3308
3410
|
if (!member.external.dirty) {
|
|
@@ -3310,14 +3412,24 @@ function createMarkPoolsForReelection(config, ports) {
|
|
|
3310
3412
|
spread++;
|
|
3311
3413
|
}
|
|
3312
3414
|
}
|
|
3415
|
+
for (const [name, external] of Object.entries(sharedExternals)) {
|
|
3416
|
+
if (pooled.has(name) || !clearPoolState(external)) continue;
|
|
3417
|
+
external.dirty = true;
|
|
3418
|
+
unpooled++;
|
|
3419
|
+
}
|
|
3313
3420
|
if (spread > 0)
|
|
3314
3421
|
config.log.debug(3, `[${scope}] ${spread} pool member(s) marked dirty for re-election.`);
|
|
3422
|
+
if (unpooled > 0)
|
|
3423
|
+
config.log.debug(
|
|
3424
|
+
3,
|
|
3425
|
+
`[${scope}] ${unpooled} external(s) left every pool; cleared their pool state for re-election.`
|
|
3426
|
+
);
|
|
3315
3427
|
}
|
|
3316
3428
|
return Promise.resolve();
|
|
3317
3429
|
};
|
|
3318
3430
|
}
|
|
3319
3431
|
|
|
3320
|
-
// node_modules/.pnpm/@softarc+native-federation@4.
|
|
3432
|
+
// node_modules/.pnpm/@softarc+native-federation@4.7.0/node_modules/@softarc/native-federation/dist/lib/domain/core/chunk.js
|
|
3321
3433
|
var CHUNK_PREFIX = "@nf-internal";
|
|
3322
3434
|
function toChunkImport(fileName) {
|
|
3323
3435
|
if (fileName.startsWith("./")) {
|
|
@@ -3922,7 +4034,6 @@ function createUpdateCache(config, ports) {
|
|
|
3922
4034
|
// src/lib/core/2.app/steps/pooling/pool-dynamic-externals.ts
|
|
3923
4035
|
function createPoolDynamicExternals(config, ports) {
|
|
3924
4036
|
return ({ entry, actions }) => {
|
|
3925
|
-
const { useAutoExternalPooling } = config.feature;
|
|
3926
4037
|
const declared = /* @__PURE__ */ new Map();
|
|
3927
4038
|
for (const external of entry.shared ?? []) {
|
|
3928
4039
|
const name = external.packageName;
|
|
@@ -3934,18 +4045,22 @@ function createPoolDynamicExternals(config, ports) {
|
|
|
3934
4045
|
names.add(name);
|
|
3935
4046
|
}
|
|
3936
4047
|
if (declared.size === 0) return Promise.resolve({ entry, actions });
|
|
3937
|
-
|
|
4048
|
+
let verdicts = /* @__PURE__ */ new Map();
|
|
4049
|
+
const scope = (name, cause) => {
|
|
3938
4050
|
actions[name].action = "scope";
|
|
3939
4051
|
delete actions[name].override;
|
|
4052
|
+
verdicts.set(name, { cause });
|
|
3940
4053
|
};
|
|
3941
4054
|
for (const [shareScope, names] of declared) {
|
|
3942
|
-
if (!
|
|
4055
|
+
if (!ports.sharedExternalsRepo.hasPoolState(shareScope)) continue;
|
|
3943
4056
|
const committed = ports.sharedExternalsRepo.getFromScope(shareScope);
|
|
3944
|
-
|
|
4057
|
+
const pools = buildPools(committed);
|
|
4058
|
+
verdicts = /* @__PURE__ */ new Map();
|
|
4059
|
+
for (const pool of pools.values()) {
|
|
3945
4060
|
const mine = pool.filter((member) => names.has(member.name));
|
|
3946
4061
|
if (mine.length === 0) continue;
|
|
3947
4062
|
if (mine.some((member) => actions[member.name].action === "scope")) {
|
|
3948
|
-
mine.forEach((member) => scope(member.name));
|
|
4063
|
+
mine.forEach((member) => scope(member.name, "incompatible"));
|
|
3949
4064
|
continue;
|
|
3950
4065
|
}
|
|
3951
4066
|
const asked = gateViews(entry.name, pool);
|
|
@@ -3958,11 +4073,18 @@ function createPoolDynamicExternals(config, ports) {
|
|
|
3958
4073
|
8,
|
|
3959
4074
|
`[${shareScope}] '${entry.name}' serves its own family: no committed build offers every entrypoint it imports at a version it accepts \u2014 '${reason.gap}' is the gap, ${closest}. All ${mine.length} members it imports are scoped for it.`
|
|
3960
4075
|
);
|
|
3961
|
-
mine.forEach((member) => scope(member.name));
|
|
4076
|
+
mine.forEach((member) => scope(member.name, "uncovered"));
|
|
3962
4077
|
continue;
|
|
3963
4078
|
}
|
|
3964
|
-
redirect(entry.name, anchor, pool, asked.view, actions, shareScope)
|
|
4079
|
+
for (const name of redirect(entry.name, anchor, pool, asked.view, actions, shareScope))
|
|
4080
|
+
verdicts.set(name, { servedBy: anchor });
|
|
3965
4081
|
}
|
|
4082
|
+
const written = {};
|
|
4083
|
+
for (const [name, verdict] of verdicts) {
|
|
4084
|
+
written[name] = recordVerdict(committed[name], entry.name, verdict);
|
|
4085
|
+
ports.sharedExternalsRepo.addOrUpdate(name, written[name], shareScope);
|
|
4086
|
+
}
|
|
4087
|
+
syncPoolNames({ ...committed, ...written }, pools, ports.sharedExternalsRepo, shareScope);
|
|
3966
4088
|
}
|
|
3967
4089
|
return Promise.resolve({ entry, actions });
|
|
3968
4090
|
};
|
|
@@ -4027,8 +4149,10 @@ function createPoolDynamicExternals(config, ports) {
|
|
|
4027
4149
|
8,
|
|
4028
4150
|
`[${shareScope}][${remote}] '${anchor}' is not in the cache, so its files cannot be mapped.`
|
|
4029
4151
|
);
|
|
4030
|
-
return;
|
|
4152
|
+
return [];
|
|
4031
4153
|
}
|
|
4154
|
+
const basis = basisPerMember(pool);
|
|
4155
|
+
const served = [];
|
|
4032
4156
|
for (const member of pool) {
|
|
4033
4157
|
const action = actions[member.name];
|
|
4034
4158
|
if (!action || action.action !== "skip") continue;
|
|
@@ -4044,7 +4168,42 @@ function createPoolDynamicExternals(config, ports) {
|
|
|
4044
4168
|
}
|
|
4045
4169
|
action.covered = specifiers;
|
|
4046
4170
|
if (Object.keys(override).length > 0) action.override = override;
|
|
4171
|
+
if (basis.get(member.name) !== anchor) served.push(member.name);
|
|
4172
|
+
}
|
|
4173
|
+
return served;
|
|
4174
|
+
}
|
|
4175
|
+
function recordVerdict(external, remote, verdict) {
|
|
4176
|
+
if ("servedBy" in verdict) {
|
|
4177
|
+
return {
|
|
4178
|
+
...external,
|
|
4179
|
+
versions: external.versions.map((v) => ({
|
|
4180
|
+
...v,
|
|
4181
|
+
remotes: v.remotes.map(
|
|
4182
|
+
(r) => r.name === remote ? { ...r, servedBy: verdict.servedBy } : r
|
|
4183
|
+
)
|
|
4184
|
+
}))
|
|
4185
|
+
};
|
|
4047
4186
|
}
|
|
4187
|
+
const moved = [];
|
|
4188
|
+
const versions = external.versions.map((v) => {
|
|
4189
|
+
const own = v.remotes.find((r) => r.name === remote);
|
|
4190
|
+
if (!own) return v;
|
|
4191
|
+
const { servedBy: _anchor, ...rest } = own;
|
|
4192
|
+
const meta = { ...rest, cached: true, poolCause: verdict.cause };
|
|
4193
|
+
if (v.action === "scope")
|
|
4194
|
+
return { ...v, remotes: v.remotes.map((r) => r === own ? meta : r) };
|
|
4195
|
+
moved.push({ tag: v.tag, meta });
|
|
4196
|
+
return { ...v, remotes: v.remotes.filter((r) => r !== own) };
|
|
4197
|
+
}).filter((v) => v.remotes.length > 0);
|
|
4198
|
+
for (const { tag, meta } of moved) {
|
|
4199
|
+
const at = versions.findIndex((v) => v.tag === tag && v.action === "scope");
|
|
4200
|
+
if (at >= 0) versions[at] = { ...versions[at], remotes: [...versions[at].remotes, meta] };
|
|
4201
|
+
else versions.push({ tag, action: "scope", host: false, remotes: [meta] });
|
|
4202
|
+
}
|
|
4203
|
+
return {
|
|
4204
|
+
...external,
|
|
4205
|
+
versions: versions.sort((a, b) => ports.versionCheck.compare(b.tag, a.tag))
|
|
4206
|
+
};
|
|
4048
4207
|
}
|
|
4049
4208
|
}
|
|
4050
4209
|
|