@fulgurjs/federation 5.9.2 → 6.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.
Files changed (100) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.en.md +57 -416
  3. package/README.md +56 -446
  4. package/dist/bridge-app-vue.d.cts +1 -1
  5. package/dist/bridge-app-vue.d.ts +1 -1
  6. package/dist/bridge-core.cjs +1 -1
  7. package/dist/bridge-core.js +2 -2
  8. package/dist/bridge-errors.cjs +1 -1
  9. package/dist/bridge-errors.js +1 -1
  10. package/dist/bridge-host-react.cjs +1 -1
  11. package/dist/bridge-host-react.js +3 -3
  12. package/dist/bridge-host-vue.cjs +1 -1
  13. package/dist/bridge-host-vue.js +3 -3
  14. package/dist/bridge-router-react.d.ts +4 -2
  15. package/dist/bridge-router-react.js +95 -9
  16. package/dist/bridge-router-vue.d.ts +24 -5
  17. package/dist/bridge-router-vue.js +4 -5
  18. package/dist/{chunk-YKIFZIBH.js → chunk-77JZ6U6V.js} +1 -1
  19. package/dist/{chunk-Q6V5O5Y6.js → chunk-ENT3BOTX.js} +1 -1
  20. package/dist/{chunk-WRJG2YG6.js → chunk-ZAYNS7YQ.js} +1 -1
  21. package/dist/cli.js +460 -109
  22. package/dist/index.cjs +25 -38
  23. package/dist/index.js +25 -38
  24. package/dist/react.d.ts +194 -101
  25. package/dist/react.js +4 -0
  26. package/dist/runtime-entry.d.ts +9 -174
  27. package/dist/runtime-entry.js +0 -1
  28. package/dist/runtime.js +1 -1
  29. package/dist/vue-adapter.cjs +5 -1
  30. package/dist/vue-adapter.js +5 -1
  31. package/dist/vue.d.ts +576 -0
  32. package/dist/vue.js +8 -0
  33. package/docs/en/migration.md +210 -0
  34. package/docs/en/reference/api.md +534 -0
  35. package/docs/en/reference/errors.md +86 -0
  36. package/docs/{P5-vite7-8 → maintainers/P5-vite7-8}/345/205/274/345/256/271/347/237/251/351/230/265.md +7 -9
  37. package/docs/{webpack-mf- → maintainers/webpack-mf-}/345/257/271/347/205/247/344/270/216/347/274/272/345/217/243.md +10 -10
  38. package/docs/maintainers//346/262/231/347/256/261/350/276/271/347/225/214/345/256/241/350/256/241.md +43 -0
  39. package/docs/zh/migration.md +210 -0
  40. package/docs/zh/reference/api.md +533 -0
  41. package/docs/zh/reference/errors.md +86 -0
  42. package/examples/templates/README.md +1 -1
  43. package/examples/templates/react-host-vue-remote/pnpm-lock.yaml +7 -7
  44. package/examples/templates/react-host-vue-remote/pnpm-workspace.yaml +1 -1
  45. package/examples/templates/react-host-vue-remote/react-host/README.md +2 -2
  46. package/examples/templates/react-host-vue-remote/react-host/package.json +1 -1
  47. package/examples/templates/react-host-vue-remote/react-host/src/main.tsx +2 -2
  48. package/examples/templates/react-host-vue-remote/scripts/dev.config.json +11 -2
  49. package/examples/templates/react-host-vue-remote/vue-remote/package.json +1 -1
  50. package/examples/templates/react-host-vue-remote/vue-remote/src/bridge.ts +1 -1
  51. package/examples/templates/react-react/host/package.json +1 -1
  52. package/examples/templates/react-react/pnpm-lock.yaml +7 -7
  53. package/examples/templates/react-react/pnpm-workspace.yaml +1 -1
  54. package/examples/templates/react-react/remote/package.json +1 -1
  55. package/examples/templates/react-react/scripts/dev.config.json +11 -2
  56. package/examples/templates/showcase/README.md +6 -6
  57. package/examples/templates/showcase/pnpm-lock.yaml +11 -11
  58. package/examples/templates/showcase/pnpm-workspace.yaml +1 -1
  59. package/examples/templates/showcase/react-host/package.json +1 -1
  60. package/examples/templates/showcase/react-host/src/pages/BridgeVuePage.tsx +1 -1
  61. package/examples/templates/showcase/react-host/src/routing.ts +1 -1
  62. package/examples/templates/showcase/react-remote/package.json +1 -1
  63. package/examples/templates/showcase/react-remote/src/bridge.tsx +1 -1
  64. package/examples/templates/showcase/scripts/dev.config.json +22 -4
  65. package/examples/templates/showcase/vue-host/package.json +1 -1
  66. package/examples/templates/showcase/vue-host/src/pages/BridgeReactPage.vue +1 -1
  67. package/examples/templates/showcase/vue-host/src/routing.ts +3 -13
  68. package/examples/templates/showcase/vue-remote/package.json +1 -1
  69. package/examples/templates/showcase/vue-remote/src/bridge.ts +2 -2
  70. package/examples/templates/vue-host-react-remote/pnpm-lock.yaml +7 -7
  71. package/examples/templates/vue-host-react-remote/pnpm-workspace.yaml +1 -1
  72. package/examples/templates/vue-host-react-remote/react-remote/package.json +1 -1
  73. package/examples/templates/vue-host-react-remote/scripts/dev.config.json +11 -2
  74. package/examples/templates/vue-host-react-remote/vue-host/README.md +2 -2
  75. package/examples/templates/vue-host-react-remote/vue-host/package.json +1 -1
  76. package/examples/templates/vue-host-react-remote/vue-host/src/App.vue +2 -2
  77. package/examples/templates/vue-vue/host/package.json +1 -1
  78. package/examples/templates/vue-vue/host/src/main.ts +28 -21
  79. package/examples/templates/vue-vue/host/src/pages/HomePage.vue +1 -1
  80. package/examples/templates/vue-vue/pnpm-lock.yaml +7 -7
  81. package/examples/templates/vue-vue/pnpm-workspace.yaml +1 -1
  82. package/examples/templates/vue-vue/remote/package.json +1 -1
  83. package/examples/templates/vue-vue/scripts/dev.config.json +11 -2
  84. package/package.json +24 -37
  85. package/dist/bridge-core-D37VanBl.d.ts +0 -99
  86. package/dist/bridge-host-react-CGymCzD2.d.ts +0 -35
  87. package/dist/bridge-host-vue-B3GHaQAC.d.ts +0 -32
  88. package/dist/bridge-react.d.ts +0 -14
  89. package/dist/bridge-react.js +0 -3
  90. package/dist/bridge-vue.d.ts +0 -8
  91. package/dist/bridge-vue.js +0 -3
  92. package/dist/bridge.d.ts +0 -18
  93. package/dist/bridge.js +0 -5
  94. package/dist/chunk-GLASM5EX.js +0 -1730
  95. package/dist/chunk-V6EASSCR.js +0 -249
  96. package/dist/chunk-X34EJB4H.js +0 -207
  97. package/docs/API.en.md +0 -339
  98. package/docs/API.md +0 -914
  99. package/docs//346/262/231/347/256/261/350/276/271/347/225/214/345/256/241/350/256/241.md +0 -45
  100. package/docs//350/277/201/347/247/273/346/214/207/345/215/227.md +0 -179
package/dist/react.d.ts CHANGED
@@ -1,5 +1,150 @@
1
1
  import * as react from 'react';
