@module-federation/runtime 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -89,8 +89,8 @@ function registerPlugins$1(plugins, hookInstances) {
89
89
  return plugins;
90
90
  }
91
91
 
92
- function _extends$5() {
93
- _extends$5 = Object.assign || function(target) {
92
+ function _extends$7() {
93
+ _extends$7 = Object.assign || function(target) {
94
94
  for(var i = 1; i < arguments.length; i++){
95
95
  var source = arguments[i];
96
96
  for(var key in source){
@@ -101,7 +101,7 @@ function _extends$5() {
101
101
  }
102
102
  return target;
103
103
  };
104
- return _extends$5.apply(this, arguments);
104
+ return _extends$7.apply(this, arguments);
105
105
  }
106
106
  async function loadEsmEntry({ entry, remoteEntryExports }) {
107
107
  return new Promise((resolve, reject)=>{
@@ -189,7 +189,7 @@ async function getRemoteEntry({ remoteEntryExports, remoteInfo, createScriptHook
189
189
  return share.globalLoading[uniqueKey];
190
190
  }
191
191
  function getRemoteInfo(remote) {
192
- return _extends$5({}, remote, {
192
+ return _extends$7({}, remote, {
193
193
  entry: 'entry' in remote ? remote.entry : '',
194
194
  type: remote.type || share.DEFAULT_REMOTE_TYPE,
195
195
  entryGlobalName: remote.entryGlobalName || remote.name,
@@ -197,8 +197,8 @@ function getRemoteInfo(remote) {
197
197
  });
198
198
  }
199
199
 
200
- function _extends$4() {
201
- _extends$4 = Object.assign || function(target) {
200
+ function _extends$6() {
201
+ _extends$6 = Object.assign || function(target) {
202
202
  for(var i = 1; i < arguments.length; i++){
203
203
  var source = arguments[i];
204
204
  for(var key in source){
@@ -209,7 +209,7 @@ function _extends$4() {
209
209
  }
210
210
  return target;
211
211
  };
212
- return _extends$4.apply(this, arguments);
212
+ return _extends$6.apply(this, arguments);
213
213
  }
214
214
  let Module = class Module {
215
215
  async getEntry() {
@@ -271,7 +271,7 @@ let Module = class Module {
271
271
  origin: this.host
272
272
  });
273
273
  await remoteEntryExports.init(initContainerOptions.shareScope, initContainerOptions.initScope, initContainerOptions.remoteEntryInitOptions);
274
- await this.host.hooks.lifecycle.initContainer.emit(_extends$4({}, initContainerOptions, {
274
+ await this.host.hooks.lifecycle.initContainer.emit(_extends$6({}, initContainerOptions, {
275
275
  remoteEntryExports
276
276
  }));
277
277
  }
@@ -481,8 +481,8 @@ class PluginSystem {
481
481
  }
482
482
  }
483
483
 
484
- function _extends$3() {
485
- _extends$3 = Object.assign || function(target) {
484
+ function _extends$5() {
485
+ _extends$5 = Object.assign || function(target) {
486
486
  for(var i = 1; i < arguments.length; i++){
487
487
  var source = arguments[i];
488
488
  for(var key in source){
@@ -493,10 +493,10 @@ function _extends$3() {
493
493
  }
494
494
  return target;
495
495
  };
496
- return _extends$3.apply(this, arguments);
496
+ return _extends$5.apply(this, arguments);
497
497
  }
498
498
  function defaultPreloadArgs(preloadConfig) {
499
- return _extends$3({
499
+ return _extends$5({
500
500
  resourceCategory: 'sync',
501
501
  share: true,
502
502
  depsRemote: true,
@@ -603,8 +603,8 @@ function preloadAssets(remoteInfo, host, assets) {
603
603
  }
604
604
  }
605
605
 
606
- function _extends$2() {
607
- _extends$2 = Object.assign || function(target) {
606
+ function _extends$4() {
607
+ _extends$4 = Object.assign || function(target) {
608
608
  for(var i = 1; i < arguments.length; i++){
609
609
  var source = arguments[i];
610
610
  for(var key in source){
@@ -615,7 +615,7 @@ function _extends$2() {
615
615
  }
616
616
  return target;
617
617
  };
618
- return _extends$2.apply(this, arguments);
618
+ return _extends$4.apply(this, arguments);
619
619
  }
620
620
  function assignRemoteInfo(remoteInfo, remoteSnapshot) {
621
621
  if (!('remoteEntry' in remoteSnapshot) || !remoteSnapshot.remoteEntry) {
@@ -650,7 +650,7 @@ function snapshotPlugin() {
650
650
  depsRemote: false
651
651
  }
652
652
  };
653
- const assets = await origin.hooks.lifecycle.generatePreloadAssets.emit({
653
+ const assets = await origin.remoteHandler.hooks.lifecycle.generatePreloadAssets.emit({
654
654
  origin,
655
655
  preloadOptions,
656
656
  remoteInfo,
@@ -661,7 +661,7 @@ function snapshotPlugin() {
661
661
  if (assets) {
662
662
  preloadAssets(remoteInfo, origin, assets);
663
663
  }
664
- return _extends$2({}, args, {
664
+ return _extends$4({}, args, {
665
665
  remoteSnapshot
666
666
  });
667
667
  }
@@ -787,7 +787,7 @@ function generatePreloadAssets(origin, preloadOptions, remote, globalSnapshot, r
787
787
  for(let index = 0; index < assetsLength; index++){
788
788
  const assetsInfo = moduleAssetsInfo[index];
789
789
  const exposeFullPath = `${remoteInfo.name}/${assetsInfo.moduleName}`;
790
- origin.hooks.lifecycle.handlePreloadModule.emit({
790
+ origin.remoteHandler.hooks.lifecycle.handlePreloadModule.emit({
791
791
  id: assetsInfo.moduleName === '.' ? remoteInfo.name : exposeFullPath,
792
792
  name: remoteInfo.name,
793
793
  remoteSnapshot: moduleInfoSnapshot,
@@ -815,7 +815,7 @@ function generatePreloadAssets(origin, preloadOptions, remote, globalSnapshot, r
815
815
  }, true, memo, remoteSnapshot);
816
816
  if (remoteSnapshot.shared) {
817
817
  const collectSharedAssets = (shareInfo, snapshotShared)=>{
818
- const registeredShared = share.getRegisteredShare(origin.shareScopeMap, snapshotShared.sharedName, shareInfo, origin.hooks.lifecycle.resolveShare);
818
+ const registeredShared = share.getRegisteredShare(origin.shareScopeMap, snapshotShared.sharedName, shareInfo, origin.sharedHandler.hooks.lifecycle.resolveShare);
819
819
  // If the global share does not exist, or the lib function does not exist, it means that the shared has not been loaded yet and can be preloaded.
820
820
  if (registeredShared && typeof registeredShared.lib === 'function') {
821
821
  snapshotShared.assets.js.sync.forEach((asset)=>{
@@ -882,8 +882,8 @@ const generatePreloadAssetsPlugin = function() {
882
882
  };
883
883
  };
884
884
 
885
- function _extends$1() {
886
- _extends$1 = Object.assign || function(target) {
885
+ function _extends$3() {
886
+ _extends$3 = Object.assign || function(target) {
887
887
  for(var i = 1; i < arguments.length; i++){
888
888
  var source = arguments[i];
889
889
  for(var key in source){
@@ -894,7 +894,7 @@ function _extends$1() {
894
894
  }
895
895
  return target;
896
896
  };
897
- return _extends$1.apply(this, arguments);
897
+ return _extends$3.apply(this, arguments);
898
898
  }
899
899
  class SnapshotHandler {
900
900
  async loadSnapshot(moduleInfo) {
@@ -937,7 +937,7 @@ class SnapshotHandler {
937
937
  // This ensures the snapshot's integrity and helps the chrome plugin correctly identify all producer modules, ensuring that proxyable producer modules will not be missing.
938
938
  if (hostSnapshot && 'remotesInfo' in hostSnapshot && !share.getInfoWithoutType(hostSnapshot.remotesInfo, moduleInfo.name).value) {
939
939
  if ('version' in moduleInfo || 'entry' in moduleInfo) {
940
- hostSnapshot.remotesInfo = _extends$1({}, hostSnapshot == null ? void 0 : hostSnapshot.remotesInfo, {
940
+ hostSnapshot.remotesInfo = _extends$3({}, hostSnapshot == null ? void 0 : hostSnapshot.remotesInfo, {
941
941
  [moduleInfo.name]: {
942
942
  matchedVersion: 'version' in moduleInfo ? moduleInfo.version : moduleInfo.entry
943
943
  }
@@ -957,7 +957,7 @@ class SnapshotHandler {
957
957
  if (sdk.isManifestProvider(globalRemoteSnapshot)) {
958
958
  const moduleSnapshot = await this.getManifestJson(globalRemoteSnapshot.remoteEntry, moduleInfo, {});
959
959
  // eslint-disable-next-line @typescript-eslint/no-shadow
960
- const globalSnapshotRes = share.setGlobalSnapshotInfoByModuleInfo(_extends$1({}, moduleInfo, {
960
+ const globalSnapshotRes = share.setGlobalSnapshotInfoByModuleInfo(_extends$3({}, moduleInfo, {
961
961
  // The global remote may be overridden
962
962
  // Therefore, set the snapshot key to the global address of the actual request
963
963
  entry: globalRemoteSnapshot.remoteEntry
@@ -1085,8 +1085,8 @@ class SnapshotHandler {
1085
1085
  }
1086
1086
  }
1087
1087
 
1088
- function _extends() {
1089
- _extends = Object.assign || function(target) {
1088
+ function _extends$2() {
1089
+ _extends$2 = Object.assign || function(target) {
1090
1090
  for(var i = 1; i < arguments.length; i++){
1091
1091
  var source = arguments[i];
1092
1092
  for(var key in source){
@@ -1097,7 +1097,7 @@ function _extends() {
1097
1097
  }
1098
1098
  return target;
1099
1099
  };
1100
- return _extends.apply(this, arguments);
1100
+ return _extends$2.apply(this, arguments);
1101
1101
  }
1102
1102
  function _object_without_properties_loose(source, excluded) {
1103
1103
  if (source == null) return {};
@@ -1111,21 +1111,34 @@ function _object_without_properties_loose(source, excluded) {
1111
1111
  }
1112
1112
  return target;
1113
1113
  }
1114
- class FederationHost {
1115
- _setGlobalShareScopeMap() {
1116
- const globalShareScopeMap = share.getGlobalShareScope();
1117
- const identifier = this.options.id || this.options.name;
1118
- if (identifier && !globalShareScopeMap[identifier]) {
1119
- globalShareScopeMap[identifier] = this.shareScopeMap;
1120
- }
1121
- }
1122
- initOptions(userOptions) {
1123
- this.registerPlugins(userOptions.plugins);
1124
- const options = this.formatOptions(this.options, userOptions);
1125
- this.options = options;
1126
- return options;
1114
+ class SharedHandler {
1115
+ // register shared in shareScopeMap
1116
+ registerShared(globalOptions, userOptions) {
1117
+ const { shareInfos, shared } = share.formatShareConfigs(globalOptions, userOptions);
1118
+ const sharedKeys = Object.keys(shareInfos);
1119
+ sharedKeys.forEach((sharedKey)=>{
1120
+ const sharedVals = shareInfos[sharedKey];
1121
+ sharedVals.forEach((sharedVal)=>{
1122
+ const registeredShared = share.getRegisteredShare(this.shareScopeMap, sharedKey, sharedVal, this.hooks.lifecycle.resolveShare);
1123
+ if (!registeredShared && sharedVal && sharedVal.lib) {
1124
+ this.setShared({
1125
+ pkgName: sharedKey,
1126
+ lib: sharedVal.lib,
1127
+ get: sharedVal.get,
1128
+ loaded: true,
1129
+ shared: sharedVal,
1130
+ from: userOptions.name
1131
+ });
1132
+ }
1133
+ });
1134
+ });
1135
+ return {
1136
+ shareInfos,
1137
+ shared
1138
+ };
1127
1139
  }
1128
1140
  async loadShare(pkgName, extraOptions) {
1141
+ const { host } = this;
1129
1142
  // This function performs the following steps:
1130
1143
  // 1. Checks if the currently loaded share already exists, if not, it throws an error
1131
1144
  // 2. Searches globally for a matching share, if found, it uses it directly
@@ -1133,7 +1146,7 @@ class FederationHost {
1133
1146
  const shareInfo = share.getTargetSharedOptions({
1134
1147
  pkgName,
1135
1148
  extraOptions,
1136
- shareInfos: this.options.shared
1149
+ shareInfos: host.options.shared
1137
1150
  });
1138
1151
  if (shareInfo == null ? void 0 : shareInfo.scope) {
1139
1152
  await Promise.all(shareInfo.scope.map(async (shareScope)=>{
@@ -1144,19 +1157,19 @@ class FederationHost {
1144
1157
  const loadShareRes = await this.hooks.lifecycle.beforeLoadShare.emit({
1145
1158
  pkgName,
1146
1159
  shareInfo,
1147
- shared: this.options.shared,
1148
- origin: this
1160
+ shared: host.options.shared,
1161
+ origin: host
1149
1162
  });
1150
1163
  const { shareInfo: shareInfoRes } = loadShareRes;
1151
1164
  // Assert that shareInfoRes exists, if not, throw an error
1152
- share.assert(shareInfoRes, `Cannot find ${pkgName} Share in the ${this.options.name}. Please ensure that the ${pkgName} Share parameters have been injected`);
1165
+ share.assert(shareInfoRes, `Cannot find ${pkgName} Share in the ${host.options.name}. Please ensure that the ${pkgName} Share parameters have been injected`);
1153
1166
  // Retrieve from cache
1154
1167
  const registeredShared = share.getRegisteredShare(this.shareScopeMap, pkgName, shareInfoRes, this.hooks.lifecycle.resolveShare);
1155
1168
  const addUseIn = (shared)=>{
1156
1169
  if (!shared.useIn) {
1157
1170
  shared.useIn = [];
1158
1171
  }
1159
- share.addUniqueItem(shared.useIn, this.options.name);
1172
+ share.addUniqueItem(shared.useIn, host.options.name);
1160
1173
  };
1161
1174
  if (registeredShared && registeredShared.lib) {
1162
1175
  addUseIn(registeredShared);
@@ -1187,7 +1200,7 @@ class FederationHost {
1187
1200
  pkgName,
1188
1201
  loaded: false,
1189
1202
  shared: registeredShared,
1190
- from: this.options.name,
1203
+ from: host.options.name,
1191
1204
  lib: null,
1192
1205
  loading
1193
1206
  });
@@ -1213,22 +1226,80 @@ class FederationHost {
1213
1226
  pkgName,
1214
1227
  loaded: false,
1215
1228
  shared: shareInfoRes,
1216
- from: this.options.name,
1229
+ from: host.options.name,
1217
1230
  lib: null,
1218
1231
  loading
1219
1232
  });
1220
1233
  return loading;
1221
1234
  }
1222
1235
  }
1236
+ /**
1237
+ * This function initializes the sharing sequence (executed only once per share scope).
1238
+ * It accepts one argument, the name of the share scope.
1239
+ * If the share scope does not exist, it creates one.
1240
+ */ // eslint-disable-next-line @typescript-eslint/member-ordering
1241
+ initializeSharing(shareScopeName = share.DEFAULT_SCOPE, strategy) {
1242
+ const { host } = this;
1243
+ const shareScope = this.shareScopeMap;
1244
+ const hostName = host.options.name;
1245
+ // Creates a new share scope if necessary
1246
+ if (!shareScope[shareScopeName]) {
1247
+ shareScope[shareScopeName] = {};
1248
+ }
1249
+ // Executes all initialization snippets from all accessible modules
1250
+ const scope = shareScope[shareScopeName];
1251
+ const register = (name, shared)=>{
1252
+ var _activeVersion_shareConfig;
1253
+ const { version, eager } = shared;
1254
+ scope[name] = scope[name] || {};
1255
+ const versions = scope[name];
1256
+ const activeVersion = versions[version];
1257
+ const activeVersionEager = Boolean(activeVersion && (activeVersion.eager || ((_activeVersion_shareConfig = activeVersion.shareConfig) == null ? void 0 : _activeVersion_shareConfig.eager)));
1258
+ if (!activeVersion || activeVersion.strategy !== 'loaded-first' && !activeVersion.loaded && (Boolean(!eager) !== !activeVersionEager ? eager : hostName > activeVersion.from)) {
1259
+ versions[version] = shared;
1260
+ }
1261
+ };
1262
+ const promises = [];
1263
+ const initFn = (mod)=>mod && mod.init && mod.init(shareScope[shareScopeName]);
1264
+ const initRemoteModule = async (key)=>{
1265
+ const { module } = await host.remoteHandler.getRemoteModuleAndOptions({
1266
+ id: key
1267
+ });
1268
+ if (module.getEntry) {
1269
+ const entry = await module.getEntry();
1270
+ if (!module.inited) {
1271
+ initFn(entry);
1272
+ module.inited = true;
1273
+ }
1274
+ }
1275
+ };
1276
+ Object.keys(host.options.shared).forEach((shareName)=>{
1277
+ const sharedArr = host.options.shared[shareName];
1278
+ sharedArr.forEach((shared)=>{
1279
+ if (shared.scope.includes(shareScopeName)) {
1280
+ register(shareName, shared);
1281
+ }
1282
+ });
1283
+ });
1284
+ if (strategy === 'version-first') {
1285
+ host.options.remotes.forEach((remote)=>{
1286
+ if (remote.shareScope === shareScopeName) {
1287
+ promises.push(initRemoteModule(remote.name));
1288
+ }
1289
+ });
1290
+ }
1291
+ return promises;
1292
+ }
1223
1293
  // The lib function will only be available if the shared set by eager or runtime init is set or the shared is successfully loaded.
1224
1294
  // 1. If the loaded shared already exists globally, then it will be reused
1225
1295
  // 2. If lib exists in local shared, it will be used directly
1226
1296
  // 3. If the local get returns something other than Promise, then it will be used directly
1227
1297
  loadShareSync(pkgName, extraOptions) {
1298
+ const { host } = this;
1228
1299
  const shareInfo = share.getTargetSharedOptions({
1229
1300
  pkgName,
1230
1301
  extraOptions,
1231
- shareInfos: this.options.shared
1302
+ shareInfos: host.options.shared
1232
1303
  });
1233
1304
  if (shareInfo == null ? void 0 : shareInfo.scope) {
1234
1305
  shareInfo.scope.forEach((shareScope)=>{
@@ -1240,14 +1311,14 @@ class FederationHost {
1240
1311
  if (!shared.useIn) {
1241
1312
  shared.useIn = [];
1242
1313
  }
1243
- share.addUniqueItem(shared.useIn, this.options.name);
1314
+ share.addUniqueItem(shared.useIn, host.options.name);
1244
1315
  };
1245
1316
  if (registeredShared) {
1246
1317
  if (typeof registeredShared.lib === 'function') {
1247
1318
  addUseIn(registeredShared);
1248
1319
  if (!registeredShared.loaded) {
1249
1320
  registeredShared.loaded = true;
1250
- if (registeredShared.from === this.options.name) {
1321
+ if (registeredShared.from === host.options.name) {
1251
1322
  shareInfo.loaded = true;
1252
1323
  }
1253
1324
  }
@@ -1260,7 +1331,7 @@ class FederationHost {
1260
1331
  this.setShared({
1261
1332
  pkgName,
1262
1333
  loaded: true,
1263
- from: this.options.name,
1334
+ from: host.options.name,
1264
1335
  lib: module,
1265
1336
  shared: registeredShared
1266
1337
  });
@@ -1278,7 +1349,7 @@ class FederationHost {
1278
1349
  const module = shareInfo.get();
1279
1350
  if (module instanceof Promise) {
1280
1351
  throw new Error(`
1281
- The loadShareSync function was unable to load ${pkgName}. The ${pkgName} could not be found in ${this.options.name}.
1352
+ The loadShareSync function was unable to load ${pkgName}. The ${pkgName} could not be found in ${host.options.name}.
1282
1353
  Possible reasons for failure: \n
1283
1354
  1. The ${pkgName} share was registered with the 'get' attribute, but loadShare was not used beforehand.\n
1284
1355
  2. The ${pkgName} share was not registered with the 'lib' attribute.\n
@@ -1288,92 +1359,112 @@ class FederationHost {
1288
1359
  this.setShared({
1289
1360
  pkgName,
1290
1361
  loaded: true,
1291
- from: this.options.name,
1362
+ from: host.options.name,
1292
1363
  lib: shareInfo.lib,
1293
1364
  shared: shareInfo
1294
1365
  });
1295
1366
  return shareInfo.lib;
1296
1367
  }
1297
1368
  throw new Error(`
1298
- The loadShareSync function was unable to load ${pkgName}. The ${pkgName} could not be found in ${this.options.name}.
1369
+ The loadShareSync function was unable to load ${pkgName}. The ${pkgName} could not be found in ${host.options.name}.
1299
1370
  Possible reasons for failure: \n
1300
1371
  1. The ${pkgName} share was registered with the 'get' attribute, but loadShare was not used beforehand.\n
1301
1372
  2. The ${pkgName} share was not registered with the 'lib' attribute.\n
1302
1373
  `);
1303
1374
  }
1304
- initRawContainer(name, url, container) {
1305
- const remoteInfo = getRemoteInfo({
1306
- name,
1307
- entry: url
1308
- });
1309
- const module = new Module({
1310
- host: this,
1311
- remoteInfo
1375
+ initShareScopeMap(scopeName, shareScope) {
1376
+ const { host } = this;
1377
+ this.shareScopeMap[scopeName] = shareScope;
1378
+ this.hooks.lifecycle.initContainerShareScopeMap.emit({
1379
+ shareScope,
1380
+ options: host.options,
1381
+ origin: host
1312
1382
  });
1313
- module.remoteEntryExports = container;
1314
- this.moduleCache.set(name, module);
1315
- return module;
1316
1383
  }
1317
- async _getRemoteModuleAndOptions(id) {
1318
- let loadRemoteArgs;
1319
- try {
1320
- loadRemoteArgs = await this.hooks.lifecycle.beforeRequest.emit({
1321
- id,
1322
- options: this.options,
1323
- origin: this
1324
- });
1325
- } catch (error) {
1326
- loadRemoteArgs = await this.hooks.lifecycle.errorLoadRemote.emit({
1327
- id,
1328
- options: this.options,
1329
- origin: this,
1330
- from: 'runtime',
1331
- error,
1332
- lifecycle: 'beforeRequest'
1384
+ setShared({ pkgName, shared, from, lib, loading, loaded, get }) {
1385
+ const { version, scope = 'default' } = shared, shareInfo = _object_without_properties_loose(shared, [
1386
+ "version",
1387
+ "scope"
1388
+ ]);
1389
+ const scopes = Array.isArray(scope) ? scope : [
1390
+ scope
1391
+ ];
1392
+ scopes.forEach((sc)=>{
1393
+ if (!this.shareScopeMap[sc]) {
1394
+ this.shareScopeMap[sc] = {};
1395
+ }
1396
+ if (!this.shareScopeMap[sc][pkgName]) {
1397
+ this.shareScopeMap[sc][pkgName] = {};
1398
+ }
1399
+ if (this.shareScopeMap[sc][pkgName][version]) {
1400
+ return;
1401
+ }
1402
+ this.shareScopeMap[sc][pkgName][version] = _extends$2({
1403
+ version,
1404
+ scope: [
1405
+ 'default'
1406
+ ]
1407
+ }, shareInfo, {
1408
+ lib,
1409
+ loaded,
1410
+ loading
1333
1411
  });
1334
- if (!loadRemoteArgs) {
1335
- throw error;
1412
+ if (get) {
1413
+ this.shareScopeMap[sc][pkgName][version].get = get;
1336
1414
  }
1415
+ });
1416
+ }
1417
+ _setGlobalShareScopeMap(hostOptions) {
1418
+ const globalShareScopeMap = share.getGlobalShareScope();
1419
+ const identifier = hostOptions.id || hostOptions.name;
1420
+ if (identifier && !globalShareScopeMap[identifier]) {
1421
+ globalShareScopeMap[identifier] = this.shareScopeMap;
1337
1422
  }
1338
- const { id: idRes } = loadRemoteArgs;
1339
- const remoteSplitInfo = matchRemoteWithNameAndExpose(this.options.remotes, idRes);
1340
- share.assert(remoteSplitInfo, `
1341
- Unable to locate ${idRes} in ${this.options.name}. Potential reasons for failure include:\n
1342
- 1. ${idRes} was not included in the 'remotes' parameter of ${this.options.name || 'the host'}.\n
1343
- 2. ${idRes} could not be found in the 'remotes' of ${this.options.name} with either 'name' or 'alias' attributes.
1344
- 3. ${idRes} is not online, injected, or loaded.
1345
- 4. ${idRes} cannot be accessed on the expected.
1346
- 5. The 'beforeRequest' hook was provided but did not return the correct 'remoteInfo' when attempting to load ${idRes}.
1347
- `);
1348
- const { remote: rawRemote } = remoteSplitInfo;
1349
- const remoteInfo = getRemoteInfo(rawRemote);
1350
- const matchInfo = await this.hooks.lifecycle.afterResolve.emit(_extends({
1351
- id: idRes
1352
- }, remoteSplitInfo, {
1353
- options: this.options,
1354
- origin: this,
1355
- remoteInfo
1356
- }));
1357
- const { remote, expose } = matchInfo;
1358
- share.assert(remote && expose, `The 'beforeRequest' hook was executed, but it failed to return the correct 'remote' and 'expose' values while loading ${idRes}.`);
1359
- let module = this.moduleCache.get(remote.name);
1360
- const moduleOptions = {
1361
- host: this,
1362
- remoteInfo
1363
- };
1364
- if (!module) {
1365
- module = new Module(moduleOptions);
1366
- this.moduleCache.set(remote.name, module);
1423
+ }
1424
+ constructor(host){
1425
+ this.hooks = new PluginSystem({
1426
+ afterResolve: new AsyncWaterfallHook('afterResolve'),
1427
+ beforeLoadShare: new AsyncWaterfallHook('beforeLoadShare'),
1428
+ // not used yet
1429
+ loadShare: new AsyncHook(),
1430
+ resolveShare: new SyncWaterfallHook('resolveShare'),
1431
+ // maybe will change, temporarily for internal use only
1432
+ initContainerShareScopeMap: new AsyncWaterfallHook('initContainer')
1433
+ });
1434
+ this.host = host;
1435
+ this.shareScopeMap = {};
1436
+ this._setGlobalShareScopeMap(host.options);
1437
+ }
1438
+ }
1439
+
1440
+ function _extends$1() {
1441
+ _extends$1 = Object.assign || function(target) {
1442
+ for(var i = 1; i < arguments.length; i++){
1443
+ var source = arguments[i];
1444
+ for(var key in source){
1445
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1446
+ target[key] = source[key];
1447
+ }
1448
+ }
1367
1449
  }
1368
- return {
1369
- module,
1370
- moduleOptions,
1371
- remoteMatchInfo: matchInfo
1372
- };
1450
+ return target;
1451
+ };
1452
+ return _extends$1.apply(this, arguments);
1453
+ }
1454
+ class RemoteHandler {
1455
+ formatAndRegisterRemote(globalOptions, userOptions) {
1456
+ const userRemotes = userOptions.remotes || [];
1457
+ return userRemotes.reduce((res, remote)=>{
1458
+ this.registerRemote(remote, res, {
1459
+ force: false
1460
+ });
1461
+ return res;
1462
+ }, globalOptions.remotes);
1373
1463
  }
1374
1464
  // eslint-disable-next-line max-lines-per-function
1375
1465
  // eslint-disable-next-line @typescript-eslint/member-ordering
1376
1466
  async loadRemote(id, options) {
1467
+ const { host } = this;
1377
1468
  try {
1378
1469
  const { loadFactory = true } = options || {
1379
1470
  loadFactory: true
@@ -1385,7 +1476,9 @@ class FederationHost {
1385
1476
  // id: pkgName(@federation/app1) + expose(button) = @federation/app1/button
1386
1477
  // id: alias(app1) + expose(button) = app1/button
1387
1478
  // id: alias(app1/utils) + expose(loadash/sort) = app1/utils/loadash/sort
1388
- const { module, moduleOptions, remoteMatchInfo } = await this._getRemoteModuleAndOptions(id);
1479
+ const { module, moduleOptions, remoteMatchInfo } = await this.getRemoteModuleAndOptions({
1480
+ id
1481
+ });
1389
1482
  const { pkgNameOrAlias, remote, expose, id: idRes } = remoteMatchInfo;
1390
1483
  const moduleOrFactory = await module.get(expose, options);
1391
1484
  const moduleWrapper = await this.hooks.lifecycle.onLoad.emit({
@@ -1397,7 +1490,7 @@ class FederationHost {
1397
1490
  remote,
1398
1491
  options: moduleOptions,
1399
1492
  moduleInstance: module,
1400
- origin: this
1493
+ origin: host
1401
1494
  });
1402
1495
  if (typeof moduleWrapper === 'function') {
1403
1496
  return moduleWrapper;
@@ -1412,7 +1505,7 @@ class FederationHost {
1412
1505
  error,
1413
1506
  from,
1414
1507
  lifecycle: 'onLoad',
1415
- origin: this
1508
+ origin: host
1416
1509
  });
1417
1510
  if (!failOver) {
1418
1511
  throw error;
@@ -1422,18 +1515,19 @@ class FederationHost {
1422
1515
  }
1423
1516
  // eslint-disable-next-line @typescript-eslint/member-ordering
1424
1517
  async preloadRemote(preloadOptions) {
1518
+ const { host } = this;
1425
1519
  await this.hooks.lifecycle.beforePreloadRemote.emit({
1426
1520
  preloadOptions,
1427
- options: this.options,
1428
- origin: this
1521
+ options: host.options,
1522
+ origin: host
1429
1523
  });
1430
- const preloadOps = formatPreloadArgs(this.options.remotes, preloadOptions);
1524
+ const preloadOps = formatPreloadArgs(host.options.remotes, preloadOptions);
1431
1525
  await Promise.all(preloadOps.map(async (ops)=>{
1432
1526
  const { remote } = ops;
1433
1527
  const remoteInfo = getRemoteInfo(remote);
1434
- const { globalSnapshot, remoteSnapshot } = await this.snapshotHandler.loadRemoteSnapshotInfo(remote);
1528
+ const { globalSnapshot, remoteSnapshot } = await host.snapshotHandler.loadRemoteSnapshotInfo(remote);
1435
1529
  const assets = await this.hooks.lifecycle.generatePreloadAssets.emit({
1436
- origin: this,
1530
+ origin: host,
1437
1531
  preloadOptions: ops,
1438
1532
  remote,
1439
1533
  remoteInfo,
@@ -1443,117 +1537,279 @@ class FederationHost {
1443
1537
  if (!assets) {
1444
1538
  return;
1445
1539
  }
1446
- preloadAssets(remoteInfo, this, assets);
1540
+ preloadAssets(remoteInfo, host, assets);
1447
1541
  }));
1448
1542
  }
1449
- /**
1450
- * This function initializes the sharing sequence (executed only once per share scope).
1451
- * It accepts one argument, the name of the share scope.
1452
- * If the share scope does not exist, it creates one.
1453
- */ // eslint-disable-next-line @typescript-eslint/member-ordering
1454
- initializeSharing(shareScopeName = share.DEFAULT_SCOPE, strategy) {
1455
- const shareScope = this.shareScopeMap;
1456
- const hostName = this.options.name;
1457
- // Creates a new share scope if necessary
1458
- if (!shareScope[shareScopeName]) {
1459
- shareScope[shareScopeName] = {};
1460
- }
1461
- // Executes all initialization snippets from all accessible modules
1462
- const scope = shareScope[shareScopeName];
1463
- const register = (name, shared)=>{
1464
- var _activeVersion_shareConfig;
1465
- const { version, eager } = shared;
1466
- scope[name] = scope[name] || {};
1467
- const versions = scope[name];
1468
- const activeVersion = versions[version];
1469
- const activeVersionEager = Boolean(activeVersion && (activeVersion.eager || ((_activeVersion_shareConfig = activeVersion.shareConfig) == null ? void 0 : _activeVersion_shareConfig.eager)));
1470
- if (!activeVersion || activeVersion.strategy !== 'loaded-first' && !activeVersion.loaded && (Boolean(!eager) !== !activeVersionEager ? eager : hostName > activeVersion.from)) {
1471
- versions[version] = shared;
1472
- }
1473
- };
1474
- const promises = [];
1475
- const initFn = (mod)=>mod && mod.init && mod.init(shareScope[shareScopeName]);
1476
- const initRemoteModule = async (key)=>{
1477
- const { module } = await this._getRemoteModuleAndOptions(key);
1478
- if (module.getEntry) {
1479
- const entry = await module.getEntry();
1480
- if (!module.inited) {
1481
- initFn(entry);
1482
- module.inited = true;
1543
+ registerRemotes(remotes, options) {
1544
+ const { host } = this;
1545
+ remotes.forEach((remote)=>{
1546
+ this.registerRemote(remote, host.options.remotes, {
1547
+ force: options == null ? void 0 : options.force
1548
+ });
1549
+ });
1550
+ }
1551
+ async getRemoteModuleAndOptions(options) {
1552
+ const { host } = this;
1553
+ const { id } = options;
1554
+ let loadRemoteArgs;
1555
+ try {
1556
+ loadRemoteArgs = await this.hooks.lifecycle.beforeRequest.emit({
1557
+ id,
1558
+ options: host.options,
1559
+ origin: host
1560
+ });
1561
+ } catch (error) {
1562
+ loadRemoteArgs = await this.hooks.lifecycle.errorLoadRemote.emit({
1563
+ id,
1564
+ options: host.options,
1565
+ origin: host,
1566
+ from: 'runtime',
1567
+ error,
1568
+ lifecycle: 'beforeRequest'
1569
+ });
1570
+ if (!loadRemoteArgs) {
1571
+ throw error;
1572
+ }
1573
+ }
1574
+ const { id: idRes } = loadRemoteArgs;
1575
+ const remoteSplitInfo = matchRemoteWithNameAndExpose(host.options.remotes, idRes);
1576
+ share.assert(remoteSplitInfo, `
1577
+ Unable to locate ${idRes} in ${host.options.name}. Potential reasons for failure include:\n
1578
+ 1. ${idRes} was not included in the 'remotes' parameter of ${host.options.name || 'the host'}.\n
1579
+ 2. ${idRes} could not be found in the 'remotes' of ${host.options.name} with either 'name' or 'alias' attributes.
1580
+ 3. ${idRes} is not online, injected, or loaded.
1581
+ 4. ${idRes} cannot be accessed on the expected.
1582
+ 5. The 'beforeRequest' hook was provided but did not return the correct 'remoteInfo' when attempting to load ${idRes}.
1583
+ `);
1584
+ const { remote: rawRemote } = remoteSplitInfo;
1585
+ const remoteInfo = getRemoteInfo(rawRemote);
1586
+ const matchInfo = await host.sharedHandler.hooks.lifecycle.afterResolve.emit(_extends$1({
1587
+ id: idRes
1588
+ }, remoteSplitInfo, {
1589
+ options: host.options,
1590
+ origin: host,
1591
+ remoteInfo
1592
+ }));
1593
+ const { remote, expose } = matchInfo;
1594
+ share.assert(remote && expose, `The 'beforeRequest' hook was executed, but it failed to return the correct 'remote' and 'expose' values while loading ${idRes}.`);
1595
+ let module = host.moduleCache.get(remote.name);
1596
+ const moduleOptions = {
1597
+ host: host,
1598
+ remoteInfo
1599
+ };
1600
+ if (!module) {
1601
+ module = new Module(moduleOptions);
1602
+ host.moduleCache.set(remote.name, module);
1603
+ }
1604
+ return {
1605
+ module,
1606
+ moduleOptions,
1607
+ remoteMatchInfo: matchInfo
1608
+ };
1609
+ }
1610
+ registerRemote(remote, targetRemotes, options) {
1611
+ const normalizeRemote = ()=>{
1612
+ if (remote.alias) {
1613
+ // Validate if alias equals the prefix of remote.name and remote.alias, if so, throw an error
1614
+ // As multi-level path references cannot guarantee unique names, alias being a prefix of remote.name is not supported
1615
+ const findEqual = targetRemotes.find((item)=>{
1616
+ var _item_alias;
1617
+ return remote.alias && (item.name.startsWith(remote.alias) || ((_item_alias = item.alias) == null ? void 0 : _item_alias.startsWith(remote.alias)));
1618
+ });
1619
+ share.assert(!findEqual, `The alias ${remote.alias} of remote ${remote.name} is not allowed to be the prefix of ${findEqual && findEqual.name} name or alias`);
1620
+ }
1621
+ // Set the remote entry to a complete path
1622
+ if ('entry' in remote) {
1623
+ if (sdk.isBrowserEnv() && !remote.entry.startsWith('http')) {
1624
+ remote.entry = new URL(remote.entry, window.location.origin).href;
1483
1625
  }
1484
1626
  }
1627
+ if (!remote.shareScope) {
1628
+ remote.shareScope = share.DEFAULT_SCOPE;
1629
+ }
1630
+ if (!remote.type) {
1631
+ remote.type = share.DEFAULT_REMOTE_TYPE;
1632
+ }
1485
1633
  };
1486
- Object.keys(this.options.shared).forEach((shareName)=>{
1487
- const sharedArr = this.options.shared[shareName];
1488
- sharedArr.forEach((shared)=>{
1489
- if (shared.scope.includes(shareScopeName)) {
1490
- register(shareName, shared);
1634
+ const registeredRemote = targetRemotes.find((item)=>item.name === remote.name);
1635
+ if (!registeredRemote) {
1636
+ normalizeRemote();
1637
+ targetRemotes.push(remote);
1638
+ } else {
1639
+ const messages = [
1640
+ `The remote "${remote.name}" is already registered.`,
1641
+ (options == null ? void 0 : options.force) ? 'Hope you have known that OVERRIDE it may have some unexpected errors' : 'If you want to merge the remote, you can set "force: true".'
1642
+ ];
1643
+ if (options == null ? void 0 : options.force) {
1644
+ // remove registered remote
1645
+ this.removeRemote(registeredRemote);
1646
+ normalizeRemote();
1647
+ targetRemotes.push(remote);
1648
+ }
1649
+ sdk.warn(messages.join(' '));
1650
+ }
1651
+ }
1652
+ removeRemote(remote) {
1653
+ const { host } = this;
1654
+ const { name } = remote;
1655
+ const remoteIndex = host.options.remotes.findIndex((item)=>item.name === name);
1656
+ if (remoteIndex !== -1) {
1657
+ host.options.remotes.splice(remoteIndex, 1);
1658
+ }
1659
+ const loadedModule = host.moduleCache.get(remote.name);
1660
+ if (loadedModule) {
1661
+ const remoteInfo = loadedModule.remoteInfo;
1662
+ const key = remoteInfo.entryGlobalName;
1663
+ if (globalThis[key]) {
1664
+ delete globalThis[key];
1665
+ }
1666
+ const remoteEntryUniqueKey = getRemoteEntryUniqueKey(loadedModule.remoteInfo);
1667
+ if (share.globalLoading[remoteEntryUniqueKey]) {
1668
+ delete share.globalLoading[remoteEntryUniqueKey];
1669
+ }
1670
+ // delete un loaded shared and instance
1671
+ let remoteInsId = remoteInfo.buildVersion ? sdk.composeKeyWithSeparator(remoteInfo.name, remoteInfo.buildVersion) : remoteInfo.name;
1672
+ const remoteInsIndex = globalThis.__FEDERATION__.__INSTANCES__.findIndex((ins)=>{
1673
+ if (remoteInfo.buildVersion) {
1674
+ return ins.options.id === remoteInsId;
1675
+ } else {
1676
+ return ins.name === remoteInsId;
1491
1677
  }
1492
1678
  });
1493
- });
1494
- if (strategy === 'version-first') {
1495
- this.options.remotes.forEach((remote)=>{
1496
- if (remote.shareScope === shareScopeName) {
1497
- promises.push(initRemoteModule(remote.name));
1679
+ if (remoteInsIndex !== -1) {
1680
+ const remoteIns = globalThis.__FEDERATION__.__INSTANCES__[remoteInsIndex];
1681
+ remoteInsId = remoteIns.options.id || remoteInsId;
1682
+ const globalShareScopeMap = share.getGlobalShareScope();
1683
+ let isAllSharedNotUsed = true;
1684
+ const needDeleteKeys = [];
1685
+ Object.keys(globalShareScopeMap).forEach((instId)=>{
1686
+ Object.keys(globalShareScopeMap[instId]).forEach((shareScope)=>{
1687
+ Object.keys(globalShareScopeMap[instId][shareScope]).forEach((shareName)=>{
1688
+ Object.keys(globalShareScopeMap[instId][shareScope][shareName]).forEach((shareVersion)=>{
1689
+ const shared = globalShareScopeMap[instId][shareScope][shareName][shareVersion];
1690
+ if (shared.from === remoteInfo.name) {
1691
+ if (shared.loaded || shared.loading) {
1692
+ shared.useIn = shared.useIn.filter((usedHostName)=>usedHostName !== remoteInfo.name);
1693
+ if (shared.useIn.length) {
1694
+ isAllSharedNotUsed = false;
1695
+ } else {
1696
+ needDeleteKeys.push([
1697
+ instId,
1698
+ shareScope,
1699
+ shareName,
1700
+ shareVersion
1701
+ ]);
1702
+ }
1703
+ } else {
1704
+ needDeleteKeys.push([
1705
+ instId,
1706
+ shareScope,
1707
+ shareName,
1708
+ shareVersion
1709
+ ]);
1710
+ }
1711
+ }
1712
+ });
1713
+ });
1714
+ });
1715
+ });
1716
+ if (isAllSharedNotUsed) {
1717
+ remoteIns.shareScopeMap = {};
1718
+ delete globalShareScopeMap[remoteInsId];
1498
1719
  }
1499
- });
1720
+ needDeleteKeys.forEach(([insId, shareScope, shareName, shareVersion])=>{
1721
+ var _globalShareScopeMap_insId_shareScope_shareName, _globalShareScopeMap_insId_shareScope, _globalShareScopeMap_insId;
1722
+ (_globalShareScopeMap_insId = globalShareScopeMap[insId]) == null ? true : (_globalShareScopeMap_insId_shareScope = _globalShareScopeMap_insId[shareScope]) == null ? true : (_globalShareScopeMap_insId_shareScope_shareName = _globalShareScopeMap_insId_shareScope[shareName]) == null ? true : delete _globalShareScopeMap_insId_shareScope_shareName[shareVersion];
1723
+ });
1724
+ globalThis.__FEDERATION__.__INSTANCES__.splice(remoteInsIndex, 1);
1725
+ }
1726
+ host.moduleCache.delete(remote.name);
1500
1727
  }
1501
- return promises;
1502
1728
  }
1503
- initShareScopeMap(scopeName, shareScope) {
1504
- this.shareScopeMap[scopeName] = shareScope;
1505
- this.hooks.lifecycle.initContainerShareScopeMap.emit({
1506
- shareScope,
1507
- options: this.options,
1508
- origin: this
1729
+ constructor(host){
1730
+ this.hooks = new PluginSystem({
1731
+ beforeRequest: new AsyncWaterfallHook('beforeRequest'),
1732
+ onLoad: new AsyncHook('onLoad'),
1733
+ handlePreloadModule: new SyncHook('handlePreloadModule'),
1734
+ errorLoadRemote: new AsyncHook('errorLoadRemote'),
1735
+ beforePreloadRemote: new AsyncHook(),
1736
+ generatePreloadAssets: new AsyncHook('generatePreloadAssets'),
1737
+ // not used yet
1738
+ afterPreloadRemote: new AsyncHook()
1509
1739
  });
1740
+ this.host = host;
1510
1741
  }
1511
- formatOptions(globalOptions, userOptions) {
1512
- const formatShareOptions = share.formatShareConfigs(userOptions.shared || {}, userOptions.name);
1513
- const shared = _extends({}, globalOptions.shared);
1514
- Object.keys(formatShareOptions).forEach((shareKey)=>{
1515
- if (!shared[shareKey]) {
1516
- shared[shareKey] = formatShareOptions[shareKey];
1517
- } else {
1518
- formatShareOptions[shareKey].forEach((newUserSharedOptions)=>{
1519
- const isSameVersion = shared[shareKey].find((sharedVal)=>sharedVal.version === newUserSharedOptions.version);
1520
- if (!isSameVersion) {
1521
- shared[shareKey].push(newUserSharedOptions);
1522
- }
1523
- });
1742
+ }
1743
+
1744
+ function _extends() {
1745
+ _extends = Object.assign || function(target) {
1746
+ for(var i = 1; i < arguments.length; i++){
1747
+ var source = arguments[i];
1748
+ for(var key in source){
1749
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1750
+ target[key] = source[key];
1751
+ }
1524
1752
  }
1753
+ }
1754
+ return target;
1755
+ };
1756
+ return _extends.apply(this, arguments);
1757
+ }
1758
+ class FederationHost {
1759
+ initOptions(userOptions) {
1760
+ this.registerPlugins(userOptions.plugins);
1761
+ const options = this.formatOptions(this.options, userOptions);
1762
+ this.options = options;
1763
+ return options;
1764
+ }
1765
+ async loadShare(pkgName, extraOptions) {
1766
+ return this.sharedHandler.loadShare(pkgName, extraOptions);
1767
+ }
1768
+ // The lib function will only be available if the shared set by eager or runtime init is set or the shared is successfully loaded.
1769
+ // 1. If the loaded shared already exists globally, then it will be reused
1770
+ // 2. If lib exists in local shared, it will be used directly
1771
+ // 3. If the local get returns something other than Promise, then it will be used directly
1772
+ loadShareSync(pkgName, extraOptions) {
1773
+ return this.sharedHandler.loadShareSync(pkgName, extraOptions);
1774
+ }
1775
+ initializeSharing(shareScopeName = share.DEFAULT_SCOPE, strategy) {
1776
+ return this.sharedHandler.initializeSharing(shareScopeName, strategy);
1777
+ }
1778
+ initRawContainer(name, url, container) {
1779
+ const remoteInfo = getRemoteInfo({
1780
+ name,
1781
+ entry: url
1782
+ });
1783
+ const module = new Module({
1784
+ host: this,
1785
+ remoteInfo
1525
1786
  });
1787
+ module.remoteEntryExports = container;
1788
+ this.moduleCache.set(name, module);
1789
+ return module;
1790
+ }
1791
+ // eslint-disable-next-line max-lines-per-function
1792
+ // eslint-disable-next-line @typescript-eslint/member-ordering
1793
+ async loadRemote(id, options) {
1794
+ return this.remoteHandler.loadRemote(id, options);
1795
+ }
1796
+ // eslint-disable-next-line @typescript-eslint/member-ordering
1797
+ async preloadRemote(preloadOptions) {
1798
+ return this.remoteHandler.preloadRemote(preloadOptions);
1799
+ }
1800
+ initShareScopeMap(scopeName, shareScope) {
1801
+ this.sharedHandler.initShareScopeMap(scopeName, shareScope);
1802
+ }
1803
+ formatOptions(globalOptions, userOptions) {
1804
+ const { shared } = share.formatShareConfigs(globalOptions, userOptions);
1526
1805
  const { userOptions: userOptionsRes, options: globalOptionsRes } = this.hooks.lifecycle.beforeInit.emit({
1527
1806
  origin: this,
1528
1807
  userOptions,
1529
1808
  options: globalOptions,
1530
1809
  shareInfo: shared
1531
1810
  });
1532
- const userRemotes = userOptionsRes.remotes || [];
1533
- const remotes = userRemotes.reduce((res, remote)=>{
1534
- this.registerRemote(remote, res, {
1535
- force: false
1536
- });
1537
- return res;
1538
- }, globalOptionsRes.remotes);
1539
- // register shared in shareScopeMap
1540
- const sharedKeys = Object.keys(formatShareOptions);
1541
- sharedKeys.forEach((sharedKey)=>{
1542
- const sharedVals = formatShareOptions[sharedKey];
1543
- sharedVals.forEach((sharedVal)=>{
1544
- const registeredShared = share.getRegisteredShare(this.shareScopeMap, sharedKey, sharedVal, this.hooks.lifecycle.resolveShare);
1545
- if (!registeredShared && sharedVal && sharedVal.lib) {
1546
- this.setShared({
1547
- pkgName: sharedKey,
1548
- lib: sharedVal.lib,
1549
- get: sharedVal.get,
1550
- loaded: true,
1551
- shared: sharedVal,
1552
- from: userOptions.name
1553
- });
1554
- }
1555
- });
1556
- });
1811
+ const remotes = this.remoteHandler.formatAndRegisterRemote(globalOptionsRes, userOptionsRes);
1812
+ const { shared: handledShared } = this.sharedHandler.registerShared(globalOptionsRes, userOptionsRes);
1557
1813
  const plugins = [
1558
1814
  ...globalOptionsRes.plugins
1559
1815
  ];
@@ -1567,7 +1823,7 @@ class FederationHost {
1567
1823
  const optionsRes = _extends({}, globalOptions, userOptions, {
1568
1824
  plugins,
1569
1825
  remotes,
1570
- shared
1826
+ shared: handledShared
1571
1827
  });
1572
1828
  this.hooks.lifecycle.init.emit({
1573
1829
  origin: this,
@@ -1578,6 +1834,8 @@ class FederationHost {
1578
1834
  registerPlugins(plugins) {
1579
1835
  const pluginRes = registerPlugins$1(plugins, [
1580
1836
  this.hooks,
1837
+ this.remoteHandler.hooks,
1838
+ this.sharedHandler.hooks,
1581
1839
  this.snapshotHandler.hooks,
1582
1840
  this.loaderHook
1583
1841
  ]);
@@ -1590,132 +1848,19 @@ class FederationHost {
1590
1848
  return res;
1591
1849
  }, pluginRes || []);
1592
1850
  }
1593
- setShared({ pkgName, shared, from, lib, loading, loaded, get }) {
1594
- const { version, scope = 'default' } = shared, shareInfo = _object_without_properties_loose(shared, [
1595
- "version",
1596
- "scope"
1597
- ]);
1598
- const scopes = Array.isArray(scope) ? scope : [
1599
- scope
1600
- ];
1601
- scopes.forEach((sc)=>{
1602
- if (!this.shareScopeMap[sc]) {
1603
- this.shareScopeMap[sc] = {};
1604
- }
1605
- if (!this.shareScopeMap[sc][pkgName]) {
1606
- this.shareScopeMap[sc][pkgName] = {};
1607
- }
1608
- if (this.shareScopeMap[sc][pkgName][version]) {
1609
- return;
1610
- }
1611
- this.shareScopeMap[sc][pkgName][version] = _extends({
1612
- version,
1613
- scope: [
1614
- 'default'
1615
- ]
1616
- }, shareInfo, {
1617
- lib,
1618
- loaded,
1619
- loading
1620
- });
1621
- if (get) {
1622
- this.shareScopeMap[sc][pkgName][version].get = get;
1623
- }
1624
- });
1625
- }
1626
- removeRemote(remote) {
1627
- const { name } = remote;
1628
- const remoteIndex = this.options.remotes.findIndex((item)=>item.name === name);
1629
- if (remoteIndex !== -1) {
1630
- this.options.remotes.splice(remoteIndex, 1);
1631
- }
1632
- const loadedModule = this.moduleCache.get(remote.name);
1633
- if (loadedModule) {
1634
- const key = loadedModule.remoteInfo.entryGlobalName;
1635
- if (globalThis[key]) {
1636
- delete globalThis[key];
1637
- }
1638
- const remoteEntryUniqueKey = getRemoteEntryUniqueKey(loadedModule.remoteInfo);
1639
- if (share.globalLoading[remoteEntryUniqueKey]) {
1640
- delete share.globalLoading[remoteEntryUniqueKey];
1641
- }
1642
- this.moduleCache.delete(remote.name);
1643
- }
1644
- }
1645
- registerRemote(remote, targetRemotes, options) {
1646
- const normalizeRemote = ()=>{
1647
- if (remote.alias) {
1648
- // Validate if alias equals the prefix of remote.name and remote.alias, if so, throw an error
1649
- // As multi-level path references cannot guarantee unique names, alias being a prefix of remote.name is not supported
1650
- const findEqual = targetRemotes.find((item)=>{
1651
- var _item_alias;
1652
- return remote.alias && (item.name.startsWith(remote.alias) || ((_item_alias = item.alias) == null ? void 0 : _item_alias.startsWith(remote.alias)));
1653
- });
1654
- share.assert(!findEqual, `The alias ${remote.alias} of remote ${remote.name} is not allowed to be the prefix of ${findEqual && findEqual.name} name or alias`);
1655
- }
1656
- // Set the remote entry to a complete path
1657
- if ('entry' in remote) {
1658
- if (share.isBrowserEnv() && !remote.entry.startsWith('http')) {
1659
- remote.entry = new URL(remote.entry, window.location.origin).href;
1660
- }
1661
- }
1662
- if (!remote.shareScope) {
1663
- remote.shareScope = share.DEFAULT_SCOPE;
1664
- }
1665
- if (!remote.type) {
1666
- remote.type = share.DEFAULT_REMOTE_TYPE;
1667
- }
1668
- };
1669
- const registeredRemote = targetRemotes.find((item)=>item.name === remote.name);
1670
- if (!registeredRemote) {
1671
- normalizeRemote();
1672
- targetRemotes.push(remote);
1673
- } else {
1674
- const messages = [
1675
- `The remote "${remote.name}" is already registered.`,
1676
- (options == null ? void 0 : options.force) ? 'Hope you have known that OVERRIDE it may have some unexpected errors' : 'If you want to merge the remote, you can set "force: true".'
1677
- ];
1678
- if (options == null ? void 0 : options.force) {
1679
- // remove registered remote
1680
- this.removeRemote(registeredRemote);
1681
- normalizeRemote();
1682
- targetRemotes.push(remote);
1683
- }
1684
- share.warn(messages.join(' '));
1685
- }
1686
- }
1687
1851
  registerRemotes(remotes, options) {
1688
- remotes.forEach((remote)=>{
1689
- this.registerRemote(remote, this.options.remotes, {
1690
- force: options == null ? void 0 : options.force
1691
- });
1692
- });
1852
+ return this.remoteHandler.registerRemotes(remotes, options);
1693
1853
  }
1694
1854
  constructor(userOptions){
1695
1855
  this.hooks = new PluginSystem({
1696
1856
  beforeInit: new SyncWaterfallHook('beforeInit'),
1697
1857
  init: new SyncHook(),
1698
- beforeRequest: new AsyncWaterfallHook('beforeRequest'),
1699
- afterResolve: new AsyncWaterfallHook('afterResolve'),
1700
1858
  // maybe will change, temporarily for internal use only
1701
1859
  beforeInitContainer: new AsyncWaterfallHook('beforeInitContainer'),
1702
1860
  // maybe will change, temporarily for internal use only
1703
- initContainerShareScopeMap: new AsyncWaterfallHook('initContainer'),
1704
- // maybe will change, temporarily for internal use only
1705
- initContainer: new AsyncWaterfallHook('initContainer'),
1706
- onLoad: new AsyncHook('onLoad'),
1707
- handlePreloadModule: new SyncHook('handlePreloadModule'),
1708
- errorLoadRemote: new AsyncHook('errorLoadRemote'),
1709
- beforeLoadShare: new AsyncWaterfallHook('beforeLoadShare'),
1710
- // not used yet
1711
- loadShare: new AsyncHook(),
1712
- resolveShare: new SyncWaterfallHook('resolveShare'),
1713
- beforePreloadRemote: new AsyncHook(),
1714
- generatePreloadAssets: new AsyncHook('generatePreloadAssets'),
1715
- // not used yet
1716
- afterPreloadRemote: new AsyncHook()
1861
+ initContainer: new AsyncWaterfallHook('initContainer')
1717
1862
  });
1718
- this.version = "0.1.12";
1863
+ this.version = "0.1.13";
1719
1864
  this.moduleCache = new Map();
1720
1865
  this.loaderHook = new PluginSystem({
1721
1866
  // FIXME: may not be suitable , not open to the public yet
@@ -1740,9 +1885,10 @@ class FederationHost {
1740
1885
  };
1741
1886
  this.name = userOptions.name;
1742
1887
  this.options = defaultOptions;
1743
- this.shareScopeMap = {};
1744
- this._setGlobalShareScopeMap();
1745
1888
  this.snapshotHandler = new SnapshotHandler(this);
1889
+ this.sharedHandler = new SharedHandler(this);
1890
+ this.remoteHandler = new RemoteHandler(this);
1891
+ this.shareScopeMap = this.sharedHandler.shareScopeMap;
1746
1892
  this.registerPlugins([
1747
1893
  ...defaultOptions.plugins,
1748
1894
  ...userOptions.plugins || []