@fulgurjs/federation 5.3.3 → 5.4.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 (59) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/DESIGN.md +4 -0
  3. package/README.en.md +23 -3
  4. package/README.md +83 -1
  5. package/dist/bridge-app-react.cjs +14 -4
  6. package/dist/bridge-app-react.d.cts +16 -4
  7. package/dist/bridge-app-react.d.ts +16 -4
  8. package/dist/bridge-app-react.js +6 -4
  9. package/dist/bridge-app-vue.cjs +55 -9
  10. package/dist/bridge-app-vue.d.cts +25 -4
  11. package/dist/bridge-app-vue.d.ts +25 -4
  12. package/dist/bridge-app-vue.js +47 -9
  13. package/dist/bridge-core-BOWvVUxO.d.ts +91 -0
  14. package/dist/bridge-core.cjs +9 -1
  15. package/dist/bridge-core.d.cts +8 -1
  16. package/dist/bridge-core.d.ts +8 -1
  17. package/dist/bridge-core.js +2 -2
  18. package/dist/bridge-errors.cjs +55 -3
  19. package/dist/bridge-errors.d.cts +18 -2
  20. package/dist/bridge-errors.d.ts +18 -2
  21. package/dist/bridge-errors.js +11 -3
  22. package/dist/{bridge-host-react-C55RmGll.d.ts → bridge-host-react-CMVd-ym0.d.ts} +1 -1
  23. package/dist/bridge-host-react.cjs +324 -3
  24. package/dist/bridge-host-react.d.cts +2 -0
  25. package/dist/bridge-host-react.d.ts +2 -0
  26. package/dist/bridge-host-react.js +30 -4
  27. package/dist/{bridge-host-vue-BAxDKqGH.d.ts → bridge-host-vue-BuCGlLdS.d.ts} +1 -1
  28. package/dist/bridge-host-vue.cjs +335 -3
  29. package/dist/bridge-host-vue.js +42 -5
  30. package/dist/bridge-react.d.ts +5 -3
  31. package/dist/bridge-router-core-BxBx-reP.d.cts +44 -0
  32. package/dist/bridge-router-core-BxBx-reP.d.ts +44 -0
  33. package/dist/bridge-router-react.d.ts +96 -0
  34. package/dist/bridge-router-react.js +70 -0
  35. package/dist/bridge-router-vue.d.ts +75 -0
  36. package/dist/bridge-router-vue.js +73 -0
  37. package/dist/bridge-vue.d.ts +2 -2
  38. package/dist/bridge.d.ts +6 -4
  39. package/dist/{chunk-WD2ON7SN.js → chunk-BTJGYDHT.js} +303 -2
  40. package/dist/{chunk-GWJKABE7.js → chunk-GF6KOH67.js} +39 -4
  41. package/dist/{chunk-DH2QMM4Y.js → chunk-JQF7KYZF.js} +50 -2
  42. package/dist/{chunk-ZTRJLCOF.js → chunk-OXEAGRPY.js} +27 -3
  43. package/dist/{chunk-LE2G23E7.js → chunk-PRUYHYX2.js} +1 -1
  44. package/dist/chunk-WOTR2FUQ.js +266 -0
  45. package/dist/index.cjs +2 -2
  46. package/dist/index.js +2 -2
  47. package/dist/react.d.ts +51 -4
  48. package/dist/runtime-entry.d.ts +60 -4
  49. package/dist/runtime.js +1 -1
  50. package/examples/bridge/react-host/package-lock.json +105 -104
  51. package/examples/bridge/react-remote/package-lock.json +105 -104
  52. package/examples/bridge/vue-host/package-lock.json +105 -104
  53. package/examples/bridge/vue-remote/package-lock.json +105 -104
  54. package/examples/react/host/package-lock.json +1 -1
  55. package/examples/react/remote/package-lock.json +1 -1
  56. package/examples/vue/host/package-lock.json +1 -1
  57. package/examples/vue/remote/package-lock.json +1 -1
  58. package/package.json +28 -4
  59. package/dist/bridge-core-6uLJiMVa.d.ts +0 -42
@@ -1,28 +1,65 @@
1
1
  import {
2
2
  bridgeLifecycleError
3
- } from "./chunk-DH2QMM4Y.js";
3
+ } from "./chunk-JQF7KYZF.js";
4
4
  import "./chunk-OF2JCXTZ.js";
5
5
 
6
6
  // src/bridge-app-vue.ts
7
7
  var appsByEl = /* @__PURE__ */ new WeakMap();