2
- import { ComponentType, ReactNode, Component, ErrorInfo, ReactElement } from 'react';
2
+ import { ReactNode, ComponentType, Component, ErrorInfo, ReactElement } from 'react';
3
+ import { RouteObject } from 'react-router-dom';
4
+
5
+ /**
6
+ * 跨应用上下文标准字段表(§4.3,0.8.2 精简后)。
7
+ *
8
+ * 读写约定:宿主桥先写标准字段;远程 boot 只增不改宿主键;
9
+ * 嵌套对象(如 events)是引用共享,子应用挂属性即时可见(同 realm 直引用)。
10
+ *
11
+ * 精简记录(0.8.2):`token` 快照与 `formUrl`/`baseUrl` 从默认 provide 集合移除——
12
+ * token 快照与 getToken 函数引用重复(快照会过期),formUrl/baseUrl 自 0.7.0
13
+ * remoteComponent 直渲染后无消费点;项目如需可经扩展位自行提供。
14
+ */
15
+ interface AppContext {
16
+ /** 宿主登录用户原始形态(只读约定) */
17
+ user: Record<string, any>;
18
+ /** 取最新 token(拉取式防过期;0.8.2 起 bridge 不再传一次性 token 快照,用本函数取值) */
19
+ getToken?: () => string | undefined;
20
+ /** 宿主 pinia 实例:子应用 useUserStore(ctx.store) 拿共享响应式状态 */
21
+ store?: unknown;
22
+ /** 宿主 Vue App 实例(同 realm 直引用):全局组件/指令注册目标 */
23
+ hostApp?: unknown;
24
+ /** EP locale 等 UI 配置(原 W4 字段) */
25
+ locale?: unknown;
26
+ /** 事件/方法池:events.main.* 宿主提供、events.bpm.* / events.lowcode.* 子应用反向注册 */
27
+ events?: Record<string, any>;
28
+ /**
29
+ * 非敏感登录代次 ID:宿主每次成功登录/重新登录生成新值,token 刷新但会话未变时沿用。
30
+ * 远程 onSession 按它去重(同一代次只执行一次)。不是用户 ID、不是 token、不作为授权凭证。
31
+ * 远程声明了 onSession 时必填(缺省即 MFU-013)。
32
+ */
33
+ sessionKey?: string;
34
+ /** 项目扩展位(formUrl/baseUrl 等自定义键,按需自行提供) */
35
+ [key: string]: unknown;
36
+ }
37
+ /**
38
+ * 宿主写入跨应用上下文(merge 语义,幂等可多次调用,后写覆盖同键)。
39
+ *
40
+ * 宿主桥(host/src/fulgurjs/host/bridge.ts)在登录完成后调用:
41
+ * provideAppContext({ user, getToken, store, hostApp, locale, sessionKey, events: { main: mainEvents }, ... })
42
+ * 登录态变化(换账号/token 刷新)时再次调用即以最新值覆盖同键——不要用布尔闩锁把桥封成只跑一次。
43
+ */
44
+ declare function provideAppContext(config: Partial<AppContext> & Record<string, unknown>): void;
45
+ /**
46
+ * 宿主退出登录时清理:删除整个 context 对象(旧 user/getToken 引用一并失效),并通知
47
+ * 运行时单例作废全部远程的会话信号与 onSession 去重状态(下次登录必须重新执行 onSession)。
48
+ *
49
+ * 边界(契约):只清 AppContext 与会话初始化状态;不重置远程模块缓存、共享模块图与
50
+ * 应用级 setup 注册(同一页面内组件与共享实例继续复用)。页面无运行时单例时静默幂等
51
+ * (退出动作不依赖联邦形态,不得因缺运行时而打断登出流程)。
52
+ */
53
+ declare function clearAppContext(): void;
54
+ /**
55
+ * 读上下文快照(传输层快照:顶层 merge 结果 + 嵌套对象引用共享)。
56
+ * 页面无运行时单例(独立直开远程页)→ CC-002 显式抛错,不静默回空。
57
+ */
58
+ declare function getAppContext(): AppContext;
59
+ /**
60
+ * 显式校验读取(远程 setup/boot 消费入口):任一键缺失 → CC-001 三段式。
61
+ *
62
+ * 用法:const { store, user, hostApp } = requireAppContext('store', 'user', 'hostApp')
63
+ * 时序契约:宿主桥先 provide,远程 setup/onSession 后 require——违反即在初始化处显式失败。
64
+ */
65
+ declare function requireAppContext(...keys: string[]): AppContext;
66
+
67
+ /** 统一逻辑位置:pathname 以 / 开头;search 空串或 ? 开头;hash 空串或 # 开头 */
68
+ interface BridgeLocation {
69
+ pathname: string;
70
+ search: string;
71
+ hash: string;
72
+ }
73
+ type BridgeNavigationResult = {
74
+ status: 'committed';
75
+ location: BridgeLocation;
76
+ } | {
77
+ status: 'cancelled';
78
+ location: BridgeLocation;
79
+ };
80
+ /** 宿主导航端口(宿主适配器把 Router 包装成本接口;逻辑路径不含部署 base) */
81
+ interface BridgeHostNavigation {
82
+ getLocation(): BridgeLocation;
83
+ subscribe(listener: (location: BridgeLocation) => void): () => void;
84
+ navigate(target: BridgeLocation, action: 'push' | 'replace', options?: {
85
+ signal?: AbortSignal;
86
+ }): Promise<BridgeNavigationResult>;
87
+ go(delta: number): void;
88
+ }
89
+ /** 子应用路由通道(桥接宿主按挂载代次创建,随 mount 第三参数交给子应用) */
90
+ interface BridgeChildRoute {
91
+ /**
92
+ * 远程 spec(宿主创建通道时标注,如 "remote-b/bridge");子应用路由接线
93
+ * (connectVueBridgeRouter/createReactBridgeRouter)的诊断错误用它定位真实远程,
94
+ * 缺省(纯 memory 小部件自建通道)回退 'child-router'。
95
+ */
96
+ readonly spec?: string;
97
+ getLocation(): BridgeLocation;
98
+ subscribe(listener: (location: BridgeLocation) => void): () => void;
99
+ navigate(target: BridgeLocation, action: 'push' | 'replace'): Promise<BridgeNavigationResult>;
100
+ go(delta: number): void;
101
+ }
102
+ /** 挂载控制参数(mount 第三参数;不混入业务 props) */
103
+ interface BridgeMountOptions {
104
+ signal?: AbortSignal;
105
+ routing?: BridgeChildRoute;
106
+ }
107
+ /** 子应用路由协议声明(defineBridgeApp(工厂, { routing: true }) 时写入) */
108
+ interface BridgeRoutingProtocol {
109
+ protocol: 1;
110
+ }
111
+ /** 宿主组件 routing prop(独立控制通道,不进 appProps/Context) */
112
+ interface BridgeHostRouting {
113
+ /** 宿主路由视角的静态绝对路径,如 "/approval";同页各同步实例不得相同或重叠 */
114
+ basePath: string;
115
+ navigation: BridgeHostNavigation;
116
+ }
117
+
118
+ /**
119
+ * React 宿主桥接工厂(/bridge、/bridge/react 导出 createReactBridgeApp;任务书 §3.4)。
120
+ *
121
+ * 定位:接收注入的 loadRemote(不静态引用运行时内核,dist 壳绑定),返回
122
+ * `ComponentType<{ appProps: P; sessionKey?: string | null }>`,负责:
123
+ * - DOM 所有权(§4.5):只创建并保持稳定的空挂载 el(fragment 的固定子节点);
124
+ * pending/error 占位是它的兄弟节点,宿主重渲染不 patch 子应用 root 内部;
125
+ * - 会话代次(§4.3):受控 sessionKey 驱动 挂载/换会话/登出;同会话重渲染不重挂;
126
+ * - StrictMode 安全(§4.5):双 effect 走 cleanup(作废+卸载)→setup(新代次) 顺序,
127
+ * 顺序 unmount/mount 不产生双实例或残留;
128
+ * - unmount 抛错(BN09):报告 MFU-016(phase: unmount)并封锁该容器的新挂载。
129
+ *
130
+ * appProps 是挂载时浅拷贝快照(顶层替换不追踪,重挂由 key 重建);sessionKey
131
+ * 是桥接控制参数,不混入业务 props。
132
+ */
133
+
134
+ /** 渲染函数形态的错误占位:(error, retry) => ReactNode */
135
+ type BridgeErrorFallback = (error: unknown, retry: () => void) => ReactNode;
136
+ interface ReactBridgeAppOptions {
137
+ /** 加载 pending 占位(默认 null) */
138
+ fallback?: ReactNode;
139
+ /** 加载/挂载失败占位;默认内置中文诊断 + 「重试加载 / 刷新页面重试」 */
140
+ error?: ReactNode | BridgeErrorFallback;
141
+ /** 透传现行 loadRemote 的重试选项(0-10 整数),不另叠自动重试 */
142
+ retries?: number;
143
+ /** 本次桥接加载等待上限 ms;不取消已发出的共享请求,迟到结果一律丢弃 */
144
+ timeout?: number;
145
+ /** 无副作用的同步 getter:首次、重试及换会话的实际加载前返回本次所需上下文快照 */
146
+ getContext?: () => Partial<AppContext> & Record<string, unknown>;
147
+ }
3
148
 
