@module-federation/runtime 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/LICENSE +21 -0
  2. package/dist/helpers.cjs.d.ts +2 -0
  3. package/dist/helpers.cjs.js +34 -0
  4. package/dist/helpers.esm.js +32 -0
  5. package/dist/index.cjs.d.ts +1 -0
  6. package/dist/index.cjs.js +1808 -0
  7. package/dist/index.esm.js +1788 -0
  8. package/dist/package.json +50 -0
  9. package/dist/share.cjs.js +878 -0
  10. package/dist/share.esm.js +839 -0
  11. package/dist/src/constant.d.ts +2 -0
  12. package/dist/src/core.d.ts +170 -0
  13. package/dist/src/global.d.ts +43 -0
  14. package/dist/src/helpers.d.ts +33 -0
  15. package/dist/src/index.d.ts +15 -0
  16. package/dist/src/module/index.d.ts +19 -0
  17. package/dist/src/plugins/generate-preload-assets.d.ts +8 -0
  18. package/dist/src/plugins/snapshot/SnapshotHandler.d.ts +44 -0
  19. package/dist/src/plugins/snapshot/index.d.ts +5 -0
  20. package/dist/src/type/config.d.ts +104 -0
  21. package/dist/src/type/index.d.ts +3 -0
  22. package/dist/src/type/plugin.d.ts +20 -0
  23. package/dist/src/type/preload.d.ts +26 -0
  24. package/dist/src/types.d.ts +1 -0
  25. package/dist/src/utils/env.d.ts +4 -0
  26. package/dist/src/utils/hooks/asyncHook.d.ts +6 -0
  27. package/dist/src/utils/hooks/asyncWaterfallHooks.d.ts +10 -0
  28. package/dist/src/utils/hooks/index.d.ts +6 -0
  29. package/dist/src/utils/hooks/pluginSystem.d.ts +15 -0
  30. package/dist/src/utils/hooks/syncHook.d.ts +12 -0
  31. package/dist/src/utils/hooks/syncWaterfallHook.d.ts +9 -0
  32. package/dist/src/utils/index.d.ts +6 -0
  33. package/dist/src/utils/load.d.ts +18 -0
  34. package/dist/src/utils/logger.d.ts +3 -0
  35. package/dist/src/utils/manifest.d.ts +7 -0
  36. package/dist/src/utils/plugin.d.ts +4 -0
  37. package/dist/src/utils/preload.d.ts +6 -0
  38. package/dist/src/utils/semver/compare.d.ts +9 -0
  39. package/dist/src/utils/semver/constants.d.ts +10 -0
  40. package/dist/src/utils/semver/index.d.ts +2 -0
  41. package/dist/src/utils/semver/parser.d.ts +9 -0
  42. package/dist/src/utils/semver/utils.d.ts +11 -0
  43. package/dist/src/utils/share.d.ts +22 -0
  44. package/dist/src/utils/tool.d.ts +13 -0
  45. package/dist/types.cjs.d.ts +1 -0
  46. package/dist/types.cjs.js +2 -0
  47. package/dist/types.esm.js +1 -0
  48. package/package.json +2 -2
