@useavalon/avalon 0.1.11 → 0.1.13
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/README.md +54 -54
- package/mod.ts +302 -302
- package/package.json +49 -26
- package/src/build/integration-bundler-plugin.ts +116 -116
- package/src/build/integration-config.ts +168 -168
- package/src/build/integration-detection-plugin.ts +117 -117
- package/src/build/integration-resolver-plugin.ts +90 -90
- package/src/build/island-manifest.ts +269 -269
- package/src/build/island-types-generator.ts +476 -476
- package/src/build/mdx-island-transform.ts +464 -464
- package/src/build/mdx-plugin.ts +98 -98
- package/src/build/page-island-transform.ts +598 -598
- package/src/build/prop-extractors/index.ts +21 -21
- package/src/build/prop-extractors/lit.ts +140 -140
- package/src/build/prop-extractors/qwik.ts +16 -16
- package/src/build/prop-extractors/solid.ts +125 -125
- package/src/build/prop-extractors/svelte.ts +194 -194
- package/src/build/prop-extractors/vue.ts +111 -111
- package/src/build/sidecar-file-manager.ts +104 -104
- package/src/build/sidecar-renderer.ts +30 -30
- package/src/client/adapters/index.ts +21 -13
- package/src/client/components.ts +35 -35
- package/src/client/css-hmr-handler.ts +344 -344
- package/src/client/framework-adapter.ts +462 -462
- package/src/client/hmr-coordinator.ts +396 -396
- package/src/client/hmr-error-overlay.js +533 -533
- package/src/client/main.js +824 -816
- package/src/client/types/framework-runtime.d.ts +68 -68
- package/src/client/types/vite-hmr.d.ts +46 -46
- package/src/client/types/vite-virtual-modules.d.ts +70 -60
- package/src/components/Image.tsx +123 -123
- package/src/components/IslandErrorBoundary.tsx +145 -145
- package/src/components/LayoutDataErrorBoundary.tsx +141 -141
- package/src/components/LayoutErrorBoundary.tsx +127 -127
- package/src/components/PersistentIsland.tsx +52 -52
- package/src/components/StreamingErrorBoundary.tsx +233 -233
- package/src/components/StreamingLayout.tsx +538 -538
- package/src/core/components/component-analyzer.ts +192 -192
- package/src/core/components/component-detection.ts +508 -508
- package/src/core/components/enhanced-framework-detector.ts +500 -500
- package/src/core/components/framework-registry.ts +563 -563
- package/src/core/content/mdx-processor.ts +46 -46
- package/src/core/integrations/index.ts +19 -19
- package/src/core/integrations/loader.ts +125 -125
- package/src/core/integrations/registry.ts +175 -175
- package/src/core/islands/island-persistence.ts +325 -325
- package/src/core/islands/island-state-serializer.ts +258 -258
- package/src/core/islands/persistent-island-context.tsx +80 -80
- package/src/core/islands/use-persistent-state.ts +68 -68
- package/src/core/layout/enhanced-layout-resolver.ts +322 -322
- package/src/core/layout/layout-cache-manager.ts +485 -485
- package/src/core/layout/layout-composer.ts +357 -357
- package/src/core/layout/layout-data-loader.ts +516 -516
- package/src/core/layout/layout-discovery.ts +243 -243
- package/src/core/layout/layout-matcher.ts +299 -299
- package/src/core/layout/layout-types.ts +110 -110
- package/src/core/modules/framework-module-resolver.ts +273 -273
- package/src/islands/component-analysis.ts +213 -213
- package/src/islands/css-utils.ts +565 -565
- package/src/islands/discovery/index.ts +80 -80
- package/src/islands/discovery/registry.ts +340 -340
- package/src/islands/discovery/resolver.ts +477 -477
- package/src/islands/discovery/scanner.ts +386 -386
- package/src/islands/discovery/types.ts +117 -117
- package/src/islands/discovery/validator.ts +544 -544
- package/src/islands/discovery/watcher.ts +368 -368
- package/src/islands/framework-detection.ts +428 -428
- package/src/islands/integration-loader.ts +490 -490
- package/src/islands/island.tsx +565 -565
- package/src/islands/render-cache.ts +550 -550
- package/src/islands/types.ts +80 -80
- package/src/islands/universal-css-collector.ts +157 -157
- package/src/islands/universal-head-collector.ts +137 -137
- package/src/layout-system.d.ts +592 -592
- package/src/layout-system.ts +218 -218
- package/src/middleware/discovery.ts +268 -268
- package/src/middleware/executor.ts +315 -315
- package/src/middleware/index.ts +76 -76
- package/src/middleware/types.ts +99 -99
- package/src/nitro/build-config.ts +575 -575
- package/src/nitro/config.ts +483 -483
- package/src/nitro/error-handler.ts +636 -636
- package/src/nitro/index.ts +173 -173
- package/src/nitro/island-manifest.ts +584 -584
- package/src/nitro/middleware-adapter.ts +260 -260
- package/src/nitro/renderer.ts +1471 -1471
- package/src/nitro/route-discovery.ts +439 -439
- package/src/nitro/types.ts +321 -321
- package/src/render/collect-css.ts +198 -198
- package/src/render/error-pages.ts +79 -79
- package/src/render/isolated-ssr-renderer.ts +654 -654
- package/src/render/ssr.ts +1030 -1030
- package/src/schemas/api.ts +30 -30
- package/src/schemas/core.ts +64 -64
- package/src/schemas/index.ts +212 -212
- package/src/schemas/layout.ts +279 -279
- package/src/schemas/routing/index.ts +38 -38
- package/src/schemas/routing.ts +376 -376
- package/src/types/as-island.ts +20 -20
- package/src/types/image.d.ts +106 -106
- package/src/types/index.d.ts +22 -22
- package/src/types/island-jsx.d.ts +33 -33
- package/src/types/island-prop.d.ts +20 -20
- package/src/types/layout.ts +285 -285
- package/src/types/mdx.d.ts +6 -6
- package/src/types/routing.ts +555 -555
- package/src/types/types.ts +5 -5
- package/src/types/urlpattern.d.ts +49 -49
- package/src/types/vite-env.d.ts +11 -11
- package/src/utils/dev-logger.ts +299 -299
- package/src/utils/fs.ts +151 -151
- package/src/vite-plugin/auto-discover.ts +551 -551
- package/src/vite-plugin/config.ts +266 -266
- package/src/vite-plugin/errors.ts +127 -127
- package/src/vite-plugin/image-optimization.ts +156 -156
- package/src/vite-plugin/integration-activator.ts +126 -126
- package/src/vite-plugin/island-sidecar-plugin.ts +176 -176
- package/src/vite-plugin/module-discovery.ts +189 -189
- package/src/vite-plugin/nitro-integration.ts +1354 -1354
- package/src/vite-plugin/plugin.ts +403 -409
- package/src/vite-plugin/types.ts +327 -327
- package/src/vite-plugin/validation.ts +228 -228
- package/src/client/adapters/index.js +0 -12
- package/src/client/adapters/lit-adapter.js +0 -467
- package/src/client/adapters/lit-adapter.ts +0 -654
- package/src/client/adapters/preact-adapter.js +0 -223
- package/src/client/adapters/preact-adapter.ts +0 -331
- package/src/client/adapters/qwik-adapter.js +0 -259
- package/src/client/adapters/qwik-adapter.ts +0 -345
- package/src/client/adapters/react-adapter.js +0 -220
- package/src/client/adapters/react-adapter.ts +0 -353
- package/src/client/adapters/solid-adapter.js +0 -295
- package/src/client/adapters/solid-adapter.ts +0 -451
- package/src/client/adapters/svelte-adapter.js +0 -368
- package/src/client/adapters/svelte-adapter.ts +0 -524
- package/src/client/adapters/vue-adapter.js +0 -278
- package/src/client/adapters/vue-adapter.ts +0 -467
- package/src/client/components.js +0 -23
- package/src/client/css-hmr-handler.js +0 -263
- package/src/client/framework-adapter.js +0 -283
- package/src/client/hmr-coordinator.js +0 -274
|
@@ -1,233 +1,233 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* StreamingErrorBoundary - Error boundary component for streaming contexts
|
|
3
|
-
*
|
|
4
|
-
* This component provides error isolation for Suspense boundaries in streaming SSR.
|
|
5
|
-
* It ensures that errors in one component don't break the entire page.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { Component, type ComponentChildren } from 'preact';
|
|
9
|
-
|
|
10
|
-
export interface StreamingErrorBoundaryProps {
|
|
11
|
-
children: ComponentChildren;
|
|
12
|
-
fallback?: (error: Error, retry: () => void) => ComponentChildren;
|
|
13
|
-
onError?: (error: Error, errorInfo: any) => void;
|
|
14
|
-
componentId?: string;
|
|
15
|
-
isolateError?: boolean; // If true, error won't propagate to parent
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface StreamingErrorBoundaryState {
|
|
19
|
-
hasError: boolean;
|
|
20
|
-
error: Error | null;
|
|
21
|
-
errorInfo: any;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Error boundary component for streaming contexts
|
|
26
|
-
*
|
|
27
|
-
* Wraps Suspense boundaries to provide error isolation and recovery.
|
|
28
|
-
* Prevents errors in one component from breaking the entire page.
|
|
29
|
-
*/
|
|
30
|
-
export class StreamingErrorBoundary extends Component<
|
|
31
|
-
StreamingErrorBoundaryProps,
|
|
32
|
-
StreamingErrorBoundaryState
|
|
33
|
-
> {
|
|
34
|
-
constructor(props: StreamingErrorBoundaryProps) {
|
|
35
|
-
super(props);
|
|
36
|
-
this.state = {
|
|
37
|
-
hasError: false,
|
|
38
|
-
error: null,
|
|
39
|
-
errorInfo: null,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
static override getDerivedStateFromError(error: Error): Partial<StreamingErrorBoundaryState> {
|
|
44
|
-
return {
|
|
45
|
-
hasError: true,
|
|
46
|
-
error,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
override componentDidCatch(error: Error, errorInfo: any): void {
|
|
51
|
-
this.setState({
|
|
52
|
-
errorInfo,
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// Log the error
|
|
56
|
-
console.error('[StreamingErrorBoundary] Caught error:', {
|
|
57
|
-
componentId: this.props.componentId,
|
|
58
|
-
error: error.message,
|
|
59
|
-
stack: error.stack,
|
|
60
|
-
componentStack: errorInfo.componentStack,
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// Call onError callback if provided
|
|
64
|
-
if (this.props.onError) {
|
|
65
|
-
this.props.onError(error, errorInfo);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// If isolateError is false, re-throw to propagate to parent
|
|
69
|
-
if (!this.props.isolateError) {
|
|
70
|
-
throw error;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
private handleRetry = (): void => {
|
|
75
|
-
this.setState({
|
|
76
|
-
hasError: false,
|
|
77
|
-
error: null,
|
|
78
|
-
errorInfo: null,
|
|
79
|
-
});
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
private renderFallback(): ComponentChildren {
|
|
83
|
-
const { error } = this.state;
|
|
84
|
-
const { fallback, componentId } = this.props;
|
|
85
|
-
|
|
86
|
-
if (fallback && error) {
|
|
87
|
-
return fallback(error, this.handleRetry);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Default fallback UI
|
|
91
|
-
const isDevelopment = typeof Deno !== 'undefined' && Deno.env.get('DENO_ENV') !== 'production';
|
|
92
|
-
|
|
93
|
-
return (
|
|
94
|
-
<div
|
|
95
|
-
class="streaming-error-boundary"
|
|
96
|
-
data-error-boundary="true"
|
|
97
|
-
data-component-id={componentId}
|
|
98
|
-
style={{
|
|
99
|
-
background: '#fff3cd',
|
|
100
|
-
border: '2px solid #ffc107',
|
|
101
|
-
borderRadius: '8px',
|
|
102
|
-
padding: '20px',
|
|
103
|
-
margin: '20px 0',
|
|
104
|
-
fontFamily: 'system-ui, -apple-system, sans-serif',
|
|
105
|
-
}}
|
|
106
|
-
>
|
|
107
|
-
<div
|
|
108
|
-
class="error-boundary-header"
|
|
109
|
-
style={{
|
|
110
|
-
display: 'flex',
|
|
111
|
-
alignItems: 'center',
|
|
112
|
-
gap: '10px',
|
|
113
|
-
marginBottom: '10px',
|
|
114
|
-
}}
|
|
115
|
-
>
|
|
116
|
-
<span style={{ fontSize: '24px' }}>⚠️</span>
|
|
117
|
-
<h3 style={{ margin: 0, color: '#856404' }}>Component Error</h3>
|
|
118
|
-
</div>
|
|
119
|
-
|
|
120
|
-
<p style={{ margin: '10px 0', color: '#856404' }}>
|
|
121
|
-
An error occurred while rendering this component. The rest of the page should work normally.
|
|
122
|
-
</p>
|
|
123
|
-
|
|
124
|
-
<button
|
|
125
|
-
onClick={this.handleRetry}
|
|
126
|
-
style={{
|
|
127
|
-
background: '#ffc107',
|
|
128
|
-
border: 'none',
|
|
129
|
-
borderRadius: '4px',
|
|
130
|
-
padding: '8px 16px',
|
|
131
|
-
cursor: 'pointer',
|
|
132
|
-
fontWeight: 'bold',
|
|
133
|
-
color: '#856404',
|
|
134
|
-
marginTop: '10px',
|
|
135
|
-
}}
|
|
136
|
-
>
|
|
137
|
-
Retry
|
|
138
|
-
</button>
|
|
139
|
-
|
|
140
|
-
{isDevelopment && error && (
|
|
141
|
-
<details style={{ marginTop: '15px' }}>
|
|
142
|
-
<summary
|
|
143
|
-
style={{
|
|
144
|
-
cursor: 'pointer',
|
|
145
|
-
color: '#856404',
|
|
146
|
-
fontWeight: 'bold',
|
|
147
|
-
}}
|
|
148
|
-
>
|
|
149
|
-
Error Details (Development Mode)
|
|
150
|
-
</summary>
|
|
151
|
-
<div style={{ marginTop: '10px' }}>
|
|
152
|
-
{componentId && (
|
|
153
|
-
<p>
|
|
154
|
-
<strong>Component ID:</strong> {componentId}
|
|
155
|
-
</p>
|
|
156
|
-
)}
|
|
157
|
-
<p>
|
|
158
|
-
<strong>Error:</strong> {error.message}
|
|
159
|
-
</p>
|
|
160
|
-
{error.stack && (
|
|
161
|
-
<pre
|
|
162
|
-
style={{
|
|
163
|
-
background: '#f5f5f5',
|
|
164
|
-
padding: '10px',
|
|
165
|
-
borderRadius: '4px',
|
|
166
|
-
overflowX: 'auto',
|
|
167
|
-
fontSize: '12px',
|
|
168
|
-
marginTop: '10px',
|
|
169
|
-
}}
|
|
170
|
-
>
|
|
171
|
-
{error.stack}
|
|
172
|
-
</pre>
|
|
173
|
-
)}
|
|
174
|
-
{this.state.errorInfo?.componentStack && (
|
|
175
|
-
<div>
|
|
176
|
-
<p>
|
|
177
|
-
<strong>Component Stack:</strong>
|
|
178
|
-
</p>
|
|
179
|
-
<pre
|
|
180
|
-
style={{
|
|
181
|
-
background: '#f5f5f5',
|
|
182
|
-
padding: '10px',
|
|
183
|
-
borderRadius: '4px',
|
|
184
|
-
overflowX: 'auto',
|
|
185
|
-
fontSize: '12px',
|
|
186
|
-
marginTop: '10px',
|
|
187
|
-
}}
|
|
188
|
-
>
|
|
189
|
-
{this.state.errorInfo.componentStack}
|
|
190
|
-
</pre>
|
|
191
|
-
</div>
|
|
192
|
-
)}
|
|
193
|
-
</div>
|
|
194
|
-
</details>
|
|
195
|
-
)}
|
|
196
|
-
</div>
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
render() {
|
|
201
|
-
if (this.state.hasError) {
|
|
202
|
-
return this.renderFallback();
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return this.props.children;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Higher-order component to wrap components with streaming error boundaries
|
|
211
|
-
*/
|
|
212
|
-
export function withStreamingErrorBoundary<P extends object>(
|
|
213
|
-
WrappedComponent: (props: P) => ComponentChildren,
|
|
214
|
-
options?: {
|
|
215
|
-
fallback?: (error: Error, retry: () => void) => ComponentChildren;
|
|
216
|
-
componentId?: string;
|
|
217
|
-
isolateError?: boolean;
|
|
218
|
-
onError?: (error: Error, errorInfo: any) => void;
|
|
219
|
-
}
|
|
220
|
-
) {
|
|
221
|
-
return function ComponentWithErrorBoundary(props: P) {
|
|
222
|
-
return (
|
|
223
|
-
<StreamingErrorBoundary
|
|
224
|
-
componentId={options?.componentId}
|
|
225
|
-
fallback={options?.fallback}
|
|
226
|
-
isolateError={options?.isolateError ?? true}
|
|
227
|
-
onError={options?.onError}
|
|
228
|
-
>
|
|
229
|
-
<WrappedComponent {...props} />
|
|
230
|
-
</StreamingErrorBoundary>
|
|
231
|
-
);
|
|
232
|
-
};
|
|
233
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* StreamingErrorBoundary - Error boundary component for streaming contexts
|
|
3
|
+
*
|
|
4
|
+
* This component provides error isolation for Suspense boundaries in streaming SSR.
|
|
5
|
+
* It ensures that errors in one component don't break the entire page.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Component, type ComponentChildren } from 'preact';
|
|
9
|
+
|
|
10
|
+
export interface StreamingErrorBoundaryProps {
|
|
11
|
+
children: ComponentChildren;
|
|
12
|
+
fallback?: (error: Error, retry: () => void) => ComponentChildren;
|
|
13
|
+
onError?: (error: Error, errorInfo: any) => void;
|
|
14
|
+
componentId?: string;
|
|
15
|
+
isolateError?: boolean; // If true, error won't propagate to parent
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface StreamingErrorBoundaryState {
|
|
19
|
+
hasError: boolean;
|
|
20
|
+
error: Error | null;
|
|
21
|
+
errorInfo: any;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Error boundary component for streaming contexts
|
|
26
|
+
*
|
|
27
|
+
* Wraps Suspense boundaries to provide error isolation and recovery.
|
|
28
|
+
* Prevents errors in one component from breaking the entire page.
|
|
29
|
+
*/
|
|
30
|
+
export class StreamingErrorBoundary extends Component<
|
|
31
|
+
StreamingErrorBoundaryProps,
|
|
32
|
+
StreamingErrorBoundaryState
|
|
33
|
+
> {
|
|
34
|
+
constructor(props: StreamingErrorBoundaryProps) {
|
|
35
|
+
super(props);
|
|
36
|
+
this.state = {
|
|
37
|
+
hasError: false,
|
|
38
|
+
error: null,
|
|
39
|
+
errorInfo: null,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static override getDerivedStateFromError(error: Error): Partial<StreamingErrorBoundaryState> {
|
|
44
|
+
return {
|
|
45
|
+
hasError: true,
|
|
46
|
+
error,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
override componentDidCatch(error: Error, errorInfo: any): void {
|
|
51
|
+
this.setState({
|
|
52
|
+
errorInfo,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Log the error
|
|
56
|
+
console.error('[StreamingErrorBoundary] Caught error:', {
|
|
57
|
+
componentId: this.props.componentId,
|
|
58
|
+
error: error.message,
|
|
59
|
+
stack: error.stack,
|
|
60
|
+
componentStack: errorInfo.componentStack,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Call onError callback if provided
|
|
64
|
+
if (this.props.onError) {
|
|
65
|
+
this.props.onError(error, errorInfo);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// If isolateError is false, re-throw to propagate to parent
|
|
69
|
+
if (!this.props.isolateError) {
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private handleRetry = (): void => {
|
|
75
|
+
this.setState({
|
|
76
|
+
hasError: false,
|
|
77
|
+
error: null,
|
|
78
|
+
errorInfo: null,
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
private renderFallback(): ComponentChildren {
|
|
83
|
+
const { error } = this.state;
|
|
84
|
+
const { fallback, componentId } = this.props;
|
|
85
|
+
|
|
86
|
+
if (fallback && error) {
|
|
87
|
+
return fallback(error, this.handleRetry);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Default fallback UI
|
|
91
|
+
const isDevelopment = typeof Deno !== 'undefined' && Deno.env.get('DENO_ENV') !== 'production';
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<div
|
|
95
|
+
class="streaming-error-boundary"
|
|
96
|
+
data-error-boundary="true"
|
|
97
|
+
data-component-id={componentId}
|
|
98
|
+
style={{
|
|
99
|
+
background: '#fff3cd',
|
|
100
|
+
border: '2px solid #ffc107',
|
|
101
|
+
borderRadius: '8px',
|
|
102
|
+
padding: '20px',
|
|
103
|
+
margin: '20px 0',
|
|
104
|
+
fontFamily: 'system-ui, -apple-system, sans-serif',
|
|
105
|
+
}}
|
|
106
|
+
>
|
|
107
|
+
<div
|
|
108
|
+
class="error-boundary-header"
|
|
109
|
+
style={{
|
|
110
|
+
display: 'flex',
|
|
111
|
+
alignItems: 'center',
|
|
112
|
+
gap: '10px',
|
|
113
|
+
marginBottom: '10px',
|
|
114
|
+
}}
|
|
115
|
+
>
|
|
116
|
+
<span style={{ fontSize: '24px' }}>⚠️</span>
|
|
117
|
+
<h3 style={{ margin: 0, color: '#856404' }}>Component Error</h3>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<p style={{ margin: '10px 0', color: '#856404' }}>
|
|
121
|
+
An error occurred while rendering this component. The rest of the page should work normally.
|
|
122
|
+
</p>
|
|
123
|
+
|
|
124
|
+
<button
|
|
125
|
+
onClick={this.handleRetry}
|
|
126
|
+
style={{
|
|
127
|
+
background: '#ffc107',
|
|
128
|
+
border: 'none',
|
|
129
|
+
borderRadius: '4px',
|
|
130
|
+
padding: '8px 16px',
|
|
131
|
+
cursor: 'pointer',
|
|
132
|
+
fontWeight: 'bold',
|
|
133
|
+
color: '#856404',
|
|
134
|
+
marginTop: '10px',
|
|
135
|
+
}}
|
|
136
|
+
>
|
|
137
|
+
Retry
|
|
138
|
+
</button>
|
|
139
|
+
|
|
140
|
+
{isDevelopment && error && (
|
|
141
|
+
<details style={{ marginTop: '15px' }}>
|
|
142
|
+
<summary
|
|
143
|
+
style={{
|
|
144
|
+
cursor: 'pointer',
|
|
145
|
+
color: '#856404',
|
|
146
|
+
fontWeight: 'bold',
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
Error Details (Development Mode)
|
|
150
|
+
</summary>
|
|
151
|
+
<div style={{ marginTop: '10px' }}>
|
|
152
|
+
{componentId && (
|
|
153
|
+
<p>
|
|
154
|
+
<strong>Component ID:</strong> {componentId}
|
|
155
|
+
</p>
|
|
156
|
+
)}
|
|
157
|
+
<p>
|
|
158
|
+
<strong>Error:</strong> {error.message}
|
|
159
|
+
</p>
|
|
160
|
+
{error.stack && (
|
|
161
|
+
<pre
|
|
162
|
+
style={{
|
|
163
|
+
background: '#f5f5f5',
|
|
164
|
+
padding: '10px',
|
|
165
|
+
borderRadius: '4px',
|
|
166
|
+
overflowX: 'auto',
|
|
167
|
+
fontSize: '12px',
|
|
168
|
+
marginTop: '10px',
|
|
169
|
+
}}
|
|
170
|
+
>
|
|
171
|
+
{error.stack}
|
|
172
|
+
</pre>
|
|
173
|
+
)}
|
|
174
|
+
{this.state.errorInfo?.componentStack && (
|
|
175
|
+
<div>
|
|
176
|
+
<p>
|
|
177
|
+
<strong>Component Stack:</strong>
|
|
178
|
+
</p>
|
|
179
|
+
<pre
|
|
180
|
+
style={{
|
|
181
|
+
background: '#f5f5f5',
|
|
182
|
+
padding: '10px',
|
|
183
|
+
borderRadius: '4px',
|
|
184
|
+
overflowX: 'auto',
|
|
185
|
+
fontSize: '12px',
|
|
186
|
+
marginTop: '10px',
|
|
187
|
+
}}
|
|
188
|
+
>
|
|
189
|
+
{this.state.errorInfo.componentStack}
|
|
190
|
+
</pre>
|
|
191
|
+
</div>
|
|
192
|
+
)}
|
|
193
|
+
</div>
|
|
194
|
+
</details>
|
|
195
|
+
)}
|
|
196
|
+
</div>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
render() {
|
|
201
|
+
if (this.state.hasError) {
|
|
202
|
+
return this.renderFallback();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return this.props.children;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Higher-order component to wrap components with streaming error boundaries
|
|
211
|
+
*/
|
|
212
|
+
export function withStreamingErrorBoundary<P extends object>(
|
|
213
|
+
WrappedComponent: (props: P) => ComponentChildren,
|
|
214
|
+
options?: {
|
|
215
|
+
fallback?: (error: Error, retry: () => void) => ComponentChildren;
|
|
216
|
+
componentId?: string;
|
|
217
|
+
isolateError?: boolean;
|
|
218
|
+
onError?: (error: Error, errorInfo: any) => void;
|
|
219
|
+
}
|
|
220
|
+
) {
|
|
221
|
+
return function ComponentWithErrorBoundary(props: P) {
|
|
222
|
+
return (
|
|
223
|
+
<StreamingErrorBoundary
|
|
224
|
+
componentId={options?.componentId}
|
|
225
|
+
fallback={options?.fallback}
|
|
226
|
+
isolateError={options?.isolateError ?? true}
|
|
227
|
+
onError={options?.onError}
|
|
228
|
+
>
|
|
229
|
+
<WrappedComponent {...props} />
|
|
230
|
+
</StreamingErrorBoundary>
|
|
231
|
+
);
|
|
232
|
+
};
|
|
233
|
+
}
|