@softarc/native-federation-orchestrator 4.0.0-RC1 → 4.0.0-RC3

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.
Files changed (25) hide show
  1. package/fesm2022/@softarc/native-federation-orchestrator.mjs +221 -47
  2. package/fesm2022/@softarc/native-federation-orchestrator.mjs.map +4 -4
  3. package/fesm2022/options.mjs +8 -2
  4. package/fesm2022/options.mjs.map +2 -2
  5. package/package.json +1 -6
  6. package/quickstart.mjs +13 -13
  7. package/types/lib/1.domain/externals/chunks.contract.d.ts +3 -0
  8. package/types/lib/1.domain/externals/version.contract.d.ts +2 -0
  9. package/types/lib/1.domain/remote-entry/remote-entry.contract.d.ts +1 -18
  10. package/types/lib/2.app/config/import-map.contract.d.ts +1 -0
  11. package/types/lib/2.app/config/log.contract.d.ts +2 -0
  12. package/types/lib/2.app/driving-ports/driving.contract.d.ts +4 -0
  13. package/types/lib/2.app/driving-ports/for-shared-chunks-storage.port.d.ts +6 -0
  14. package/types/lib/2.app/driving-ports/for-sse.port.d.ts +4 -0
  15. package/types/lib/2.app/driving-ports/index.d.ts +1 -0
  16. package/types/lib/2.app/flows/dynamic-init/convert-to-import-map.d.ts +2 -1
  17. package/types/lib/2.app/flows/dynamic-init/get-remote-entry.d.ts +1 -1
  18. package/types/lib/2.app/flows/dynamic-init/update-cache.d.ts +1 -1
  19. package/types/lib/2.app/flows/init/commit-changes.d.ts +1 -1
  20. package/types/lib/2.app/flows/init/generate-import-map.d.ts +1 -1
  21. package/types/lib/2.app/flows/init/get-remote-entries.d.ts +1 -1
  22. package/types/lib/2.app/flows/init/process-remote-entries.d.ts +1 -1
  23. package/types/lib/3.adapters/browser/sse-handler.d.ts +13 -0
  24. package/types/lib/3.adapters/storage/chunk.repository.d.ts +4 -0
  25. package/types/lib/4.config/logging/log.config.d.ts +1 -1
@@ -1281,7 +1281,7 @@ function createGetRemoteEntries(config, ports) {
1281
1281
  return (remotesOrManifestUrl = {}) => ports.manifestProvider.provide(remotesOrManifestUrl).catch((e) => {
1282
1282
  config.log.error(1, "Could not fetch manifest.", e);
1283
1283
  return Promise.reject(new NFError("Failed to fetch manifest"));
1284
- }).then(addHostRemoteEntry).then(fetchRemoteEntries).then(removeSkippedRemotes);
1284
+ }).then(addHostRemoteEntry).then(fetchRemoteEntries).then(removeSkippedRemotes).then(checkForSSE);
1285
1285
  function addHostRemoteEntry(manifest) {
1286
1286
  if (!config.hostRemoteEntry) return manifest;
1287
1287
  const { name, url, cacheTag } = config.hostRemoteEntry;
@@ -1344,6 +1344,21 @@ function createGetRemoteEntries(config, ports) {
1344
1344
  function removeSkippedRemotes(remoteEntries) {
1345
1345
  return remoteEntries.filter((entry) => entry !== false);
1346
1346
  }
1347
+ function checkForSSE(remoteEntries) {
1348
+ if (config.sse) {
1349
+ remoteEntries.forEach((entry) => {
1350
+ if (entry.buildNotificationsEndpoint) {
1351
+ ports.sse.watchRemoteBuilds(
1352
+ join(getScope(entry.url), entry.buildNotificationsEndpoint)
1353
+ );
1354
+ config.log.debug(1, `Registered SSE endpoint of remote '${entry.name}' `);
1355
+ return;
1356
+ }
1357
+ config.log.debug(1, `Remote ${entry.name} has no defined 'buildNotificationsEndpoint'`);
1358
+ });
1359
+ }
1360
+ return remoteEntries;
1361
+ }
1347
1362
  }
1348
1363
 
1349
1364
  // src/lib/2.app/flows/init/process-remote-entries.ts
@@ -1354,6 +1369,7 @@ function createProcessRemoteEntries(config, ports) {
1354
1369
  if (remoteEntry?.override) removeCachedRemoteEntry(remoteEntry);
1355
1370
  addRemoteInfoToStorage(remoteEntry);
1356
1371
  addExternalsToStorage(remoteEntry);
1372
+ addSharedChunksToStorage(remoteEntry);
1357
1373
  });