8
- function defineBridgeApp(factory) {
8
+ var PENDING_MARKER = { __fulgurjsPending: true };
9
+ function entriesAborted(el) {
10
+ return appsByEl.get(el) !== PENDING_MARKER;
11
+ }
12
+ function defineBridgeApp(factory, options = {}) {
13
+ const attach = (el, app, mountOptions) => {
14
+ if (!app || typeof app.mount !== "function" || typeof app.unmount !== "function") {
15
+ throw new Error(
16
+ `defineBridgeApp \u5DE5\u5382\u8FD4\u56DE\u503C\u4E0D\u662F VueApp\uFF08\u5F53\u524D ${app === null ? "null" : typeof app}\uFF09\uFF1B\u5DE5\u5382\u5FC5\u987B\u8FD4\u56DE createApp(...) \u521B\u5EFA\u7684\u5E94\u7528\u5B9E\u4F8B\u3002`
17
+ );
18
+ }
19
+ try {
20
+ app.mount(el);
21
+ } catch (e) {
22
+ try {
23
+ app.unmount();
24
+ } catch {
25
+ }
26
+ throw bridgeLifecycleError("mount", "bridge", e instanceof Error ? e : String(e));
27
+ }
28
+ appsByEl.set(el, app);
29
+ void mountOptions;
30
+ };
9
31
  return {
10
- mount(el, props) {
32
+ ...options.routing ? { routing: { protocol: 1 } } : {},
33
+ // 同步工厂保持同步语义(容器占用/工厂抛错同步抛,BN03/BN02 口径不变);
34
+ // Promise 工厂(URL 同步初始路由准备)走异步续体:挂起期间作废(signal aborted)
35
+ // 则结果丢弃不落挂(迟到初始化不得复活,BN06 同源语义)。
36
+ mount(el, props, mountOptions) {
11
37
  if (appsByEl.has(el)) {
12
38
  throw bridgeLifecycleError("mount", "bridge", "\u540C\u4E00\u5BB9\u5668 el \u5DF2\u6302\u8F7D\u672C\u6865\u63A5\u5E94\u7528\uFF08\u5BB9\u5668\u5DF2\u88AB\u5360\u7528\uFF09\u3002", {
13
39
  reason: "container-occupied"
14
40
  });
15
41
  }
16
42
  const snapshot = { ...props ?? {} };
43
+ const ctx = { signal: mountOptions?.signal, routing: mountOptions?.routing };
17
44
  let app;
18
45
  try {
19
- app = factory(snapshot);
20
- if (!app || typeof app.mount !== "function" || typeof app.unmount !== "function") {
21
- throw new Error(
22
- `defineBridgeApp \u5DE5\u5382\u8FD4\u56DE\u503C\u4E0D\u662F VueApp\uFF08\u5F53\u524D ${app === null ? "null" : typeof app}\uFF09\uFF1B\u5DE5\u5382\u5FC5\u987B\u8FD4\u56DE createApp(...) \u521B\u5EFA\u7684\u5E94\u7528\u5B9E\u4F8B\u3002`
46
+ const produced = factory(snapshot, ctx);
47
+ const thenable = produced.then;
48
+ if (typeof thenable === "function") {
49
+ appsByEl.set(el, PENDING_MARKER);
50
+ return produced.then(
51
+ (resolved) => {
52
+ if (entriesAborted(el)) return;
53
+ attach(el, resolved, mountOptions);
54
+ },
55
+ (e) => {
56
+ if (entriesAborted(el)) return;
57
+ appsByEl.delete(el);
58
+ throw bridgeLifecycleError("mount", "bridge", e instanceof Error ? e : String(e));
59
+ }
23
60
  );
24
61
  }
25
- app.mount(el);
62
+ app = produced;
26
63
  } catch (e) {
27
64
  if (app) {
28
65
  try {
@@ -32,12 +69,13 @@ function defineBridgeApp(factory) {
32
69
  }
33
70
  throw bridgeLifecycleError("mount", "bridge", e instanceof Error ? e : String(e));
34
71
  }
35
- appsByEl.set(el, app);
72
+ attach(el, app, mountOptions);
36
73
  },
37
74
  unmount(el) {
38
75
  const app = appsByEl.get(el);
39
76
  if (!app) return;
40
77
  appsByEl.delete(el);
78
+ if (app === PENDING_MARKER) return;
41
79
  try {
42
80
  app.unmount();
43
81
  } catch (e) {
@@ -0,0 +1,91 @@
1
+ /** 统一逻辑位置:pathname 以 / 开头;search 空串或 ? 开头;hash 空串或 # 开头 */
2
+ interface BridgeLocation {
3
+ pathname: string;
4
+ search: string;
5
+ hash: string;
6
+ }
7
+ type BridgeNavigationResult = {
8
+ status: 'committed';
9
+ location: BridgeLocation;
10
+ } | {
11
+ status: 'cancelled';
12
+ location: BridgeLocation;
13
+ };
14
+ /** 宿主导航端口(宿主适配器把 Router 包装成本接口;逻辑路径不含部署 base) */
15
+ interface BridgeHostNavigation {
16
+ getLocation(): BridgeLocation;
17
+ subscribe(listener: (location: BridgeLocation) => void): () => void;
18
+ navigate(target: BridgeLocation, action: 'push' | 'replace'): Promise<BridgeNavigationResult>;
19
+ go(delta: number): void;
20
+ }
21
+ /** 子应用路由通道(桥接宿主按挂载代次创建,随 mount 第三参数交给子应用) */
22
+ interface BridgeChildRoute {
23
+ getLocation(): BridgeLocation;
24
+ subscribe(listener: (location: BridgeLocation) => void): () => void;
25
+ navigate(target: BridgeLocation, action: 'push' | 'replace'): Promise<BridgeNavigationResult>;
26
+ go(delta: number): void;
27
+ }
28
+ /** 挂载控制参数(mount 第三参数;不混入业务 props) */
29
+ interface BridgeMountOptions {
30
+ signal?: AbortSignal;
31
+ routing?: BridgeChildRoute;
32
+ }
33
+ /** 子应用路由协议声明(defineBridgeApp(工厂, { routing: true }) 时写入) */
34
+ interface BridgeRoutingProtocol {
35
+ protocol: 1;
36
+ }
37
+ /** 宿主组件 routing prop(独立控制通道,不进 appProps/Context) */
38
+ interface BridgeHostRouting {
39
+ /** 宿主路由视角的静态绝对路径,如 "/approval";同页各同步实例不得相同或重叠 */
40
+ basePath: string;
41
+ navigation: BridgeHostNavigation;
42
+ }
43
+
44
+ /**
45
+ * 跨应用上下文标准字段表(§4.3,0.8.2 精简后)。
46
+ *
47
+ * 读写约定:宿主桥先写标准字段;远程 boot 只增不改宿主键;
48
+ * 嵌套对象(如 events)是引用共享,子应用挂属性即时可见(同 realm 直引用)。
49
+ *
50
+ * 精简记录(0.8.2):`token` 快照与 `formUrl`/`baseUrl` 从默认 provide 集合移除——
51
+ * token 快照与 getToken 函数引用重复(快照会过期),formUrl/baseUrl 自 0.7.0
52
+ * remoteComponent 直渲染后无消费点;项目如需可经扩展位自行提供。
53
+ */
54
+ interface AppContext {
55
+ /** 宿主登录用户原始形态(只读约定) */
56
+ user: Record<string, any>;
57
+ /** 取最新 token(拉取式防过期;0.8.2 起 bridge 不再传一次性 token 快照,用本函数取值) */
58
+ getToken?: () => string | undefined;
59
+ /** 宿主 pinia 实例:子应用 useUserStore(ctx.store) 拿共享响应式状态 */
60
+ store?: unknown;
61
+ /** 宿主 Vue App 实例(同 realm 直引用):全局组件/指令注册目标 */
62
+ hostApp?: unknown;
63
+ /** EP locale 等 UI 配置(原 W4 字段) */
64
+ locale?: unknown;
65
+ /** 事件/方法池:events.main.* 宿主提供、events.bpm.* / events.lowcode.* 子应用反向注册 */
66
+ events?: Record<string, any>;
67
+ /**
68
+ * 非敏感登录代次 ID:宿主每次成功登录/重新登录生成新值,token 刷新但会话未变时沿用。
69
+ * 远程 onSession 按它去重(同一代次只执行一次)。不是用户 ID、不是 token、不作为授权凭证。
70
+ * 远程声明了 onSession 时必填(缺省即 MFU-013)。
71
+ */
72
+ sessionKey?: string;
73
+ /** 项目扩展位(formUrl/baseUrl 等自定义键,按需自行提供) */
74
+ [key: string]: unknown;
75
+ }
76
+
77
+ /** 子应用桥接契约(远程 ./bridge 模块的默认导出;任务书 §3.2) */
78
+ interface BridgeApp {
79
+ /** 首次根提交完成时才算挂载成功;同一容器未卸载前重复 mount 是契约违例 */
80
+ mount(el: HTMLElement, props?: Record<string, unknown>, options?: BridgeMountOptions): void | Promise<void>;
81
+ /** 同步使当前挂载代次失效并清理已创建的 root;未知容器为 no-op */
82
+ unmount(el: HTMLElement): void;
83
+ /**
84
+ * 路由协议声明(URL 同步):defineBridgeApp(工厂, { routing: true }) 时写入
85
+ * { protocol: 1 }。宿主启用 routing 时必须存在且 protocol === 1(MFU-031),
86
+ * 不允许静默退回 memory 假装深链成功。
87
+ */
88
+ routing?: BridgeRoutingProtocol;
89
+ }
90
+
91
+ export type { AppContext as A, BridgeHostRouting as B, BridgeApp as a };
@@ -60,7 +60,15 @@ var BridgeErrorCodes = {
60
60
  /** 桥接准备或生命周期失败(details.phase = getContext | mount | unmount) */
61
61
  BRIDGE_LIFECYCLE_FAILED: "MFU-016",
62
62
  /** 桥接会话参数与 AppContext 不一致(受控 sessionKey 与全局会话矛盾) */
63
- BRIDGE_SESSION_MISMATCH: "MFU-017"
63
+ BRIDGE_SESSION_MISMATCH: "MFU-017",
64
+ /** 路由同步配置/前缀冲突(basePath 非法、同页前缀冲突或重叠) */
65
+ ROUTING_CONFIG_INVALID: "MFU-030",
66
+ /** 路由协议缺失/通道失效(子应用未声明 routing 协议,或已销毁通道被再次使用) */
67
+ ROUTING_PROTOCOL_MISSING: "MFU-031",
68
+ /** 非法导航(目标越界前缀、非法 go 参数、失效实例的请求) */
69
+ ROUTING_NAVIGATION_INVALID: "MFU-032",
70
+ /** 路由准备/同步失败(重定向循环、子应用路由准备失败且已阻止错误页面显示) */
71
+ ROUTING_SYNC_FAILED: "MFU-033"
64
72
  };
65
73
  function invalidBridgeContractError(spec, mod) {
66
74
  const actual = mod === null ? "null" : typeof mod;
@@ -1,11 +1,18 @@
1
1
  import { AppContext } from './context.cjs';
2
+ import { a as BridgeMountOptions, b as BridgeRoutingProtocol } from './bridge-router-core-BxBx-reP.cjs';
2
3
 
3
4
  /** 子应用桥接契约(远程 ./bridge 模块的默认导出;任务书 §3.2) */
4
5
  interface BridgeApp {
5
6
  /** 首次根提交完成时才算挂载成功;同一容器未卸载前重复 mount 是契约违例 */
6
- mount(el: HTMLElement, props?: Record<string, unknown>): void | Promise<void>;
7
+ mount(el: HTMLElement, props?: Record<string, unknown>, options?: BridgeMountOptions): void | Promise<void>;
7
8
  /** 同步使当前挂载代次失效并清理已创建的 root;未知容器为 no-op */
8
9
  unmount(el: HTMLElement): void;
10
+ /**
11
+ * 路由协议声明(URL 同步):defineBridgeApp(工厂, { routing: true }) 时写入
12
+ * { protocol: 1 }。宿主启用 routing 时必须存在且 protocol === 1(MFU-031),
13
+ * 不允许静默退回 memory 假装深链成功。
14
+ */
15
+ routing?: BridgeRoutingProtocol;
9
16
  }
10
17
  /** 远程模块 → 契约校验(默认导出须含函数类型的 mount/unmount,否则 MFU-015) */
11
18
  declare function assertBridgeContract(spec: string, mod: unknown): BridgeApp;
@@ -1,11 +1,18 @@
1
1
  import { AppContext } from './context.js';
2
+ import { a as BridgeMountOptions, b as BridgeRoutingProtocol } from './bridge-router-core-BxBx-reP.js';
2
3
 
3
4
  /** 子应用桥接契约(远程 ./bridge 模块的默认导出;任务书 §3.2) */
4
5
  interface BridgeApp {
5
6
  /** 首次根提交完成时才算挂载成功;同一容器未卸载前重复 mount 是契约违例 */
6
- mount(el: HTMLElement, props?: Record<string, unknown>): void | Promise<void>;
7
+ mount(el: HTMLElement, props?: Record<string, unknown>, options?: BridgeMountOptions): void | Promise<void>;
7
8
  /** 同步使当前挂载代次失效并清理已创建的 root;未知容器为 no-op */
8
9
  unmount(el: HTMLElement): void;
10
+ /**
11
+ * 路由协议声明(URL 同步):defineBridgeApp(工厂, { routing: true }) 时写入
12
+ * { protocol: 1 }。宿主启用 routing 时必须存在且 protocol === 1(MFU-031),
13
+ * 不允许静默退回 memory 假装深链成功。
14
+ */
15
+ routing?: BridgeRoutingProtocol;
9
16
  }
10
17
  /** 远程模块 → 契约校验(默认导出须含函数类型的 mount/unmount,否则 MFU-015) */
11
18
  declare function assertBridgeContract(spec: string, mod: unknown): BridgeApp;
@@ -6,8 +6,8 @@ import {
6
6
  releaseBridgeSession,
7
7
  resolveBridgeContext,
8
8
  withBridgeTimeout
9
- } from "./chunk-LE2G23E7.js";
10
- import "./chunk-DH2QMM4Y.js";
9
+ } from "./chunk-PRUYHYX2.js";
10
+ import "./chunk-JQF7KYZF.js";
11
11
  import "./chunk-TSYLDY6H.js";
12
12
  import "./chunk-OF2JCXTZ.js";
13
13
  export {
@@ -24,7 +24,11 @@ __export(bridge_errors_exports, {
24
24
  bridgeLifecycleError: () => bridgeLifecycleError,
25
25
  bridgeSessionMismatchError: () => bridgeSessionMismatchError,
26
26
  invalidBridgeContractError: () => invalidBridgeContractError,
27
- invalidSessionKeyError: () => invalidSessionKeyError
27
+ invalidSessionKeyError: () => invalidSessionKeyError,
28
+ routingConfigError: () => routingConfigError,
29
+ routingNavigationError: () => routingNavigationError,
30
+ routingProtocolError: () => routingProtocolError,
31
+ routingSyncError: () => routingSyncError
28
32
  });
29
33
  module.exports = __toCommonJS(bridge_errors_exports);
30
34
 
@@ -47,7 +51,15 @@ var BridgeErrorCodes = {
47
51
  /** 桥接准备或生命周期失败(details.phase = getContext | mount | unmount) */
48
52
  BRIDGE_LIFECYCLE_FAILED: "MFU-016",
49
53
  /** 桥接会话参数与 AppContext 不一致(受控 sessionKey 与全局会话矛盾) */
50
- BRIDGE_SESSION_MISMATCH: "MFU-017"
54
+ BRIDGE_SESSION_MISMATCH: "MFU-017",
55
+ /** 路由同步配置/前缀冲突(basePath 非法、同页前缀冲突或重叠) */
56
+ ROUTING_CONFIG_INVALID: "MFU-030",
57
+ /** 路由协议缺失/通道失效(子应用未声明 routing 协议,或已销毁通道被再次使用) */
58
+ ROUTING_PROTOCOL_MISSING: "MFU-031",
59
+ /** 非法导航(目标越界前缀、非法 go 参数、失效实例的请求) */
60
+ ROUTING_NAVIGATION_INVALID: "MFU-032",
61
+ /** 路由准备/同步失败(重定向循环、子应用路由准备失败且已阻止错误页面显示) */
62
+ ROUTING_SYNC_FAILED: "MFU-033"
51
63
  };
52
64
  function invalidBridgeContractError(spec, mod) {
53
65
  const actual = mod === null ? "null" : typeof mod;
@@ -104,11 +116,51 @@ function invalidSessionKeyError(spec, value) {
104
116
  { spec, value: String(value) }
105
117
  );
106
118
  }
119
+ function routingConfigError(spec, reason) {
120
+ return new FgError(
121
+ BridgeErrorCodes.ROUTING_CONFIG_INVALID,
122
+ `\u73B0\u8C61\uFF1A\u6865\u63A5\u5E94\u7528 "${spec}" \u7684 URL \u540C\u6B65\u914D\u7F6E\u65E0\u6CD5\u542F\u7528\u3002
123
+ \u539F\u56E0\uFF1A${reason}
124
+ \u4FEE\u6CD5\uFF1A\u4FEE\u6B63 routing.basePath \u4E3A\u5BBF\u4E3B\u8DEF\u7531\u89C6\u89D2\u7684\u9759\u6001\u7EDD\u5BF9\u8DEF\u5F84\uFF08\u5982 "/approval"\uFF09\uFF0C\u5E76\u4FDD\u8BC1\u540C\u9875\u5404\u540C\u6B65\u5B9E\u4F8B\u524D\u7F00\u4E92\u4E0D\u91CD\u53E0\uFF1B\u5BBF\u4E3B\u8DEF\u7531\u9700\u58F0\u660E\u5BF9\u5E94\u7684\u540E\u7F00\u5339\u914D\uFF08Vue "/approval/:pathMatch(.*)*"\u3001React "/approval/*"\uFF09\u3002`,
125
+ { spec }
126
+ );
127
+ }
128
+ function routingProtocolError(spec, reason) {
129
+ return new FgError(
130
+ BridgeErrorCodes.ROUTING_PROTOCOL_MISSING,
131
+ `\u73B0\u8C61\uFF1A\u6865\u63A5\u5E94\u7528 "${spec}" \u7684 URL \u540C\u6B65\u901A\u9053\u4E0D\u53EF\u7528\u3002
132
+ \u539F\u56E0\uFF1A${reason}
133
+ \u4FEE\u6CD5\uFF1A\u5B50\u5E94\u7528\u4EE5 defineBridgeApp(\u5DE5\u5382, { routing: true }) \u58F0\u660E\u8DEF\u7531\u534F\u8BAE\u5E76\u5728\u5DE5\u5382\u7B2C\u4E8C\u53C2\u6570\u63A5\u6536 { signal, routing } \u63A5\u7EBF\u53D7\u63A7\u8DEF\u7531\uFF1B\u901A\u9053\u968F\u6302\u8F7D\u751F\u547D\u5468\u671F\u521B\u5EFA\uFF0C\u9500\u6BC1\u540E\u4E0D\u5F97\u590D\u7528\uFF08\u91CD\u6302\u4F1A\u5F97\u5230\u65B0\u901A\u9053\uFF09\u3002`,
134
+ { spec }
135
+ );
136
+ }
137
+ function routingNavigationError(spec, reason) {
138
+ return new FgError(
139
+ BridgeErrorCodes.ROUTING_NAVIGATION_INVALID,
140
+ `\u73B0\u8C61\uFF1A\u6865\u63A5\u5E94\u7528 "${spec}" \u7684\u4E00\u6B21\u5BFC\u822A\u8BF7\u6C42\u88AB\u62D2\u7EDD\u3002
141
+ \u539F\u56E0\uFF1A${reason}
142
+ \u4FEE\u6CD5\uFF1A\u5B50\u5E94\u7528\u5BFC\u822A\u76EE\u6807\u5FC5\u987B\u4F4D\u4E8E\u81EA\u8EAB basePath \u524D\u7F00\u5185\uFF08\u8DE8\u524D\u7F00\u8BF7\u7528\u5BBF\u4E3B\u83DC\u5355/\u5BBF\u4E3B\u80FD\u529B\uFF09\uFF1Bgo \u53C2\u6570\u4E3A\u6709\u9650\u6574\u6570\u4E14 |delta| \u2264 50\u3002`,
143
+ { spec }
144
+ );
145
+ }
146
+ function routingSyncError(spec, reason, chain) {
147
+ return new FgError(
148
+ BridgeErrorCodes.ROUTING_SYNC_FAILED,
149
+ `\u73B0\u8C61\uFF1A\u6865\u63A5\u5E94\u7528 "${spec}" \u7684 URL \u540C\u6B65\u5728\u91CD\u5B9A\u5411\u94FE\u4E0A\u8D85\u51FA\u4E0A\u9650\uFF08${chain.length} \u6B21\uFF09\u3002
150
+ \u539F\u56E0\uFF1A${reason}
151
+ \u4FEE\u6CD5\uFF1A\u68C0\u67E5\u5B50\u5E94\u7528\u8DEF\u7531\u7684\u91CD\u5B9A\u5411\u89C4\u5219\u662F\u5426\u4E92\u76F8\u6210\u73AF\uFF1B\u540C\u6B65\u91CD\u5B9A\u5411\u4F7F\u7528 replace \u4E14\u4E0D\u5F97\u5BF9\u540C\u4E00\u4F4D\u7F6E\u91CD\u590D\u53D1\u8D77\u3002\u76EE\u6807\u94FE\uFF1A${chain.join(" \u2192 ")}\u3002`,
152
+ { spec, chain: [...chain] }
153
+ );
154
+ }
107
155
  // Annotate the CommonJS export names for ESM import in node:
108
156
  0 && (module.exports = {
109
157
  BridgeErrorCodes,
110
158
  bridgeLifecycleError,
111
159
  bridgeSessionMismatchError,
112
160
  invalidBridgeContractError,
113
- invalidSessionKeyError
161
+ invalidSessionKeyError,
162
+ routingConfigError,
163
+ routingNavigationError,
164
+ routingProtocolError,
165
+ routingSyncError
114
166
  });
@@ -6,7 +6,7 @@ declare class FgError extends Error {
6
6
  }
7
7
 
8
8
  /**
9
- * 桥接层错误码表(MFU-015/016/017,任务书 D3)。
9
+ * 桥接层错误码表(MFU-015/016/017 + 路由同步 MFU-030~033,任务书 D3 / URL 同步 §6)。
10
10
  *
11
11
  * 与 runtime.js 解耦:桥接专用分支不进内核 bundle(runtime 内核零改动为首选目标);
12
12
  * 码值登记于 src/diagnostics.ts 的 CODE_REGISTRY,由 scripts/check-manual-codes.mjs
@@ -21,6 +21,14 @@ declare const BridgeErrorCodes: {
21
21
  readonly BRIDGE_LIFECYCLE_FAILED: "MFU-016";
22
22
  /** 桥接会话参数与 AppContext 不一致(受控 sessionKey 与全局会话矛盾) */
23
23
  readonly BRIDGE_SESSION_MISMATCH: "MFU-017";
24
+ /** 路由同步配置/前缀冲突(basePath 非法、同页前缀冲突或重叠) */
25
+ readonly ROUTING_CONFIG_INVALID: "MFU-030";
26
+ /** 路由协议缺失/通道失效(子应用未声明 routing 协议,或已销毁通道被再次使用) */
27
+ readonly ROUTING_PROTOCOL_MISSING: "MFU-031";
28
+ /** 非法导航(目标越界前缀、非法 go 参数、失效实例的请求) */
29
+ readonly ROUTING_NAVIGATION_INVALID: "MFU-032";
30
+ /** 路由准备/同步失败(重定向循环、子应用路由准备失败且已阻止错误页面显示) */
31
+ readonly ROUTING_SYNC_FAILED: "MFU-033";
24
32
  };
25
33
  /** 桥接生命周期阶段(MFU-016 details.phase 取值) */
26
34
  type BridgePhase = 'getContext' | 'mount' | 'unmount';
@@ -32,5 +40,13 @@ declare function bridgeLifecycleError(phase: BridgePhase, spec: string, cause: u
32
40
  declare function bridgeSessionMismatchError(spec: string, controlled: string, actual: unknown, extra?: Record<string, unknown>): FgError;
33
41
  /** MFU-017:受控 sessionKey 值本身非法(空字符串/数字等,非 undefined/null/非空字符串) */
34
42
  declare function invalidSessionKeyError(spec: string, value: unknown): FgError;
43
+ /** MFU-030:路由同步配置非法或前缀冲突(basePath 校验失败、同页重叠前缀登记) */
44
+ declare function routingConfigError(spec: string, reason: string): FgError;
45
+ /** MFU-031:路由协议缺失/通道失效(子应用未以 { routing: true } 声明协议,或通道已销毁仍被使用) */
46
+ declare function routingProtocolError(spec: string, reason: string): FgError;
47
+ /** MFU-032:非法导航(越界目标、非法 go 参数、失效通道请求被拒绝) */
48
+ declare function routingNavigationError(spec: string, reason: string): FgError;
49
+ /** MFU-033:路由准备/同步失败(重定向循环等;不伪装成功也不静默回退 memory) */
50
+ declare function routingSyncError(spec: string, reason: string, chain: string[]): FgError;
35
51
 
36
- export { BridgeErrorCodes, type BridgePhase, bridgeLifecycleError, bridgeSessionMismatchError, invalidBridgeContractError, invalidSessionKeyError };
52
+ export { BridgeErrorCodes, type BridgePhase, bridgeLifecycleError, bridgeSessionMismatchError, invalidBridgeContractError, invalidSessionKeyError, routingConfigError, routingNavigationError, routingProtocolError, routingSyncError };
@@ -6,7 +6,7 @@ declare class FgError extends Error {
6
6
  }
7
7
 
8
8
  /**
9
- * 桥接层错误码表(MFU-015/016/017,任务书 D3)。
9
+ * 桥接层错误码表(MFU-015/016/017 + 路由同步 MFU-030~033,任务书 D3 / URL 同步 §6)。
10
10
  *
11
11
  * 与 runtime.js 解耦:桥接专用分支不进内核 bundle(runtime 内核零改动为首选目标);
12
12
  * 码值登记于 src/diagnostics.ts 的 CODE_REGISTRY,由 scripts/check-manual-codes.mjs
@@ -21,6 +21,14 @@ declare const BridgeErrorCodes: {
21
21
  readonly BRIDGE_LIFECYCLE_FAILED: "MFU-016";
22
22
  /** 桥接会话参数与 AppContext 不一致(受控 sessionKey 与全局会话矛盾) */
23
23
  readonly BRIDGE_SESSION_MISMATCH: "MFU-017";
24
+ /** 路由同步配置/前缀冲突(basePath 非法、同页前缀冲突或重叠) */
25
+ readonly ROUTING_CONFIG_INVALID: "MFU-030";
26
+ /** 路由协议缺失/通道失效(子应用未声明 routing 协议,或已销毁通道被再次使用) */
27
+ readonly ROUTING_PROTOCOL_MISSING: "MFU-031";
28
+ /** 非法导航(目标越界前缀、非法 go 参数、失效实例的请求) */
29
+ readonly ROUTING_NAVIGATION_INVALID: "MFU-032";
30
+ /** 路由准备/同步失败(重定向循环、子应用路由准备失败且已阻止错误页面显示) */
31
+ readonly ROUTING_SYNC_FAILED: "MFU-033";
24
32
  };
25
33
  /** 桥接生命周期阶段(MFU-016 details.phase 取值) */
26
34
  type BridgePhase = 'getContext' | 'mount' | 'unmount';
@@ -32,5 +40,13 @@ declare function bridgeLifecycleError(phase: BridgePhase, spec: string, cause: u
32
40
  declare function bridgeSessionMismatchError(spec: string, controlled: string, actual: unknown, extra?: Record<string, unknown>): FgError;
33
41
  /** MFU-017:受控 sessionKey 值本身非法(空字符串/数字等,非 undefined/null/非空字符串) */
34
42
  declare function invalidSessionKeyError(spec: string, value: unknown): FgError;
43
+ /** MFU-030:路由同步配置非法或前缀冲突(basePath 校验失败、同页重叠前缀登记) */
44
+ declare function routingConfigError(spec: string, reason: string): FgError;
45
+ /** MFU-031:路由协议缺失/通道失效(子应用未以 { routing: true } 声明协议,或通道已销毁仍被使用) */
46
+ declare function routingProtocolError(spec: string, reason: string): FgError;
47
+ /** MFU-032:非法导航(越界目标、非法 go 参数、失效通道请求被拒绝) */
48
+ declare function routingNavigationError(spec: string, reason: string): FgError;
49
+ /** MFU-033:路由准备/同步失败(重定向循环等;不伪装成功也不静默回退 memory) */
50
+ declare function routingSyncError(spec: string, reason: string, chain: string[]): FgError;
35
51
 
36
- export { BridgeErrorCodes, type BridgePhase, bridgeLifecycleError, bridgeSessionMismatchError, invalidBridgeContractError, invalidSessionKeyError };
52
+ export { BridgeErrorCodes, type BridgePhase, bridgeLifecycleError, bridgeSessionMismatchError, invalidBridgeContractError, invalidSessionKeyError, routingConfigError, routingNavigationError, routingProtocolError, routingSyncError };
@@ -3,13 +3,21 @@ import {
3
3
  bridgeLifecycleError,
4
4
  bridgeSessionMismatchError,
5
5
  invalidBridgeContractError,
6
- invalidSessionKeyError
7
- } from "./chunk-DH2QMM4Y.js";
6
+ invalidSessionKeyError,
7
+ routingConfigError,
8
+ routingNavigationError,
9
+ routingProtocolError,
10
+ routingSyncError
11
+ } from "./chunk-JQF7KYZF.js";
8
12
  import "./chunk-OF2JCXTZ.js";
9
13
  export {
10
14
  BridgeErrorCodes,
11
15
  bridgeLifecycleError,
12
16
  bridgeSessionMismatchError,
13
17
  invalidBridgeContractError,
14
- invalidSessionKeyError
18
+ invalidSessionKeyError,
19
+ routingConfigError,
20
+ routingNavigationError,
21
+ routingProtocolError,
22
+ routingSyncError
15
23
  };
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { A as AppContext } from './bridge-core-6uLJiMVa.js';
2
+ import { A as AppContext } from './bridge-core-BOWvVUxO.js';
3
3
 
4
4
  /**
5
5
  * React 宿主桥接工厂(/bridge、/bridge/react 导出 createReactBridgeApp;任务书 §3.4)。