@module-federation/runtime 0.1.12 → 0.1.14

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() {
@@ -224,6 +224,7 @@ let Module = class Module {
224
224
  const res = this.host.loaderHook.lifecycle.createScript.emit({
225
225
  url
226
226
  });
227
+ if (!res) return;
227
228
  if (typeof document === 'undefined') {
228
229
  //todo: needs real fix
229
230
  return res;
@@ -231,6 +232,9 @@ let Module = class Module {
231
232
  if (res instanceof HTMLScriptElement) {
232
233
  return res;
233
234
  }
235
+ if ('script' in res || 'timeout' in res) {
236
+ return res;
237
+ }
234
238
  return;
235
239
  }
236
240
  });
@@ -271,7 +275,7 @@ let Module = class Module {
271
275
  origin: this.host
272
276
  });
273
277
  await remoteEntryExports.init(initContainerOptions.shareScope, initContainerOptions.initScope, initContainerOptions.remoteEntryInitOptions);
274
- await this.host.hooks.lifecycle.initContainer.emit(_extends$4({}, initContainerOptions, {
278
+ await this.host.hooks.lifecycle.initContainer.emit(_extends$6({}, initContainerOptions, {
275
279
  remoteEntryExports
276
280
  }));
277
281
  }
@@ -481,8 +485,8 @@ class PluginSystem {
481
485
  }
482
486
  }
483
487
 
484
- function _extends$3() {
485
- _extends$3 = Object.assign || function(target) {
488
+ function _extends$5() {
489
+ _extends$5 = Object.assign || function(target) {
486
490
  for(var i = 1; i < arguments.length; i++){
487
491
  var source = arguments[i];
488
492
  for(var key in source){
@@ -493,10 +497,10 @@ function _extends$3() {
493
497
  }
494
498
  return target;
495
499
  };
496
- return _extends$3.apply(this, arguments);
500
+ return _extends$5.apply(this, arguments);
497
501
  }
498
502
  function defaultPreloadArgs(preloadConfig) {
499
- return _extends$3({
503
+ return _extends$5({
500
504
  resourceCategory: 'sync',
501
505
  share: true,
502
506
  depsRemote: true,
@@ -544,9 +548,17 @@ function preloadAssets(remoteInfo, host, assets) {
544
548
  const res = host.loaderHook.lifecycle.createScript.emit({
545
549
  url
546
550
  });
551
+ if (!res) return;
552
+ if (typeof document === 'undefined') {
553
+ //todo: needs real fix
554
+ return res;
555
+ }
547
556
  if (res instanceof HTMLScriptElement) {
548
557
  return res;
549
558
  }
559
+ if ('script' in res || 'timeout' in res) {
560
+ return res;
561
+ }
550
562
  return;
551
563
  }
552
564
  });
@@ -558,9 +570,17 @@ function preloadAssets(remoteInfo, host, assets) {
558
570
  const res = host.loaderHook.lifecycle.createScript.emit({
559
571
  url
560
572
  });
573
+ if (!res) return;
574
+ if (typeof document === 'undefined') {
575
+ //todo: needs real fix
576
+ return res;
577
+ }
561
578
  if (res instanceof HTMLScriptElement) {
562
579
  return res;
563
580
  }
581
+ if ('script' in res || 'timeout' in res) {
582
+ return res;
583
+ }
564
584
  return;
565
585
  }
566
586
  });
@@ -603,8 +623,8 @@ function preloadAssets(remoteInfo, host, assets) {
603
623
  }
604
624
  }
605
625
 
606
- function _extends$2() {
607
- _extends$2 = Object.assign || function(target) {
626
+ function _extends$4() {
627
+ _extends$4 = Object.assign || function(target) {
608
628
  for(var i = 1; i < arguments.length; i++){
609
629
  var source = arguments[i];
610
630
  for(var key in source){
@@ -615,7 +635,7 @@ function _extends$2() {
615
635
  }
616
636
  return target;
617
637
  };
618
- return _extends$2.apply(this, arguments);
638
+ return _extends$4.apply(this, arguments);
619
639
  }
620
640
  function assignRemoteInfo(remoteInfo, remoteSnapshot) {
621
641
  if (!('remoteEntry' in remoteSnapshot) || !remoteSnapshot.remoteEntry) {
@@ -650,7 +670,7 @@ function snapshotPlugin() {
650
670
  depsRemote: false
651
671
  }
652
672
  };
653
- const assets = await origin.hooks.lifecycle.generatePreloadAssets.emit({
673
+ const assets = await origin.remoteHandler.hooks.lifecycle.generatePreloadAssets.emit({
654
674
  origin,
655
675
  preloadOptions,
656
676
  remoteInfo,
@@ -661,7 +681,7 @@ function snapshotPlugin() {
661
681
  if (assets) {
662
682
  preloadAssets(remoteInfo, origin, assets);
663
683
  }
664
- return _extends$2({}, args, {
684
+ return _extends$4({}, args, {
665
685
  remoteSnapshot
666
686
  });
667
687
  }
@@ -787,7 +807,7 @@ function generatePreloadAssets(origin, preloadOptions, remote, globalSnapshot, r
787
807
  for(let index = 0; index < assetsLength; index++){
788
808
  const assetsInfo = moduleAssetsInfo[index];
789
809
  const exposeFullPath = `${remoteInfo.name}/${assetsInfo.moduleName}`;
790
- origin.hooks.lifecycle.handlePreloadModule.emit({
810
+ origin.remoteHandler.hooks.lifecycle.handlePreloadModule.emit({
791
811
  id: assetsInfo.moduleName === '.' ? remoteInfo.name : exposeFullPath,
792
812
  name: remoteInfo.name,
793
813
  remoteSnapshot: moduleInfoSnapshot,
@@ -815,7 +835,7 @@ function generatePreloadAssets(origin, preloadOptions, remote, globalSnapshot, r
815
835
  }, true, memo, remoteSnapshot);
816
836
  if (remoteSnapshot.shared) {
817
837
  const collectSharedAssets = (shareInfo, snapshotShared)=>{
818
- const registeredShared = share.getRegisteredShare(origin.shareScopeMap, snapshotShared.sharedName, shareInfo, origin.hooks.lifecycle.resolveShare);
838
+ const registeredShared = share.getRegisteredShare(origin.shareScopeMap, snapshotShared.sharedName, shareInfo, origin.sharedHandler.hooks.lifecycle.resolveShare);
819
839
  // 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
840
  if (registeredShared && typeof registeredShared.lib === 'function') {
821
841
  snapshotShared.assets.js.sync.forEach((asset)=>{
@@ -882,8 +902,8 @@ const generatePreloadAssetsPlugin = function() {
882
902
  };
883
903
  };
884
904
 
885
- function _extends$1() {
886
- _extends$1 = Object.assign || function(target) {
905
+ function _extends$3() {
906
+ _extends$3 = Object.assign || function(target) {
887
907
  for(var i = 1; i < arguments.length; i++){
888
908
  var source = arguments[i];
889
909
  for(var key in source){
@@ -894,7 +914,7 @@ function _extends$1() {
894
914
  }
895
915
  return target;
896
916
  };
897
- return _extends$1.apply(this, arguments);
917
+ return _extends$3.apply(this, arguments);
898
918
  }
899
919
  class SnapshotHandler {
900
920
  async loadSnapshot(moduleInfo) {
@@ -937,7 +957,7 @@ class SnapshotHandler {
937
957
  // 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
958
  if (hostSnapshot && 'remotesInfo' in hostSnapshot && !share.getInfoWithoutType(hostSnapshot.remotesInfo, moduleInfo.name).value) {
939
959
  if ('version' in moduleInfo || 'entry' in moduleInfo) {
940
- hostSnapshot.remotesInfo = _extends$1({}, hostSnapshot == null ? void 0 : hostSnapshot.remotesInfo, {
960
+ hostSnapshot.remotesInfo = _extends$3({}, hostSnapshot == null ? void 0 : hostSnapshot.remotesInfo, {
941
961
  [moduleInfo.name]: {
942
962
  matchedVersion: 'version' in moduleInfo ? moduleInfo.version : moduleInfo.entry
943
963
  }
@@ -957,7 +977,7 @@ class SnapshotHandler {
957
977
  if (sdk.isManifestProvider(globalRemoteSnapshot)) {
958
978
  const moduleSnapshot = await this.getManifestJson(globalRemoteSnapshot.remoteEntry, moduleInfo, {});
959
979
  // eslint-disable-next-line @typescript-eslint/no-shadow
960
- const globalSnapshotRes = share.setGlobalSnapshotInfoByModuleInfo(_extends$1({}, moduleInfo, {
980
+ const globalSnapshotRes = share.setGlobalSnapshotInfoByModuleInfo(_extends$3({}, moduleInfo, {
961
981
  // The global remote may be overridden
962
982
  // Therefore, set the snapshot key to the global address of the actual request
963
983
  entry: globalRemoteSnapshot.remoteEntry
@@ -1085,8 +1105,8 @@ class SnapshotHandler {
1085
1105
  }
1086
1106
  }
1087
1107
 
1088
- function _extends() {
1089
- _extends = Object.assign || function(target) {
1108
+ function _extends$2() {
1109
+ _extends$2 = Object.assign || function(target) {
1090
1110
  for(var i = 1; i < arguments.length; i++){
1091
1111
  var source = arguments[i];
1092
1112
  for(var key in source){
@@ -1097,7 +1117,7 @@ function _extends() {
1097
1117
  }
1098
1118
  return target;
1099
1119
  };
1100
- return _extends.apply(this, arguments);
1120
+ return _extends$2.apply(this, arguments);
1101
1121
  }
1102
1122
  function _object_without_properties_loose(source, excluded) {
1103
1123
  if (source == null) return {};
@@ -1111,21 +1131,34 @@ function _object_without_properties_loose(source, excluded) {
1111
1131
  }
1112
1132
  return target;
1113
1133
  }
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;
1134
+ class SharedHandler {
1135
+ // register shared in shareScopeMap
1136
+ registerShared(globalOptions, userOptions) {
1137
+ const { shareInfos, shared } = share.formatShareConfigs(globalOptions, userOptions);
1138
+ const sharedKeys = Object.keys(shareInfos);
1139
+ sharedKeys.forEach((sharedKey)=>{
1140
+ const sharedVals = shareInfos[sharedKey];
1141
+ sharedVals.forEach((sharedVal)=>{
1142
+ const registeredShared = share.getRegisteredShare(this.shareScopeMap, sharedKey, sharedVal, this.hooks.lifecycle.resolveShare);
1143
+ if (!registeredShared && sharedVal && sharedVal.lib) {
1144
+ this.setShared({
1145
+ pkgName: sharedKey,
1146
+ lib: sharedVal.lib,
1147
+ get: sharedVal.get,
1148
+ loaded: true,
1149
+ shared: sharedVal,
1150
+ from: userOptions.name
1151
+ });
1152
+ }
1153
+ });
1154
+ });
1155
+ return {
1156
+ shareInfos,
1157
+ shared
1158
+ };
1127
1159
  }
1128
1160
  async loadShare(pkgName, extraOptions) {
1161
+ const { host } = this;
1129
1162
  // This function performs the following steps:
1130
1163
  // 1. Checks if the currently loaded share already exists, if not, it throws an error
1131
1164
  // 2. Searches globally for a matching share, if found, it uses it directly
@@ -1133,7 +1166,7 @@ class FederationHost {
1133
1166
  const shareInfo = share.getTargetSharedOptions({
1134
1167
  pkgName,
1135
1168
  extraOptions,
1136
- shareInfos: this.options.shared
1169
+ shareInfos: host.options.shared
1137
1170
  });
1138
1171
  if (shareInfo == null ? void 0 : shareInfo.scope) {
1139
1172
  await Promise.all(shareInfo.scope.map(async (shareScope)=>{
@@ -1144,19 +1177,19 @@ class FederationHost {
1144
1177
  const loadShareRes = await this.hooks.lifecycle.beforeLoadShare.emit({
1145
1178
  pkgName,
1146
1179
  shareInfo,
1147
- shared: this.options.shared,
1148
- origin: this
1180
+ shared: host.options.shared,
1181
+ origin: host
1149
1182
  });
1150
1183
  const { shareInfo: shareInfoRes } = loadShareRes;
1151
1184
  // 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`);
1185
+ share.assert(shareInfoRes, `Cannot find ${pkgName} Share in the ${host.options.name}. Please ensure that the ${pkgName} Share parameters have been injected`);
1153
1186
  // Retrieve from cache
1154
1187
  const registeredShared = share.getRegisteredShare(this.shareScopeMap, pkgName, shareInfoRes, this.hooks.lifecycle.resolveShare);
1155
1188
  const addUseIn = (shared)=>{
1156
1189
  if (!shared.useIn) {
1157
1190
  shared.useIn = [];
1158
1191
  }
1159
- share.addUniqueItem(shared.useIn, this.options.name);
1192
+ share.addUniqueItem(shared.useIn, host.options.name);
1160
1193
  };
1161
1194
  if (registeredShared && registeredShared.lib) {
1162
1195
  addUseIn(registeredShared);
@@ -1187,7 +1220,7 @@ class FederationHost {
1187
1220
  pkgName,
1188
1221
  loaded: false,
1189
1222
  shared: registeredShared,
1190
- from: this.options.name,
1223
+ from: host.options.name,
1191
1224
  lib: null,
1192
1225
  loading
1193
1226
  });
@@ -1213,22 +1246,80 @@ class FederationHost {
1213
1246
  pkgName,
1214
1247
  loaded: false,
1215
1248
  shared: shareInfoRes,
1216
- from: this.options.name,
1249
+ from: host.options.name,
1217
1250
  lib: null,
1218
1251
  loading
1219
1252
  });
1220
1253
  return loading;
1221
1254
  }
1222
1255
  }
1256
+ /**
1257
+ * This function initializes the sharing sequence (executed only once per share scope).
1258
+ * It accepts one argument, the name of the share scope.
1259
+ * If the share scope does not exist, it creates one.
1260
+ */ // eslint-disable-next-line @typescript-eslint/member-ordering
1261
+ initializeSharing(shareScopeName = share.DEFAULT_SCOPE, strategy) {
1262
+ const { host } = this;
1263
+ const shareScope = this.shareScopeMap;
1264
+ const hostName = host.options.name;
1265
+ // Creates a new share scope if necessary
1266
+ if (!shareScope[shareScopeName]) {
1267
+ shareScope[shareScopeName] = {};
1268
+ }
1269
+ // Executes all initialization snippets from all accessible modules
1270
+ const scope = shareScope[shareScopeName];
1271
+ const register = (name, shared)=>{
1272
+ var _activeVersion_shareConfig;
1273
+ const { version, eager } = shared;
1274
+ scope[name] = scope[name] || {};
1275
+ const versions = scope[name];
1276
+ const activeVersion = versions[version];
1277
+ const activeVersionEager = Boolean(activeVersion && (activeVersion.eager || ((_activeVersion_shareConfig = activeVersion.shareConfig) == null ? void 0 : _activeVersion_shareConfig.eager)));
1278
+ if (!activeVersion || activeVersion.strategy !== 'loaded-first' && !activeVersion.loaded && (Boolean(!eager) !== !activeVersionEager ? eager : hostName > activeVersion.from)) {
1279
+ versions[version] = shared;
1280
+ }
1281
+ };
1282
+ const promises = [];
1283
+ const initFn = (mod)=>mod && mod.init && mod.init(shareScope[shareScopeName]);
1284
+ const initRemoteModule = async (key)=>{
1285
+ const { module } = await host.remoteHandler.getRemoteModuleAndOptions({
1286
+ id: key
1287
+ });
1288
+ if (module.getEntry) {
1289
+ const entry = await module.getEntry();
1290
+ if (!module.inited) {
1291
+ initFn(entry);
1292
+ module.inited = true;
1293
+ }
1294
+ }
1295
+ };
1296
+ Object.keys(host.options.shared).forEach((shareName)=>{
1297
+ const sharedArr = host.options.shared[shareName];
1298
+ sharedArr.forEach((shared)=>{
1299
+ if (shared.scope.includes(shareScopeName)) {
1300
+ register(shareName, shared);
1301
+ }
1302
+ });
1303
+ });
1304
+ if (strategy === 'version-first') {
1305
+ host.options.remotes.forEach((remote)=>{
1306
+ if (remote.shareScope === shareScopeName) {
1307
+ promises.push(initRemoteModule(remote.name));
1308
+ }
1309
+ });
1310
+ }
1311
+ return promises;
1312
+ }
1223
1313
  // 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
1314
  // 1. If the loaded shared already exists globally, then it will be reused
1225
1315
  // 2. If lib exists in local shared, it will be used directly
1226
1316
  // 3. If the local get returns something other than Promise, then it will be used directly
1227
1317
  loadShareSync(pkgName, extraOptions) {
1318
+ const { host } = this;
1228
1319
  const shareInfo = share.getTargetSharedOptions({
1229
1320
  pkgName,
1230
1321
  extraOptions,
1231
- shareInfos: this.options.shared
1322
+ shareInfos: host.options.shared
1232
1323
  });
1233
1324
  if (shareInfo == null ? void 0 : shareInfo.scope) {
1234
1325
  shareInfo.scope.forEach((shareScope)=>{
@@ -1240,14 +1331,14 @@ class FederationHost {
1240
1331
  if (!shared.useIn) {
1241
1332
  shared.useIn = [];
1242
1333
  }
1243
- share.addUniqueItem(shared.useIn, this.options.name);
1334
+ share.addUniqueItem(shared.useIn, host.options.name);
1244
1335
  };
1245
1336
  if (registeredShared) {
1246
1337
  if (typeof registeredShared.lib === 'function') {
1247
1338
  addUseIn(registeredShared);
1248
1339
  if (!registeredShared.loaded) {
1249
1340
  registeredShared.loaded = true;
1250
- if (registeredShared.from === this.options.name) {
1341
+ if (registeredShared.from === host.options.name) {
1251
1342
  shareInfo.loaded = true;
1252
1343
  }
1253
1344
  }
@@ -1260,7 +1351,7 @@ class FederationHost {
1260
1351
  this.setShared({
1261
1352
  pkgName,
1262
1353
  loaded: true,
1263
- from: this.options.name,
1354
+ from: host.options.name,
1264
1355
  lib: module,
1265
1356
  shared: registeredShared
1266
1357
  });
@@ -1278,7 +1369,7 @@ class FederationHost {
1278
1369
  const module = shareInfo.get();
1279
1370
  if (module instanceof Promise) {
1280
1371
  throw new Error(`
1281
- The loadShareSync function was unable to load ${pkgName}. The ${pkgName} could not be found in ${this.options.name}.
1372
+ The loadShareSync function was unable to load ${pkgName}. The ${pkgName} could not be found in ${host.options.name}.
1282
1373
  Possible reasons for failure: \n
1283
1374
  1. The ${pkgName} share was registered with the 'get' attribute, but loadShare was not used beforehand.\n
1284
1375
  2. The ${pkgName} share was not registered with the 'lib' attribute.\n
@@ -1288,92 +1379,112 @@ class FederationHost {
1288
1379
  this.setShared({
1289
1380
  pkgName,
1290
1381
  loaded: true,
1291
- from: this.options.name,
1382
+ from: host.options.name,
1292
1383
  lib: shareInfo.lib,
1293
1384
  shared: shareInfo
1294
1385
  });
1295
1386
  return shareInfo.lib;
1296
1387
  }
1297
1388
  throw new Error(`
1298
- The loadShareSync function was unable to load ${pkgName}. The ${pkgName} could not be found in ${this.options.name}.
1389
+ The loadShareSync function was unable to load ${pkgName}. The ${pkgName} could not be found in ${host.options.name}.
1299
1390
  Possible reasons for failure: \n
1300
1391
  1. The ${pkgName} share was registered with the 'get' attribute, but loadShare was not used beforehand.\n
1301
1392
  2. The ${pkgName} share was not registered with the 'lib' attribute.\n
1302
1393
  `);
1303
1394
  }
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
1395
+ initShareScopeMap(scopeName, shareScope) {
1396
+ const { host } = this;
1397
+ this.shareScopeMap[scopeName] = shareScope;
1398
+ this.hooks.lifecycle.initContainerShareScopeMap.emit({
1399
+ shareScope,
1400
+ options: host.options,
1401
+ origin: host
1312
1402
  });
1313
- module.remoteEntryExports = container;
1314
- this.moduleCache.set(name, module);
1315
- return module;
1316
1403
  }
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'
1404
+ setShared({ pkgName, shared, from, lib, loading, loaded, get }) {
1405
+ const { version, scope = 'default' } = shared, shareInfo = _object_without_properties_loose(shared, [
1406
+ "version",
1407
+ "scope"
1408
+ ]);
1409
+ const scopes = Array.isArray(scope) ? scope : [
1410
+ scope
1411
+ ];
1412
+ scopes.forEach((sc)=>{
1413
+ if (!this.shareScopeMap[sc]) {
1414
+ this.shareScopeMap[sc] = {};
1415
+ }
1416
+ if (!this.shareScopeMap[sc][pkgName]) {
1417
+ this.shareScopeMap[sc][pkgName] = {};
1418
+ }
1419
+ if (this.shareScopeMap[sc][pkgName][version]) {
1420
+ return;
1421
+ }
1422
+ this.shareScopeMap[sc][pkgName][version] = _extends$2({
1423
+ version,
1424
+ scope: [
1425
+ 'default'
1426
+ ]
1427
+ }, shareInfo, {
1428
+ lib,
1429
+ loaded,
1430
+ loading
1333
1431
  });
1334
- if (!loadRemoteArgs) {
1335
- throw error;
1432
+ if (get) {
1433
+ this.shareScopeMap[sc][pkgName][version].get = get;
1336
1434
  }
1435
+ });
1436
+ }
1437
+ _setGlobalShareScopeMap(hostOptions) {
1438
+ const globalShareScopeMap = share.getGlobalShareScope();
1439
+ const identifier = hostOptions.id || hostOptions.name;
1440
+ if (identifier && !globalShareScopeMap[identifier]) {
1441
+ globalShareScopeMap[identifier] = this.shareScopeMap;
1337
1442
  }
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);
1443
+ }
1444
+ constructor(host){
1445
+ this.hooks = new PluginSystem({
1446
+ afterResolve: new AsyncWaterfallHook('afterResolve'),
1447
+ beforeLoadShare: new AsyncWaterfallHook('beforeLoadShare'),
1448
+ // not used yet
1449
+ loadShare: new AsyncHook(),
1450
+ resolveShare: new SyncWaterfallHook('resolveShare'),
1451
+ // maybe will change, temporarily for internal use only
1452
+ initContainerShareScopeMap: new AsyncWaterfallHook('initContainer')
1453
+ });
1454
+ this.host = host;
1455
+ this.shareScopeMap = {};
1456
+ this._setGlobalShareScopeMap(host.options);
1457
+ }
1458
+ }
1459
+
1460
+ function _extends$1() {
1461
+ _extends$1 = Object.assign || function(target) {
1462
+ for(var i = 1; i < arguments.length; i++){
1463
+ var source = arguments[i];
1464
+ for(var key in source){
1465
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1466
+ target[key] = source[key];
1467
+ }
1468
+ }
1367
1469
  }
1368
- return {
1369
- module,
1370
- moduleOptions,
1371
- remoteMatchInfo: matchInfo
1372
- };
1470
+ return target;
1471
+ };
1472
+ return _extends$1.apply(this, arguments);
1473
+ }
1474
+ class RemoteHandler {
1475
+ formatAndRegisterRemote(globalOptions, userOptions) {
1476
+ const userRemotes = userOptions.remotes || [];
1477
+ return userRemotes.reduce((res, remote)=>{
1478
+ this.registerRemote(remote, res, {
1479
+ force: false
1480
+ });
1481
+ return res;
1482
+ }, globalOptions.remotes);
1373
1483
  }
1374
1484
  // eslint-disable-next-line max-lines-per-function
1375
1485
  // eslint-disable-next-line @typescript-eslint/member-ordering
1376
1486
  async loadRemote(id, options) {
1487
+ const { host } = this;
1377
1488
  try {
1378
1489
  const { loadFactory = true } = options || {
1379
1490
  loadFactory: true
@@ -1385,7 +1496,9 @@ class FederationHost {
1385
1496
  // id: pkgName(@federation/app1) + expose(button) = @federation/app1/button
1386
1497
  // id: alias(app1) + expose(button) = app1/button
1387
1498
  // id: alias(app1/utils) + expose(loadash/sort) = app1/utils/loadash/sort
1388
- const { module, moduleOptions, remoteMatchInfo } = await this._getRemoteModuleAndOptions(id);
1499
+ const { module, moduleOptions, remoteMatchInfo } = await this.getRemoteModuleAndOptions({
1500
+ id
1501
+ });
1389
1502
  const { pkgNameOrAlias, remote, expose, id: idRes } = remoteMatchInfo;
1390
1503
  const moduleOrFactory = await module.get(expose, options);
1391
1504
  const moduleWrapper = await this.hooks.lifecycle.onLoad.emit({
@@ -1397,7 +1510,7 @@ class FederationHost {
1397
1510
  remote,
1398
1511
  options: moduleOptions,
1399
1512
  moduleInstance: module,
1400
- origin: this
1513
+ origin: host
1401
1514
  });
1402
1515
  if (typeof moduleWrapper === 'function') {
1403
1516
  return moduleWrapper;
@@ -1412,7 +1525,7 @@ class FederationHost {
1412
1525
  error,
1413
1526
  from,
1414
1527
  lifecycle: 'onLoad',
1415
- origin: this
1528
+ origin: host
1416
1529
  });
1417
1530
  if (!failOver) {
1418
1531
  throw error;
@@ -1422,18 +1535,19 @@ class FederationHost {
1422
1535
  }
1423
1536
  // eslint-disable-next-line @typescript-eslint/member-ordering
1424
1537
  async preloadRemote(preloadOptions) {
1538
+ const { host } = this;
1425
1539
  await this.hooks.lifecycle.beforePreloadRemote.emit({
1426
1540
  preloadOptions,
1427
- options: this.options,
1428
- origin: this
1541
+ options: host.options,
1542
+ origin: host
1429
1543
  });
1430
- const preloadOps = formatPreloadArgs(this.options.remotes, preloadOptions);
1544
+ const preloadOps = formatPreloadArgs(host.options.remotes, preloadOptions);
1431
1545
  await Promise.all(preloadOps.map(async (ops)=>{
1432
1546
  const { remote } = ops;
1433
1547
  const remoteInfo = getRemoteInfo(remote);
1434
- const { globalSnapshot, remoteSnapshot } = await this.snapshotHandler.loadRemoteSnapshotInfo(remote);
1548
+ const { globalSnapshot, remoteSnapshot } = await host.snapshotHandler.loadRemoteSnapshotInfo(remote);
1435
1549
  const assets = await this.hooks.lifecycle.generatePreloadAssets.emit({
1436
- origin: this,
1550
+ origin: host,
1437
1551
  preloadOptions: ops,
1438
1552
  remote,
1439
1553
  remoteInfo,
@@ -1443,117 +1557,279 @@ class FederationHost {
1443
1557
  if (!assets) {
1444
1558
  return;
1445
1559
  }
1446
- preloadAssets(remoteInfo, this, assets);
1560
+ preloadAssets(remoteInfo, host, assets);
1447
1561
  }));
1448
1562
  }
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;
1563
+ registerRemotes(remotes, options) {
1564
+ const { host } = this;
1565
+ remotes.forEach((remote)=>{
1566
+ this.registerRemote(remote, host.options.remotes, {
1567
+ force: options == null ? void 0 : options.force
1568
+ });
1569
+ });
1570
+ }
1571
+ async getRemoteModuleAndOptions(options) {
1572
+ const { host } = this;
1573
+ const { id } = options;
1574
+ let loadRemoteArgs;
1575
+ try {
1576
+ loadRemoteArgs = await this.hooks.lifecycle.beforeRequest.emit({
1577
+ id,
1578
+ options: host.options,
1579
+ origin: host
1580
+ });
1581
+ } catch (error) {
1582
+ loadRemoteArgs = await this.hooks.lifecycle.errorLoadRemote.emit({
1583
+ id,
1584
+ options: host.options,
1585
+ origin: host,
1586
+ from: 'runtime',
1587
+ error,
1588
+ lifecycle: 'beforeRequest'
1589
+ });
1590
+ if (!loadRemoteArgs) {
1591
+ throw error;
1472
1592
  }
1593
+ }
1594
+ const { id: idRes } = loadRemoteArgs;
1595
+ const remoteSplitInfo = matchRemoteWithNameAndExpose(host.options.remotes, idRes);
1596
+ share.assert(remoteSplitInfo, `
1597
+ Unable to locate ${idRes} in ${host.options.name}. Potential reasons for failure include:\n
1598
+ 1. ${idRes} was not included in the 'remotes' parameter of ${host.options.name || 'the host'}.\n
1599
+ 2. ${idRes} could not be found in the 'remotes' of ${host.options.name} with either 'name' or 'alias' attributes.
1600
+ 3. ${idRes} is not online, injected, or loaded.
1601
+ 4. ${idRes} cannot be accessed on the expected.
1602
+ 5. The 'beforeRequest' hook was provided but did not return the correct 'remoteInfo' when attempting to load ${idRes}.
1603
+ `);
1604
+ const { remote: rawRemote } = remoteSplitInfo;
1605
+ const remoteInfo = getRemoteInfo(rawRemote);
1606
+ const matchInfo = await host.sharedHandler.hooks.lifecycle.afterResolve.emit(_extends$1({
1607
+ id: idRes
1608
+ }, remoteSplitInfo, {
1609
+ options: host.options,
1610
+ origin: host,
1611
+ remoteInfo
1612
+ }));
1613
+ const { remote, expose } = matchInfo;
1614
+ share.assert(remote && expose, `The 'beforeRequest' hook was executed, but it failed to return the correct 'remote' and 'expose' values while loading ${idRes}.`);
1615
+ let module = host.moduleCache.get(remote.name);
1616
+ const moduleOptions = {
1617
+ host: host,
1618
+ remoteInfo
1473
1619
  };
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;
1620
+ if (!module) {
1621
+ module = new Module(moduleOptions);
1622
+ host.moduleCache.set(remote.name, module);
1623
+ }
1624
+ return {
1625
+ module,
1626
+ moduleOptions,
1627
+ remoteMatchInfo: matchInfo
1628
+ };
1629
+ }
1630
+ registerRemote(remote, targetRemotes, options) {
1631
+ const normalizeRemote = ()=>{
1632
+ if (remote.alias) {
1633
+ // Validate if alias equals the prefix of remote.name and remote.alias, if so, throw an error
1634
+ // As multi-level path references cannot guarantee unique names, alias being a prefix of remote.name is not supported
1635
+ const findEqual = targetRemotes.find((item)=>{
1636
+ var _item_alias;
1637
+ return remote.alias && (item.name.startsWith(remote.alias) || ((_item_alias = item.alias) == null ? void 0 : _item_alias.startsWith(remote.alias)));
1638
+ });
1639
+ 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`);
1640
+ }
1641
+ // Set the remote entry to a complete path
1642
+ if ('entry' in remote) {
1643
+ if (sdk.isBrowserEnv() && !remote.entry.startsWith('http')) {
1644
+ remote.entry = new URL(remote.entry, window.location.origin).href;
1483
1645
  }
1484
1646
  }
1647
+ if (!remote.shareScope) {
1648
+ remote.shareScope = share.DEFAULT_SCOPE;
1649
+ }
1650
+ if (!remote.type) {
1651
+ remote.type = share.DEFAULT_REMOTE_TYPE;
1652
+ }
1485
1653
  };
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);
1654
+ const registeredRemote = targetRemotes.find((item)=>item.name === remote.name);
1655
+ if (!registeredRemote) {
1656
+ normalizeRemote();
1657
+ targetRemotes.push(remote);
1658
+ } else {
1659
+ const messages = [
1660
+ `The remote "${remote.name}" is already registered.`,
1661
+ (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".'
1662
+ ];
1663
+ if (options == null ? void 0 : options.force) {
1664
+ // remove registered remote
1665
+ this.removeRemote(registeredRemote);
1666
+ normalizeRemote();
1667
+ targetRemotes.push(remote);
1668
+ }
1669
+ sdk.warn(messages.join(' '));
1670
+ }
1671
+ }
1672
+ removeRemote(remote) {
1673
+ const { host } = this;
1674
+ const { name } = remote;
1675
+ const remoteIndex = host.options.remotes.findIndex((item)=>item.name === name);
1676
+ if (remoteIndex !== -1) {
1677
+ host.options.remotes.splice(remoteIndex, 1);
1678
+ }
1679
+ const loadedModule = host.moduleCache.get(remote.name);
1680
+ if (loadedModule) {
1681
+ const remoteInfo = loadedModule.remoteInfo;
1682
+ const key = remoteInfo.entryGlobalName;
1683
+ if (globalThis[key]) {
1684
+ delete globalThis[key];
1685
+ }
1686
+ const remoteEntryUniqueKey = getRemoteEntryUniqueKey(loadedModule.remoteInfo);
1687
+ if (share.globalLoading[remoteEntryUniqueKey]) {
1688
+ delete share.globalLoading[remoteEntryUniqueKey];
1689
+ }
1690
+ // delete un loaded shared and instance
1691
+ let remoteInsId = remoteInfo.buildVersion ? sdk.composeKeyWithSeparator(remoteInfo.name, remoteInfo.buildVersion) : remoteInfo.name;
1692
+ const remoteInsIndex = globalThis.__FEDERATION__.__INSTANCES__.findIndex((ins)=>{
1693
+ if (remoteInfo.buildVersion) {
1694
+ return ins.options.id === remoteInsId;
1695
+ } else {
1696
+ return ins.name === remoteInsId;
1491
1697
  }
1492
1698
  });
1493
- });
1494
- if (strategy === 'version-first') {
1495
- this.options.remotes.forEach((remote)=>{
1496
- if (remote.shareScope === shareScopeName) {
1497
- promises.push(initRemoteModule(remote.name));
1699
+ if (remoteInsIndex !== -1) {
1700
+ const remoteIns = globalThis.__FEDERATION__.__INSTANCES__[remoteInsIndex];
1701
+ remoteInsId = remoteIns.options.id || remoteInsId;
1702
+ const globalShareScopeMap = share.getGlobalShareScope();
1703
+ let isAllSharedNotUsed = true;
1704
+ const needDeleteKeys = [];
1705
+ Object.keys(globalShareScopeMap).forEach((instId)=>{
1706
+ Object.keys(globalShareScopeMap[instId]).forEach((shareScope)=>{
1707
+ Object.keys(globalShareScopeMap[instId][shareScope]).forEach((shareName)=>{
1708
+ Object.keys(globalShareScopeMap[instId][shareScope][shareName]).forEach((shareVersion)=>{
1709
+ const shared = globalShareScopeMap[instId][shareScope][shareName][shareVersion];
1710
+ if (shared.from === remoteInfo.name) {
1711
+ if (shared.loaded || shared.loading) {
1712
+ shared.useIn = shared.useIn.filter((usedHostName)=>usedHostName !== remoteInfo.name);
1713
+ if (shared.useIn.length) {
1714
+ isAllSharedNotUsed = false;
1715
+ } else {
1716
+ needDeleteKeys.push([
1717
+ instId,
1718
+ shareScope,
1719
+ shareName,
1720
+ shareVersion
1721
+ ]);
1722
+ }
1723
+ } else {
1724
+ needDeleteKeys.push([
1725
+ instId,
1726
+ shareScope,
1727
+ shareName,
1728
+ shareVersion
1729
+ ]);
1730
+ }
1731
+ }
1732
+ });
1733
+ });
1734
+ });
1735
+ });
1736
+ if (isAllSharedNotUsed) {
1737
+ remoteIns.shareScopeMap = {};
1738
+ delete globalShareScopeMap[remoteInsId];
1498
1739
  }
1499
- });
1740
+ needDeleteKeys.forEach(([insId, shareScope, shareName, shareVersion])=>{
1741
+ var _globalShareScopeMap_insId_shareScope_shareName, _globalShareScopeMap_insId_shareScope, _globalShareScopeMap_insId;
1742
+ (_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];
1743
+ });
1744
+ globalThis.__FEDERATION__.__INSTANCES__.splice(remoteInsIndex, 1);
1745
+ }
1746
+ host.moduleCache.delete(remote.name);
1500
1747
  }
1501
- return promises;
1502
1748
  }
1503
- initShareScopeMap(scopeName, shareScope) {
1504
- this.shareScopeMap[scopeName] = shareScope;
1505
- this.hooks.lifecycle.initContainerShareScopeMap.emit({
1506
- shareScope,
1507
- options: this.options,
1508
- origin: this
1749
+ constructor(host){
1750
+ this.hooks = new PluginSystem({
1751
+ beforeRequest: new AsyncWaterfallHook('beforeRequest'),
1752
+ onLoad: new AsyncHook('onLoad'),
1753
+ handlePreloadModule: new SyncHook('handlePreloadModule'),
1754
+ errorLoadRemote: new AsyncHook('errorLoadRemote'),
1755
+ beforePreloadRemote: new AsyncHook(),
1756
+ generatePreloadAssets: new AsyncHook('generatePreloadAssets'),
1757
+ // not used yet
1758
+ afterPreloadRemote: new AsyncHook()
1509
1759
  });
1760
+ this.host = host;
1510
1761
  }
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
- });
1762
+ }
1763
+
1764
+ function _extends() {
1765
+ _extends = Object.assign || function(target) {
1766
+ for(var i = 1; i < arguments.length; i++){
1767
+ var source = arguments[i];
1768
+ for(var key in source){
1769
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1770
+ target[key] = source[key];
1771
+ }
1524
1772
  }
1773
+ }
1774
+ return target;
1775
+ };
1776
+ return _extends.apply(this, arguments);
1777
+ }
1778
+ class FederationHost {
1779
+ initOptions(userOptions) {
1780
+ this.registerPlugins(userOptions.plugins);
1781
+ const options = this.formatOptions(this.options, userOptions);
1782
+ this.options = options;
1783
+ return options;
1784
+ }
1785
+ async loadShare(pkgName, extraOptions) {
1786
+ return this.sharedHandler.loadShare(pkgName, extraOptions);
1787
+ }
1788
+ // The lib function will only be available if the shared set by eager or runtime init is set or the shared is successfully loaded.
1789
+ // 1. If the loaded shared already exists globally, then it will be reused
1790
+ // 2. If lib exists in local shared, it will be used directly
1791
+ // 3. If the local get returns something other than Promise, then it will be used directly
1792
+ loadShareSync(pkgName, extraOptions) {
1793
+ return this.sharedHandler.loadShareSync(pkgName, extraOptions);
1794
+ }
1795
+ initializeSharing(shareScopeName = share.DEFAULT_SCOPE, strategy) {
1796
+ return this.sharedHandler.initializeSharing(shareScopeName, strategy);
1797
+ }
1798
+ initRawContainer(name, url, container) {
1799
+ const remoteInfo = getRemoteInfo({
1800
+ name,
1801
+ entry: url
1802
+ });
1803
+ const module = new Module({
1804
+ host: this,
1805
+ remoteInfo
1525
1806
  });
1807
+ module.remoteEntryExports = container;
1808
+ this.moduleCache.set(name, module);
1809
+ return module;
1810
+ }
1811
+ // eslint-disable-next-line max-lines-per-function
1812
+ // eslint-disable-next-line @typescript-eslint/member-ordering
1813
+ async loadRemote(id, options) {
1814
+ return this.remoteHandler.loadRemote(id, options);
1815
+ }
1816
+ // eslint-disable-next-line @typescript-eslint/member-ordering
1817
+ async preloadRemote(preloadOptions) {
1818
+ return this.remoteHandler.preloadRemote(preloadOptions);
1819
+ }
1820
+ initShareScopeMap(scopeName, shareScope) {
1821
+ this.sharedHandler.initShareScopeMap(scopeName, shareScope);
1822
+ }
1823
+ formatOptions(globalOptions, userOptions) {
1824
+ const { shared } = share.formatShareConfigs(globalOptions, userOptions);
1526
1825
  const { userOptions: userOptionsRes, options: globalOptionsRes } = this.hooks.lifecycle.beforeInit.emit({
1527
1826
  origin: this,
1528
1827
  userOptions,
1529
1828
  options: globalOptions,
1530
1829
  shareInfo: shared
1531
1830
  });
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
- });
1831
+ const remotes = this.remoteHandler.formatAndRegisterRemote(globalOptionsRes, userOptionsRes);
1832
+ const { shared: handledShared } = this.sharedHandler.registerShared(globalOptionsRes, userOptionsRes);
1557
1833
  const plugins = [
1558
1834
  ...globalOptionsRes.plugins
1559
1835
  ];
@@ -1567,7 +1843,7 @@ class FederationHost {
1567
1843
  const optionsRes = _extends({}, globalOptions, userOptions, {
1568
1844
  plugins,
1569
1845
  remotes,
1570
- shared
1846
+ shared: handledShared
1571
1847
  });
1572
1848
  this.hooks.lifecycle.init.emit({
1573
1849
  origin: this,
@@ -1578,6 +1854,8 @@ class FederationHost {
1578
1854
  registerPlugins(plugins) {
1579
1855
  const pluginRes = registerPlugins$1(plugins, [
1580
1856
  this.hooks,
1857
+ this.remoteHandler.hooks,
1858
+ this.sharedHandler.hooks,
1581
1859
  this.snapshotHandler.hooks,
1582
1860
  this.loaderHook
1583
1861
  ]);
@@ -1590,132 +1868,19 @@ class FederationHost {
1590
1868
  return res;
1591
1869
  }, pluginRes || []);
1592
1870
  }
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
1871
  registerRemotes(remotes, options) {
1688
- remotes.forEach((remote)=>{
1689
- this.registerRemote(remote, this.options.remotes, {
1690
- force: options == null ? void 0 : options.force
1691
- });
1692
- });
1872
+ return this.remoteHandler.registerRemotes(remotes, options);
1693
1873
  }
1694
1874
  constructor(userOptions){
1695
1875
  this.hooks = new PluginSystem({
1696
1876
  beforeInit: new SyncWaterfallHook('beforeInit'),
1697
1877
  init: new SyncHook(),
1698
- beforeRequest: new AsyncWaterfallHook('beforeRequest'),
1699
- afterResolve: new AsyncWaterfallHook('afterResolve'),
1700
1878
  // maybe will change, temporarily for internal use only
1701
1879
  beforeInitContainer: new AsyncWaterfallHook('beforeInitContainer'),
1702
1880
  // 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()
1881
+ initContainer: new AsyncWaterfallHook('initContainer')
1717
1882
  });
1718
- this.version = "0.1.12";
1883
+ this.version = "0.1.14";
1719
1884
  this.moduleCache = new Map();
1720
1885
  this.loaderHook = new PluginSystem({
1721
1886
  // FIXME: may not be suitable , not open to the public yet
@@ -1740,9 +1905,10 @@ class FederationHost {
1740
1905
  };
1741
1906
  this.name = userOptions.name;
1742
1907
  this.options = defaultOptions;
1743
- this.shareScopeMap = {};
1744
- this._setGlobalShareScopeMap();
1745
1908
  this.snapshotHandler = new SnapshotHandler(this);
1909
+ this.sharedHandler = new SharedHandler(this);
1910
+ this.remoteHandler = new RemoteHandler(this);
1911
+ this.shareScopeMap = this.sharedHandler.shareScopeMap;
1746
1912
  this.registerPlugins([
1747
1913
  ...defaultOptions.plugins,
1748
1914
  ...userOptions.plugins || []