@sbee/vite-federation 0.0.1

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.mjs ADDED
@@ -0,0 +1,1261 @@
1
+ import path, { basename, dirname, extname, join, parse, posix, relative, resolve } from "path";
2
+ import { RolldownMagicString } from "rolldown";
3
+ //#region src/public.ts
4
+ var EXPOSES_MAP = /* @__PURE__ */ new Map();
5
+ var EXPOSES_KEY_MAP = /* @__PURE__ */ new Map();
6
+ var SHARED = "shared";
7
+ var DYNAMIC_LOADING_CSS = "dynamicLoadingCss";
8
+ var DYNAMIC_LOADING_CSS_PREFIX = "__v__css__";
9
+ var DEFAULT_ENTRY_FILENAME = "remoteEntry.js";
10
+ var EXTERNALS = [];
11
+ var builderInfo = {
12
+ builder: "rolldown",
13
+ version: "",
14
+ assetsDir: "",
15
+ isHost: false,
16
+ isRemote: false,
17
+ isShared: false
18
+ };
19
+ var parsedOptions = {
20
+ prodExpose: [],
21
+ prodRemote: [],
22
+ prodShared: [],
23
+ devShared: [],
24
+ devExpose: [],
25
+ devRemote: []
26
+ };
27
+ var devRemotes = [];
28
+ var prodRemotes = [];
29
+ var viteConfigResolved = { config: void 0 };
30
+ //#endregion
31
+ //#region src/utils/html.ts
32
+ var unaryTags = /* @__PURE__ */ new Set([
33
+ "link",
34
+ "meta",
35
+ "base"
36
+ ]);
37
+ function serializeTag({ tag, attrs, children }, indent = "") {
38
+ if (unaryTags.has(tag)) return `<${tag}${serializeAttrs(attrs)}>`;
39
+ else return `<${tag}${serializeAttrs(attrs)}>${serializeTags(children, incrementIndent(indent))}</${tag}>`;
40
+ }
41
+ function serializeTags(tags, indent = "") {
42
+ if (typeof tags === "string") return tags;
43
+ else if (tags && tags.length) return tags.map((tag) => `${indent}${serializeTag(tag, indent)}\n`).join("");
44
+ return "";
45
+ }
46
+ function serializeAttrs(attrs) {
47
+ let res = "";
48
+ for (const key in attrs) if (typeof attrs[key] === "boolean") res += attrs[key] ? ` ${key}` : ``;
49
+ else res += ` ${key}="${escapeHtml(attrs[key])}"`;
50
+ return res;
51
+ }
52
+ function incrementIndent(indent = "") {
53
+ return `${indent}${indent[0] === " " ? " " : " "}`;
54
+ }
55
+ var matchHtmlRegExp = /["'&<>]/;
56
+ function escapeHtml(string) {
57
+ const str = "" + string;
58
+ const match = matchHtmlRegExp.exec(str);
59
+ if (!match) return str;
60
+ let escape;
61
+ let html = "";
62
+ let index = 0;
63
+ let lastIndex = 0;
64
+ for (index = match.index; index < str.length; index++) {
65
+ switch (str.charCodeAt(index)) {
66
+ case 34:
67
+ escape = "&quot;";
68
+ break;
69
+ case 38:
70
+ escape = "&amp;";
71
+ break;
72
+ case 39:
73
+ escape = "&#39;";
74
+ break;
75
+ case 60:
76
+ escape = "&lt;";
77
+ break;
78
+ case 62:
79
+ escape = "&gt;";
80
+ break;
81
+ default: continue;
82
+ }
83
+ if (lastIndex !== index) html += str.substring(lastIndex, index);
84
+ lastIndex = index + 1;
85
+ html += escape;
86
+ }
87
+ return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
88
+ }
89
+ var headInjectRE = /([ \t]*)<\/head>/i;
90
+ var headPrependInjectRE = /([ \t]*)<head[^>]*>/i;
91
+ var htmlPrependInjectRE = /([ \t]*)<html[^>]*>/i;
92
+ var bodyPrependInjectRE = /([ \t]*)<body[^>]*>/i;
93
+ var doctypePrependInjectRE = /<!doctype html>/i;
94
+ var toPreloadTag = (href) => ({
95
+ tag: "link",
96
+ attrs: {
97
+ rel: "modulepreload",
98
+ crossorigin: true,
99
+ href
100
+ }
101
+ });
102
+ function injectToHead(html, tags, prepend = false) {
103
+ if (tags.length === 0) return html;
104
+ if (prepend) {
105
+ if (headPrependInjectRE.test(html)) return html.replace(headPrependInjectRE, (match, p1) => `${match}\n${serializeTags(tags, incrementIndent(p1))}`);
106
+ } else {
107
+ if (headInjectRE.test(html)) return html.replace(headInjectRE, (match, p1) => `${serializeTags(tags, incrementIndent(p1))}${match}`);
108
+ if (bodyPrependInjectRE.test(html)) return html.replace(bodyPrependInjectRE, (match, p1) => `${serializeTags(tags, p1)}\n${match}`);
109
+ }
110
+ return prependInjectFallback(html, tags);
111
+ }
112
+ function prependInjectFallback(html, tags) {
113
+ if (htmlPrependInjectRE.test(html)) return html.replace(htmlPrependInjectRE, `$&\n${serializeTags(tags)}`);
114
+ if (doctypePrependInjectRE.test(html)) return html.replace(doctypePrependInjectRE, `$&\n${serializeTags(tags)}`);
115
+ return serializeTags(tags) + html;
116
+ }
117
+ //#endregion
118
+ //#region src/utils/index.ts
119
+ var MagicString = RolldownMagicString;
120
+ var SKIP_KEYS = /* @__PURE__ */ new Set([
121
+ "type",
122
+ "start",
123
+ "end",
124
+ "loc",
125
+ "span"
126
+ ]);
127
+ function walk(node, visitor) {
128
+ if (!node) return;
129
+ const enter = typeof visitor === "function" ? visitor : visitor.enter;
130
+ const leave = typeof visitor === "function" ? void 0 : visitor.leave;
131
+ enter?.(node);
132
+ for (const key of Object.keys(node)) {
133
+ if (SKIP_KEYS.has(key)) continue;
134
+ const child = node[key];
135
+ if (!child || typeof child !== "object") continue;
136
+ if (Array.isArray(child)) {
137
+ for (const item of child) if (item && typeof item === "object" && "type" in item) walk(item, visitor);
138
+ } else if ("type" in child) walk(child, visitor);
139
+ }
140
+ leave?.(node);
141
+ }
142
+ function parseSharedOptions(options) {
143
+ return parseOptions(options.shared || {}, (value, key) => ({
144
+ import: true,
145
+ shareScope: "default",
146
+ packagePath: key,
147
+ manuallyPackagePathSetting: false,
148
+ generate: true,
149
+ modulePreload: false
150
+ }), (value, key) => {
151
+ value.import = value.import ?? true;
152
+ value.shareScope = value.shareScope || "default";
153
+ value.packagePath = value.packagePath || key;
154
+ value.manuallyPackagePathSetting = value.packagePath !== key;
155
+ value.generate = value.generate ?? true;
156
+ value.modulePreload = value.modulePreload ?? false;
157
+ return value;
158
+ });
159
+ }
160
+ function parseExposeOptions(options) {
161
+ return parseOptions(options.exposes, (item) => {
162
+ return {
163
+ import: item,
164
+ name: void 0,
165
+ dontAppendStylesToHead: false
166
+ };
167
+ }, (item) => ({
168
+ import: item.import,
169
+ name: item.name || void 0,
170
+ dontAppendStylesToHead: item.dontAppendStylesToHead || false
171
+ }));
172
+ }
173
+ function parseRemoteOptions(options) {
174
+ return parseOptions(options.remotes ? options.remotes : {}, (item) => ({
175
+ external: Array.isArray(item) ? item : [item],
176
+ shareScope: options.shareScope || "default",
177
+ format: "esm",
178
+ from: "vite",
179
+ externalType: "url"
180
+ }), (item) => ({
181
+ external: Array.isArray(item.external) ? item.external : [item.external],
182
+ shareScope: item.shareScope || options.shareScope || "default",
183
+ format: item.format || "esm",
184
+ from: item.from ?? "vite",
185
+ externalType: item.externalType || "url"
186
+ }));
187
+ }
188
+ function parseOptions(options, normalizeSimple, normalizeOptions) {
189
+ if (!options) return [];
190
+ const list = [];
191
+ const array = (items) => {
192
+ for (const item of items) if (typeof item === "string") list.push([item, normalizeSimple(item, item)]);
193
+ else if (item && typeof item === "object") object(item);
194
+ else throw new Error("Unexpected options format");
195
+ };
196
+ const object = (obj) => {
197
+ for (const [key, value] of Object.entries(obj)) if (typeof value === "string" || Array.isArray(value)) list.push([key, normalizeSimple(value, key)]);
198
+ else list.push([key, normalizeOptions(value, key)]);
199
+ };
200
+ if (Array.isArray(options)) array(options);
201
+ else if (typeof options === "object") object(options);
202
+ else throw new Error("Unexpected options format");
203
+ return list;
204
+ }
205
+ var letterReg = /* @__PURE__ */ new RegExp("[0-9a-zA-Z]+");
206
+ function removeNonRegLetter(str, reg = letterReg) {
207
+ let needUpperCase = false;
208
+ const chars = [];
209
+ for (const c of str) if (reg.test(c)) {
210
+ chars.push(needUpperCase ? c.toUpperCase() : c);
211
+ needUpperCase = false;
212
+ } else needUpperCase = true;
213
+ return chars.join("");
214
+ }
215
+ function getModuleMarker(value, type) {
216
+ return type ? `__rf_${type}__${value}` : `__rf_placeholder__${value}`;
217
+ }
218
+ function normalizePath(id) {
219
+ return posix.normalize(id.replace(/\\/g, "/"));
220
+ }
221
+ function createRemotesMap(remotes) {
222
+ const createUrl = (remote) => {
223
+ const external = remote.config.external[0];
224
+ if (remote.config.externalType === "promise") return `()=>${external}`;
225
+ else return `'${external}'`;
226
+ };
227
+ return `const remotesMap = {
228
+ ${remotes.map((remote) => `'${remote.id}':{url:${createUrl(remote)},format:'${remote.config.format}',from:'${remote.config.from}'}`).join(",\n ")}
229
+ };`;
230
+ }
231
+ /**
232
+ * get file extname from url
233
+ * @param url
234
+ */
235
+ function getFileExtname(url) {
236
+ const fileNameAndParamArr = normalizePath(url).split("/");
237
+ const fileName = fileNameAndParamArr[fileNameAndParamArr.length - 1].split("?")[0];
238
+ return path.extname(fileName);
239
+ }
240
+ var REMOTE_FROM_PARAMETER = "remoteFrom";
241
+ var NAME_CHAR_REG = /* @__PURE__ */ new RegExp("[0-9a-zA-Z@_-]+");
242
+ //#endregion
243
+ //#region src/dev/expose-development.ts
244
+ function devExposePlugin(options) {
245
+ parsedOptions.devExpose = parseExposeOptions(options);
246
+ return { name: "sbee:expose-development" };
247
+ }
248
+ //#endregion
249
+ //#region src/dev/remote-development.ts
250
+ function devRemotePlugin(options) {
251
+ parsedOptions.devRemote = parseRemoteOptions(options);
252
+ for (const item of parsedOptions.devRemote) devRemotes.push({
253
+ id: item[0],
254
+ regexp: new RegExp(`^${item[0]}/.+?`),
255
+ config: item[1]
256
+ });
257
+ options.transformFileTypes = (options.transformFileTypes ?? []).concat([
258
+ ".js",
259
+ ".ts",
260
+ ".jsx",
261
+ ".tsx",
262
+ ".mjs",
263
+ ".cjs",
264
+ ".vue",
265
+ ".svelte"
266
+ ]).map((item) => item.toLowerCase());
267
+ const transformFileTypeSet = new Set(options.transformFileTypes);
268
+ let viteDevServer;
269
+ return {
270
+ name: "sbee:remote-development",
271
+ virtualFile: options.remotes ? { __federation__: `
272
+ ${createRemotesMap(devRemotes)}
273
+ const loadJS = async (url, fn) => {
274
+ const resolvedUrl = typeof url === 'function' ? await url() : url;
275
+ const script = document.createElement('script')
276
+ script.type = 'text/javascript';
277
+ script.onload = fn;
278
+ script.src = resolvedUrl;
279
+ document.getElementsByTagName('head')[0].appendChild(script);
280
+ }
281
+ function get(name, ${REMOTE_FROM_PARAMETER}){
282
+ return import(/* @vite-ignore */ name).then(module => ()=> {
283
+ if (${REMOTE_FROM_PARAMETER} === 'webpack') {
284
+ return Object.prototype.toString.call(module).indexOf('Module') > -1 && module.default ? module.default : module
285
+ }
286
+ return module
287
+ })
288
+ }
289
+ const wrapShareScope = ${REMOTE_FROM_PARAMETER} => {
290
+ return {
291
+ ${getModuleMarker("shareScope")}
292
+ }
293
+ }
294
+ async function __federation_method_ensure(remoteId) {
295
+ const remote = remotesMap[remoteId];
296
+ if (!remote.inited) {
297
+ if ('var' === remote.format) {
298
+ // loading js with script tag
299
+ return new Promise(resolve => {
300
+ const callback = () => {
301
+ if (!remote.inited) {
302
+ remote.lib = window[remoteId];
303
+ remote.lib.init(wrapShareScope(remote.from))
304
+ remote.inited = true;
305
+ }
306
+ resolve(remote.lib);
307
+ }
308
+ return loadJS(remote.url, callback);
309
+ });
310
+ } else if (['esm', 'systemjs'].includes(remote.format)) {
311
+ // loading js with import(...)
312
+ return new Promise((resolve, reject) => {
313
+ const getUrl = typeof remote.url === 'function' ? remote.url : () => Promise.resolve(remote.url);
314
+ getUrl().then(url => {
315
+ import(/* @vite-ignore */ url).then(lib => {
316
+ if (!remote.inited) {
317
+ const shareScope = wrapShareScope(remote.from)
318
+ remote.lib = lib;
319
+ remote.lib.init(shareScope);
320
+ remote.inited = true;
321
+ }
322
+ resolve(remote.lib);
323
+ }).catch(reject)
324
+ })
325
+ })
326
+ }
327
+ } else {
328
+ return remote.lib;
329
+ }
330
+ }
331
+
332
+ function __federation_method_unwrapDefault(module) {
333
+ return (module?.__esModule || module?.[Symbol.toStringTag] === 'Module')?module.default:module
334
+ }
335
+
336
+ function __federation_method_wrapDefault(module ,need){
337
+ if (!module?.default && need) {
338
+ let obj = Object.create(null);
339
+ obj.default = module;
340
+ obj.__esModule = true;
341
+ return obj;
342
+ }
343
+ return module;
344
+ }
345
+
346
+ function __federation_method_getRemote(remoteName, componentName){
347
+ return __federation_method_ensure(remoteName).then((remote) => remote.get(componentName).then(factory => factory()));
348
+ }
349
+
350
+ function __federation_method_setRemote(remoteName, remoteConfig) {
351
+ remotesMap[remoteName] = remoteConfig;
352
+ }
353
+ export {__federation_method_ensure, __federation_method_getRemote , __federation_method_setRemote , __federation_method_unwrapDefault , __federation_method_wrapDefault}
354
+ ;` } : { __federation__: "" },
355
+ config(config) {
356
+ if (parsedOptions.devRemote.length) {
357
+ const excludeRemotes = [];
358
+ parsedOptions.devRemote.forEach((item) => excludeRemotes.push(item[0]));
359
+ let optimizeDeps = config.optimizeDeps;
360
+ if (!optimizeDeps) optimizeDeps = config.optimizeDeps = {};
361
+ if (!optimizeDeps.exclude) optimizeDeps.exclude = [];
362
+ optimizeDeps.exclude = optimizeDeps.exclude.concat(excludeRemotes);
363
+ }
364
+ },
365
+ configureServer(server) {
366
+ viteDevServer = server;
367
+ },
368
+ async transform(code, id) {
369
+ if (builderInfo.isHost && !builderInfo.isRemote) {
370
+ for (const arr of parsedOptions.devShared) if (!arr[1].version && !arr[1].manuallyPackagePathSetting) {
371
+ const packageJsonPath = (await this.resolve(`${arr[0]}/package.json`))?.id;
372
+ if (!packageJsonPath) this.error(`No description file or no version in description file (usually package.json) of ${arr[0]}(${packageJsonPath}). Add version to description file, or manually specify version in shared config.`);
373
+ else {
374
+ const json = await this.fs.readFile(packageJsonPath, { encoding: "utf8" }).then((jsonStr) => JSON.parse(jsonStr));
375
+ arr[1].version = json.version;
376
+ }
377
+ }
378
+ }
379
+ if (id === "\0virtual:__federation__") {
380
+ const scopeCode = await devSharedScopeCode.call(this, parsedOptions.devShared);
381
+ return code.replace(getModuleMarker("shareScope"), scopeCode.join(","));
382
+ }
383
+ const fileExtname = getFileExtname(id);
384
+ if (!transformFileTypeSet.has((fileExtname ?? "").toLowerCase())) return;
385
+ let ast = null;
386
+ try {
387
+ ast = this.parse(code);
388
+ } catch (err) {
389
+ console.error(err);
390
+ }
391
+ if (!ast) return null;
392
+ const magicString = new MagicString(code);
393
+ const hasStaticImported = /* @__PURE__ */ new Map();
394
+ let requiresRuntime = false;
395
+ let manualRequired = null;
396
+ walk(ast, { enter(node) {
397
+ if (node.type === "ImportDeclaration" && node.source?.value === "virtual:__federation__") manualRequired = node;
398
+ if ((node.type === "ImportExpression" || node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration") && node.source?.value?.indexOf("/") > -1) {
399
+ const moduleId = node.source.value;
400
+ const remote = devRemotes.find((r) => r.regexp.test(moduleId));
401
+ const needWrap = remote?.config.from === "vite";
402
+ if (remote) {
403
+ requiresRuntime = true;
404
+ const modName = `.${moduleId.slice(remote.id.length)}`;
405
+ switch (node.type) {
406
+ case "ImportExpression":
407
+ magicString.overwrite(node.start, node.end, `__federation_method_getRemote(${JSON.stringify(remote.id)} , ${JSON.stringify(modName)}).then(module=>__federation_method_wrapDefault(module, ${needWrap}))`);
408
+ break;
409
+ case "ImportDeclaration":
410
+ if (node.specifiers?.length) {
411
+ const afterImportName = `__federation_var_${moduleId.replace(/[@/\\.-]/g, "")}`;
412
+ if (!hasStaticImported.has(moduleId)) {
413
+ magicString.overwrite(node.start, node.end, `const ${afterImportName} = await __federation_method_getRemote(${JSON.stringify(remote.id)} , ${JSON.stringify(modName)});`);
414
+ hasStaticImported.set(moduleId, afterImportName);
415
+ }
416
+ let deconstructStr = "";
417
+ node.specifiers.forEach((spec) => {
418
+ if (spec.type === "ImportDefaultSpecifier") magicString.appendRight(node.end, `\n let ${spec.local.name} = __federation_method_unwrapDefault(${afterImportName}) `);
419
+ else if (spec.type === "ImportSpecifier") {
420
+ const importedName = spec.imported.name;
421
+ const localName = spec.local.name;
422
+ deconstructStr += `${importedName === localName ? localName : `${importedName} : ${localName}`},`;
423
+ } else if (spec.type === "ImportNamespaceSpecifier") magicString.appendRight(node.end, `let {${spec.local.name}} = ${afterImportName}`);
424
+ });
425
+ if (deconstructStr.length > 0) magicString.appendRight(node.end, `\n let {${deconstructStr.slice(0, -1)}} = ${afterImportName}`);
426
+ }
427
+ break;
428
+ case "ExportNamedDeclaration": {
429
+ const afterImportName = `__federation_var_${moduleId.replace(/[@/\\.-]/g, "")}`;
430
+ if (!hasStaticImported.has(moduleId)) {
431
+ hasStaticImported.set(moduleId, afterImportName);
432
+ magicString.overwrite(node.start, node.end, `const ${afterImportName} = await __federation_method_getRemote(${JSON.stringify(remote.id)} , ${JSON.stringify(modName)});`);
433
+ }
434
+ if (node.specifiers.length > 0) {
435
+ const specifiers = node.specifiers;
436
+ let exportContent = "";
437
+ let deconstructContent = "";
438
+ specifiers.forEach((spec) => {
439
+ const localName = spec.local.name;
440
+ const exportName = spec.exported.name;
441
+ const variableName = `${afterImportName}_${localName}`;
442
+ deconstructContent = deconstructContent.concat(`${localName}:${variableName},`);
443
+ exportContent = exportContent.concat(`${variableName} as ${exportName},`);
444
+ });
445
+ magicString.append(`\n const {${deconstructContent.slice(0, deconstructContent.length - 1)}} = ${afterImportName}; \n`);
446
+ magicString.append(`\n export {${exportContent.slice(0, exportContent.length - 1)}}; `);
447
+ }
448
+ break;
449
+ }
450
+ }
451
+ }
452
+ }
453
+ } });
454
+ if (requiresRuntime) {
455
+ let requiresCode = `import {__federation_method_ensure, __federation_method_getRemote , __federation_method_wrapDefault , __federation_method_unwrapDefault} from '__federation__';\n\n`;
456
+ if (manualRequired) {
457
+ requiresCode = `import {__federation_method_setRemote, __federation_method_ensure, __federation_method_getRemote , __federation_method_wrapDefault , __federation_method_unwrapDefault} from '__federation__';\n\n`;
458
+ magicString.overwrite(manualRequired.start, manualRequired.end, ``);
459
+ }
460
+ magicString.prepend(requiresCode);
461
+ }
462
+ return magicString.toString();
463
+ }
464
+ };
465
+ async function devSharedScopeCode(shared) {
466
+ const res = [];
467
+ if (shared.length) {
468
+ const serverConfiguration = viteDevServer.config.server;
469
+ const base = viteDevServer.config.base;
470
+ const cwdPath = normalizePath(process.cwd());
471
+ for (const item of shared) {
472
+ const moduleInfo = await this.resolve(item[1].packagePath, void 0, { skipSelf: true });
473
+ if (!moduleInfo) continue;
474
+ const moduleFilePath = normalizePath(moduleInfo.id);
475
+ const relativePath = moduleFilePath.indexOf(cwdPath) === 0 ? posix.join(base, moduleFilePath.slice(cwdPath.length)) : null;
476
+ const sharedName = item[0];
477
+ const obj = item[1];
478
+ let str = "";
479
+ if (typeof obj === "object") {
480
+ const origin = serverConfiguration.origin;
481
+ const pathname = relativePath ?? `/@fs/${moduleInfo.id}`;
482
+ const url = origin ? `'${origin}${pathname}'` : `window.location.origin+'${pathname}'`;
483
+ str += `get:()=> get(${url}, ${REMOTE_FROM_PARAMETER})`;
484
+ res.push(`'${sharedName}':{'${obj.version}':{${str}}}`);
485
+ }
486
+ }
487
+ }
488
+ return res;
489
+ }
490
+ }
491
+ //#endregion
492
+ //#region src/dev/shared-development.ts
493
+ function devSharedPlugin(options) {
494
+ parsedOptions.devShared = parseSharedOptions(options);
495
+ return { name: "sbee:shared-development" };
496
+ }
497
+ //#endregion
498
+ //#region src/prod/expose-production.ts
499
+ function prodExposePlugin(options) {
500
+ const exposeOptions = parseExposeOptions(options);
501
+ let moduleMap = "";
502
+ if (!parsedOptions.prodExpose.some((expose) => {
503
+ return expose[0] === exposeOptions[0]?.[0];
504
+ })) parsedOptions.prodExpose = Array.prototype.concat(parsedOptions.prodExpose, exposeOptions);
505
+ for (const item of exposeOptions) {
506
+ const moduleName = getModuleMarker(`\${${item[0]}}`, SHARED);
507
+ EXTERNALS.push(moduleName);
508
+ const exposeFilepath = normalizePath(resolve(item[1].import));
509
+ EXPOSES_MAP.set(item[0], exposeFilepath);
510
+ EXPOSES_KEY_MAP.set(item[0], `__federation_expose_${removeNonRegLetter(item[0], NAME_CHAR_REG)}`);
511
+ moduleMap += `\n"${item[0]}":()=>{
512
+ ${DYNAMIC_LOADING_CSS}('${DYNAMIC_LOADING_CSS_PREFIX}${exposeFilepath}', ${item[1].dontAppendStylesToHead}, '${item[0]}')
513
+ return __federation_import('\${__federation_expose_${item[0]}}').then(module =>Object.keys(module).every(item => exportSet.has(item)) ? () => module.default : () => module)},`;
514
+ }
515
+ return {
516
+ name: "sbee:expose-production",
517
+ virtualFile: { [`__remoteEntryHelper__${options.filename}`]: `
518
+ const currentImports = {}
519
+ const exportSet = new Set(['Module', '__esModule', 'default', '_export_sfc']);
520
+ let moduleMap = {${moduleMap}}
521
+ const seen = {}
522
+ export const ${DYNAMIC_LOADING_CSS} = (cssFilePaths, dontAppendStylesToHead, exposeItemName) => {
523
+ const metaUrl = import.meta.url;
524
+ if (typeof metaUrl === 'undefined') {
525
+ console.warn('The remote style takes effect only when the build.target option in the vite.config.ts file is higher than that of "es2020".');
526
+ return;
527
+ }
528
+
529
+ const curUrl = metaUrl.substring(0, metaUrl.lastIndexOf('${options.filename}'));
530
+ const base = __VITE_BASE_PLACEHOLDER__;
531
+ const assetsDir = __VITE_ASSETS_DIR_PLACEHOLDER__;
532
+
533
+ cssFilePaths.forEach(cssPath => {
534
+ let href = '';
535
+ const baseUrl = base || curUrl;
536
+ if (baseUrl) {
537
+ const trimmer = {
538
+ trailing: (path) => (path.endsWith('/') ? path.slice(0, -1) : path),
539
+ leading: (path) => (path.startsWith('/') ? path.slice(1) : path)
540
+ }
541
+ const isAbsoluteUrl = (url) => url.startsWith('http') || url.startsWith('//');
542
+
543
+ const cleanBaseUrl = trimmer.trailing(baseUrl);
544
+ const cleanCssPath = trimmer.leading(cssPath);
545
+ const cleanCurUrl = trimmer.trailing(curUrl);
546
+
547
+ if (isAbsoluteUrl(baseUrl)) {
548
+ href = [cleanBaseUrl, cleanCssPath].filter(Boolean).join('/');
549
+ } else {
550
+ if (cleanCurUrl.includes(cleanBaseUrl)) {
551
+ href = [cleanCurUrl, cleanCssPath].filter(Boolean).join('/');
552
+ } else {
553
+ href = [cleanCurUrl + cleanBaseUrl, cleanCssPath].filter(Boolean).join('/');
554
+ }
555
+ }
556
+ } else {
557
+ href = cssPath;
558
+ }
559
+
560
+ if (dontAppendStylesToHead) {
561
+ const key = 'css__${options.name}__' + exposeItemName;
562
+ window[key] = window[key] || [];
563
+ window[key].push(href);
564
+ return;
565
+ }
566
+
567
+ if (href in seen) return;
568
+ seen[href] = true;
569
+
570
+ const element = document.createElement('link');
571
+ element.rel = 'stylesheet';
572
+ element.href = href;
573
+ document.head.appendChild(element);
574
+ });
575
+ };
576
+ async function __federation_import(name) {
577
+ currentImports[name] ??= import(name)
578
+ return currentImports[name]
579
+ };
580
+ export const get =(module) => {
581
+ if(!moduleMap[module]) throw new Error('Can not find remote module ' + module)
582
+ return moduleMap[module]();
583
+ };
584
+ export const init =(shareScope) => {
585
+ globalThis.__federation_shared__= globalThis.__federation_shared__|| {};
586
+ Object.entries(shareScope).forEach(([key, value]) => {
587
+ for (const [versionKey, versionValue] of Object.entries(value)) {
588
+ const scope = versionValue.scope || 'default'
589
+ globalThis.__federation_shared__[scope] = globalThis.__federation_shared__[scope] || {};
590
+ const shared= globalThis.__federation_shared__[scope];
591
+ (shared[key] = shared[key]||{})[versionKey] = versionValue;
592
+ }
593
+ });
594
+ }` },
595
+ configResolved(config) {
596
+ if (config) viteConfigResolved.config = config;
597
+ },
598
+ buildStart() {
599
+ if (parsedOptions.prodExpose.length > 0) this.emitFile({
600
+ fileName: `${builderInfo.assetsDir ? builderInfo.assetsDir + "/" : ""}${options.filename}`,
601
+ type: "chunk",
602
+ id: `__remoteEntryHelper__${options.filename}`,
603
+ preserveSignature: "strict"
604
+ });
605
+ },
606
+ generateBundle(_options, bundle) {
607
+ let remoteEntryChunk;
608
+ for (const file in bundle) {
609
+ const chunk = bundle[file];
610
+ if (chunk?.facadeModuleId === `\0virtual:__remoteEntryHelper__${options.filename}`) {
611
+ remoteEntryChunk = chunk;
612
+ break;
613
+ }
614
+ }
615
+ if (remoteEntryChunk) {
616
+ remoteEntryChunk.code = remoteEntryChunk.code.replace("__VITE_BASE_PLACEHOLDER__", `'${viteConfigResolved.config?.base || ""}'`).replace("__VITE_ASSETS_DIR_PLACEHOLDER__", `'${viteConfigResolved.config?.build?.assetsDir || ""}'`);
617
+ const filepathMap = /* @__PURE__ */ new Map();
618
+ const facadeIndex = /* @__PURE__ */ new Map();
619
+ for (const b of Object.values(bundle)) if ("facadeModuleId" in b && b.facadeModuleId) facadeIndex.set(b.facadeModuleId, b);
620
+ const getFilename = (name) => parse(parse(name).name).name;
621
+ const cssBundlesMap = Object.keys(bundle).filter((name) => extname(name) === ".css").reduce((res, name) => {
622
+ const filename = getFilename(name);
623
+ res.set(filename, bundle[name]);
624
+ return res;
625
+ }, /* @__PURE__ */ new Map());
626
+ remoteEntryChunk.code = remoteEntryChunk.code.replace(new RegExp(`(["'])${DYNAMIC_LOADING_CSS_PREFIX}.*?\\1`, "g"), (str) => {
627
+ if (viteConfigResolved.config && !viteConfigResolved.config.build.cssCodeSplit) if (cssBundlesMap.size) return `[${[...cssBundlesMap.values()].map((cssBundle) => JSON.stringify(basename(cssBundle.fileName))).join(",")}]`;
628
+ else return "[]";
629
+ const filepath = str.slice((`'` + DYNAMIC_LOADING_CSS_PREFIX).length, -1);
630
+ if (!filepath || !filepath.length) return str;
631
+ let fileBundle = filepathMap.get(filepath);
632
+ if (!fileBundle) {
633
+ fileBundle = facadeIndex.get(filepath);
634
+ if (fileBundle) filepathMap.set(filepath, fileBundle);
635
+ else return str;
636
+ }
637
+ const depCssFiles = /* @__PURE__ */ new Set();
638
+ const addDepCss = (bundleName) => {
639
+ const theBundle = bundle[bundleName];
640
+ if (theBundle && theBundle.viteMetadata) for (const cssFileName of theBundle.viteMetadata.importedCss.values()) {
641
+ const cssBundle = cssBundlesMap.get(getFilename(cssFileName));
642
+ if (cssBundle) depCssFiles.add(cssBundle.fileName);
643
+ }
644
+ if (theBundle && theBundle.imports && theBundle.imports.length) theBundle.imports.forEach((name) => addDepCss(name));
645
+ };
646
+ [fileBundle.fileName, ...fileBundle.imports].forEach(addDepCss);
647
+ return `[${[...depCssFiles].map((d) => JSON.stringify(basename(d))).join(",")}]`;
648
+ });
649
+ const nameToKey = /* @__PURE__ */ new Map();
650
+ for (const key of Object.keys(bundle)) {
651
+ const name = bundle[key].name;
652
+ if (name) nameToKey.set(name, key);
653
+ }
654
+ for (const expose of exposeOptions) {
655
+ const exposeKey = EXPOSES_KEY_MAP.get(expose[0]);
656
+ const module = exposeKey ? nameToKey.get(exposeKey) : void 0;
657
+ if (module) {
658
+ const chunk = bundle[module];
659
+ const slashPath = relative(dirname(remoteEntryChunk.fileName), chunk.fileName).replace(/\\/g, "/");
660
+ remoteEntryChunk.code = remoteEntryChunk.code.replace(`\${__federation_expose_${expose[0]}}`, viteConfigResolved.config?.base?.replace(/\/+$/, "") ? [
661
+ viteConfigResolved.config.base.replace(/\/+$/, ""),
662
+ viteConfigResolved.config.build?.assetsDir?.replace(/\/+$/, ""),
663
+ slashPath
664
+ ].filter(Boolean).join("/") : `./${slashPath}`);
665
+ }
666
+ }
667
+ let ast = null;
668
+ try {
669
+ ast = this.parse(remoteEntryChunk.code);
670
+ } catch (err) {
671
+ console.error(err);
672
+ }
673
+ if (!ast) return;
674
+ const magicString = new MagicString(remoteEntryChunk.code);
675
+ walk(ast, { enter(node) {
676
+ if (node && node.type === "CallExpression" && typeof node.arguments[0]?.value === "string" && node.arguments[0]?.value.indexOf(`__v__css__`) > -1) magicString.remove(node.start, node.end + 1);
677
+ } });
678
+ remoteEntryChunk.code = magicString.toString();
679
+ }
680
+ }
681
+ };
682
+ }
683
+ //#endregion
684
+ //#region src/prod/remote-production.ts
685
+ function joinUrlSegments(a, b) {
686
+ if (!a || !b) return a || b || "";
687
+ if (a[a.length - 1] === "/") a = a.substring(0, a.length - 1);
688
+ if (b[0] !== "/") b = "/" + b;
689
+ return a + b;
690
+ }
691
+ function toOutputFilePathWithoutRuntime(filename, type, hostId, hostType, config, toRelative) {
692
+ const { renderBuiltUrl } = config.experimental;
693
+ let relative = config.base === "" || config.base === "./";
694
+ if (renderBuiltUrl) {
695
+ const result = renderBuiltUrl(filename, {
696
+ hostId,
697
+ hostType,
698
+ type,
699
+ ssr: !!config.build.ssr
700
+ });
701
+ if (typeof result === "object") {
702
+ if (result.runtime) throw new Error(`{ runtime: "${result.runtime}" } is not supported for assets in ${hostType} files: ${filename}`);
703
+ if (typeof result.relative === "boolean") relative = result.relative;
704
+ } else if (result) return result;
705
+ }
706
+ if (relative && !config.build.ssr) return toRelative(filename, hostId);
707
+ else return joinUrlSegments(config.base, filename);
708
+ }
709
+ function prodRemotePlugin(options) {
710
+ parsedOptions.prodRemote = parseRemoteOptions(options);
711
+ for (const item of parsedOptions.prodRemote) prodRemotes.push({
712
+ id: item[0],
713
+ regexp: new RegExp(`^${item[0]}/.+?`),
714
+ config: item[1]
715
+ });
716
+ const shareScope = options.shareScope || "default";
717
+ let resolvedConfig;
718
+ return {
719
+ name: "sbee:remote-production",
720
+ virtualFile: options.remotes ? { __federation__: `
721
+ ${createRemotesMap(prodRemotes)}
722
+ const currentImports = {}
723
+ const loadJS = async (url, fn) => {
724
+ const resolvedUrl = typeof url === 'function' ? await url() : url;
725
+ const script = document.createElement('script')
726
+ script.type = 'text/javascript';
727
+ script.onload = fn;
728
+ script.src = resolvedUrl;
729
+ document.getElementsByTagName('head')[0].appendChild(script);
730
+ }
731
+
732
+ function get(name, ${REMOTE_FROM_PARAMETER}) {
733
+ return __federation_import(name).then(module => () => {
734
+ if (${REMOTE_FROM_PARAMETER} === 'webpack') {
735
+ return Object.prototype.toString.call(module).indexOf('Module') > -1 && module.default ? module.default : module
736
+ }
737
+ return module
738
+ })
739
+ }
740
+
741
+ function merge(obj1, obj2) {
742
+ const mergedObj = Object.assign(obj1, obj2);
743
+ for (const key of Object.keys(mergedObj)) {
744
+ if (typeof mergedObj[key] === 'object' && typeof obj2[key] === 'object') {
745
+ mergedObj[key] = merge(mergedObj[key], obj2[key]);
746
+ }
747
+ }
748
+ return mergedObj;
749
+ }
750
+
751
+ const wrapShareModule = ${REMOTE_FROM_PARAMETER} => {
752
+ return merge({
753
+ ${getModuleMarker("shareScope")}
754
+ }, (globalThis.__federation_shared__ || {})['${shareScope}'] || {});
755
+ }
756
+
757
+ async function __federation_import(name) {
758
+ currentImports[name] ??= import(name)
759
+ return currentImports[name]
760
+ }
761
+
762
+ async function __federation_method_ensure(remoteId) {
763
+ const remote = remotesMap[remoteId];
764
+ if (!remote.inited) {
765
+ if ('var' === remote.format) {
766
+ // loading js with script tag
767
+ return new Promise(resolve => {
768
+ const callback = () => {
769
+ if (!remote.inited) {
770
+ remote.lib = window[remoteId];
771
+ remote.lib.init(wrapShareModule(remote.from))
772
+ remote.inited = true;
773
+ }
774
+ resolve(remote.lib);
775
+ }
776
+ return loadJS(remote.url, callback);
777
+ });
778
+ } else if (['esm', 'systemjs'].includes(remote.format)) {
779
+ // loading js with import(...)
780
+ return new Promise((resolve, reject) => {
781
+ const getUrl = typeof remote.url === 'function' ? remote.url : () => Promise.resolve(remote.url);
782
+ getUrl().then(url => {
783
+ import(/* @vite-ignore */ url).then(lib => {
784
+ if (!remote.inited) {
785
+ const shareScope = wrapShareModule(remote.from);
786
+ remote.lib = lib;
787
+ remote.lib.init(shareScope);
788
+ remote.inited = true;
789
+ }
790
+ resolve(remote.lib);
791
+ }).catch(reject)
792
+ })
793
+ })
794
+ }
795
+ } else {
796
+ return remote.lib;
797
+ }
798
+ }
799
+
800
+ function __federation_method_unwrapDefault(module) {
801
+ return (module?.__esModule || module?.[Symbol.toStringTag] === 'Module') ? module.default : module
802
+ }
803
+
804
+ function __federation_method_wrapDefault(module, need) {
805
+ if (!module?.default && need) {
806
+ let obj = Object.create(null);
807
+ obj.default = module;
808
+ obj.__esModule = true;
809
+ return obj;
810
+ }
811
+ return module;
812
+ }
813
+
814
+ function __federation_method_getRemote(remoteName, componentName) {
815
+ return __federation_method_ensure(remoteName).then((remote) => remote.get(componentName).then(factory => factory()));
816
+ }
817
+
818
+ function __federation_method_setRemote(remoteName, remoteConfig) {
819
+ remotesMap[remoteName] = remoteConfig;
820
+ }
821
+
822
+ export {
823
+ __federation_method_ensure,
824
+ __federation_method_getRemote,
825
+ __federation_method_setRemote,
826
+ __federation_method_unwrapDefault,
827
+ __federation_method_wrapDefault
828
+ }
829
+ ` } : { __federation__: "" },
830
+ configResolved(config) {
831
+ resolvedConfig = config;
832
+ },
833
+ async transform(code, id) {
834
+ if (builderInfo.isShared) {
835
+ for (const sharedInfo of parsedOptions.prodShared) if (!sharedInfo[1].emitFile) sharedInfo[1].emitFile = this.emitFile({
836
+ type: "chunk",
837
+ id: sharedInfo[1].id ?? sharedInfo[1].packagePath,
838
+ preserveSignature: "strict",
839
+ name: `__federation_shared_${sharedInfo[0]}`
840
+ });
841
+ if (id === "\0virtual:__federation_fn_import") {
842
+ const moduleMapCode = parsedOptions.prodShared.filter((shareInfo) => shareInfo[1].generate).map((sharedInfo) => `'${sharedInfo[0]}':{get:()=>()=>__federation_import(import.meta.ROLLUP_FILE_URL_${sharedInfo[1].emitFile}),import:${sharedInfo[1].import}${sharedInfo[1].requiredVersion ? `,requiredVersion:'${sharedInfo[1].requiredVersion}'` : ""}}`).join(",");
843
+ return code.replace(getModuleMarker("moduleMap", "var"), `{${moduleMapCode}}`);
844
+ }
845
+ }
846
+ if (builderInfo.isRemote) {
847
+ for (const expose of parsedOptions.prodExpose) if (!expose[1].emitFile) expose[1].emitFile = this.emitFile({
848
+ type: "chunk",
849
+ id: expose[1].id ?? expose[1].import,
850
+ name: EXPOSES_KEY_MAP.get(expose[0]),
851
+ preserveSignature: "allow-extension"
852
+ });
853
+ }
854
+ if (builderInfo.isHost) {
855
+ if (id === "\0virtual:__federation__") {
856
+ const res = [];
857
+ parsedOptions.prodShared.forEach((arr) => {
858
+ const obj = arr[1];
859
+ let str = "";
860
+ if (typeof obj === "object") {
861
+ const fileUrl = `import.meta.ROLLUP_FILE_URL_${obj.emitFile}`;
862
+ str += `get:()=>get(${fileUrl}, ${REMOTE_FROM_PARAMETER}), loaded:1`;
863
+ res.push(`'${arr[0]}':{'${obj.version}':{${str}}}`);
864
+ }
865
+ });
866
+ return code.replace(getModuleMarker("shareScope"), res.join(","));
867
+ }
868
+ }
869
+ if (builderInfo.isHost || builderInfo.isShared) {
870
+ let ast = null;
871
+ try {
872
+ ast = this.parse(code);
873
+ } catch (err) {
874
+ console.error(err);
875
+ }
876
+ if (!ast) return null;
877
+ const magicString = new MagicString(code);
878
+ const hasStaticImported = /* @__PURE__ */ new Map();
879
+ let requiresRuntime = false;
880
+ let hasImportShared = false;
881
+ let modify = false;
882
+ let manualRequired = null;
883
+ const sharedNameSet = new Set(parsedOptions.prodShared.map((sharedInfo) => sharedInfo[0]));
884
+ walk(ast, { enter(node) {
885
+ if (node.type === "ImportDeclaration") {
886
+ const moduleName = node.source.value;
887
+ if (sharedNameSet.has(moduleName)) {
888
+ const namedImportDeclaration = [];
889
+ let defaultImportDeclaration = null;
890
+ if (!node.specifiers?.length) {
891
+ magicString.remove(node.start, node.end);
892
+ modify = true;
893
+ } else {
894
+ node.specifiers.forEach((specify) => {
895
+ if (specify.imported?.name) namedImportDeclaration.push(`${specify.imported.name === specify.local.name ? specify.imported.name : `${specify.imported.name}:${specify.local.name}`}`);
896
+ else defaultImportDeclaration = specify.local.name;
897
+ });
898
+ hasImportShared = true;
899
+ if (defaultImportDeclaration && namedImportDeclaration.length) {
900
+ const imports = namedImportDeclaration.join(",");
901
+ const line = `const ${defaultImportDeclaration} = await importShared('${moduleName}');\nconst {${imports}} = ${defaultImportDeclaration};\n`;
902
+ magicString.overwrite(node.start, node.end, line);
903
+ } else if (defaultImportDeclaration) magicString.overwrite(node.start, node.end, `const ${defaultImportDeclaration} = await importShared('${moduleName}');\n`);
904
+ else if (namedImportDeclaration.length) magicString.overwrite(node.start, node.end, `const {${namedImportDeclaration.join(",")}} = await importShared('${moduleName}');\n`);
905
+ }
906
+ }
907
+ }
908
+ if (node.type === "ImportDeclaration" && node.source?.value === "virtual:__federation__") manualRequired = node;
909
+ if ((node.type === "ImportExpression" || node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration") && node.source?.value?.indexOf("/") > -1) {
910
+ const moduleId = node.source.value;
911
+ const remote = prodRemotes.find((r) => r.regexp.test(moduleId));
912
+ const needWrap = remote?.config.from === "vite";
913
+ if (remote) {
914
+ requiresRuntime = true;
915
+ const modName = `.${moduleId.slice(remote.id.length)}`;
916
+ switch (node.type) {
917
+ case "ImportExpression":
918
+ magicString.overwrite(node.start, node.end, `__federation_method_getRemote(${JSON.stringify(remote.id)} , ${JSON.stringify(modName)}).then(module=>__federation_method_wrapDefault(module, ${needWrap}))`);
919
+ break;
920
+ case "ImportDeclaration":
921
+ if (node.specifiers?.length) {
922
+ const afterImportName = `__federation_var_${moduleId.replace(/[@/\\.-]/g, "")}`;
923
+ if (!hasStaticImported.has(moduleId)) {
924
+ hasStaticImported.set(moduleId, afterImportName);
925
+ magicString.overwrite(node.start, node.end, `const ${afterImportName} = await __federation_method_getRemote(${JSON.stringify(remote.id)} , ${JSON.stringify(modName)});`);
926
+ }
927
+ let deconstructStr = "";
928
+ node.specifiers.forEach((spec) => {
929
+ if (spec.type === "ImportDefaultSpecifier") magicString.appendRight(node.end, `\n let ${spec.local.name} = __federation_method_unwrapDefault(${afterImportName}) `);
930
+ else if (spec.type === "ImportSpecifier") {
931
+ const importedName = spec.imported.name;
932
+ const localName = spec.local.name;
933
+ deconstructStr += `${importedName === localName ? localName : `${importedName} : ${localName}`},`;
934
+ } else if (spec.type === "ImportNamespaceSpecifier") magicString.appendRight(node.end, `let {${spec.local.name}} = ${afterImportName}`);
935
+ });
936
+ if (deconstructStr.length > 0) magicString.appendRight(node.end, `\n let {${deconstructStr.slice(0, -1)}} = ${afterImportName}`);
937
+ }
938
+ break;
939
+ case "ExportNamedDeclaration": {
940
+ const afterImportName = `__federation_var_${moduleId.replace(/[@/\\.-]/g, "")}`;
941
+ if (!hasStaticImported.has(moduleId)) {
942
+ hasStaticImported.set(moduleId, afterImportName);
943
+ magicString.overwrite(node.start, node.end, `const ${afterImportName} = await __federation_method_getRemote(${JSON.stringify(remote.id)} , ${JSON.stringify(modName)});`);
944
+ }
945
+ if (node.specifiers.length > 0) {
946
+ const specifiers = node.specifiers;
947
+ let exportContent = "";
948
+ let deconstructContent = "";
949
+ specifiers.forEach((spec) => {
950
+ const localName = spec.local.name;
951
+ const exportName = spec.exported.name;
952
+ const variableName = `${afterImportName}_${localName}`;
953
+ deconstructContent = deconstructContent.concat(`${localName}:${variableName},`);
954
+ exportContent = exportContent.concat(`${variableName} as ${exportName},`);
955
+ });
956
+ magicString.append(`\n const {${deconstructContent.slice(0, deconstructContent.length - 1)}} = ${afterImportName}; \n`);
957
+ magicString.append(`\n export {${exportContent.slice(0, exportContent.length - 1)}}; `);
958
+ }
959
+ break;
960
+ }
961
+ }
962
+ }
963
+ }
964
+ } });
965
+ if (requiresRuntime) {
966
+ let requiresCode = `import {__federation_method_ensure, __federation_method_getRemote , __federation_method_wrapDefault , __federation_method_unwrapDefault} from '__federation__';\n\n`;
967
+ if (manualRequired) {
968
+ requiresCode = `import {__federation_method_setRemote, __federation_method_ensure, __federation_method_getRemote , __federation_method_wrapDefault , __federation_method_unwrapDefault} from '__federation__';\n\n`;
969
+ magicString.overwrite(manualRequired.start, manualRequired.end, ``);
970
+ }
971
+ magicString.prepend(requiresCode);
972
+ }
973
+ if (hasImportShared) magicString.prepend(`import {importShared} from '\0virtual:__federation_fn_import';\n`);
974
+ if (requiresRuntime || hasImportShared || modify) return {
975
+ code: magicString.toString(),
976
+ map: magicString.generateMap({ hires: true })
977
+ };
978
+ }
979
+ },
980
+ generateBundle(options, bundle) {
981
+ const preloadSharedReg = parsedOptions.prodShared.filter((shareInfo) => shareInfo[1].modulePreload).map((item) => new RegExp(`__federation_shared_${item[0]}-.{8}\\.js`));
982
+ const getImportedChunks = (rootChunk, satisfy, seen = /* @__PURE__ */ new Set()) => {
983
+ const chunks = [];
984
+ const stack = [rootChunk];
985
+ while (stack.length > 0) {
986
+ const chunk = stack.pop();
987
+ for (const file of chunk.imports) {
988
+ const importee = bundle[file];
989
+ if (importee?.type === "chunk" && !seen.has(file)) {
990
+ if (satisfy(importee)) {
991
+ seen.add(file);
992
+ stack.push(importee);
993
+ chunks.push(importee);
994
+ }
995
+ }
996
+ }
997
+ }
998
+ return chunks;
999
+ };
1000
+ const sharedFiles = [];
1001
+ const entryChunk = {};
1002
+ for (const fileName in bundle) {
1003
+ const file = bundle[fileName];
1004
+ if (file.type === "asset") {
1005
+ if (fileName.endsWith(".html")) entryChunk[fileName] = file;
1006
+ } else if (preloadSharedReg.some((item) => item.test(fileName))) sharedFiles.push(fileName);
1007
+ }
1008
+ if (!sharedFiles.length) return;
1009
+ Object.keys(entryChunk).forEach((fileName) => {
1010
+ let html = entryChunk[fileName].source;
1011
+ const htmlPath = entryChunk[fileName].fileName;
1012
+ const basePath = resolvedConfig.base === "./" || resolvedConfig.base === "" ? path.posix.join(path.posix.relative(entryChunk[fileName].fileName, "").slice(0, -2), "./") : resolvedConfig.base;
1013
+ const toOutputFilePath = (filename) => toOutputFilePathWithoutRuntime(filename, "asset", htmlPath, "html", resolvedConfig, (filename) => basePath + filename);
1014
+ const importFiles = sharedFiles.filter((item) => {
1015
+ return !html.includes(toOutputFilePath(item));
1016
+ }).flatMap((item) => {
1017
+ return [item, ...getImportedChunks(bundle[item], (chunk) => !html.includes(toOutputFilePath(chunk.fileName))).map((item) => item.fileName)].map((item) => toOutputFilePath(item));
1018
+ });
1019
+ html = injectToHead(html, [...new Set(importFiles)].map((item) => toPreloadTag(item)));
1020
+ entryChunk[fileName].source = html;
1021
+ });
1022
+ }
1023
+ };
1024
+ }
1025
+ //#endregion
1026
+ //#region src/prod/federation_fn_import.js?raw
1027
+ var federation_fn_import_default = "import { satisfy } from '__federation_fn_satisfy'\n\nconst currentImports = {}\n\n// eslint-disable-next-line no-undef\nconst moduleMap = __rf_var__moduleMap\nconst moduleCache = Object.create(null)\nasync function importShared(name, shareScope = 'default') {\n return moduleCache[name]\n ? new Promise((r) => r(moduleCache[name]))\n : (await getSharedFromRuntime(name, shareScope)) || getSharedFromLocal(name)\n}\n// eslint-disable-next-line\nasync function __federation_import(name) {\n currentImports[name] ??= import(name)\n return currentImports[name]\n}\nasync function getSharedFromRuntime(name, shareScope) {\n let module = null\n if (globalThis?.__federation_shared__?.[shareScope]?.[name]) {\n const versionObj = globalThis.__federation_shared__[shareScope][name]\n const requiredVersion = moduleMap[name]?.requiredVersion\n const hasRequiredVersion = !!requiredVersion\n if (hasRequiredVersion) {\n const versionKey = Object.keys(versionObj).find((version) =>\n satisfy(version, requiredVersion)\n )\n if (versionKey) {\n const versionValue = versionObj[versionKey]\n module = await (await versionValue.get())()\n } else {\n console.log(\n `provider support ${name}(${versionKey}) is not satisfied requiredVersion(\\${moduleMap[name].requiredVersion})`\n )\n }\n } else {\n const versionKey = Object.keys(versionObj)[0]\n const versionValue = versionObj[versionKey]\n module = await (await versionValue.get())()\n }\n }\n if (module) {\n return flattenModule(module, name)\n }\n}\nasync function getSharedFromLocal(name) {\n if (moduleMap[name]?.import) {\n let module = await (await moduleMap[name].get())()\n return flattenModule(module, name)\n } else {\n console.error(\n `consumer config import=false,so cant use callback shared module`\n )\n }\n}\nfunction flattenModule(module, name) {\n // use a shared module which export default a function will getting error 'TypeError: xxx is not a function'\n if (typeof module.default === 'function') {\n Object.keys(module).forEach((key) => {\n if (key !== 'default') {\n module.default[key] = module[key]\n }\n })\n moduleCache[name] = module.default\n return module.default\n }\n if (module.default) module = Object.assign({}, module.default, module)\n moduleCache[name] = module\n return module\n}\nexport {\n importShared,\n getSharedFromRuntime as importSharedRuntime,\n getSharedFromLocal as importSharedLocal\n}\n";
1028
+ //#endregion
1029
+ //#region src/prod/shared-production.ts
1030
+ var sharedFilePathReg = /__federation_shared_(.+)-.{8}\.js$/;
1031
+ function prodSharedPlugin(options) {
1032
+ parsedOptions.prodShared = parseSharedOptions(options);
1033
+ const shareName2Prop = /* @__PURE__ */ new Map();
1034
+ parsedOptions.prodShared.forEach((value) => shareName2Prop.set(removeNonRegLetter(value[0], NAME_CHAR_REG), value[1]));
1035
+ let isHost = false;
1036
+ let isRemote = false;
1037
+ const id2Prop = /* @__PURE__ */ new Map();
1038
+ return {
1039
+ name: "sbee:shared-production",
1040
+ virtualFile: { __federation_fn_import: federation_fn_import_default },
1041
+ options(inputOptions) {
1042
+ isRemote = !!parsedOptions.prodExpose.length;
1043
+ isHost = !!parsedOptions.prodRemote.length && !parsedOptions.prodExpose.length;
1044
+ if (shareName2Prop.size) inputOptions.external = inputOptions.external?.filter((item) => {
1045
+ if (item instanceof RegExp) return ![...shareName2Prop.keys()].some((key) => item.test(key));
1046
+ return !shareName2Prop.has(removeNonRegLetter(item, NAME_CHAR_REG));
1047
+ });
1048
+ return inputOptions;
1049
+ },
1050
+ async buildStart() {
1051
+ if (parsedOptions.prodShared.length && isRemote) this.emitFile({
1052
+ name: "__federation_fn_import",
1053
+ type: "chunk",
1054
+ id: "__federation_fn_import",
1055
+ preserveSignature: "strict"
1056
+ });
1057
+ const collectDirFn = async (filePath, collect) => {
1058
+ try {
1059
+ const files = await this.fs.readdir(filePath);
1060
+ for (const name of files) {
1061
+ const tempPath = join(filePath, name);
1062
+ try {
1063
+ if ((await this.fs.stat(tempPath)).isDirectory()) {
1064
+ collect.push(tempPath);
1065
+ await collectDirFn(tempPath, collect);
1066
+ }
1067
+ } catch {}
1068
+ }
1069
+ } catch {}
1070
+ };
1071
+ const monoRepos = [];
1072
+ const currentDir = resolve();
1073
+ for (const arr of parsedOptions.prodShared) if (isHost && !arr[1].version && !arr[1].manuallyPackagePathSetting) {
1074
+ const packageJsonPath = (await this.resolve(`${arr[1].packagePath}/package.json`))?.id;
1075
+ if (packageJsonPath) {
1076
+ const packageJson = JSON.parse(await this.fs.readFile(packageJsonPath, { encoding: "utf8" }));
1077
+ arr[1].version = packageJson.version;
1078
+ } else {
1079
+ arr[1].removed = true;
1080
+ const dirPaths = [];
1081
+ const dir = join(currentDir, "node_modules", arr[0]);
1082
+ if ((await this.fs.stat(dir)).isDirectory()) await collectDirFn(dir, dirPaths);
1083
+ else this.error(`cant resolve "${arr[1].packagePath}"`);
1084
+ if (dirPaths.length > 0) monoRepos.push({
1085
+ arr: dirPaths,
1086
+ root: arr
1087
+ });
1088
+ }
1089
+ if (!arr[1].removed && !arr[1].version) this.error(`No description file or no version in description file (usually package.json) of ${arr[0]}. Add version to description file, or manually specify version in shared config.`);
1090
+ }
1091
+ parsedOptions.prodShared = parsedOptions.prodShared.filter((item) => !item[1].removed);
1092
+ if (monoRepos.length > 0) for (const monoRepo of monoRepos) for (const id of monoRepo.arr) try {
1093
+ const idResolve = await this.resolve(id);
1094
+ if (idResolve?.id) parsedOptions.prodShared.push([`${monoRepo.root[0]}/${basename(id)}`, {
1095
+ id: idResolve?.id,
1096
+ import: monoRepo.root[1].import,
1097
+ shareScope: monoRepo.root[1].shareScope,
1098
+ root: monoRepo.root
1099
+ }]);
1100
+ } catch (e) {}
1101
+ if (parsedOptions.prodShared.length && isRemote) for (const prod of parsedOptions.prodShared) id2Prop.set(prod[1].id, prod[1]);
1102
+ },
1103
+ outputOptions: function(outputOption) {
1104
+ outputOption.hoistTransitiveImports = false;
1105
+ const depToChunk = /* @__PURE__ */ new Map();
1106
+ for (const arr of parsedOptions.prodShared) {
1107
+ const deps = arr[1].dependencies;
1108
+ if (deps) for (const depId of deps) depToChunk.set(depId, arr[0]);
1109
+ }
1110
+ const manualChunkFunc = (id) => {
1111
+ return depToChunk.get(id);
1112
+ };
1113
+ if (typeof outputOption.manualChunks === "function") {
1114
+ const originalManualChunks = outputOption.manualChunks;
1115
+ outputOption.manualChunks = (id, getModuleInfo) => {
1116
+ const result = manualChunkFunc(id);
1117
+ return result ? result : originalManualChunks(id, getModuleInfo);
1118
+ };
1119
+ }
1120
+ if (outputOption.manualChunks === void 0) outputOption.manualChunks = manualChunkFunc;
1121
+ return outputOption;
1122
+ },
1123
+ generateBundle(options, bundle) {
1124
+ if (!isRemote) return;
1125
+ const needRemoveShared = /* @__PURE__ */ new Set();
1126
+ for (const key in bundle) {
1127
+ const chunk = bundle[key];
1128
+ if (chunk.type === "chunk") {
1129
+ if (!isHost) {
1130
+ const regRst = sharedFilePathReg.exec(chunk.fileName);
1131
+ if (regRst && shareName2Prop.get(removeNonRegLetter(regRst[1], NAME_CHAR_REG))?.generate === false) needRemoveShared.add(key);
1132
+ }
1133
+ }
1134
+ }
1135
+ if (needRemoveShared.size !== 0) for (const key of needRemoveShared) delete bundle[key];
1136
+ }
1137
+ };
1138
+ }
1139
+ //#endregion
1140
+ //#region src/index.ts
1141
+ function resolveHook(hook) {
1142
+ if (!hook) return void 0;
1143
+ if (typeof hook === "function") return hook;
1144
+ return hook.handler;
1145
+ }
1146
+ function federation(options) {
1147
+ options.filename = options.filename ? options.filename : DEFAULT_ENTRY_FILENAME;
1148
+ let pluginList = [];
1149
+ let virtualFiles = {};
1150
+ let registerCount = 0;
1151
+ let _mode;
1152
+ function registerPlugins(mode, command) {
1153
+ if (mode === "production" || command === "build") pluginList = [
1154
+ prodSharedPlugin(options),
1155
+ prodExposePlugin(options),
1156
+ prodRemotePlugin(options)
1157
+ ];
1158
+ else if (mode === "development" || command === "serve") pluginList = [
1159
+ devSharedPlugin(options),
1160
+ devExposePlugin(options),
1161
+ devRemotePlugin(options)
1162
+ ];
1163
+ else pluginList = [];
1164
+ builderInfo.isHost = !!(parsedOptions.prodRemote.length || parsedOptions.devRemote.length);
1165
+ builderInfo.isRemote = !!(parsedOptions.prodExpose.length || parsedOptions.devExpose.length);
1166
+ builderInfo.isShared = !!(parsedOptions.prodShared.length || parsedOptions.devShared.length);
1167
+ virtualFiles = {};
1168
+ pluginList.forEach((plugin) => {
1169
+ if (plugin.virtualFile) Object.assign(virtualFiles, plugin.virtualFile);
1170
+ });
1171
+ }
1172
+ return {
1173
+ name: "sbee:federation",
1174
+ enforce: "post",
1175
+ options(_options) {
1176
+ if (!registerCount++) {
1177
+ _mode = options.mode ?? "production";
1178
+ registerPlugins(_mode, "");
1179
+ }
1180
+ if (typeof _options.input === "string") _options.input = { index: _options.input };
1181
+ _options.external = _options.external || [];
1182
+ if (!Array.isArray(_options.external)) _options.external = [_options.external];
1183
+ for (const pluginHook of pluginList) resolveHook(pluginHook.options)?.call(this, _options);
1184
+ return _options;
1185
+ },
1186
+ config(config, env) {
1187
+ _mode = _mode ?? env.mode;
1188
+ registerPlugins(_mode, env.command);
1189
+ registerCount++;
1190
+ for (const pluginHook of pluginList) resolveHook(pluginHook.config)?.call(this, config, env);
1191
+ builderInfo.builder = "vite";
1192
+ builderInfo.assetsDir = config?.build?.assetsDir ?? "assets";
1193
+ },
1194
+ configureServer(server) {
1195
+ for (const pluginHook of pluginList) resolveHook(pluginHook.configureServer)?.call(this, server);
1196
+ },
1197
+ configResolved(config) {
1198
+ for (const pluginHook of pluginList) resolveHook(pluginHook.configResolved)?.call(this, config);
1199
+ },
1200
+ buildStart(inputOptions) {
1201
+ for (const pluginHook of pluginList) resolveHook(pluginHook.buildStart)?.call(this, inputOptions);
1202
+ },
1203
+ async resolveId(...args) {
1204
+ const id = args[0];
1205
+ const importer = args[1];
1206
+ if (id in virtualFiles) return "\0virtual:" + id;
1207
+ if (id.startsWith("\0virtual:")) return id;
1208
+ if (importer && importer.startsWith("\0virtual:")) {
1209
+ const resolved = id;
1210
+ if (resolved in virtualFiles) return "\0virtual:" + resolved;
1211
+ }
1212
+ if (args[0] === "\0virtual:__federation_fn_import") return {
1213
+ id: "\0virtual:__federation_fn_import",
1214
+ moduleSideEffects: true
1215
+ };
1216
+ if (args[0] === "__federation_fn_satisfy") {
1217
+ const federationId = (await this.resolve("@sbee/vite-federation"))?.id;
1218
+ return await this.resolve(`${dirname(federationId)}/satisfy.mjs`);
1219
+ }
1220
+ if (args[0] === "virtual:__federation__") return {
1221
+ id: "\0virtual:__federation__",
1222
+ moduleSideEffects: true
1223
+ };
1224
+ return null;
1225
+ },
1226
+ load(...args) {
1227
+ const id = args[0];
1228
+ if (id.startsWith("\0virtual:")) {
1229
+ const key = id.slice(9);
1230
+ if (key in virtualFiles) return virtualFiles[key];
1231
+ }
1232
+ return null;
1233
+ },
1234
+ transform(code, id) {
1235
+ for (const pluginHook of pluginList) {
1236
+ const result = resolveHook(pluginHook.transform)?.call(this, code, id);
1237
+ if (result) return result;
1238
+ }
1239
+ return code;
1240
+ },
1241
+ moduleParsed(moduleInfo) {
1242
+ for (const pluginHook of pluginList) resolveHook(pluginHook.moduleParsed)?.call(this, moduleInfo);
1243
+ },
1244
+ outputOptions(outputOptions) {
1245
+ for (const pluginHook of pluginList) resolveHook(pluginHook.outputOptions)?.call(this, outputOptions);
1246
+ return outputOptions;
1247
+ },
1248
+ renderChunk(code, chunkInfo, _options) {
1249
+ for (const pluginHook of pluginList) {
1250
+ const result = resolveHook(pluginHook.renderChunk)?.call(this, code, chunkInfo, _options);
1251
+ if (result) return result;
1252
+ }
1253
+ return null;
1254
+ },
1255
+ generateBundle: function(_options, bundle, isWrite) {
1256
+ for (const pluginHook of pluginList) resolveHook(pluginHook.generateBundle)?.call(this, _options, bundle, isWrite);
1257
+ }
1258
+ };
1259
+ }
1260
+ //#endregion
1261
+ export { federation as default };