@@ -0,0 +1,1788 @@
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';
2
+ export { I as registerGlobalPlugins } from './share.esm.js';
3
+ import { loadScriptNode, loadScript, composeKeyWithSeparator, createLink, getResourceUrl, isManifestProvider, generateSnapshotFromManifest } from '@module-federation/sdk';
4
+ export { loadScript, loadScriptNode } from '@module-federation/sdk';
5
+
6
+ // Function to match a remote with its name and expose
7
+ // id: pkgName(@federation/app1) + expose(button) = @federation/app1/button
8
+ // id: alias(app1) + expose(button) = app1/button
9
+ // id: alias(app1/utils) + expose(loadash/sort) = app1/utils/loadash/sort
10
+ function matchRemoteWithNameAndExpose(remotes, id) {
11
+ for (const remote of remotes){
12
+ // match pkgName
13
+ const isNameMatched = id.startsWith(remote.name);
14
+ let expose = id.replace(remote.name, '');
15
+ if (isNameMatched) {
16
+ if (expose.startsWith('/')) {
17
+ const pkgNameOrAlias = remote.name;
18
+ expose = `.${expose}`;
19
+ return {
20
+ pkgNameOrAlias,
21
+ expose,
22
+ remote
23
+ };
24
+ } else if (expose === '') {
25
+ return {
26
+ pkgNameOrAlias: remote.name,
27
+ expose: '.',
28
+ remote
29
+ };
30
+ }
31
+ }
32
+ // match alias
33
+ const isAliasMatched = remote.alias && id.startsWith(remote.alias);
34
+ let exposeWithAlias = remote.alias && id.replace(remote.alias, '');
35
+ if (remote.alias && isAliasMatched) {
36
+ if (exposeWithAlias && exposeWithAlias.startsWith('/')) {
37
+ const pkgNameOrAlias = remote.alias;
38
+ exposeWithAlias = `.${exposeWithAlias}`;
39
+ return {
40
+ pkgNameOrAlias,
41
+ expose: exposeWithAlias,
42
+ remote
43
+ };
44
+ } else if (exposeWithAlias === '') {
45
+ return {
46
+ pkgNameOrAlias: remote.alias,
47
+ expose: '.',
48
+ remote
49
+ };
50
+ }
51
+ }
52
+ }
53
+ return;
54
+ }
55
+ // Function to match a remote with its name or alias
56
+ function matchRemote(remotes, nameOrAlias) {
57
+ for (const remote of remotes){
58
+ const isNameMatched = nameOrAlias === remote.name;
59
+ if (isNameMatched) {
60
+ return remote;
61
+ }
62
+ const isAliasMatched = remote.alias && nameOrAlias === remote.alias;
63
+ if (isAliasMatched) {
64
+ return remote;
65
+ }
66
+ }
67
+ return;
68
+ }
69
+
70
+ function registerPlugins$1(plugins, hookInstances) {
71
+ const globalPlugins = getGlobalHostPlugins();
72
+ // Incorporate global plugins
73
+ if (globalPlugins.length > 0) {
74
+ globalPlugins.forEach((plugin)=>{
75
+ if (plugins == null ? void 0 : plugins.find((item)=>item.name !== plugin.name)) {
76
+ plugins.push(plugin);
77
+ }
78
+ });
79
+ }
80
+ if (plugins && plugins.length > 0) {
81
+ plugins.forEach((plugin)=>{
82
+ hookInstances.forEach((hookInstance)=>{
83
+ hookInstance.applyPlugin(plugin);
84
+ });
85
+ });
86
+ }
87
+ return plugins;
88
+ }
89
+
90
+ function _extends$5() {
91
+ _extends$5 = Object.assign || function(target) {
92
+ for(var i = 1; i < arguments.length; i++){
93
+ var source = arguments[i];
94
+ for(var key in source){
95
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
96
+ target[key] = source[key];
97
+ }
98
+ }
99
+ }
100
+ return target;
101
+ };
102
+ return _extends$5.apply(this, arguments);
103
+ }
104
+ async function loadEsmEntry({ entry, remoteEntryExports }) {
105
+ return new Promise((resolve, reject)=>{
106
+ try {
107
+ if (!remoteEntryExports) {
108
+ // eslint-disable-next-line no-eval
109
+ new Function('callbacks', `import("${entry}").then(callbacks[0]).catch(callbacks[1])`)([
110
+ resolve,
111
+ reject
112
+ ]);
113
+ } else {
114
+ resolve(remoteEntryExports);
115
+ }
116
+ } catch (e) {
117
+ reject(e);
118
+ }
119
+ });
120
+ }
121
+ async function loadEntryScript({ name, globalName, entry, createScriptHook }) {
122
+ const { entryExports: remoteEntryExports } = getRemoteEntryExports(name, globalName);
123
+ if (remoteEntryExports) {
124
+ return remoteEntryExports;
125
+ }
126
+ if (typeof document === 'undefined') {
127
+ return loadScriptNode(entry, {
128
+ attrs: {
129
+ name,
130
+ globalName
131
+ },
132
+ createScriptHook
133
+ }).then(()=>{
134
+ const { remoteEntryKey, entryExports } = getRemoteEntryExports(name, globalName);
135
+ assert(entryExports, `
136
+ Unable to use the ${name}'s '${entry}' URL with ${remoteEntryKey}'s globalName to get remoteEntry exports.
137
+ Possible reasons could be:\n
138
+ 1. '${entry}' is not the correct URL, or the remoteEntry resource or name is incorrect.\n
139
+ 2. ${remoteEntryKey} cannot be used to get remoteEntry exports in the window object.
140
+ `);
141
+ return entryExports;
142
+ }).catch((e)=>{
143
+ return e;
144
+ });
145
+ }
146
+ return loadScript(entry, {
147
+ attrs: {},
148
+ createScriptHook
149
+ }).then(()=>{
150
+ const { remoteEntryKey, entryExports } = getRemoteEntryExports(name, globalName);
151
+ assert(entryExports, `
152
+ Unable to use the ${name}'s '${entry}' URL with ${remoteEntryKey}'s globalName to get remoteEntry exports.
153
+ Possible reasons could be:\n
154
+ 1. '${entry}' is not the correct URL, or the remoteEntry resource or name is incorrect.\n
155
+ 2. ${remoteEntryKey} cannot be used to get remoteEntry exports in the window object.
156
+ `);
157
+ return entryExports;
158
+ }).catch((e)=>{
159
+ return e;
160
+ });
161
+ }
162
+ function getRemoteEntryUniqueKey(remoteInfo) {
163
+ const { entry, name } = remoteInfo;
164
+ return composeKeyWithSeparator(name, entry);
165
+ }
166
+ async function getRemoteEntry({ remoteEntryExports, remoteInfo, createScriptHook }) {
167
+ const { entry, name, type, entryGlobalName } = remoteInfo;
168
+ const uniqueKey = getRemoteEntryUniqueKey(remoteInfo);
169
+ if (remoteEntryExports) {
170
+ return remoteEntryExports;
171
+ }
172
+ if (!globalLoading[uniqueKey]) {
173
+ if (type === 'esm') {
174
+ globalLoading[uniqueKey] = loadEsmEntry({
175
+ entry,
176
+ remoteEntryExports
177
+ });
178
+ } else {
179
+ globalLoading[uniqueKey] = loadEntryScript({
180
+ name,
181
+ globalName: entryGlobalName,
182
+ entry,
183
+ createScriptHook
184
+ });
185
+ }
186
+ }
187
+ return globalLoading[uniqueKey];
188
+ }
189
+ function getRemoteInfo(remote) {
190
+ return _extends$5({}, remote, {
191
+ entry: 'entry' in remote ? remote.entry : '',
192
+ type: remote.type || DEFAULT_REMOTE_TYPE,
193
+ entryGlobalName: remote.entryGlobalName || remote.name,
194
+ shareScope: remote.shareScope || DEFAULT_SCOPE
195
+ });
196
+ }
197
+
198
+ function _extends$4() {
199
+ _extends$4 = Object.assign || function(target) {
200
+ for(var i = 1; i < arguments.length; i++){
201
+ var source = arguments[i];
202
+ for(var key in source){
203
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
204
+ target[key] = source[key];
205
+ }
206
+ }
207
+ }
208
+ return target;
209
+ };
210
+ return _extends$4.apply(this, arguments);
211
+ }
212
+ let Module = class Module {
213
+ async getEntry() {
214
+ if (this.remoteEntryExports) {
215
+ return this.remoteEntryExports;
216
+ }
217
+ // Get remoteEntry.js
218
+ const remoteEntryExports = await getRemoteEntry({
219
+ remoteInfo: this.remoteInfo,
220
+ remoteEntryExports: this.remoteEntryExports,
221
+ createScriptHook: (url)=>{
222
+ const res = this.host.loaderHook.lifecycle.createScript.emit({
223
+ url
224
+ });
225
+ if (typeof document === 'undefined') {
226
+ //todo: needs real fix
227
+ return res;
228
+ }
229
+ if (res instanceof HTMLScriptElement) {
230
+ return res;
231
+ }
232
+ return;
233
+ }
234
+ });
235
+ assert(remoteEntryExports, `remoteEntryExports is undefined \n ${safeToString(this.remoteInfo)}`);
236
+ this.remoteEntryExports = remoteEntryExports;
237
+ return this.remoteEntryExports;
238
+ }
239
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
240
+ async get(expose, options) {
241
+ const { loadFactory = true } = options || {
242
+ loadFactory: true
243
+ };
244
+ // Get remoteEntry.js
245
+ const remoteEntryExports = await this.getEntry();
246
+ if (!this.inited) {
247
+ const localShareScopeMap = this.host.shareScopeMap;
248
+ const remoteShareScope = this.remoteInfo.shareScope || 'default';
249
+ if (!localShareScopeMap[remoteShareScope]) {
250
+ localShareScopeMap[remoteShareScope] = {};
251
+ }
252
+ const shareScope = localShareScopeMap[remoteShareScope];
253
+ const initScope = [];
254
+ const remoteEntryInitOptions = {
255
+ version: this.remoteInfo.version || ''
256
+ };
257
+ // Help to find host instance
258
+ Object.defineProperty(remoteEntryInitOptions, 'hostId', {
259
+ value: this.host.options.id || this.host.name,
260
+ // remoteEntryInitOptions will be traversed and assigned during container init, ,so this attribute is not allowed to be traversed
261
+ enumerable: false
262
+ });
263
+ const initContainerOptions = await this.host.hooks.lifecycle.beforeInitContainer.emit({
264
+ shareScope,
265
+ // @ts-ignore hostId will be set by Object.defineProperty
266
+ remoteEntryInitOptions,
267
+ initScope,
268
+ remoteInfo: this.remoteInfo,
269
+ origin: this.host
270
+ });
271
+ await remoteEntryExports.init(initContainerOptions.shareScope, initContainerOptions.initScope, initContainerOptions.remoteEntryInitOptions);
272
+ await this.host.hooks.lifecycle.initContainer.emit(_extends$4({}, initContainerOptions, {
273
+ remoteEntryExports
274
+ }));
275
+ }
276
+ this.lib = remoteEntryExports;
277
+ this.inited = true;
278
+ // get exposeGetter
279
+ const moduleFactory = await remoteEntryExports.get(expose);
280
+ assert(moduleFactory, `${getFMId(this.remoteInfo)} remote don't export ${expose}.`);
281
+ if (!loadFactory) {
282
+ return moduleFactory;
283
+ }
284
+ const exposeContent = await moduleFactory();
285
+ return exposeContent;
286
+ }
287
+ constructor({ remoteInfo, host }){
288
+ this.inited = false;
289
+ this.lib = undefined;
290
+ this.remoteInfo = remoteInfo;
291
+ this.host = host;
292
+ }
293
+ };
294
+
295
+ class SyncHook {
296
+ on(fn) {
297
+ if (typeof fn === 'function') {
298
+ this.listeners.add(fn);
299
+ }
300
+ }
301
+ once(fn) {
302
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
303
+ const self = this;
304
+ this.on(function wrapper(...args) {
305
+ self.remove(wrapper);
306
+ // eslint-disable-next-line prefer-spread
307
+ return fn.apply(null, args);
308
+ });
309
+ }
310
+ emit(...data) {
311
+ let result;
312
+ if (this.listeners.size > 0) {
313
+ // eslint-disable-next-line prefer-spread
314
+ this.listeners.forEach((fn)=>{
315
+ result = fn(...data);
316
+ });
317
+ }
318
+ return result;
319
+ }
320
+ remove(fn) {
321
+ this.listeners.delete(fn);
322
+ }
323
+ removeAll() {
324
+ this.listeners.clear();
325
+ }
326
+ constructor(type){
327
+ this.type = '';
328
+ this.listeners = new Set();
329
+ if (type) {
330
+ this.type = type;
331
+ }
332
+ }
333
+ }
334
+
335
+ class AsyncHook extends SyncHook {
336
+ emit(...data) {
337
+ let result;
338
+ const ls = Array.from(this.listeners);
339
+ if (ls.length > 0) {
340
+ let i = 0;
341
+ const call = (prev)=>{
342
+ if (prev === false) {
343
+ return false; // Abort process
344
+ } else if (i < ls.length) {
345
+ return Promise.resolve(ls[i++].apply(null, data)).then(call);
346
+ } else {
347
+ return prev;
348
+ }
349
+ };
350
+ result = call();
351
+ }
352
+ return Promise.resolve(result);
353
+ }
354
+ }
355
+
356
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
357
+ function checkReturnData(originalData, returnedData) {
358
+ if (!isObject(returnedData)) {
359
+ return false;
360
+ }
361
+ if (originalData !== returnedData) {
362
+ // eslint-disable-next-line no-restricted-syntax
363
+ for(const key in originalData){
364
+ if (!(key in returnedData)) {
365
+ return false;
366
+ }
367
+ }
368
+ }
369
+ return true;
370
+ }
371
+ class SyncWaterfallHook extends SyncHook {
372
+ emit(data) {
373
+ if (!isObject(data)) {
374
+ error(`The data for the "${this.type}" hook should be an object.`);
375
+ }
376
+ for (const fn of this.listeners){
377
+ try {
378
+ const tempData = fn(data);
379
+ if (checkReturnData(data, tempData)) {
380
+ data = tempData;
381
+ } else {
382
+ this.onerror(`A plugin returned an unacceptable value for the "${this.type}" type.`);
383
+ break;
384
+ }
385
+ } catch (e) {
386
+ warn(e);
387
+ this.onerror(e);
388
+ }
389
+ }
390
+ return data;
391
+ }
392
+ constructor(type){
393
+ super();
394
+ this.onerror = error;
395
+ this.type = type;
396
+ }
397
+ }
398
+
399
+ class AsyncWaterfallHook extends SyncHook {
400
+ emit(data) {
401
+ if (!isObject(data)) {
402
+ error(`The response data for the "${this.type}" hook must be an object.`);
403
+ }
404
+ const ls = Array.from(this.listeners);
405
+ if (ls.length > 0) {
406
+ let i = 0;
407
+ const processError = (e)=>{
408
+ warn(e);
409
+ this.onerror(e);
410
+ return data;
411
+ };
412
+ const call = (prevData)=>{
413
+ if (checkReturnData(data, prevData)) {
414
+ data = prevData;
415
+ if (i < ls.length) {
416
+ try {
417
+ return Promise.resolve(ls[i++](data)).then(call, processError);
418
+ } catch (e) {
419
+ return processError(e);
420
+ }
421
+ }
422
+ } else {
423
+ this.onerror(`A plugin returned an incorrect value for the "${this.type}" type.`);
424
+ }
425
+ return data;
426
+ };
427
+ return Promise.resolve(call(data));
428
+ }
429
+ return Promise.resolve(data);
430
+ }
431
+ constructor(type){
432
+ super();
433
+ this.onerror = error;
434
+ this.type = type;
435
+ }
436
+ }
437
+
438
+ class PluginSystem {
439
+ applyPlugin(plugin) {
440
+ assert(isPlainObject(plugin), 'Plugin configuration is invalid.');
441
+ // The plugin's name is mandatory and must be unique
442
+ const pluginName = plugin.name;
443
+ assert(pluginName, 'A name must be provided by the plugin.');
444
+ if (!this.registerPlugins[pluginName]) {
445
+ this.registerPlugins[pluginName] = plugin;
446
+ Object.keys(this.lifecycle).forEach((key)=>{
447
+ const pluginLife = plugin[key];
448
+ if (pluginLife) {
449
+ this.lifecycle[key].on(pluginLife);
450
+ }
451
+ });
452
+ }
453
+ }
454
+ removePlugin(pluginName) {
455
+ assert(pluginName, 'A name is required.');
456
+ const plugin = this.registerPlugins[pluginName];
457
+ assert(plugin, `The plugin "${pluginName}" is not registered.`);
458
+ Object.keys(plugin).forEach((key)=>{
459
+ if (key !== 'name') {
460
+ this.lifecycle[key].remove(plugin[key]);
461
+ }
462
+ });
463
+ }
464
+ // eslint-disable-next-line @typescript-eslint/no-shadow
465
+ inherit({ lifecycle, registerPlugins }) {
466
+ Object.keys(lifecycle).forEach((hookName)=>{
467
+ assert(!this.lifecycle[hookName], `The hook "${hookName}" has a conflict and cannot be inherited.`);
468
+ this.lifecycle[hookName] = lifecycle[hookName];
469
+ });
470
+ Object.keys(registerPlugins).forEach((pluginName)=>{
471
+ assert(!this.registerPlugins[pluginName], `The plugin "${pluginName}" has a conflict and cannot be inherited.`);
472
+ this.applyPlugin(registerPlugins[pluginName]);
473
+ });
474
+ }
475
+ constructor(lifecycle){
476
+ this.registerPlugins = {};
477
+ this.lifecycle = lifecycle;
478
+ this.lifecycleKeys = Object.keys(lifecycle);
479
+ }
480
+ }
481
+
482
+ function _extends$3() {
483
+ _extends$3 = Object.assign || function(target) {
484
+ for(var i = 1; i < arguments.length; i++){
485
+ var source = arguments[i];
486
+ for(var key in source){
487
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
488
+ target[key] = source[key];
489
+ }
490
+ }
491
+ }
492
+ return target;
493
+ };
494
+ return _extends$3.apply(this, arguments);
495
+ }
496
+ function defaultPreloadArgs(preloadConfig) {
497
+ return _extends$3({
498
+ resourceCategory: 'sync',
499
+ share: true,
500
+ depsRemote: true,
501
+ prefetchInterface: false
502
+ }, preloadConfig);
503
+ }
504
+ function formatPreloadArgs(remotes, preloadArgs) {
505
+ return preloadArgs.map((args)=>{
506
+ const remoteInfo = matchRemote(remotes, args.nameOrAlias);
507
+ assert(remoteInfo, `Unable to preload ${args.nameOrAlias} as it is not included in ${!remoteInfo && safeToString({
508
+ remoteInfo,
509
+ remotes
510
+ })}`);
511
+ return {
512
+ remote: remoteInfo,
513
+ preloadConfig: defaultPreloadArgs(args)
514
+ };
515
+ });
516
+ }
517
+ function normalizePreloadExposes(exposes) {
518
+ if (!exposes) {
519
+ return [];
520
+ }
521
+ return exposes.map((expose)=>{
522
+ if (expose === '.') {
523
+ return expose;
524
+ }
525
+ if (expose.startsWith('./')) {
526
+ return expose.replace('./', '');
527
+ }
528
+ return expose;
529
+ });
530
+ }
531
+ function preloadAssets(remoteInfo, host, assets) {
532
+ const { cssAssets, jsAssetsWithoutEntry, entryAssets } = assets;
533
+ if (host.options.inBrowser) {
534
+ entryAssets.forEach((asset)=>{
535
+ const { moduleInfo } = asset;
536
+ const module = host.moduleCache.get(remoteInfo.name);
537
+ if (module) {
538
+ getRemoteEntry({
539
+ remoteInfo: moduleInfo,
540
+ remoteEntryExports: module.remoteEntryExports,
541
+ createScriptHook: (url)=>{
542
+ const res = host.loaderHook.lifecycle.createScript.emit({
543
+ url
544
+ });
545
+ if (res instanceof HTMLScriptElement) {
546
+ return res;
547
+ }
548
+ return;
549
+ }
550
+ });
551
+ } else {
552
+ getRemoteEntry({
553
+ remoteInfo: moduleInfo,
554
+ remoteEntryExports: undefined,
555
+ createScriptHook: (url)=>{
556
+ const res = host.loaderHook.lifecycle.createScript.emit({
557
+ url
558
+ });
559
+ if (res instanceof HTMLScriptElement) {
560
+ return res;
561
+ }
562
+ return;
563
+ }
564
+ });
565
+ }
566
+ });
567
+ const fragment = document.createDocumentFragment();
568
+ cssAssets.forEach((cssUrl)=>{
569
+ const { link: cssEl, needAttach } = createLink(cssUrl, ()=>{}, {
570
+ rel: 'preload',
571
+ as: 'style'
572
+ }, (url)=>{
573
+ const res = host.loaderHook.lifecycle.createLink.emit({
574
+ url
575
+ });
576
+ if (res instanceof HTMLLinkElement) {
577
+ return res;
578
+ }
579
+ return;
580
+ });
581
+ needAttach && fragment.appendChild(cssEl);
582
+ });
583
+ jsAssetsWithoutEntry.forEach((jsUrl)=>{
584
+ const { link: linkEl, needAttach } = createLink(jsUrl, ()=>{
585
+ // noop
586
+ }, {
587
+ rel: 'preload',
588
+ as: 'script'
589
+ }, (url)=>{
590
+ const res = host.loaderHook.lifecycle.createLink.emit({
591
+ url
592
+ });
593
+ if (res instanceof HTMLLinkElement) {
594
+ return res;
595
+ }
596
+ return;
597
+ });
598
+ needAttach && document.head.appendChild(linkEl);
599
+ });
600
+ document.head.appendChild(fragment);
601
+ }
602
+ }
603
+
604
+ function _extends$2() {
605
+ _extends$2 = Object.assign || function(target) {
606
+ for(var i = 1; i < arguments.length; i++){
607
+ var source = arguments[i];
608
+ for(var key in source){
609
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
610
+ target[key] = source[key];
611
+ }
612
+ }
613
+ }
614
+ return target;
615
+ };
616
+ return _extends$2.apply(this, arguments);
617
+ }
618
+ function assignRemoteInfo(remoteInfo, remoteSnapshot) {
619
+ if (!('remoteEntry' in remoteSnapshot) || !remoteSnapshot.remoteEntry) {
620
+ error(`The attribute remoteEntry of ${name} must not be undefined.`);
621
+ }
622
+ const { remoteEntry } = remoteSnapshot;
623
+ const entryUrl = getResourceUrl(remoteSnapshot, remoteEntry);
624
+ remoteInfo.type = remoteSnapshot.remoteEntryType;
625
+ remoteInfo.entryGlobalName = remoteSnapshot.globalName;
626
+ remoteInfo.entry = entryUrl;
627
+ remoteInfo.version = remoteSnapshot.version;
628
+ remoteInfo.buildVersion = remoteSnapshot.buildVersion;
629
+ }
630
+ function snapshotPlugin() {
631
+ return {
632
+ name: 'snapshot-plugin',
633
+ async afterResolve (args) {
634
+ const { remote, pkgNameOrAlias, expose, origin, remoteInfo } = args;
635
+ if (!isRemoteInfoWithEntry(remote) || !isPureRemoteEntry(remote)) {
636
+ const { remoteSnapshot, globalSnapshot } = await origin.snapshotHandler.loadRemoteSnapshotInfo(remote);
637
+ assignRemoteInfo(remoteInfo, remoteSnapshot);
638
+ // preloading assets
639
+ const preloadOptions = {
640
+ remote,
641
+ preloadConfig: {
642
+ nameOrAlias: pkgNameOrAlias,
643
+ exposes: [
644
+ expose
645
+ ],
646
+ resourceCategory: 'sync',
647
+ share: false,
648
+ depsRemote: false
649
+ }
650
+ };
651
+ const assets = await origin.hooks.lifecycle.generatePreloadAssets.emit({
652
+ origin,
653
+ preloadOptions,
654
+ remoteInfo,
655
+ remote,
656
+ remoteSnapshot,
657
+ globalSnapshot
658
+ });
659
+ if (assets) {
660
+ preloadAssets(remoteInfo, origin, assets);
661
+ }
662
+ return _extends$2({}, args, {
663
+ remoteSnapshot
664
+ });
665
+ }
666
+ return args;
667
+ }
668
+ };
669
+ }
670
+
671
+ // name
672
+ // name:version
673
+ function splitId(id) {
674
+ const splitInfo = id.split(':');
675
+ if (splitInfo.length === 1) {
676
+ return {
677
+ name: splitInfo[0],
678
+ version: undefined
679
+ };
680
+ } else if (splitInfo.length === 2) {
681
+ return {
682
+ name: splitInfo[0],
683
+ version: splitInfo[1]
684
+ };
685
+ } else {
686
+ return {
687
+ name: splitInfo[1],
688
+ version: splitInfo[2]
689
+ };
690
+ }
691
+ }
692
+ // Traverse all nodes in moduleInfo and traverse the entire snapshot
693
+ function traverseModuleInfo(globalSnapshot, remoteInfo, traverse, isRoot, memo = {}, remoteSnapshot) {
694
+ const id = getFMId(remoteInfo);
695
+ const { value: snapshotValue } = getInfoWithoutType(globalSnapshot, id);
696
+ const effectiveRemoteSnapshot = remoteSnapshot || snapshotValue;
697
+ if (effectiveRemoteSnapshot && !isManifestProvider(effectiveRemoteSnapshot)) {
698
+ traverse(effectiveRemoteSnapshot, remoteInfo, isRoot);
699
+ if (effectiveRemoteSnapshot.remotesInfo) {
700
+ const remoteKeys = Object.keys(effectiveRemoteSnapshot.remotesInfo);
701
+ for (const key of remoteKeys){
702
+ if (memo[key]) {
703
+ continue;
704
+ }
705
+ memo[key] = true;
706
+ const subRemoteInfo = splitId(key);
707
+ const remoteValue = effectiveRemoteSnapshot.remotesInfo[key];
708
+ traverseModuleInfo(globalSnapshot, {
709
+ name: subRemoteInfo.name,
710
+ version: remoteValue.matchedVersion
711
+ }, traverse, false, memo, undefined);
712
+ }
713
+ }
714
+ }
715
+ }
716
+ // eslint-disable-next-line max-lines-per-function
717
+ function generatePreloadAssets(origin, preloadOptions, remote, globalSnapshot, remoteSnapshot) {
718
+ const cssAssets = [];
719
+ const jsAssets = [];
720
+ const entryAssets = [];
721
+ const loadedSharedJsAssets = new Set();
722
+ const loadedSharedCssAssets = new Set();
723
+ const { options } = origin;
724
+ const { preloadConfig: rootPreloadConfig } = preloadOptions;
725
+ const { depsRemote } = rootPreloadConfig;
726
+ const memo = {};
727
+ traverseModuleInfo(globalSnapshot, remote, (moduleInfoSnapshot, remoteInfo, isRoot)=>{
728
+ let preloadConfig;
729
+ if (isRoot) {
730
+ preloadConfig = rootPreloadConfig;
731
+ } else {
732
+ if (Array.isArray(depsRemote)) {
733
+ // eslint-disable-next-line array-callback-return
734
+ const findPreloadConfig = depsRemote.find((remoteConfig)=>{
735
+ if (remoteConfig.nameOrAlias === remoteInfo.name || remoteConfig.nameOrAlias === remoteInfo.alias) {
736
+ return true;
737
+ }
738
+ return false;
739
+ });
740
+ if (!findPreloadConfig) {
741
+ return;
742
+ }
743
+ preloadConfig = defaultPreloadArgs(findPreloadConfig);
744
+ } else if (depsRemote === true) {
745
+ preloadConfig = rootPreloadConfig;
746
+ } else {
747
+ return;
748
+ }
749
+ }
750
+ const remoteEntryUrl = getResourceUrl(moduleInfoSnapshot, 'remoteEntry' in moduleInfoSnapshot ? moduleInfoSnapshot.remoteEntry : '');
751
+ if (remoteEntryUrl) {
752
+ entryAssets.push({
753
+ name: remoteInfo.name,
754
+ moduleInfo: {
755
+ name: remoteInfo.name,
756
+ entry: remoteEntryUrl,
757
+ type: 'remoteEntryType' in moduleInfoSnapshot ? moduleInfoSnapshot.remoteEntryType : 'global',
758
+ entryGlobalName: 'globalName' in moduleInfoSnapshot ? moduleInfoSnapshot.globalName : remoteInfo.name,
759
+ shareScope: '',
760
+ version: 'version' in moduleInfoSnapshot ? moduleInfoSnapshot.version : undefined
761
+ },
762
+ url: remoteEntryUrl
763
+ });
764
+ }
765
+ let moduleAssetsInfo = 'modules' in moduleInfoSnapshot ? moduleInfoSnapshot.modules : [];
766
+ const normalizedPreloadExposes = normalizePreloadExposes(preloadConfig.exposes);
767
+ if (normalizedPreloadExposes.length && 'modules' in moduleInfoSnapshot) {
768
+ var _moduleInfoSnapshot_modules;
769
+ moduleAssetsInfo = moduleInfoSnapshot == null ? void 0 : (_moduleInfoSnapshot_modules = moduleInfoSnapshot.modules) == null ? void 0 : _moduleInfoSnapshot_modules.reduce((assets, moduleAssetInfo)=>{
770
+ if ((normalizedPreloadExposes == null ? void 0 : normalizedPreloadExposes.indexOf(moduleAssetInfo.moduleName)) !== -1) {
771
+ assets.push(moduleAssetInfo);
772
+ }
773
+ return assets;
774
+ }, []);
775
+ }
776
+ function handleAssets(assets) {
777
+ const assetsRes = assets.map((asset)=>getResourceUrl(moduleInfoSnapshot, asset));
778
+ if (preloadConfig.filter) {
779
+ return assetsRes.filter(preloadConfig.filter);
780
+ }
781
+ return assetsRes;
782
+ }
783
+ if (moduleAssetsInfo) {
784
+ const assetsLength = moduleAssetsInfo.length;
785
+ for(let index = 0; index < assetsLength; index++){
786
+ const assetsInfo = moduleAssetsInfo[index];
787
+ const exposeFullPath = `${remoteInfo.name}/${assetsInfo.moduleName}`;
788
+ origin.hooks.lifecycle.handlePreloadModule.emit({
789
+ id: assetsInfo.moduleName === '.' ? remoteInfo.name : exposeFullPath,
790
+ name: remoteInfo.name,
791
+ remoteSnapshot: moduleInfoSnapshot,
792
+ preloadConfig,
793
+ remote: remoteInfo,
794
+ origin
795
+ });
796
+ const preloaded = getPreloaded(exposeFullPath);
797
+ if (preloaded) {
798
+ continue;
799
+ }
800
+ if (preloadConfig.resourceCategory === 'all') {
801
+ cssAssets.push(...handleAssets(assetsInfo.assets.css.async));
802
+ cssAssets.push(...handleAssets(assetsInfo.assets.css.sync));
803
+ jsAssets.push(...handleAssets(assetsInfo.assets.js.async));
804
+ jsAssets.push(...handleAssets(assetsInfo.assets.js.sync));
805
+ // eslint-disable-next-line no-constant-condition
806
+ } else if (preloadConfig.resourceCategory = 'sync') {
807
+ cssAssets.push(...handleAssets(assetsInfo.assets.css.sync));
808
+ jsAssets.push(...handleAssets(assetsInfo.assets.js.sync));
809
+ }
810
+ setPreloaded(exposeFullPath);
811
+ }
812
+ }
813
+ }, true, memo, remoteSnapshot);
814
+ if (remoteSnapshot.shared) {
815
+ const collectSharedAssets = (shareInfo, snapshotShared)=>{
816
+ const registeredShared = getRegisteredShare(origin.shareScopeMap, snapshotShared.sharedName, shareInfo, origin.hooks.lifecycle.resolveShare);
817
+ // 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
+ if (registeredShared && typeof registeredShared.lib === 'function') {
819
+ snapshotShared.assets.js.sync.forEach((asset)=>{
820
+ loadedSharedJsAssets.add(asset);
821
+ });
822
+ snapshotShared.assets.css.sync.forEach((asset)=>{
823
+ loadedSharedCssAssets.add(asset);
824
+ });
825
+ }
826
+ };
827
+ remoteSnapshot.shared.forEach((shared)=>{
828
+ var _options_shared;
829
+ const shareInfos = (_options_shared = options.shared) == null ? void 0 : _options_shared[shared.sharedName];
830
+ if (!shareInfos) {
831
+ return;
832
+ }
833
+ // if no version, preload all shared
834
+ const sharedOptions = shared.version ? shareInfos.find((s)=>s.version === shared.version) : shareInfos;
835
+ if (!sharedOptions) {
836
+ return;
837
+ }
838
+ const arrayShareInfo = arrayOptions(sharedOptions);
839
+ arrayShareInfo.forEach((s)=>{
840
+ collectSharedAssets(s, shared);
841
+ });
842
+ });
843
+ }
844
+ const needPreloadJsAssets = jsAssets.filter((asset)=>!loadedSharedJsAssets.has(asset));
845
+ const needPreloadCssAssets = cssAssets.filter((asset)=>!loadedSharedCssAssets.has(asset));
846
+ return {
847
+ cssAssets: needPreloadCssAssets,
848
+ jsAssetsWithoutEntry: needPreloadJsAssets,
849
+ entryAssets
850
+ };
851
+ }
852
+ const generatePreloadAssetsPlugin = function() {
853
+ return {
854
+ name: 'generate-preload-assets-plugin',
855
+ async generatePreloadAssets (args) {
856
+ const { origin, preloadOptions, remoteInfo, remote, globalSnapshot, remoteSnapshot } = args;
857
+ if (isRemoteInfoWithEntry(remote) && isPureRemoteEntry(remote)) {
858
+ return {
859
+ cssAssets: [],
860
+ jsAssetsWithoutEntry: [],
861
+ entryAssets: [
862
+ {
863
+ name: remote.name,
864
+ url: remote.entry,
865
+ moduleInfo: {
866
+ name: remoteInfo.name,
867
+ entry: remote.entry,
868
+ type: 'global',
869
+ entryGlobalName: '',
870
+ shareScope: ''
871
+ }
872
+ }
873
+ ]
874
+ };
875
+ }
876
+ assignRemoteInfo(remoteInfo, remoteSnapshot);
877
+ const assets = generatePreloadAssets(origin, preloadOptions, remoteInfo, globalSnapshot, remoteSnapshot);
878
+ return assets;
879
+ }
880
+ };
881
+ };
882
+
883
+ function _extends$1() {
884
+ _extends$1 = Object.assign || function(target) {
885
+ for(var i = 1; i < arguments.length; i++){
886
+ var source = arguments[i];
887
+ for(var key in source){
888
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
889
+ target[key] = source[key];
890
+ }
891
+ }
892
+ }
893
+ return target;
894
+ };
895
+ return _extends$1.apply(this, arguments);
896
+ }
897
+ class SnapshotHandler {
898
+ async loadSnapshot(moduleInfo) {
899
+ const { options } = this.HostInstance;
900
+ const { hostGlobalSnapshot, remoteSnapshot, globalSnapshot } = this.getGlobalRemoteInfo(moduleInfo);
901
+ const { remoteSnapshot: globalRemoteSnapshot, globalSnapshot: globalSnapshotRes } = await this.hooks.lifecycle.loadSnapshot.emit({
902
+ options,
903
+ moduleInfo,
904
+ hostGlobalSnapshot,
905
+ remoteSnapshot,
906
+ globalSnapshot
907
+ });
908
+ return {
909
+ remoteSnapshot: globalRemoteSnapshot,
910
+ globalSnapshot: globalSnapshotRes
911
+ };
912
+ }
913
+ // eslint-disable-next-line max-lines-per-function
914
+ async loadRemoteSnapshotInfo(moduleInfo) {
915
+ const { options } = this.HostInstance;
916
+ await this.hooks.lifecycle.beforeLoadRemoteSnapshot.emit({
917
+ options,
918
+ moduleInfo
919
+ });
920
+ let hostSnapshot = getGlobalSnapshotInfoByModuleInfo({
921
+ name: this.HostInstance.options.name,
922
+ version: this.HostInstance.options.version
923
+ });
924
+ if (!hostSnapshot) {
925
+ hostSnapshot = {
926
+ version: this.HostInstance.options.version || '',
927
+ remoteEntry: '',
928
+ remotesInfo: {}
929
+ };
930
+ addGlobalSnapshot({
931
+ [this.HostInstance.options.name]: hostSnapshot
932
+ });
933
+ }
934
+ // In dynamic loadRemote scenarios, incomplete remotesInfo delivery may occur. In such cases, the remotesInfo in the host needs to be completed in the snapshot at runtime.
935
+ // 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
+ if (hostSnapshot && 'remotesInfo' in hostSnapshot && !getInfoWithoutType(hostSnapshot.remotesInfo, moduleInfo.name).value) {
937
+ if ('version' in moduleInfo || 'entry' in moduleInfo) {
938
+ hostSnapshot.remotesInfo = _extends$1({}, hostSnapshot == null ? void 0 : hostSnapshot.remotesInfo, {
939
+ [moduleInfo.name]: {
940
+ matchedVersion: 'version' in moduleInfo ? moduleInfo.version : moduleInfo.entry
941
+ }
942
+ });
943
+ }
944
+ }
945
+ const { hostGlobalSnapshot, remoteSnapshot, globalSnapshot } = this.getGlobalRemoteInfo(moduleInfo);
946
+ const { remoteSnapshot: globalRemoteSnapshot, globalSnapshot: globalSnapshotRes } = await this.hooks.lifecycle.loadSnapshot.emit({
947
+ options,
948
+ moduleInfo,
949
+ hostGlobalSnapshot,
950
+ remoteSnapshot,
951
+ globalSnapshot
952
+ });
953
+ // global snapshot includes manifest or module info includes manifest
954
+ if (globalRemoteSnapshot) {
955
+ if (isManifestProvider(globalRemoteSnapshot)) {
956
+ const moduleSnapshot = await this.getManifestJson(globalRemoteSnapshot.remoteEntry, moduleInfo, {});
957
+ // eslint-disable-next-line @typescript-eslint/no-shadow
958
+ const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo(_extends$1({}, moduleInfo, {
959
+ // The global remote may be overridden
960
+ // Therefore, set the snapshot key to the global address of the actual request
961
+ entry: globalRemoteSnapshot.remoteEntry
962
+ }), moduleSnapshot);
963
+ return {
964
+ remoteSnapshot: moduleSnapshot,
965
+ globalSnapshot: globalSnapshotRes
966
+ };
967
+ } else {
968
+ const { remoteSnapshot: remoteSnapshotRes } = await this.hooks.lifecycle.loadRemoteSnapshot.emit({
969
+ options: this.HostInstance.options,
970
+ moduleInfo,
971
+ remoteSnapshot: globalRemoteSnapshot,
972
+ from: 'global'
973
+ });
974
+ return {
975
+ remoteSnapshot: remoteSnapshotRes,
976
+ globalSnapshot: globalSnapshotRes
977
+ };
978
+ }
979
+ } else {
980
+ if (isRemoteInfoWithEntry(moduleInfo)) {
981
+ // get from manifest.json and merge remote info from remote server
982
+ const moduleSnapshot = await this.getManifestJson(moduleInfo.entry, moduleInfo, {});
983
+ // eslint-disable-next-line @typescript-eslint/no-shadow
984
+ const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo(moduleInfo, moduleSnapshot);
985
+ const { remoteSnapshot: remoteSnapshotRes } = await this.hooks.lifecycle.loadRemoteSnapshot.emit({
986
+ options: this.HostInstance.options,
987
+ moduleInfo,
988
+ remoteSnapshot: moduleSnapshot,
989
+ from: 'global'
990
+ });
991
+ return {
992
+ remoteSnapshot: remoteSnapshotRes,
993
+ globalSnapshot: globalSnapshotRes
994
+ };
995
+ } else {
996
+ error(`
997
+ Cannot get remoteSnapshot with the name: '${moduleInfo.name}', version: '${moduleInfo.version}' from __FEDERATION__.moduleInfo. The following reasons may be causing the problem:\n
998
+ 1. The Deploy platform did not deliver the correct data. You can use __FEDERATION__.moduleInfo to check the remoteInfo.\n
999
+ 2. The remote '${moduleInfo.name}' version '${moduleInfo.version}' is not released.\n
1000
+ The transformed module info: ${JSON.stringify(globalSnapshotRes)}
1001
+ `);
1002
+ }
1003
+ }
1004
+ }
1005
+ getGlobalRemoteInfo(moduleInfo) {
1006
+ const hostGlobalSnapshot = getGlobalSnapshotInfoByModuleInfo({
1007
+ name: this.HostInstance.options.name,
1008
+ version: this.HostInstance.options.version
1009
+ });
1010
+ // get remote detail info from global
1011
+ const globalRemoteInfo = hostGlobalSnapshot && 'remotesInfo' in hostGlobalSnapshot && hostGlobalSnapshot.remotesInfo && getInfoWithoutType(hostGlobalSnapshot.remotesInfo, moduleInfo.name).value;
1012
+ if (globalRemoteInfo && globalRemoteInfo.matchedVersion) {
1013
+ return {
1014
+ hostGlobalSnapshot,
1015
+ globalSnapshot: getGlobalSnapshot(),
1016
+ remoteSnapshot: getGlobalSnapshotInfoByModuleInfo({
1017
+ name: moduleInfo.name,
1018
+ version: globalRemoteInfo.matchedVersion
1019
+ })
1020
+ };
1021
+ }
1022
+ return {
1023
+ hostGlobalSnapshot: undefined,
1024
+ globalSnapshot: getGlobalSnapshot(),
1025
+ remoteSnapshot: getGlobalSnapshotInfoByModuleInfo({
1026
+ name: moduleInfo.name,
1027
+ version: 'version' in moduleInfo ? moduleInfo.version : undefined
1028
+ })
1029
+ };
1030
+ }
1031
+ async getManifestJson(manifestUrl, moduleInfo, extraOptions) {
1032
+ const getManifest = async ()=>{
1033
+ let manifestJson = this.manifestCache.get(manifestUrl);
1034
+ if (manifestJson) {
1035
+ return manifestJson;
1036
+ }
1037
+ try {
1038
+ let res = await this.loaderHook.lifecycle.fetch.emit(manifestUrl, {});
1039
+ if (!res || !(res instanceof Response)) {
1040
+ res = await fetch(manifestUrl, {});
1041
+ }
1042
+ manifestJson = await res.json();
1043
+ assert(manifestJson.metaData && manifestJson.exposes && manifestJson.shared, `${manifestUrl} is not a federation manifest`);
1044
+ this.manifestCache.set(manifestUrl, manifestJson);
1045
+ return manifestJson;
1046
+ } catch (err) {
1047
+ error(`Failed to get manifestJson for ${moduleInfo.name}. The manifest URL is ${manifestUrl}. Please ensure that the manifestUrl is accessible.
1048
+ \n Error message:
1049
+ \n ${err}`);
1050
+ }
1051
+ };
1052
+ const asyncLoadProcess = async ()=>{
1053
+ const manifestJson = await getManifest();
1054
+ const remoteSnapshot = generateSnapshotFromManifest(manifestJson, {
1055
+ version: manifestUrl
1056
+ });
1057
+ const { remoteSnapshot: remoteSnapshotRes } = await this.hooks.lifecycle.loadRemoteSnapshot.emit({
1058
+ options: this.HostInstance.options,
1059
+ moduleInfo,
1060
+ manifestJson,
1061
+ remoteSnapshot,
1062
+ manifestUrl,
1063
+ from: 'manifest'
1064
+ });
1065
+ return remoteSnapshotRes;
1066
+ };
1067
+ if (!this.manifestLoading[manifestUrl]) {
1068
+ this.manifestLoading[manifestUrl] = asyncLoadProcess().then((res)=>res);
1069
+ }
1070
+ return this.manifestLoading[manifestUrl];
1071
+ }
1072
+ constructor(HostInstance){
1073
+ this.loadingHostSnapshot = null;
1074
+ this.manifestCache = new Map();
1075
+ this.hooks = new PluginSystem({
1076
+ beforeLoadRemoteSnapshot: new AsyncHook('beforeLoadRemoteSnapshot'),
1077
+ loadSnapshot: new AsyncWaterfallHook('loadGlobalSnapshot'),
1078
+ loadRemoteSnapshot: new AsyncWaterfallHook('loadRemoteSnapshot')
1079
+ });
1080
+ this.manifestLoading = Global.__FEDERATION__.__MANIFEST_LOADING__;
1081
+ this.HostInstance = HostInstance;
1082
+ this.loaderHook = HostInstance.loaderHook;
1083
+ }
1084
+ }
1085
+
1086
+ function _extends() {
1087
+ _extends = Object.assign || function(target) {
1088
+ for(var i = 1; i < arguments.length; i++){
1089
+ var source = arguments[i];
1090
+ for(var key in source){
1091
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1092
+ target[key] = source[key];
1093
+ }
1094
+ }
1095
+ }
1096
+ return target;
1097
+ };
1098
+ return _extends.apply(this, arguments);
1099
+ }
1100
+ function _object_without_properties_loose(source, excluded) {
1101
+ if (source == null) return {};
1102
+ var target = {};
1103
+ var sourceKeys = Object.keys(source);
1104
+ var key, i;
1105
+ for(i = 0; i < sourceKeys.length; i++){
1106
+ key = sourceKeys[i];
1107
+ if (excluded.indexOf(key) >= 0) continue;
1108
+ target[key] = source[key];
1109
+ }
1110
+ return target;
1111
+ }
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;
1125
+ }
1126
+ async loadShare(pkgName, extraOptions) {
1127
+ // This function performs the following steps:
1128
+ // 1. Checks if the currently loaded share already exists, if not, it throws an error
1129
+ // 2. Searches globally for a matching share, if found, it uses it directly
1130
+ // 3. If not found, it retrieves it from the current share and stores the obtained share globally.
1131
+ const shareInfo = getTargetSharedOptions({
1132
+ pkgName,
1133
+ extraOptions,
1134
+ shareInfos: this.options.shared
1135
+ });
1136
+ if (shareInfo == null ? void 0 : shareInfo.scope) {
1137
+ await Promise.all(shareInfo.scope.map(async (shareScope)=>{
1138
+ await Promise.all(this.initializeSharing(shareScope, shareInfo.strategy));
1139
+ return;
1140
+ }));
1141
+ }
1142
+ const loadShareRes = await this.hooks.lifecycle.beforeLoadShare.emit({
1143
+ pkgName,
1144
+ shareInfo,
1145
+ shared: this.options.shared,
1146
+ origin: this
1147
+ });
1148
+ const { shareInfo: shareInfoRes } = loadShareRes;
1149
+ // 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`);
1151
+ // Retrieve from cache
1152
+ const registeredShared = getRegisteredShare(this.shareScopeMap, pkgName, shareInfoRes, this.hooks.lifecycle.resolveShare);
1153
+ const addUseIn = (shared)=>{
1154
+ if (!shared.useIn) {
1155
+ shared.useIn = [];
1156
+ }
1157
+ addUniqueItem(shared.useIn, this.options.name);
1158
+ };
1159
+ if (registeredShared && registeredShared.lib) {
1160
+ addUseIn(registeredShared);
1161
+ return registeredShared.lib;
1162
+ } else if (registeredShared && registeredShared.loading && !registeredShared.loaded) {
1163
+ const factory = await registeredShared.loading;
1164
+ registeredShared.loaded = true;
1165
+ if (!registeredShared.lib) {
1166
+ registeredShared.lib = factory;
1167
+ }
1168
+ addUseIn(registeredShared);
1169
+ return factory;
1170
+ } else if (registeredShared) {
1171
+ const asyncLoadProcess = async ()=>{
1172
+ const factory = await registeredShared.get();
1173
+ shareInfoRes.lib = factory;
1174
+ shareInfoRes.loaded = true;
1175
+ addUseIn(shareInfoRes);
1176
+ const gShared = getRegisteredShare(this.shareScopeMap, pkgName, shareInfoRes, this.hooks.lifecycle.resolveShare);
1177
+ if (gShared) {
1178
+ gShared.lib = factory;
1179
+ gShared.loaded = true;
1180
+ }
1181
+ return factory;
1182
+ };
1183
+ const loading = asyncLoadProcess();
1184
+ this.setShared({
1185
+ pkgName,
1186
+ loaded: false,
1187
+ shared: registeredShared,
1188
+ from: this.options.name,
1189
+ lib: null,
1190
+ loading
1191
+ });
1192
+ return loading;
1193
+ } else {
1194
+ if (extraOptions == null ? void 0 : extraOptions.customShareInfo) {
1195
+ return false;
1196
+ }
1197
+ const asyncLoadProcess = async ()=>{
1198
+ const factory = await shareInfoRes.get();
1199
+ shareInfoRes.lib = factory;
1200
+ shareInfoRes.loaded = true;
1201
+ addUseIn(shareInfoRes);
1202
+ const gShared = getRegisteredShare(this.shareScopeMap, pkgName, shareInfoRes, this.hooks.lifecycle.resolveShare);
1203
+ if (gShared) {
1204
+ gShared.lib = factory;
1205
+ gShared.loaded = true;
1206
+ }
1207
+ return factory;
1208
+ };
1209
+ const loading = asyncLoadProcess();
1210
+ this.setShared({
1211
+ pkgName,
1212
+ loaded: false,
1213
+ shared: shareInfoRes,
1214
+ from: this.options.name,
1215
+ lib: null,
1216
+ loading
1217
+ });
1218
+ return loading;
1219
+ }
1220
+ }
1221
+ // 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
+ // 1. If the loaded shared already exists globally, then it will be reused
1223
+ // 2. If lib exists in local shared, it will be used directly
1224
+ // 3. If the local get returns something other than Promise, then it will be used directly
1225
+ loadShareSync(pkgName, extraOptions) {
1226
+ const shareInfo = getTargetSharedOptions({
1227
+ pkgName,
1228
+ extraOptions,
1229
+ shareInfos: this.options.shared
1230
+ });
1231
+ if (shareInfo == null ? void 0 : shareInfo.scope) {
1232
+ shareInfo.scope.forEach((shareScope)=>{
1233
+ this.initializeSharing(shareScope, shareInfo.strategy);
1234
+ });
1235
+ }
1236
+ const registeredShared = getRegisteredShare(this.shareScopeMap, pkgName, shareInfo, this.hooks.lifecycle.resolveShare);
1237
+ const addUseIn = (shared)=>{
1238
+ if (!shared.useIn) {
1239
+ shared.useIn = [];
1240
+ }
1241
+ addUniqueItem(shared.useIn, this.options.name);
1242
+ };
1243
+ if (registeredShared) {
1244
+ if (typeof registeredShared.lib === 'function') {
1245
+ addUseIn(registeredShared);
1246
+ if (!registeredShared.loaded) {
1247
+ registeredShared.loaded = true;
1248
+ if (registeredShared.from === this.options.name) {
1249
+ shareInfo.loaded = true;
1250
+ }
1251
+ }
1252
+ return registeredShared.lib;
1253
+ }
1254
+ if (typeof registeredShared.get === 'function') {
1255
+ const module = registeredShared.get();
1256
+ if (!(module instanceof Promise)) {
1257
+ addUseIn(registeredShared);
1258
+ this.setShared({
1259
+ pkgName,
1260
+ loaded: true,
1261
+ from: this.options.name,
1262
+ lib: module,
1263
+ shared: registeredShared
1264
+ });
1265
+ return module;
1266
+ }
1267
+ }
1268
+ }
1269
+ if (shareInfo.lib) {
1270
+ if (!shareInfo.loaded) {
1271
+ shareInfo.loaded = true;
1272
+ }
1273
+ return shareInfo.lib;
1274
+ }
1275
+ if (shareInfo.get) {
1276
+ const module = shareInfo.get();
1277
+ if (module instanceof Promise) {
1278
+ throw new Error(`
1279
+ The loadShareSync function was unable to load ${pkgName}. The ${pkgName} could not be found in ${this.options.name}.
1280
+ Possible reasons for failure: \n
1281
+ 1. The ${pkgName} share was registered with the 'get' attribute, but loadShare was not used beforehand.\n
1282
+ 2. The ${pkgName} share was not registered with the 'lib' attribute.\n
1283
+ `);
1284
+ }
1285
+ shareInfo.lib = module;
1286
+ this.setShared({
1287
+ pkgName,
1288
+ loaded: true,
1289
+ from: this.options.name,
1290
+ lib: shareInfo.lib,
1291
+ shared: shareInfo
1292
+ });
1293
+ return shareInfo.lib;
1294
+ }
1295
+ throw new Error(`
1296
+ The loadShareSync function was unable to load ${pkgName}. The ${pkgName} could not be found in ${this.options.name}.
1297
+ Possible reasons for failure: \n
1298
+ 1. The ${pkgName} share was registered with the 'get' attribute, but loadShare was not used beforehand.\n
1299
+ 2. The ${pkgName} share was not registered with the 'lib' attribute.\n
1300
+ `);
1301
+ }
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
1310
+ });
1311
+ module.remoteEntryExports = container;
1312
+ this.moduleCache.set(name, module);
1313
+ return module;
1314
+ }
1315
+ async _getRemoteModuleAndOptions(id) {
1316
+ const loadRemoteArgs = await this.hooks.lifecycle.beforeRequest.emit({
1317
+ id,
1318
+ options: this.options,
1319
+ origin: this
1320
+ });
1321
+ const { id: idRes } = loadRemoteArgs;
1322
+ const remoteSplitInfo = matchRemoteWithNameAndExpose(this.options.remotes, idRes);
1323
+ assert(remoteSplitInfo, `
1324
+ Unable to locate ${idRes} in ${this.options.name}. Potential reasons for failure include:\n
1325
+ 1. ${idRes} was not included in the 'remotes' parameter of ${this.options.name || 'the host'}.\n
1326
+ 2. ${idRes} could not be found in the 'remotes' of ${this.options.name} with either 'name' or 'alias' attributes.
1327
+ 3. ${idRes} is not online, injected, or loaded.
1328
+ 4. ${idRes} cannot be accessed on the expected.
1329
+ 5. The 'beforeRequest' hook was provided but did not return the correct 'remoteInfo' when attempting to load ${idRes}.
1330
+ `);
1331
+ const { remote: rawRemote } = remoteSplitInfo;
1332
+ const remoteInfo = getRemoteInfo(rawRemote);
1333
+ const matchInfo = await this.hooks.lifecycle.afterResolve.emit(_extends({
1334
+ id: idRes
1335
+ }, remoteSplitInfo, {
1336
+ options: this.options,
1337
+ origin: this,
1338
+ remoteInfo
1339
+ }));
1340
+ const { remote, expose } = matchInfo;
1341
+ assert(remote && expose, `The 'beforeRequest' hook was executed, but it failed to return the correct 'remote' and 'expose' values while loading ${idRes}.`);
1342
+ let module = this.moduleCache.get(remote.name);
1343
+ const moduleOptions = {
1344
+ host: this,
1345
+ remoteInfo
1346
+ };
1347
+ if (!module) {
1348
+ module = new Module(moduleOptions);
1349
+ this.moduleCache.set(remote.name, module);
1350
+ }
1351
+ return {
1352
+ module,
1353
+ moduleOptions,
1354
+ remoteMatchInfo: matchInfo
1355
+ };
1356
+ }
1357
+ // eslint-disable-next-line max-lines-per-function
1358
+ // eslint-disable-next-line @typescript-eslint/member-ordering
1359
+ async loadRemote(id, options) {
1360
+ try {
1361
+ const { loadFactory = true } = options || {
1362
+ loadFactory: true
1363
+ };
1364
+ // 1. Validate the parameters of the retrieved module. There are two module request methods: pkgName + expose and alias + expose.
1365
+ // 2. Request the snapshot information of the current host and globally store the obtained snapshot information. The retrieved module information is partially offline and partially online. The online module information will retrieve the modules used online.
1366
+ // 3. Retrieve the detailed information of the current module from global (remoteEntry address, expose resource address)
1367
+ // 4. After retrieving remoteEntry, call the init of the module, and then retrieve the exported content of the module through get
1368
+ // id: pkgName(@federation/app1) + expose(button) = @federation/app1/button
1369
+ // id: alias(app1) + expose(button) = app1/button
1370
+ // id: alias(app1/utils) + expose(loadash/sort) = app1/utils/loadash/sort
1371
+ const { module, moduleOptions, remoteMatchInfo } = await this._getRemoteModuleAndOptions(id);
1372
+ const { pkgNameOrAlias, remote, expose, id: idRes } = remoteMatchInfo;
1373
+ const moduleOrFactory = await module.get(expose, options);
1374
+ const moduleWrapper = await this.hooks.lifecycle.onLoad.emit({
1375
+ id: idRes,
1376
+ pkgNameOrAlias,
1377
+ expose,
1378
+ exposeModule: loadFactory ? moduleOrFactory : undefined,
1379
+ exposeModuleFactory: loadFactory ? undefined : moduleOrFactory,
1380
+ remote,
1381
+ options: moduleOptions,
1382
+ moduleInstance: module,
1383
+ origin: this
1384
+ });
1385
+ if (typeof moduleWrapper === 'function') {
1386
+ return moduleWrapper;
1387
+ }
1388
+ return moduleOrFactory;
1389
+ } catch (error) {
1390
+ const { from = 'runtime' } = options || {
1391
+ from: 'runtime'
1392
+ };
1393
+ const failOver = await this.hooks.lifecycle.errorLoadRemote.emit({
1394
+ id,
1395
+ error,
1396
+ from,
1397
+ origin: this
1398
+ });
1399
+ if (!failOver) {
1400
+ throw error;
1401
+ }
1402
+ return failOver;
1403
+ }
1404
+ }
1405
+ // eslint-disable-next-line @typescript-eslint/member-ordering
1406
+ async preloadRemote(preloadOptions) {
1407
+ await this.hooks.lifecycle.beforePreloadRemote.emit({
1408
+ preloadOptions,
1409
+ options: this.options,
1410
+ origin: this
1411
+ });
1412
+ const preloadOps = formatPreloadArgs(this.options.remotes, preloadOptions);
1413
+ await Promise.all(preloadOps.map(async (ops)=>{
1414
+ const { remote } = ops;
1415
+ const remoteInfo = getRemoteInfo(remote);
1416
+ const { globalSnapshot, remoteSnapshot } = await this.snapshotHandler.loadRemoteSnapshotInfo(remote);
1417
+ const assets = await this.hooks.lifecycle.generatePreloadAssets.emit({
1418
+ origin: this,
1419
+ preloadOptions: ops,
1420
+ remote,
1421
+ remoteInfo,
1422
+ globalSnapshot,
1423
+ remoteSnapshot
1424
+ });
1425
+ if (!assets) {
1426
+ return;
1427
+ }
1428
+ preloadAssets(remoteInfo, this, assets);
1429
+ }));
1430
+ }
1431
+ /**
1432
+ * This function initializes the sharing sequence (executed only once per share scope).
1433
+ * It accepts one argument, the name of the share scope.
1434
+ * If the share scope does not exist, it creates one.
1435
+ */ // eslint-disable-next-line @typescript-eslint/member-ordering
1436
+ initializeSharing(shareScopeName = DEFAULT_SCOPE, strategy) {
1437
+ const shareScope = this.shareScopeMap;
1438
+ const hostName = this.options.name;
1439
+ // Creates a new share scope if necessary
1440
+ if (!shareScope[shareScopeName]) {
1441
+ shareScope[shareScopeName] = {};
1442
+ }
1443
+ // Executes all initialization snippets from all accessible modules
1444
+ const scope = shareScope[shareScopeName];
1445
+ const register = (name, shared)=>{
1446
+ var _activeVersion_shareConfig;
1447
+ const { version, eager } = shared;
1448
+ scope[name] = scope[name] || {};
1449
+ const versions = scope[name];
1450
+ const activeVersion = versions[version];
1451
+ const activeVersionEager = Boolean(activeVersion && (activeVersion.eager || ((_activeVersion_shareConfig = activeVersion.shareConfig) == null ? void 0 : _activeVersion_shareConfig.eager)));
1452
+ if (!activeVersion || activeVersion.strategy !== 'loaded-first' && !activeVersion.loaded && (Boolean(!eager) !== !activeVersionEager ? eager : hostName > activeVersion.from)) {
1453
+ versions[version] = shared;
1454
+ }
1455
+ };
1456
+ const promises = [];
1457
+ const initFn = (mod)=>mod && mod.init && mod.init(shareScope[shareScopeName]);
1458
+ const initRemoteModule = async (key)=>{
1459
+ const { module } = await this._getRemoteModuleAndOptions(key);
1460
+ if (module.getEntry) {
1461
+ const entry = await module.getEntry();
1462
+ if (!module.inited) {
1463
+ initFn(entry);
1464
+ module.inited = true;
1465
+ }
1466
+ }
1467
+ };
1468
+ Object.keys(this.options.shared).forEach((shareName)=>{
1469
+ const sharedArr = this.options.shared[shareName];
1470
+ sharedArr.forEach((shared)=>{
1471
+ if (shared.scope.includes(shareScopeName)) {
1472
+ register(shareName, shared);
1473
+ }
1474
+ });
1475
+ });
1476
+ if (strategy === 'version-first') {
1477
+ this.options.remotes.forEach((remote)=>{
1478
+ if (remote.shareScope === shareScopeName) {
1479
+ promises.push(initRemoteModule(remote.name));
1480
+ }
1481
+ });
1482
+ }
1483
+ return promises;
1484
+ }
1485
+ initShareScopeMap(scopeName, shareScope) {
1486
+ this.shareScopeMap[scopeName] = shareScope;
1487
+ this.hooks.lifecycle.initContainerShareScopeMap.emit({
1488
+ shareScope,
1489
+ options: this.options,
1490
+ origin: this
1491
+ });
1492
+ }
1493
+ formatOptions(globalOptions, userOptions) {
1494
+ const formatShareOptions = formatShareConfigs(userOptions.shared || {}, userOptions.name);
1495
+ const shared = _extends({}, globalOptions.shared);
1496
+ Object.keys(formatShareOptions).forEach((shareKey)=>{
1497
+ if (!shared[shareKey]) {
1498
+ shared[shareKey] = formatShareOptions[shareKey];
1499
+ } else {
1500
+ formatShareOptions[shareKey].forEach((newUserSharedOptions)=>{
1501
+ const isSameVersion = shared[shareKey].find((sharedVal)=>sharedVal.version === newUserSharedOptions.version);
1502
+ if (!isSameVersion) {
1503
+ shared[shareKey].push(newUserSharedOptions);
1504
+ }
1505
+ });
1506
+ }
1507
+ });
1508
+ const { userOptions: userOptionsRes, options: globalOptionsRes } = this.hooks.lifecycle.beforeInit.emit({
1509
+ origin: this,
1510
+ userOptions,
1511
+ options: globalOptions,
1512
+ shareInfo: shared
1513
+ });
1514
+ const userRemotes = userOptionsRes.remotes || [];
1515
+ const remotes = userRemotes.reduce((res, remote)=>{
1516
+ this.registerRemote(remote, res, {
1517
+ force: false
1518
+ });
1519
+ return res;
1520
+ }, globalOptionsRes.remotes);
1521
+ // register shared in shareScopeMap
1522
+ const sharedKeys = Object.keys(formatShareOptions);
1523
+ sharedKeys.forEach((sharedKey)=>{
1524
+ const sharedVals = formatShareOptions[sharedKey];
1525
+ sharedVals.forEach((sharedVal)=>{
1526
+ const registeredShared = getRegisteredShare(this.shareScopeMap, sharedKey, sharedVal, this.hooks.lifecycle.resolveShare);
1527
+ if (!registeredShared && sharedVal && sharedVal.lib) {
1528
+ this.setShared({
1529
+ pkgName: sharedKey,
1530
+ lib: sharedVal.lib,
1531
+ get: sharedVal.get,
1532
+ loaded: true,
1533
+ shared: sharedVal,
1534
+ from: userOptions.name
1535
+ });
1536
+ }
1537
+ });
1538
+ });
1539
+ const plugins = [
1540
+ ...globalOptionsRes.plugins
1541
+ ];
1542
+ if (userOptionsRes.plugins) {
1543
+ userOptionsRes.plugins.forEach((plugin)=>{
1544
+ if (!plugins.includes(plugin)) {
1545
+ plugins.push(plugin);
1546
+ }
1547
+ });
1548
+ }
1549
+ const optionsRes = _extends({}, globalOptions, userOptions, {
1550
+ plugins,
1551
+ remotes,
1552
+ shared
1553
+ });
1554
+ this.hooks.lifecycle.init.emit({
1555
+ origin: this,
1556
+ options: optionsRes
1557
+ });
1558
+ return optionsRes;
1559
+ }
1560
+ registerPlugins(plugins) {
1561
+ const pluginRes = registerPlugins$1(plugins, [
1562
+ this.hooks,
1563
+ this.snapshotHandler.hooks,
1564
+ this.loaderHook
1565
+ ]);
1566
+ // Merge plugin
1567
+ this.options.plugins = this.options.plugins.reduce((res, plugin)=>{
1568
+ if (!plugin) return res;
1569
+ if (res && !res.find((item)=>item.name === plugin.name)) {
1570
+ res.push(plugin);
1571
+ }
1572
+ return res;
1573
+ }, pluginRes || []);
1574
+ }
1575
+ setShared({ pkgName, shared, from, lib, loading, loaded, get }) {
1576
+ const { version, scope = 'default' } = shared, shareInfo = _object_without_properties_loose(shared, [
1577
+ "version",
1578
+ "scope"
1579
+ ]);
1580
+ const scopes = Array.isArray(scope) ? scope : [
1581
+ scope
1582
+ ];
1583
+ scopes.forEach((sc)=>{
1584
+ if (!this.shareScopeMap[sc]) {
1585
+ this.shareScopeMap[sc] = {};
1586
+ }
1587
+ if (!this.shareScopeMap[sc][pkgName]) {
1588
+ this.shareScopeMap[sc][pkgName] = {};
1589
+ }
1590
+ if (this.shareScopeMap[sc][pkgName][version]) {
1591
+ return;
1592
+ }
1593
+ this.shareScopeMap[sc][pkgName][version] = _extends({
1594
+ version,
1595
+ scope: [
1596
+ 'default'
1597
+ ]
1598
+ }, shareInfo, {
1599
+ lib,
1600
+ loaded,
1601
+ loading
1602
+ });
1603
+ if (get) {
1604
+ this.shareScopeMap[sc][pkgName][version].get = get;
1605
+ }
1606
+ });
1607
+ }
1608
+ removeRemote(remote) {
1609
+ const { name } = remote;
1610
+ const remoteIndex = this.options.remotes.findIndex((item)=>item.name === name);
1611
+ if (remoteIndex !== -1) {
1612
+ this.options.remotes.splice(remoteIndex, 1);
1613
+ }
1614
+ const loadedModule = this.moduleCache.get(remote.name);
1615
+ if (loadedModule) {
1616
+ const key = loadedModule.remoteInfo.entryGlobalName;
1617
+ if (globalThis[key]) {
1618
+ delete globalThis[key];
1619
+ }
1620
+ const remoteEntryUniqueKey = getRemoteEntryUniqueKey(loadedModule.remoteInfo);
1621
+ if (globalLoading[remoteEntryUniqueKey]) {
1622
+ delete globalLoading[remoteEntryUniqueKey];
1623
+ }
1624
+ this.moduleCache.delete(remote.name);
1625
+ }
1626
+ }
1627
+ registerRemote(remote, targetRemotes, options) {
1628
+ const normalizeRemote = ()=>{
1629
+ if (remote.alias) {
1630
+ // Validate if alias equals the prefix of remote.name and remote.alias, if so, throw an error
1631
+ // As multi-level path references cannot guarantee unique names, alias being a prefix of remote.name is not supported
1632
+ const findEqual = targetRemotes.find((item)=>{
1633
+ var _item_alias;
1634
+ return remote.alias && (item.name.startsWith(remote.alias) || ((_item_alias = item.alias) == null ? void 0 : _item_alias.startsWith(remote.alias)));
1635
+ });
1636
+ assert(!findEqual, `The alias ${remote.alias} of remote ${remote.name} is not allowed to be the prefix of ${findEqual && findEqual.name} name or alias`);
1637
+ }
1638
+ // Set the remote entry to a complete path
1639
+ if ('entry' in remote) {
1640
+ if (isBrowserEnv() && !remote.entry.startsWith('http')) {
1641
+ remote.entry = new URL(remote.entry, window.location.origin).href;
1642
+ }
1643
+ }
1644
+ if (!remote.shareScope) {
1645
+ remote.shareScope = DEFAULT_SCOPE;
1646
+ }
1647
+ if (!remote.type) {
1648
+ remote.type = DEFAULT_REMOTE_TYPE;
1649
+ }
1650
+ };
1651
+ const registeredRemote = targetRemotes.find((item)=>item.name === remote.name);
1652
+ if (!registeredRemote) {
1653
+ normalizeRemote();
1654
+ targetRemotes.push(remote);
1655
+ } else {
1656
+ const messages = [
1657
+ `The remote "${remote.name}" is already registered.`,
1658
+ (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".'
1659
+ ];
1660
+ if (options == null ? void 0 : options.force) {
1661
+ // remove registered remote
1662
+ this.removeRemote(registeredRemote);
1663
+ normalizeRemote();
1664
+ targetRemotes.push(remote);
1665
+ }
1666
+ warn(messages.join(' '));
1667
+ }
1668
+ }
1669
+ registerRemotes(remotes, options) {
1670
+ remotes.forEach((remote)=>{
1671
+ this.registerRemote(remote, this.options.remotes, {
1672
+ force: options == null ? void 0 : options.force
1673
+ });
1674
+ });
1675
+ }
1676
+ constructor(userOptions){
1677
+ this.hooks = new PluginSystem({
1678
+ beforeInit: new SyncWaterfallHook('beforeInit'),
1679
+ init: new SyncHook(),
1680
+ beforeRequest: new AsyncWaterfallHook('beforeRequest'),
1681
+ afterResolve: new AsyncWaterfallHook('afterResolve'),
1682
+ // maybe will change, temporarily for internal use only
1683
+ beforeInitContainer: new AsyncWaterfallHook('beforeInitContainer'),
1684
+ // maybe will change, temporarily for internal use only
1685
+ initContainerShareScopeMap: new AsyncWaterfallHook('initContainer'),
1686
+ // maybe will change, temporarily for internal use only
1687
+ initContainer: new AsyncWaterfallHook('initContainer'),
1688
+ onLoad: new AsyncHook('onLoad'),
1689
+ handlePreloadModule: new SyncHook('handlePreloadModule'),
1690
+ errorLoadRemote: new AsyncHook('errorLoadRemote'),
1691
+ beforeLoadShare: new AsyncWaterfallHook('beforeLoadShare'),
1692
+ // not used yet
1693
+ loadShare: new AsyncHook(),
1694
+ resolveShare: new SyncWaterfallHook('resolveShare'),
1695
+ beforePreloadRemote: new AsyncHook(),
1696
+ generatePreloadAssets: new AsyncHook('generatePreloadAssets'),
1697
+ // not used yet
1698
+ afterPreloadRemote: new AsyncHook()
1699
+ });
1700
+ this.version = "0.1.7";
1701
+ this.moduleCache = new Map();
1702
+ this.loaderHook = new PluginSystem({
1703
+ // FIXME: may not be suitable , not open to the public yet
1704
+ getModuleInfo: new SyncHook(),
1705
+ createScript: new SyncHook(),
1706
+ createLink: new SyncHook(),
1707
+ // only work for manifest , so not open to the public yet
1708
+ fetch: new AsyncHook('fetch')
1709
+ });
1710
+ // TODO: Validate the details of the options
1711
+ // Initialize options with default values
1712
+ const defaultOptions = {
1713
+ id: getBuilderId(),
1714
+ name: userOptions.name,
1715
+ plugins: [
1716
+ snapshotPlugin(),
1717
+ generatePreloadAssetsPlugin()
1718
+ ],
1719
+ remotes: [],
1720
+ shared: {},
1721
+ inBrowser: isBrowserEnv()
1722
+ };
1723
+ this.name = userOptions.name;
1724
+ this.options = defaultOptions;
1725
+ this.shareScopeMap = {};
1726
+ this._setGlobalShareScopeMap();
1727
+ this.snapshotHandler = new SnapshotHandler(this);
1728
+ this.registerPlugins([
1729
+ ...defaultOptions.plugins,
1730
+ ...userOptions.plugins || []
1731
+ ]);
1732
+ this.options = this.formatOptions(defaultOptions, userOptions);
1733
+ }
1734
+ }
1735
+
1736
+ let FederationInstance = null;
1737
+ function init(options) {
1738
+ // Retrieve the same instance with the same name
1739
+ const instance = getGlobalFederationInstance(options.name, options.version);
1740
+ if (!instance) {
1741
+ // Retrieve debug constructor
1742
+ const FederationConstructor = getGlobalFederationConstructor() || FederationHost;
1743
+ FederationInstance = new FederationConstructor(options);
1744
+ setGlobalFederationInstance(FederationInstance);
1745
+ return FederationInstance;
1746
+ } else {
1747
+ // Merge options
1748
+ instance.initOptions(options);
1749
+ if (!FederationInstance) {
1750
+ FederationInstance = instance;
1751
+ }
1752
+ return instance;
1753
+ }
1754
+ }
1755
+ function loadRemote(...args) {
1756
+ assert(FederationInstance, 'Please call init first');
1757
+ // eslint-disable-next-line prefer-spread
1758
+ return FederationInstance.loadRemote.apply(FederationInstance, args);
1759
+ }
1760
+ function loadShare(...args) {
1761
+ assert(FederationInstance, 'Please call init first');
1762
+ // eslint-disable-next-line prefer-spread
1763
+ return FederationInstance.loadShare.apply(FederationInstance, args);
1764
+ }
1765
+ function loadShareSync(...args) {
1766
+ assert(FederationInstance, 'Please call init first');
1767
+ // eslint-disable-next-line prefer-spread
1768
+ return FederationInstance.loadShareSync.apply(FederationInstance, args);
1769
+ }
1770
+ function preloadRemote(...args) {
1771
+ assert(FederationInstance, 'Please call init first');
1772
+ // eslint-disable-next-line prefer-spread
1773
+ return FederationInstance.preloadRemote.apply(FederationInstance, args);
1774
+ }
1775
+ function registerRemotes(...args) {
1776
+ assert(FederationInstance, 'Please call init first');
1777
+ // eslint-disable-next-line prefer-spread
1778
+ return FederationInstance.registerRemotes.apply(FederationInstance, args);
1779
+ }
1780
+ function registerPlugins(...args) {
1781
+ assert(FederationInstance, 'Please call init first');
1782
+ // eslint-disable-next-line prefer-spread
1783
+ return FederationInstance.registerPlugins.apply(FederationInstance, args);
1784
+ }
1785
+ // Inject for debug
1786
+ setGlobalFederationConstructor(FederationHost);
1787
+
1788
+ export { FederationHost, getRemoteEntry, getRemoteInfo, init, loadRemote, loadShare, loadShareSync, preloadRemote, registerPlugins, registerRemotes };