@fulgurjs/federation 5.2.5 → 5.3.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 (101) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/DESIGN.md +7 -0
  3. package/README.en.md +86 -4
  4. package/README.md +125 -3
  5. package/dist/bridge-app-react.cjs +185 -0
  6. package/dist/bridge-app-react.d.cts +37 -0
  7. package/dist/bridge-app-react.d.ts +37 -0
  8. package/dist/bridge-app-react.js +115 -0
  9. package/dist/bridge-app-vue.cjs +111 -0
  10. package/dist/bridge-app-vue.d.cts +34 -0
  11. package/dist/bridge-app-vue.d.ts +34 -0
  12. package/dist/bridge-app-vue.js +51 -0
  13. package/dist/bridge-core-6uLJiMVa.d.ts +42 -0
  14. package/dist/bridge-core.cjs +224 -0
  15. package/dist/bridge-core.d.cts +51 -0
  16. package/dist/bridge-core.d.ts +51 -0
  17. package/dist/bridge-core.js +21 -0
  18. package/dist/bridge-errors.cjs +114 -0
  19. package/dist/bridge-errors.d.cts +36 -0
  20. package/dist/bridge-errors.d.ts +36 -0
  21. package/dist/bridge-errors.js +15 -0
  22. package/dist/bridge-host-react-C55RmGll.d.ts +35 -0
  23. package/dist/bridge-host-react.cjs +392 -0
  24. package/dist/bridge-host-react.d.cts +45 -0
  25. package/dist/bridge-host-react.d.ts +45 -0
  26. package/dist/bridge-host-react.js +183 -0
  27. package/dist/bridge-host-vue-BAxDKqGH.d.ts +32 -0
  28. package/dist/bridge-host-vue.cjs +426 -0
  29. package/dist/bridge-host-vue.d.cts +39 -0
  30. package/dist/bridge-host-vue.d.ts +39 -0
  31. package/dist/bridge-host-vue.js +211 -0
  32. package/dist/bridge-react.d.ts +12 -0
  33. package/dist/bridge-react.js +3 -0
  34. package/dist/bridge-vue.d.ts +8 -0
  35. package/dist/bridge-vue.js +3 -0
  36. package/dist/bridge.d.ts +16 -0
  37. package/dist/bridge.js +5 -0
  38. package/dist/chunk-E55P4TIY.js +76 -0
  39. package/dist/chunk-EH34L46P.js +207 -0
  40. package/dist/chunk-FVYGSLAQ.js +179 -0
  41. package/dist/chunk-LWJBHUJQ.js +114 -0
  42. package/dist/chunk-OF2JCXTZ.js +15 -0
  43. package/dist/chunk-TSYLDY6H.js +64 -0
  44. package/dist/chunk-UJFCPQGN.js +1210 -0
  45. package/dist/context.js +8 -64
  46. package/dist/index.cjs +84 -8
  47. package/dist/index.js +84 -8
  48. package/dist/react.d.ts +44 -2
  49. package/dist/react.js +2 -0
  50. package/dist/runtime-entry.d.ts +41 -2
  51. package/dist/runtime-entry.js +1 -1
  52. package/dist/runtime.js +1 -1
  53. package/dist/vue.js +2 -0
  54. package/docs/webpack-mf-/345/257/271/347/205/247/344/270/216/347/274/272/345/217/243.md +1 -1
  55. package/docs//350/277/201/347/247/273/346/214/207/345/215/227.md +1 -1
  56. package/examples/README.en.md +20 -0
  57. package/examples/README.md +20 -0
  58. package/examples/bridge/README.md +36 -0
  59. package/examples/bridge/react-host/README.md +23 -0
  60. package/examples/bridge/react-host/fulgurjs.config.ts +20 -0
  61. package/examples/bridge/react-host/index.html +11 -0
  62. package/examples/bridge/react-host/package-lock.json +2457 -0
  63. package/examples/bridge/react-host/package.json +24 -0
  64. package/examples/bridge/react-host/src/env.d.ts +7 -0
  65. package/examples/bridge/react-host/src/host-session.ts +26 -0
  66. package/examples/bridge/react-host/src/main.tsx +62 -0
  67. package/examples/bridge/react-host/tsconfig.json +13 -0
  68. package/examples/bridge/react-host/vite.config.ts +9 -0
  69. package/examples/bridge/react-remote/README.md +20 -0
  70. package/examples/bridge/react-remote/fulgurjs.config.ts +17 -0
  71. package/examples/bridge/react-remote/index.html +11 -0
  72. package/examples/bridge/react-remote/package-lock.json +2382 -0
  73. package/examples/bridge/react-remote/package.json +24 -0
  74. package/examples/bridge/react-remote/src/bridge.tsx +66 -0
  75. package/examples/bridge/react-remote/src/env.d.ts +7 -0
  76. package/examples/bridge/react-remote/src/main.tsx +7 -0
  77. package/examples/bridge/react-remote/tsconfig.json +13 -0
  78. package/examples/bridge/react-remote/vite.config.ts +9 -0
  79. package/examples/bridge/vue-host/README.md +24 -0
  80. package/examples/bridge/vue-host/fulgurjs.config.ts +22 -0
  81. package/examples/bridge/vue-host/index.html +11 -0
  82. package/examples/bridge/vue-host/package-lock.json +1885 -0
  83. package/examples/bridge/vue-host/package.json +24 -0
  84. package/examples/bridge/vue-host/src/App.vue +70 -0
  85. package/examples/bridge/vue-host/src/env.d.ts +7 -0
  86. package/examples/bridge/vue-host/src/host-session.ts +29 -0
  87. package/examples/bridge/vue-host/src/main.ts +4 -0
  88. package/examples/bridge/vue-host/tsconfig.json +13 -0
  89. package/examples/bridge/vue-host/vite.config.ts +9 -0
  90. package/examples/bridge/vue-remote/README.md +19 -0
  91. package/examples/bridge/vue-remote/fulgurjs.config.ts +16 -0
  92. package/examples/bridge/vue-remote/index.html +11 -0
  93. package/examples/bridge/vue-remote/package-lock.json +1856 -0
  94. package/examples/bridge/vue-remote/package.json +21 -0
  95. package/examples/bridge/vue-remote/src/App.vue +12 -0
  96. package/examples/bridge/vue-remote/src/bridge.ts +57 -0
  97. package/examples/bridge/vue-remote/src/env.d.ts +7 -0
  98. package/examples/bridge/vue-remote/src/main.ts +15 -0
  99. package/examples/bridge/vue-remote/tsconfig.json +13 -0
  100. package/examples/bridge/vue-remote/vite.config.ts +9 -0
  101. package/package.json +43 -2