4
149
  /** 统一错误码体系(对齐 webpack ScriptExternalLoadError 等运行时错误的可诊断性) */
5
150
  declare class FgError extends Error {
@@ -387,104 +532,6 @@ interface ReactHostPages {
387
532
  }
388
533
  declare function createReactHostPages$1(options: ReactHostPagesOptions, loadRemote: LoadRemoteFn): ReactHostPages;
389
534
 
390
- /**
391
- * 跨应用上下文标准字段表(§4.3,0.8.2 精简后)。
392
- *
393
- * 读写约定:宿主桥先写标准字段;远程 boot 只增不改宿主键;
394
- * 嵌套对象(如 events)是引用共享,子应用挂属性即时可见(同 realm 直引用)。
395
- *
396
- * 精简记录(0.8.2):`token` 快照与 `formUrl`/`baseUrl` 从默认 provide 集合移除——
397
- * token 快照与 getToken 函数引用重复(快照会过期),formUrl/baseUrl 自 0.7.0
398
- * remoteComponent 直渲染后无消费点;项目如需可经扩展位自行提供。
399
- */
400
- interface AppContext {
401
- /** 宿主登录用户原始形态(只读约定) */
402
- user: Record<string, any>;
403
- /** 取最新 token(拉取式防过期;0.8.2 起 bridge 不再传一次性 token 快照,用本函数取值) */
404
- getToken?: () => string | undefined;
405
- /** 宿主 pinia 实例:子应用 useUserStore(ctx.store) 拿共享响应式状态 */
406
- store?: unknown;
407
- /** 宿主 Vue App 实例(同 realm 直引用):全局组件/指令注册目标 */
408
- hostApp?: unknown;
409
- /** EP locale 等 UI 配置(原 W4 字段) */
410
- locale?: unknown;
411
- /** 事件/方法池:events.main.* 宿主提供、events.bpm.* / events.lowcode.* 子应用反向注册 */
412
- events?: Record<string, any>;
413
- /**
414
- * 非敏感登录代次 ID:宿主每次成功登录/重新登录生成新值,token 刷新但会话未变时沿用。
415
- * 远程 onSession 按它去重(同一代次只执行一次)。不是用户 ID、不是 token、不作为授权凭证。
416
- * 远程声明了 onSession 时必填(缺省即 MFU-013)。
417
- */
418
- sessionKey?: string;
419
- /** 项目扩展位(formUrl/baseUrl 等自定义键,按需自行提供) */
420
- [key: string]: unknown;
421
- }
422
- /**
423
- * 宿主写入跨应用上下文(merge 语义,幂等可多次调用,后写覆盖同键)。
424
- *
425
- * 宿主桥(host/src/fulgurjs/host/bridge.ts)在登录完成后调用:
426
- * provideAppContext({ user, getToken, store, hostApp, locale, sessionKey, events: { main: mainEvents }, ... })
427
- * 登录态变化(换账号/token 刷新)时再次调用即以最新值覆盖同键——不要用布尔闩锁把桥封成只跑一次。
428
- */
429
- declare function provideAppContext(config: Partial<AppContext> & Record<string, unknown>): void;
430
- /**
431
- * 宿主退出登录时清理:删除整个 context 对象(旧 user/getToken 引用一并失效),并通知
432
- * 运行时单例作废全部远程的会话信号与 onSession 去重状态(下次登录必须重新执行 onSession)。
433
- *
434
- * 边界(契约):只清 AppContext 与会话初始化状态;不重置远程模块缓存、共享模块图与
435
- * 应用级 setup 注册(同一页面内组件与共享实例继续复用)。页面无运行时单例时静默幂等
436
- * (退出动作不依赖联邦形态,不得因缺运行时而打断登出流程)。
437
- */
438
- declare function clearAppContext(): void;
439
- /**
440
- * 读上下文快照(传输层快照:顶层 merge 结果 + 嵌套对象引用共享)。
441
- * 页面无运行时单例(独立直开远程页)→ CC-002 显式抛错,不静默回空。
442
- */
443
- declare function getAppContext(): AppContext;
444
- /**
445
- * 显式校验读取(远程 setup/boot 消费入口):任一键缺失 → CC-001 三段式。
446
- *
447
- * 用法:const { store, user, hostApp } = requireAppContext('store', 'user', 'hostApp')
448
- * 时序契约:宿主桥先 provide,远程 setup/onSession 后 require——违反即在初始化处显式失败。
449
- */
450
- declare function requireAppContext(...keys: string[]): AppContext;
451
-
452
- /** 统一逻辑位置:pathname 以 / 开头;search 空串或 ? 开头;hash 空串或 # 开头 */
453
- interface BridgeLocation {
454
- pathname: string;
455
- search: string;
456
- hash: string;
457
- }
458
- type BridgeNavigationResult = {
459
- status: 'committed';
460
- location: BridgeLocation;
461
- } | {
462
- status: 'cancelled';
463
- location: BridgeLocation;
464
- };
465
- /** 子应用路由通道(桥接宿主按挂载代次创建,随 mount 第三参数交给子应用) */
466
- interface BridgeChildRoute {
467
- /**
468
- * 远程 spec(宿主创建通道时标注,如 "remote-b/bridge");子应用路由接线
469
- * (connectVueBridgeRouter/createReactBridgeRouter)的诊断错误用它定位真实远程,
470
- * 缺省(纯 memory 小部件自建通道)回退 'child-router'。
471
- */
472
- readonly spec?: string;
473
- getLocation(): BridgeLocation;
474
- subscribe(listener: (location: BridgeLocation) => void): () => void;
475
- navigate(target: BridgeLocation, action: 'push' | 'replace'): Promise<BridgeNavigationResult>;
476
- go(delta: number): void;
477
- }
478
- /** 挂载控制参数(mount 第三参数;不混入业务 props) */
479
- interface BridgeMountOptions {
480
- signal?: AbortSignal;
481
- routing?: BridgeChildRoute;
482
- }
483
- /** 子应用路由协议声明(defineBridgeApp(工厂, { routing: true }) 时写入) */
484
- interface BridgeRoutingProtocol {
485
- protocol: 1;
486
- }
487
-
488
535
  /** 子应用桥接契约(远程 ./bridge 模块的默认导出;任务书 §3.2) */
489
536
  interface BridgeApp {
490
537
  /** 首次根提交完成时才算挂载成功;同一容器未卸载前重复 mount 是契约违例 */
@@ -542,12 +589,58 @@ interface DefineReactBridgeAppOptions {
542
589
  */
543
590
  declare function defineBridgeApp$1(factory: ReactBridgeAppFactory, options?: DefineReactBridgeAppOptions): BridgeApp;
544
591
 
592
+ /** React Router data router 的宿主导航端口与子应用 memory router 接线(统一入口 /react 提供)。 */
593
+
594
+ type ReactBridgeCancelPolicy = (next: BridgeLocation) => boolean;
595
+ interface ReactDataRouterLike {
596
+ state: {
597
+ location: {
598
+ pathname: string;
599
+ search: string;
600
+ hash: string;
601
+ key?: string;
602
+ };
603
+ navigation?: {
604
+ state: string;
605
+ location?: BridgeLocation;
606
+ };
607
+ blockers?: ReadonlyMap<string, {
608
+ state: string;
609
+ reset?: () => void;
610
+ }>;
611
+ };
612
+ subscribe(cb: () => void): () => void;
613
+ navigate(to: string | number, opts?: {
614
+ replace?: boolean;
615
+ }): void | Promise<void>;
616
+ }
617
+ /** canNavigate 是可选预判;最终结果同时核对真实 blocker 与已提交位置。 */
618
+ declare function createReactBridgeNavigation(router: ReactDataRouterLike, options?: {
619
+ canNavigate?: ReactBridgeCancelPolicy;
620
+ basename?: string;
621
+ }): BridgeHostNavigation;
622
+ interface ReactBridgeRouterConnection {
623
+ element: ReactElement;
624
+ dispose(): void;
625
+ }
626
+ /** 返回 RouterProvider 元素,直接作为 defineBridgeApp 工厂的 ReactElement 返回值。 */
627
+ declare function createReactBridgeRouter(routing: BridgeChildRoute, routes: RouteObject[], options?: {
628
+ signal?: AbortSignal;
629
+ }): ReactBridgeRouterConnection;
630
+
545
631
  declare const remoteComponent: <P = Record<string, unknown>>(spec: string, opts?: ReactRemoteComponentOptions) => react.ComponentType<P & {
546
632
  ref?: react.Ref<unknown>;
547
633
  }>;
548
634
  declare const useLoadRemote: <Module = any>(spec: string, opts?: UseLoadRemoteOptions) => UseLoadRemoteResult<Module>;
549
- /** React 子应用桥接契约(defineBridgeApp;远程 ./bridge 模块默认导出,任务书 §3.3) */
635
+ /** React 子应用桥接契约(远程 ./bridge 模块默认导出) */
550
636
  declare const defineBridgeApp: typeof defineBridgeApp$1;
637
+ /** React 宿主桥接工厂:返回 `ComponentType<{ appProps: P; sessionKey?: string | null }>` */
638
+ declare const createReactBridgeApp: <P = Record<string, unknown>>(spec: string, options?: ReactBridgeAppOptions) => react.ComponentType<{
639
+ appProps?: P;
640
+ sessionKey?: string | null;
641
+ routing?: BridgeHostRouting;
642
+ }>;
643
+
551
644
  /** 宿主页面适配器(绑定本包运行时的 loadRemote;选项与返回值类型见 react-adapter) */
552
645
  declare function createReactHostPages(options: Parameters<typeof createReactHostPages$1>[0]): ReactHostPages;
553
646
 
@@ -555,4 +648,4 @@ type RemoteSchema = Record<string, RemoteSchemaEntry>;
555
648
  /** 无插件转换的场景(构建、Node 导入)如实返回空清单。 */
556
649
  declare const remoteSchema: RemoteSchema;
557
650
 
558
- export { type AppContext, type BridgeApp, type FgRuntime, type LoadRemoteOptions, type LoadShareOptions, type PageRouteLike, type PageViolation, type PagesOptions, type PreloadRemoteOptions, type ReactBridgeAppFactory, type ReactHostPages, type ReactHostPagesOptions, type ReactRemoteComponentOptions, type RemoteConfig, type RemoteDebugInfo, RemoteErrorBoundary, type RemoteErrorBoundaryProps, type RemoteErrorFallback, type RemoteInput, type RemoteSchema, type RemoteSchemaEntry, type RemoteSetupContext, type RemoteSetupModule, type ResolvedHostPage, type RuntimeHooks, type RuntimePlugin, type ShareEntry, type ShareScope, type ShareScopeMap, type UseLoadRemoteOptions, type UseLoadRemoteResult, clearAppContext, clearSessionState, createReactHostPages, defineBridgeApp, definePages, getAppContext, getContainer, getLoadedShare, getRuntime, initSharing, loadRemote, loadShare, parseSpec, pinLoadedShare, preloadRemote, provideAppContext, registerPlugins, registerRemote, registerRemotes, registerShare, remoteComponent, remoteSchema, requireAppContext, shareScopeMap, unwrapDefault, useLoadRemote, validatePages, version };
651
+ export { type AppContext, type BridgeApp, type BridgeErrorFallback, type BridgeHostRouting, type FgRuntime, type LoadRemoteOptions, type LoadShareOptions, type PageRouteLike, type PageViolation, type PagesOptions, type PreloadRemoteOptions, type ReactBridgeAppFactory, type ReactBridgeAppOptions, type ReactBridgeCancelPolicy, type ReactBridgeRouterConnection, type ReactHostPages, type ReactHostPagesOptions, type ReactRemoteComponentOptions, type RemoteConfig, type RemoteDebugInfo, RemoteErrorBoundary, type RemoteErrorBoundaryProps, type RemoteErrorFallback, type RemoteInput, type RemoteSchema, type RemoteSchemaEntry, type RemoteSetupContext, type RemoteSetupModule, type ResolvedHostPage, type RuntimeHooks, type RuntimePlugin, type ShareEntry, type ShareScope, type ShareScopeMap, type UseLoadRemoteOptions, type UseLoadRemoteResult, clearAppContext, clearSessionState, createReactBridgeApp, createReactBridgeNavigation, createReactBridgeRouter, createReactHostPages, defineBridgeApp, definePages, getAppContext, getContainer, getLoadedShare, getRuntime, initSharing, loadRemote, loadShare, parseSpec, pinLoadedShare, preloadRemote, provideAppContext, registerPlugins, registerRemote, registerRemotes, registerShare, remoteComponent, remoteSchema, requireAppContext, shareScopeMap, unwrapDefault, useLoadRemote, validatePages, version };
package/dist/react.js CHANGED
@@ -4,9 +4,13 @@ export { definePages, validatePages } from "./pages.js";
4
4
  import { loadRemote } from "./runtime.js";
5
5
  import { createRemoteComponent, createUseLoadRemote, RemoteErrorBoundary, createReactHostPages as createReactHostPagesWithLoader } from "./react-adapter.js";
6
6
  import { defineBridgeApp as defineReactBridgeApp } from "./bridge-app-react.js";
7
+ import { createReactBridgeAppWithLoader } from "./bridge-host-react.js";
8
+ import { createReactBridgeNavigation, createReactBridgeRouter } from "./bridge-router-react.js";
7
9
  export const remoteComponent = createRemoteComponent(loadRemote);
8
10
  export const useLoadRemote = createUseLoadRemote(loadRemote);
9
11
  export { RemoteErrorBoundary };
10
12
  export const createReactHostPages = (options) => createReactHostPagesWithLoader(options, loadRemote);
11
13
  export const defineBridgeApp = defineReactBridgeApp;
14
+ export const createReactBridgeApp = createReactBridgeAppWithLoader(loadRemote);
15
+ export { createReactBridgeNavigation, createReactBridgeRouter };
12
16
  export const remoteSchema = {};
@@ -1,6 +1,3 @@
1
- import * as vue from 'vue';
2
- import { Component, App } from 'vue';
3
-
4
1
  /** 统一错误码体系(对齐 webpack ScriptExternalLoadError 等运行时错误的可诊断性) */
5
2
  declare class FgError extends Error {
6
3
  code: string;
@@ -314,182 +311,20 @@ declare function validatePages(pages: PageRouteLike[], options?: PagesOptions):
314
311
  declare function definePages<P extends PageRouteLike[]>(pages: P, options?: PagesOptions): P;
315
312
 
316
313
  /**
317
- * 宿主页面表纯解析核心(框架无关)。
314
+ * 框架无关浏览器运行时入口(/runtime)。
318
315
  *
319
- * 5.1.0 从 vue-adapter 提取:definePages 校验接入、最长前缀远程归属、缺省 spec 推导、
320
- * base 剥离、段式参数匹配——Vue 与 React 适配器共用同一份解析,组件缓存/错误边界/
321
- * 保活策略由各框架适配器自行负责(不把 Vue 的卸载策略强加给 React,反之亦然)。
322
- */
323
-
324
- /** 页面表数据项(两个框架适配器共用;展示项 fallback/error 等在各适配器定义) */
325
- interface HostPagesCoreOptions {
326
- /** 页面表(宿主路由与布局共用的唯一数据源;definePages R1–R5 校验照常执行) */
327
- pages: PageRouteLike[];
328
- /** 路由前缀 → remote 名(最长前缀匹配;页面路由无匹配前缀时创建期即报错) */
329
- remotePrefixes: Record<string, string>;
330
- /** 缺省 spec 推导(缺省 = 去首段前缀 + 剥 :参数 段,同 definePages 默认) */
331
- deriveSpec?: (route: string) => string;
332
- /** 远程 exposes 清单(dev 由 remoteSchema 提供;build 为空表时按语义诚实降级) */
333
- schema?: Record<string, RemoteSchemaEntry>;
334
- /** ERROR 级校验失败是否 throw(默认 true) */
335
- strict?: boolean;
336
- /** 站点 base 前缀(如 '/main'):resolve 时先剥离再匹配路由空间 */
337
- base?: string;
338
- }
339
- interface ResolvedHostPage {
340
- /** 原页面记录(含宿主自由扩展字段 name/title/keepAlive/...) */
341
- page: PageRouteLike;
342
- /** 命中的 remote 名 */
343
- remote: string;
344
- /** 完整加载 spec(`<remote>/<exposes 键>`,loadRemote 直用) */
345
- spec: string;
346
- /** 路径参数(解码失败只让该次匹配失败,不让页面初始化崩溃) */
347
- params: Record<string, string>;
348
- }
349
-
350
- /** Vue 适配层只接收加载函数,不静态引用运行时内核。 */
351
-
352
- interface RemoteComponentOptions {
353
- loadingComponent?: Component;
354
- errorComponent?: Component;
355
- retries?: number;
356
- delay?: number;
357
- timeout?: number;
358
- }
359
- interface HostPagesOptions extends HostPagesCoreOptions {
360
- /** 每次页面模块实际加载前执行(同步或异步);宿主在此提供最新 context */
361
- beforeLoad?: () => void | Promise<void>;
362
- /** 加载期占位组件(骨架屏) */
363
- loadingComponent?: Component;
364
- /** 错误占位组件(缺省 = 内置错误占位:错误码+根因+修法+重试加载/刷新页面重试;自定义时完全接管) */
365
- errorComponent?: Component;
366
- /** 骨架屏延迟 ms(默认 200,防闪) */
367
- delay?: number;
368
- }
369
- interface HostPages {
370
- /** 原页面记录 */
371
- pages: PageRouteLike[];
372
- /** 路径 → 页面解析(兼容 base 前缀与深链;无匹配返回 null) */
373
- resolve(path: string): ResolvedHostPage | null;
374
- /** 按 spec 取异步页面组件(同 spec 复用;换登录代次后重建以触发会话同步) */
375
- component(spec: string): Component;
376
- /** 保活白名单:keepAlive 页面的组件 name(与实际被 KeepAlive 缓存的包装组件一致) */
377
- keepAliveNames: string[];
378
- }
379
- declare function createHostPages$1(options: HostPagesOptions, load: (spec: string, opts?: {
380
- retries?: number;
381
- }) => Promise<any>): HostPages;
382
-
383
- /** 统一逻辑位置:pathname 以 / 开头;search 空串或 ? 开头;hash 空串或 # 开头 */
384
- interface BridgeLocation {
385
- pathname: string;
386
- search: string;
387
- hash: string;
388
- }
389
- type BridgeNavigationResult = {
390
- status: 'committed';
391
- location: BridgeLocation;
392
- } | {
393
- status: 'cancelled';
394
- location: BridgeLocation;
395
- };
396
- /** 子应用路由通道(桥接宿主按挂载代次创建,随 mount 第三参数交给子应用) */
397
- interface BridgeChildRoute {
398
- /**
399
- * 远程 spec(宿主创建通道时标注,如 "remote-b/bridge");子应用路由接线
400
- * (connectVueBridgeRouter/createReactBridgeRouter)的诊断错误用它定位真实远程,
401
- * 缺省(纯 memory 小部件自建通道)回退 'child-router'。
402
- */
403
- readonly spec?: string;
404
- getLocation(): BridgeLocation;
405
- subscribe(listener: (location: BridgeLocation) => void): () => void;
406
- navigate(target: BridgeLocation, action: 'push' | 'replace'): Promise<BridgeNavigationResult>;
407
- go(delta: number): void;
408
- }
409
- /** 挂载控制参数(mount 第三参数;不混入业务 props) */
410
- interface BridgeMountOptions {
411
- signal?: AbortSignal;
412
- routing?: BridgeChildRoute;
413
- }
414
- /** 子应用路由协议声明(defineBridgeApp(工厂, { routing: true }) 时写入) */
415
- interface BridgeRoutingProtocol {
416
- protocol: 1;
417
- }
418
-
419
- /** 子应用桥接契约(远程 ./bridge 模块的默认导出;任务书 §3.2) */
420
- interface BridgeApp {
421
- /** 首次根提交完成时才算挂载成功;同一容器未卸载前重复 mount 是契约违例 */
422
- mount(el: HTMLElement, props?: Record<string, unknown>, options?: BridgeMountOptions): void | Promise<void>;
423
- /** 同步使当前挂载代次失效并清理已创建的 root;未知容器为 no-op */
424
- unmount(el: HTMLElement): void;
425
- /**
426
- * 路由协议声明(URL 同步):defineBridgeApp(工厂, { routing: true }) 时写入
427
- * { protocol: 1 }。宿主启用 routing 时必须存在且 protocol === 1(MFU-031),
428
- * 不允许静默退回 memory 假装深链成功。
429
- */
430
- routing?: BridgeRoutingProtocol;
431
- }
432
-
433
- /**
434
- * Vue 子应用桥接适配(/runtime 导出 defineBridgeApp;任务书 §3.3 D1/D2)。
435
- *
436
- * 工厂形态:接收 props 快照,返回已装配完整的 VueApp(router/pinia 等由子应用自行装配);
437
- * helper 负责 app.mount(el) / app.unmount() 与按容器 el 的实例跟踪。
438
- *
439
- * 契约语义(§3.2):
440
- * - 契约实例按容器 el 分键(WeakMap):同一契约多处挂载互不干扰;
441
- * - 同一容器未卸载再次 mount → 拒绝(容器占用,原始错误原样抛出)且不覆盖原实例;
442
- * - Vue 的 app.mount 同步完成首次渲染,mount 成功即返回 void(首次根提交语义由 Vue 保证);
443
- * - mount 抛错时清理已创建的 app(best-effort unmount),不留半挂状态;
444
- * - unmount 未知容器为 no-op;mount/unmount 的原始错误**原样抛出**——MFU-016 包装
445
- * (真实 spec + phase + cause)由宿主适配器在生命周期边界统一完成(见 bridgeHostError)。
446
- *
447
- * 本文件零 React:/runtime 导入图隔离由 tests/runtime-entry-graph.test.ts 守护。
448
- */
449
-
450
- /** 工厂第二参数:挂载生命周期与路由通道(URL 同步;不混入业务 props) */
451
- interface VueBridgeAppContext {
452
- /** 会话代次信号(登出/换代即 aborted;异步写回前必须检查) */
453
- signal?: AbortSignal;
454
- /** 路由通道(宿主启用 URL 同步时存在);配 connectVueBridgeRouter 使用 */
455
- routing?: BridgeChildRoute;
456
- }
457
- /**
458
- * Vue 子应用工厂:接收挂载时 props 快照与生命周期上下文,返回装配完成的 VueApp。
459
- * 允许返回 Promise<VueApp>(URL 同步子应用的初始 memory 路由准备是异步的——
460
- * 必须等初始 push 落定再 app.use(router),否则 install 的初始导航会覆盖深链位置;
461
- * 见 /bridge/router/vue 的 connectVueBridgeRouter 与任务书 §1 原型结论 1)。
462
- * Promise 被作废(signal aborted / 容器已换代)时结果丢弃,不落挂。
463
- */
464
- type VueBridgeAppFactory = (props: Record<string, unknown>, ctx?: VueBridgeAppContext) => App | Promise<App>;
465
- interface DefineVueBridgeAppOptions {
466
- /**
467
- * 声明路由协议(URL 同步):契约写入 routing: { protocol: 1 },宿主启用 routing 时
468
- * 校验;未声明而宿主启用同步 → MFU-031(不静默退回 memory 假装深链成功)。
469
- */
470
- routing?: boolean;
471
- }
472
- /**
473
- * 定义 Vue 子应用的桥接契约(远程 ./bridge 模块默认导出)。
316
+ * 定位(6.0.0 入口统一合同):只依赖浏览器与 Module Federation 内核的能力——
317
+ * 共享协商(initSharing/loadShare/…)、远程加载(registerRemotes/loadRemote/…)、
318
+ * 上下文(AppContext)、页面表契约(definePages/validatePages)。
319
+ * 本入口静态导入图**不含 Vue/React/任何框架 router**(tests/runtime-entry-graph 守护),
320
+ * 纯 JS/TS 模块消费方不需要安装任何框架。
474
321
  *
475
- * ```ts
476
- * import { createApp } from 'vue'
477
- * import { defineBridgeApp } from '@fulgurjs/federation/runtime'
478
- * export default defineBridgeApp((props) => { const app = createApp(App, props); app.use(router); return app })
479
- * ```
322
+ * Vue 应用代码用 @fulgurjs/federation/vue,React 用 /react——两个框架入口
323
+ * 再导出本入口全部导出,语义一致、运行时单例同一份(页面级 globalThis 单例)。
480
324
  */
481
- declare function defineBridgeApp$1(factory: VueBridgeAppFactory, options?: DefineVueBridgeAppOptions): BridgeApp;
482
-
483
- declare const remoteComponent: (spec: string, opts?: RemoteComponentOptions) => vue.Component;
484
- /** 宿主页面适配器(绑定本包运行时的 loadRemote;选项与返回值类型见 vue-adapter) */
485
- declare function createHostPages(options: Parameters<typeof createHostPages$1>[0]): HostPages;
486
- /** Vue 子应用桥接契约(defineBridgeApp;远程 ./bridge 模块默认导出,任务书 §3.3) */
487
- declare const defineBridgeApp: typeof defineBridgeApp$1;
488
-
489
- /** 浏览器应用唯一公开入口。 */
490
325
 
491
326
  type RemoteSchema = Record<string, RemoteSchemaEntry>;
492
327
  /** 无插件转换的场景(构建、Node 导入)如实返回空清单。 */
493
328
  declare const remoteSchema: RemoteSchema;
494
329
 
495
- export { type AppContext, type BridgeApp, type FgRuntime, type HostPages, type HostPagesOptions, type LoadRemoteOptions, type LoadShareOptions, type PageRouteLike, type PageViolation, type PagesOptions, type PreloadRemoteOptions, type RemoteComponentOptions, type RemoteConfig, type RemoteDebugInfo, type RemoteInput, type RemoteSchema, type RemoteSchemaEntry, type RemoteSetupContext, type RemoteSetupModule, type ResolvedHostPage, type RuntimeHooks, type RuntimePlugin, type ShareEntry, type ShareScope, type ShareScopeMap, type VueBridgeAppFactory, clearAppContext, clearSessionState, createHostPages, defineBridgeApp, definePages, getAppContext, getContainer, getLoadedShare, getRuntime, initSharing, loadRemote, loadShare, parseSpec, pinLoadedShare, preloadRemote, provideAppContext, registerPlugins, registerRemote, registerRemotes, registerShare, remoteComponent, remoteSchema, requireAppContext, shareScopeMap, unwrapDefault, validatePages, version };
330
+ export { type AppContext, type FgRuntime, type LoadRemoteOptions, type LoadShareOptions, type PageRouteLike, type PageViolation, type PagesOptions, type PreloadRemoteOptions, type RemoteConfig, type RemoteDebugInfo, type RemoteInput, type RemoteSchema, type RemoteSchemaEntry, type RemoteSetupContext, type RemoteSetupModule, type RuntimeHooks, type RuntimePlugin, type ShareEntry, type ShareScope, type ShareScopeMap, clearAppContext, clearSessionState, definePages, getAppContext, getContainer, getLoadedShare, getRuntime, initSharing, loadRemote, loadShare, parseSpec, pinLoadedShare, preloadRemote, provideAppContext, registerPlugins, registerRemote, registerRemotes, registerShare, remoteSchema, requireAppContext, shareScopeMap, unwrapDefault, validatePages, version };
@@ -1,5 +1,4 @@
1
1
  export { initSharing, registerShare, registerRemotes, registerRemote, registerPlugins, loadShare, loadRemote, getLoadedShare, pinLoadedShare, getContainer, preloadRemote, parseSpec, getRuntime, shareScopeMap, unwrapDefault, version, clearSessionState } from "./runtime.js";
2
2
  export { provideAppContext, getAppContext, requireAppContext, clearAppContext } from "./context.js";
3
3
  export { definePages, validatePages } from "./pages.js";
4
- export { remoteComponent, createHostPages, defineBridgeApp } from "./vue.js";
5
4
  export const remoteSchema = {};
package/dist/runtime.js CHANGED
@@ -1,4 +1,4 @@
1
- var ve=/^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-((?:[0-9A-Za-z-]+)(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.-]+)?$/;function N(c){let u=ve.exec(String(c).trim());return u?{major:Number(u[1]),minor:Number(u[2]??0),patch:Number(u[3]??0),pre:u[4]?u[4].split("."):[]}:null}function $e(c,u){if(c.length===0&&u.length===0)return 0;if(c.length===0)return 1;if(u.length===0)return-1;let f=Math.max(c.length,u.length);for(let a=0;a<f;a++){let p=c[a],S=u[a];if(p===void 0)return-1;if(S===void 0)return 1;let b=/^\d+$/.test(p),v=/^\d+$/.test(S);if(b&&v){let I=Number(p)-Number(S);if(I!==0)return I}else{if(b!==v)return b?-1:1;if(p!==S)return p<S?-1:1}}return 0}function x(c,u){let f=N(c),a=N(u);return!f||!a?c<u?-1:c>u?1:0:f.major!==a.major?f.major-a.major:f.minor!==a.minor?f.minor-a.minor:f.patch!==a.patch?f.patch-a.patch:$e(f.pre,a.pre)}var Pe=/^[a-z]+[+:-]/i;function A(c,u){if(u===!1||u==null||u==="")return!0;let f=String(u).trim();return!f||f==="*"||f==="latest"||Pe.test(f)?!0:f.split("||").some(a=>_e(c,a.trim()))}function _e(c,u){if(!u||u==="*")return!N(c)?.pre.length;let f=u.split(/\s+-\s+/);if(f.length===2){let S=f[0].trim(),b=f[1].trim();return!(!A(c,`>=${S}`)||!A(c,`<=${b}`))}let a=N(c);if(!a)return!1;let p=Le(u);if(p===null)return!0;for(let S of p)if(!Te(a,c,S))return!1;return!(a.pre.length>0&&!p.some(S=>S.ver.pre.length>0)&&!p.some(b=>b.ver.major===a.major&&b.ver.minor===a.minor&&b.ver.patch===a.patch))}function Le(c){let u=[],f=c.trim().split(/\s+/).filter(Boolean);if(f.length===0)return null;for(let a of f){let p=/^(>=|<=|>|<|=|\^|~)?(.*)$/.exec(a);if(!p)return null;let S=p[1],b=p[2],v=Oe(S,b);if(v===null)return null;u.push(...v)}return u}function Oe(c,u){let f=Me(u);if(!f)return null;let{ver:a,partial:p}=f;switch(c){case"^":{let S=ke(a);return S?[{op:">=",ver:a},{op:"<",ver:S}]:null}case"~":{let S=p>=2?{major:a.major,minor:a.minor+1,patch:0,pre:[]}:{major:a.major+1,minor:0,patch:0,pre:[]};return[{op:">=",ver:a},{op:"<",ver:S}]}case">=":return[{op:">=",ver:a}];case">":return p===1?[{op:">=",ver:{major:a.major+1,minor:0,patch:0,pre:[]}}]:p===2?[{op:">=",ver:{major:a.major,minor:a.minor+1,patch:0,pre:[]}}]:[{op:">",ver:a}];case"<":return p===1?[{op:"<",ver:{major:a.major,minor:0,patch:0,pre:[]}}]:p===2?[{op:"<",ver:{major:a.major,minor:a.minor,patch:0,pre:[]}}]:[{op:"<",ver:a}];case"<=":return[{op:"<=",ver:a}];case"=":case void 0:return p===1?[{op:">=",ver:a},{op:"<",ver:{major:a.major+1,minor:0,patch:0,pre:[]}}]:p===2?[{op:">=",ver:a},{op:"<",ver:{major:a.major,minor:a.minor+1,patch:0,pre:[]}}]:[{op:"=",ver:a}];default:return null}}function ke(c){return c.major>0?{major:c.major+1,minor:0,patch:0,pre:[]}:c.minor>0?{major:0,minor:c.minor+1,patch:0,pre:[]}:{major:0,minor:0,patch:c.patch+1,pre:[]}}function Me(c){let u=c.replace(/^v/,"").trim();if(!u||u==="*"||u==="x"||u==="X")return{ver:{major:0,minor:0,patch:0,pre:[]},partial:0};let f=u.split("."),a=[],p=0;for(let v of f.slice(0,3))if(/^\d+$/.test(v))a.push(Number(v)),p++;else{if(v==="x"||v==="X"||v==="*")break;break}let S=u.split("-"),b=S.length>1?S.slice(1).join("-").split("+")[0].split("."):[];return p===0&&b.length===0?{ver:{major:0,minor:0,patch:0,pre:[]},partial:0}:{ver:{major:a[0]??0,minor:a[1]??0,patch:a[2]??0,pre:b},partial:p}}function Ie(c,u){switch(u){case">=":return c>=0;case">":return c>0;case"<":return c<0;case"<=":return c<=0;case"=":return c===0}}function Te(c,u,f){let a=`${c.major}.${c.minor}.${c.patch}`+(c.pre.length?`-${c.pre.join(".")}`:"");if(f.upper)return!(!(x(a,`${f.ver.major}.${f.ver.minor}.${f.ver.patch}`+(f.ver.pre.length?`-${f.ver.pre.join(".")}`:""))>=0)||!(x(a,`${f.upper.major}.${f.upper.minor}.${f.upper.patch}`)<0));let p=x(a,`${f.ver.major}.${f.ver.minor}.${f.ver.patch}`+(f.ver.pre.length?`-${f.ver.pre.join(".")}`:"")),S=Ie(p,f.op);return f.ver.pre.length>0&&c.pre.length===0&&(f.op===">"||f.op==="<")?!1:S}var E=class extends Error{code;details;constructor(u,f,a,p){super(`[fulgurjs:${u}] ${f}`,p),this.name="FgError",this.code=u,this.details=a}},w={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",SETUP_INVALID_EXPORT:"MFU-011",SETUP_RUN_FAILED:"MFU-012",SETUP_SESSION_KEY_MISSING:"MFU-013",SETUP_RECURSION:"MFU-014"};var ne="5.9.2";var xe="__fulgurjsSetup",Ae="__FULGURJS_APP_CONFIG__",H=15e3,te=2,je=5,Ne=3e4,Ue=4e3,Ve=.2;function Ce(){let c=Object.create(null),u=new Map,f=[],a=new Set,p=new Map,S=(e,r)=>JSON.stringify([r.shareScope||"default",r.shareKey||e,r.requiredVersion??null,!!r.singleton,!!r.strictVersion]),b=new Map,v=new Map,I=new WeakMap,U=new WeakMap,_={},se=()=>{for(let e of f)try{e.init?.(_)}catch(r){console.warn("[fulgurjs] \u8FD0\u884C\u65F6\u6269\u5C55\u521D\u59CB\u5316\u5931\u8D25\uFF0C\u8BE5\u6269\u5C55\u5C06\u4E0D\u53EF\u7528\uFF1A",e.name,r)}},V=new Map,C,ie=e=>{let r=V.get(e);return r||V.set(e,r={}),r},G=()=>globalThis[Ae]??{};async function B(e,r,n,o){let t=l=>l instanceof E?l:new E(w.SETUP_RUN_FAILED,`\u73B0\u8C61\uFF1A\u8FDC\u7A0B\u5E94\u7528 "${e}" \u7684 ${o} \u521D\u59CB\u5316\u5931\u8D25\u3002
1
+ var ve=/^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-((?:[0-9A-Za-z-]+)(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.-]+)?$/;function N(c){let u=ve.exec(String(c).trim());return u?{major:Number(u[1]),minor:Number(u[2]??0),patch:Number(u[3]??0),pre:u[4]?u[4].split("."):[]}:null}function $e(c,u){if(c.length===0&&u.length===0)return 0;if(c.length===0)return 1;if(u.length===0)return-1;let f=Math.max(c.length,u.length);for(let a=0;a<f;a++){let p=c[a],S=u[a];if(p===void 0)return-1;if(S===void 0)return 1;let b=/^\d+$/.test(p),v=/^\d+$/.test(S);if(b&&v){let I=Number(p)-Number(S);if(I!==0)return I}else{if(b!==v)return b?-1:1;if(p!==S)return p<S?-1:1}}return 0}function x(c,u){let f=N(c),a=N(u);return!f||!a?c<u?-1:c>u?1:0:f.major!==a.major?f.major-a.major:f.minor!==a.minor?f.minor-a.minor:f.patch!==a.patch?f.patch-a.patch:$e(f.pre,a.pre)}var Pe=/^[a-z]+[+:-]/i;function A(c,u){if(u===!1||u==null||u==="")return!0;let f=String(u).trim();return!f||f==="*"||f==="latest"||Pe.test(f)?!0:f.split("||").some(a=>_e(c,a.trim()))}function _e(c,u){if(!u||u==="*")return!N(c)?.pre.length;let f=u.split(/\s+-\s+/);if(f.length===2){let S=f[0].trim(),b=f[1].trim();return!(!A(c,`>=${S}`)||!A(c,`<=${b}`))}let a=N(c);if(!a)return!1;let p=Le(u);if(p===null)return!0;for(let S of p)if(!Te(a,c,S))return!1;return!(a.pre.length>0&&!p.some(S=>S.ver.pre.length>0)&&!p.some(b=>b.ver.major===a.major&&b.ver.minor===a.minor&&b.ver.patch===a.patch))}function Le(c){let u=[],f=c.trim().split(/\s+/).filter(Boolean);if(f.length===0)return null;for(let a of f){let p=/^(>=|<=|>|<|=|\^|~)?(.*)$/.exec(a);if(!p)return null;let S=p[1],b=p[2],v=Oe(S,b);if(v===null)return null;u.push(...v)}return u}function Oe(c,u){let f=Me(u);if(!f)return null;let{ver:a,partial:p}=f;switch(c){case"^":{let S=ke(a);return S?[{op:">=",ver:a},{op:"<",ver:S}]:null}case"~":{let S=p>=2?{major:a.major,minor:a.minor+1,patch:0,pre:[]}:{major:a.major+1,minor:0,patch:0,pre:[]};return[{op:">=",ver:a},{op:"<",ver:S}]}case">=":return[{op:">=",ver:a}];case">":return p===1?[{op:">=",ver:{major:a.major+1,minor:0,patch:0,pre:[]}}]:p===2?[{op:">=",ver:{major:a.major,minor:a.minor+1,patch:0,pre:[]}}]:[{op:">",ver:a}];case"<":return p===1?[{op:"<",ver:{major:a.major,minor:0,patch:0,pre:[]}}]:p===2?[{op:"<",ver:{major:a.major,minor:a.minor,patch:0,pre:[]}}]:[{op:"<",ver:a}];case"<=":return[{op:"<=",ver:a}];case"=":case void 0:return p===1?[{op:">=",ver:a},{op:"<",ver:{major:a.major+1,minor:0,patch:0,pre:[]}}]:p===2?[{op:">=",ver:a},{op:"<",ver:{major:a.major,minor:a.minor+1,patch:0,pre:[]}}]:[{op:"=",ver:a}];default:return null}}function ke(c){return c.major>0?{major:c.major+1,minor:0,patch:0,pre:[]}:c.minor>0?{major:0,minor:c.minor+1,patch:0,pre:[]}:{major:0,minor:0,patch:c.patch+1,pre:[]}}function Me(c){let u=c.replace(/^v/,"").trim();if(!u||u==="*"||u==="x"||u==="X")return{ver:{major:0,minor:0,patch:0,pre:[]},partial:0};let f=u.split("."),a=[],p=0;for(let v of f.slice(0,3))if(/^\d+$/.test(v))a.push(Number(v)),p++;else{if(v==="x"||v==="X"||v==="*")break;break}let S=u.split("-"),b=S.length>1?S.slice(1).join("-").split("+")[0].split("."):[];return p===0&&b.length===0?{ver:{major:0,minor:0,patch:0,pre:[]},partial:0}:{ver:{major:a[0]??0,minor:a[1]??0,patch:a[2]??0,pre:b},partial:p}}function Ie(c,u){switch(u){case">=":return c>=0;case">":return c>0;case"<":return c<0;case"<=":return c<=0;case"=":return c===0}}function Te(c,u,f){let a=`${c.major}.${c.minor}.${c.patch}`+(c.pre.length?`-${c.pre.join(".")}`:"");if(f.upper)return!(!(x(a,`${f.ver.major}.${f.ver.minor}.${f.ver.patch}`+(f.ver.pre.length?`-${f.ver.pre.join(".")}`:""))>=0)||!(x(a,`${f.upper.major}.${f.upper.minor}.${f.upper.patch}`)<0));let p=x(a,`${f.ver.major}.${f.ver.minor}.${f.ver.patch}`+(f.ver.pre.length?`-${f.ver.pre.join(".")}`:"")),S=Ie(p,f.op);return f.ver.pre.length>0&&c.pre.length===0&&(f.op===">"||f.op==="<")?!1:S}var E=class extends Error{code;details;constructor(u,f,a,p){super(`[fulgurjs:${u}] ${f}`,p),this.name="FgError",this.code=u,this.details=a}},w={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",SETUP_INVALID_EXPORT:"MFU-011",SETUP_RUN_FAILED:"MFU-012",SETUP_SESSION_KEY_MISSING:"MFU-013",SETUP_RECURSION:"MFU-014"};var ne="6.0.0";var xe="__fulgurjsSetup",Ae="__FULGURJS_APP_CONFIG__",H=15e3,te=2,je=5,Ne=3e4,Ue=4e3,Ve=.2;function Ce(){let c=Object.create(null),u=new Map,f=[],a=new Set,p=new Map,S=(e,r)=>JSON.stringify([r.shareScope||"default",r.shareKey||e,r.requiredVersion??null,!!r.singleton,!!r.strictVersion]),b=new Map,v=new Map,I=new WeakMap,U=new WeakMap,_={},se=()=>{for(let e of f)try{e.init?.(_)}catch(r){console.warn("[fulgurjs] \u8FD0\u884C\u65F6\u6269\u5C55\u521D\u59CB\u5316\u5931\u8D25\uFF0C\u8BE5\u6269\u5C55\u5C06\u4E0D\u53EF\u7528\uFF1A",e.name,r)}},V=new Map,C,ie=e=>{let r=V.get(e);return r||V.set(e,r={}),r},G=()=>globalThis[Ae]??{};async function B(e,r,n,o){let t=l=>l instanceof E?l:new E(w.SETUP_RUN_FAILED,`\u73B0\u8C61\uFF1A\u8FDC\u7A0B\u5E94\u7528 "${e}" \u7684 ${o} \u521D\u59CB\u5316\u5931\u8D25\u3002
2
2
  \u539F\u56E0\uFF1A${String(l?.message??l)}
3
3
  \u4FEE\u6CD5\uFF1A\u68C0\u67E5\u5E76\u4FEE\u590D\u8BE5 ${o} \u51FD\u6570\u540E\u91CD\u65B0\u52A0\u8F7D\uFF1B\u5931\u8D25\u7F13\u5B58\u5DF2\u6E05\u9664\uFF0C\u53EF\u4EE5\u76F4\u63A5\u91CD\u8BD5\u3002`,{remote:e,phase:o},{cause:l});C=e;let s;try{s=r(n)}catch(l){throw t(l)}finally{C=void 0}try{await s}catch(l){throw t(l)}}async function ae(e,r,n,o){e.debug.setup="pending";try{if(e.manifestUrl)try{await q(`${e.name}/${n}`)}catch{}let t=await r.get(n),s=t?.default;if(typeof s!="function")throw new E(w.SETUP_INVALID_EXPORT,`\u73B0\u8C61\uFF1A\u8FDC\u7A0B\u5E94\u7528 "${e.name}" \u7684 setup \u6A21\u5757 "${n}" \u65E0\u6CD5\u521D\u59CB\u5316\u3002
4
4
  \u539F\u56E0\uFF1A\u9ED8\u8BA4\u5BFC\u51FA\u7C7B\u578B\u4E3A ${t==null?String(t):typeof s}\uFF0C\u5E94\u4E3A\u51FD\u6570\u3002
@@ -373,13 +373,17 @@ function createHostPages(options, load) {
373
373
  let comp = compCache.get(spec);
374
374
  if (!comp) {
375
375
  const name = cleanCompName(spec);
376
+ const keepAlivePage = core.pages.some((p) => p.keepAlive && core.specOf(p) === spec);
376
377
  const pageLoader = async () => {
377
378
  await beforeLoad?.();
378
379
  const mod = await load(spec);
379
- const inner = mod?.default ?? mod;
380
+ let inner = mod?.default ?? mod;
380
381
  if (!inner) {
381
382
  throw noRenderableExportError(spec, inner);
382
383
  }
384
+ if (keepAlivePage && inner && typeof inner === "object") {
385
+ inner = Object.defineProperties({ ...inner }, { name: { value: name, configurable: true } });
386
+ }
383
387
  return inner;
384
388
  };
385
389
  const asyncComp = (0, import_vue.defineAsyncComponent)({
@@ -142,13 +142,17 @@ function createHostPages(options, load) {
142
142
  let comp = compCache.get(spec);
143
143
  if (!comp) {
144
144
  const name = cleanCompName(spec);
145
+ const keepAlivePage = core.pages.some((p) => p.keepAlive && core.specOf(p) === spec);
145
146
  const pageLoader = async () => {
146
147
  await beforeLoad?.();
147
148
  const mod = await load(spec);
148
- const inner = mod?.default ?? mod;
149
+ let inner = mod?.default ?? mod;
149
150
  if (!inner) {
150
151
  throw noRenderableExportError(spec, inner);
151
152
  }
153
+ if (keepAlivePage && inner && typeof inner === "object") {
154
+ inner = Object.defineProperties({ ...inner }, { name: { value: name, configurable: true } });
155
+ }
152
156
  return inner;
153
157
  };
154
158
  const asyncComp = defineAsyncComponent({