@useavalon/avalon 0.1.10 → 0.1.12
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/dist/mod.js +1 -0
- package/dist/src/build/integration-bundler-plugin.js +1 -0
- package/dist/src/build/integration-config.js +1 -0
- package/dist/src/build/integration-detection-plugin.js +1 -0
- package/dist/src/build/integration-resolver-plugin.js +1 -0
- package/dist/src/build/island-manifest.js +1 -0
- package/dist/src/build/island-types-generator.js +5 -0
- package/dist/src/build/mdx-island-transform.js +2 -0
- package/dist/src/build/mdx-plugin.js +1 -0
- package/dist/src/build/page-island-transform.js +3 -0
- package/dist/src/build/prop-extractors/index.js +1 -0
- package/dist/src/build/prop-extractors/lit.js +1 -0
- package/dist/src/build/prop-extractors/qwik.js +1 -0
- package/dist/src/build/prop-extractors/solid.js +1 -0
- package/dist/src/build/prop-extractors/svelte.js +1 -0
- package/dist/src/build/prop-extractors/vue.js +1 -0
- package/dist/src/build/sidecar-file-manager.js +1 -0
- package/dist/src/build/sidecar-renderer.js +6 -0
- package/dist/src/client/adapters/index.js +1 -0
- package/dist/src/client/components.js +1 -0
- package/dist/src/client/css-hmr-handler.js +1 -0
- package/dist/src/client/framework-adapter.js +13 -0
- package/dist/src/client/hmr-coordinator.js +1 -0
- package/dist/src/client/hmr-error-overlay.js +214 -0
- package/dist/src/client/main.js +39 -0
- package/{src → dist/src}/client/types/framework-runtime.d.ts +68 -68
- package/{src → dist/src}/client/types/vite-hmr.d.ts +46 -46
- package/dist/src/client/types/vite-virtual-modules.d.ts +70 -0
- package/dist/src/components/Image.js +1 -0
- package/dist/src/components/IslandErrorBoundary.js +1 -0
- package/dist/src/components/LayoutDataErrorBoundary.js +1 -0
- package/dist/src/components/LayoutErrorBoundary.js +1 -0
- package/dist/src/components/PersistentIsland.js +1 -0
- package/dist/src/components/StreamingErrorBoundary.js +1 -0
- package/dist/src/components/StreamingLayout.js +29 -0
- package/dist/src/core/components/component-analyzer.js +1 -0
- package/dist/src/core/components/component-detection.js +5 -0
- package/dist/src/core/components/enhanced-framework-detector.js +1 -0
- package/dist/src/core/components/framework-registry.js +1 -0
- package/dist/src/core/content/mdx-processor.js +1 -0
- package/dist/src/core/integrations/index.js +1 -0
- package/dist/src/core/integrations/loader.js +1 -0
- package/dist/src/core/integrations/registry.js +1 -0
- package/dist/src/core/islands/island-persistence.js +1 -0
- package/dist/src/core/islands/island-state-serializer.js +1 -0
- package/dist/src/core/islands/persistent-island-context.js +1 -0
- package/dist/src/core/islands/use-persistent-state.js +1 -0
- package/dist/src/core/layout/enhanced-layout-resolver.js +1 -0
- package/dist/src/core/layout/layout-cache-manager.js +1 -0
- package/dist/src/core/layout/layout-composer.js +1 -0
- package/dist/src/core/layout/layout-data-loader.js +1 -0
- package/dist/src/core/layout/layout-discovery.js +1 -0
- package/dist/src/core/layout/layout-matcher.js +1 -0
- package/dist/src/core/layout/layout-types.js +1 -0
- package/dist/src/core/modules/framework-module-resolver.js +1 -0
- package/dist/src/islands/component-analysis.js +1 -0
- package/dist/src/islands/css-utils.js +17 -0
- package/dist/src/islands/discovery/index.js +1 -0
- package/dist/src/islands/discovery/registry.js +1 -0
- package/dist/src/islands/discovery/resolver.js +2 -0
- package/dist/src/islands/discovery/scanner.js +1 -0
- package/dist/src/islands/discovery/types.js +1 -0
- package/dist/src/islands/discovery/validator.js +18 -0
- package/dist/src/islands/discovery/watcher.js +1 -0
- package/dist/src/islands/framework-detection.js +1 -0
- package/dist/src/islands/integration-loader.js +1 -0
- package/dist/src/islands/island.js +1 -0
- package/dist/src/islands/render-cache.js +1 -0
- package/dist/src/islands/types.js +1 -0
- package/dist/src/islands/universal-css-collector.js +5 -0
- package/dist/src/islands/universal-head-collector.js +2 -0
- package/{src → dist/src}/layout-system.d.ts +592 -592
- package/dist/src/layout-system.js +1 -0
- package/dist/src/middleware/discovery.js +1 -0
- package/dist/src/middleware/executor.js +1 -0
- package/dist/src/middleware/index.js +1 -0
- package/dist/src/middleware/types.js +1 -0
- package/dist/src/nitro/build-config.js +1 -0
- package/dist/src/nitro/config.js +1 -0
- package/dist/src/nitro/error-handler.js +198 -0
- package/dist/src/nitro/index.js +1 -0
- package/dist/src/nitro/island-manifest.js +2 -0
- package/dist/src/nitro/middleware-adapter.js +1 -0
- package/dist/src/nitro/renderer.js +183 -0
- package/dist/src/nitro/route-discovery.js +1 -0
- package/dist/src/nitro/types.js +1 -0
- package/dist/src/render/collect-css.js +3 -0
- package/{src/render/error-pages.ts → dist/src/render/error-pages.js} +7 -38
- package/dist/src/render/isolated-ssr-renderer.js +1 -0
- package/dist/src/render/ssr.js +90 -0
- package/dist/src/schemas/api.js +1 -0
- package/dist/src/schemas/core.js +1 -0
- package/dist/src/schemas/index.js +1 -0
- package/dist/src/schemas/layout.js +1 -0
- package/dist/src/schemas/routing/index.js +1 -0
- package/dist/src/schemas/routing.js +1 -0
- package/dist/src/types/as-island.js +1 -0
- package/{src → dist/src}/types/image.d.ts +106 -106
- package/{src → dist/src}/types/index.d.ts +22 -22
- package/{src → dist/src}/types/island-jsx.d.ts +33 -33
- package/{src → dist/src}/types/island-prop.d.ts +20 -20
- package/dist/src/types/layout.js +1 -0
- package/{src → dist/src}/types/mdx.d.ts +6 -6
- package/dist/src/types/routing.js +1 -0
- package/dist/src/types/types.js +1 -0
- package/{src → dist/src}/types/urlpattern.d.ts +49 -49
- package/{src → dist/src}/types/vite-env.d.ts +11 -11
- package/dist/src/utils/dev-logger.js +12 -0
- package/dist/src/utils/fs.js +1 -0
- package/dist/src/vite-plugin/auto-discover.js +1 -0
- package/dist/src/vite-plugin/config.js +1 -0
- package/dist/src/vite-plugin/errors.js +1 -0
- package/dist/src/vite-plugin/image-optimization.js +45 -0
- package/dist/src/vite-plugin/integration-activator.js +1 -0
- package/dist/src/vite-plugin/island-sidecar-plugin.js +1 -0
- package/dist/src/vite-plugin/module-discovery.js +1 -0
- package/dist/src/vite-plugin/nitro-integration.js +42 -0
- package/dist/src/vite-plugin/plugin.js +1 -0
- package/dist/src/vite-plugin/types.js +1 -0
- package/dist/src/vite-plugin/validation.js +2 -0
- package/package.json +57 -26
- package/mod.ts +0 -302
- package/src/build/integration-bundler-plugin.ts +0 -116
- package/src/build/integration-config.ts +0 -168
- package/src/build/integration-detection-plugin.ts +0 -117
- package/src/build/integration-resolver-plugin.ts +0 -90
- package/src/build/island-manifest.ts +0 -269
- package/src/build/island-types-generator.ts +0 -476
- package/src/build/mdx-island-transform.ts +0 -464
- package/src/build/mdx-plugin.ts +0 -98
- package/src/build/page-island-transform.ts +0 -598
- package/src/build/prop-extractors/index.ts +0 -21
- package/src/build/prop-extractors/lit.ts +0 -140
- package/src/build/prop-extractors/qwik.ts +0 -16
- package/src/build/prop-extractors/solid.ts +0 -125
- package/src/build/prop-extractors/svelte.ts +0 -194
- package/src/build/prop-extractors/vue.ts +0 -111
- package/src/build/sidecar-file-manager.ts +0 -104
- package/src/build/sidecar-renderer.ts +0 -30
- package/src/client/adapters/index.js +0 -12
- package/src/client/adapters/index.ts +0 -13
- 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/components.ts +0 -35
- package/src/client/css-hmr-handler.js +0 -263
- package/src/client/css-hmr-handler.ts +0 -344
- package/src/client/framework-adapter.js +0 -283
- package/src/client/framework-adapter.ts +0 -462
- package/src/client/hmr-coordinator.js +0 -274
- package/src/client/hmr-coordinator.ts +0 -396
- package/src/client/hmr-error-overlay.js +0 -533
- package/src/client/main.js +0 -816
- package/src/client/types/vite-virtual-modules.d.ts +0 -60
- package/src/components/Image.tsx +0 -123
- package/src/components/IslandErrorBoundary.tsx +0 -145
- package/src/components/LayoutDataErrorBoundary.tsx +0 -141
- package/src/components/LayoutErrorBoundary.tsx +0 -127
- package/src/components/PersistentIsland.tsx +0 -52
- package/src/components/StreamingErrorBoundary.tsx +0 -233
- package/src/components/StreamingLayout.tsx +0 -538
- package/src/core/components/component-analyzer.ts +0 -192
- package/src/core/components/component-detection.ts +0 -508
- package/src/core/components/enhanced-framework-detector.ts +0 -500
- package/src/core/components/framework-registry.ts +0 -563
- package/src/core/content/mdx-processor.ts +0 -46
- package/src/core/integrations/index.ts +0 -19
- package/src/core/integrations/loader.ts +0 -125
- package/src/core/integrations/registry.ts +0 -175
- package/src/core/islands/island-persistence.ts +0 -325
- package/src/core/islands/island-state-serializer.ts +0 -258
- package/src/core/islands/persistent-island-context.tsx +0 -80
- package/src/core/islands/use-persistent-state.ts +0 -68
- package/src/core/layout/enhanced-layout-resolver.ts +0 -322
- package/src/core/layout/layout-cache-manager.ts +0 -485
- package/src/core/layout/layout-composer.ts +0 -357
- package/src/core/layout/layout-data-loader.ts +0 -516
- package/src/core/layout/layout-discovery.ts +0 -243
- package/src/core/layout/layout-matcher.ts +0 -299
- package/src/core/layout/layout-types.ts +0 -110
- package/src/core/modules/framework-module-resolver.ts +0 -273
- package/src/islands/component-analysis.ts +0 -213
- package/src/islands/css-utils.ts +0 -565
- package/src/islands/discovery/index.ts +0 -80
- package/src/islands/discovery/registry.ts +0 -340
- package/src/islands/discovery/resolver.ts +0 -477
- package/src/islands/discovery/scanner.ts +0 -386
- package/src/islands/discovery/types.ts +0 -117
- package/src/islands/discovery/validator.ts +0 -544
- package/src/islands/discovery/watcher.ts +0 -368
- package/src/islands/framework-detection.ts +0 -428
- package/src/islands/integration-loader.ts +0 -490
- package/src/islands/island.tsx +0 -565
- package/src/islands/render-cache.ts +0 -550
- package/src/islands/types.ts +0 -80
- package/src/islands/universal-css-collector.ts +0 -157
- package/src/islands/universal-head-collector.ts +0 -137
- package/src/layout-system.ts +0 -218
- package/src/middleware/discovery.ts +0 -268
- package/src/middleware/executor.ts +0 -315
- package/src/middleware/index.ts +0 -76
- package/src/middleware/types.ts +0 -99
- package/src/nitro/build-config.ts +0 -576
- package/src/nitro/config.ts +0 -483
- package/src/nitro/error-handler.ts +0 -636
- package/src/nitro/index.ts +0 -173
- package/src/nitro/island-manifest.ts +0 -584
- package/src/nitro/middleware-adapter.ts +0 -260
- package/src/nitro/renderer.ts +0 -1471
- package/src/nitro/route-discovery.ts +0 -439
- package/src/nitro/types.ts +0 -321
- package/src/render/collect-css.ts +0 -198
- package/src/render/isolated-ssr-renderer.ts +0 -654
- package/src/render/ssr.ts +0 -1030
- package/src/schemas/api.ts +0 -30
- package/src/schemas/core.ts +0 -64
- package/src/schemas/index.ts +0 -212
- package/src/schemas/layout.ts +0 -279
- package/src/schemas/routing/index.ts +0 -38
- package/src/schemas/routing.ts +0 -376
- package/src/types/as-island.ts +0 -20
- package/src/types/layout.ts +0 -285
- package/src/types/routing.ts +0 -555
- package/src/types/types.ts +0 -5
- package/src/utils/dev-logger.ts +0 -299
- package/src/utils/fs.ts +0 -151
- package/src/vite-plugin/auto-discover.ts +0 -551
- package/src/vite-plugin/config.ts +0 -266
- package/src/vite-plugin/errors.ts +0 -127
- package/src/vite-plugin/image-optimization.ts +0 -156
- package/src/vite-plugin/integration-activator.ts +0 -126
- package/src/vite-plugin/island-sidecar-plugin.ts +0 -176
- package/src/vite-plugin/module-discovery.ts +0 -189
- package/src/vite-plugin/nitro-integration.ts +0 -1354
- package/src/vite-plugin/plugin.ts +0 -401
- package/src/vite-plugin/types.ts +0 -327
- package/src/vite-plugin/validation.ts +0 -228
|
@@ -1,636 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Nitro Error Handler for Avalon
|
|
3
|
-
*
|
|
4
|
-
* This module provides error handling utilities for the Nitro integration,
|
|
5
|
-
* including support for custom error pages (404, 500, _error).
|
|
6
|
-
*
|
|
7
|
-
* Custom error pages are discovered from the pages directory:
|
|
8
|
-
* - src/pages/404.tsx → Custom 404 page
|
|
9
|
-
* - src/pages/500.tsx → Custom 500 page
|
|
10
|
-
* - src/pages/_error.tsx → Generic error page (fallback)
|
|
11
|
-
*
|
|
12
|
-
* Requirements: 10.1, 10.2, 10.3, 10.4, 10.5
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import type { PageModule, NitroRenderContext, AvalonRuntimeConfig } from "./types.ts";
|
|
16
|
-
import type { H3Event } from "h3";
|
|
17
|
-
import { HttpError, isHttpError, createNotFoundError, createInternalError } from "./types.ts";
|
|
18
|
-
import { createRenderContext, getRequestURL } from "./renderer.ts";
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Error page props passed to custom error page components
|
|
22
|
-
*/
|
|
23
|
-
export interface ErrorPageProps {
|
|
24
|
-
/** HTTP status code */
|
|
25
|
-
statusCode: number;
|
|
26
|
-
/** Error message */
|
|
27
|
-
message: string;
|
|
28
|
-
/** Error object (development only) */
|
|
29
|
-
error?: Error;
|
|
30
|
-
/** Stack trace (development only) */
|
|
31
|
-
stack?: string;
|
|
32
|
-
/** Request URL that caused the error */
|
|
33
|
-
url?: string;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Options for error handling
|
|
38
|
-
*/
|
|
39
|
-
export interface ErrorHandlerOptions {
|
|
40
|
-
/** Whether running in development mode */
|
|
41
|
-
isDev?: boolean;
|
|
42
|
-
/** Avalon runtime configuration */
|
|
43
|
-
avalonConfig?: AvalonRuntimeConfig;
|
|
44
|
-
/** Custom page module loader */
|
|
45
|
-
loadPageModule?: (filePath: string) => Promise<PageModule>;
|
|
46
|
-
/** Pages directory path */
|
|
47
|
-
pagesDir?: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Cache for discovered error pages
|
|
52
|
-
*/
|
|
53
|
-
interface ErrorPageCache {
|
|
54
|
-
/** Custom 404 page module */
|
|
55
|
-
notFound?: PageModule | null;
|
|
56
|
-
/** Custom 500 page module */
|
|
57
|
-
serverError?: PageModule | null;
|
|
58
|
-
/** Generic error page module */
|
|
59
|
-
genericError?: PageModule | null;
|
|
60
|
-
/** Whether cache has been initialized */
|
|
61
|
-
initialized: boolean;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Module-level cache for error pages
|
|
65
|
-
let errorPageCache: ErrorPageCache = {
|
|
66
|
-
initialized: false,
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Clears the error page cache
|
|
71
|
-
* Call this during development when error pages change
|
|
72
|
-
*/
|
|
73
|
-
export function clearErrorPageCache(): void {
|
|
74
|
-
errorPageCache = {
|
|
75
|
-
initialized: false,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Discovers and caches custom error pages from the pages directory
|
|
81
|
-
*
|
|
82
|
-
* @param options - Error handler options
|
|
83
|
-
* @returns Object containing discovered error page modules
|
|
84
|
-
*/
|
|
85
|
-
export async function discoverErrorPages(
|
|
86
|
-
options: ErrorHandlerOptions
|
|
87
|
-
): Promise<ErrorPageCache> {
|
|
88
|
-
if (errorPageCache.initialized && !options.isDev) {
|
|
89
|
-
return errorPageCache;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const { loadPageModule, pagesDir = "src/pages" } = options;
|
|
93
|
-
|
|
94
|
-
if (!loadPageModule) {
|
|
95
|
-
errorPageCache.initialized = true;
|
|
96
|
-
return errorPageCache;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Try to load custom 404 page
|
|
100
|
-
try {
|
|
101
|
-
errorPageCache.notFound = await loadPageModule(`${pagesDir}/404.tsx`);
|
|
102
|
-
} catch {
|
|
103
|
-
// Try .jsx extension
|
|
104
|
-
try {
|
|
105
|
-
errorPageCache.notFound = await loadPageModule(`${pagesDir}/404.jsx`);
|
|
106
|
-
} catch {
|
|
107
|
-
errorPageCache.notFound = null;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Try to load custom 500 page
|
|
112
|
-
try {
|
|
113
|
-
errorPageCache.serverError = await loadPageModule(`${pagesDir}/500.tsx`);
|
|
114
|
-
} catch {
|
|
115
|
-
// Try .jsx extension
|
|
116
|
-
try {
|
|
117
|
-
errorPageCache.serverError = await loadPageModule(`${pagesDir}/500.jsx`);
|
|
118
|
-
} catch {
|
|
119
|
-
errorPageCache.serverError = null;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Try to load generic error page
|
|
124
|
-
try {
|
|
125
|
-
errorPageCache.genericError = await loadPageModule(`${pagesDir}/_error.tsx`);
|
|
126
|
-
} catch {
|
|
127
|
-
// Try .jsx extension
|
|
128
|
-
try {
|
|
129
|
-
errorPageCache.genericError = await loadPageModule(`${pagesDir}/_error.jsx`);
|
|
130
|
-
} catch {
|
|
131
|
-
errorPageCache.genericError = null;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
errorPageCache.initialized = true;
|
|
136
|
-
return errorPageCache;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Gets the appropriate error page module for a status code
|
|
141
|
-
*
|
|
142
|
-
* @param statusCode - HTTP status code
|
|
143
|
-
* @param cache - Error page cache
|
|
144
|
-
* @returns Error page module or null if no custom page exists
|
|
145
|
-
*/
|
|
146
|
-
export function getErrorPageModule(
|
|
147
|
-
statusCode: number,
|
|
148
|
-
cache: ErrorPageCache
|
|
149
|
-
): PageModule | null {
|
|
150
|
-
// Check for specific status code pages first
|
|
151
|
-
if (statusCode === 404 && cache.notFound) {
|
|
152
|
-
return cache.notFound;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (statusCode === 500 && cache.serverError) {
|
|
156
|
-
return cache.serverError;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Fall back to generic error page
|
|
160
|
-
if (cache.genericError) {
|
|
161
|
-
return cache.genericError;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return null;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Creates error page props from an error
|
|
169
|
-
*
|
|
170
|
-
* @param error - The error that occurred
|
|
171
|
-
* @param url - Request URL
|
|
172
|
-
* @param isDev - Whether running in development mode
|
|
173
|
-
* @returns Error page props
|
|
174
|
-
*/
|
|
175
|
-
export function createErrorPageProps(
|
|
176
|
-
error: Error | HttpError,
|
|
177
|
-
url?: string,
|
|
178
|
-
isDev?: boolean
|
|
179
|
-
): ErrorPageProps {
|
|
180
|
-
const statusCode = isHttpError(error) ? error.statusCode : 500;
|
|
181
|
-
|
|
182
|
-
const props: ErrorPageProps = {
|
|
183
|
-
statusCode,
|
|
184
|
-
message: error.message,
|
|
185
|
-
url,
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
// Include error details only in development
|
|
189
|
-
if (isDev) {
|
|
190
|
-
props.error = error;
|
|
191
|
-
props.stack = error.stack;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return props;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Renders a custom error page to HTML
|
|
199
|
-
*
|
|
200
|
-
* @param pageModule - The error page module
|
|
201
|
-
* @param props - Error page props
|
|
202
|
-
* @param context - Render context
|
|
203
|
-
* @param isDev - Whether running in development mode
|
|
204
|
-
* @returns Rendered HTML string
|
|
205
|
-
*/
|
|
206
|
-
export async function renderErrorPage(
|
|
207
|
-
pageModule: PageModule,
|
|
208
|
-
props: ErrorPageProps,
|
|
209
|
-
context: NitroRenderContext,
|
|
210
|
-
isDev: boolean
|
|
211
|
-
): Promise<string> {
|
|
212
|
-
// The page module's default export should be a component function
|
|
213
|
-
const Component = pageModule.default as (props: ErrorPageProps) => unknown;
|
|
214
|
-
|
|
215
|
-
if (typeof Component !== "function") {
|
|
216
|
-
// Fall back to default error page if component is invalid
|
|
217
|
-
return generateDefaultErrorPage(props.statusCode, props.message, isDev, props.stack);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
try {
|
|
221
|
-
// Render the component
|
|
222
|
-
// In a real implementation, this would use the SSR pipeline
|
|
223
|
-
// For now, we generate a basic HTML structure
|
|
224
|
-
const metadata = pageModule.metadata || {};
|
|
225
|
-
|
|
226
|
-
return `<!DOCTYPE html>
|
|
227
|
-
<html lang="en">
|
|
228
|
-
<head>
|
|
229
|
-
<meta charset="utf-8">
|
|
230
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
231
|
-
<title>${escapeHtml(String(metadata.title || `Error ${props.statusCode}`))}</title>
|
|
232
|
-
${metadata.description ? `<meta name="description" content="${escapeHtml(String(metadata.description))}">` : ""}
|
|
233
|
-
<style>
|
|
234
|
-
body {
|
|
235
|
-
font-family: system-ui, -apple-system, sans-serif;
|
|
236
|
-
margin: 0;
|
|
237
|
-
padding: 40px;
|
|
238
|
-
display: flex;
|
|
239
|
-
align-items: center;
|
|
240
|
-
justify-content: center;
|
|
241
|
-
min-height: 100vh;
|
|
242
|
-
box-sizing: border-box;
|
|
243
|
-
background: #f5f5f5;
|
|
244
|
-
}
|
|
245
|
-
.error-page {
|
|
246
|
-
text-align: center;
|
|
247
|
-
max-width: 600px;
|
|
248
|
-
}
|
|
249
|
-
h1 {
|
|
250
|
-
font-size: 48px;
|
|
251
|
-
margin: 0 0 20px 0;
|
|
252
|
-
color: #333;
|
|
253
|
-
}
|
|
254
|
-
p {
|
|
255
|
-
color: #666;
|
|
256
|
-
margin: 0 0 20px 0;
|
|
257
|
-
}
|
|
258
|
-
a {
|
|
259
|
-
color: #0066cc;
|
|
260
|
-
text-decoration: none;
|
|
261
|
-
}
|
|
262
|
-
a:hover {
|
|
263
|
-
text-decoration: underline;
|
|
264
|
-
}
|
|
265
|
-
details {
|
|
266
|
-
margin-top: 20px;
|
|
267
|
-
text-align: left;
|
|
268
|
-
}
|
|
269
|
-
pre {
|
|
270
|
-
background: #1a1a1a;
|
|
271
|
-
color: #e0e0e0;
|
|
272
|
-
padding: 15px;
|
|
273
|
-
border-radius: 4px;
|
|
274
|
-
overflow-x: auto;
|
|
275
|
-
font-size: 12px;
|
|
276
|
-
}
|
|
277
|
-
</style>
|
|
278
|
-
</head>
|
|
279
|
-
<body>
|
|
280
|
-
<div id="app" data-error-page="true" data-status-code="${props.statusCode}" data-props='${escapeHtml(JSON.stringify(props))}'>
|
|
281
|
-
<!-- Custom error page content rendered by Avalon SSR pipeline -->
|
|
282
|
-
<div class="error-page">
|
|
283
|
-
<h1>${props.statusCode}</h1>
|
|
284
|
-
<p>${escapeHtml(props.message)}</p>
|
|
285
|
-
${isDev && props.stack ? `
|
|
286
|
-
<details>
|
|
287
|
-
<summary>Error details</summary>
|
|
288
|
-
<pre>${escapeHtml(props.stack)}</pre>
|
|
289
|
-
</details>
|
|
290
|
-
` : ""}
|
|
291
|
-
<a href="/">Go back home</a>
|
|
292
|
-
</div>
|
|
293
|
-
</div>
|
|
294
|
-
</body>
|
|
295
|
-
</html>`;
|
|
296
|
-
} catch (renderError) {
|
|
297
|
-
console.error("[Error Page Render Error]", renderError);
|
|
298
|
-
// Fall back to default error page
|
|
299
|
-
return generateDefaultErrorPage(props.statusCode, props.message, isDev, props.stack);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Generates a default error page when no custom page is available
|
|
305
|
-
*
|
|
306
|
-
* @param statusCode - HTTP status code
|
|
307
|
-
* @param message - Error message
|
|
308
|
-
* @param isDev - Whether running in development mode
|
|
309
|
-
* @param stack - Stack trace (development only)
|
|
310
|
-
* @returns HTML string
|
|
311
|
-
*/
|
|
312
|
-
export function generateDefaultErrorPage(
|
|
313
|
-
statusCode: number,
|
|
314
|
-
message: string,
|
|
315
|
-
isDev: boolean,
|
|
316
|
-
stack?: string
|
|
317
|
-
): string {
|
|
318
|
-
if (isDev) {
|
|
319
|
-
return generateDevErrorPage(statusCode, message, stack);
|
|
320
|
-
}
|
|
321
|
-
return generateProdErrorPage(statusCode, message);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* Generates a development error page with full details
|
|
326
|
-
*/
|
|
327
|
-
function generateDevErrorPage(
|
|
328
|
-
statusCode: number,
|
|
329
|
-
message: string,
|
|
330
|
-
stack?: string
|
|
331
|
-
): string {
|
|
332
|
-
return `<!DOCTYPE html>
|
|
333
|
-
<html lang="en">
|
|
334
|
-
<head>
|
|
335
|
-
<meta charset="utf-8">
|
|
336
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
337
|
-
<title>Error ${statusCode}</title>
|
|
338
|
-
<style>
|
|
339
|
-
body {
|
|
340
|
-
font-family: system-ui, -apple-system, sans-serif;
|
|
341
|
-
margin: 0;
|
|
342
|
-
padding: 40px;
|
|
343
|
-
background: #1a1a1a;
|
|
344
|
-
color: #fff;
|
|
345
|
-
}
|
|
346
|
-
.error-container {
|
|
347
|
-
max-width: 800px;
|
|
348
|
-
margin: 0 auto;
|
|
349
|
-
background: #2d2d2d;
|
|
350
|
-
padding: 40px;
|
|
351
|
-
border-radius: 8px;
|
|
352
|
-
border-left: 4px solid #ff6b6b;
|
|
353
|
-
}
|
|
354
|
-
h1 {
|
|
355
|
-
color: #ff6b6b;
|
|
356
|
-
margin-top: 0;
|
|
357
|
-
font-size: 24px;
|
|
358
|
-
}
|
|
359
|
-
.status-code {
|
|
360
|
-
font-size: 48px;
|
|
361
|
-
font-weight: bold;
|
|
362
|
-
color: #ff6b6b;
|
|
363
|
-
margin-bottom: 10px;
|
|
364
|
-
}
|
|
365
|
-
.message {
|
|
366
|
-
font-size: 18px;
|
|
367
|
-
color: #ccc;
|
|
368
|
-
margin-bottom: 20px;
|
|
369
|
-
}
|
|
370
|
-
pre {
|
|
371
|
-
background: #1a1a1a;
|
|
372
|
-
padding: 20px;
|
|
373
|
-
border-radius: 4px;
|
|
374
|
-
overflow-x: auto;
|
|
375
|
-
font-size: 14px;
|
|
376
|
-
line-height: 1.5;
|
|
377
|
-
color: #e0e0e0;
|
|
378
|
-
}
|
|
379
|
-
.stack-title {
|
|
380
|
-
color: #888;
|
|
381
|
-
font-size: 12px;
|
|
382
|
-
text-transform: uppercase;
|
|
383
|
-
margin-bottom: 10px;
|
|
384
|
-
}
|
|
385
|
-
a {
|
|
386
|
-
color: #6b9fff;
|
|
387
|
-
text-decoration: none;
|
|
388
|
-
}
|
|
389
|
-
a:hover {
|
|
390
|
-
text-decoration: underline;
|
|
391
|
-
}
|
|
392
|
-
</style>
|
|
393
|
-
</head>
|
|
394
|
-
<body>
|
|
395
|
-
<div class="error-container">
|
|
396
|
-
<div class="status-code">${statusCode}</div>
|
|
397
|
-
<h1>${getStatusText(statusCode)}</h1>
|
|
398
|
-
<p class="message">${escapeHtml(message)}</p>
|
|
399
|
-
${stack ? `
|
|
400
|
-
<div class="stack-title">Stack Trace</div>
|
|
401
|
-
<pre>${escapeHtml(stack)}</pre>
|
|
402
|
-
` : ""}
|
|
403
|
-
<p><a href="/">← Return to home</a></p>
|
|
404
|
-
</div>
|
|
405
|
-
</body>
|
|
406
|
-
</html>`;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
/**
|
|
410
|
-
* Generates a production error page without sensitive details
|
|
411
|
-
*/
|
|
412
|
-
function generateProdErrorPage(statusCode: number, message: string): string {
|
|
413
|
-
// Use generic message for 500 errors in production
|
|
414
|
-
const displayMessage = statusCode >= 500
|
|
415
|
-
? "An unexpected error occurred. Please try again later."
|
|
416
|
-
: message;
|
|
417
|
-
|
|
418
|
-
return `<!DOCTYPE html>
|
|
419
|
-
<html lang="en">
|
|
420
|
-
<head>
|
|
421
|
-
<meta charset="utf-8">
|
|
422
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
423
|
-
<title>Error ${statusCode}</title>
|
|
424
|
-
<style>
|
|
425
|
-
body {
|
|
426
|
-
font-family: system-ui, -apple-system, sans-serif;
|
|
427
|
-
margin: 0;
|
|
428
|
-
padding: 40px;
|
|
429
|
-
background: #f5f5f5;
|
|
430
|
-
display: flex;
|
|
431
|
-
align-items: center;
|
|
432
|
-
justify-content: center;
|
|
433
|
-
min-height: 100vh;
|
|
434
|
-
box-sizing: border-box;
|
|
435
|
-
}
|
|
436
|
-
.error-container {
|
|
437
|
-
text-align: center;
|
|
438
|
-
max-width: 400px;
|
|
439
|
-
}
|
|
440
|
-
.status-code {
|
|
441
|
-
font-size: 72px;
|
|
442
|
-
font-weight: bold;
|
|
443
|
-
color: #333;
|
|
444
|
-
margin-bottom: 10px;
|
|
445
|
-
}
|
|
446
|
-
h1 {
|
|
447
|
-
color: #666;
|
|
448
|
-
font-size: 24px;
|
|
449
|
-
margin: 0 0 20px 0;
|
|
450
|
-
}
|
|
451
|
-
p {
|
|
452
|
-
color: #888;
|
|
453
|
-
margin: 0 0 20px 0;
|
|
454
|
-
}
|
|
455
|
-
a {
|
|
456
|
-
color: #0066cc;
|
|
457
|
-
text-decoration: none;
|
|
458
|
-
}
|
|
459
|
-
a:hover {
|
|
460
|
-
text-decoration: underline;
|
|
461
|
-
}
|
|
462
|
-
</style>
|
|
463
|
-
</head>
|
|
464
|
-
<body>
|
|
465
|
-
<div class="error-container">
|
|
466
|
-
<div class="status-code">${statusCode}</div>
|
|
467
|
-
<h1>${getStatusText(statusCode)}</h1>
|
|
468
|
-
<p>${escapeHtml(displayMessage)}</p>
|
|
469
|
-
<p><a href="/">Return to home</a></p>
|
|
470
|
-
</div>
|
|
471
|
-
</body>
|
|
472
|
-
</html>`;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
/**
|
|
476
|
-
* Gets the status text for an HTTP status code
|
|
477
|
-
*/
|
|
478
|
-
function getStatusText(statusCode: number): string {
|
|
479
|
-
const statusTexts: Record<number, string> = {
|
|
480
|
-
400: "Bad Request",
|
|
481
|
-
401: "Unauthorized",
|
|
482
|
-
403: "Forbidden",
|
|
483
|
-
404: "Page Not Found",
|
|
484
|
-
405: "Method Not Allowed",
|
|
485
|
-
408: "Request Timeout",
|
|
486
|
-
410: "Gone",
|
|
487
|
-
429: "Too Many Requests",
|
|
488
|
-
500: "Internal Server Error",
|
|
489
|
-
502: "Bad Gateway",
|
|
490
|
-
503: "Service Unavailable",
|
|
491
|
-
504: "Gateway Timeout",
|
|
492
|
-
};
|
|
493
|
-
return statusTexts[statusCode] || "Error";
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
/**
|
|
497
|
-
* Escapes HTML special characters
|
|
498
|
-
*/
|
|
499
|
-
function escapeHtml(str: string): string {
|
|
500
|
-
return str
|
|
501
|
-
.replaceAll('&', "&")
|
|
502
|
-
.replaceAll('<', "<")
|
|
503
|
-
.replaceAll('>', ">")
|
|
504
|
-
.replaceAll('"', """)
|
|
505
|
-
.replaceAll('\'', "'");
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
/**
|
|
509
|
-
* Handles a render error and returns an appropriate response
|
|
510
|
-
*
|
|
511
|
-
* This function:
|
|
512
|
-
* 1. Discovers custom error pages if available
|
|
513
|
-
* 2. Renders the appropriate error page (custom or default)
|
|
514
|
-
* 3. Returns a Response with the correct status code
|
|
515
|
-
*
|
|
516
|
-
* Requirements: 10.1, 10.2, 10.3, 10.4, 10.5
|
|
517
|
-
*
|
|
518
|
-
* @param error - The error that occurred
|
|
519
|
-
* @param event - H3 event
|
|
520
|
-
* @param options - Error handler options
|
|
521
|
-
* @returns Response with error page
|
|
522
|
-
*/
|
|
523
|
-
export async function handleRenderError(
|
|
524
|
-
error: Error | HttpError,
|
|
525
|
-
event: H3Event,
|
|
526
|
-
options: ErrorHandlerOptions
|
|
527
|
-
): Promise<Response> {
|
|
528
|
-
const { isDev = false } = options;
|
|
529
|
-
const statusCode = isHttpError(error) ? error.statusCode : 500;
|
|
530
|
-
const url = getRequestURL(event);
|
|
531
|
-
|
|
532
|
-
console.error(`[Render Error] ${statusCode} - ${error.message}`, {
|
|
533
|
-
url: url.pathname,
|
|
534
|
-
stack: isDev ? error.stack : undefined,
|
|
535
|
-
});
|
|
536
|
-
|
|
537
|
-
// Try to discover and use custom error pages
|
|
538
|
-
const errorPages = await discoverErrorPages(options);
|
|
539
|
-
const errorPageModule = getErrorPageModule(statusCode, errorPages);
|
|
540
|
-
|
|
541
|
-
let html: string;
|
|
542
|
-
|
|
543
|
-
if (errorPageModule) {
|
|
544
|
-
// Render custom error page
|
|
545
|
-
const props = createErrorPageProps(error, url.pathname, isDev);
|
|
546
|
-
const context = createRenderContext(event, {});
|
|
547
|
-
html = await renderErrorPage(errorPageModule, props, context, isDev);
|
|
548
|
-
} else {
|
|
549
|
-
// Use default error page
|
|
550
|
-
html = generateDefaultErrorPage(
|
|
551
|
-
statusCode,
|
|
552
|
-
error.message,
|
|
553
|
-
isDev,
|
|
554
|
-
isDev ? error.stack : undefined
|
|
555
|
-
);
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
return new Response(html, {
|
|
559
|
-
status: statusCode,
|
|
560
|
-
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
561
|
-
});
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
/**
|
|
565
|
-
* Handles an API error and returns an appropriate JSON response
|
|
566
|
-
*
|
|
567
|
-
* Requirements: 10.1, 10.2, 10.4
|
|
568
|
-
*
|
|
569
|
-
* @param error - The error that occurred
|
|
570
|
-
* @param options - Error handler options
|
|
571
|
-
* @returns Response with JSON error
|
|
572
|
-
*/
|
|
573
|
-
export function handleApiError(
|
|
574
|
-
error: Error | HttpError,
|
|
575
|
-
options: ErrorHandlerOptions
|
|
576
|
-
): Response {
|
|
577
|
-
const { isDev = false } = options;
|
|
578
|
-
const statusCode = isHttpError(error) ? error.statusCode : 500;
|
|
579
|
-
|
|
580
|
-
console.error(`[API Error] ${statusCode} - ${error.message}`, {
|
|
581
|
-
stack: isDev ? error.stack : undefined,
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
const body = isDev
|
|
585
|
-
? {
|
|
586
|
-
error: error.message,
|
|
587
|
-
statusCode,
|
|
588
|
-
stack: error.stack,
|
|
589
|
-
}
|
|
590
|
-
: {
|
|
591
|
-
error: statusCode >= 500 ? "Internal Server Error" : error.message,
|
|
592
|
-
statusCode,
|
|
593
|
-
};
|
|
594
|
-
|
|
595
|
-
return new Response(JSON.stringify(body), {
|
|
596
|
-
status: statusCode,
|
|
597
|
-
headers: { "Content-Type": "application/json" },
|
|
598
|
-
});
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
/**
|
|
602
|
-
* Creates a 404 Not Found response
|
|
603
|
-
*
|
|
604
|
-
* @param pathname - The requested path
|
|
605
|
-
* @param event - H3 event
|
|
606
|
-
* @param options - Error handler options
|
|
607
|
-
* @returns Response with 404 error page
|
|
608
|
-
*/
|
|
609
|
-
export async function handleNotFound(
|
|
610
|
-
pathname: string,
|
|
611
|
-
event: H3Event,
|
|
612
|
-
options: ErrorHandlerOptions
|
|
613
|
-
): Promise<Response> {
|
|
614
|
-
const error = createNotFoundError(`Page not found: ${pathname}`);
|
|
615
|
-
return handleRenderError(error, event, options);
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
/**
|
|
619
|
-
* Creates a 500 Internal Server Error response
|
|
620
|
-
*
|
|
621
|
-
* @param error - The original error
|
|
622
|
-
* @param event - H3 event
|
|
623
|
-
* @param options - Error handler options
|
|
624
|
-
* @returns Response with 500 error page
|
|
625
|
-
*/
|
|
626
|
-
export async function handleInternalError(
|
|
627
|
-
error: Error,
|
|
628
|
-
event: H3Event,
|
|
629
|
-
options: ErrorHandlerOptions
|
|
630
|
-
): Promise<Response> {
|
|
631
|
-
const httpError = createInternalError(error.message);
|
|
632
|
-
// Preserve the original stack trace
|
|
633
|
-
httpError.stack = error.stack;
|
|
634
|
-
return handleRenderError(httpError, event, options);
|
|
635
|
-
}
|
|
636
|
-
|