@@ -0,0 +1,392 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/bridge-host-react.ts
21
+ var bridge_host_react_exports = {};
22
+ __export(bridge_host_react_exports, {
23
+ createReactBridgeAppWithLoader: () => createReactBridgeAppWithLoader
24
+ });
25
+ module.exports = __toCommonJS(bridge_host_react_exports);
26
+ var import_react = require("react");
27
+
28
+ // src/runtime/errors.ts
29
+ var FgError = class extends Error {
30
+ code;
31
+ details;
32
+ constructor(code, message, details, options) {
33
+ super(`[fulgurjs:${code}] ${message}`, options);
34
+ this.name = "FgError";
35
+ this.code = code;
36
+ this.details = details;
37
+ }
38
+ };
39
+
40
+ // src/context.ts
41
+ var ContextErrorCodes = {
42
+ /** context 必需字段缺失(三段式,修法指向宿主桥) */
43
+ CONTEXT_MISSING_KEY: "CC-001",
44
+ /** 运行时单例不可用(独立直开远程页,修法=经宿主联邦加载) */
45
+ CONTEXT_NO_RUNTIME: "CC-002"
46
+ };
47
+ var APP_CONTEXT_STORAGE_KEY = "__FULGURJS_APP_CONFIG__";
48
+ function requireRuntime() {
49
+ const rt = globalThis.__FULGURJS_RUNTIME__;
50
+ if (!rt || typeof rt.loadRemote !== "function") {
51
+ throw new FgError(
52
+ ContextErrorCodes.CONTEXT_NO_RUNTIME,
53
+ "\u73B0\u8C61\uFF1A\u5F53\u524D\u9875\u9762\u627E\u4E0D\u5230 fulgurjs \u8FD0\u884C\u65F6\u5355\u4F8B\uFF08globalThis.__FULGURJS_RUNTIME__ \u672A\u5B9A\u4E49\uFF09\u3002\n \u6839\u56E0: \u5F53\u524D\u9875\u9762\u6CA1\u6709\u7ECF\u5BBF\u4E3B\u7684\u8054\u90A6\u8FD0\u884C\u65F6\u52A0\u8F7D\uFF08\u72EC\u7ACB\u76F4\u5F00\u8FDC\u7A0B\u9875\uFF0C\u6216\u5BBF\u4E3B\u6865\u665A\u4E8E\u672C\u8C03\u7528\u6267\u884C\uFF09\u3002\n \u4FEE\u6CD5: \u2460 \u4ECE\u5BBF\u4E3B\u5E94\u7528\u7684\u8054\u90A6\u8DEF\u7531\u6253\u5F00\u672C\u9875\u9762\uFF08\u5BBF\u4E3B\u6865\u4F1A\u5148\u52A0\u8F7D\u8FD0\u884C\u65F6\u5E76\u63D0\u4F9B context\uFF09\uFF1B\n \u2461 \u82E5\u4F60\u662F\u5BBF\u4E3B\u6865\u4F5C\u8005\uFF1A\u628A provideAppContext \u653E\u5728\u6865\u521D\u59CB\u5316\u5C3E\u90E8\uFF08\u65F6\u5E8F\u5951\u7EA6 bridge \u2192 \u8FDC\u7A0B setup \u2192 \u9875\u9762\u6A21\u5757\uFF09\u3002",
54
+ { runtime: false }
55
+ );
56
+ }
57
+ return rt;
58
+ }
59
+ function provideAppContext(config) {
60
+ requireRuntime();
61
+ const g = globalThis;
62
+ g[APP_CONTEXT_STORAGE_KEY] = { ...g[APP_CONTEXT_STORAGE_KEY] ?? {}, ...config };
63
+ }
64
+ function clearAppContext() {
65
+ const g = globalThis;
66
+ delete g[APP_CONTEXT_STORAGE_KEY];
67
+ try {
68
+ g.__FULGURJS_RUNTIME__?.clearSessionState?.();
69
+ } catch {
70
+ }
71
+ }
72
+
73
+ // src/bridge-errors.ts
74
+ var BridgeErrorCodes = {
75
+ /** 桥接契约非法(./bridge 默认导出缺 mount/unmount 或不是函数) */
76
+ BRIDGE_INVALID_CONTRACT: "MFU-015",
77
+ /** 桥接准备或生命周期失败(details.phase = getContext | mount | unmount) */
78
+ BRIDGE_LIFECYCLE_FAILED: "MFU-016",
79
+ /** 桥接会话参数与 AppContext 不一致(受控 sessionKey 与全局会话矛盾) */
80
+ BRIDGE_SESSION_MISMATCH: "MFU-017"
81
+ };
82
+ function invalidBridgeContractError(spec, mod) {
83
+ const actual = mod === null ? "null" : typeof mod;
84
+ const missing = [];
85
+ if (typeof mod?.mount !== "function") missing.push("mount");
86
+ if (typeof mod?.unmount !== "function") missing.push("unmount");
87
+ return new FgError(
88
+ BridgeErrorCodes.BRIDGE_INVALID_CONTRACT,
89
+ `\u73B0\u8C61\uFF1A\u8FDC\u7A0B\u6A21\u5757 "${spec}" \u7684\u9ED8\u8BA4\u5BFC\u51FA\u4E0D\u662F\u5408\u6CD5\u7684\u6865\u63A5\u5951\u7EA6\uFF08BridgeApp\uFF09\u3002
90
+ \u6839\u56E0: \u5BFC\u51FA\u503C\u4E3A ${actual}` + (missing.length ? `\uFF0C\u7F3A\u5C11\u51FD\u6570\u7C7B\u578B\u7684 ${missing.map((m) => `"${m}"`).join(" / ")} \u5BFC\u51FA\u3002` : "\u3002") + `
91
+ \u4FEE\u6CD5: \u8FDC\u7A0B\u4FA7\u7528 defineBridgeApp(...) \u521B\u5EFA\u5951\u7EA6\u5E76\u4F5C\u4E3A\u6A21\u5757\u9ED8\u8BA4\u5BFC\u51FA\u2014\u2014
92
+ Vue \u5B50\u5E94\u7528: import { defineBridgeApp } from '@fulgurjs/federation/runtime'\uFF1B
93
+ React \u5B50\u5E94\u7528: import { defineBridgeApp } from '@fulgurjs/federation/react'\u3002
94
+ \u5951\u7EA6\u5FC5\u987B\u5305\u542B mount(el, props?) \u4E0E unmount(el) \u4E24\u4E2A\u51FD\u6570\u3002`,
95
+ { spec, missing, actual }
96
+ );
97
+ }
98
+ function bridgeLifecycleError(phase, spec, cause, extra) {
99
+ const raw = cause instanceof Error ? cause.message : String(cause ?? "unknown");
100
+ const fixes = {
101
+ getContext: "\u4FEE\u6CD5: \u2460 getContext \u5FC5\u987B\u662F\u540C\u6B65\u3001\u65E0\u526F\u4F5C\u7528\u7684 getter\uFF08\u4E0D\u5F97\u8FD4\u56DE Promise/thenable\uFF09\uFF1B\n \u2461 \u8FD4\u56DE\u503C\u987B\u662F\u5305\u542B\u672C\u6B21\u4F1A\u8BDD\u5FEB\u7167\u7684\u5BF9\u8C61\uFF08\u53D7\u63A7 sessionKey \u65F6\u987B\u542B\u76F8\u540C sessionKey\uFF09\uFF1B\n \u2462 \u5F02\u6B65\u83B7\u53D6\u7528\u6237\u8D44\u6599\u8BF7\u5728\u5BBF\u4E3B\u5B8C\u6210\u540E\u518D\u8BA9\u6865\u63A5\u7EC4\u4EF6\u8FDB\u5165\u53EF\u6302\u8F7D\u72B6\u6001\u3002",
102
+ mount: "\u4FEE\u6CD5: \u2460 \u67E5\u770B\u6839\u56E0\u4E2D\u5B50\u5E94\u7528 mount \u7684\u539F\u59CB\u9519\u8BEF\uFF08\u5DE5\u5382\u629B\u9519\u6216\u9996\u6B21\u6E32\u67D3\u5931\u8D25\uFF09\uFF1B\n \u2461 \u540C\u4E00\u5BB9\u5668\u672A\u5378\u8F7D\u524D\u91CD\u590D mount \u662F\u5951\u7EA6\u8FDD\u4F8B\u2014\u2014\u5148 unmount \u518D mount\uFF1B\n \u2462 \u4FEE\u590D\u540E\u70B9\u51FB\u300C\u91CD\u8BD5\u52A0\u8F7D\u300D\u5728\u540C\u9875\u91CD\u5EFA\u6302\u8F7D\u3002",
103
+ unmount: "\u4FEE\u6CD5: \u2460 \u6839\u56E0\u6765\u81EA\u5B50\u5E94\u7528 unmount \u5B9E\u73B0\uFF08app.unmount/root.unmount \u629B\u9519\uFF09\uFF1B\n \u2461 \u8BE5\u5BB9\u5668\u6E05\u7406\u72B6\u6001\u4E0D\u786E\u5B9A\u2014\u2014\u4E0D\u8981\u76F4\u63A5\u5728\u540C\u4E00 el \u4E0A\u542F\u52A8\u65B0\u5B9E\u4F8B\uFF1B\n \u2462 \u5237\u65B0\u9875\u9762\u53EF\u5F7B\u5E95\u6E05\u7406\uFF0C\u6B8B\u7559\u8D44\u6E90\u8BF7\u5982\u5B9E\u6392\u67E5\uFF08\u4E8B\u4EF6\u8BA2\u9605/\u5B9A\u65F6\u5668/\u5168\u5C40\u526F\u4F5C\u7528\uFF09\u3002"
104
+ };
105
+ return new FgError(
106
+ BridgeErrorCodes.BRIDGE_LIFECYCLE_FAILED,
107
+ `\u73B0\u8C61\uFF1A\u6865\u63A5\u5E94\u7528 "${spec}" \u7684 ${phase} \u9636\u6BB5\u5931\u8D25\u3002
108
+ \u6839\u56E0: ${raw}
109
+ ` + fixes[phase],
110
+ { phase, spec, cause: String(raw), ...extra },
111
+ { cause }
112
+ );
113
+ }
114
+ function bridgeSessionMismatchError(spec, controlled, actual, extra) {
115
+ const actualText = actual === void 0 ? "undefined\uFF08\u9875\u9762\u5C1A\u65E0 AppContext\uFF09" : typeof actual === "string" ? `"${actual}"` : String(actual);
116
+ return new FgError(
117
+ BridgeErrorCodes.BRIDGE_SESSION_MISMATCH,
118
+ `\u73B0\u8C61\uFF1A\u6865\u63A5\u5E94\u7528 "${spec}" \u7684\u53D7\u63A7 sessionKey\uFF08"${controlled}"\uFF09\u4E0E\u5F53\u524D\u4F1A\u8BDD\u4E0D\u4E00\u81F4\uFF08\u5F53\u524D ${actualText}\uFF09\u3002
119
+ \u6839\u56E0: AppContext \u662F\u9875\u9762\u7EA7\u5355\u4F8B\uFF0C\u540C\u9875\u6240\u6709\u6865\u63A5\u5B9E\u4F8B\u5FC5\u987B\u4F7F\u7528\u540C\u4E00\u767B\u5F55\u4EE3\u6B21\uFF1B
120
+ getContext \u5FEB\u7167\u7684 sessionKey\uFF08\u6216\u73B0\u6709 AppContext \u7684 sessionKey\uFF09\u4E0E\u53D7\u63A7\u503C\u4E0D\u540C\u3002
121
+ \u4FEE\u6CD5: \u2460 \u6362\u8D26\u53F7\u65F6\u5148\u8BA9\u53D7\u63A7 prop \u7F6E null \u5E76\u7B49\u5F85\u5378\u8F7D\uFF0C\u518D clearAppContext() \u6E05\u65E7\u8D26\u53F7\u3001
122
+ \u51C6\u5907\u65B0\u8D26\u53F7\u5B8C\u6574\u5FEB\u7167\u540E\u66F4\u65B0\u53D7\u63A7 prop\uFF1B
123
+ \u2461 \u65E0 getContext \u65F6\uFF0C\u5148\u7531\u5BBF\u4E3B\u6865 provideAppContext({...\u65B0\u4F1A\u8BDD, sessionKey}) \u518D\u6302\u8F7D\uFF1B
124
+ \u2462 \u540C\u9875\u4E0D\u8981\u540C\u65F6\u6302\u8F7D\u4E0D\u540C\u8D26\u53F7\u7684\u6865\u63A5\u5B9E\u4F8B\uFF08\u9875\u9762\u7EA7\u5355\u4F1A\u8BDD\u7EA6\u675F\uFF09\u3002`,
125
+ { spec, controlled, actual: String(actual), ...extra }
126
+ );
127
+ }
128
+ function invalidSessionKeyError(spec, value) {
129
+ return new FgError(
130
+ BridgeErrorCodes.BRIDGE_SESSION_MISMATCH,
131
+ `\u73B0\u8C61\uFF1A\u6865\u63A5\u5E94\u7528 "${spec}" \u6536\u5230\u975E\u6CD5\u7684\u53D7\u63A7 sessionKey\uFF1A${typeof value === "string" ? '\u7A7A\u5B57\u7B26\u4E32 ""' : `${typeof value}\uFF08${String(value)}\uFF09`}\u3002
132
+ \u6839\u56E0: sessionKey \u53EA\u63A5\u53D7 undefined\uFF08\u4E0D\u542F\u7528\u53D7\u63A7\u4F1A\u8BDD\uFF09\u3001null\uFF08\u767B\u51FA\u6001\uFF09\u6216\u975E\u7A7A\u5B57\u7B26\u4E32\uFF08\u767B\u5F55\u4EE3\u6B21 ID\uFF09\u3002
133
+ \u4FEE\u6CD5: \u767B\u51FA\u4F20 null \u800C\u4E0D\u662F\u7A7A\u5B57\u7B26\u4E32\uFF1B\u767B\u5F55\u4EE3\u6B21\u7528\u975E\u7A7A\u5B57\u7B26\u4E32\uFF1B\u4E0D\u8981\u4F20\u6570\u5B57/\u5E03\u5C14\u7B49\u5176\u4ED6\u7C7B\u578B\u3002`,
134
+ { spec, value: String(value) }
135
+ );
136
+ }
137
+
138
+ // src/bridge-core.ts
139
+ function assertBridgeContract(spec, mod) {
140
+ const contract = mod?.default ?? mod;
141
+ if (contract === null || typeof contract !== "object" || typeof contract.mount !== "function" || typeof contract.unmount !== "function") {
142
+ throw invalidBridgeContractError(spec, mod);
143
+ }
144
+ return contract;
145
+ }
146
+ var activeBridgeSessions = /* @__PURE__ */ new Map();
147
+ function acquireBridgeSession(spec, sessionKey) {
148
+ for (const [active] of activeBridgeSessions) {
149
+ if (active !== sessionKey && (activeBridgeSessions.get(active) ?? 0) > 0) {
150
+ throw bridgeSessionMismatchError(spec, sessionKey, active, { reason: "active-instance" });
151
+ }
152
+ }
153
+ activeBridgeSessions.set(sessionKey, (activeBridgeSessions.get(sessionKey) ?? 0) + 1);
154
+ }
155
+ function releaseBridgeSession(sessionKey) {
156
+ const n = activeBridgeSessions.get(sessionKey) ?? 0;
157
+ if (n <= 1) activeBridgeSessions.delete(sessionKey);
158
+ else activeBridgeSessions.set(sessionKey, n - 1);
159
+ }
160
+ function resolveBridgeContext(spec, controlled, getContext) {
161
+ if (getContext) {
162
+ let snapshot;
163
+ try {
164
+ snapshot = getContext();
165
+ } catch (e) {
166
+ throw bridgeLifecycleError("getContext", spec, e);
167
+ }
168
+ if (snapshot === null || typeof snapshot !== "object" || typeof snapshot.then === "function") {
169
+ throw bridgeLifecycleError(
170
+ "getContext",
171
+ spec,
172
+ `getContext \u8FD4\u56DE\u4E86${typeof snapshot.then === "function" ? " Promise/thenable" : "\u975E\u5BF9\u8C61\u503C\uFF08" + typeof snapshot + "\uFF09"}\uFF1B\u5B83\u5FC5\u987B\u662F\u540C\u6B65\u8FD4\u56DE\u5FEB\u7167\u5BF9\u8C61\u7684\u7EAF getter\u3002`
173
+ );
174
+ }
175
+ if (controlled !== void 0 && snapshot.sessionKey !== controlled) {
176
+ throw bridgeSessionMismatchError(spec, controlled, snapshot.sessionKey, { reason: "getter-snapshot" });
177
+ }
178
+ const current = currentSessionKey();
179
+ if (snapshot.sessionKey !== void 0 && snapshot.sessionKey !== current) {
180
+ clearAppContext();
181
+ }
182
+ return { provide: snapshot };
183
+ }
184
+ if (controlled !== void 0) {
185
+ const current = currentSessionKey();
186
+ if (current !== controlled) {
187
+ throw bridgeSessionMismatchError(spec, controlled, current, { reason: "app-context" });
188
+ }
189
+ }
190
+ return {};
191
+ }
192
+ function currentSessionKey() {
193
+ const sk = (globalThis.__FULGURJS_APP_CONFIG__ ?? {}).sessionKey;
194
+ return typeof sk === "string" && sk !== "" ? sk : void 0;
195
+ }
196
+ function assertControlledSessionKey(spec, value) {
197
+ if (value === void 0 || value === null) return;
198
+ if (typeof value === "string" && value !== "") return;
199
+ throw invalidSessionKeyError(spec, value);
200
+ }
201
+ function assertBridgeOptions(source, opts) {
202
+ if (opts.retries !== void 0 && (typeof opts.retries !== "number" || !Number.isInteger(opts.retries) || opts.retries < 0 || opts.retries > 10)) {
203
+ throw new Error(
204
+ `[fulgurjs] ${source} \u7684 retries \u914D\u7F6E\u65E0\u6548\uFF1A\u5F53\u524D\u4E3A ${String(opts.retries)}\uFF0C\u5E94\u4E3A 0 \u5230 10 \u7684\u6574\u6570\u3002\u8BF7\u4FEE\u6B63\u9009\u9879\u3002`
205
+ );
206
+ }
207
+ if (opts.timeout !== void 0 && (typeof opts.timeout !== "number" || !Number.isFinite(opts.timeout) || opts.timeout <= 0)) {
208
+ throw new Error(
209
+ `[fulgurjs] ${source} \u7684 timeout \u914D\u7F6E\u65E0\u6548\uFF1A\u5F53\u524D\u4E3A ${String(opts.timeout)}\uFF0C\u5E94\u4E3A\u5927\u4E8E 0 \u7684\u6709\u9650\u6BEB\u79D2\u6570\u3002\u8BF7\u4FEE\u6B63\u9009\u9879\u3002`
210
+ );
211
+ }
212
+ }
213
+ function withBridgeTimeout(p, ms, spec) {
214
+ return new Promise((resolve, reject) => {
215
+ const timer = setTimeout(() => {
216
+ reject(new Error(
217
+ `[fulgurjs] \u6865\u63A5\u5E94\u7528 "${spec}" \u52A0\u8F7D\u7B49\u5F85\u8D85\u8FC7 ${ms} \u6BEB\u79D2\uFF08\u9002\u914D\u5C42 timeout\uFF09\u3002\u8BE5\u8D85\u65F6\u53EA\u7ED3\u675F\u672C\u6B21\u7B49\u5F85\uFF0C\u4E0D\u53D6\u6D88\u5DF2\u53D1\u51FA\u7684\u5171\u4EAB\u8BF7\u6C42\uFF1B\u53EF\u70B9\u51FB\u300C\u91CD\u8BD5\u52A0\u8F7D\u300D\u5EFA\u7ACB\u65B0\u7684\u5C1D\u8BD5\u3002`
218
+ ));
219
+ }, ms);
220
+ p.then(
221
+ (v) => {
222
+ clearTimeout(timer);
223
+ resolve(v);
224
+ },
225
+ (e) => {
226
+ clearTimeout(timer);
227
+ reject(e);
228
+ }
229
+ );
230
+ });
231
+ }
232
+
233
+ // src/bridge-host-react.ts
234
+ var ERROR_STYLE = {
235
+ padding: "16px",
236
+ border: "1px solid #fde2e2",
237
+ borderRadius: "4px",
238
+ background: "#fef0f0",
239
+ color: "#c45656",
240
+ fontSize: "13px",
241
+ lineHeight: "1.6",
242
+ boxSizing: "border-box"
243
+ };
244
+ var MESSAGE_STYLE = { margin: "0 0 8px", wordBreak: "break-all" };
245
+ var BUTTON_STYLE = {
246
+ padding: "4px 14px",
247
+ marginRight: "8px",
248
+ border: "1px solid #c45656",
249
+ borderRadius: "4px",
250
+ background: "#c45656",
251
+ color: "#fff",
252
+ fontSize: "13px",
253
+ cursor: "pointer"
254
+ };
255
+ var SECONDARY_BUTTON_STYLE = {
256
+ padding: "4px 14px",
257
+ border: "1px solid #c45656",
258
+ borderRadius: "4px",
259
+ background: "#fff",
260
+ color: "#c45656",
261
+ fontSize: "13px",
262
+ cursor: "pointer"
263
+ };
264
+ function DefaultBridgeErrorView({ error, retry }) {
265
+ const err = error;
266
+ const code = err?.code ?? "UNKNOWN";
267
+ const message = err?.message ?? String(error ?? "unknown error");
268
+ return (0, import_react.createElement)("div", { style: ERROR_STYLE, "data-fulgurjs-error": code }, [
269
+ (0, import_react.createElement)("p", { key: "t", style: { margin: "0 0 4px", fontWeight: 600 } }, `\u6865\u63A5\u5E94\u7528\u52A0\u8F7D\u5931\u8D25\uFF08\u9519\u8BEF\u7801 ${code}\uFF09`),
270
+ (0, import_react.createElement)("p", { key: "m", style: MESSAGE_STYLE }, message),
271
+ (0, import_react.createElement)(
272
+ "p",
273
+ { key: "n", style: { margin: "0 0 10px" } },
274
+ "\u300C\u91CD\u8BD5\u52A0\u8F7D\u300D\u5728\u5F53\u524D\u9875\u9762\u91CD\u5EFA\u6302\u8F7D\uFF1B\u82E5\u6D4F\u89C8\u5668\u5DF2\u7F13\u5B58\u5931\u8D25\u7684\u6A21\u5757\uFF0C\u8BF7\u7528\u300C\u5237\u65B0\u9875\u9762\u91CD\u8BD5\u300D\u2014\u2014\u5B83\u4F1A\u6574\u9875\u5237\u65B0\uFF08\u4FDD\u7559\u5F53\u524D\u5730\u5740\uFF09\uFF0C\u672A\u4FDD\u5B58\u7684\u9875\u9762\u72B6\u6001\u4F1A\u4E22\u5931\u3002"
275
+ ),
276
+ (0, import_react.createElement)("button", { key: "r", type: "button", style: BUTTON_STYLE, "data-fulgurjs-retry": "", onClick: retry }, "\u91CD\u8BD5\u52A0\u8F7D"),
277
+ (0, import_react.createElement)("button", {
278
+ key: "rl",
279
+ type: "button",
280
+ style: SECONDARY_BUTTON_STYLE,
281
+ "data-fulgurjs-reload": "",
282
+ onClick: () => window.location.reload()
283
+ }, "\u5237\u65B0\u9875\u9762\u91CD\u8BD5")
284
+ ]);
285
+ }
286
+ function renderBridgeErrorNode(errorOpt, error, retry) {
287
+ if (typeof errorOpt === "function") return errorOpt(error, retry);
288
+ if (errorOpt !== void 0) return errorOpt;
289
+ return (0, import_react.createElement)(DefaultBridgeErrorView, { error, retry });
290
+ }
291
+ function createReactBridgeAppWithLoader(loadRemote) {
292
+ return function createReactBridgeApp(spec, options = {}) {
293
+ assertBridgeOptions(`createReactBridgeApp("${spec}")`, options);
294
+ const displayName = "FulgurjsBridge_" + spec.replace(/[^A-Za-z0-9_-]/g, "_");
295
+ function BridgeHost(props) {
296
+ const [status, setStatus] = (0, import_react.useState)("idle");
297
+ const [error, setError] = (0, import_react.useState)(void 0);
298
+ const [attempt, setAttempt] = (0, import_react.useState)(0);
299
+ const containerRef = (0, import_react.useRef)(null);
300
+ const generationRef = (0, import_react.useRef)(0);
301
+ const contractRef = (0, import_react.useRef)(void 0);
302
+ const acquiredRef = (0, import_react.useRef)(void 0);
303
+ const blockedRef = (0, import_react.useRef)(false);
304
+ const latest = (0, import_react.useRef)(props);
305
+ latest.current = props;
306
+ (0, import_react.useEffect)(() => {
307
+ if (blockedRef.current) return;
308
+ const myGen = ++generationRef.current;
309
+ const el = containerRef.current;
310
+ const release = () => {
311
+ if (acquiredRef.current !== void 0) {
312
+ releaseBridgeSession(acquiredRef.current);
313
+ acquiredRef.current = void 0;
314
+ }
315
+ };
316
+ const run = async () => {
317
+ if (!el) return;
318
+ const sk = latest.current.sessionKey;
319
+ setStatus("pending");
320
+ setError(void 0);
321
+ if (sk === null) {
322
+ setStatus("idle");
323
+ return;
324
+ }
325
+ try {
326
+ assertControlledSessionKey(spec, sk);
327
+ const controlled = typeof sk === "string" ? sk : void 0;
328
+ if (controlled !== void 0 && controlled !== acquiredRef.current) {
329
+ release();
330
+ acquireBridgeSession(spec, controlled);
331
+ acquiredRef.current = controlled;
332
+ }
333
+ const resolution = resolveBridgeContext(spec, controlled, options.getContext);
334
+ if (resolution.provide) provideAppContext(resolution.provide);
335
+ const load = loadRemote(spec, { retries: options.retries });
336
+ const mod = options.timeout !== void 0 ? await withBridgeTimeout(load, options.timeout, spec) : await load;
337
+ if (generationRef.current !== myGen) return;
338
+ const contract = assertBridgeContract(spec, mod);
339
+ contractRef.current = contract;
340
+ await contract.mount(el, { ...latest.current.appProps ?? {} });
341
+ if (generationRef.current !== myGen) return;
342
+ setStatus("ready");
343
+ } catch (e) {
344
+ if (generationRef.current !== myGen) return;
345
+ setError(e);
346
+ setStatus("error");
347
+ }
348
+ };
349
+ void run();
350
+ return () => {
351
+ generationRef.current++;
352
+ release();
353
+ const c = contractRef.current;
354
+ contractRef.current = void 0;
355
+ if (c && el) {
356
+ try {
357
+ c.unmount(el);
358
+ } catch (e) {
359
+ const err = bridgeLifecycleError("unmount", spec, e instanceof Error ? e : String(e));
360
+ console.error("[fulgurjs] \u6865\u63A5\u5E94\u7528\u5378\u8F7D\u5931\u8D25\uFF1A", err);
361
+ blockedRef.current = true;
362
+ setError(err);
363
+ setStatus("error");
364
+ }
365
+ }
366
+ };
367
+ }, [props.sessionKey, attempt]);
368
+ const retry = () => setAttempt((a) => a + 1);
369
+ const children = [];
370
+ if (status === "pending" && options.fallback !== void 0) {
371
+ children.push((0, import_react.createElement)(import_react.Fragment, { key: "loading" }, options.fallback));
372
+ }
373
+ if (status === "error") {
374
+ children.push((0, import_react.createElement)(import_react.Fragment, { key: "error" }, renderBridgeErrorNode(options.error, error, retry)));
375
+ }
376
+ children.push((0, import_react.createElement)("div", {
377
+ key: "bridge-root",
378
+ ref: containerRef,
379
+ "data-fulgurjs-bridge-root": spec,
380
+ "data-fulgurjs-bridge-status": status
381
+ }));
382
+ return (0, import_react.createElement)(import_react.Fragment, null, children);
383
+ }
384
+ ;
385
+ BridgeHost.displayName = displayName;
386
+ return BridgeHost;
387
+ };
388
+ }
389
+ // Annotate the CommonJS export names for ESM import in node:
390
+ 0 && (module.exports = {
391
+ createReactBridgeAppWithLoader
392
+ });
@@ -0,0 +1,45 @@
1
+ import { ReactNode, ComponentType } from 'react';
2
+ import { AppContext } from './context.cjs';
3
+
4
+ /**
5
+ * React 宿主桥接工厂(/bridge、/bridge/react 导出 createReactBridgeApp;任务书 §3.4)。
6
+ *
7
+ * 定位:接收注入的 loadRemote(不静态引用运行时内核,dist 壳绑定),返回
8
+ * `ComponentType<{ appProps: P; sessionKey?: string | null }>`,负责:
9
+ * - DOM 所有权(§4.5):只创建并保持稳定的空挂载 el(fragment 的固定子节点);
10
+ * pending/error 占位是它的兄弟节点,宿主重渲染不 patch 子应用 root 内部;
11
+ * - 会话代次(§4.3):受控 sessionKey 驱动 挂载/换会话/登出;同会话重渲染不重挂;
12
+ * - StrictMode 安全(§4.5):双 effect 走 cleanup(作废+卸载)→setup(新代次) 顺序,
13
+ * 顺序 unmount/mount 不产生双实例或残留;
14
+ * - unmount 抛错(BN09):报告 MFU-016(phase: unmount)并封锁该容器的新挂载。
15
+ *
16
+ * appProps 是挂载时浅拷贝快照(顶层替换不追踪,重挂由 key 重建);sessionKey
17
+ * 是桥接控制参数,不混入业务 props。
18
+ */
19
+
20
+ type LoadRemoteFn = (spec: string, opts?: {
21
+ retries?: number;
22
+ }) => Promise<any>;
23
+ /** 渲染函数形态的错误占位:(error, retry) => ReactNode */
24
+ type BridgeErrorFallback = (error: unknown, retry: () => void) => ReactNode;
25
+ interface ReactBridgeAppOptions {
26
+ /** 加载 pending 占位(默认 null) */
27
+ fallback?: ReactNode;
28
+ /** 加载/挂载失败占位;默认内置中文诊断 + 「重试加载 / 刷新页面重试」 */
29
+ error?: ReactNode | BridgeErrorFallback;
30
+ /** 透传现行 loadRemote 的重试选项(0-10 整数),不另叠自动重试 */
31
+ retries?: number;
32
+ /** 本次桥接加载等待上限 ms;不取消已发出的共享请求,迟到结果一律丢弃 */
33
+ timeout?: number;
34
+ /** 无副作用的同步 getter:首次、重试及换会话的实际加载前返回本次所需上下文快照 */
35
+ getContext?: () => Partial<AppContext> & Record<string, unknown>;
36
+ }
37
+ /**
38
+ * 构建 React 宿主桥接工厂(dist 壳与 dev 门面绑定各自运行时的 loadRemote 后导出)。
39
+ */
40
+ declare function createReactBridgeAppWithLoader(loadRemote: LoadRemoteFn): <P = Record<string, unknown>>(spec: string, options?: ReactBridgeAppOptions) => ComponentType<{
41
+ appProps?: P;
42
+ sessionKey?: string | null;
43
+ }>;
44
+
45
+ export { type BridgeErrorFallback, type ReactBridgeAppOptions, createReactBridgeAppWithLoader };
@@ -0,0 +1,45 @@
1
+ import { ReactNode, ComponentType } from 'react';
2
+ import { AppContext } from './context.js';
3
+
4
+ /**
5
+ * React 宿主桥接工厂(/bridge、/bridge/react 导出 createReactBridgeApp;任务书 §3.4)。
6
+ *
7
+ * 定位:接收注入的 loadRemote(不静态引用运行时内核,dist 壳绑定),返回
8
+ * `ComponentType<{ appProps: P; sessionKey?: string | null }>`,负责:
9
+ * - DOM 所有权(§4.5):只创建并保持稳定的空挂载 el(fragment 的固定子节点);
10
+ * pending/error 占位是它的兄弟节点,宿主重渲染不 patch 子应用 root 内部;
11
+ * - 会话代次(§4.3):受控 sessionKey 驱动 挂载/换会话/登出;同会话重渲染不重挂;
12
+ * - StrictMode 安全(§4.5):双 effect 走 cleanup(作废+卸载)→setup(新代次) 顺序,
13
+ * 顺序 unmount/mount 不产生双实例或残留;
14
+ * - unmount 抛错(BN09):报告 MFU-016(phase: unmount)并封锁该容器的新挂载。
15
+ *
16
+ * appProps 是挂载时浅拷贝快照(顶层替换不追踪,重挂由 key 重建);sessionKey
17
+ * 是桥接控制参数,不混入业务 props。
18
+ */
19
+
20
+ type LoadRemoteFn = (spec: string, opts?: {
21
+ retries?: number;
22
+ }) => Promise<any>;
23
+ /** 渲染函数形态的错误占位:(error, retry) => ReactNode */
24
+ type BridgeErrorFallback = (error: unknown, retry: () => void) => ReactNode;
25
+ interface ReactBridgeAppOptions {
26
+ /** 加载 pending 占位(默认 null) */
27
+ fallback?: ReactNode;
28
+ /** 加载/挂载失败占位;默认内置中文诊断 + 「重试加载 / 刷新页面重试」 */
29
+ error?: ReactNode | BridgeErrorFallback;
30
+ /** 透传现行 loadRemote 的重试选项(0-10 整数),不另叠自动重试 */
31
+ retries?: number;
32
+ /** 本次桥接加载等待上限 ms;不取消已发出的共享请求,迟到结果一律丢弃 */
33
+ timeout?: number;
34
+ /** 无副作用的同步 getter:首次、重试及换会话的实际加载前返回本次所需上下文快照 */
35
+ getContext?: () => Partial<AppContext> & Record<string, unknown>;
36
+ }
37
+ /**
38
+ * 构建 React 宿主桥接工厂(dist 壳与 dev 门面绑定各自运行时的 loadRemote 后导出)。
39
+ */
40
+ declare function createReactBridgeAppWithLoader(loadRemote: LoadRemoteFn): <P = Record<string, unknown>>(spec: string, options?: ReactBridgeAppOptions) => ComponentType<{
41
+ appProps?: P;
42
+ sessionKey?: string | null;
43
+ }>;
44
+
45
+ export { type BridgeErrorFallback, type ReactBridgeAppOptions, createReactBridgeAppWithLoader };
@@ -0,0 +1,183 @@
1
+ import {
2
+ acquireBridgeSession,
3
+ assertBridgeContract,
4
+ assertBridgeOptions,
5
+ assertControlledSessionKey,
6
+ releaseBridgeSession,
7
+ resolveBridgeContext,
8
+ withBridgeTimeout
9
+ } from "./chunk-LWJBHUJQ.js";
10
+ import {
11
+ bridgeLifecycleError
12
+ } from "./chunk-E55P4TIY.js";
13
+ import {
14
+ provideAppContext
15
+ } from "./chunk-TSYLDY6H.js";
16
+ import "./chunk-OF2JCXTZ.js";
17
+
18
+ // src/bridge-host-react.ts
19
+ import {
20
+ createElement,
21
+ Fragment,
22
+ useEffect,
23
+ useRef,
24
+ useState
25
+ } from "react";
26
+ var ERROR_STYLE = {
27
+ padding: "16px",
28
+ border: "1px solid #fde2e2",
29
+ borderRadius: "4px",
30
+ background: "#fef0f0",
31
+ color: "#c45656",
32
+ fontSize: "13px",
33
+ lineHeight: "1.6",
34
+ boxSizing: "border-box"
35
+ };
36
+ var MESSAGE_STYLE = { margin: "0 0 8px", wordBreak: "break-all" };
37
+ var BUTTON_STYLE = {
38
+ padding: "4px 14px",
39
+ marginRight: "8px",
40
+ border: "1px solid #c45656",
41
+ borderRadius: "4px",
42
+ background: "#c45656",
43
+ color: "#fff",
44
+ fontSize: "13px",
45
+ cursor: "pointer"
46
+ };
47
+ var SECONDARY_BUTTON_STYLE = {
48
+ padding: "4px 14px",
49
+ border: "1px solid #c45656",
50
+ borderRadius: "4px",
51
+ background: "#fff",
52
+ color: "#c45656",
53
+ fontSize: "13px",
54
+ cursor: "pointer"
55
+ };
56
+ function DefaultBridgeErrorView({ error, retry }) {
57
+ const err = error;
58
+ const code = err?.code ?? "UNKNOWN";
59
+ const message = err?.message ?? String(error ?? "unknown error");
60
+ return createElement("div", { style: ERROR_STYLE, "data-fulgurjs-error": code }, [
61
+ createElement("p", { key: "t", style: { margin: "0 0 4px", fontWeight: 600 } }, `\u6865\u63A5\u5E94\u7528\u52A0\u8F7D\u5931\u8D25\uFF08\u9519\u8BEF\u7801 ${code}\uFF09`),
62
+ createElement("p", { key: "m", style: MESSAGE_STYLE }, message),
63
+ createElement(
64
+ "p",
65
+ { key: "n", style: { margin: "0 0 10px" } },
66
+ "\u300C\u91CD\u8BD5\u52A0\u8F7D\u300D\u5728\u5F53\u524D\u9875\u9762\u91CD\u5EFA\u6302\u8F7D\uFF1B\u82E5\u6D4F\u89C8\u5668\u5DF2\u7F13\u5B58\u5931\u8D25\u7684\u6A21\u5757\uFF0C\u8BF7\u7528\u300C\u5237\u65B0\u9875\u9762\u91CD\u8BD5\u300D\u2014\u2014\u5B83\u4F1A\u6574\u9875\u5237\u65B0\uFF08\u4FDD\u7559\u5F53\u524D\u5730\u5740\uFF09\uFF0C\u672A\u4FDD\u5B58\u7684\u9875\u9762\u72B6\u6001\u4F1A\u4E22\u5931\u3002"
67
+ ),
68
+ createElement("button", { key: "r", type: "button", style: BUTTON_STYLE, "data-fulgurjs-retry": "", onClick: retry }, "\u91CD\u8BD5\u52A0\u8F7D"),
69
+ createElement("button", {
70
+ key: "rl",
71
+ type: "button",
72
+ style: SECONDARY_BUTTON_STYLE,
73
+ "data-fulgurjs-reload": "",
74
+ onClick: () => window.location.reload()
75
+ }, "\u5237\u65B0\u9875\u9762\u91CD\u8BD5")
76
+ ]);
77
+ }
78
+ function renderBridgeErrorNode(errorOpt, error, retry) {
79
+ if (typeof errorOpt === "function") return errorOpt(error, retry);
80
+ if (errorOpt !== void 0) return errorOpt;
81
+ return createElement(DefaultBridgeErrorView, { error, retry });
82
+ }
83
+ function createReactBridgeAppWithLoader(loadRemote) {
84
+ return function createReactBridgeApp(spec, options = {}) {
85
+ assertBridgeOptions(`createReactBridgeApp("${spec}")`, options);
86
+ const displayName = "FulgurjsBridge_" + spec.replace(/[^A-Za-z0-9_-]/g, "_");
87
+ function BridgeHost(props) {
88
+ const [status, setStatus] = useState("idle");
89
+ const [error, setError] = useState(void 0);
90
+ const [attempt, setAttempt] = useState(0);
91
+ const containerRef = useRef(null);
92
+ const generationRef = useRef(0);
93
+ const contractRef = useRef(void 0);
94
+ const acquiredRef = useRef(void 0);
95
+ const blockedRef = useRef(false);
96
+ const latest = useRef(props);
97
+ latest.current = props;
98
+ useEffect(() => {
99
+ if (blockedRef.current) return;
100
+ const myGen = ++generationRef.current;
101
+ const el = containerRef.current;
102
+ const release = () => {
103
+ if (acquiredRef.current !== void 0) {
104
+ releaseBridgeSession(acquiredRef.current);
105
+ acquiredRef.current = void 0;
106
+ }
107
+ };
108
+ const run = async () => {
109
+ if (!el) return;
110
+ const sk = latest.current.sessionKey;
111
+ setStatus("pending");
112
+ setError(void 0);
113
+ if (sk === null) {
114
+ setStatus("idle");
115
+ return;
116
+ }
117
+ try {
118
+ assertControlledSessionKey(spec, sk);
119
+ const controlled = typeof sk === "string" ? sk : void 0;
120
+ if (controlled !== void 0 && controlled !== acquiredRef.current) {
121
+ release();
122
+ acquireBridgeSession(spec, controlled);
123
+ acquiredRef.current = controlled;
124
+ }
125
+ const resolution = resolveBridgeContext(spec, controlled, options.getContext);
126
+ if (resolution.provide) provideAppContext(resolution.provide);
127
+ const load = loadRemote(spec, { retries: options.retries });
128
+ const mod = options.timeout !== void 0 ? await withBridgeTimeout(load, options.timeout, spec) : await load;
129
+ if (generationRef.current !== myGen) return;
130
+ const contract = assertBridgeContract(spec, mod);
131
+ contractRef.current = contract;
132
+ await contract.mount(el, { ...latest.current.appProps ?? {} });
133
+ if (generationRef.current !== myGen) return;
134
+ setStatus("ready");
135
+ } catch (e) {
136
+ if (generationRef.current !== myGen) return;
137
+ setError(e);
138
+ setStatus("error");
139
+ }
140
+ };
141
+ void run();
142
+ return () => {
143
+ generationRef.current++;
144
+ release();
145
+ const c = contractRef.current;
146
+ contractRef.current = void 0;
147
+ if (c && el) {
148
+ try {
149
+ c.unmount(el);
150
+ } catch (e) {
151
+ const err = bridgeLifecycleError("unmount", spec, e instanceof Error ? e : String(e));
152
+ console.error("[fulgurjs] \u6865\u63A5\u5E94\u7528\u5378\u8F7D\u5931\u8D25\uFF1A", err);
153
+ blockedRef.current = true;
154
+ setError(err);
155
+ setStatus("error");
156
+ }
157
+ }
158
+ };
159
+ }, [props.sessionKey, attempt]);
160
+ const retry = () => setAttempt((a) => a + 1);
161
+ const children = [];
162
+ if (status === "pending" && options.fallback !== void 0) {
163
+ children.push(createElement(Fragment, { key: "loading" }, options.fallback));
164
+ }
165
+ if (status === "error") {
166
+ children.push(createElement(Fragment, { key: "error" }, renderBridgeErrorNode(options.error, error, retry)));
167
+ }
168
+ children.push(createElement("div", {
169
+ key: "bridge-root",
170
+ ref: containerRef,
171
+ "data-fulgurjs-bridge-root": spec,
172
+ "data-fulgurjs-bridge-status": status
173
+ }));
174
+ return createElement(Fragment, null, children);
175
+ }
176
+ ;
177
+ BridgeHost.displayName = displayName;
178
+ return BridgeHost;
179
+ };
180
+ }
181
+ export {
182
+ createReactBridgeAppWithLoader
183
+ };