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