@fulgurjs/federation 3.0.0 → 4.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/CHANGELOG.md +25 -0
- package/README.md +27 -25
- package/dist/chunk-AYS56IRF.js +42 -0
- package/dist/{chunk-YBS2PO34.js → chunk-X4LZDAZQ.js} +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.cjs +85 -43
- package/dist/index.js +85 -43
- package/dist/runtime-entry.d.ts +279 -0
- package/dist/runtime-entry.js +5 -0
- package/dist/runtime.js +2 -2
- package/dist/vue-adapter.cjs +66 -0
- package/dist/vue-adapter.d.cts +16 -0
- package/dist/vue-adapter.d.ts +16 -0
- package/dist/vue-adapter.js +6 -0
- package/dist/vue.cjs +17 -18
- package/dist/vue.d.cts +4 -33
- package/dist/vue.d.ts +4 -33
- package/dist/vue.js +3 -845
- package/docs//350/277/201/347/247/273/346/214/207/345/215/227.md +12 -10
- package/package.json +13 -5
- package/client.d.ts +0 -180
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.0.0(2026-09-24)
|
|
4
|
+
|
|
5
|
+
### 应用代码改用物理入口
|
|
6
|
+
|
|
7
|
+
- 唯一公开应用入口改为 `@fulgurjs/federation/runtime`,提供实际的 ESM 文件与类型声明;配置入口仍为包根和 `/config`。
|
|
8
|
+
- `virtual:fulgurjs-api` 与 `@fulgurjs/federation/client` 删除。3.x 用户将应用导入改为 `/runtime`,并清除 tsconfig 中的 `client` 类型项及旧生成的 `fulgurjs-runtime.d.ts`。
|
|
9
|
+
- 开发态 exposes 使用内部页面级代理;`remoteComponent()` 保持同步返回 Vue 组件。`remoteSchema` 静态具名导入由插件拆出,非开发环境为空清单。
|
|
10
|
+
- Vue 适配层与运行时内核分离,公开 ESM 图只引用一份 `runtime.js`。
|
|
11
|
+
- `/runtime` 只提供 ESM `import` 条件,使用时需安装 Vue;包根和 `/config` 的 CJS 条件不变。新入口沿用 3.0.x 实际 JS 门面的值导出,不提供 `runtime` 对象或 default(旧 `client.d.ts` 曾多声明这两项)。
|
|
12
|
+
|
|
13
|
+
| 旧应用写法 | 4.0.0 写法 |
|
|
14
|
+
|---|---|
|
|
15
|
+
| `virtual:fulgurjs-api`(3.0.x) | `@fulgurjs/federation/runtime` |
|
|
16
|
+
| `virtual:fulgurjs-runtime`(≤2.x) | `@fulgurjs/federation/runtime` |
|
|
17
|
+
| `@fulgurjs/federation/context`、`/pages`、`/vue`(≤2.x) | `@fulgurjs/federation/runtime` |
|
|
18
|
+
| `import remoteSchema from 'virtual:fulgurjs-remote-schema'` | `import { remoteSchema } from '@fulgurjs/federation/runtime'` |
|
|
19
|
+
| tsconfig `types` 中的 `@fulgurjs/federation/client` | 删除该项;类型由 `/runtime` 的包导出解析 |
|
|
20
|
+
|
|
21
|
+
## 3.0.1(2026-09-24)
|
|
22
|
+
|
|
23
|
+
### 修复
|
|
24
|
+
|
|
25
|
+
- **runtime-proxy 的 `parseSpec` 保持同步语义**:3.0.0 的 serve 门面把 runtime 部分转发到惰性单例委托时,`parseSpec` 也在 promise 转发列表里——同步纯函数经 promise 转发返回 Promise,返回对象的属性全部为 undefined。修复:`parseSpec` 同步直读页面级单例(时序契约同 shareScopeMap)。
|
|
26
|
+
|
|
27
|
+
|
|
3
28
|
## 3.0.0(2026-09-24)
|
|
4
29
|
|
|
5
30
|
### 破坏性变更:应用代码唯一 API 入口 `virtual:fulgurjs-api`
|
package/README.md
CHANGED
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
- **HMR 全链路**:remote 改动 → host 页面热更,L1 组件热替换 / L2 状态保留 / L3 错误覆盖与恢复
|
|
33
33
|
- **零报错纪律**:配置问题启动瞬间三段式报错;联邦失败显式抛错(错误码 + 可执行修复建议),**无任何静默兜底路径**
|
|
34
34
|
- **CLI(主包内置 bin)**:`fulgurjs init`——`fulgurjs.config.ts` 单配置驱动的迁移生成器(模板 = 真实工程验证形态:vite 配置/路由表/桥/联邦启动器/NGINX conf 全量编码,锚点补丁幂等可续跑);`fulgurjs doctor`——部署面体检(remoteEntry/manifest/HTML 缓存头与形态、CORS、chunk 抽样可达、版本 skew 预演、`--dev` 端口探测)
|
|
35
|
-
-
|
|
36
|
-
- **Vue 直渲染**:`remoteComponent('remote/X')
|
|
35
|
+
- **跨应用传值与方法引用**:`@fulgurjs/federation/runtime` 导出 `provideAppContext` / `getAppContext` / `requireAppContext`(缺键 `CC-001` 三段式、独立直开远程页 `CC-002` 显式)。宿主桥一次写入页面级单例(user/token/getToken/store/hostApp/locale/events 标准字段 + 项目扩展位),远程 boot 显式校验消费;方法引用两条通道 = context 携带函数引用(热路径直调)+ exposes 方法模块 `loadRemote('remote/api')`(低频重逻辑)。数据语义 = 传输层快照 + 函数引用,非响应式(与乾坤 props 同语义;"实时"靠函数引用拉取 / 宿主 pinia 共享 / 登录刷新三通道)`provideAppContext` / `getAppContext` / `requireAppContext`(缺键 `CC-001` 三段式、独立直开远程页 `CC-002` 显式)。宿主桥一次写入页面级单例(user/token/getToken/store/hostApp/locale/events 标准字段 + 项目扩展位),远程 boot 显式校验消费;方法引用两条通道 = context 携带函数引用(热路径直调)+ exposes 方法模块 `loadRemote('remote/api')`(低频重逻辑)。数据语义 = 传输层快照 + 函数引用,非响应式(与乾坤 props 同语义;"实时"靠函数引用拉取 / 宿主 pinia 共享 / 登录刷新三通道)
|
|
36
|
+
- **Vue 直渲染**:`remoteComponent('remote/X')`(`@fulgurjs/federation/runtime` 导出)——`defineAsyncComponent + loadRemote` 的标准封装,加载失败显式错误占位(错误码+根因+修法),runtime.js 零框架依赖零体积增量
|
|
37
37
|
- **CSP 友好**:原生 ESM 加载路径全程无 `eval` / `new Function`,可在严格 CSP(无 `unsafe-eval`)下运行
|
|
38
38
|
- **全链路错误码体系(30 码)**:CFG/DEV/BLD/MFU/CC 五段 + 手册 §8 码表防漂移校验
|
|
39
39
|
|
|
@@ -99,13 +99,13 @@ export default defineConfig({
|
|
|
99
99
|
import Button from 'remote-a/Button'
|
|
100
100
|
|
|
101
101
|
// 动态导入 / 运行时 API
|
|
102
|
-
import { loadRemote, registerRemote, preloadRemote } from '
|
|
102
|
+
import { loadRemote, registerRemote, preloadRemote } from '@fulgurjs/federation/runtime'
|
|
103
103
|
|
|
104
104
|
const Chart = defineAsyncComponent(() => loadRemote('remote-a/Chart').then(m => m.default))
|
|
105
105
|
|
|
106
106
|
// Vue 组件直渲染:remoteComponent = 上行的标准封装
|
|
107
107
|
// 加载失败显式错误占位(错误码+根因+修法),loading/错误组件可自定义
|
|
108
|
-
import { remoteComponent } from '
|
|
108
|
+
import { remoteComponent } from '@fulgurjs/federation/runtime'
|
|
109
109
|
const ChartCard = remoteComponent('remote-a/Chart', { retries: 2 })
|
|
110
110
|
|
|
111
111
|
// 构建时地址未知的远程?运行时注册(对齐 webpack promise remote 语义)
|
|
@@ -129,15 +129,17 @@ const Panel = await loadRemote('shop/Panel', {
|
|
|
129
129
|
|
|
130
130
|
> 以上只是最小面。**全部选项(remotes 四形态/shared 九个开关/dts/runtimePlugins…)、运行时 API、CLI、错误码见下方 [API 参考](#api-参考)。**
|
|
131
131
|
|
|
132
|
-
**唯一 API 入口(
|
|
132
|
+
**唯一 API 入口(4.0.0)**:应用代码的一切联邦导入——运行时函数、context 三函数、`definePages`、`remoteSchema`、`remoteComponent`——**只来自物理子路径**:
|
|
133
133
|
|
|
134
134
|
```ts
|
|
135
|
-
import { loadRemote, loadShare, preloadRemote, provideAppContext, getAppContext, definePages, remoteSchema, remoteComponent } from '
|
|
135
|
+
import { loadRemote, loadShare, preloadRemote, provideAppContext, getAppContext, definePages, remoteSchema, remoteComponent } from '@fulgurjs/federation/runtime'
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
旧应用入口 `virtual:fulgurjs-api` 已删除;`virtual:fulgurjs-runtime` 仅供插件内部使用。旧 context/pages/vue 子路径也不再公开(迁移映射见 CHANGELOG 4.0.0)。
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
`/runtime` 是 ESM 应用入口,包含 `remoteComponent`,所以使用此入口的应用需安装 Vue。`remoteSchema` 必须以具名静态导入取得 dev 探针结果;命名空间导入、动态导入和 re-export 不触发探针拆写。未经过插件转换时该值是空表。包根与 `/config` 仍可在 Node 配置中使用。
|
|
141
|
+
|
|
142
|
+
dev 下 remote 跑它自己的 `vite dev`(容器入口 `/@fulgurjs-entry.js` 由插件中间件直出);build 下 expose 自动拆独立 chunk、shared 自动剥离——同一份配置两端通用。
|
|
141
143
|
|
|
142
144
|
## CLI:init 起步模板 + doctor 部署体检
|
|
143
145
|
|
|
@@ -259,22 +261,22 @@ shared: {
|
|
|
259
261
|
|
|
260
262
|
版本裁决语义对齐 webpack:满足 requiredVersion 的最高版本胜出;已加载版本永不替换;singleton 收敛到唯一实例(skew 告警 MFU-010);strictVersion 不满足抛 MFU-003。
|
|
261
263
|
|
|
262
|
-
### 2. 运行时 API —
|
|
264
|
+
### 2. 运行时 API — `@fulgurjs/federation/runtime`
|
|
263
265
|
|
|
264
266
|
**任何文件都直接静态导入**——宿主页面、exposes 目标文件(远程页面)都一样,插件自动保证同一页面只有一个运行时实例(远程页面里的导入会被自动改写为惰性单例委托):
|
|
265
267
|
|
|
266
268
|
```ts
|
|
267
269
|
// 宿主页面、远程页面,写法完全一致
|
|
268
|
-
import { loadRemote } from '
|
|
270
|
+
import { loadRemote } from '@fulgurjs/federation/runtime'
|
|
269
271
|
```
|
|
270
272
|
|
|
271
273
|
> 仍可绕过代理直取全局单例(等价,调试用):`(globalThis as any).__FULGURJS_RUNTIME__`。
|
|
272
274
|
|
|
273
275
|
#### 函数总表
|
|
274
276
|
|
|
275
|
-
> 下表全部函数与 `definePages` / `remoteSchema` / `provideAppContext` 等 context 函数 / `remoteComponent` 都从**唯一入口**
|
|
277
|
+
> 下表全部函数与 `definePages` / `remoteSchema` / `provideAppContext` 等 context 函数 / `remoteComponent` 都从**唯一入口** `@fulgurjs/federation/runtime` 导入(见 §2);旧入口已删除。
|
|
276
278
|
|
|
277
|
-
> **TS
|
|
279
|
+
> **TS 提示**:`@fulgurjs/federation/runtime` 的类型随包发布,由包的 `exports` 和 `typesVersions` 直接解析;不需要 `client` 类型垫片。dev 启动时插件仅在类型目录(默认 `src/fulgurjs/types/`)生成远程 exposes 的类型声明。
|
|
278
280
|
|
|
279
281
|
| 函数 | 签名 | 说明 |
|
|
280
282
|
|---|---|---|
|
|
@@ -308,7 +310,7 @@ const Panel = await loadRemote('shop/Panel', {
|
|
|
308
310
|
> hook 错误契约:`beforeLoadRemote` / `afterLoadRemote` 是**观测 hook**——自身抛错只告警、不改写加载结果;`resolveShare` 是**决策 hook**——显式抛错向调用方传播(绝不静默回退到另一份共享依赖)。
|
|
309
311
|
|
|
310
312
|
```ts
|
|
311
|
-
import type { RuntimePlugin } from '
|
|
313
|
+
import type { RuntimePlugin } from '@fulgurjs/federation/runtime'
|
|
312
314
|
|
|
313
315
|
export default {
|
|
314
316
|
name: 'my-plugin',
|
|
@@ -332,13 +334,13 @@ export default {
|
|
|
332
334
|
| `window.__FULGURJS_APP_CONFIG__` | W4 全局配置镜像 |
|
|
333
335
|
| `window` 事件 `fulgurjs:error` | `CustomEvent<{ remote, error }>`,所有远程加载/共享错误都会发出 |
|
|
334
336
|
|
|
335
|
-
### 3. `definePages` —
|
|
337
|
+
### 3. `definePages` — 宿主页面路由表(`@fulgurjs/federation/runtime`)
|
|
336
338
|
|
|
337
339
|
宿主把「URL 路径 → 远程 exposes 键」的映射表交给它校验,带参路由的静默冲突在启动期报错而不是运行时加载错组件:
|
|
338
340
|
|
|
339
341
|
```ts
|
|
340
|
-
import { definePages } from '
|
|
341
|
-
import { remoteSchema } from '
|
|
342
|
+
import { definePages } from '@fulgurjs/federation/runtime'
|
|
343
|
+
import { remoteSchema } from '@fulgurjs/federation/runtime' // dev 自动生成;build 恒为空(诚实降级)
|
|
342
344
|
|
|
343
345
|
export const PAGES = definePages(
|
|
344
346
|
[
|
|
@@ -466,10 +468,10 @@ export default defineRepoConfig({
|
|
|
466
468
|
|
|
467
469
|
NGINX 部署模板(no-cache 规则 + 深链回退)用 `fulgurjs init --config` 自动生成。
|
|
468
470
|
|
|
469
|
-
### 8. `remoteComponent` — Vue
|
|
471
|
+
### 8. `remoteComponent` — Vue 远程组件直渲染(`@fulgurjs/federation/runtime`)
|
|
470
472
|
|
|
471
473
|
```ts
|
|
472
|
-
import { remoteComponent } from '
|
|
474
|
+
import { remoteComponent } from '@fulgurjs/federation/runtime'
|
|
473
475
|
|
|
474
476
|
const FederatedBusinessForm = remoteComponent('demo-host/FormRouterPage')
|
|
475
477
|
const FederatedAmisForm = remoteComponent('demo-host/AmisFormRouterPage', {
|
|
@@ -492,16 +494,16 @@ const FederatedAmisForm = remoteComponent('demo-host/AmisFormRouterPage', {
|
|
|
492
494
|
- 内部 = `defineAsyncComponent({ loader: () => loadRemote(spec, opts).then(m => m.default ?? m) })`,返回标准 Vue 异步组件,`props`(如 `form-params`)在使用处直接透传;
|
|
493
495
|
- **无任何兜底/降级**(H3 零兜底):加载失败显式进错误态;不传 `errorComponent` 时渲染内置占位(错误码 + 根因 + 修法三段式文案),`window` 的 `fulgurjs:error` 事件由 runtime 层照常发出;
|
|
494
496
|
- 模块去重沿用 `loadRemote` 内部 Promise 缓存——同 spec 多组件实例只加载一次容器模块;
|
|
495
|
-
- `vue` 为**可选 peerDependency**(`peerDependenciesMeta.optional
|
|
496
|
-
- 运行时实例经 `globalThis.__FULGURJS_RUNTIME__` 页面级单例复用,与
|
|
497
|
+
- `vue` 为**可选 peerDependency**(`peerDependenciesMeta.optional`):只使用包根或 `/config` 时无需安装;应用使用 `/runtime` 时需要安装 Vue,因为该入口导出 `remoteComponent`。内部 `runtime.js` 仍不导入 Vue,体积零增量;
|
|
498
|
+
- 运行时实例经 `globalThis.__FULGURJS_RUNTIME__` 页面级单例复用,与 `@fulgurjs/federation/runtime` 的导入殊途同归,无需额外接线。
|
|
497
499
|
|
|
498
|
-
### 9. `AppContext` —
|
|
500
|
+
### 9. `AppContext` — 跨应用传值与方法引用(`@fulgurjs/federation/runtime`)
|
|
499
501
|
|
|
500
502
|
宿主向子应用传值、子应用向宿主反向注册方法,一律走这条一等公民通道(对标乾坤 `props`,但带类型与错误契约)——不再各自挂 `window.*` 裸口子。
|
|
501
503
|
|
|
502
504
|
```ts
|
|
503
505
|
// —— 宿主桥(host/src/fulgurjs/host/bridge.ts):登录完成后一次性提供 ——
|
|
504
|
-
import { provideAppContext } from '
|
|
506
|
+
import { provideAppContext } from '@fulgurjs/federation/runtime'
|
|
505
507
|
|
|
506
508
|
provideAppContext({
|
|
507
509
|
user, // 宿主登录用户原始形态
|
|
@@ -514,14 +516,14 @@ provideAppContext({
|
|
|
514
516
|
})
|
|
515
517
|
|
|
516
518
|
// —— 远程 boot(exposes/federatedBoot.ts):显式校验消费 ——
|
|
517
|
-
import { requireAppContext } from '
|
|
519
|
+
import { requireAppContext } from '@fulgurjs/federation/runtime'
|
|
518
520
|
|
|
519
521
|
const { store, user, hostApp } = requireAppContext('store', 'user', 'hostApp')
|
|
520
522
|
// 缺任一键 → [fulgurjs:CC-001] 三段式抛错(got / expected / example 指向宿主桥);
|
|
521
523
|
// 页面无运行时单例(独立直开远程页)→ [fulgurjs:CC-002] 显式,修法 = 经宿主联邦加载。
|
|
522
524
|
|
|
523
525
|
// —— 远程页面读点 ——
|
|
524
|
-
import { getAppContext } from '
|
|
526
|
+
import { getAppContext } from '@fulgurjs/federation/runtime'
|
|
525
527
|
const dict = getAppContext().events?.main?.getDictItems?.('sex')
|
|
526
528
|
|
|
527
529
|
// —— 子应用反向注册方法给宿主(页面 onUnmounted 时记得摘除,见迁移指南「页面卸载清理清单」)——
|
|
@@ -669,7 +671,7 @@ const PREFETCH_REMOTES: string[] = []
|
|
|
669
671
|
#### 9.1.5 IDE 说明(`src/fulgurjs/` 目录的红波浪线)
|
|
670
672
|
|
|
671
673
|
- `types/` 下的 `*.d.ts` 是**插件每次 dev 自动生成**的类型直连声明(勿手改):内部 `export * from '../../../demo-app-xxx/src/***.vue'` 指向**兄弟工程的源码**。命令行 `vue-tsc --noEmit`(走本应用 tsconfig,skipLibCheck 生效)为 **0 错误**;但 **VSCode/Volar 在打开这些 d.ts 时**可能把工程外 .vue 用推断项目(inferred project,无 tsconfig 上下文)展开检查,显示大片"找不到模块 '@/...'"——**仅编辑器显示问题,不影响命令行检查与构建**,不打开 `types/` 生成物即无感。
|
|
672
|
-
- 升级插件版本后若 `import ... from '
|
|
674
|
+
- 升级插件版本后若 `import ... from '@fulgurjs/federation/runtime'` 报 ts(2307):是 IDE 的 TS 服务缓存了旧包——`Restart TS Server`(⌘⇧P)或重开窗口即可。3.0.0 起旧子路径(`@fulgurjs/federation/{context,pages,vue}`)已从包 exports 删除,按迁移映射改为 `@fulgurjs/federation/runtime`。
|
|
673
675
|
- **根治红波浪线**:`federation({ dts: { mode: 'shim' } })` —— 生成物不再引用跨工程源文件(宽松占位形态),IDE 全程干净;取舍是失去"跳转直达远程源码"的补全能力(默认 `source` 不变,按项目偏好选择)。
|
|
674
676
|
|
|
675
677
|
## ⚠️ 首次使用避坑指南(真实迁移项目踩坑实录)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/vue-adapter.ts
|
|
2
|
+
import { defineAsyncComponent, defineComponent, h } from "vue";
|
|
3
|
+
var ERROR_STYLE = {
|
|
4
|
+
padding: "16px",
|
|
5
|
+
border: "1px solid #fde2e2",
|
|
6
|
+
borderRadius: "4px",
|
|
7
|
+
background: "#fef0f0",
|
|
8
|
+
color: "#c45656",
|
|
9
|
+
fontSize: "13px",
|
|
10
|
+
lineHeight: "1.6"
|
|
11
|
+
};
|
|
12
|
+
var RemoteErrorPlaceholder = defineComponent({
|
|
13
|
+
name: "FulgurjsRemoteError",
|
|
14
|
+
props: { error: { type: Object, default: void 0 } },
|
|
15
|
+
setup(props) {
|
|
16
|
+
return () => {
|
|
17
|
+
const err = props.error;
|
|
18
|
+
const code = err?.code ?? "UNKNOWN";
|
|
19
|
+
const message = err?.message ?? String(props.error ?? "unknown error");
|
|
20
|
+
return h("div", { style: ERROR_STYLE }, [
|
|
21
|
+
h("p", { style: "margin:0 0 4px;font-weight:600" }, `\u8FDC\u7A0B\u7EC4\u4EF6\u52A0\u8F7D\u5931\u8D25\uFF08\u9519\u8BEF\u7801 ${code}\uFF09`),
|
|
22
|
+
h("p", { style: "margin:0 0 8px;word-break:break-all" }, message),
|
|
23
|
+
h("p", { style: "margin:0" }, "\u4FEE\u6CD5\uFF1A\u2460 \u6838\u5BF9 spec \u7684\u300C\u8FDC\u7A0B\u540D/expose \u540D\u300D\u4E0E\u8FDC\u7A0B\u5E94\u7528 exposes \u662F\u5426\u4E00\u81F4\uFF08MFU-006/008\uFF09\uFF1B\u2461 \u6838\u5BF9 remotes \u5730\u5740\u7AEF\u53E3\u4E0E\u8FDC\u7A0B\u670D\u52A1\u53EF\u8FBE\u6027\u3001remoteEntry \u662F\u5426\u53EF\u8BBF\u95EE\uFF08MFU-001\uFF09\uFF1B\u2462 \u67E5\u770B window \u7684 fulgurjs:error \u4E8B\u4EF6\u4E0E console \u540C\u6E90\u9519\u8BEF\u5B9A\u4F4D\u6839\u56E0\u3002")
|
|
24
|
+
]);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
function createRemoteComponent(loadRemote) {
|
|
29
|
+
return function remoteComponent(spec, opts = {}) {
|
|
30
|
+
return defineAsyncComponent({
|
|
31
|
+
loader: () => loadRemote(spec, { retries: opts.retries }).then((m) => m.default ?? m),
|
|
32
|
+
loadingComponent: opts.loadingComponent,
|
|
33
|
+
errorComponent: opts.errorComponent ?? RemoteErrorPlaceholder,
|
|
34
|
+
delay: opts.delay,
|
|
35
|
+
timeout: opts.timeout
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
createRemoteComponent
|
|
42
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -205,8 +205,8 @@ async function inspectConfig(configPath) {
|
|
|
205
205
|
out.push("2. expose \u4E00\u5F8B\u6307\u5411\u72EC\u7ACB\u9875\uFF08\u9875\u9762\u4ECE\u8DEF\u7531\u53D6\u53C2\uFF09\uFF1B\u7EC4\u4EF6\u9700\u8981\u5FC5\u586B props \u65F6\u7ED9\u9ED8\u8BA4\u503C\uFF08BLD-003\uFF09");
|
|
206
206
|
out.push("3. shared \u91CC vue / vue-router / pinia \u5EFA\u8BAE singleton: true\u2014\u2014\u8DE8\u5E94\u7528\u5FC5\u987B\u540C\u5B9E\u4F8B\uFF08\u5168\u5C40\u54CD\u5E94\u6027\u3001getActivePinia\u3001\u8DEF\u7531\u6CE8\u5165\uFF09");
|
|
207
207
|
out.push("4. \u8FDC\u7A0B\u7684\u5168\u5C40\u526F\u4F5C\u7528\uFF08\u5168\u5C40\u7EC4\u4EF6/\u6307\u4EE4/\u542F\u52A8\u671F\u521D\u59CB\u5316\uFF09\u5C01\u88C5\u4E3A\u542F\u52A8\u5668\u6A21\u5757\u5E76 expose\uFF0C\u5BBF\u4E3B\u5728 loadRemote \u9875\u9762\u524D\u8C03\u7528\uFF1B");
|
|
208
|
-
out.push(" \u8DE8\u5E94\u7528\u4F20\u503C\uFF08locale/store/\u4E8B\u4EF6\u7B49\uFF09\u7EDF\u4E00\u8D70
|
|
209
|
-
out.push("5. \u5E94\u7528\u4EE3\u7801\u552F\u4E00 API \u5165\u53E3\uFF1Aimport { loadRemote, provideAppContext, getAppContext, definePages, remoteSchema, remoteComponent } from '
|
|
208
|
+
out.push(" \u8DE8\u5E94\u7528\u4F20\u503C\uFF08locale/store/\u4E8B\u4EF6\u7B49\uFF09\u7EDF\u4E00\u8D70 @fulgurjs/federation/runtime \u7684 context \u51FD\u6570\uFF1A\u5BBF\u4E3B provideAppContext \u4E00\u6B21\u5199\u5165\uFF0C\u8FDC\u7A0B boot \u7528 getAppContext / requireAppContext \u6D88\u8D39");
|
|
209
|
+
out.push("5. \u5E94\u7528\u4EE3\u7801\u552F\u4E00 API \u5165\u53E3\uFF1Aimport { loadRemote, provideAppContext, getAppContext, definePages, remoteSchema, remoteComponent } from '@fulgurjs/federation/runtime'\u2014\u20144.0.0 \u8D77 virtual:fulgurjs-api \u5DF2\u5220\u9664\uFF0C\u7C7B\u578B\u7531\u7269\u7406\u5B50\u8DEF\u5F84\u76F4\u63A5\u89E3\u6790");
|
|
210
210
|
out.push('6. dev \u51B7\u542F\u52A8\u9996\u8F6E 30~60s \u6709\u9884\u6784\u5EFA\u7A97\u53E3\uFF08\u77AC\u65F6 504/"ce"\uFF0CDEV-010\uFF09\uFF1A\u5148\u771F\u5B9E\u6253\u5F00\u9875\u9762\u9884\u70ED\u518D\u505A\u65AD\u8A00');
|
|
211
211
|
out.push("7. \u90E8\u7F72\u540E\u4F53\u68C0\uFF1Afulgurjs doctor --base <URL> --apps <\u5E94\u7528...>\uFF08\u7F13\u5B58\u5934/\u8D44\u6E90\u5F62\u6001/CORS/chunk \u53EF\u8FBE/\u7248\u672C skew\uFF09");
|
|
212
212
|
out.push("8. \u90E8\u7F72\u8BED\u4E49\uFF1AremoteEntry/manifest/index.html \u5FC5\u987B no-cache\uFF08\u4E25\u7981 immutable\uFF09\uFF1B\u5E26 hash \u7684 assets \u957F\u7F13\u5B58");
|
package/dist/index.cjs
CHANGED
|
@@ -43,7 +43,7 @@ var import_node_fs = __toESM(require("fs"), 1);
|
|
|
43
43
|
var import_node_path = __toESM(require("path"), 1);
|
|
44
44
|
|
|
45
45
|
// src/version.ts
|
|
46
|
-
var RUNTIME_VERSION = "
|
|
46
|
+
var RUNTIME_VERSION = "4.0.0";
|
|
47
47
|
|
|
48
48
|
// src/dev-cors.ts
|
|
49
49
|
function normalizeDevCorsOrigins(input) {
|
|
@@ -802,8 +802,7 @@ function genRuntimeProxyModule() {
|
|
|
802
802
|
"registerRemotes",
|
|
803
803
|
"registerShare",
|
|
804
804
|
"initSharing",
|
|
805
|
-
"registerPlugins"
|
|
806
|
-
"parseSpec"
|
|
805
|
+
"registerPlugins"
|
|
807
806
|
];
|
|
808
807
|
const lines = [
|
|
809
808
|
`let __fulgurjs_mod_p;`,
|
|
@@ -812,6 +811,10 @@ function genRuntimeProxyModule() {
|
|
|
812
811
|
` return await __fulgurjs_mod_p;`,
|
|
813
812
|
`};`,
|
|
814
813
|
...promiseApis.map((m) => `export const ${m} = (...a) => __fulgurjs_rt().then((m2) => m2.${m}(...a));`),
|
|
814
|
+
// parseSpec 是同步纯函数:promise 转发会把返回值变成 Promise(返回对象上的属性
|
|
815
|
+
// 全部 undefined,3.0.0 门面切换时实测)——同步直读页面级单例(调用期单例必已由
|
|
816
|
+
// init 建立,时序契约同 shareScopeMap)
|
|
817
|
+
`export const parseSpec = (...a) => (globalThis).__FULGURJS_RUNTIME__.parseSpec(...a);`,
|
|
815
818
|
// shareScopeMap:本模块只会在应用代码 import 链里被求值——页面运行期单例必已由 init 建立
|
|
816
819
|
// (时序契约:宿主/远程 init 先于一切联邦模块),故求值期直读 globalThis 安全
|
|
817
820
|
`export const shareScopeMap = (globalThis).__FULGURJS_RUNTIME__?.shareScopeMap;`,
|
|
@@ -918,21 +921,7 @@ function genBuildRemoteEntry(options, exposeAbsPaths) {
|
|
|
918
921
|
""
|
|
919
922
|
].join("\n");
|
|
920
923
|
}
|
|
921
|
-
function genApiFacade(
|
|
922
|
-
if (mode === "build") {
|
|
923
|
-
return [
|
|
924
|
-
"export {",
|
|
925
|
-
" initSharing, registerShare, registerRemotes, registerRemote, registerPlugins,",
|
|
926
|
-
" loadShare, loadRemote, getContainer, preloadRemote, parseSpec,",
|
|
927
|
-
" getRuntime, shareScopeMap, unwrapDefault, version,",
|
|
928
|
-
'} from "virtual:fulgurjs-runtime";',
|
|
929
|
-
"export { provideAppContext, getAppContext, requireAppContext } from '@fulgurjs/federation/internal/context.js';",
|
|
930
|
-
"export { definePages, validatePages } from '@fulgurjs/federation/internal/pages.js';",
|
|
931
|
-
"export { remoteComponent } from '@fulgurjs/federation/internal/vue.js';",
|
|
932
|
-
"export { default as remoteSchema } from 'virtual:fulgurjs-remote-schema';",
|
|
933
|
-
""
|
|
934
|
-
].join("\n");
|
|
935
|
-
}
|
|
924
|
+
function genApiFacade() {
|
|
936
925
|
return [
|
|
937
926
|
"export {",
|
|
938
927
|
" loadRemote, loadShare, preloadRemote, getContainer,",
|
|
@@ -941,9 +930,9 @@ function genApiFacade(mode) {
|
|
|
941
930
|
'} from "virtual:fulgurjs-runtime-proxy";',
|
|
942
931
|
"export { provideAppContext, getAppContext, requireAppContext } from '@fulgurjs/federation/internal/context.js';",
|
|
943
932
|
"export { definePages, validatePages } from '@fulgurjs/federation/internal/pages.js';",
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
"export
|
|
933
|
+
"import { createRemoteComponent } from '@fulgurjs/federation/internal/vue-adapter.js';",
|
|
934
|
+
"import { loadRemote as __fulgurjs_loadRemote } from 'virtual:fulgurjs-runtime-proxy';",
|
|
935
|
+
"export const remoteComponent = createRemoteComponent(__fulgurjs_loadRemote);",
|
|
947
936
|
""
|
|
948
937
|
].join("\n");
|
|
949
938
|
}
|
|
@@ -1009,6 +998,61 @@ function ensureLexer() {
|
|
|
1009
998
|
lexerReady ??= import_es_module_lexer.init;
|
|
1010
999
|
return lexerReady;
|
|
1011
1000
|
}
|
|
1001
|
+
function splitNamedImportBindings(inner) {
|
|
1002
|
+
const parts = [];
|
|
1003
|
+
let start = 0;
|
|
1004
|
+
for (let i = 0; i < inner.length; i++) {
|
|
1005
|
+
if (inner.startsWith("/*", i)) {
|
|
1006
|
+
const end = inner.indexOf("*/", i + 2);
|
|
1007
|
+
i = end < 0 ? inner.length : end + 1;
|
|
1008
|
+
} else if (inner.startsWith("//", i)) {
|
|
1009
|
+
const end = inner.indexOf("\n", i + 2);
|
|
1010
|
+
i = end < 0 ? inner.length : end;
|
|
1011
|
+
} else if (inner[i] === ",") {
|
|
1012
|
+
parts.push(inner.slice(start, i).trim());
|
|
1013
|
+
start = i + 1;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
parts.push(inner.slice(start).trim());
|
|
1017
|
+
return parts.filter(Boolean);
|
|
1018
|
+
}
|
|
1019
|
+
async function rewriteRuntimeEntryImports(code, exposeTarget) {
|
|
1020
|
+
if (!code.includes("@fulgurjs/federation/runtime")) return null;
|
|
1021
|
+
await ensureLexer();
|
|
1022
|
+
const [imports] = (0, import_es_module_lexer.parse)(code);
|
|
1023
|
+
const out = new import_magic_string.default(code);
|
|
1024
|
+
let changed = false;
|
|
1025
|
+
for (const imp of imports) {
|
|
1026
|
+
if (imp.n !== "@fulgurjs/federation/runtime" || imp.d !== -1) continue;
|
|
1027
|
+
const statement = code.slice(imp.ss, imp.se);
|
|
1028
|
+
if (/^\s*import\s+type\b/.test(statement)) continue;
|
|
1029
|
+
const destination = exposeTarget ? "virtual:fulgurjs-api-facade" : "@fulgurjs/federation/runtime";
|
|
1030
|
+
const braces = statement.match(/\{([\s\S]*?)\}/);
|
|
1031
|
+
if (braces && /^\s*import\b/.test(statement)) {
|
|
1032
|
+
const parts = splitNamedImportBindings(braces[1]);
|
|
1033
|
+
const normalized = parts.map((x) => x.replace(/\/\*[\s\S]*?\*\/|\/\/[^\n]*/g, "").trim());
|
|
1034
|
+
const schema = normalized.filter((x) => /^remoteSchema(?:\s+as\s+[A-Za-z_$][\w$]*)?$/.test(x));
|
|
1035
|
+
if (schema.length) {
|
|
1036
|
+
const rest = parts.filter((_, i) => !schema.includes(normalized[i]));
|
|
1037
|
+
const before = statement.slice(0, statement.indexOf("{")).trim();
|
|
1038
|
+
const defaultBinding = before.replace(/^import\s*/, "").replace(/,\s*$/, "").trim();
|
|
1039
|
+
const replacement = [
|
|
1040
|
+
...rest.length || defaultBinding ? [`import ${defaultBinding ? defaultBinding + (rest.length ? ", " : "") : ""}${rest.length ? `{ ${rest.join(", ")} }` : ""} from ${JSON.stringify(destination)};`] : [],
|
|
1041
|
+
`import { ${schema.join(", ")} } from "virtual:fulgurjs-remote-schema";`
|
|
1042
|
+
].join("\n");
|
|
1043
|
+
const end = code[imp.se] === ";" ? imp.se + 1 : imp.se;
|
|
1044
|
+
out.overwrite(imp.ss, end, replacement);
|
|
1045
|
+
changed = true;
|
|
1046
|
+
continue;
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
if (exposeTarget) {
|
|
1050
|
+
out.overwrite(imp.s, imp.e, destination);
|
|
1051
|
+
changed = true;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
return changed ? out.toString() : null;
|
|
1055
|
+
}
|
|
1012
1056
|
function isExposeTargetFile(cleanPath, root, exposes) {
|
|
1013
1057
|
for (const e of exposes) {
|
|
1014
1058
|
const abs = import_node_path2.default.resolve(root, e.import.replace(/^\.\//, ""));
|
|
@@ -1375,14 +1419,6 @@ function extractTsExportNames(text) {
|
|
|
1375
1419
|
}
|
|
1376
1420
|
return [...names];
|
|
1377
1421
|
}
|
|
1378
|
-
function genRuntimeTypesShim() {
|
|
1379
|
-
return [
|
|
1380
|
-
"// \u81EA\u52A8\u751F\u6210\uFF1Afulgurjs-federation \u8FD0\u884C\u65F6\u7C7B\u578B\uFF08virtual:fulgurjs-api\uFF09",
|
|
1381
|
-
"import '@fulgurjs/federation/client'",
|
|
1382
|
-
"export {}",
|
|
1383
|
-
""
|
|
1384
|
-
].join("\n");
|
|
1385
|
-
}
|
|
1386
1422
|
function resolveDtsDir(dtsOpt, rootHasSrc) {
|
|
1387
1423
|
if (dtsOpt === false) return "";
|
|
1388
1424
|
return (typeof dtsOpt === "object" ? dtsOpt.dir : void 0) ?? (rootHasSrc ? "src/fulgurjs/types" : ".fulgurjs/types");
|
|
@@ -1420,7 +1456,6 @@ async function generateDevTypes(options, _server) {
|
|
|
1420
1456
|
const dir = resolveDtsDir(dtsOpt, import_node_fs2.default.existsSync(import_node_path3.default.join(options.root, "src")));
|
|
1421
1457
|
const outDir = import_node_path3.default.join(options.root, dir);
|
|
1422
1458
|
import_node_fs2.default.mkdirSync(outDir, { recursive: true });
|
|
1423
|
-
import_node_fs2.default.writeFileSync(import_node_path3.default.join(outDir, "fulgurjs-runtime.d.ts"), genRuntimeTypesShim());
|
|
1424
1459
|
for (const remote of options.remotes) {
|
|
1425
1460
|
if (!remote.devEntry || remote.promise) continue;
|
|
1426
1461
|
const manifest = await fetchManifest(remote.devEntry);
|
|
@@ -1667,7 +1702,10 @@ async function probeRemotesAndBuildSchema(options) {
|
|
|
1667
1702
|
}
|
|
1668
1703
|
function genEmptyRemoteSchemaModule() {
|
|
1669
1704
|
console.info("[fulgurjs] build \u671F\u8DF3\u8FC7\u8DEF\u7531 spec \u5B58\u5728\u6027\u6821\u9A8C\uFF08\u8FDC\u7A0B manifest \u4E0D\u5728\u6784\u5EFA\u673A\u672C\u5730\uFF1Bdev \u4E0B\u81EA\u52A8\u542F\u7528\uFF09");
|
|
1670
|
-
return
|
|
1705
|
+
return genRemoteSchemaModule({});
|
|
1706
|
+
}
|
|
1707
|
+
function genRemoteSchemaModule(schema) {
|
|
1708
|
+
return `export const remoteSchema = ${JSON.stringify(schema)}; export default remoteSchema`;
|
|
1671
1709
|
}
|
|
1672
1710
|
|
|
1673
1711
|
// src/vite-cache.ts
|
|
@@ -1695,7 +1733,7 @@ function syncViteCacheMarker(root, pluginVersion, log) {
|
|
|
1695
1733
|
}
|
|
1696
1734
|
|
|
1697
1735
|
// src/runtime-code.gen.ts
|
|
1698
|
-
var runtime_code_gen_default = 'var oe=/^v?(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?(?:-((?:[0-9A-Za-z-]+)(?:\\.[0-9A-Za-z-]+)*))?(?:\\+[0-9A-Za-z.-]+)?$/;function I(o){let i=oe.exec(String(o).trim());return i?{major:Number(i[1]),minor:Number(i[2]??0),patch:Number(i[3]??0),pre:i[4]?i[4].split("."):[]}:null}function ie(o,i){if(o.length===0&&i.length===0)return 0;if(o.length===0)return 1;if(i.length===0)return-1;let s=Math.max(o.length,i.length);for(let n=0;n<s;n++){let f=o[n],y=i[n];if(f===void 0)return-1;if(y===void 0)return 1;let R=/^\\d+$/.test(f),w=/^\\d+$/.test(y);if(R&&w){let T=Number(f)-Number(y);if(T!==0)return T}else{if(R!==w)return R?-1:1;if(f!==y)return f<y?-1:1}}return 0}function j(o,i){let s=I(o),n=I(i);return!s||!n?o<i?-1:o>i?1:0:s.major!==n.major?s.major-n.major:s.minor!==n.minor?s.minor-n.minor:s.patch!==n.patch?s.patch-n.patch:ie(s.pre,n.pre)}var se=/^[a-z]+[+:-]/i;function P(o,i){if(i===!1||i==null||i==="")return!0;let s=String(i).trim();return!s||s==="*"||s==="latest"||se.test(s)?!0:s.split("||").some(n=>ae(o,n.trim()))}function ae(o,i){if(!i||i==="*")return!I(o)?.pre.length;let s=i.split(/\\s+-\\s+/);if(s.length===2){let y=s[0].trim(),R=s[1].trim();return!(!P(o,`>=${y}`)||!P(o,`<=${R}`))}let n=I(o);if(!n)return!1;let f=ce(i);if(f===null)return!0;for(let y of f)if(!pe(n,o,y))return!1;return!(n.pre.length>0&&!f.some(y=>y.ver.pre.length>0)&&!f.some(R=>R.ver.major===n.major&&R.ver.minor===n.minor&&R.ver.patch===n.patch))}function ce(o){let i=[],s=o.trim().split(/\\s+/).filter(Boolean);if(s.length===0)return null;for(let n of s){let f=/^(>=|<=|>|<|=|\\^|~)?(.*)$/.exec(n);if(!f)return null;let y=f[1],R=f[2],w=le(y,R);if(w===null)return null;i.push(...w)}return i}function le(o,i){let s=me(i);if(!s)return null;let{ver:n,partial:f}=s;switch(o){case"^":{let y=ue(n);return y?[{op:">=",ver:n},{op:"<",ver:y}]:null}case"~":{let y=f>=2?{major:n.major,minor:n.minor+1,patch:0,pre:[]}:{major:n.major+1,minor:0,patch:0,pre:[]};return[{op:">=",ver:n},{op:"<",ver:y}]}case">=":return[{op:">=",ver:n}];case">":return f===1?[{op:">=",ver:{major:n.major+1,minor:0,patch:0,pre:[]}}]:f===2?[{op:">=",ver:{major:n.major,minor:n.minor+1,patch:0,pre:[]}}]:[{op:">",ver:n}];case"<":return f===1?[{op:"<",ver:{major:n.major,minor:0,patch:0,pre:[]}}]:f===2?[{op:"<",ver:{major:n.major,minor:n.minor,patch:0,pre:[]}}]:[{op:"<",ver:n}];case"<=":return[{op:"<=",ver:n}];case"=":case void 0:return f===1?[{op:">=",ver:n},{op:"<",ver:{major:n.major+1,minor:0,patch:0,pre:[]}}]:f===2?[{op:">=",ver:n},{op:"<",ver:{major:n.major,minor:n.minor+1,patch:0,pre:[]}}]:[{op:"=",ver:n}];default:return null}}function ue(o){return o.major>0?{major:o.major+1,minor:0,patch:0,pre:[]}:o.minor>0?{major:0,minor:o.minor+1,patch:0,pre:[]}:{major:0,minor:0,patch:o.patch+1,pre:[]}}function me(o){let i=o.replace(/^v/,"").trim();if(!i||i==="*"||i==="x"||i==="X")return{ver:{major:0,minor:0,patch:0,pre:[]},partial:0};let s=i.split("."),n=[],f=0;for(let w of s.slice(0,3))if(/^\\d+$/.test(w))n.push(Number(w)),f++;else{if(w==="x"||w==="X"||w==="*")break;break}let y=i.split("-"),R=y.length>1?y.slice(1).join("-").split("+")[0].split("."):[];return f===0&&R.length===0?{ver:{major:0,minor:0,patch:0,pre:[]},partial:0}:{ver:{major:n[0]??0,minor:n[1]??0,patch:n[2]??0,pre:R},partial:f}}function fe(o,i){switch(i){case">=":return o>=0;case">":return o>0;case"<":return o<0;case"<=":return o<=0;case"=":return o===0}}function pe(o,i,s){let n=`${o.major}.${o.minor}.${o.patch}`+(o.pre.length?`-${o.pre.join(".")}`:"");if(s.upper)return!(!(j(n,`${s.ver.major}.${s.ver.minor}.${s.ver.patch}`+(s.ver.pre.length?`-${s.ver.pre.join(".")}`:""))>=0)||!(j(n,`${s.upper.major}.${s.upper.minor}.${s.upper.patch}`)<0));let f=j(n,`${s.ver.major}.${s.ver.minor}.${s.ver.patch}`+(s.ver.pre.length?`-${s.ver.pre.join(".")}`:"")),y=fe(f,s.op);return s.ver.pre.length>0&&o.pre.length===0&&(s.op===">"||s.op==="<")?!1:y}var b=class extends Error{code;details;constructor(i,s,n){super(`[fulgurjs:${i}] ${s}`),this.name="FgError",this.code=i,this.details=n}},S={REMOTE_LOAD_FAILED:"MFU-001",REMOTE_NAME_MISMATCH:"MFU-002",SHARE_STRICT_VERSION:"MFU-003",SHARE_NOT_AVAILABLE:"MFU-004",CONTAINER_REINIT_CONFLICT:"MFU-005",MODULE_NOT_EXPOSED:"MFU-006",PRELOAD_FAILED:"MFU-007",REMOTE_UNKNOWN:"MFU-008",EMPTY_EXPORTS:"MFU-009",SINGLETON_SKEW:"MFU-010"};var q="3.0.0";var x=15e3,z=2,de=5,ge=3e4,he=4e3,ye=.2;function Ee(){let o=Object.create(null),i=new Map,s=[],n=new Map,f=new Map,y=new WeakMap,R=new WeakMap,w={},T=()=>{for(let e of s)try{e.init?.(w)}catch(t){console.warn("[fulgurjs] runtimePlugin init failed:",e.name,t)}},N=e=>o[e]??=Object.create(null);function $(e){try{w.onRemoteError?.(e)}catch{}typeof window<"u"&&window.dispatchEvent(new CustomEvent("fulgurjs:error",{detail:e}))}function B(e="default"){return N(e),o}function J(e,t,r,l,h={}){let a=N(e||"default"),p=Object.hasOwn(a,t)?a[t]:void 0,d=p&&typeof p=="object"?p:void 0;d||(d=Object.create(null),a[t]=d),!(Object.hasOwn(d,r)&&d[r])&&(d[r]={version:r,get:l,from:h.from??"unknown",eager:!!h.eager,loaded:!!h.loaded})}function G(e){let t=(r,l,h)=>{if(r===void 0)return;if(!(typeof r=="number"&&(h?Number.isInteger(r)&&r>=0&&r<=10:Number.isFinite(r)&&r>0)))throw new Error(`[fulgurjs] registerRemote("${e.name}"): ${l} must be a ${h?"integer 0..10":"finite positive number"}, got ${String(r)}`)};t(e.timeout,"timeout"),t(e.retries,"retries",!0),e.breaker&&(t(e.breaker.threshold,"breaker.threshold"),t(e.breaker.resetMs,"breaker.resetMs"))}function F(e){for(let t of e){G(t);let r=i.get(t.name);i.set(t.name,{timeout:x,retries:z,...r,...t,breakerThreshold:t.breaker?.threshold??r?.breakerThreshold??de,breakerResetMs:t.breaker?.resetMs??r?.breakerResetMs??ge,state:r?.state??"idle",breakerState:r?.breakerState??{fails:0,openUntil:0},entryInflight:r?.entryInflight??new Map,debug:r?.debug??{entry:t.entry,status:"idle"}})}}function X(e){F([e])}function Y(e){s.push(...e),T()}async function Z(e,t={}){let r=t.shareScope||"default",l=t.shareKey||e,a=N(r)[l]||{},p=Object.keys(a),d=t.requiredVersion,g=p.filter(c=>d===void 0||d===!1||P(c,d)),m;if(t.singleton&&p.length>0){let c=p.filter(u=>a[u].loaded);if(m=[...c.length?c:p].sort(j).pop(),p.length>1||!g.includes(m)){let u=a[m],k=`singleton skew "${l}": req "${d??"any"}" use ${m} from ${u.from}`;if(t.strictVersion){let v=new b(S.SHARE_STRICT_VERSION,k,{shareKey:l,requiredVersion:d});throw $({remote:u.from,error:v}),v}console.warn(`[fulgurjs:MFU-010] ${k}`)}}else if(m=[...g].sort(j).pop(),!m){if(t.strictVersion){let u=new b(S.SHARE_STRICT_VERSION,`no satisfying version for "${l}" (required "${d}") in share scope "${r}"`);throw $({remote:l,error:u}),u}if(t.fallback)return t.fallback();let c=new b(S.SHARE_NOT_AVAILABLE,`shared "${l}" (${d??"any"}) unavailable in scope "${r}" (no local fallback)`,{shareKey:l,requiredVersion:d});throw $({remote:l,error:c}),c}let E=a[m];if(w.resolveShare){let c=await w.resolveShare({shareKey:l,shareScope:r,requiredVersion:d,picked:E,available:Object.values(a)});c&&(E=c)}return E.loaded=!0,E.get()}function Q(e){try{let t=new URL(e,typeof location<"u"?location.href:"http://f.invalid");return t.protocol+"//"+t.host+t.pathname}catch{return String(e).replace(/[?#].*$/,"")}}function C(e,t,r){return new Promise((l,h)=>{let a=setTimeout(()=>h(new Error(`timeout after ${t}ms: ${r}`)),t);e.then(p=>{clearTimeout(a),l(p)},p=>{clearTimeout(a),h(p)})})}let ee=e=>new Promise(t=>setTimeout(t,e));function A(e,t){if(!e||typeof e.get!="function")throw new Error(`remoteEntry of "${t.name}" does not export a container interface (get/init)`);if(e.name&&t.name&&e.name!==t.name){let r=`remoteEntry self-reported name "${e.name}" mismatches configured name "${t.name}"`;if(t.promise)console.warn(`[fulgurjs] ${r} (promise-based remote, continuing)`);else throw Object.assign(new Error(r),{code:S.REMOTE_NAME_MISMATCH})}}async function D(e,t){let r=t.entryInflight.get(e),l=r??import(e);return r||(t.entryInflight.set(e,l),l.catch(()=>t.entryInflight.delete(e))),C(l,t.timeout??x,`load remoteEntry ${e}`)}async function V(e,t){let r=e.shareScope||"default";if(e.container){let a=R.get(e.container);if(a&&a!==r)throw new b(S.CONTAINER_REINIT_CONFLICT,`container "${e.name}" already initialized with share scope "${a}", cannot re-init with "${r}"`);return e.container}if(e.containerPromise)return e.containerPromise;let l=e.breakerState;if(l.openUntil>Date.now()){let a=new b(S.REMOTE_LOAD_FAILED,`circuit breaker open for remote "${e.name}" until ${new Date(l.openUntil).toISOString()}`,{remote:e.name});throw $({remote:e.name,error:a}),a}e.state="loading",e.debug.status="loading";let h=(async()=>{let a=[];if(e.promise)a.push(async()=>{let c=await C(e.promise(),e.timeout??x,`resolve promise remote "${e.name}"`),u=typeof c=="string"?await D(c,e):c;return A(u,e),u});else for(let c of[e.entry,...e.fallback??[]])a.push(async()=>{let u=await D(c,e);return A(u,e),u});let p,d,g=!1,m=t?.retries??e.retries??z;for(let c of a){for(let u=0;u<=m;u++){let k=performance.now();try{p=await c(),e.lastLoadMs=Math.round(performance.now()-k),e.debug.lastLoadMs=e.lastLoadMs,g=!0;break}catch(v){if(d=v,v?.code)throw v;u<m&&await ee(Math.min(he,200*2**u)*(1-ye*(1-2*Math.random())))}}if(g)break}if(!g||!p){let c=Q(e.entry),u=[];throw/^https?:\\/\\//.test(e.entry)&&typeof location<"u"?(u.push(`1. is the remote dev server running? open ${c} in a browser \\u2014 it must return JS, not HTML`),u.push("2. is the URL correct in federation({ remotes })? dev/prod entries can differ"),u.push("3. CORS: the remote dev server must allow cross-origin requests (check its server.cors)")):(u.push(`1. is the remote deployed? open ${c} in a browser \\u2014 it must return JS`),u.push("2. NGINX/CDN routing: the entry path must serve the remoteEntry JS (check try_files)")),new b(S.REMOTE_LOAD_FAILED,`failed to load remote "${e.name}" from ${c}: ${String(d?.message??d)}\n`+u.join(`\n`),{remote:e.name})}A(p,e);let E=R.get(p);if(E&&E!==r)throw new b(S.CONTAINER_REINIT_CONFLICT,`container "${e.name}" already initialized with share scope "${E}", cannot re-init with "${r}"`);return typeof p.init=="function"&&await p.init(o),R.set(p,r),e.container=p,e.state="loaded",e.debug.status="loaded",l.fails=0,p})();e.containerPromise=h;try{return await h}catch(a){if(e.containerPromise=void 0,e.state="failed",e.debug.status="failed",e.debug.error=String(a?.message??a),l.fails+=1,l.fails>=e.breakerThreshold&&(l.openUntil=Date.now()+e.breakerResetMs,l.fails=0),a instanceof b)throw $({remote:e.name,error:a}),a;if(a?.code)throw $({remote:e.name,error:a}),a;let p=new b(S.REMOTE_LOAD_FAILED,String(a?.message??a),{remote:e.name});throw $({remote:e.name,error:p}),p}}function U(e){let t=e.indexOf("/");return t===-1?{remote:e,module:""}:{remote:e.slice(0,t),module:H(e.slice(t+1))}}function H(e){return e?e.startsWith(".")?e:`./${e}`:""}async function re(e,t){let{remote:r,module:l}=U(e);try{w.beforeLoadRemote?.({remote:r,module:l})}catch(g){console.warn("[fulgurjs] beforeLoadRemote hook error (ignored):",g)}let h=i.get(r);if(!h)throw new b(S.REMOTE_UNKNOWN,`unknown remote "${r}". Register it via federation({ remotes }) or registerRemote().`,{remote:r});let a;try{let g=l&&h.manifestUrl?K(e):Promise.resolve();[a]=await Promise.all([V(h,{retries:t?.retries}),g])}catch(g){if(t?.fallbackModule)return console.error(`[fulgurjs] loadRemote("${e}") failed; returning fallbackModule (\\u663E\\u5F0F\\u964D\\u7EA7\\uFF0C\\u9519\\u8BEF\\u5DF2\\u900F\\u51FA)`,g),$({remote:r,error:g}),await t.fallbackModule();throw g}if(!l)return a;let p=`${r}@${h.shareScope||"default"}#${l}`;n.has(p)||n.set(p,a.get(l).catch(g=>{throw n.delete(p),g instanceof b||g?.code?g:new b(S.REMOTE_LOAD_FAILED,`failed to load module "${l}" from remote "${r}": ${String(g?.message??g)}`,{remote:r,module:l})}));let d;try{d=await n.get(p)}catch(g){if(t?.fallbackModule)return console.error(`[fulgurjs] loadRemote("${e}") failed; returning fallbackModule (\\u663E\\u5F0F\\u964D\\u7EA7\\uFF0C\\u9519\\u8BEF\\u5DF2\\u900F\\u51FA)`,g),$({remote:r,error:g}),await t.fallbackModule();throw g}try{w.afterLoadRemote?.({remote:r,module:l,module_ns:d})}catch(g){console.warn("[fulgurjs] afterLoadRemote hook error (ignored):",g)}if(d&&typeof d=="object"&&Object.keys(d).length===0){let g=new b(S.EMPTY_EXPORTS,`no exports: ${l} @ ${r}`,{remote:r,module:l});$({remote:r,error:g}),console.error(`[fulgurjs:MFU-009] ${g.message}`)}return d}function te(e){let t=i.get(e);if(!t)throw new b(S.REMOTE_UNKNOWN,`unknown remote "${e}"`,{remote:e});return V(t)}async function K(e,t={}){let{remote:r,module:l}=U(e),h=i.get(r);if(!h)throw new b(S.REMOTE_UNKNOWN,`unknown remote "${r}"`,{remote:r});let a=t.mode??"preload",p=(m,E)=>{if(m.sheet)return Promise.resolve();let c=y.get(m);if(c)return c;let u=new Promise(k=>{let v=()=>{m.removeEventListener("load",v),m.removeEventListener("error",O),k()},O=()=>{$({remote:r,error:new b(S.PRELOAD_FAILED,`failed to load remote stylesheet ${E}`,{remote:r})}),v()};m.addEventListener("load",v,{once:!0}),m.addEventListener("error",O,{once:!0}),m.sheet&&v()});return y.set(m,u),u},d=(m,E)=>{if(typeof document>"u")return Promise.resolve();let c=document.querySelector(`link[href="${m}"]`);if(c)return E==="style"&&a==="preload"?y.get(c)??Promise.resolve():Promise.resolve();let u=document.createElement("link");u.rel=E==="style"?"stylesheet":"modulepreload",u.href=m,a==="prefetch"&&(u.fetchPriority="low");let k=E==="style"?p(u,m):Promise.resolve();return document.head.appendChild(u),E==="style"&&a==="preload"?k:Promise.resolve()},g=m=>{let E=typeof document<"u"?document.baseURI:void 0,c=new URL(h.entry,E||"http://fulgurjs.invalid/");return!c.pathname.endsWith("/")&&!c.pathname.split("/").pop().includes(".")&&(c.pathname+="/"),new URL(m,c).href};try{if(h.manifestUrl){let m=f.get(h.manifestUrl);m||(m=fetch(h.manifestUrl,{cache:"no-cache",signal:AbortSignal.timeout(8e3)}).then(c=>c.ok?c.json():void 0),f.set(h.manifestUrl,m),m.then(c=>{c||f.delete(h.manifestUrl)},()=>f.delete(h.manifestUrl)));let E=await m;if(E){let c=E.schemaVersion;if(typeof c=="number"&&(!Number.isInteger(c)||c>1)){$({remote:r,error:new b(S.PRELOAD_FAILED,`unsupported manifest schemaVersion ${String(c)} (expected 1)`,{remote:r})}),await d(h.entry,"modulepreload");return}await d(h.entry,"modulepreload");let u=E.exposes,k=Array.isArray(u)?u.filter(_=>_&&typeof _=="object").map(_=>[String(_.name??""),_]):u&&typeof u=="object"?Object.entries(u):[],v=l?k.filter(([_,L])=>H(String(L?.name??_))===l):k,O=[];for(let[,_]of v)if(typeof _?.file=="string"&&await d(g(_.file),"modulepreload"),Array.isArray(_?.css))for(let L of _.css){if(typeof L!="string")continue;let ne=d(g(L),"style");a==="preload"&&O.push(ne)}await Promise.all(O);return}}await d(h.entry,"modulepreload")}catch(m){$({remote:r,error:new b(S.PRELOAD_FAILED,String(m?.message??m),{remote:r})})}}return typeof window>"u"||(window.__FULGURJS_SCOPE__=o,window.__FULGURJS_INFO__={get remotes(){let e={};for(let[t,r]of i)e[t]={...r.debug,entry:r.entry};return e},errors:[]}),{shareScopeMap:o,initSharing:B,registerShare:J,registerRemotes:F,registerRemote:X,registerPlugins:Y,loadShare:Z,loadRemote:re,getContainer:te,preloadRemote:K,parseSpec:U}}var W=globalThis,M=W.__FULGURJS_RUNTIME__??Ee();W.__FULGURJS_RUNTIME__=M;try{Object.freeze(M)}catch{}var _e=q;function ke(){return M}var je=M.initSharing,Oe=M.registerShare,Te=M.registerRemotes,Le=M.registerRemote,Ie=M.registerPlugins,Pe=M.loadShare,Ne=M.loadRemote,Ae=M.getContainer,Ue=M.preloadRemote,xe=M.parseSpec,Fe=M.shareScopeMap;function Ce(o){if(o&&typeof o=="object"&&"default"in o){let i=o.default;return i!==void 0?i:o}return o}var De=M;export{De as default,Ae as getContainer,ke as getRuntime,je as initSharing,Ne as loadRemote,Pe as loadShare,xe as parseSpec,Ue as preloadRemote,Ie as registerPlugins,Le as registerRemote,Te as registerRemotes,Oe as registerShare,M as runtime,Fe as shareScopeMap,Ce as unwrapDefault,_e as version};\n';
|
|
1736
|
+
var runtime_code_gen_default = 'var oe=/^v?(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?(?:-((?:[0-9A-Za-z-]+)(?:\\.[0-9A-Za-z-]+)*))?(?:\\+[0-9A-Za-z.-]+)?$/;function I(o){let i=oe.exec(String(o).trim());return i?{major:Number(i[1]),minor:Number(i[2]??0),patch:Number(i[3]??0),pre:i[4]?i[4].split("."):[]}:null}function ie(o,i){if(o.length===0&&i.length===0)return 0;if(o.length===0)return 1;if(i.length===0)return-1;let s=Math.max(o.length,i.length);for(let n=0;n<s;n++){let f=o[n],y=i[n];if(f===void 0)return-1;if(y===void 0)return 1;let b=/^\\d+$/.test(f),w=/^\\d+$/.test(y);if(b&&w){let T=Number(f)-Number(y);if(T!==0)return T}else{if(b!==w)return b?-1:1;if(f!==y)return f<y?-1:1}}return 0}function O(o,i){let s=I(o),n=I(i);return!s||!n?o<i?-1:o>i?1:0:s.major!==n.major?s.major-n.major:s.minor!==n.minor?s.minor-n.minor:s.patch!==n.patch?s.patch-n.patch:ie(s.pre,n.pre)}var se=/^[a-z]+[+:-]/i;function P(o,i){if(i===!1||i==null||i==="")return!0;let s=String(i).trim();return!s||s==="*"||s==="latest"||se.test(s)?!0:s.split("||").some(n=>ae(o,n.trim()))}function ae(o,i){if(!i||i==="*")return!I(o)?.pre.length;let s=i.split(/\\s+-\\s+/);if(s.length===2){let y=s[0].trim(),b=s[1].trim();return!(!P(o,`>=${y}`)||!P(o,`<=${b}`))}let n=I(o);if(!n)return!1;let f=ce(i);if(f===null)return!0;for(let y of f)if(!pe(n,o,y))return!1;return!(n.pre.length>0&&!f.some(y=>y.ver.pre.length>0)&&!f.some(b=>b.ver.major===n.major&&b.ver.minor===n.minor&&b.ver.patch===n.patch))}function ce(o){let i=[],s=o.trim().split(/\\s+/).filter(Boolean);if(s.length===0)return null;for(let n of s){let f=/^(>=|<=|>|<|=|\\^|~)?(.*)$/.exec(n);if(!f)return null;let y=f[1],b=f[2],w=le(y,b);if(w===null)return null;i.push(...w)}return i}function le(o,i){let s=me(i);if(!s)return null;let{ver:n,partial:f}=s;switch(o){case"^":{let y=ue(n);return y?[{op:">=",ver:n},{op:"<",ver:y}]:null}case"~":{let y=f>=2?{major:n.major,minor:n.minor+1,patch:0,pre:[]}:{major:n.major+1,minor:0,patch:0,pre:[]};return[{op:">=",ver:n},{op:"<",ver:y}]}case">=":return[{op:">=",ver:n}];case">":return f===1?[{op:">=",ver:{major:n.major+1,minor:0,patch:0,pre:[]}}]:f===2?[{op:">=",ver:{major:n.major,minor:n.minor+1,patch:0,pre:[]}}]:[{op:">",ver:n}];case"<":return f===1?[{op:"<",ver:{major:n.major,minor:0,patch:0,pre:[]}}]:f===2?[{op:"<",ver:{major:n.major,minor:n.minor,patch:0,pre:[]}}]:[{op:"<",ver:n}];case"<=":return[{op:"<=",ver:n}];case"=":case void 0:return f===1?[{op:">=",ver:n},{op:"<",ver:{major:n.major+1,minor:0,patch:0,pre:[]}}]:f===2?[{op:">=",ver:n},{op:"<",ver:{major:n.major,minor:n.minor+1,patch:0,pre:[]}}]:[{op:"=",ver:n}];default:return null}}function ue(o){return o.major>0?{major:o.major+1,minor:0,patch:0,pre:[]}:o.minor>0?{major:0,minor:o.minor+1,patch:0,pre:[]}:{major:0,minor:0,patch:o.patch+1,pre:[]}}function me(o){let i=o.replace(/^v/,"").trim();if(!i||i==="*"||i==="x"||i==="X")return{ver:{major:0,minor:0,patch:0,pre:[]},partial:0};let s=i.split("."),n=[],f=0;for(let w of s.slice(0,3))if(/^\\d+$/.test(w))n.push(Number(w)),f++;else{if(w==="x"||w==="X"||w==="*")break;break}let y=i.split("-"),b=y.length>1?y.slice(1).join("-").split("+")[0].split("."):[];return f===0&&b.length===0?{ver:{major:0,minor:0,patch:0,pre:[]},partial:0}:{ver:{major:n[0]??0,minor:n[1]??0,patch:n[2]??0,pre:b},partial:f}}function fe(o,i){switch(i){case">=":return o>=0;case">":return o>0;case"<":return o<0;case"<=":return o<=0;case"=":return o===0}}function pe(o,i,s){let n=`${o.major}.${o.minor}.${o.patch}`+(o.pre.length?`-${o.pre.join(".")}`:"");if(s.upper)return!(!(O(n,`${s.ver.major}.${s.ver.minor}.${s.ver.patch}`+(s.ver.pre.length?`-${s.ver.pre.join(".")}`:""))>=0)||!(O(n,`${s.upper.major}.${s.upper.minor}.${s.upper.patch}`)<0));let f=O(n,`${s.ver.major}.${s.ver.minor}.${s.ver.patch}`+(s.ver.pre.length?`-${s.ver.pre.join(".")}`:"")),y=fe(f,s.op);return s.ver.pre.length>0&&o.pre.length===0&&(s.op===">"||s.op==="<")?!1:y}var E=class extends Error{code;details;constructor(i,s,n){super(`[fulgurjs:${i}] ${s}`),this.name="FgError",this.code=i,this.details=n}},S={REMOTE_LOAD_FAILED:"MFU-001",REMOTE_NAME_MISMATCH:"MFU-002",SHARE_STRICT_VERSION:"MFU-003",SHARE_NOT_AVAILABLE:"MFU-004",CONTAINER_REINIT_CONFLICT:"MFU-005",MODULE_NOT_EXPOSED:"MFU-006",PRELOAD_FAILED:"MFU-007",REMOTE_UNKNOWN:"MFU-008",EMPTY_EXPORTS:"MFU-009",SINGLETON_SKEW:"MFU-010"};var q="4.0.0";var U=15e3,z=2,de=5,ge=3e4,he=4e3,ye=.2;function Re(){let o=Object.create(null),i=new Map,s=[],n=new Map,f=new Map,y=new WeakMap,b=new WeakMap,w={},T=()=>{for(let e of s)try{e.init?.(w)}catch(t){console.warn("[fulgurjs] runtimePlugin init failed:",e.name,t)}},N=e=>o[e]??=Object.create(null);function k(e){try{w.onRemoteError?.(e)}catch{}typeof window<"u"&&window.dispatchEvent(new CustomEvent("fulgurjs:error",{detail:e}))}function B(e="default"){return N(e),o}function J(e,t,r,l,h={}){let a=N(e||"default"),p=Object.hasOwn(a,t)?a[t]:void 0,d=p&&typeof p=="object"?p:void 0;d||(d=Object.create(null),a[t]=d),!(Object.hasOwn(d,r)&&d[r])&&(d[r]={version:r,get:l,from:h.from??"unknown",eager:!!h.eager,loaded:!!h.loaded})}function G(e){let t=(r,l,h)=>{if(r===void 0)return;if(!(typeof r=="number"&&(h?Number.isInteger(r)&&r>=0&&r<=10:Number.isFinite(r)&&r>0)))throw new Error(`[fulgurjs] registerRemote("${e.name}"): ${l} must be a ${h?"integer 0..10":"finite positive number"}, got ${String(r)}`)};t(e.timeout,"timeout"),t(e.retries,"retries",!0),e.breaker&&(t(e.breaker.threshold,"breaker.threshold"),t(e.breaker.resetMs,"breaker.resetMs"))}function F(e){for(let t of e){G(t);let r=i.get(t.name);i.set(t.name,{timeout:U,retries:z,...r,...t,breakerThreshold:t.breaker?.threshold??r?.breakerThreshold??de,breakerResetMs:t.breaker?.resetMs??r?.breakerResetMs??ge,state:r?.state??"idle",breakerState:r?.breakerState??{fails:0,openUntil:0},entryInflight:r?.entryInflight??new Map,debug:r?.debug??{entry:t.entry,status:"idle"}})}}function X(e){F([e])}function Y(e){s.push(...e),T()}async function Z(e,t={}){let r=t.shareScope||"default",l=t.shareKey||e,a=N(r)[l]||{},p=Object.keys(a),d=t.requiredVersion,g=p.filter(c=>d===void 0||d===!1||P(c,d)),m;if(t.singleton&&p.length>0){let c=p.filter(u=>a[u].loaded);if(m=[...c.length?c:p].sort(O).pop(),p.length>1||!g.includes(m)){let u=a[m],_=`singleton skew "${l}": req "${d??"any"}" use ${m} from ${u.from}`;if(t.strictVersion){let $=new E(S.SHARE_STRICT_VERSION,_,{shareKey:l,requiredVersion:d});throw k({remote:u.from,error:$}),$}console.warn(`[fulgurjs:MFU-010] ${_}`)}}else if(m=[...g].sort(O).pop(),!m){if(t.strictVersion){let u=new E(S.SHARE_STRICT_VERSION,`no satisfying version for "${l}" (required "${d}") in share scope "${r}"`);throw k({remote:l,error:u}),u}if(t.fallback)return t.fallback();let c=new E(S.SHARE_NOT_AVAILABLE,`shared "${l}" (${d??"any"}) unavailable in scope "${r}" (no local fallback)`,{shareKey:l,requiredVersion:d});throw k({remote:l,error:c}),c}let R=a[m];if(w.resolveShare){let c=await w.resolveShare({shareKey:l,shareScope:r,requiredVersion:d,picked:R,available:Object.values(a)});c&&(R=c)}return R.loaded=!0,R.get()}function Q(e){try{let t=new URL(e,typeof location<"u"?location.href:"http://f.invalid");return t.protocol+"//"+t.host+t.pathname}catch{return String(e).replace(/[?#].*$/,"")}}function C(e,t,r){return new Promise((l,h)=>{let a=setTimeout(()=>h(new Error(`timeout after ${t}ms: ${r}`)),t);e.then(p=>{clearTimeout(a),l(p)},p=>{clearTimeout(a),h(p)})})}let ee=e=>new Promise(t=>setTimeout(t,e));function A(e,t){if(!e||typeof e.get!="function")throw new Error(`remoteEntry of "${t.name}" does not export a container interface (get/init)`);if(e.name&&t.name&&e.name!==t.name){let r=`remoteEntry self-reported name "${e.name}" mismatches configured name "${t.name}"`;if(t.promise)console.warn(`[fulgurjs] ${r} (promise-based remote, continuing)`);else throw Object.assign(new Error(r),{code:S.REMOTE_NAME_MISMATCH})}}async function D(e,t){let r=t.entryInflight.get(e),l=r??import(e);return r||(t.entryInflight.set(e,l),l.catch(()=>t.entryInflight.delete(e))),C(l,t.timeout??U,`load remoteEntry ${e}`)}async function V(e,t){let r=e.shareScope||"default";if(e.container){let a=b.get(e.container);if(a&&a!==r)throw new E(S.CONTAINER_REINIT_CONFLICT,`container "${e.name}" already initialized with share scope "${a}", cannot re-init with "${r}"`);return e.container}if(e.containerPromise)return e.containerPromise;let l=e.breakerState;if(l.openUntil>Date.now()){let a=new E(S.REMOTE_LOAD_FAILED,`circuit breaker open for remote "${e.name}" until ${new Date(l.openUntil).toISOString()}`,{remote:e.name});throw k({remote:e.name,error:a}),a}e.state="loading",e.debug.status="loading";let h=(async()=>{let a=[];if(e.promise)a.push(async()=>{let c=await C(e.promise(),e.timeout??U,`resolve promise remote "${e.name}"`),u=typeof c=="string"?await D(c,e):c;return A(u,e),u});else for(let c of[e.entry,...e.fallback??[]])a.push(async()=>{let u=await D(c,e);return A(u,e),u});let p,d,g=!1,m=t?.retries??e.retries??z;for(let c of a){for(let u=0;u<=m;u++){let _=performance.now();try{p=await c(),e.lastLoadMs=Math.round(performance.now()-_),e.debug.lastLoadMs=e.lastLoadMs,g=!0;break}catch($){if(d=$,$?.code)throw $;u<m&&await ee(Math.min(he,200*2**u)*(1-ye*(1-2*Math.random())))}}if(g)break}if(!g||!p){let c=Q(e.entry),u=[];throw/^https?:\\/\\//.test(e.entry)&&typeof location<"u"?(u.push(`1. is the remote dev server running? open ${c} in a browser \\u2014 it must return JS, not HTML`),u.push("2. is the URL correct in federation({ remotes })? dev/prod entries can differ"),u.push("3. CORS: the remote dev server must allow cross-origin requests (check its server.cors)")):(u.push(`1. is the remote deployed? open ${c} in a browser \\u2014 it must return JS`),u.push("2. NGINX/CDN routing: the entry path must serve the remoteEntry JS (check try_files)")),new E(S.REMOTE_LOAD_FAILED,`failed to load remote "${e.name}" from ${c}: ${String(d?.message??d)}\n`+u.join(`\n`),{remote:e.name})}A(p,e);let R=b.get(p);if(R&&R!==r)throw new E(S.CONTAINER_REINIT_CONFLICT,`container "${e.name}" already initialized with share scope "${R}", cannot re-init with "${r}"`);return typeof p.init=="function"&&await p.init(o),b.set(p,r),e.container=p,e.state="loaded",e.debug.status="loaded",l.fails=0,p})();e.containerPromise=h;try{return await h}catch(a){if(e.containerPromise=void 0,e.state="failed",e.debug.status="failed",e.debug.error=String(a?.message??a),l.fails+=1,l.fails>=e.breakerThreshold&&(l.openUntil=Date.now()+e.breakerResetMs,l.fails=0),a instanceof E)throw k({remote:e.name,error:a}),a;if(a?.code)throw k({remote:e.name,error:a}),a;let p=new E(S.REMOTE_LOAD_FAILED,String(a?.message??a),{remote:e.name});throw k({remote:e.name,error:p}),p}}function x(e){let t=e.indexOf("/");return t===-1?{remote:e,module:""}:{remote:e.slice(0,t),module:H(e.slice(t+1))}}function H(e){return e?e.startsWith(".")?e:`./${e}`:""}async function re(e,t){let{remote:r,module:l}=x(e);try{w.beforeLoadRemote?.({remote:r,module:l})}catch(g){console.warn("[fulgurjs] beforeLoadRemote hook error (ignored):",g)}let h=i.get(r);if(!h)throw new E(S.REMOTE_UNKNOWN,`unknown remote "${r}". Register it via federation({ remotes }) or registerRemote().`,{remote:r});let a;try{let g=l&&h.manifestUrl?K(e):Promise.resolve();[a]=await Promise.all([V(h,{retries:t?.retries}),g])}catch(g){if(t?.fallbackModule)return console.error(`[fulgurjs] loadRemote("${e}") failed; returning fallbackModule (\\u663E\\u5F0F\\u964D\\u7EA7\\uFF0C\\u9519\\u8BEF\\u5DF2\\u900F\\u51FA)`,g),k({remote:r,error:g}),await t.fallbackModule();throw g}if(!l)return a;let p=`${r}@${h.shareScope||"default"}#${l}`;n.has(p)||n.set(p,a.get(l).catch(g=>{throw n.delete(p),g instanceof E||g?.code?g:new E(S.REMOTE_LOAD_FAILED,`failed to load module "${l}" from remote "${r}": ${String(g?.message??g)}`,{remote:r,module:l})}));let d;try{d=await n.get(p)}catch(g){if(t?.fallbackModule)return console.error(`[fulgurjs] loadRemote("${e}") failed; returning fallbackModule (\\u663E\\u5F0F\\u964D\\u7EA7\\uFF0C\\u9519\\u8BEF\\u5DF2\\u900F\\u51FA)`,g),k({remote:r,error:g}),await t.fallbackModule();throw g}try{w.afterLoadRemote?.({remote:r,module:l,module_ns:d})}catch(g){console.warn("[fulgurjs] afterLoadRemote hook error (ignored):",g)}if(d&&typeof d=="object"&&Object.keys(d).length===0){let g=new E(S.EMPTY_EXPORTS,`no exports: ${l} @ ${r}`,{remote:r,module:l});k({remote:r,error:g}),console.error(`[fulgurjs:MFU-009] ${g.message}`)}return d}function te(e){let t=i.get(e);if(!t)throw new E(S.REMOTE_UNKNOWN,`unknown remote "${e}"`,{remote:e});return V(t)}async function K(e,t={}){let{remote:r,module:l}=x(e),h=i.get(r);if(!h)throw new E(S.REMOTE_UNKNOWN,`unknown remote "${r}"`,{remote:r});let a=t.mode??"preload",p=(m,R)=>{if(m.sheet)return Promise.resolve();let c=y.get(m);if(c)return c;let u=new Promise(_=>{let $=()=>{m.removeEventListener("load",$),m.removeEventListener("error",j),_()},j=()=>{k({remote:r,error:new E(S.PRELOAD_FAILED,`failed to load remote stylesheet ${R}`,{remote:r})}),$()};m.addEventListener("load",$,{once:!0}),m.addEventListener("error",j,{once:!0}),m.sheet&&$()});return y.set(m,u),u},d=(m,R)=>{if(typeof document>"u")return Promise.resolve();let c=document.querySelector(`link[href="${m}"]`);if(c)return R==="style"&&a==="preload"?y.get(c)??Promise.resolve():Promise.resolve();let u=document.createElement("link");u.rel=R==="style"?"stylesheet":"modulepreload",u.href=m,a==="prefetch"&&(u.fetchPriority="low");let _=R==="style"?p(u,m):Promise.resolve();return document.head.appendChild(u),R==="style"&&a==="preload"?_:Promise.resolve()},g=m=>{let R=typeof document<"u"?document.baseURI:void 0,c=new URL(h.entry,R||"http://fulgurjs.invalid/");return!c.pathname.endsWith("/")&&!c.pathname.split("/").pop().includes(".")&&(c.pathname+="/"),new URL(m,c).href};try{if(h.manifestUrl){let m=f.get(h.manifestUrl);m||(m=fetch(h.manifestUrl,{cache:"no-cache",signal:AbortSignal.timeout(8e3)}).then(c=>c.ok?c.json():void 0),f.set(h.manifestUrl,m),m.then(c=>{c||f.delete(h.manifestUrl)},()=>f.delete(h.manifestUrl)));let R=await m;if(R){let c=R.schemaVersion;if(typeof c=="number"&&(!Number.isInteger(c)||c>1)){k({remote:r,error:new E(S.PRELOAD_FAILED,`unsupported manifest schemaVersion ${String(c)} (expected 1)`,{remote:r})}),await d(h.entry,"modulepreload");return}await d(h.entry,"modulepreload");let u=R.exposes,_=Array.isArray(u)?u.filter(v=>v&&typeof v=="object").map(v=>[String(v.name??""),v]):u&&typeof u=="object"?Object.entries(u):[],$=l?_.filter(([v,L])=>H(String(L?.name??v))===l):_,j=[];for(let[,v]of $)if(typeof v?.file=="string"&&await d(g(v.file),"modulepreload"),Array.isArray(v?.css))for(let L of v.css){if(typeof L!="string")continue;let ne=d(g(L),"style");a==="preload"&&j.push(ne)}await Promise.all(j);return}}await d(h.entry,"modulepreload")}catch(m){k({remote:r,error:new E(S.PRELOAD_FAILED,String(m?.message??m),{remote:r})})}}return typeof window>"u"||(window.__FULGURJS_SCOPE__=o,window.__FULGURJS_INFO__={get remotes(){let e={};for(let[t,r]of i)e[t]={...r.debug,entry:r.entry};return e},errors:[]}),{shareScopeMap:o,initSharing:B,registerShare:J,registerRemotes:F,registerRemote:X,registerPlugins:Y,loadShare:Z,loadRemote:re,getContainer:te,preloadRemote:K,parseSpec:x}}var W=globalThis,M=W.__FULGURJS_RUNTIME__??Re();W.__FULGURJS_RUNTIME__=M;try{Object.freeze(M)}catch{}var ve=q;function _e(){return M}var Oe=M.initSharing,je=M.registerShare,Te=M.registerRemotes,Le=M.registerRemote,Ie=M.registerPlugins,Pe=M.loadShare,Ne=M.loadRemote,Ae=M.getContainer,xe=M.preloadRemote,Ue=M.parseSpec,Fe=M.shareScopeMap;function Ce(o){if(o&&typeof o=="object"&&"default"in o){let i=o.default;return i!==void 0?i:o}return o}var De=M;export{De as default,Ae as getContainer,_e as getRuntime,Oe as initSharing,Ne as loadRemote,Pe as loadShare,Ue as parseSpec,xe as preloadRemote,Ie as registerPlugins,Le as registerRemote,Te as registerRemotes,je as registerShare,M as runtime,Fe as shareScopeMap,Ce as unwrapDefault,ve as version};\n';
|
|
1699
1737
|
|
|
1700
1738
|
// src/index.ts
|
|
1701
1739
|
function readRuntimeCode() {
|
|
@@ -1967,7 +2005,7 @@ export { default } from ${JSON.stringify(url)};
|
|
|
1967
2005
|
const slash = bareClean.indexOf("/");
|
|
1968
2006
|
if (slash > 0) {
|
|
1969
2007
|
const prefix = bareClean.slice(0, slash);
|
|
1970
|
-
const known = n.remotes.some((r) => r.key === prefix) || n.shared.some((sh) => sh.aliases.includes(prefix) || sh.aliases.some((a) => a.endsWith("/") && prefix.startsWith(a)));
|
|
2008
|
+
const known = bareClean === "@fulgurjs/federation/runtime" || n.remotes.some((r) => r.key === prefix) || n.shared.some((sh) => sh.aliases.includes(prefix) || sh.aliases.some((a) => a.endsWith("/") && prefix.startsWith(a)));
|
|
1971
2009
|
if (!known && !warnedUnknownPrefixes.has(prefix)) {
|
|
1972
2010
|
warnedUnknownPrefixes.add(prefix);
|
|
1973
2011
|
console.warn(
|
|
@@ -1980,7 +2018,7 @@ export { default } from ${JSON.stringify(url)};
|
|
|
1980
2018
|
if (bareClean === RUNTIME_PROXY_VIRTUAL_ID) return RESOLVED.runtimeProxy;
|
|
1981
2019
|
if (bareClean === INIT_VIRTUAL_ID) return RESOLVED.init;
|
|
1982
2020
|
if (bareClean === "virtual:fulgurjs-remote-schema") return bareClean;
|
|
1983
|
-
if (bareClean === "virtual:fulgurjs-api") return bareClean;
|
|
2021
|
+
if (bareClean === "virtual:fulgurjs-api-facade") return bareClean;
|
|
1984
2022
|
if (bareClean === "virtual:fulgurjs-provides") return RESOLVED.provides;
|
|
1985
2023
|
if (bareClean === "virtual:fulgurjs-remote-entry") return RESOLVED.remoteEntry;
|
|
1986
2024
|
if (bareClean.startsWith(SHARED_NS_FACADE_PREFIX)) {
|
|
@@ -2007,13 +2045,13 @@ export { default } from ${JSON.stringify(url)};
|
|
|
2007
2045
|
if (clean === "virtual:fulgurjs-provides" && state.normalized) {
|
|
2008
2046
|
return genDevProvides(state.normalized);
|
|
2009
2047
|
}
|
|
2010
|
-
if (clean === "virtual:fulgurjs-api") {
|
|
2011
|
-
return genApiFacade(
|
|
2048
|
+
if (clean === "virtual:fulgurjs-api-facade" && state.command === "serve") {
|
|
2049
|
+
return genApiFacade();
|
|
2012
2050
|
}
|
|
2013
2051
|
if (clean === "virtual:fulgurjs-remote-schema" && state.normalized) {
|
|
2014
2052
|
if (state.command === "build") return genEmptyRemoteSchemaModule();
|
|
2015
2053
|
remoteSchemaPromise ??= probeRemotesAndBuildSchema(state.normalized).then(
|
|
2016
|
-
|
|
2054
|
+
genRemoteSchemaModule
|
|
2017
2055
|
);
|
|
2018
2056
|
return remoteSchemaPromise;
|
|
2019
2057
|
}
|
|
@@ -2313,7 +2351,7 @@ ${code}`, map: null };
|
|
|
2313
2351
|
server.httpServer?.once("listening", () => {
|
|
2314
2352
|
setTimeout(() => {
|
|
2315
2353
|
remoteSchemaPromise ??= probeRemotesAndBuildSchema(n).then(
|
|
2316
|
-
|
|
2354
|
+
genRemoteSchemaModule
|
|
2317
2355
|
);
|
|
2318
2356
|
}, 5e3);
|
|
2319
2357
|
});
|
|
@@ -2344,17 +2382,20 @@ ${code}`, map: null };
|
|
|
2344
2382
|
async transform(code, id) {
|
|
2345
2383
|
if (!state.normalized) return null;
|
|
2346
2384
|
const clean = id.split("?")[0];
|
|
2385
|
+
const isAppSource = clean.startsWith(state.normalized.root + import_node_path6.default.sep) && !clean.includes(`${import_node_path6.default.sep}node_modules${import_node_path6.default.sep}`) && !clean.includes(`${import_node_path6.default.sep}.vite${import_node_path6.default.sep}`);
|
|
2386
|
+
const entryRewrite = state.command === "serve" && isAppSource ? await rewriteRuntimeEntryImports(code, isExposeTargetFile(clean, state.normalized.root, state.normalized.exposes)) : null;
|
|
2387
|
+
if (entryRewrite !== null) code = entryRewrite;
|
|
2347
2388
|
if (state.command === "serve" && code.includes("virtual:fulgurjs-runtime") && !code.includes("virtual:fulgurjs-runtime-proxy") && isExposeTargetFile(clean, state.normalized.root, state.normalized.exposes)) {
|
|
2348
2389
|
return { code: code.split("virtual:fulgurjs-runtime").join("virtual:fulgurjs-runtime-proxy"), map: null };
|
|
2349
2390
|
}
|
|
2350
|
-
if (state.command === "serve" && isPluginProcessedModule(code)) return null;
|
|
2351
|
-
if (/type=(style|template)/.test(id)) return null;
|
|
2391
|
+
if (state.command === "serve" && isPluginProcessedModule(code)) return entryRewrite === null ? null : { code, map: null };
|
|
2392
|
+
if (/type=(style|template)/.test(id)) return entryRewrite === null ? null : { code, map: null };
|
|
2352
2393
|
const isJsLike = /\.(m|c)?[jt]sx?$/.test(clean) || clean.endsWith(".vue");
|
|
2353
|
-
if (!isJsLike) return null;
|
|
2394
|
+
if (!isJsLike) return entryRewrite === null ? null : { code, map: null };
|
|
2354
2395
|
const devRewriteAll = state.command === "serve" && state.normalized.devSharedSelf;
|
|
2355
2396
|
const isPureRemoteBuild = state.normalized.exposes.length > 0 && state.normalized.remotes.length === 0;
|
|
2356
2397
|
if (state.command === "serve" && clean.includes("node_modules") && !id.includes(".vite/deps") && !devRewriteAll) {
|
|
2357
|
-
return null;
|
|
2398
|
+
return entryRewrite === null ? null : { code, map: null };
|
|
2358
2399
|
}
|
|
2359
2400
|
if (state.command === "build") {
|
|
2360
2401
|
return buildFallbackTransform(code, id);
|
|
@@ -2371,13 +2412,14 @@ ${code}`, map: null };
|
|
|
2371
2412
|
if (!cleanPath.startsWith("/")) return null;
|
|
2372
2413
|
return state.resolvedSharedPaths.get(cleanPath) ?? null;
|
|
2373
2414
|
};
|
|
2374
|
-
|
|
2415
|
+
const transformed = await transformModule(code, id, {
|
|
2375
2416
|
onRewrite: () => recordRewritten(id),
|
|
2376
2417
|
options: state.normalized,
|
|
2377
2418
|
remapSpecifier,
|
|
2378
2419
|
rewriteShared,
|
|
2379
2420
|
sharedClosureRoots: state.sharedClosureRoots
|
|
2380
2421
|
});
|
|
2422
|
+
return transformed ?? (entryRewrite === null ? null : { code, map: null });
|
|
2381
2423
|
}
|
|
2382
2424
|
};
|
|
2383
2425
|
function warmResolvedSharedPaths(server) {
|