@fulgurjs/federation 4.3.0 → 5.0.0

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/config.cjs DELETED
@@ -1,174 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/config.ts
31
- var config_exports = {};
32
- __export(config_exports, {
33
- defineRepoConfig: () => defineRepoConfig,
34
- federationOptionsForApp: () => federationOptionsForApp,
35
- loadRepoConfig: () => loadRepoConfig
36
- });
37
- module.exports = __toCommonJS(config_exports);
38
- var import_meta = {};
39
- function defineRepoConfig(config) {
40
- return config;
41
- }
42
- async function loadRepoConfig(configPath) {
43
- const { pathToFileURL, fileURLToPath } = await import("url");
44
- const { createRequire } = await import("module");
45
- const fs = await import("fs");
46
- const os = await import("os");
47
- const path = await import("path");
48
- const selfDir = await (async () => {
49
- try {
50
- return path.dirname(fileURLToPath(import_meta.url));
51
- } catch {
52
- }
53
- try {
54
- return __dirname;
55
- } catch {
56
- }
57
- return "";
58
- })();
59
- const selfConfigJs = selfDir ? path.join(selfDir, "config.js") : "";
60
- const SELF_SPEC = selfConfigJs && fs.existsSync(selfConfigJs) ? pathToFileURL(selfConfigJs).href : "@fulgurjs-federation-config-unavailable";
61
- const rewriteSelfImports = (source) => source.replace(/(['"])@fulgurjs\/federation\/config\1/g, (_m, q) => `${q}${SELF_SPEC}${q}`);
62
- let cacheBust = 0;
63
- const importConfigs = async (cacheKey) => {
64
- return await import(`${cacheKey}?t=${Date.now()}-${++cacheBust}`);
65
- };
66
- let mod;
67
- if (configPath.endsWith(".json")) {
68
- mod = { default: JSON.parse(fs.readFileSync(configPath, "utf8")) };
69
- } else {
70
- const source = rewriteSelfImports(fs.readFileSync(configPath, "utf8"));
71
- const tmpBase = path.join(os.tmpdir(), `fulgurjs-config-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
72
- if (/\.(ts|mts|cts)$/.test(configPath)) {
73
- try {
74
- const tmpTs = `${tmpBase}.ts`;
75
- fs.writeFileSync(tmpTs, source);
76
- mod = await importConfigs(pathToFileURL(tmpTs).href);
77
- } catch (e) {
78
- if (!/Unexpected|SyntaxError|ERR_UNSUPPORTED_NODE_MODULES|ERR_UNKNOWN_FILE_EXTENSION|ERR_IMPORT_ATTRIBUTE/.test(String(e)) && process.version.startsWith("v2")) {
79
- throw e;
80
- }
81
- const requireFromConfig = createRequire(configPath);
82
- let esbuild;
83
- try {
84
- esbuild = requireFromConfig("esbuild");
85
- } catch {
86
- const requireFromSelf = createRequire(import_meta.url);
87
- esbuild = requireFromSelf("esbuild");
88
- }
89
- const out = esbuild.buildSync({ entryPoints: [configPath], bundle: false, write: false, format: "esm", target: "node18" });
90
- const jsFile = `${tmpBase}.mjs`;
91
- fs.writeFileSync(jsFile, rewriteSelfImports(out.outputFiles[0].text));
92
- mod = await importConfigs(pathToFileURL(jsFile).href);
93
- }
94
- } else {
95
- const jsFile = `${tmpBase}.mjs`;
96
- fs.writeFileSync(jsFile, source);
97
- mod = await importConfigs(pathToFileURL(jsFile).href);
98
- }
99
- }
100
- const cfg = mod.default;
101
- if (!cfg?.root) {
102
- throw new Error(
103
- `[fulgurjs:init] \u914D\u7F6E\u7F3A\u5C11 root\uFF08\u5DE5\u7A0B\u6839\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84\uFF09
104
- \u6839\u56E0\uFF1ACLI \u9700\u8981\u77E5\u9053\u5728\u54EA\u4E2A\u5DE5\u7A0B\u4E0A\u505A\u96C6\u6210
105
- \u4FEE\u6CD5\uFF1Afulgurjs.config.ts \u9876\u5C42\u8865 root: '/abs/path/to/repo'\uFF08\u8D77\u6B65\u6A21\u677F\uFF1Afulgurjs init\uFF09`
106
- );
107
- }
108
- if (!Array.isArray(cfg.apps) || cfg.apps.length === 0) {
109
- throw new Error("[fulgurjs:init] \u914D\u7F6E\u7F3A\u5C11 apps\uFF08\u81F3\u5C11\u4E00\u4E2A\u5BBF\u4E3B\u6216\u8FDC\u7A0B\u5E94\u7528\uFF09");
110
- }
111
- for (const app of cfg.apps) {
112
- if (!app.host && !app.remote) {
113
- throw new Error(
114
- `[fulgurjs:init] \u5E94\u7528 "${app.path}" \u65E2\u65E0 host \u4E5F\u65E0 remote \u89D2\u8272
115
- \u6839\u56E0\uFF1A\u5E94\u7528\u5FC5\u987B\u81F3\u5C11\u58F0\u660E\u4E00\u4E2A\u89D2\u8272
116
- \u4FEE\u6CD5\uFF1A\u5BBF\u4E3B\u8865 host: { remotePrefixes, remotes }\uFF08pages \u53EF\u9009\uFF09\uFF0C\u8FDC\u7A0B\u8865 remote: { exposes }`
117
- );
118
- }
119
- }
120
- return cfg;
121
- }
122
- function federationOptionsForApp(config, appPathOrName) {
123
- const app = config.apps.find(
124
- (a) => a.path === appPathOrName || a.name === appPathOrName
125
- );
126
- if (!app) {
127
- throw new Error(
128
- `[fulgurjs] \u5E94\u7528 "${appPathOrName}" \u4E0D\u5728\u4ED3\u5E93\u914D\u7F6E\u4E2D
129
- \u53EF\u7528\u5E94\u7528: ${config.apps.map((a) => `${a.path}(${a.name})`).join("\u3001")}
130
- \u4FEE\u6CD5: \u4FEE\u6B63\u5E94\u7528\u76EE\u5F55\u540D\u6216\u5BB9\u5668\u540D\uFF08fulgurjs.config.ts apps \u6570\u7EC4\u5185\u4E8C\u9009\u4E00\u5339\u914D\uFF09`
131
- );
132
- }
133
- if (!app.host && !app.remote) {
134
- throw new Error(
135
- `[fulgurjs] \u5E94\u7528 "${app.path}" \u65E2\u65E0 host \u4E5F\u65E0 remote \u89D2\u8272
136
- \u4FEE\u6CD5: \u5BBF\u4E3B\u8865 host: { remotePrefixes, remotes }\uFF0C\u8FDC\u7A0B\u8865 remote: { exposes }`
137
- );
138
- }
139
- const remotes = {};
140
- const remoteSource = /* @__PURE__ */ new Map();
141
- const mergeRemotes = (from, role) => {
142
- for (const [key, addr] of Object.entries(from ?? {})) {
143
- const prev = remotes[key];
144
- if (prev && (prev.dev !== addr.dev || prev.prod !== addr.prod)) {
145
- throw new Error(
146
- `[fulgurjs] \u5E94\u7528 "${app.path}" \u7684\u8FDC\u7A0B "${key}" \u5728 ${role} \u4E0E ${remoteSource.get(key)} \u4E24\u5904\u5730\u5740\u4E0D\u4E00\u81F4
147
- ${remoteSource.get(key)}: dev=${prev.dev} prod=${prev.prod}
148
- ${role}: dev=${addr.dev} prod=${addr.prod}
149
- \u4FEE\u6CD5: \u4FEE\u6B63 fulgurjs.config.ts \u4F7F\u4E24\u5904\u4E00\u81F4\uFF08\u540C\u4E00\u8FDC\u7A0B\u5728\u4E00\u4E2A\u5E94\u7528\u5185\u53EA\u80FD\u6709\u4E00\u4E2A\u5730\u5740\uFF09`
150
- );
151
- }
152
- remotes[key] = addr;
153
- remoteSource.set(key, role);
154
- }
155
- };
156
- mergeRemotes(app.host?.remotes, "host.remotes");
157
- mergeRemotes(app.remote?.remotes, "remote.remotes");
158
- const hasExposes = !!app.remote && Object.keys(app.remote.exposes).length > 0;
159
- const hasRemotes = Object.keys(remotes).length > 0;
160
- return {
161
- name: app.name,
162
- ...hasRemotes ? { remotes } : {},
163
- ...hasExposes ? { exposes: app.remote.exposes } : {},
164
- ...app.remote?.setup ? { setup: app.remote.setup } : {},
165
- ...app.shared ? { shared: app.shared } : {},
166
- devSharedSelf: app.devSharedSelf ?? (hasExposes || !!app.remote?.setup)
167
- };
168
- }
169
- // Annotate the CommonJS export names for ESM import in node:
170
- 0 && (module.exports = {
171
- defineRepoConfig,
172
- federationOptionsForApp,
173
- loadRepoConfig
174
- });
package/dist/config.d.cts DELETED
@@ -1,106 +0,0 @@
1
- import { F as FederationOptions } from './options-CRGpSmVj.cjs';
2
-
3
- /**
4
- * W1 fulgurjs.config.ts:单配置文件驱动的 schema + 加载器(项目无关,决策见排期文档 §4:
5
- * 主包内置 bin + 单配置文件驱动,可入库可复跑)。
6
- * init 只消费该配置生成通用样板(见 init.ts);插件运行时(federation())不读取本文件。
7
- */
8
- interface PageEntry {
9
- /** 宿主路由路径(参数段用 :xx) */
10
- route: string;
11
- /** 路由 name(命名跳转依赖) */
12
- name?: string;
13
- /** 远程 exposes 键(显式覆盖默认推导 pages/<去前缀去参数段>) */
14
- spec?: string;
15
- /** 页签标题 */
16
- title?: string;
17
- /** 页面保活开关(按页显式开启;默认关闭) */
18
- keepAlive?: boolean;
19
- }
20
- interface RemoteAddress {
21
- dev: string;
22
- prod: string;
23
- }
24
- interface HostConfig {
25
- /**
26
- * 页面路由表(可选):应用代码的页面表是运行时页面真源(供宿主路由与
27
- * createHostPages 共用),仓库配置中的副本仅供 init/explain 摘要与核对。
28
- * 不再强制——缺省时 CLI 摘要按实际提供数量报告。
29
- */
30
- pages?: PageEntry[];
31
- /** 页面 spec 推导规则(与宿主 createHostPages 的 deriveSpec 保持一致;缺省 = 去首段 + 剥 :参 段) */
32
- deriveSpec?: (route: string) => string;
33
- /** 路由前缀 → 远程名 */
34
- remotePrefixes: Record<string, string>;
35
- /** 消费的远程地址(键 = import 前缀;裸 URL,对象形式不支持 name@ 前缀) */
36
- remotes: Record<string, RemoteAddress>;
37
- }
38
- interface RemoteConfig {
39
- /** exposes:./键 → 源文件(独立页) */
40
- exposes: Record<string, string>;
41
- /** 远程初始化入口(默认导出 setup(context),可选具名导出 onSession(context)) */
42
- setup?: string;
43
- /** 反向消费的远程(双向联邦时) */
44
- remotes?: Record<string, RemoteAddress>;
45
- }
46
- interface AppConfig {
47
- /** 相对 root 的应用目录 */
48
- path: string;
49
- /** 联邦容器名 */
50
- name: string;
51
- /** dev 端口 */
52
- port: number;
53
- /** 部署/dev 的 URL 前缀,如 /main */
54
- base: string;
55
- /** 部署目录名(缺省取 base 去斜杠) */
56
- deployDir?: string;
57
- /** 宿主角色 */
58
- host?: HostConfig;
59
- /** 远程角色 */
60
- remote?: RemoteConfig;
61
- /** 该应用的 shared 表(缺省建议 vue/vue-router/pinia singleton,见 init 输出的样板) */
62
- shared?: Record<string, {
63
- singleton?: boolean;
64
- requiredVersion?: string;
65
- }>;
66
- /** 显式覆盖 dev 下自身源码参与 shared 协商改写;缺省按角色推断(见 federationOptionsForApp) */
67
- devSharedSelf?: boolean;
68
- }
69
- interface DeployConfig {
70
- /** NGINX 站点根(样板输出用,可选) */
71
- webRoot?: string;
72
- /** 监听端口(样板输出用,可选) */
73
- listen?: number;
74
- }
75
- interface RepoConfig {
76
- /** 工程根(monorepo 根或单应用仓库根) */
77
- root: string;
78
- apps: AppConfig[];
79
- deploy?: DeployConfig;
80
- }
81
- type UserConfig = Partial<RepoConfig>;
82
- /** 用户配置文件入口:仅做类型收窄(identity),不引入运行时逻辑 */
83
- declare function defineRepoConfig(config: UserConfig): UserConfig;
84
- /**
85
- * 加载 fulgurjs.config.ts(或 .js/.json)。
86
- * - 配置内的 `@fulgurjs/federation/config` 导入被重写为本包 dist/config.js 绝对路径——
87
- * init 之前工程依赖尚未安装(鸡生蛋),重写后零依赖可加载;
88
- * - TS 走 Node 原生类型剥离(Node ≥23.6 默认开启;配置文件须用可擦除语法——纯对象无 enum/namespace);
89
- * 老版本 Node 回退 esbuild 转译(先试配置工程,再试 CLI 自带依赖树)。
90
- */
91
- declare function loadRepoConfig(configPath: string): Promise<RepoConfig>;
92
- /**
93
- * 仓库配置 → 某应用的 federation() Vite 插件选项(§3.4 单配置驱动)。
94
- *
95
- * 转换范围:name、宿主/反向 remotes(两处同键冲突即报错,带两边值)、exposes、
96
- * 可选 setup、shared、devSharedSelf。build.target/base/端口/代理/插件顺序等仍归各应用
97
- * vite.config.ts 管理——本函数只生成 federation({...}) 的入参。
98
- *
99
- * devSharedSelf 来源(优先级):app.devSharedSelf 显式值 > 角色推断。
100
- * 推断规则:提供 exposes(含仅 setup)的应用为 true(其源码被宿主消费,需协商到宿主
101
- * 实例);纯宿主(只消费)为 false。双向联邦漏配该项曾是已知错误配置(§12.4),
102
- * 推断后不再依赖背诵。
103
- */
104
- declare function federationOptionsForApp(config: RepoConfig, appPathOrName: string): FederationOptions;
105
-
106
- export { type AppConfig, type DeployConfig, type HostConfig, type PageEntry, type RemoteAddress, type RemoteConfig, type RepoConfig, type UserConfig, defineRepoConfig, federationOptionsForApp, loadRepoConfig };
package/dist/config.d.ts DELETED
@@ -1,106 +0,0 @@
1
- import { F as FederationOptions } from './options-CRGpSmVj.js';
2
-
3
- /**
4
- * W1 fulgurjs.config.ts:单配置文件驱动的 schema + 加载器(项目无关,决策见排期文档 §4:
5
- * 主包内置 bin + 单配置文件驱动,可入库可复跑)。
6
- * init 只消费该配置生成通用样板(见 init.ts);插件运行时(federation())不读取本文件。
7
- */
8
- interface PageEntry {
9
- /** 宿主路由路径(参数段用 :xx) */
10
- route: string;
11
- /** 路由 name(命名跳转依赖) */
12
- name?: string;
13
- /** 远程 exposes 键(显式覆盖默认推导 pages/<去前缀去参数段>) */
14
- spec?: string;
15
- /** 页签标题 */
16
- title?: string;
17
- /** 页面保活开关(按页显式开启;默认关闭) */
18
- keepAlive?: boolean;
19
- }
20
- interface RemoteAddress {
21
- dev: string;
22
- prod: string;
23
- }
24
- interface HostConfig {
25
- /**
26
- * 页面路由表(可选):应用代码的页面表是运行时页面真源(供宿主路由与
27
- * createHostPages 共用),仓库配置中的副本仅供 init/explain 摘要与核对。
28
- * 不再强制——缺省时 CLI 摘要按实际提供数量报告。
29
- */
30
- pages?: PageEntry[];
31
- /** 页面 spec 推导规则(与宿主 createHostPages 的 deriveSpec 保持一致;缺省 = 去首段 + 剥 :参 段) */
32
- deriveSpec?: (route: string) => string;
33
- /** 路由前缀 → 远程名 */
34
- remotePrefixes: Record<string, string>;
35
- /** 消费的远程地址(键 = import 前缀;裸 URL,对象形式不支持 name@ 前缀) */
36
- remotes: Record<string, RemoteAddress>;
37
- }
38
- interface RemoteConfig {
39
- /** exposes:./键 → 源文件(独立页) */
40
- exposes: Record<string, string>;
41
- /** 远程初始化入口(默认导出 setup(context),可选具名导出 onSession(context)) */
42
- setup?: string;
43
- /** 反向消费的远程(双向联邦时) */
44
- remotes?: Record<string, RemoteAddress>;
45
- }
46
- interface AppConfig {
47
- /** 相对 root 的应用目录 */
48
- path: string;
49
- /** 联邦容器名 */
50
- name: string;
51
- /** dev 端口 */
52
- port: number;
53
- /** 部署/dev 的 URL 前缀,如 /main */
54
- base: string;
55
- /** 部署目录名(缺省取 base 去斜杠) */
56
- deployDir?: string;
57
- /** 宿主角色 */
58
- host?: HostConfig;
59
- /** 远程角色 */
60
- remote?: RemoteConfig;
61
- /** 该应用的 shared 表(缺省建议 vue/vue-router/pinia singleton,见 init 输出的样板) */
62
- shared?: Record<string, {
63
- singleton?: boolean;
64
- requiredVersion?: string;
65
- }>;
66
- /** 显式覆盖 dev 下自身源码参与 shared 协商改写;缺省按角色推断(见 federationOptionsForApp) */
67
- devSharedSelf?: boolean;
68
- }
69
- interface DeployConfig {
70
- /** NGINX 站点根(样板输出用,可选) */
71
- webRoot?: string;
72
- /** 监听端口(样板输出用,可选) */
73
- listen?: number;
74
- }
75
- interface RepoConfig {
76
- /** 工程根(monorepo 根或单应用仓库根) */
77
- root: string;
78
- apps: AppConfig[];
79
- deploy?: DeployConfig;
80
- }
81
- type UserConfig = Partial<RepoConfig>;
82
- /** 用户配置文件入口:仅做类型收窄(identity),不引入运行时逻辑 */
83
- declare function defineRepoConfig(config: UserConfig): UserConfig;
84
- /**
85
- * 加载 fulgurjs.config.ts(或 .js/.json)。
86
- * - 配置内的 `@fulgurjs/federation/config` 导入被重写为本包 dist/config.js 绝对路径——
87
- * init 之前工程依赖尚未安装(鸡生蛋),重写后零依赖可加载;
88
- * - TS 走 Node 原生类型剥离(Node ≥23.6 默认开启;配置文件须用可擦除语法——纯对象无 enum/namespace);
89
- * 老版本 Node 回退 esbuild 转译(先试配置工程,再试 CLI 自带依赖树)。
90
- */
91
- declare function loadRepoConfig(configPath: string): Promise<RepoConfig>;
92
- /**
93
- * 仓库配置 → 某应用的 federation() Vite 插件选项(§3.4 单配置驱动)。
94
- *
95
- * 转换范围:name、宿主/反向 remotes(两处同键冲突即报错,带两边值)、exposes、
96
- * 可选 setup、shared、devSharedSelf。build.target/base/端口/代理/插件顺序等仍归各应用
97
- * vite.config.ts 管理——本函数只生成 federation({...}) 的入参。
98
- *
99
- * devSharedSelf 来源(优先级):app.devSharedSelf 显式值 > 角色推断。
100
- * 推断规则:提供 exposes(含仅 setup)的应用为 true(其源码被宿主消费,需协商到宿主
101
- * 实例);纯宿主(只消费)为 false。双向联邦漏配该项曾是已知错误配置(§12.4),
102
- * 推断后不再依赖背诵。
103
- */
104
- declare function federationOptionsForApp(config: RepoConfig, appPathOrName: string): FederationOptions;
105
-
106
- export { type AppConfig, type DeployConfig, type HostConfig, type PageEntry, type RemoteAddress, type RemoteConfig, type RepoConfig, type UserConfig, defineRepoConfig, federationOptionsForApp, loadRepoConfig };
package/dist/config.js DELETED
@@ -1,136 +0,0 @@
1
- // src/config.ts
2
- function defineRepoConfig(config) {
3
- return config;
4
- }
5
- async function loadRepoConfig(configPath) {
6
- const { pathToFileURL, fileURLToPath } = await import("url");
7
- const { createRequire } = await import("module");
8
- const fs = await import("fs");
9
- const os = await import("os");
10
- const path = await import("path");
11
- const selfDir = await (async () => {
12
- try {
13
- return path.dirname(fileURLToPath(import.meta.url));
14
- } catch {
15
- }
16
- try {
17
- return __dirname;
18
- } catch {
19
- }
20
- return "";
21
- })();
22
- const selfConfigJs = selfDir ? path.join(selfDir, "config.js") : "";
23
- const SELF_SPEC = selfConfigJs && fs.existsSync(selfConfigJs) ? pathToFileURL(selfConfigJs).href : "@fulgurjs-federation-config-unavailable";
24
- const rewriteSelfImports = (source) => source.replace(/(['"])@fulgurjs\/federation\/config\1/g, (_m, q) => `${q}${SELF_SPEC}${q}`);
25
- let cacheBust = 0;
26
- const importConfigs = async (cacheKey) => {
27
- return await import(`${cacheKey}?t=${Date.now()}-${++cacheBust}`);
28
- };
29
- let mod;
30
- if (configPath.endsWith(".json")) {
31
- mod = { default: JSON.parse(fs.readFileSync(configPath, "utf8")) };
32
- } else {
33
- const source = rewriteSelfImports(fs.readFileSync(configPath, "utf8"));
34
- const tmpBase = path.join(os.tmpdir(), `fulgurjs-config-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
35
- if (/\.(ts|mts|cts)$/.test(configPath)) {
36
- try {
37
- const tmpTs = `${tmpBase}.ts`;
38
- fs.writeFileSync(tmpTs, source);
39
- mod = await importConfigs(pathToFileURL(tmpTs).href);
40
- } catch (e) {
41
- if (!/Unexpected|SyntaxError|ERR_UNSUPPORTED_NODE_MODULES|ERR_UNKNOWN_FILE_EXTENSION|ERR_IMPORT_ATTRIBUTE/.test(String(e)) && process.version.startsWith("v2")) {
42
- throw e;
43
- }
44
- const requireFromConfig = createRequire(configPath);
45
- let esbuild;
46
- try {
47
- esbuild = requireFromConfig("esbuild");
48
- } catch {
49
- const requireFromSelf = createRequire(import.meta.url);
50
- esbuild = requireFromSelf("esbuild");
51
- }
52
- const out = esbuild.buildSync({ entryPoints: [configPath], bundle: false, write: false, format: "esm", target: "node18" });
53
- const jsFile = `${tmpBase}.mjs`;
54
- fs.writeFileSync(jsFile, rewriteSelfImports(out.outputFiles[0].text));
55
- mod = await importConfigs(pathToFileURL(jsFile).href);
56
- }
57
- } else {
58
- const jsFile = `${tmpBase}.mjs`;
59
- fs.writeFileSync(jsFile, source);
60
- mod = await importConfigs(pathToFileURL(jsFile).href);
61
- }
62
- }
63
- const cfg = mod.default;
64
- if (!cfg?.root) {
65
- throw new Error(
66
- `[fulgurjs:init] \u914D\u7F6E\u7F3A\u5C11 root\uFF08\u5DE5\u7A0B\u6839\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84\uFF09
67
- \u6839\u56E0\uFF1ACLI \u9700\u8981\u77E5\u9053\u5728\u54EA\u4E2A\u5DE5\u7A0B\u4E0A\u505A\u96C6\u6210
68
- \u4FEE\u6CD5\uFF1Afulgurjs.config.ts \u9876\u5C42\u8865 root: '/abs/path/to/repo'\uFF08\u8D77\u6B65\u6A21\u677F\uFF1Afulgurjs init\uFF09`
69
- );
70
- }
71
- if (!Array.isArray(cfg.apps) || cfg.apps.length === 0) {
72
- throw new Error("[fulgurjs:init] \u914D\u7F6E\u7F3A\u5C11 apps\uFF08\u81F3\u5C11\u4E00\u4E2A\u5BBF\u4E3B\u6216\u8FDC\u7A0B\u5E94\u7528\uFF09");
73
- }
74
- for (const app of cfg.apps) {
75
- if (!app.host && !app.remote) {
76
- throw new Error(
77
- `[fulgurjs:init] \u5E94\u7528 "${app.path}" \u65E2\u65E0 host \u4E5F\u65E0 remote \u89D2\u8272
78
- \u6839\u56E0\uFF1A\u5E94\u7528\u5FC5\u987B\u81F3\u5C11\u58F0\u660E\u4E00\u4E2A\u89D2\u8272
79
- \u4FEE\u6CD5\uFF1A\u5BBF\u4E3B\u8865 host: { remotePrefixes, remotes }\uFF08pages \u53EF\u9009\uFF09\uFF0C\u8FDC\u7A0B\u8865 remote: { exposes }`
80
- );
81
- }
82
- }
83
- return cfg;
84
- }
85
- function federationOptionsForApp(config, appPathOrName) {
86
- const app = config.apps.find(
87
- (a) => a.path === appPathOrName || a.name === appPathOrName
88
- );
89
- if (!app) {
90
- throw new Error(
91
- `[fulgurjs] \u5E94\u7528 "${appPathOrName}" \u4E0D\u5728\u4ED3\u5E93\u914D\u7F6E\u4E2D
92
- \u53EF\u7528\u5E94\u7528: ${config.apps.map((a) => `${a.path}(${a.name})`).join("\u3001")}
93
- \u4FEE\u6CD5: \u4FEE\u6B63\u5E94\u7528\u76EE\u5F55\u540D\u6216\u5BB9\u5668\u540D\uFF08fulgurjs.config.ts apps \u6570\u7EC4\u5185\u4E8C\u9009\u4E00\u5339\u914D\uFF09`
94
- );
95
- }
96
- if (!app.host && !app.remote) {
97
- throw new Error(
98
- `[fulgurjs] \u5E94\u7528 "${app.path}" \u65E2\u65E0 host \u4E5F\u65E0 remote \u89D2\u8272
99
- \u4FEE\u6CD5: \u5BBF\u4E3B\u8865 host: { remotePrefixes, remotes }\uFF0C\u8FDC\u7A0B\u8865 remote: { exposes }`
100
- );
101
- }
102
- const remotes = {};
103
- const remoteSource = /* @__PURE__ */ new Map();
104
- const mergeRemotes = (from, role) => {
105
- for (const [key, addr] of Object.entries(from ?? {})) {
106
- const prev = remotes[key];
107
- if (prev && (prev.dev !== addr.dev || prev.prod !== addr.prod)) {
108
- throw new Error(
109
- `[fulgurjs] \u5E94\u7528 "${app.path}" \u7684\u8FDC\u7A0B "${key}" \u5728 ${role} \u4E0E ${remoteSource.get(key)} \u4E24\u5904\u5730\u5740\u4E0D\u4E00\u81F4
110
- ${remoteSource.get(key)}: dev=${prev.dev} prod=${prev.prod}
111
- ${role}: dev=${addr.dev} prod=${addr.prod}
112
- \u4FEE\u6CD5: \u4FEE\u6B63 fulgurjs.config.ts \u4F7F\u4E24\u5904\u4E00\u81F4\uFF08\u540C\u4E00\u8FDC\u7A0B\u5728\u4E00\u4E2A\u5E94\u7528\u5185\u53EA\u80FD\u6709\u4E00\u4E2A\u5730\u5740\uFF09`
113
- );
114
- }
115
- remotes[key] = addr;
116
- remoteSource.set(key, role);
117
- }
118
- };
119
- mergeRemotes(app.host?.remotes, "host.remotes");
120
- mergeRemotes(app.remote?.remotes, "remote.remotes");
121
- const hasExposes = !!app.remote && Object.keys(app.remote.exposes).length > 0;
122
- const hasRemotes = Object.keys(remotes).length > 0;
123
- return {
124
- name: app.name,
125
- ...hasRemotes ? { remotes } : {},
126
- ...hasExposes ? { exposes: app.remote.exposes } : {},
127
- ...app.remote?.setup ? { setup: app.remote.setup } : {},
128
- ...app.shared ? { shared: app.shared } : {},
129
- devSharedSelf: app.devSharedSelf ?? (hasExposes || !!app.remote?.setup)
130
- };
131
- }
132
- export {
133
- defineRepoConfig,
134
- federationOptionsForApp,
135
- loadRepoConfig
136
- };
@@ -1,100 +0,0 @@
1
- interface SharedHint {
2
- /** 放入共享作用域的本地模块;false 表示不提供本地副本 */
3
- import?: string | false;
4
- /** 用于从 package.json 推断 requiredVersion 的包名 */
5
- packageName?: string;
6
- /** 期望版本(完整 semver 语法 / false 接受任意) */
7
- requiredVersion?: string | false;
8
- /** 只允许单实例 */
9
- singleton?: boolean;
10
- /** 版本无效时抛运行时错误(默认:有本地副本且非 singleton 时为 true,对齐 webpack) */
11
- strictVersion?: boolean;
12
- /** 在共享作用域中的键(导入名与共享名不同时使用) */
13
- shareKey?: string;
14
- /** 共享作用域命名空间 */
15
- shareScope?: string;
16
- /** 同步提供(打进初始 chunk,总是被下载) */
17
- eager?: boolean;
18
- /** 提供版本显式指定 */
19
- version?: string;
20
- }
21
- type SharedConfig = string[] | Record<string, string | SharedHint>;
22
- interface ExposeHint {
23
- import: string;
24
- /** 稳定 chunk 文件名(不写则内部 id,随构建变化) */
25
- name?: string;
26
- }
27
- interface RemoteEntryConfig {
28
- external?: string;
29
- shareScope?: string;
30
- /** dev 专用地址(缺省回落 external) */
31
- dev?: string;
32
- /** prod 专用地址(缺省回落 external) */
33
- prod?: string;
34
- timeout?: number;
35
- retries?: number;
36
- /** 备用 remoteEntry 地址 */
37
- fallback?: string[];
38
- breaker?: {
39
- threshold?: number;
40
- resetMs?: number;
41
- };
42
- }
43
- interface FederationOptions {
44
- name: string;
45
- filename?: string;
46
- exposes?: Record<string, string | ExposeHint>;
47
- /**
48
- * 可选远程初始化入口:相对本应用根目录的 TS/JS 模块路径。
49
- * 模块须默认导出 `setup(context)`(应用级,容器首次加载业务模块前执行一次),
50
- * 可选具名导出 `onSession(context)`(会话级,按宿主 AppContext.sessionKey 去重执行)。
51
- * 缺省时无初始化行为(普通 exposes 语义完全不变)。
52
- */
53
- setup?: string;
54
- remotes?: Record<string, string | RemoteEntryConfig | (() => Promise<any>)>;
55
- shared?: SharedConfig;
56
- shareScope?: string;
57
- /** 仅支持 'module'(ESM);其他值在配置期报 CFG-011(webpack script/var 互操作未实现) */
58
- remoteType?: 'module';
59
- library?: {
60
- type?: string;
61
- name?: string;
62
- };
63
- runtime?: string | false;
64
- runtimeChunk?: boolean | 'single';
65
- manifest?: boolean | Record<string, unknown>;
66
- runtimePlugins?: string[];
67
- dts?: boolean | {
68
- dir?: string;
69
- mode?: 'source' | 'shim';
70
- };
71
- /** 接受并恒为 true:TLA 天然异步边界,无需手工 bootstrap(比 webpack 更进一步) */
72
- automaticAsyncBoundary?: boolean;
73
- /** 接受并恒为 true:preloadRemote 能力始终可用 */
74
- dataPrefetch?: boolean;
75
- /** 接受 no-op:Rollup/Rolldown 原生 tree-shaking 已覆盖 */
76
- usedExports?: boolean;
77
- ignoreUnusedSharedExports?: boolean;
78
- /**
79
- * dev 下自身源码(含依赖,需配合 optimizeDeps.exclude)是否参与 shared 协商改写。
80
- * 默认:纯 remote(无 remotes)为 true——被宿主消费的组件需协商到宿主实例;
81
- * 有 remotes 的宿主为 false——自身 import 即自身 provide,避免巨型工程 TLA/循环依赖风险。
82
- * 双向联邦(宿主同时 expose 组件给更高层消费)显式设 true。
83
- */
84
- devSharedSelf?: boolean;
85
- /**
86
- * dev 跨源访问策略(插件端点 /@fulgurjs-entry.js、/@fulgurjs-manifest.json 与 server.cors
87
- * 共用同一来源)。缺省 = '*'(现状兼容:端点与 server.cors 全放开);'*' = 显式全放开(不告警);
88
- * 数组 = 来源 allowlist(端点按 Origin 反射匹配,不匹配省略头;server.cors 传 { origin: [...] },
89
- * 用户显式配置的 server.cors 永远优先)。
90
- */
91
- devCorsOrigins?: string[] | '*';
92
- /**
93
- * dev manifest 是否携带 fsRoot(remote 根目录本机绝对路径,宿主 dts 类型直连用)。
94
- * 默认 true(现状兼容);false 时不写入 manifest,宿主 dts 降级为 any 桩并给出提示。
95
- * fsRoot 是 dev-only 字段,永不进入 prod manifest。
96
- */
97
- devFsRoot?: boolean;
98
- }
99
-
100
- export type { FederationOptions as F };