@fias/arche-sdk 2.3.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bridge.d.ts +76 -1
- package/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.js +219 -6
- package/dist/bridge.js.map +1 -1
- package/dist/bridge.test.js +155 -6
- package/dist/bridge.test.js.map +1 -1
- package/dist/coverage-fills.test.js +26 -32
- package/dist/coverage-fills.test.js.map +1 -1
- package/dist/entity-ops.d.ts +55 -0
- package/dist/entity-ops.d.ts.map +1 -0
- package/dist/entity-ops.js +48 -0
- package/dist/entity-ops.js.map +1 -0
- package/dist/fias.d.ts +11 -1
- package/dist/fias.d.ts.map +1 -1
- package/dist/fias.js +39 -12
- package/dist/fias.js.map +1 -1
- package/dist/generated/permissions.d.ts +7 -1
- package/dist/generated/permissions.d.ts.map +1 -1
- package/dist/generated/permissions.js +35 -2
- package/dist/generated/permissions.js.map +1 -1
- package/dist/generated/surfaces.d.ts +424 -0
- package/dist/generated/surfaces.d.ts.map +1 -1
- package/dist/generated/surfaces.js +97 -1
- package/dist/generated/surfaces.js.map +1 -1
- package/dist/hooks.d.ts +228 -13
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +527 -104
- package/dist/hooks.js.map +1 -1
- package/dist/hooks.test.js +314 -247
- package/dist/hooks.test.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +982 -115
- package/dist/protocol.d.ts +7 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +7 -0
- package/dist/protocol.js.map +1 -1
- package/dist/provider.d.ts +50 -1
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +187 -2
- package/dist/provider.js.map +1 -1
- package/dist/provider.render.test.d.ts +17 -0
- package/dist/provider.render.test.d.ts.map +1 -0
- package/dist/provider.render.test.js +191 -0
- package/dist/provider.render.test.js.map +1 -0
- package/dist/provider.test.js +64 -8
- package/dist/provider.test.js.map +1 -1
- package/dist/types.d.ts +373 -27
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -1
- package/templates/default/AGENTS.md +321 -34
- package/templates/default/CLAUDE.md +321 -34
package/dist/protocol.d.ts
CHANGED
|
@@ -31,6 +31,13 @@
|
|
|
31
31
|
*
|
|
32
32
|
* CHANGELOG
|
|
33
33
|
* v1 (2026-05) — initial published version.
|
|
34
|
+
* v1 (2026-06) — additive: preview-state preservation
|
|
35
|
+
* (`preview_state_capture` / `preview_state_restore` / `preview_state`
|
|
36
|
+
* messages + the `supportsPreviewState` flag on `ready`). Capability-gated,
|
|
37
|
+
* so it does NOT bump the version. Exposed to plugins via
|
|
38
|
+
* `useFiasPreviewState`. Inert outside the builder preview. To reach
|
|
39
|
+
* server-built plugins it needs an SDK minor publish so the CDN bundle
|
|
40
|
+
* (SDK_BUILD_VERSION) carries it.
|
|
34
41
|
*/
|
|
35
42
|
export declare const SDK_BRIDGE_PROTOCOL_VERSION = 1;
|
|
36
43
|
export declare const SDK_REQUIRES_HOST_PROTOCOL_VERSION = 1;
|
package/dist/protocol.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAC7C,eAAO,MAAM,kCAAkC,IAAI,CAAC"}
|
package/dist/protocol.js
CHANGED
|
@@ -32,6 +32,13 @@
|
|
|
32
32
|
*
|
|
33
33
|
* CHANGELOG
|
|
34
34
|
* v1 (2026-05) — initial published version.
|
|
35
|
+
* v1 (2026-06) — additive: preview-state preservation
|
|
36
|
+
* (`preview_state_capture` / `preview_state_restore` / `preview_state`
|
|
37
|
+
* messages + the `supportsPreviewState` flag on `ready`). Capability-gated,
|
|
38
|
+
* so it does NOT bump the version. Exposed to plugins via
|
|
39
|
+
* `useFiasPreviewState`. Inert outside the builder preview. To reach
|
|
40
|
+
* server-built plugins it needs an SDK minor publish so the CDN bundle
|
|
41
|
+
* (SDK_BUILD_VERSION) carries it.
|
|
35
42
|
*/
|
|
36
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
44
|
exports.SDK_REQUIRES_HOST_PROTOCOL_VERSION = exports.SDK_BRIDGE_PROTOCOL_VERSION = void 0;
|
package/dist/protocol.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;;;AAEU,QAAA,2BAA2B,GAAG,CAAC,CAAC;AAChC,QAAA,kCAAkC,GAAG,CAAC,CAAC"}
|
package/dist/provider.d.ts
CHANGED
|
@@ -1,7 +1,56 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
2
|
interface FiasProviderProps {
|
|
3
3
|
children: React.ReactNode;
|
|
4
4
|
}
|
|
5
|
+
interface PluginErrorBoundaryProps {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
interface PluginErrorBoundaryState {
|
|
9
|
+
error: Error | null;
|
|
10
|
+
/**
|
|
11
|
+
* Bumped on every reset. Used as the `key` of the children wrapper so the
|
|
12
|
+
* crashed subtree is remounted from scratch (fresh component state) rather
|
|
13
|
+
* than re-rendered with whatever broken state caused the crash.
|
|
14
|
+
*/
|
|
15
|
+
resetCount: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Minimal, theme-independent error screen rendered when a plugin throws
|
|
19
|
+
* during render. Deliberately uses inline styles and no theme tokens — the
|
|
20
|
+
* theme itself may be the thing that failed to load, so the fallback must
|
|
21
|
+
* not depend on it.
|
|
22
|
+
*
|
|
23
|
+
* The most common trigger is a denied capability: e.g. a plugin that calls
|
|
24
|
+
* `useFiasUser()` without declaring `user:profile:read` in fias-plugin.json.
|
|
25
|
+
* Before this existed, that surfaced as an indistinguishable infinite
|
|
26
|
+
* "loading" spinner; now it renders the actual error.
|
|
27
|
+
*
|
|
28
|
+
* `onReset` (when provided) renders a "Try again" button so a transient
|
|
29
|
+
* crash (e.g. a failed bridge request that would succeed on retry) doesn't
|
|
30
|
+
* strand the user on a dead screen with no recourse but a full reload.
|
|
31
|
+
*/
|
|
32
|
+
export declare function FiasErrorScreen({ error, onReset, }: {
|
|
33
|
+
error: Error;
|
|
34
|
+
onReset?: () => void;
|
|
35
|
+
}): React.ReactElement;
|
|
36
|
+
/**
|
|
37
|
+
* Catches errors thrown anywhere in the plugin's render tree and shows a
|
|
38
|
+
* readable message instead of unmounting to a blank iframe. Installed by
|
|
39
|
+
* `FiasProvider` so that hooks which `throw` on a failed/denied bridge
|
|
40
|
+
* request (e.g. `useFiasUser`) surface the failure to the user and the host
|
|
41
|
+
* log stream rather than hanging.
|
|
42
|
+
*
|
|
43
|
+
* The error screen's "Try again" button clears the error AND remounts the
|
|
44
|
+
* children subtree (via the wrapper key), so a crash caused by transient
|
|
45
|
+
* state doesn't permanently black-screen the plugin.
|
|
46
|
+
*/
|
|
47
|
+
export declare class PluginErrorBoundary extends Component<PluginErrorBoundaryProps, PluginErrorBoundaryState> {
|
|
48
|
+
state: PluginErrorBoundaryState;
|
|
49
|
+
static getDerivedStateFromError(error: Error): Pick<PluginErrorBoundaryState, 'error'>;
|
|
50
|
+
componentDidCatch(error: Error, info: React.ErrorInfo): void;
|
|
51
|
+
handleReset: () => void;
|
|
52
|
+
render(): React.ReactNode;
|
|
53
|
+
}
|
|
5
54
|
/**
|
|
6
55
|
* Root wrapper component for FIAS plugins.
|
|
7
56
|
* Must wrap the entire plugin component tree.
|
package/dist/provider.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAgC,MAAM,OAAO,CAAC;AAIvE,UAAU,iBAAiB;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,UAAU,wBAAwB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,UAAU,wBAAwB;IAChC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,OAAO,GACR,EAAE;IACD,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,GAAG,KAAK,CAAC,YAAY,CAyDrB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,mBAAoB,SAAQ,SAAS,CAChD,wBAAwB,EACxB,wBAAwB,CACzB;IACC,KAAK,EAAE,wBAAwB,CAAkC;IAEjE,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC,wBAAwB,EAAE,OAAO,CAAC;IAItF,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI;IAM5D,WAAW,QAAO,IAAI,CAEpB;IAEF,MAAM,IAAI,KAAK,CAAC,SAAS;CAS1B;AAoED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE,iBAAiB,kDA2D3D"}
|
package/dist/provider.js
CHANGED
|
@@ -1,10 +1,176 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PluginErrorBoundary = void 0;
|
|
37
|
+
exports.FiasErrorScreen = FiasErrorScreen;
|
|
3
38
|
exports.FiasProvider = FiasProvider;
|
|
4
39
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const react_1 = require("react");
|
|
40
|
+
const react_1 = __importStar(require("react"));
|
|
6
41
|
const context_1 = require("./context");
|
|
7
42
|
const bridge_1 = require("./bridge");
|
|
43
|
+
/**
|
|
44
|
+
* Minimal, theme-independent error screen rendered when a plugin throws
|
|
45
|
+
* during render. Deliberately uses inline styles and no theme tokens — the
|
|
46
|
+
* theme itself may be the thing that failed to load, so the fallback must
|
|
47
|
+
* not depend on it.
|
|
48
|
+
*
|
|
49
|
+
* The most common trigger is a denied capability: e.g. a plugin that calls
|
|
50
|
+
* `useFiasUser()` without declaring `user:profile:read` in fias-plugin.json.
|
|
51
|
+
* Before this existed, that surfaced as an indistinguishable infinite
|
|
52
|
+
* "loading" spinner; now it renders the actual error.
|
|
53
|
+
*
|
|
54
|
+
* `onReset` (when provided) renders a "Try again" button so a transient
|
|
55
|
+
* crash (e.g. a failed bridge request that would succeed on retry) doesn't
|
|
56
|
+
* strand the user on a dead screen with no recourse but a full reload.
|
|
57
|
+
*/
|
|
58
|
+
function FiasErrorScreen({ error, onReset, }) {
|
|
59
|
+
const code = error.code;
|
|
60
|
+
return ((0, jsx_runtime_1.jsxs)("div", { role: "alert", style: {
|
|
61
|
+
boxSizing: 'border-box',
|
|
62
|
+
minHeight: '100vh',
|
|
63
|
+
display: 'flex',
|
|
64
|
+
flexDirection: 'column',
|
|
65
|
+
alignItems: 'center',
|
|
66
|
+
justifyContent: 'center',
|
|
67
|
+
gap: '12px',
|
|
68
|
+
padding: '24px',
|
|
69
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
70
|
+
color: '#1a1a1a',
|
|
71
|
+
background: '#fff',
|
|
72
|
+
textAlign: 'center',
|
|
73
|
+
}, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: '15px', fontWeight: 600 }, children: "This plugin hit an error" }), (0, jsx_runtime_1.jsx)("div", { style: {
|
|
74
|
+
fontSize: '13px',
|
|
75
|
+
lineHeight: 1.5,
|
|
76
|
+
maxWidth: '520px',
|
|
77
|
+
color: '#b00020',
|
|
78
|
+
wordBreak: 'break-word',
|
|
79
|
+
}, children: error.message }), typeof code === 'string' && code.length > 0 ? ((0, jsx_runtime_1.jsxs)("div", { style: { fontSize: '11px', color: '#737373' }, children: ["Code: ", code] })) : null, onReset ? ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: onReset, style: {
|
|
80
|
+
marginTop: '4px',
|
|
81
|
+
padding: '8px 20px',
|
|
82
|
+
fontSize: '13px',
|
|
83
|
+
fontWeight: 600,
|
|
84
|
+
fontFamily: 'inherit',
|
|
85
|
+
color: '#fff',
|
|
86
|
+
background: '#1a1a1a',
|
|
87
|
+
border: 'none',
|
|
88
|
+
borderRadius: '6px',
|
|
89
|
+
cursor: 'pointer',
|
|
90
|
+
}, children: "Try again" })) : null] }));
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Catches errors thrown anywhere in the plugin's render tree and shows a
|
|
94
|
+
* readable message instead of unmounting to a blank iframe. Installed by
|
|
95
|
+
* `FiasProvider` so that hooks which `throw` on a failed/denied bridge
|
|
96
|
+
* request (e.g. `useFiasUser`) surface the failure to the user and the host
|
|
97
|
+
* log stream rather than hanging.
|
|
98
|
+
*
|
|
99
|
+
* The error screen's "Try again" button clears the error AND remounts the
|
|
100
|
+
* children subtree (via the wrapper key), so a crash caused by transient
|
|
101
|
+
* state doesn't permanently black-screen the plugin.
|
|
102
|
+
*/
|
|
103
|
+
class PluginErrorBoundary extends react_1.Component {
|
|
104
|
+
constructor() {
|
|
105
|
+
super(...arguments);
|
|
106
|
+
this.state = { error: null, resetCount: 0 };
|
|
107
|
+
this.handleReset = () => {
|
|
108
|
+
this.setState((prev) => ({ error: null, resetCount: prev.resetCount + 1 }));
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
static getDerivedStateFromError(error) {
|
|
112
|
+
return { error };
|
|
113
|
+
}
|
|
114
|
+
componentDidCatch(error, info) {
|
|
115
|
+
// Surface to devtools and (via the iframe's console proxy) the host log
|
|
116
|
+
// stream, instead of failing silently.
|
|
117
|
+
console.error('[fias-sdk] Uncaught error in plugin render:', error, info.componentStack);
|
|
118
|
+
}
|
|
119
|
+
render() {
|
|
120
|
+
if (this.state.error) {
|
|
121
|
+
return (0, jsx_runtime_1.jsx)(FiasErrorScreen, { error: this.state.error, onReset: this.handleReset });
|
|
122
|
+
}
|
|
123
|
+
// The key forces a clean remount of the crashed subtree after a reset —
|
|
124
|
+
// without it, React would try to reuse the component instances whose
|
|
125
|
+
// state just caused the crash.
|
|
126
|
+
return (0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: this.props.children }, this.state.resetCount);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.PluginErrorBoundary = PluginErrorBoundary;
|
|
130
|
+
/**
|
|
131
|
+
* Non-fatal notice for unhandled promise rejections (e.g. a floating
|
|
132
|
+
* `invoke()` whose rejection nothing catches). Rendered ABOVE the plugin —
|
|
133
|
+
* the plugin keeps running; the full-screen fallback stays reserved for
|
|
134
|
+
* render crashes. Inline styles only (same rationale as FiasErrorScreen).
|
|
135
|
+
*/
|
|
136
|
+
function UnhandledRejectionBanner({ message, onDismiss, }) {
|
|
137
|
+
return ((0, jsx_runtime_1.jsxs)("div", { role: "alert", style: {
|
|
138
|
+
boxSizing: 'border-box',
|
|
139
|
+
display: 'flex',
|
|
140
|
+
alignItems: 'center',
|
|
141
|
+
gap: '10px',
|
|
142
|
+
padding: '8px 12px',
|
|
143
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
144
|
+
fontSize: '12px',
|
|
145
|
+
lineHeight: 1.4,
|
|
146
|
+
color: '#7a2900',
|
|
147
|
+
background: '#fff4ec',
|
|
148
|
+
borderBottom: '1px solid #f0c9ae',
|
|
149
|
+
}, children: [(0, jsx_runtime_1.jsxs)("span", { style: { flex: 1, wordBreak: 'break-word' }, children: ["Something went wrong in this app: ", message] }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: onDismiss, "aria-label": "Dismiss", style: {
|
|
150
|
+
flexShrink: 0,
|
|
151
|
+
padding: '2px 8px',
|
|
152
|
+
fontSize: '12px',
|
|
153
|
+
fontFamily: 'inherit',
|
|
154
|
+
color: '#7a2900',
|
|
155
|
+
background: 'transparent',
|
|
156
|
+
border: '1px solid #f0c9ae',
|
|
157
|
+
borderRadius: '4px',
|
|
158
|
+
cursor: 'pointer',
|
|
159
|
+
}, children: "Dismiss" })] }));
|
|
160
|
+
}
|
|
161
|
+
/** Best-effort readable message from an arbitrary rejection reason. */
|
|
162
|
+
function describeRejectionReason(reason) {
|
|
163
|
+
if (reason instanceof Error)
|
|
164
|
+
return reason.message || reason.name;
|
|
165
|
+
if (typeof reason === 'string')
|
|
166
|
+
return reason;
|
|
167
|
+
try {
|
|
168
|
+
return JSON.stringify(reason) ?? String(reason);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return String(reason);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
8
174
|
/**
|
|
9
175
|
* Root wrapper component for FIAS plugins.
|
|
10
176
|
* Must wrap the entire plugin component tree.
|
|
@@ -25,6 +191,7 @@ const bridge_1 = require("./bridge");
|
|
|
25
191
|
*/
|
|
26
192
|
function FiasProvider({ children }) {
|
|
27
193
|
const [ready, setReady] = (0, react_1.useState)(false);
|
|
194
|
+
const [rejectionMessage, setRejectionMessage] = (0, react_1.useState)(null);
|
|
28
195
|
const bridge = (0, react_1.useMemo)(() => (0, bridge_1.getBridge)(), []);
|
|
29
196
|
(0, react_1.useEffect)(() => {
|
|
30
197
|
let mounted = true;
|
|
@@ -43,9 +210,27 @@ function FiasProvider({ children }) {
|
|
|
43
210
|
// mount's waitForInit() to hang forever.
|
|
44
211
|
};
|
|
45
212
|
}, [bridge]);
|
|
213
|
+
// Catch unhandled promise rejections (async errors the error boundary can
|
|
214
|
+
// never see — boundaries only catch RENDER-phase throws). The SDK runs
|
|
215
|
+
// inside the plugin iframe, so this listener is iframe-scoped by
|
|
216
|
+
// construction. Non-fatal: the plugin keeps rendering; we log for the host
|
|
217
|
+
// stream and show a dismissible banner instead of a silent swallow (or,
|
|
218
|
+
// worse, the crash-on-undefined-result the rejection often cascades into).
|
|
219
|
+
(0, react_1.useEffect)(() => {
|
|
220
|
+
if (typeof window === 'undefined')
|
|
221
|
+
return;
|
|
222
|
+
const handler = (event) => {
|
|
223
|
+
console.error('[fias-sdk] Unhandled rejection:', event.reason);
|
|
224
|
+
setRejectionMessage(describeRejectionReason(event.reason) || 'Unknown error');
|
|
225
|
+
};
|
|
226
|
+
window.addEventListener('unhandledrejection', handler);
|
|
227
|
+
return () => {
|
|
228
|
+
window.removeEventListener('unhandledrejection', handler);
|
|
229
|
+
};
|
|
230
|
+
}, []);
|
|
46
231
|
if (!ready) {
|
|
47
232
|
return null;
|
|
48
233
|
}
|
|
49
|
-
return (0, jsx_runtime_1.
|
|
234
|
+
return ((0, jsx_runtime_1.jsxs)(context_1.FiasBridgeContext.Provider, { value: bridge, children: [rejectionMessage !== null ? ((0, jsx_runtime_1.jsx)(UnhandledRejectionBanner, { message: rejectionMessage, onDismiss: () => setRejectionMessage(null) })) : null, (0, jsx_runtime_1.jsx)(PluginErrorBoundary, { children: children })] }));
|
|
50
235
|
}
|
|
51
236
|
//# sourceMappingURL=provider.js.map
|
package/dist/provider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment @happy-dom/jest-environment
|
|
3
|
+
*
|
|
4
|
+
* Real-render tests for FiasProvider / PluginErrorBoundary (Phase 6 of the
|
|
5
|
+
* builder stability overhaul). `provider.test.ts` unit-tests the pieces with
|
|
6
|
+
* mocked React hooks; these tests mount the real tree in a DOM environment (happy-dom) to prove the
|
|
7
|
+
* user-observable recovery behaviors:
|
|
8
|
+
*
|
|
9
|
+
* 1. the error screen's "Try again" REMOUNTS the crashed subtree — after a
|
|
10
|
+
* transiently-throwing child stops throwing, the plugin renders again
|
|
11
|
+
* (no permanent black screen);
|
|
12
|
+
* 2. an unhandled promise rejection shows a dismissible non-fatal banner
|
|
13
|
+
* above the still-running plugin;
|
|
14
|
+
* 3. the unhandledrejection listener is removed on unmount.
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=provider.render.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.render.test.d.ts","sourceRoot":"","sources":["../src/provider.render.test.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
37
|
+
/**
|
|
38
|
+
* @jest-environment @happy-dom/jest-environment
|
|
39
|
+
*
|
|
40
|
+
* Real-render tests for FiasProvider / PluginErrorBoundary (Phase 6 of the
|
|
41
|
+
* builder stability overhaul). `provider.test.ts` unit-tests the pieces with
|
|
42
|
+
* mocked React hooks; these tests mount the real tree in a DOM environment (happy-dom) to prove the
|
|
43
|
+
* user-observable recovery behaviors:
|
|
44
|
+
*
|
|
45
|
+
* 1. the error screen's "Try again" REMOUNTS the crashed subtree — after a
|
|
46
|
+
* transiently-throwing child stops throwing, the plugin renders again
|
|
47
|
+
* (no permanent black screen);
|
|
48
|
+
* 2. an unhandled promise rejection shows a dismissible non-fatal banner
|
|
49
|
+
* above the still-running plugin;
|
|
50
|
+
* 3. the unhandledrejection listener is removed on unmount.
|
|
51
|
+
*/
|
|
52
|
+
const react_1 = __importStar(require("react"));
|
|
53
|
+
const client_1 = require("react-dom/client");
|
|
54
|
+
// Mock the bridge singleton so waitForInit resolves immediately.
|
|
55
|
+
const mockBridge = {
|
|
56
|
+
waitForInit: jest.fn().mockResolvedValue(undefined),
|
|
57
|
+
ready: jest.fn(),
|
|
58
|
+
getTheme: jest.fn().mockReturnValue(null),
|
|
59
|
+
getCurrentPath: jest.fn().mockReturnValue('/'),
|
|
60
|
+
destroy: jest.fn(),
|
|
61
|
+
};
|
|
62
|
+
jest.mock('./bridge', () => ({
|
|
63
|
+
getBridge: jest.fn(() => mockBridge),
|
|
64
|
+
}));
|
|
65
|
+
const provider_1 = require("./provider");
|
|
66
|
+
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
|
|
67
|
+
function dispatchUnhandledRejection(reason) {
|
|
68
|
+
// Not every DOM implementation exposes a PromiseRejectionEvent constructor — synthesize the shape.
|
|
69
|
+
const event = new Event('unhandledrejection');
|
|
70
|
+
event.reason = reason;
|
|
71
|
+
window.dispatchEvent(event);
|
|
72
|
+
}
|
|
73
|
+
describe('provider render behavior (DOM)', () => {
|
|
74
|
+
let container;
|
|
75
|
+
let root;
|
|
76
|
+
let consoleErrorSpy;
|
|
77
|
+
beforeEach(() => {
|
|
78
|
+
container = document.createElement('div');
|
|
79
|
+
document.body.appendChild(container);
|
|
80
|
+
root = (0, client_1.createRoot)(container);
|
|
81
|
+
// Error boundaries + our rejection handler both console.error; keep the
|
|
82
|
+
// test output clean and assert against the spy where relevant.
|
|
83
|
+
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
|
|
84
|
+
});
|
|
85
|
+
afterEach(async () => {
|
|
86
|
+
await (0, react_1.act)(async () => {
|
|
87
|
+
root.unmount();
|
|
88
|
+
});
|
|
89
|
+
container.remove();
|
|
90
|
+
consoleErrorSpy.mockRestore();
|
|
91
|
+
jest.clearAllMocks();
|
|
92
|
+
});
|
|
93
|
+
describe('PluginErrorBoundary reset', () => {
|
|
94
|
+
it('remounts the subtree via "Try again" once the child stops throwing', async () => {
|
|
95
|
+
let shouldThrow = true;
|
|
96
|
+
let mountCount = 0;
|
|
97
|
+
function Bomb() {
|
|
98
|
+
// Track mounts so we can prove the reset REMOUNTED (fresh instance),
|
|
99
|
+
// not merely re-rendered the old one.
|
|
100
|
+
const mountedRef = react_1.default.useRef(false);
|
|
101
|
+
if (!mountedRef.current) {
|
|
102
|
+
mountedRef.current = true;
|
|
103
|
+
mountCount += 1;
|
|
104
|
+
}
|
|
105
|
+
if (shouldThrow) {
|
|
106
|
+
throw new Error('transient render crash');
|
|
107
|
+
}
|
|
108
|
+
return (0, jsx_runtime_1.jsx)("div", { "data-testid": "app", children: "app-content" });
|
|
109
|
+
}
|
|
110
|
+
await (0, react_1.act)(async () => {
|
|
111
|
+
root.render((0, jsx_runtime_1.jsx)(provider_1.PluginErrorBoundary, { children: (0, jsx_runtime_1.jsx)(Bomb, {}) }));
|
|
112
|
+
});
|
|
113
|
+
// Crashed → full-screen fallback with the message and a reset button.
|
|
114
|
+
expect(container.textContent).toContain('This plugin hit an error');
|
|
115
|
+
expect(container.textContent).toContain('transient render crash');
|
|
116
|
+
const button = container.querySelector('button');
|
|
117
|
+
expect(button?.textContent).toBe('Try again');
|
|
118
|
+
// The transient condition clears; the user clicks "Try again".
|
|
119
|
+
shouldThrow = false;
|
|
120
|
+
const mountsBeforeReset = mountCount;
|
|
121
|
+
await (0, react_1.act)(async () => {
|
|
122
|
+
button.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
123
|
+
});
|
|
124
|
+
// The subtree is back — remounted cleanly (a NEW mount, not a reuse).
|
|
125
|
+
expect(container.querySelector('[data-testid="app"]')?.textContent).toBe('app-content');
|
|
126
|
+
expect(container.textContent).not.toContain('This plugin hit an error');
|
|
127
|
+
expect(mountCount).toBeGreaterThan(mountsBeforeReset);
|
|
128
|
+
});
|
|
129
|
+
it('shows a string error code on the fallback screen when present', async () => {
|
|
130
|
+
function CodedBomb() {
|
|
131
|
+
const err = new Error('invoke failed');
|
|
132
|
+
err.code = 'BRIDGE_TOKEN_EXPIRED';
|
|
133
|
+
throw err;
|
|
134
|
+
}
|
|
135
|
+
await (0, react_1.act)(async () => {
|
|
136
|
+
root.render((0, jsx_runtime_1.jsx)(provider_1.PluginErrorBoundary, { children: (0, jsx_runtime_1.jsx)(CodedBomb, {}) }));
|
|
137
|
+
});
|
|
138
|
+
expect(container.textContent).toContain('invoke failed');
|
|
139
|
+
expect(container.textContent).toContain('Code: BRIDGE_TOKEN_EXPIRED');
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe('FiasProvider unhandledrejection banner', () => {
|
|
143
|
+
it('renders a dismissible non-fatal banner and keeps the plugin running', async () => {
|
|
144
|
+
await (0, react_1.act)(async () => {
|
|
145
|
+
root.render((0, jsx_runtime_1.jsx)(provider_1.FiasProvider, { children: (0, jsx_runtime_1.jsx)("div", { "data-testid": "plugin", children: "plugin-body" }) }));
|
|
146
|
+
});
|
|
147
|
+
// waitForInit resolved → children visible, no banner yet.
|
|
148
|
+
expect(container.querySelector('[data-testid="plugin"]')).not.toBeNull();
|
|
149
|
+
expect(container.textContent).not.toContain('Something went wrong');
|
|
150
|
+
await (0, react_1.act)(async () => {
|
|
151
|
+
dispatchUnhandledRejection(new Error('floating invoke rejected'));
|
|
152
|
+
});
|
|
153
|
+
// Banner is rendered ABOVE the still-mounted plugin (non-fatal).
|
|
154
|
+
expect(container.textContent).toContain('Something went wrong in this app: floating invoke rejected');
|
|
155
|
+
expect(container.querySelector('[data-testid="plugin"]')).not.toBeNull();
|
|
156
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('[fias-sdk] Unhandled rejection:', expect.any(Error));
|
|
157
|
+
// Dismiss clears it.
|
|
158
|
+
const dismiss = container.querySelector('button[aria-label="Dismiss"]');
|
|
159
|
+
expect(dismiss).not.toBeNull();
|
|
160
|
+
await (0, react_1.act)(async () => {
|
|
161
|
+
dismiss.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
162
|
+
});
|
|
163
|
+
expect(container.textContent).not.toContain('Something went wrong');
|
|
164
|
+
expect(container.querySelector('[data-testid="plugin"]')).not.toBeNull();
|
|
165
|
+
});
|
|
166
|
+
it('removes the unhandledrejection listener on unmount', async () => {
|
|
167
|
+
const addSpy = jest.spyOn(window, 'addEventListener');
|
|
168
|
+
const removeSpy = jest.spyOn(window, 'removeEventListener');
|
|
169
|
+
await (0, react_1.act)(async () => {
|
|
170
|
+
root.render((0, jsx_runtime_1.jsx)(provider_1.FiasProvider, { children: (0, jsx_runtime_1.jsx)("div", { children: "plugin" }) }));
|
|
171
|
+
});
|
|
172
|
+
const addedHandlers = addSpy.mock.calls
|
|
173
|
+
.filter(([type]) => type === 'unhandledrejection')
|
|
174
|
+
.map(([, handler]) => handler);
|
|
175
|
+
expect(addedHandlers.length).toBeGreaterThan(0);
|
|
176
|
+
await (0, react_1.act)(async () => {
|
|
177
|
+
root.unmount();
|
|
178
|
+
});
|
|
179
|
+
const removedHandlers = removeSpy.mock.calls
|
|
180
|
+
.filter(([type]) => type === 'unhandledrejection')
|
|
181
|
+
.map(([, handler]) => handler);
|
|
182
|
+
// Every registered handler was removed.
|
|
183
|
+
for (const handler of addedHandlers) {
|
|
184
|
+
expect(removedHandlers).toContain(handler);
|
|
185
|
+
}
|
|
186
|
+
addSpy.mockRestore();
|
|
187
|
+
removeSpy.mockRestore();
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
//# sourceMappingURL=provider.render.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.render.test.js","sourceRoot":"","sources":["../src/provider.render.test.tsx"],"names":[],"mappings":"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"}
|