@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 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
- - **跨应用传值与方法引用**:`virtual:fulgurjs-api` 导出 `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')`(`virtual:fulgurjs-api` 导出)——`defineAsyncComponent + loadRemote` 的标准封装,加载失败显式错误占位(错误码+根因+修法),runtime.js 零框架依赖零体积增量
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 'virtual:fulgurjs-api'
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 'virtual:fulgurjs-api'
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 入口(3.0.0 破坏性收敛)**:应用代码的一切联邦导入——运行时函数、context 三函数、`definePages`、`remoteSchema`、`remoteComponent`——**只来自一个虚拟模块**:
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 'virtual:fulgurjs-api'
135
+ import { loadRemote, loadShare, preloadRemote, provideAppContext, getAppContext, definePages, remoteSchema, remoteComponent } from '@fulgurjs/federation/runtime'
136
136
  ```
137
137
 
138
- 旧入口(`virtual:fulgurjs-runtime`、`@fulgurjs/federation/{context,pages,vue}` 子路径)**已删除**——包 exports 白名单不再暴露(迁移映射见 CHANGELOG 3.0.0)。`virtual:fulgurjs-runtime` 仅作为插件内部实现细节保留(门面/容器入口/改写管线引用),不进入文档与类型声明。
138
+ 旧应用入口 `virtual:fulgurjs-api` 已删除;`virtual:fulgurjs-runtime` 仅供插件内部使用。旧 context/pages/vue 子路径也不再公开(迁移映射见 CHANGELOG 4.0.0)。
139
139
 
140
- **没有别的步骤了。** dev 下 remote 跑它自己的 `vite dev`(容器入口 `/@fulgurjs-entry.js` 由插件中间件直出);build 下 expose 自动拆独立 chunk、shared 自动剥离——同一份配置两端通用。
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 — `virtual:fulgurjs-api`
264
+ ### 2. 运行时 API — `@fulgurjs/federation/runtime`
263
265
 
264
266
  **任何文件都直接静态导入**——宿主页面、exposes 目标文件(远程页面)都一样,插件自动保证同一页面只有一个运行时实例(远程页面里的导入会被自动改写为惰性单例委托):
265
267
 
266
268
  ```ts
267
269
  // 宿主页面、远程页面,写法完全一致
268
- import { loadRemote } from 'virtual:fulgurjs-api'
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` 都从**唯一入口** `virtual:fulgurjs-api` 导入(见 §2);旧入口已删除。
277
+ > 下表全部函数与 `definePages` / `remoteSchema` / `provideAppContext` 等 context 函数 / `remoteComponent` 都从**唯一入口** `@fulgurjs/federation/runtime` 导入(见 §2);旧入口已删除。
276
278
 
277
- > **TS 提示**:`virtual:fulgurjs-api` 的类型随包发布。dev 启动时插件自动在类型目录(默认 `src/fulgurjs/types/`,联邦产物集中一个文件夹)生成远程模块声明与运行时类型垫片——src 布局项目零配置即全量生效;手工方式则在 tsconfig `compilerOptions.types` 加 `"@fulgurjs/federation/client"`。
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 'virtual:fulgurjs-api'
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` — 宿主页面路由表(`virtual:fulgurjs-api`)
337
+ ### 3. `definePages` — 宿主页面路由表(`@fulgurjs/federation/runtime`)
336
338
 
337
339
  宿主把「URL 路径 → 远程 exposes 键」的映射表交给它校验,带参路由的静默冲突在启动期报错而不是运行时加载错组件:
338
340
 
339
341
  ```ts
340
- import { definePages } from 'virtual:fulgurjs-api'
341
- import { remoteSchema } from 'virtual:fulgurjs-api' // dev 自动生成;build 恒为空(诚实降级)
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 远程组件直渲染(`virtual:fulgurjs-api`)
471
+ ### 8. `remoteComponent` — Vue 远程组件直渲染(`@fulgurjs/federation/runtime`)
470
472
 
471
473
  ```ts
472
- import { remoteComponent } from 'virtual:fulgurjs-api'
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`):仅使用 `./vue` 子路径时才需要安装 Vue;runtime.js 保持框架无关(不 import vue),体积零增量;
496
- - 运行时实例经 `globalThis.__FULGURJS_RUNTIME__` 页面级单例复用,与 `virtual:fulgurjs-api` 的导入殊途同归,无需额外接线。
497
+ - `vue` 为**可选 peerDependency**(`peerDependenciesMeta.optional`):只使用包根或 `/config` 时无需安装;应用使用 `/runtime` 时需要安装 Vue,因为该入口导出 `remoteComponent`。内部 `runtime.js` 仍不导入 Vue,体积零增量;
498
+ - 运行时实例经 `globalThis.__FULGURJS_RUNTIME__` 页面级单例复用,与 `@fulgurjs/federation/runtime` 的导入殊途同归,无需额外接线。
497
499
 
498
- ### 9. `AppContext` — 跨应用传值与方法引用(`virtual:fulgurjs-api`)
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 'virtual:fulgurjs-api'
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 'virtual:fulgurjs-api'
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 'virtual:fulgurjs-api'
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 'virtual:fulgurjs-api'` 报 ts(2307):是 IDE 的 TS 服务缓存了旧包——`Restart TS Server`(⌘⇧P)或重开窗口即可。3.0.0 起旧子路径(`@fulgurjs/federation/{context,pages,vue}`)已从包 exports 删除,按迁移映射改为 `virtual:fulgurjs-api`。
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
+ };
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var RUNTIME_VERSION = "3.0.0";
2
+ var RUNTIME_VERSION = "4.0.0";
3
3
 
4
4
  export {
5
5
  RUNTIME_VERSION
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 virtual:fulgurjs-api \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 'virtual:fulgurjs-api'\u2014\u20143.0.0 \u8D77\u65E7\u5165\u53E3\uFF08virtual:fulgurjs-runtime / @fulgurjs/federation \u7684 context/pages/vue \u5B50\u8DEF\u5F84\uFF09\u5DF2\u5220\u9664\uFF0C\u4E00\u5F8B\u6539\u7528\u672C\u5165\u53E3");
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 = "3.0.0";
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(mode) {
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
- `let __fulgurjs_vue_p;`,
945
- `export const remoteComponent = (...a) => (__fulgurjs_vue_p ??= import('@fulgurjs/federation/internal/vue.js')).then((m) => m.remoteComponent(...a));`,
946
- "export { default as remoteSchema } from 'virtual:fulgurjs-remote-schema';",
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 "export default {}";
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(state.command);
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
- (schema) => `export default ${JSON.stringify(schema)}`
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
- (schema) => `export default ${JSON.stringify(schema)}`
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
- return transformModule(code, id, {
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) {