1358
1374
  return Promise.resolve(remoteEntries);
1359
1375
  } catch (e) {
@@ -1391,12 +1407,23 @@ function createProcessRemoteEntries(config, ports) {
1391
1407
  }
1392
1408
  });
1393
1409
  }
1410
+ function addSharedChunksToStorage(remoteEntry) {
1411
+ if (!remoteEntry.chunks) return;
1412
+ config.log.debug(
1413
+ 2,
1414
+ `Adding chunks for remote "${remoteEntry.name}", bundles: [${Object.keys(remoteEntry.chunks).join(", ")}]`
1415
+ );
1416
+ Object.entries(remoteEntry.chunks).forEach(([bundleName, chunks]) => {
1417
+ ports.sharedChunksRepo.addOrReplace(remoteEntry.name, bundleName, chunks);
1418
+ });
1419
+ }
1394
1420
  function addSharedExternal(remoteName, sharedInfo, remoteEntry) {
1395
1421
  let action = "skip";
1396
1422
  const tag = sharedInfo.version ?? ports.versionCheck.smallestVersion(sharedInfo.requiredVersion);
1397
1423
  const remote = {
1398
1424
  file: sharedInfo.outFileName,
1399
1425
  name: remoteName,
1426
+ bundle: sharedInfo.bundle,
1400
1427
  strictVersion: sharedInfo.strictVersion,
1401
1428
  cached: false,
1402
1429
  requiredVersion: sharedInfo.requiredVersion || tag
@@ -1438,7 +1465,8 @@ function createProcessRemoteEntries(config, ports) {
1438
1465
  function addScopedExternal(scope, sharedInfo) {
1439
1466
  ports.scopedExternalsRepo.addExternal(scope, sharedInfo.packageName, {
1440
1467
  tag: sharedInfo.version ?? ports.versionCheck.smallestVersion(sharedInfo.requiredVersion),
1441
- file: sharedInfo.outFileName
1468
+ file: sharedInfo.outFileName,
1469
+ bundle: sharedInfo.bundle
1442
1470
  });
1443
1471
  }
1444
1472
  }
@@ -1524,21 +1552,41 @@ function createDetermineSharedExternals(config, ports) {
1524
1552
  }
1525
1553
  }
1526
1554
 
1555
+ // node_modules/.pnpm/@softarc+native-federation@4.0.0-RC3_typescript@5.9.3_47bb4de43df406d114d8f653e70c5696/node_modules/@softarc/native-federation/src/lib/domain/core/build-notification-options.contract.js
1556
+ var BuildNotificationType;
1557
+ (function(BuildNotificationType2) {
1558
+ BuildNotificationType2["COMPLETED"] = "federation-rebuild-complete";
1559
+ BuildNotificationType2["ERROR"] = "federation-rebuild-error";
1560
+ BuildNotificationType2["CANCELLED"] = "federation-rebuild-cancelled";
1561
+ })(BuildNotificationType || (BuildNotificationType = {}));
1562
+
1563
+ // node_modules/.pnpm/@softarc+native-federation@4.0.0-RC3_typescript@5.9.3_47bb4de43df406d114d8f653e70c5696/node_modules/@softarc/native-federation/src/lib/domain/core/chunk.js
1564
+ var CHUNK_PREFIX = "@nf-internal";
1565
+ function toChunkImport(fileName) {
1566
+ if (fileName.startsWith("./")) {
1567
+ fileName = fileName.slice(2);
1568
+ }
1569
+ const packageName = fileName.replace(/.(m|c)?js$/, "");
1570
+ return CHUNK_PREFIX + "/" + packageName;
1571
+ }
1572
+
1527
1573
  // src/lib/2.app/flows/init/generate-import-map.ts
1528
1574
  function createGenerateImportMap(config, ports) {
1529
1575
  return () => {
1530
1576
  const importMap = { imports: {} };
1577
+ const chunkBundles = {};
1531
1578
  try {
1532
- addScopedExternals(importMap);
1533
- addshareScopeExternals(importMap);
1534
- addGlobalSharedExternals(importMap);
1579
+ addScopedExternals(importMap, chunkBundles);
1580
+ addshareScopeExternals(importMap, chunkBundles);
1581
+ addGlobalSharedExternals(importMap, chunkBundles);
1582
+ addChunkImports(importMap, chunkBundles);
1535
1583
  addRemoteInfos(importMap);
1536
1584
  return Promise.resolve(importMap);
1537
1585
  } catch (e) {
1538
1586
  return Promise.reject(e);
1539
1587
  }
1540
1588
  };
1541
- function addScopedExternals(importMap) {
1589
+ function addScopedExternals(importMap, chunkBundles) {
1542
1590
  const scopedExternals = ports.scopedExternalsRepo.getAll();
1543
1591
  for (const [remoteName, externals] of Object.entries(scopedExternals)) {
1544
1592
  const remote = ports.remoteInfoRepo.tryGet(remoteName).orThrow(() => {
@@ -1546,6 +1594,7 @@ function createGenerateImportMap(config, ports) {
1546
1594
  return new NFError("Could not create ImportMap.");
1547
1595
  });
1548
1596
  addToScope(importMap, remote.scopeUrl, createScopeModules(externals, remote.scopeUrl));
1597
+ Object.values(externals).filter((e) => !!e.bundle).forEach((e) => registerBundleChunks(chunkBundles, remoteName, e.bundle));
1549
1598
  }
1550
1599
  return importMap;
1551
1600
  }
@@ -1556,14 +1605,14 @@ function createGenerateImportMap(config, ports) {
1556
1605
  }
1557
1606
  return modules;
1558
1607
  }
1559
- function addshareScopeExternals(importMap) {
1608
+ function addshareScopeExternals(importMap, chunkBundles) {
1560
1609
  const shareScopes = ports.sharedExternalsRepo.getScopes({ includeGlobal: false });
1561
1610
  for (const shareScope of shareScopes) {
1562
- processshareScope(importMap, shareScope);
1611
+ processshareScope(importMap, shareScope, chunkBundles);
1563
1612
  }
1564
1613
  return importMap;
1565
1614
  }
1566
- function processshareScope(importMap, shareScope) {
1615
+ function processshareScope(importMap, shareScope, chunkBundles) {
1567
1616
  const sharedExternals = ports.sharedExternalsRepo.getFromScope(shareScope);
1568
1617
  for (const [externalName, external] of Object.entries(sharedExternals)) {
1569
1618
  let override = void 0;
@@ -1571,15 +1620,16 @@ function createGenerateImportMap(config, ports) {
1571
1620
  for (const version of external.versions) {
1572
1621
  if (version.action === "scope") {
1573
1622
  for (const remote of version.remotes) {
1574
- const remoteScope = getScope2(externalName, shareScope, remote.name);
1623
+ const remoteScope = getScope2(shareScope, remote.name, externalName);
1575
1624
  addToScope(importMap, remoteScope, {
1576
1625
  [externalName]: join(remoteScope, remote.file)
1577
1626
  });
1627
+ registerBundleChunks(chunkBundles, remote.name, remote.bundle);
1578
1628
  remote.cached = true;
1579
1629
  }
1580
1630
  continue;
1581
1631
  }
1582
- const scope = getScope2(externalName, shareScope, version.remotes[0].name);
1632
+ const scope = getScope2(shareScope, version.remotes[0].name, externalName);
1583
1633
  let targetFileUrl = join(scope, version.remotes[0].file);
1584
1634
  version.remotes[0].cached = true;
1585
1635
  if (version.action === "skip") {
@@ -1588,14 +1638,14 @@ function createGenerateImportMap(config, ports) {
1588
1638
  }
1589
1639
  if (override !== "NOT_AVAILABLE") {
1590
1640
  if (!overrideScope)
1591
- overrideScope = getScope2(externalName, shareScope, override.remotes[0].name);
1641
+ overrideScope = getScope2(shareScope, override.remotes[0].name, externalName);
1592
1642
  targetFileUrl = join(overrideScope, override.remotes[0].file);
1593
1643
  override.remotes[0].cached = true;
1594
1644
  version.remotes[0].cached = false;
1595
1645
  }
1596
1646
  }
1597
1647
  version.remotes.forEach((r) => {
1598
- const scope2 = getScope2(externalName, shareScope, r.name);
1648
+ const scope2 = getScope2(shareScope, r.name, externalName);
1599
1649
  addToScope(importMap, scope2, { [externalName]: targetFileUrl });
1600
1650
  });
1601
1651
  }
@@ -1630,34 +1680,36 @@ function createGenerateImportMap(config, ports) {
1630
1680
  }
1631
1681
  config.log.warn(4, `ShareScope external ${scopedExternalName} has multiple shared versions.`);
1632
1682
  }
1633
- function addGlobalSharedExternals(importMap) {
1683
+ function addGlobalSharedExternals(importMap, chunkBundles) {
1634
1684
  const sharedExternals = ports.sharedExternalsRepo.getFromScope();
1635
1685
  for (const [externalName, external] of Object.entries(sharedExternals)) {
1636
1686
  for (const version of external.versions) {
1637
1687
  if (version.action === "skip") continue;
1638
1688
  if (version.action === "scope") {
1639
1689
  for (const remote of version.remotes) {
1640
- const remoteScope = getScope2(externalName, GLOBAL_SCOPE, remote.name);
1690
+ const remoteScope = getScope2(GLOBAL_SCOPE, remote.name, externalName);
1641
1691
  addToScope(importMap, remoteScope, {
1642
1692
  [externalName]: join(remoteScope, remote.file)
1643
1693
  });
1644
1694
  remote.cached = true;
1695
+ registerBundleChunks(chunkBundles, remote.name, remote.bundle);
1645
1696
  }
1646
1697
  continue;
1647
1698
  }
1648
1699
  if (importMap.imports[externalName]) {
1649
- handleDuplicateGlobalExternal(externalName);
1700
+ notifyDuplicateGlobalExternal(externalName);
1650
1701
  continue;
1651
1702
  }
1652
- const scope = getScope2(externalName, GLOBAL_SCOPE, version.remotes[0].name);
1703
+ const scope = getScope2(GLOBAL_SCOPE, version.remotes[0].name, externalName);
1653
1704
  addToGlobal(importMap, { [externalName]: join(scope, version.remotes[0].file) });
1705
+ registerBundleChunks(chunkBundles, version.remotes[0].name, version.remotes[0].bundle);
1654
1706
  version.remotes[0].cached = true;
1655
1707
  }
1656
1708
  ports.sharedExternalsRepo.addOrUpdate(externalName, external);
1657
1709
  }
1658
1710
  return importMap;
1659
1711
  }
1660
- function handleDuplicateGlobalExternal(externalName) {
1712
+ function notifyDuplicateGlobalExternal(externalName) {
1661
1713
  if (config.strict.strictImportMap) {
1662
1714
  config.log.error(4, `[${externalName}] Shared external has multiple shared versions.`);
1663
1715
  throw new NFError("Could not create ImportMap.");
@@ -1685,12 +1737,37 @@ function createGenerateImportMap(config, ports) {
1685
1737
  importMap.imports[moduleName] = moduleUrl;
1686
1738
  }
1687
1739
  }
1688
- function getScope2(externalName, shareScope, remoteName) {
1740
+ function registerBundleChunks(chunkBundles, remoteName, bundleName) {
1741
+ if (!bundleName) return chunkBundles;
1742
+ if (!chunkBundles[remoteName]) chunkBundles[remoteName] = /* @__PURE__ */ new Set();
1743
+ chunkBundles[remoteName].add(bundleName);
1744
+ return chunkBundles;
1745
+ }
1746
+ function addChunkImports(importMap, chunkBundles) {
1747
+ const chunkImports = Object.entries(chunkBundles).reduce((imports, [remoteName, bundles]) => {
1748
+ const baseUrl = getScope2("CHUNKS", remoteName);
1749
+ Array.from(bundles).forEach((bundleName) => {
1750
+ ports.sharedChunksRepo.tryGet(remoteName, bundleName).ifPresent((files) => {
1751
+ files.forEach((file) => {
1752
+ imports[toChunkImport(file)] = join(baseUrl, file);
1753
+ });
1754
+ });
1755
+ });
1756
+ return imports;
1757
+ }, {});
1758
+ addToGlobal(importMap, chunkImports);
1759
+ return importMap;
1760
+ }
1761
+ function getScope2(ctx, remoteName, externalName) {
1689
1762
  return ports.remoteInfoRepo.tryGet(remoteName).map((remote) => remote.scopeUrl).orThrow(() => {
1690
- config.log.error(
1691
- 4,
1692
- `[${shareScope}][${externalName}][${remoteName}] Remote name not found in cache.`
1693
- );
1763
+ if (externalName) {
1764
+ config.log.error(
1765
+ 4,
1766
+ `[${ctx}][${externalName}][${remoteName}] Remote name not found in cache.`
1767
+ );
1768
+ } else {
1769
+ config.log.error(4, `[${ctx}][${remoteName}] Remote name not found in cache.`);
1770
+ }
1694
1771
  return new NFError("Could not create ImportMap.");
1695
1772
  });
1696
1773
  }
@@ -1708,6 +1785,7 @@ function createCommitChanges(config, ports) {
1708
1785
  ports.remoteInfoRepo.commit();
1709
1786
  ports.scopedExternalsRepo.commit();
1710
1787
  ports.sharedExternalsRepo.commit();
1788
+ ports.sharedChunksRepo.commit();
1711
1789
  return;
1712
1790
  }
1713
1791
  }
@@ -2016,6 +2094,68 @@ var createSharedExternalsRepository = (config) => {
2016
2094
  };
2017
2095
  };
2018
2096
 
2097
+ // src/lib/3.adapters/browser/sse-handler.ts
2098
+ var createSSEHandler = (config) => {
2099
+ const subscribers = [];
2100
+ return {
2101
+ watchRemoteBuilds: function(endpoint) {
2102
+ const eventSource = new EventSource(endpoint);
2103
+ eventSource.onmessage = function(event) {
2104
+ const data = JSON.parse(event.data);
2105
+ if (data.type === BuildNotificationType.COMPLETED) {
2106
+ subscribers.forEach((sub) => sub.close());
2107
+ config.log.debug(0, "[SSE] Rebuild completed, reloading...");
2108
+ config.reloadBrowserFn();
2109
+ }
2110
+ };
2111
+ eventSource.onerror = function(event) {
2112
+ config.log.error(0, "[SSE] Connection error:", event);
2113
+ };
2114
+ subscribers.push(eventSource);
2115
+ },
2116
+ closeAll: function() {
2117
+ subscribers.forEach((sub) => sub.close());
2118
+ subscribers.length = 0;
2119
+ }
2120
+ };
2121
+ };
2122
+
2123
+ // src/lib/utils/clone-entry.ts
2124
+ var cloneEntry = (name, raw) => {
2125
+ try {
2126
+ if (typeof structuredClone === "function") {
2127
+ return structuredClone(raw);
2128
+ }
2129
+ } catch {
2130
+ }
2131
+ try {
2132
+ return JSON.parse(JSON.stringify(raw));
2133
+ } catch {
2134
+ }
2135
+ throw new NFError(`Could not parse storage entry '${String(name)}'`);
2136
+ };
2137
+
2138
+ // src/lib/3.adapters/storage/chunk.repository.ts
2139
+ var createChunkRepository = (config) => {
2140
+ const STORAGE = config.storage("shared-chunks", {});
2141
+ if (config.clearStorage) STORAGE.clear();
2142
+ const _cache = STORAGE.get() ?? {};
2143
+ return {
2144
+ addOrReplace: function(remoteName, bundleName, chunks) {
2145
+ if (!_cache[remoteName]) _cache[remoteName] = {};
2146
+ _cache[remoteName][bundleName] = chunks;
2147
+ return this;
2148
+ },
2149
+ tryGet: function(remoteName, bundleName) {
2150
+ return Optional.of(_cache[remoteName]?.[bundleName]);
2151
+ },
2152
+ commit: function() {
2153
+ STORAGE.set(_cache);
2154
+ return this;
2155
+ }
2156
+ };
2157
+ };
2158
+
2019
2159
  // src/lib/5.di/driving.factory.ts
2020
2160
  var createDriving = (config) => {
2021
2161
  const adapters = {
@@ -2025,7 +2165,9 @@ var createDriving = (config) => {
2025
2165
  remoteInfoRepo: createRemoteInfoRepository(config),
2026
2166
  scopedExternalsRepo: createScopedExternalsRepository(config),
2027
2167
  sharedExternalsRepo: createSharedExternalsRepository(config),
2028
- browser: createBrowser(config)
2168
+ sharedChunksRepo: createChunkRepository(config),
2169
+ browser: createBrowser(config),
2170
+ sse: createSSEHandler(config)
2029
2171
  };
2030
2172
  return { adapters, config };
2031
2173
  };
@@ -2050,7 +2192,10 @@ var useDefaultImportMap = () => ({
2050
2192
  /* @vite-ignore */
2051
2193
  url
2052
2194
  ),
2053
- setImportMapFn: replaceInDOM("importmap")
2195
+ setImportMapFn: replaceInDOM("importmap"),
2196
+ reloadBrowserFn: () => {
2197
+ window.location.reload();
2198
+ }
2054
2199
  });
2055
2200
 
2056
2201
  // src/lib/4.config/import-map/import-map.config.ts
@@ -2058,7 +2203,8 @@ var createImportMapConfig = (o) => {
2058
2203
  const fallback = useDefaultImportMap();
2059
2204
  return {
2060
2205
  setImportMapFn: o.setImportMapFn ?? fallback.setImportMapFn,
2061
- loadModuleFn: o.loadModuleFn ?? fallback.loadModuleFn
2206
+ loadModuleFn: o.loadModuleFn ?? fallback.loadModuleFn,
2207
+ reloadBrowserFn: o.reloadBrowserFn ?? fallback.reloadBrowserFn
2062
2208
  };
2063
2209
  };
2064
2210
 
@@ -2119,25 +2265,11 @@ var createLogHandler = (logger, logLevel) => {
2119
2265
  };
2120
2266
 
2121
2267
  // src/lib/4.config/logging/log.config.ts
2122
- var createLogConfig = ({ logger, logLevel }) => ({
2123
- log: createLogHandler(logger ?? noopLogger, logLevel ?? "error")
2268
+ var createLogConfig = ({ logger, logLevel, sse }) => ({
2269
+ log: createLogHandler(logger ?? noopLogger, logLevel ?? "error"),
2270
+ sse: !!sse
2124
2271
  });
2125
2272
 
2126
- // src/lib/utils/clone-entry.ts
2127
- var cloneEntry = (name, raw) => {
2128
- try {
2129
- if (typeof structuredClone === "function") {
2130
- return structuredClone(raw);
2131
- }
2132
- } catch {
2133
- }
2134
- try {
2135
- return JSON.parse(JSON.stringify(raw));
2136
- } catch {
2137
- }
2138
- throw new NFError(`Could not parse storage entry '${String(name)}'`);
2139
- };
2140
-
2141
2273
  // src/lib/4.config/storage/global-this.storage.ts
2142
2274
  var globalThisStorageEntry = (namespace) => (key, initialValue) => {
2143
2275
  if (!globalThis[namespace]) {
@@ -2203,7 +2335,7 @@ var createConfigHandlers = (overrides) => ({
2203
2335
  });
2204
2336
 
2205
2337
  // src/lib/2.app/flows/dynamic-init/convert-to-import-map.ts
2206
- function createConvertToImportMap({ log }) {
2338
+ function createConvertToImportMap({ log }, ports) {
2207
2339
  return ({ entry, actions }) => {
2208
2340
  const importMap = { imports: {} };
2209
2341
  addExternals(entry, actions, importMap);
@@ -2216,6 +2348,7 @@ function createConvertToImportMap({ log }) {
2216
2348
  return;
2217
2349
  }
2218
2350
  const remoteEntryScope = getScope(remoteEntry.url);
2351
+ const chunkBundles = /* @__PURE__ */ new Set();
2219
2352
  remoteEntry.shared.forEach((external) => {
2220
2353
  if (!external.singleton) {
2221
2354
  addToScopes(
@@ -2224,6 +2357,7 @@ function createConvertToImportMap({ log }) {
2224
2357
  join(remoteEntryScope, external.outFileName),
2225
2358
  importMap
2226
2359
  );
2360
+ if (external?.bundle) chunkBundles.add(external?.bundle);
2227
2361
  return;
2228
2362
  }
2229
2363
  if (!actions[external.packageName]) {
@@ -2245,6 +2379,7 @@ function createConvertToImportMap({ log }) {
2245
2379
  return;
2246
2380
  }
2247
2381
  }
2382
+ if (external?.bundle) chunkBundles.add(external?.bundle);
2248
2383
  if (actions[external.packageName].action === "scope") {
2249
2384
  addToScopes(
2250
2385
  remoteEntryScope,
@@ -2265,6 +2400,7 @@ function createConvertToImportMap({ log }) {
2265
2400
  }
2266
2401
  importMap.imports[external.packageName] = join(remoteEntryScope, external.outFileName);
2267
2402
  });
2403
+ addChunkImports(importMap, remoteEntry.name, remoteEntryScope, chunkBundles);
2268
2404
  }
2269
2405
  function addToScopes(scope, packageName, url, importMap) {
2270
2406
  if (!importMap.scopes) importMap.scopes = {};
@@ -2280,6 +2416,18 @@ function createConvertToImportMap({ log }) {
2280
2416
  importMap.imports[moduleName] = moduleUrl;
2281
2417
  });
2282
2418
  }
2419
+ function addChunkImports(importMap, remoteName, baseUrl, chunkBundles) {
2420
+ const chunkImports = Array.from(chunkBundles).reduce((imports, bundleName) => {
2421
+ ports.sharedChunksRepo.tryGet(remoteName, bundleName).ifPresent((files) => {
2422
+ files.forEach((file) => {
2423
+ imports[toChunkImport(file)] = join(baseUrl, file);
2424
+ });
2425
+ });
2426
+ return imports;
2427
+ }, {});
2428
+ importMap.imports = { ...importMap.imports, ...chunkImports };
2429
+ return importMap;
2430
+ }
2283
2431
  }
2284
2432
 
2285
2433
  // src/lib/2.app/flows/dynamic-init/get-remote-entry.ts
@@ -2307,7 +2455,7 @@ function createGetRemoteEntry(config, ports) {
2307
2455
  remoteEntry.override = true;
2308
2456
  config.log.debug(7, `Overriding existing remote '${remoteName}' with '${remoteEntryUrl}'.`);
2309
2457
  }
2310
- return Optional.of(remoteEntry);
2458
+ return Optional.of(checkForSSE(remoteEntry));
2311
2459
  } catch (error) {
2312
2460
  config.log.error(
2313
2461
  7,
@@ -2324,6 +2472,19 @@ function createGetRemoteEntry(config, ports) {
2324
2472
  (cachedRemoteInfo) => config.profile.overrideCachedRemotes !== "always" || !config.profile.overrideCachedRemotesIfURLMatches && remoteEntryUrl === join(cachedRemoteInfo.scopeUrl, "remoteEntry.json")
2325
2473
  ).orElse(false);
2326
2474
  }
2475
+ function checkForSSE(entry) {
2476
+ if (config.sse) {
2477
+ if (entry.buildNotificationsEndpoint) {
2478
+ ports.sse.watchRemoteBuilds(
2479
+ join(getScope(entry.url), entry.buildNotificationsEndpoint)
2480
+ );
2481
+ config.log.debug(7, `Registered SSE endpoint of remote '${entry.name}' `);
2482
+ } else {
2483
+ config.log.debug(7, `Remote ${entry.name} has no defined 'buildNotificationsEndpoint'`);
2484
+ }
2485
+ }
2486
+ return entry;
2487
+ }
2327
2488
  }
2328
2489
 
2329
2490
  // src/lib/2.app/flows/dynamic-init/update-cache.ts
@@ -2333,6 +2494,7 @@ function createUpdateCache(config, ports) {
2333
2494
  if (remoteEntry?.override) removeCachedRemoteEntry(remoteEntry);
2334
2495
  addRemoteInfoToStorage(remoteEntry);
2335
2496
  const actions = mergeExternalsIntoStorage(remoteEntry);
2497
+ addSharedChunksToStorage(remoteEntry);
2336
2498
  return Promise.resolve({ entry: remoteEntry, actions });
2337
2499
  } catch (error) {
2338
2500
  return Promise.reject(error);
@@ -2383,6 +2545,16 @@ function createUpdateCache(config, ports) {
2383
2545
  });
2384
2546
  return actions;
2385
2547
  }
2548
+ function addSharedChunksToStorage(remoteEntry) {
2549
+ if (!remoteEntry.chunks) return;
2550
+ config.log.debug(
2551
+ 8,
2552
+ `Adding chunks for remote "${remoteEntry.name}", bundles: [${Object.keys(remoteEntry.chunks).join(", ")}]`
2553
+ );
2554
+ Object.entries(remoteEntry.chunks).forEach(([bundleName, chunks]) => {
2555
+ ports.sharedChunksRepo.addOrReplace(remoteEntry.name, bundleName, chunks);
2556
+ });
2557
+ }
2386
2558
  function addSharedExternal(remoteName, sharedInfo) {
2387
2559
  const cached = ports.sharedExternalsRepo.tryGet(sharedInfo.packageName, sharedInfo.shareScope).orElse({ dirty: false, versions: [] });
2388
2560
  let action = "skip";
@@ -2392,6 +2564,7 @@ function createUpdateCache(config, ports) {
2392
2564
  strictVersion: sharedInfo.strictVersion,
2393
2565
  requiredVersion: sharedInfo.requiredVersion || tag,
2394
2566
  name: remoteName,
2567
+ bundle: sharedInfo.bundle,
2395
2568
  cached: false
2396
2569
  };
2397
2570
  const scopeType = ports.sharedExternalsRepo.scopeType(sharedInfo.shareScope);
@@ -2439,7 +2612,8 @@ function createUpdateCache(config, ports) {
2439
2612
  function addScopedExternal(remoteName, sharedInfo) {
2440
2613
  ports.scopedExternalsRepo.addExternal(remoteName, sharedInfo.packageName, {
2441
2614
  tag: sharedInfo.version ?? ports.versionCheck.smallestVersion(sharedInfo.requiredVersion),
2442
- file: sharedInfo.outFileName
2615
+ file: sharedInfo.outFileName,
2616
+ bundle: sharedInfo.bundle
2443
2617
  });
2444
2618
  }
2445
2619
  }
@@ -2451,7 +2625,7 @@ var createDynamicInitDrivers = ({
2451
2625
  }) => ({
2452
2626
  getRemoteEntry: createGetRemoteEntry(config, adapters),
2453
2627
  updateCache: createUpdateCache(config, adapters),
2454
- convertToImportMap: createConvertToImportMap(config),
2628
+ convertToImportMap: createConvertToImportMap(config, adapters),
2455
2629
  commitChanges: createCommitChanges(config, adapters)
2456
2630
  });
2457
2631
  var DYNAMIC_INIT_FLOW_FACTORY = ({