@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{LayoutDiscovery}from"./core/layout/layout-discovery.js";export{LayoutDataLoader,LayoutDataLoadingError,loadSingleLayoutData,mergeLayoutData,getParentLayoutData,defaultLayoutDataLoader}from"./core/layout/layout-data-loader.js";export{LayoutMatcher as LayoutMatcherClass,BuiltInLayoutRules}from"./core/layout/layout-matcher.js";export{LayoutComposer}from"./core/layout/layout-composer.js";export{EnhancedLayoutResolver,createEnhancedLayoutResolver,EnhancedLayoutResolverUtils}from"./core/layout/enhanced-layout-resolver.js";export{IslandPersistence,defaultIslandPersistence}from"./core/islands/island-persistence.js";export{IslandStateSerializer}from"./core/islands/island-state-serializer.js";export{createPersistentIslandContext,usePersistentIslandContext,PersistentIslandProvider}from"./core/islands/persistent-island-context.js";export{PersistentIsland}from"./components/PersistentIsland.js";export{LayoutErrorBoundary}from"./components/LayoutErrorBoundary.js";export{LayoutDataErrorBoundary}from"./components/LayoutDataErrorBoundary.js";export{IslandErrorBoundary,withIslandErrorBoundary}from"./components/IslandErrorBoundary.js";export{StreamingErrorBoundary,withStreamingErrorBoundary}from"./components/StreamingErrorBoundary.js";export{StreamingLayout,StreamingSuspense,withStreaming,useStreamingState}from"./components/StreamingLayout.js";export{LayoutCacheManager}from"./core/layout/layout-cache-manager.js";export{LayoutContextSchema,LayoutDataSchema,LayoutRouteSchema,LayoutHandlerSchema,LayoutPropsSchema,LayoutDiscoveryOptionsSchema,RouteInfoSchema,LayoutRuleSchema,LayoutConfigSchema,IslandStateSchema,PersistentIslandPropsSchema,PersistentIslandContextSchema,LayoutErrorInfoSchema,LayoutErrorBoundaryPropsSchema,ErrorRecoveryStrategySchema,StreamingLayoutPropsSchema,StreamingComponentSchema,ResolvedLayoutSchema,LayoutCacheSchema,EnhancedLayoutContextSchema}from"./schemas/layout.js";export{EnhancedLayoutResolver as LayoutSystem}from"./core/layout/enhanced-layout-resolver.js";export{defaultIslandPersistence as defaultPersistence}from"./core/islands/island-persistence.js";export{createEnhancedLayoutResolver as createLayoutSystem}from"./core/layout/enhanced-layout-resolver.js";export const LAYOUT_SYSTEM_VERSION=`1.0.0`;export const LAYOUT_SYSTEM_FEATURES={DISCOVERY:!0,DATA_LOADING:!0,CONDITIONAL_RENDERING:!0,COMPOSITION_CONTROL:!0,PERSISTENT_ISLANDS:!0,ERROR_BOUNDARIES:!0,STREAMING:!0,CACHING:!0,PERFORMANCE_MONITORING:!0,DEBUG_UTILITIES:!0};export const LAYOUT_SYSTEM_DEFAULTS={DISCOVERY:{baseDirectory:`src/pages`,filePattern:`_layout.tsx`,excludeDirectories:[`node_modules`,`.git`,`dist`],enableWatching:!1,developmentMode:!1},CACHING:{enabled:!0,ttl:3e5,maxSize:100,cleanupInterval:6e4},STREAMING:{enabled:!0,priority:`medium`,timeout:5e3},ERROR_BOUNDARIES:{enabled:!0,maxRetries:3,fallbackStrategy:`component`},PERFORMANCE:{monitoring:!0,thresholds:{discoveryTime:100,dataLoadingTime:500,renderingTime:200,totalTime:1e3}}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{join as e,relative as t,resolve as n}from"node:path";import{stat as r,readdir as i}from"node:fs/promises";const a={filePattern:`_middleware.ts`,excludeDirs:[`node_modules`,`.git`,`dist`,`.output`,`.vite`],devMode:!1},o={pages:50};export async function discoverScopedMiddleware(t){let{baseDir:r,filePattern:i=a.filePattern,excludeDirs:o=a.excludeDirs,devMode:s=a.devMode}=t,l=n(r),u=[];if(await c(e(l,`pages`),`pages`,i,o,u,s),u.sort((e,t)=>e.priority-t.priority),s&&u.length>0){console.log(`[middleware] Discovered ${u.length} route-scoped middleware:`);for(let e of u)console.log(` - ${e.type}: ${e.filePath} (priority: ${e.priority})`)}return u}async function c(e,t,n,i,a,o){try{if(!(await r(e).catch(()=>null))?.isDirectory())return;await l(e,e,t,n,i,a,o)}catch(t){o&&(!(t instanceof Error)||t.code!==`ENOENT`)&&console.warn(`[middleware] Error scanning ${e}: ${t instanceof Error?t.message:String(t)}`)}}async function l(n,r,a,o,s,c,d){try{let f=await i(r,{withFileTypes:!0});for(let i of f){let f=e(r,i.name);if(!(i.isDirectory()&&s.includes(i.name))){if(i.isDirectory())await l(n,f,a,o,s,c,d);else if(i.name===o){let e=u(f,t(n,r),a);c.push(e)}}}}catch(e){d&&(!(e instanceof Error)||e.code!==`ENOENT`)&&console.warn(`[middleware] Error reading ${r}: ${e instanceof Error?e.message:String(e)}`)}}function u(e,t,n){let r=t?`/${t}{/*}?`:`/*`,i=t?t.split(`/`).filter(Boolean).length:0,a=o[n]+i;return{pattern:new URLPattern({pathname:r}),filePath:e,priority:a,type:n}}export function getMatchingMiddleware(e,t){let n=t.pathname.startsWith(`/api`);return e.filter(e=>!(!e.pattern.test(t)||e.type===`pages`&&n))}export function clearDiscoveryCache(){}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getMatchingMiddleware as e}from"./discovery.js";function t(e){let t=new Map;for(let n of Object.keys(e))t.set(n,e[n]);return t}function n(e,t){let n=[],r=[],i=[];for(let i of Object.keys(t))e.has(i)?e.get(i)!==t[i]&&r.push(i):n.push(i);for(let n of e.keys())n in t||i.push(n);return{added:n,modified:r,removed:i}}const r={devMode:!1,timeout:3e4},i=new Map;async function a(e,r,i,a){let o=await l(r.filePath,i);if(!o)return;let s=i?t(e.context):null,c=await u(()=>o(e),a,r.filePath);i&&s&&(n(s,e.context),r.filePath);let f=d(c,r.filePath,i);return f&&i&&console.log(`[middleware] Chain terminated by ${r.filePath}`),f}export async function executeScopedMiddleware(t,n,i={}){let{devMode:o,timeout:c}={...r,...i},l=e(n,s(t));if(l.length!==0)for(let e of l)try{let n=await a(t,e,o,c);if(n)return n}catch(t){throw o&&console.error(`[middleware] Error in ${e.filePath}:`,t),t}}function s(e){let t=`http://localhost`;return typeof e.url==`string`?new URL(e.url,t):e.req?.url?new URL(e.req.url,t):e.path?new URL(e.path,t):e.node?.req?.url?new URL(e.node.req.url,t):new URL(`/`,t)}export function toImportSpecifier(e){return/^[A-Za-z]:[\\/]/.test(e)?`file:///${e.replaceAll(`\\`,`/`)}`:e}async function l(e,t){if(!t&&i.has(e))return i.get(e);try{let n,r=globalThis.__viteDevServer;if(t&&r){let t=r.config.root||``,i=e.startsWith(t)?`/`+e.slice(t.length+1):e;n=await r.ssrLoadModule(i)}else n=await import(toImportSpecifier(e));return!n.default||typeof n.default!=`function`?(t&&console.warn(`[middleware] ${e} does not export a default function`),null):(t||i.set(e,n.default),n.default)}catch(n){return t&&console.error(`[middleware] Failed to load ${e}:`,n),null}}async function u(e,t,n){return Promise.race([Promise.resolve(e()),new Promise((e,r)=>{setTimeout(()=>{r(Error(`Middleware timeout after ${t}ms: ${n}`))},t)})])}function d(e,t,n){if(e!=null){if(e instanceof Response)return e;n&&console.warn(`[middleware] ${t} returned unexpected value: ${typeof e}. Expected void or Response.`)}}export function clearMiddlewareCache(){i.clear()}export function invalidateMiddleware(e){return i.delete(e)}export function getMiddlewareCacheSize(){return i.size}export function hasContextValue(e,t){return t in e.context}export function getContextValue(e,t){return e.context[t]}export function setContextValue(e,t,n,r=!1){let i=!(t in e.context);e.context[t]=n,r&&console.log(`[middleware] Context ${i?`set`:`updated`}: ${t}`)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{discoverScopedMiddleware,getMatchingMiddleware,clearDiscoveryCache}from"./discovery.js";export{executeScopedMiddleware,clearMiddlewareCache,invalidateMiddleware,getMiddlewareCacheSize,hasContextValue,getContextValue,setContextValue}from"./executor.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DEFAULT_NITRO_CONFIG as e,VALID_V3_PRESETS as t}from"./config.js";export const DEFAULT_BUILD_CONFIG={mode:`both`,clientOutDir:`dist/client`,serverOutDir:`dist/server`,sourcemap:!0,minify:`oxc`,target:`es2020`,ssr:!0,preset:`node_server`,verbose:!1};export const PRESET_OUTPUT_CONFIGS={node_server:{outputDir:`.output`,serverEntry:`server/index.mjs`,supportsStreaming:!0,bundleDependencies:!1},node_middleware:{outputDir:`.output`,serverEntry:`server/index.mjs`,supportsStreaming:!0,bundleDependencies:!1},vercel:{outputDir:`.vercel/output`,serverEntry:`functions/render.func/index.mjs`,supportsStreaming:!0,bundleDependencies:!0,additionalFiles:[`config.json`]},cloudflare_module:{outputDir:`dist`,serverEntry:`server/index.mjs`,supportsStreaming:!1,bundleDependencies:!0},cloudflare_pages:{outputDir:`dist`,serverEntry:`_worker.js`,supportsStreaming:!1,bundleDependencies:!0,additionalFiles:[`_routes.json`]},deno_deploy:{outputDir:`.output`,serverEntry:`server/index.ts`,supportsStreaming:!0,bundleDependencies:!1},deno_server:{outputDir:`.output`,serverEntry:`server/index.ts`,supportsStreaming:!0,bundleDependencies:!1},netlify_functions:{outputDir:`.netlify`,serverEntry:`functions-internal/render.mjs`,supportsStreaming:!0,bundleDependencies:!0},netlify_edge:{outputDir:`.netlify/edge-functions`,serverEntry:`render.js`,supportsStreaming:!0,bundleDependencies:!0},aws_lambda:{outputDir:`.output`,serverEntry:`server/index.mjs`,supportsStreaming:!1,bundleDependencies:!0},azure_swa:{outputDir:`.output`,serverEntry:`server/index.mjs`,supportsStreaming:!1,bundleDependencies:!0},firebase_functions:{outputDir:`.output`,serverEntry:`server/index.mjs`,supportsStreaming:!0,bundleDependencies:!0},render_com:{outputDir:`.output`,serverEntry:`server/index.mjs`,supportsStreaming:!0,bundleDependencies:!1},static:{outputDir:`dist`,serverEntry:``,supportsStreaming:!1,bundleDependencies:!1},browser:{outputDir:`dist`,serverEntry:``,supportsStreaming:!1,bundleDependencies:!0}};export function createClientBuildConfig(e,t={}){let r={...DEFAULT_BUILD_CONFIG,...t};return{outDir:r.clientOutDir,emptyOutDir:!0,sourcemap:r.sourcemap,minify:r.minify,target:r.target,rolldownOptions:{output:{entryFileNames:`[name].[hash].js`,chunkFileNames:`chunks/[name].[hash].js`,assetFileNames:`assets/[name].[hash].[ext]`,codeSplitting:{groups:[{name:`vendor-react`,test:/node_modules\/(react|react-dom)/},{name:`vendor-vue`,test:/node_modules\/(vue|@vue)/},{name:`vendor-svelte`,test:/node_modules\/svelte/},{name:`vendor-preact`,test:/node_modules\/preact/},{name:`vendor-solid`,test:/node_modules\/solid-js/},{name:`vendor-lit`,test:/node_modules\/(lit|@lit)/},{name:`vendor`,test:/node_modules/},{name:`islands`,test:/\/islands\//}]}}},reportCompressedSize:!e.isDev,cssCodeSplit:!0}}export function createServerBuildConfig(t,i,a={}){let s={...DEFAULT_BUILD_CONFIG,...a},c=i.preset??e.preset,l=PRESET_OUTPUT_CONFIGS[c]??PRESET_OUTPUT_CONFIGS.node_server;return{outDir:s.serverOutDir,emptyOutDir:!0,sourcemap:s.sourcemap,minify:s.minify,target:s.target,ssr:!0,rolldownOptions:{input:{index:`./server/index.ts`},output:{format:`esm`,entryFileNames:`[name].mjs`,chunkFileNames:`chunks/[name].[hash].mjs`,preserveModules:!l.bundleDependencies},external:l.bundleDependencies?[]:o(c)}}}function o(e){let t=[/^node:/,/^deno:/];switch(e){case`deno_deploy`:case`deno_server`:return[...t];case`node_server`:return[...t,/^[a-z@]/i];default:return t}}export function getPresetOutputConfig(e){return PRESET_OUTPUT_CONFIGS[e]??PRESET_OUTPUT_CONFIGS.node_server}export function presetSupportsStreaming(e){return getPresetOutputConfig(e).supportsStreaming}export function createCombinedBuildConfig(t,n,r={}){let a=n.preset??e.preset,o=getPresetOutputConfig(a);return{build:{...createClientBuildConfig(t,r),outDir:o.outputDir},define:{__DEV__:!1,__PROD__:!0,"process.env.NODE_ENV":JSON.stringify(`production`),...u(a,o)}}}function u(e,t){let n={__NITRO_PRESET__:JSON.stringify(e),__SUPPORTS_STREAMING__:JSON.stringify(t.supportsStreaming)};if(t.env)for(let[e,r]of Object.entries(t.env))n[`process.env.${e}`]=JSON.stringify(r);return n}export function createNitroBuildPlugin(t,n){let r=n.preset??e.preset,i=getPresetOutputConfig(r);return{name:`avalon:nitro-build`,enforce:`post`,config(e,{command:r}){if(r===`build`)return createCombinedBuildConfig(t,n,{sourcemap:!0,verbose:t.verbose})},buildStart(){t.verbose&&(console.log(`🚀 Avalon Nitro build starting...`),console.log(` Preset: ${r}`),console.log(` Output: ${i.outputDir}`),console.log(` Streaming: ${i.supportsStreaming}`))},writeBundle(){t.verbose&&console.log(`✅ Avalon client build complete`)},closeBundle(){t.verbose&&(console.log(`📦 Avalon build finished`),console.log(` Output directory: ${i.outputDir}`))}}}export function validateBuildConfig(e){let n=[];return e.preset&&(t.includes(e.preset)||n.push(`Unknown preset: ${e.preset}. Valid presets: ${t.join(`, `)}`)),e.mode&&![`client`,`server`,`both`].includes(e.mode)&&n.push(`Invalid build mode: ${e.mode}. Must be 'client', 'server', or 'both'`),e.sourcemap!==void 0&&typeof e.sourcemap!=`boolean`&&![`inline`,`hidden`].includes(e.sourcemap)&&n.push(`Invalid sourcemap option: ${e.sourcemap}`),{valid:n.length===0,errors:n}}export const DEFAULT_SOURCEMAP_CONFIG={enabled:!0,type:!0,includeContent:!0};export function createSourceMapConfig(e,t){return t?{enabled:!0,type:!0,includeContent:!0}:e.includes(`edge`)||e.includes(`cloudflare`)||e.includes(`lambda`)?{enabled:!0,type:`hidden`,includeContent:!1}:{enabled:!0,type:!0,includeContent:!0}}export function getViteSourceMapOption(e){return e.enabled?e.type:!1}export function createSourceMapPlugin(e){return{name:`avalon:sourcemap`,enforce:`post`,config(t,{command:n}){if(n===`build`)return{build:{sourcemap:getViteSourceMapOption(e)},...e.sourceRoot&&{rolldownOptions:{output:{sourcemapPathTransform:t=>`${e.sourceRoot}/${t}`}}}}},generateBundle(t,n){if(!e.enabled)return;let r=Object.keys(n).filter(e=>e.endsWith(`.map`)).length;r>0&&globalThis.__avalonConfig?.verbose&&console.log(`📍 Generated ${r} source map(s)`)}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const DEFAULT_STATIC_ASSETS_CONFIG={publicDir:`public`,buildDir:`dist`,compression:!0,cacheControl:`public, max-age=31536000, immutable`,mutableCacheControl:`public, max-age=0, must-revalidate`,headers:{}};export const VALID_V3_PRESETS=[`node_server`,`node_middleware`,`vercel`,`cloudflare_module`,`cloudflare_pages`,`deno_deploy`,`deno_server`,`netlify_functions`,`netlify_edge`,`aws_lambda`,`azure_swa`,`firebase_functions`,`render_com`,`static`,`browser`];export function resolvePresetName(e){if(VALID_V3_PRESETS.includes(e))return e;throw Error(`Unknown Nitro preset: "${e}". Valid presets: ${VALID_V3_PRESETS.join(`, `)}`)}export const DEFAULT_NITRO_CONFIG={preset:`node_server`,serverDir:`server`,streaming:!0};export function createNitroConfig(t,i){let a=t.pagesDir??i.pagesDir,o=i.layoutsDir,s={streaming:t.streaming??DEFAULT_NITRO_CONFIG.streaming,pagesDir:a,layoutsDir:o};if(t.runtimeConfig&&`nitro`in t.runtimeConfig)throw Error(`The "nitro" key in runtimeConfig is reserved by Nitro v3 and cannot be used.`);let c={avalon:s,...t.runtimeConfig},l={...DEFAULT_STATIC_ASSETS_CONFIG,...t.staticAssets},u=mergeRouteRules(createDefaultStaticAssetRouteRules(l),t.routeRules??{}),d=[{dir:l.publicDir??DEFAULT_STATIC_ASSETS_CONFIG.publicDir,baseURL:`/`,maxAge:0}],f=t.renderer===!1?!1:t.renderer??{handler:`./server/renderer.ts`};return{preset:resolvePresetName(t.preset??DEFAULT_NITRO_CONFIG.preset),serverDir:t.serverDir??DEFAULT_NITRO_CONFIG.serverDir,routeRules:u,runtimeConfig:c,publicRuntimeConfig:t.publicRuntimeConfig,renderer:f,compatibilityDate:t.compatibilityDate,traceDeps:t.traceDeps,rolldownConfig:t.rolldownConfig,serverEntry:t.serverEntry,compressPublicAssets:t.compressPublicAssets,publicAssets:d,staticAssets:l}}export function createDefaultStaticAssetRouteRules(t){let n=t.cacheControl??DEFAULT_STATIC_ASSETS_CONFIG.cacheControl,r=t.mutableCacheControl??DEFAULT_STATIC_ASSETS_CONFIG.mutableCacheControl;return{"/assets/**":{headers:{"Cache-Control":n,...t.headers}},"/islands/**":{headers:{"Cache-Control":n,...t.headers}},"/chunks/**":{headers:{"Cache-Control":n,...t.headers}},"/_nuxt/**":{headers:{"Cache-Control":n,...t.headers}},"/**/*.woff":{headers:{"Cache-Control":n,...t.headers}},"/**/*.woff2":{headers:{"Cache-Control":n,...t.headers}},"/**/*.html":{headers:{"Cache-Control":r,...t.headers}},"/favicon.ico":{headers:{"Cache-Control":`public, max-age=86400`,...t.headers}},"/**/*.css":{headers:{"Cache-Control":r,...t.headers}}}}export function isValidPreset(e){return VALID_V3_PRESETS.includes(e)}export function mergeRouteRules(e,t){let n={...e};for(let[e,r]of Object.entries(t))n[e]?n[e]={...n[e],...r,headers:{...n[e].headers,...r.headers}}:n[e]=r;return n}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import{isHttpError as e,createNotFoundError as t,createInternalError as n}from"./types.js";import{createRenderContext as r,getRequestURL as i}from"./renderer.js";let a={initialized:!1};export function clearErrorPageCache(){a={initialized:!1}}export async function discoverErrorPages(e){if(a.initialized&&!e.isDev)return a;let{loadPageModule:t,pagesDir:n=`src/pages`}=e;if(!t)return a.initialized=!0,a;try{a.notFound=await t(`${n}/404.tsx`)}catch{try{a.notFound=await t(`${n}/404.jsx`)}catch{a.notFound=null}}try{a.serverError=await t(`${n}/500.tsx`)}catch{try{a.serverError=await t(`${n}/500.jsx`)}catch{a.serverError=null}}try{a.genericError=await t(`${n}/_error.tsx`)}catch{try{a.genericError=await t(`${n}/_error.jsx`)}catch{a.genericError=null}}return a.initialized=!0,a}export function getErrorPageModule(e,t){return e===404&&t.notFound?t.notFound:e===500&&t.serverError?t.serverError:t.genericError?t.genericError:null}export function createErrorPageProps(t,n,r){let i={statusCode:e(t)?t.statusCode:500,message:t.message,url:n};return r&&(i.error=t,i.stack=t.stack),i}export async function renderErrorPage(e,t,n,r){if(typeof e.default!=`function`)return generateDefaultErrorPage(t.statusCode,t.message,r,t.stack);try{let n=e.metadata||{};return`<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>${u(String(n.title||`Error ${t.statusCode}`))}</title>
|
|
7
|
+
${n.description?`<meta name="description" content="${u(String(n.description))}">`:``}
|
|
8
|
+
<style>
|
|
9
|
+
body {
|
|
10
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding: 40px;
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
min-height: 100vh;
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
background: #f5f5f5;
|
|
19
|
+
}
|
|
20
|
+
.error-page {
|
|
21
|
+
text-align: center;
|
|
22
|
+
max-width: 600px;
|
|
23
|
+
}
|
|
24
|
+
h1 {
|
|
25
|
+
font-size: 48px;
|
|
26
|
+
margin: 0 0 20px 0;
|
|
27
|
+
color: #333;
|
|
28
|
+
}
|
|
29
|
+
p {
|
|
30
|
+
color: #666;
|
|
31
|
+
margin: 0 0 20px 0;
|
|
32
|
+
}
|
|
33
|
+
a {
|
|
34
|
+
color: #0066cc;
|
|
35
|
+
text-decoration: none;
|
|
36
|
+
}
|
|
37
|
+
a:hover {
|
|
38
|
+
text-decoration: underline;
|
|
39
|
+
}
|
|
40
|
+
details {
|
|
41
|
+
margin-top: 20px;
|
|
42
|
+
text-align: left;
|
|
43
|
+
}
|
|
44
|
+
pre {
|
|
45
|
+
background: #1a1a1a;
|
|
46
|
+
color: #e0e0e0;
|
|
47
|
+
padding: 15px;
|
|
48
|
+
border-radius: 4px;
|
|
49
|
+
overflow-x: auto;
|
|
50
|
+
font-size: 12px;
|
|
51
|
+
}
|
|
52
|
+
</style>
|
|
53
|
+
</head>
|
|
54
|
+
<body>
|
|
55
|
+
<div id="app" data-error-page="true" data-status-code="${t.statusCode}" data-props='${u(JSON.stringify(t))}'>
|
|
56
|
+
<!-- Custom error page content rendered by Avalon SSR pipeline -->
|
|
57
|
+
<div class="error-page">
|
|
58
|
+
<h1>${t.statusCode}</h1>
|
|
59
|
+
<p>${u(t.message)}</p>
|
|
60
|
+
${r&&t.stack?`
|
|
61
|
+
<details>
|
|
62
|
+
<summary>Error details</summary>
|
|
63
|
+
<pre>${u(t.stack)}</pre>
|
|
64
|
+
</details>
|
|
65
|
+
`:``}
|
|
66
|
+
<a href="/">Go back home</a>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</body>
|
|
70
|
+
</html>`}catch(e){return console.error(`[Error Page Render Error]`,e),generateDefaultErrorPage(t.statusCode,t.message,r,t.stack)}}export function generateDefaultErrorPage(e,t,n,r){return n?s(e,t,r):c(e,t)}function s(e,t,n){return`<!DOCTYPE html>
|
|
71
|
+
<html lang="en">
|
|
72
|
+
<head>
|
|
73
|
+
<meta charset="utf-8">
|
|
74
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
75
|
+
<title>Error ${e}</title>
|
|
76
|
+
<style>
|
|
77
|
+
body {
|
|
78
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
79
|
+
margin: 0;
|
|
80
|
+
padding: 40px;
|
|
81
|
+
background: #1a1a1a;
|
|
82
|
+
color: #fff;
|
|
83
|
+
}
|
|
84
|
+
.error-container {
|
|
85
|
+
max-width: 800px;
|
|
86
|
+
margin: 0 auto;
|
|
87
|
+
background: #2d2d2d;
|
|
88
|
+
padding: 40px;
|
|
89
|
+
border-radius: 8px;
|
|
90
|
+
border-left: 4px solid #ff6b6b;
|
|
91
|
+
}
|
|
92
|
+
h1 {
|
|
93
|
+
color: #ff6b6b;
|
|
94
|
+
margin-top: 0;
|
|
95
|
+
font-size: 24px;
|
|
96
|
+
}
|
|
97
|
+
.status-code {
|
|
98
|
+
font-size: 48px;
|
|
99
|
+
font-weight: bold;
|
|
100
|
+
color: #ff6b6b;
|
|
101
|
+
margin-bottom: 10px;
|
|
102
|
+
}
|
|
103
|
+
.message {
|
|
104
|
+
font-size: 18px;
|
|
105
|
+
color: #ccc;
|
|
106
|
+
margin-bottom: 20px;
|
|
107
|
+
}
|
|
108
|
+
pre {
|
|
109
|
+
background: #1a1a1a;
|
|
110
|
+
padding: 20px;
|
|
111
|
+
border-radius: 4px;
|
|
112
|
+
overflow-x: auto;
|
|
113
|
+
font-size: 14px;
|
|
114
|
+
line-height: 1.5;
|
|
115
|
+
color: #e0e0e0;
|
|
116
|
+
}
|
|
117
|
+
.stack-title {
|
|
118
|
+
color: #888;
|
|
119
|
+
font-size: 12px;
|
|
120
|
+
text-transform: uppercase;
|
|
121
|
+
margin-bottom: 10px;
|
|
122
|
+
}
|
|
123
|
+
a {
|
|
124
|
+
color: #6b9fff;
|
|
125
|
+
text-decoration: none;
|
|
126
|
+
}
|
|
127
|
+
a:hover {
|
|
128
|
+
text-decoration: underline;
|
|
129
|
+
}
|
|
130
|
+
</style>
|
|
131
|
+
</head>
|
|
132
|
+
<body>
|
|
133
|
+
<div class="error-container">
|
|
134
|
+
<div class="status-code">${e}</div>
|
|
135
|
+
<h1>${l(e)}</h1>
|
|
136
|
+
<p class="message">${u(t)}</p>
|
|
137
|
+
${n?`
|
|
138
|
+
<div class="stack-title">Stack Trace</div>
|
|
139
|
+
<pre>${u(n)}</pre>
|
|
140
|
+
`:``}
|
|
141
|
+
<p><a href="/">← Return to home</a></p>
|
|
142
|
+
</div>
|
|
143
|
+
</body>
|
|
144
|
+
</html>`}function c(e,t){let n=e>=500?`An unexpected error occurred. Please try again later.`:t;return`<!DOCTYPE html>
|
|
145
|
+
<html lang="en">
|
|
146
|
+
<head>
|
|
147
|
+
<meta charset="utf-8">
|
|
148
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
149
|
+
<title>Error ${e}</title>
|
|
150
|
+
<style>
|
|
151
|
+
body {
|
|
152
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
153
|
+
margin: 0;
|
|
154
|
+
padding: 40px;
|
|
155
|
+
background: #f5f5f5;
|
|
156
|
+
display: flex;
|
|
157
|
+
align-items: center;
|
|
158
|
+
justify-content: center;
|
|
159
|
+
min-height: 100vh;
|
|
160
|
+
box-sizing: border-box;
|
|
161
|
+
}
|
|
162
|
+
.error-container {
|
|
163
|
+
text-align: center;
|
|
164
|
+
max-width: 400px;
|
|
165
|
+
}
|
|
166
|
+
.status-code {
|
|
167
|
+
font-size: 72px;
|
|
168
|
+
font-weight: bold;
|
|
169
|
+
color: #333;
|
|
170
|
+
margin-bottom: 10px;
|
|
171
|
+
}
|
|
172
|
+
h1 {
|
|
173
|
+
color: #666;
|
|
174
|
+
font-size: 24px;
|
|
175
|
+
margin: 0 0 20px 0;
|
|
176
|
+
}
|
|
177
|
+
p {
|
|
178
|
+
color: #888;
|
|
179
|
+
margin: 0 0 20px 0;
|
|
180
|
+
}
|
|
181
|
+
a {
|
|
182
|
+
color: #0066cc;
|
|
183
|
+
text-decoration: none;
|
|
184
|
+
}
|
|
185
|
+
a:hover {
|
|
186
|
+
text-decoration: underline;
|
|
187
|
+
}
|
|
188
|
+
</style>
|
|
189
|
+
</head>
|
|
190
|
+
<body>
|
|
191
|
+
<div class="error-container">
|
|
192
|
+
<div class="status-code">${e}</div>
|
|
193
|
+
<h1>${l(e)}</h1>
|
|
194
|
+
<p>${u(n)}</p>
|
|
195
|
+
<p><a href="/">Return to home</a></p>
|
|
196
|
+
</div>
|
|
197
|
+
</body>
|
|
198
|
+
</html>`}function l(e){return{400:`Bad Request`,401:`Unauthorized`,403:`Forbidden`,404:`Page Not Found`,405:`Method Not Allowed`,408:`Request Timeout`,410:`Gone`,429:`Too Many Requests`,500:`Internal Server Error`,502:`Bad Gateway`,503:`Service Unavailable`,504:`Gateway Timeout`}[e]||`Error`}function u(e){return e.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`>`,`>`).replaceAll(`"`,`"`).replaceAll(`'`,`'`)}export async function handleRenderError(t,n,a){let{isDev:o=!1}=a,s=e(t)?t.statusCode:500,c=i(n);console.error(`[Render Error] ${s} - ${t.message}`,{url:c.pathname,stack:o?t.stack:void 0});let l=getErrorPageModule(s,await discoverErrorPages(a)),u;return u=l?await renderErrorPage(l,createErrorPageProps(t,c.pathname,o),r(n,{}),o):generateDefaultErrorPage(s,t.message,o,o?t.stack:void 0),new Response(u,{status:s,headers:{"Content-Type":`text/html; charset=utf-8`}})}export function handleApiError(t,n){let{isDev:r=!1}=n,i=e(t)?t.statusCode:500;console.error(`[API Error] ${i} - ${t.message}`,{stack:r?t.stack:void 0});let a=r?{error:t.message,statusCode:i,stack:t.stack}:{error:i>=500?`Internal Server Error`:t.message,statusCode:i};return new Response(JSON.stringify(a),{status:i,headers:{"Content-Type":`application/json`}})}export async function handleNotFound(e,n,r){return handleRenderError(t(`Page not found: ${e}`),n,r)}export async function handleInternalError(e,t,r){let i=n(e.message);return i.stack=e.stack,handleRenderError(i,t,r)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{createNitroConfig,isValidPreset,mergeRouteRules,createDefaultStaticAssetRouteRules,DEFAULT_NITRO_CONFIG,DEFAULT_STATIC_ASSETS_CONFIG}from"./config.js";export{HttpError,isHttpError,createNotFoundError,createMethodNotAllowedError,createInternalError}from"./types.js";export{createNitroRenderer,createNitroCatchAllRenderer,createRenderContext,renderPage,renderPageStream,createStreamingResponse,injectHydrationScript,validateHydrationMarkers,extractIslandMarkers,ensureHydrationMarkers,processHydrationRequirements,createErrorResponse,getRequestURL as getRendererRequestURL,toRequest as rendererToRequest,setResponseHeader}from"./renderer.js";export{createMiddlewareContext,storeMiddlewareContext,getMiddlewareContext,getOrCreateMiddlewareContext,setMiddlewareState,getMiddlewareState,setMiddlewareLocal,getMiddlewareLocal,hasAvalonContext,ensureAvalonContext,getRequestURL as getMiddlewareRequestURL,getRequestHeaders as getMiddlewareRequestHeaders,toRequest as middlewareToRequest,getRouterParams as getMiddlewareRouterParams}from"./middleware-adapter.js";export{discoverPageRoutes,filePathToPattern,isPrivateFile,calculateRouteSpecificity,sortRoutesBySpecificity,validateRoutePattern,extractParamsFromPattern,matchRoutePattern,PAGE_EXTENSIONS}from"./route-discovery.js";export{createClientBuildConfig,createServerBuildConfig,createCombinedBuildConfig,createNitroBuildPlugin,getPresetOutputConfig,presetSupportsStreaming,validateBuildConfig,createSourceMapConfig,createSourceMapPlugin,getViteSourceMapOption,DEFAULT_BUILD_CONFIG,DEFAULT_SOURCEMAP_CONFIG,PRESET_OUTPUT_CONFIGS}from"./build-config.js";export{createIslandManifestPlugin,createIslandEntry,detectIslandFramework,generateContentHash,extractIslandDependencies,generatePreloadHints,generatePreloadTags,loadIslandManifest,getIslandAssetPath,getPageCssAssets,DEFAULT_MANIFEST_OPTIONS}from"./island-manifest.js";export{discoverErrorPages,getErrorPageModule,renderErrorPage,generateDefaultErrorPage,createErrorPageProps,clearErrorPageCache,handleRenderError,handleApiError,handleNotFound,handleInternalError}from"./error-handler.js";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{readFile as e}from"node:fs/promises";export const DEFAULT_MANIFEST_OPTIONS={outputPath:`dist/island-manifest.json`,includeSourceMaps:!1,generatePreloadHints:!0,verbose:!1};const n={react:[/from\s+['"]react['"]/,/from\s+['"]react-dom['"]/,/@jsxImportSource\s+react/],preact:[/from\s+['"]preact['"]/,/from\s+['"]preact\/hooks['"]/,/@jsxImportSource\s+preact/],vue:[/from\s+['"]vue['"]/,/\.vue$/],svelte:[/from\s+['"]svelte['"]/,/\.svelte$/],solid:[/from\s+['"]solid-js['"]/,/\.solid\.(tsx|jsx)$/],lit:[/from\s+['"]lit['"]/,/from\s+['"]@lit['"]/,/\.lit\.(ts|js)$/]};export function detectIslandFramework(e,t){if(e.endsWith(`.vue`))return`vue`;if(e.endsWith(`.svelte`))return`svelte`;if(e.includes(`.solid.`))return`solid`;if(e.includes(`.lit.`))return`lit`;for(let[r,i]of Object.entries(n))for(let n of i)if(n.test(t)||n.test(e))return r;return e.endsWith(`.tsx`)||e.endsWith(`.jsx`)?`preact`:`unknown`}export async function generateContentHash(e){let t=new TextEncoder().encode(e),n=await crypto.subtle.digest(`SHA-256`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``).slice(0,8)}export function extractIslandDependencies(e){let t=[],n=/import\s+.*?\s+from\s+['"]([^'"]+)['"]/g,r=/import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,i;for(;(i=n.exec(e))!==null;){let e=i[1];!e.startsWith(`.`)&&!e.startsWith(`/`)&&t.push(e)}for(;(i=r.exec(e))!==null;){let e=i[1];!e.startsWith(`.`)&&!e.startsWith(`/`)&&t.push(e)}return[...new Set(t)]}export async function createIslandEntry(e,t,n,o){let s=detectIslandFramework(t,n),c=await generateContentHash(n);return{src:o,framework:s,css:[],preload:extractIslandDependencies(n).filter(e=>!e.includes(`/`)),sourcePath:t,chunkName:e,contentHash:c,preloadDeps:[],usesStreaming:!1}}export function generatePreloadHints(e){let t=[];e.clientEntry&&t.push({href:e.clientEntry,as:`script`,type:`text/javascript`});for(let n of e.css??[])t.push({href:n,as:`style`,type:`text/css`});for(let n of Object.values(e.frameworkBundles??{}))t.push({href:n,as:`script`,type:`text/javascript`});return t}export function createIslandManifestPlugin(e,n={}){let r={...DEFAULT_MANIFEST_OPTIONS,...n},a=new Map,o=new Set,c=``;return{name:`avalon:island-manifest`,enforce:`post`,generateBundle(e,t){for(let[e,n]of Object.entries(t))if(e.endsWith(`.css`)&&o.add(`/${e}`),n.type===`chunk`&&(n.name===`client`||n.name===`main`)&&(c=`/${e}`),n.type===`chunk`&&(n.facadeModuleId?.includes(`/islands/`)||n.name?.startsWith(`islands/`))){let t=n.name?.replace(`islands/`,``)??e,r=a.get(t);r?r.src=`/${e}`:a.set(t,{src:`/${e}`,framework:u(n),css:[],preload:[],sourcePath:n.facadeModuleId??``,chunkName:t,contentHash:/\.([a-f0-9]+)\.js$/.exec(e)?.[1]??``,preloadDeps:n.imports??[],usesStreaming:!1})}},async writeBundle(e,t){let n={},u=new Date().toISOString();for(let[e,r]of Object.entries(t)){let t=await l(e,r,u);t&&(n[`/${e}`]=t)}let d={islands:Object.fromEntries(a),clientEntry:c,css:Array.from(o),buildTime:Date.now(),buildHash:await generateContentHash(JSON.stringify(Object.fromEntries(a))),avalonVersion:`1.0.0`,cssAssets:Array.from(o),preloadHints:r.generatePreloadHints?generatePreloadHints({clientEntry:c,css:Array.from(o),islands:Object.fromEntries(a)}):[],frameworkBundles:{},assetMetadata:n},f=JSON.stringify(d,null,2);r.verbose&&(console.log(`📋 Island manifest generated:`),console.log(` Islands: ${a.size}`),console.log(` CSS assets: ${o.size}`),console.log(` Client entry: ${c}`),console.log(` Asset metadata entries: ${Object.keys(n).length}`)),this.emitFile({type:`asset`,fileName:`island-manifest.json`,source:f})}}}async function l(e,t,n){let r;if(t.type===`asset`&&t.source?r=t.source:t.type===`chunk`&&t.code&&(r=t.code),!r)return null;let a=typeof r==`string`?new TextEncoder().encode(r).length:r.length,o=await generateContentHash(typeof r==`string`?r:new TextDecoder().decode(r)),s=e.substring(e.lastIndexOf(`.`));return{type:{".js":`application/javascript`,".mjs":`application/javascript`,".css":`text/css`,".json":`application/json`,".html":`text/html`,".map":`application/json`}[s]??`application/octet-stream`,etag:`"${o}"`,mtime:n,size:a}}function u(e){return detectIslandFramework(e.facadeModuleId??``,e.code??``)}export async function loadIslandManifest(t=`dist/island-manifest.json`){try{let n=await e(t,`utf-8`);return JSON.parse(n)}catch{return null}}export function getIslandAssetPath(e,t){return t?t.islands[e]?.src??null:null}export function getPageCssAssets(e,t){if(!t)return[];let n=new Set;for(let e of t.css)n.add(e);for(let r of e){let e=t.islands[r];if(e?.css)for(let t of e.css)n.add(t)}return Array.from(n)}export function generatePreloadTags(e){let t=[];for(let n of e.preloadHints){let e=[`rel="preload"`,`href="${n.href}"`,`as="${n.as}"`];n.type&&e.push(`type="${n.type}"`),n.crossorigin&&e.push(`crossorigin="${n.crossorigin}"`),t.push(`<link ${e.join(` `)}>`)}return t.join(`
|
|
2
|
+
`)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getRequestURL as e}from"h3";export function getRequestURL(t){return new URL(e(t).pathname,`http://localhost`)}export function getRequestHeaders(e){return new Headers(e.req.headers)}export function toRequest(e){let r=getRequestURL(e),i=e.req.method.toUpperCase();return new Request(r,{method:i,headers:getRequestHeaders(e)})}export function getRouterParams(e){return e.context.params??{}}export function createMiddlewareContext(n,a={}){let{enableLogging:o=!1}=a,s=getRequestURL(n),c=getRouterParams(n),l={};for(let[e,t]of s.searchParams.entries())l[e]?Array.isArray(l[e])?l[e].push(t):l[e]=[l[e],t]:l[e]=t;return o&&console.log(`[Middleware Context] Created for ${n.req.method} ${e(n).pathname}`),{request:toRequest(n),url:s,params:c,query:l,state:new Map,locals:{}}}export function storeMiddlewareContext(e,t){e.context.avalon||(e.context.avalon={}),e.context.avalon.middlewareContext=t}export function getMiddlewareContext(e){return e.context.avalon?.middlewareContext}export function getOrCreateMiddlewareContext(e,t={}){let n=getMiddlewareContext(e);if(n)return n;let r=createMiddlewareContext(e,t);return storeMiddlewareContext(e,r),r}export function setMiddlewareState(e,t,n){getOrCreateMiddlewareContext(e).state.set(t,n)}export function getMiddlewareState(e,t){return getMiddlewareContext(e)?.state.get(t)}export function setMiddlewareLocal(e,t,n){let r=getOrCreateMiddlewareContext(e);r.locals[t]=n}export function getMiddlewareLocal(e,t){return getMiddlewareContext(e)?.locals[t]}export function hasAvalonContext(e){return e.context.avalon!==void 0}export function ensureAvalonContext(e){return e.context.avalon||(e.context.avalon={}),e.context.avalon}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import{getRequestURL as e}from"h3";import{createNotFoundError as t,isHttpError as n}from"./types.js";import{discoverScopedMiddleware as r,executeScopedMiddleware as i}from"../middleware/index.js";import{handleRenderError as a,discoverErrorPages as o}from"./error-handler.js";import{h as s}from"preact";import c from"preact-render-to-string";export function createRenderContext(e,t={}){let n=getRequestURL(e);return{url:n,params:t,query:Object.fromEntries(n.searchParams),request:toRequest(e),event:e}}export function getRequestURL(t){return new URL(e(t).pathname,`http://localhost`)}export function toRequest(e){let t=getRequestURL(e);return new Request(t,{method:e.req.method,headers:getRequestHeaders(e)})}export function getRequestHeaders(e){return new Headers}export function setResponseHeader(e,t,n){e.context.responseHeaders||(e.context.responseHeaders={}),e.context.responseHeaders[t]=n}export function createErrorResponse(e,t){let r=n(e)?e.statusCode:500;if(t){let t=h(e,r);return new Response(t,{status:r,headers:{"Content-Type":`text/html; charset=utf-8`}})}let i=g(r);return new Response(i,{status:r,headers:{"Content-Type":`text/html; charset=utf-8`}})}function h(e,t){return`<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>Error ${t}</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 40px;
|
|
12
|
+
background: #1a1a1a;
|
|
13
|
+
color: #fff;
|
|
14
|
+
}
|
|
15
|
+
.error-container {
|
|
16
|
+
max-width: 800px;
|
|
17
|
+
margin: 0 auto;
|
|
18
|
+
background: #2d2d2d;
|
|
19
|
+
padding: 40px;
|
|
20
|
+
border-radius: 8px;
|
|
21
|
+
border-left: 4px solid #ff6b6b;
|
|
22
|
+
}
|
|
23
|
+
h1 {
|
|
24
|
+
color: #ff6b6b;
|
|
25
|
+
margin-top: 0;
|
|
26
|
+
font-size: 24px;
|
|
27
|
+
}
|
|
28
|
+
.status-code {
|
|
29
|
+
font-size: 48px;
|
|
30
|
+
font-weight: bold;
|
|
31
|
+
color: #ff6b6b;
|
|
32
|
+
margin-bottom: 10px;
|
|
33
|
+
}
|
|
34
|
+
.message {
|
|
35
|
+
font-size: 18px;
|
|
36
|
+
color: #ccc;
|
|
37
|
+
margin-bottom: 20px;
|
|
38
|
+
}
|
|
39
|
+
pre {
|
|
40
|
+
background: #1a1a1a;
|
|
41
|
+
padding: 20px;
|
|
42
|
+
border-radius: 4px;
|
|
43
|
+
overflow-x: auto;
|
|
44
|
+
font-size: 14px;
|
|
45
|
+
line-height: 1.5;
|
|
46
|
+
color: #e0e0e0;
|
|
47
|
+
}
|
|
48
|
+
.stack-title {
|
|
49
|
+
color: #888;
|
|
50
|
+
font-size: 12px;
|
|
51
|
+
text-transform: uppercase;
|
|
52
|
+
margin-bottom: 10px;
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
55
|
+
</head>
|
|
56
|
+
<body>
|
|
57
|
+
<div class="error-container">
|
|
58
|
+
<div class="status-code">${t}</div>
|
|
59
|
+
<h1>${_(t)}</h1>
|
|
60
|
+
<p class="message">${v(e.message)}</p>
|
|
61
|
+
${e.stack?`
|
|
62
|
+
<div class="stack-title">Stack Trace</div>
|
|
63
|
+
<pre>${v(e.stack)}</pre>
|
|
64
|
+
`:``}
|
|
65
|
+
</div>
|
|
66
|
+
</body>
|
|
67
|
+
</html>`}function g(e){return`<!DOCTYPE html>
|
|
68
|
+
<html lang="en">
|
|
69
|
+
<head>
|
|
70
|
+
<meta charset="utf-8">
|
|
71
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
72
|
+
<title>Error ${e}</title>
|
|
73
|
+
<style>
|
|
74
|
+
body {
|
|
75
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
76
|
+
margin: 0;
|
|
77
|
+
padding: 40px;
|
|
78
|
+
background: #f5f5f5;
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
justify-content: center;
|
|
82
|
+
min-height: 100vh;
|
|
83
|
+
box-sizing: border-box;
|
|
84
|
+
}
|
|
85
|
+
.error-container {
|
|
86
|
+
text-align: center;
|
|
87
|
+
max-width: 400px;
|
|
88
|
+
}
|
|
89
|
+
.status-code {
|
|
90
|
+
font-size: 72px;
|
|
91
|
+
font-weight: bold;
|
|
92
|
+
color: #333;
|
|
93
|
+
margin-bottom: 10px;
|
|
94
|
+
}
|
|
95
|
+
h1 {
|
|
96
|
+
color: #666;
|
|
97
|
+
font-size: 24px;
|
|
98
|
+
margin: 0 0 20px 0;
|
|
99
|
+
}
|
|
100
|
+
p {
|
|
101
|
+
color: #888;
|
|
102
|
+
margin: 0;
|
|
103
|
+
}
|
|
104
|
+
a {
|
|
105
|
+
color: #0066cc;
|
|
106
|
+
text-decoration: none;
|
|
107
|
+
}
|
|
108
|
+
a:hover {
|
|
109
|
+
text-decoration: underline;
|
|
110
|
+
}
|
|
111
|
+
</style>
|
|
112
|
+
</head>
|
|
113
|
+
<body>
|
|
114
|
+
<div class="error-container">
|
|
115
|
+
<div class="status-code">${e}</div>
|
|
116
|
+
<h1>${_(e)}</h1>
|
|
117
|
+
<p><a href="/">Return to home</a></p>
|
|
118
|
+
</div>
|
|
119
|
+
</body>
|
|
120
|
+
</html>`}function _(e){return{400:`Bad Request`,401:`Unauthorized`,403:`Forbidden`,404:`Page Not Found`,405:`Method Not Allowed`,500:`Internal Server Error`,502:`Bad Gateway`,503:`Service Unavailable`}[e]||`Error`}function v(e){return e.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`>`,`>`).replaceAll(`"`,`"`).replaceAll(`'`,`'`)}export function extractIslandMarkers(e){let t=[],n=/<[^>]*data-framework="([^"]+)"[^>]*>/g,r;for(;(r=n.exec(e))!==null;){let e=r[0],n=r[1],i=/data-src="([^"]+)"/.exec(e),a=i?i[1]:``,o=/data-props="([^"]*)"/.exec(e),s=o?o[1]:void 0,c=/data-hydrate="([^"]+)"/.exec(e),l=c?c[1]:void 0;t.push({framework:n,src:a,props:s,hydrate:l})}return t}export function ensureHydrationMarkers(e,t){let n=e;return t.framework&&!n.includes(`data-framework=`)&&(n=n.replace(/>/,` data-framework="${t.framework}">`)),t.src&&!n.includes(`data-src=`)&&(n=n.replace(/>/,` data-src="${t.src}">`)),t.props!==void 0&&!n.includes(`data-props=`)&&(n=n.replace(/>/,` data-props="${t.props}">`)),n}export function injectHydrationScript(e,t,n={}){if(!(e.includes(`data-framework=`)||e.includes(`data-src=`))&&!n.forceInject||[`/src/client/main.js`,`/dist/client.js`,`client/main.js`].some(t=>e.includes(t)))return e;let r=n.scriptPath||(t?`/src/client/main.js`:`/dist/client.js`),i=[];i.push(`<script type="module" src="${r}"><\/script>`),n.additionalScripts&&i.push(...n.additionalScripts);let a=i.join(`
|
|
121
|
+
`);return e.includes(`</body>`)?e.replace(`</body>`,`${a}\n</body>`):e+a}export function validateHydrationMarkers(e){let t=extractIslandMarkers(e),n=e.match(/data-framework="[^"]+"/g)||[],r=e.match(/data-src="[^"]+"/g)||[],i=e.match(/data-props="[^"]*"/g)||[],a=e.includes(`/src/client/main.js`)||e.includes(`/dist/client.js`)||e.includes(`client/main.js`),o=t.every(e=>e.framework&&e.src),s=t.length===0||o&&a;return{hasFrameworkAttr:n.length>0,hasSrcAttr:r.length>0,hasPropsAttr:i.length>0,islandCount:n.length,islands:t,hasClientScript:a,isValid:s}}export function processHydrationRequirements(e,t){let n=injectHydrationScript(e,t);return{html:n,validation:validateHydrationMarkers(n)}}export async function renderPage(e,t,n={}){try{let r={};return e.getServerSideProps&&(r=await e.getServerSideProps(t)),{html:await y(e,r,t,n),statusCode:200,headers:{"Content-Type":`text/html; charset=utf-8`}}}catch(e){throw console.error(`[SSR Error]`,e),n.onError&&e instanceof Error&&n.onError(e),e}}async function y(e,t,n,r){let i=e.default,a=e.metadata||{},o;try{let e=i(t);o=e instanceof Promise?await e:e}catch(e){console.error(`[renderer] Error calling page component:`,e),o=s(`div`,null,`Error rendering page`)}let l;try{l=c(o)}catch(e){console.error(`[renderer] Error in preactRenderToString:`,e),l=`<div>Error rendering page</div>`}return`<!DOCTYPE html>
|
|
122
|
+
<html lang="en">
|
|
123
|
+
<head>
|
|
124
|
+
<meta charset="utf-8">
|
|
125
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
126
|
+
<title>${v(String(a.title||`Avalon App`))}</title>
|
|
127
|
+
${a.description?`<meta name="description" content="${v(String(a.description))}">`:``}
|
|
128
|
+
</head>
|
|
129
|
+
<body>
|
|
130
|
+
<div id="app">
|
|
131
|
+
${l}
|
|
132
|
+
</div>
|
|
133
|
+
<script type="module" src="/src/client/main.js"><\/script>
|
|
134
|
+
</body>
|
|
135
|
+
</html>`}export async function renderPageStream(e,t,n={}){let r=new TextEncoder,i=null,a={shellSent:!1,contentSent:!1,closed:!1,error:null},o=n.shellReadyTimeout,s=n.allReadyTimeout,c=null,l=null,u=()=>{c&&=(clearTimeout(c),null),l&&=(clearTimeout(l),null)};function d(e,t,n,r,i,a,o){if(n.error=e,a(),console.error(`[Streaming Error]`,{message:e.message,stack:e.stack,shellSent:n.shellSent,isShellError:t,timestamp:new Date().toISOString()}),t&&o.onShellError&&o.onShellError(e),o.onError&&o.onError(e),!n.closed&&r){if(n.shellSent){let t=C(e);r.enqueue(i.encode(t));let n=S();r.enqueue(i.encode(n))}else{let t=h(e,500);r.enqueue(i.encode(t))}n.closed=!0,r.close()}}async function f(o){i=o;let f={};e.getServerSideProps&&(f=await e.getServerSideProps(t));let p=b(e.metadata||{},t);if(a.closed||(o.enqueue(r.encode(p)),a.shellSent=!0,c&&=(clearTimeout(c),null),n.onShellReady&&n.onShellReady()),s&&s>0&&(l=setTimeout(()=>{!a.contentSent&&!a.closed&&d(Error(`All ready timeout after ${s}ms`),!1,a,i,r,u,n)},s)),!a.closed){let t=x(e,f);o.enqueue(r.encode(t)),a.contentSent=!0}if(!a.closed){let e=S();o.enqueue(r.encode(e))}u(),n.onAllReady&&!a.closed&&n.onAllReady(),a.closed||(a.closed=!0,o.close())}return new ReadableStream({async start(e){i=e,o&&o>0&&(c=setTimeout(()=>{!a.shellSent&&!a.closed&&d(Error(`Shell ready timeout after ${o}ms`),!0,a,i,r,u,n)},o));try{await f(e)}catch(e){d(e instanceof Error?e:Error(String(e)),!a.shellSent,a,i,r,u,n)}},cancel(){if(u(),!a.closed&&i){a.closed=!0;try{i.close()}catch{}}}})}function b(e,t){return`<!DOCTYPE html>
|
|
136
|
+
<html lang="en">
|
|
137
|
+
<head>
|
|
138
|
+
<meta charset="utf-8">
|
|
139
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
140
|
+
<title>${v(String(e.title||`Avalon App`))}</title>
|
|
141
|
+
${e.description?`<meta name="description" content="${v(String(e.description))}">`:``}
|
|
142
|
+
</head>
|
|
143
|
+
<body>
|
|
144
|
+
`}function x(e,t){let n=e.default?.name||`Page`;return` <div id="app" data-page="${v(String(n))}" data-props='${v(JSON.stringify(t))}'>
|
|
145
|
+
<!-- Page content rendered by Avalon SSR pipeline -->
|
|
146
|
+
</div>
|
|
147
|
+
`}function S(){return` </body>
|
|
148
|
+
</html>`}function C(e){let t=process.env.NODE_ENV!==`production`,n=e.stack?`<pre style="
|
|
149
|
+
background: #f5f5f5;
|
|
150
|
+
padding: 10px;
|
|
151
|
+
border-radius: 4px;
|
|
152
|
+
overflow-x: auto;
|
|
153
|
+
font-size: 12px;
|
|
154
|
+
margin-top: 10px;
|
|
155
|
+
">${v(e.stack)}</pre>`:``;return`
|
|
156
|
+
<div class="streaming-error-boundary" data-error-boundary="true" style="
|
|
157
|
+
background: #fff3cd;
|
|
158
|
+
border: 2px solid #ffc107;
|
|
159
|
+
border-radius: 8px;
|
|
160
|
+
padding: 20px;
|
|
161
|
+
margin: 20px 0;
|
|
162
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
163
|
+
">
|
|
164
|
+
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;">
|
|
165
|
+
<span style="font-size: 24px;">⚠️</span>
|
|
166
|
+
<h3 style="margin: 0; color: #856404;">Streaming Error</h3>
|
|
167
|
+
</div>
|
|
168
|
+
<p style="margin: 10px 0; color: #856404;">
|
|
169
|
+
An error occurred while streaming this page.
|
|
170
|
+
</p>
|
|
171
|
+
${t?`
|
|
172
|
+
<details style="margin-top: 15px;">
|
|
173
|
+
<summary style="cursor: pointer; color: #856404; font-weight: bold;">
|
|
174
|
+
Error Details (Development Mode)
|
|
175
|
+
</summary>
|
|
176
|
+
<div style="margin-top: 10px;">
|
|
177
|
+
<p><strong>Error:</strong> ${v(e.message)}</p>
|
|
178
|
+
${n}
|
|
179
|
+
</div>
|
|
180
|
+
</details>
|
|
181
|
+
`:``}
|
|
182
|
+
</div>
|
|
183
|
+
`}export function createStreamingResponse(e,t={}){let n=new Headers({"Content-Type":`text/html; charset=utf-8`,"Transfer-Encoding":`chunked`,...t.headers});return new Response(e,{status:t.status||200,headers:n})}function w(e,t,n){return async()=>(e.value??=await r({baseDir:t,devMode:n}),e.value)}function T(e,t,n){return async(r,i)=>e?a(r,i,t):createErrorResponse(r,n)}export function createNitroRenderer(e){let{avalonConfig:n,isDev:r=!1,enableCustomErrorPages:a=!0}=e,s={isDev:r,avalonConfig:n,loadPageModule:e.loadPageModule,pagesDir:n.pagesDir};a&&o(s).catch(e=>{console.warn(`[renderer] Failed to discover error pages:`,e)});let c=w({value:null},n.srcDir||`src`,r),d=T(a,s,r);return async function(a){let o=getRequestURL(a).pathname;try{let s=await i(a,await c(),{devMode:r});if(s)return r&&console.log(`[renderer] Middleware terminated request for ${o}`),s;let u=a.context.route,f=null;if(f=u||(e.resolvePageRoute?await e.resolvePageRoute(o,n.pagesDir):await E(o,n.pagesDir)),!f)return d(t(`Page not found: ${o}`),a);let m=e.loadPageModule?await e.loadPageModule(f.filePath):await D(f.filePath),h=createRenderContext(a,a.context.params||f.params);if(e.resolveLayouts&&(h.layoutContext={layouts:await e.resolveLayouts(o,n)}),n.streaming){let e=await renderPageStream(m,h,{onShellReady:()=>{setResponseHeader(a,`Content-Type`,`text/html; charset=utf-8`)}});return new Response(e,{headers:{"Content-Type":`text/html; charset=utf-8`}})}else{let e=await renderPage(m,h),t=injectHydrationScript(e.html,r);return new Response(t,{status:e.statusCode,headers:e.headers})}}catch(e){return console.error(`[Nitro Renderer Error]`,e),d(e instanceof Error?e:Error(String(e)),a)}}}async function E(e,t){return e===`/`||e===``?{filePath:`src/pages/index.tsx`,pattern:`/`,params:{}}:{filePath:`src/pages/${e.replace(/^\//,``).replace(/\/$/,``)}.tsx`,pattern:e,params:{}}}async function D(e){return{default:()=>null,metadata:{title:`Avalon Page`}}}export function createNitroCatchAllRenderer(e){let{avalonConfig:n,isDev:r=!1,loadPageModule:a,resolveLayouts:s,enableCustomErrorPages:c=!0}=e,d={isDev:r,avalonConfig:n,loadPageModule:a,pagesDir:n.pagesDir};c&&o(d).catch(e=>{console.warn(`[renderer] Failed to discover error pages:`,e)});let f=w({value:null},n.srcDir||`src`,r),m=T(c,d,r);return async function(e){let o=getRequestURL(e).pathname;try{let c=await i(e,await f(),{devMode:r});if(c)return r&&console.log(`[renderer] Middleware terminated request for ${o}`),c;let u=e.context.params||{},d=u.slug||o.replace(/^\//,``)||`index`,h=`${n.pagesDir}/${d}.tsx`,g;try{g=await a(h)}catch(i){try{g=await a(`${n.pagesDir}/${d}/index.tsx`)}catch(a){return r&&(console.debug(`[renderer] Page not found: ${h}`,i),console.debug(`[renderer] Index fallback not found: ${n.pagesDir}/${d}/index.tsx`,a)),m(t(`Page not found: ${o}`),e)}}let _=createRenderContext(e,u);if(s&&(_.layoutContext={layouts:await s(o,n)}),n.streaming){let t=await renderPageStream(g,_,{onShellReady:()=>{setResponseHeader(e,`Content-Type`,`text/html; charset=utf-8`)}});return new Response(t,{headers:{"Content-Type":`text/html; charset=utf-8`}})}else{let e=await renderPage(g,_),t=injectHydrationScript(e.html,r);return new Response(t,{status:e.statusCode,headers:e.headers})}}catch(t){return console.error(`[Nitro Catch-All Renderer Error]`,t),m(t instanceof Error?t:Error(String(t)),e)}}}export{clearMiddlewareCache as clearRendererMiddlewareCache}from"../middleware/index.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{stat as e}from"node:fs/promises";import{basename as t,dirname as n,relative as r}from"node:path";import{walk as i}from"../utils/fs.js";export const PAGE_EXTENSIONS=[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`,`.md`,`.mdx`];export async function discoverPageRoutesFromMultipleDirs(e,t){let n=[];for(let{dir:r,prefix:i}of e){let e=await discoverPageRoutes(r,t);for(let t of e)i!==`/`&&(t.pattern=t.pattern===`/`?i:i+t.pattern),n.push(t)}return sortRoutesBySpecificity(n)}export async function discoverPageRoutes(t,n){let o=[],s=n?.excludeDirectories??[`node_modules`,`.git`];try{if(!(await e(t)).isDirectory())return n?.developmentMode&&console.warn(`[route-discovery] Pages path is not a directory: ${t}`),[]}catch(e){if(e instanceof Error&&e.code===`ENOENT`)return n?.developmentMode&&console.warn(`[route-discovery] Pages directory not found: ${t}`),[];throw e}let l=PAGE_EXTENSIONS.map(e=>e.slice(1));for await(let e of i(t,{includeDirs:!1,includeSymlinks:!1,exts:l})){if(!e.isFile)continue;let n=r(t,e.path);if(s.some(e=>n.includes(e))||isPrivateFile(n))continue;let{pattern:i,params:a}=filePathToPattern(n);o.push({type:`page`,filePath:e.path,pattern:i,params:a})}return sortRoutesBySpecificity(o)}export function filePathToPattern(e){let r=[],i=e.replace(/\\/g,`/`).replace(/\.(tsx|ts|jsx|js|vue|svelte|md|mdx)$/,``).replace(/\([^)]+\)\//g,``).replace(/\([^)]+\)$/,``);return t(i)===`index`&&(i=n(i),i===`.`&&(i=``)),i=i.replace(/\[([^\]]+)\]/g,(e,t)=>{if(t.startsWith(`...`)){let e=t.slice(3);return r.push(e),`**`}else return r.push(t),`:${t}`}),i.startsWith(`/`)||(i=`/`+i),(i===`/`||i===``)&&(i=`/`),i.length>1&&i.endsWith(`/`)&&(i=i.slice(0,-1)),{pattern:i,params:r}}export function isPrivateFile(e){return e.split(/[/\\]/).some(e=>e.startsWith(`_`))}export function calculateRouteSpecificity(e){let t=e.pattern.split(`/`).filter(e=>e.length>0),n=0;for(let e of t)e===`**`?n+=1e3:e.startsWith(`:`)?n+=100:n+=1;return n+=t.length,n}export function sortRoutesBySpecificity(e){return[...e].sort((e,t)=>calculateRouteSpecificity(e)-calculateRouteSpecificity(t))}export function validateRoutePattern(e){let t=[];e.startsWith(`/`)||t.push(`Route pattern must start with /`);let n=e.match(/\[[^\]]*$/g);n&&t.push(`Malformed dynamic segments: ${n.join(`, `)}. Dynamic segments must be properly closed with ]`),e.match(/\[\]/g)&&t.push(`Empty dynamic segments [] are not allowed. Use [param] for dynamic segments or [...rest] for catch-all`);let r=e.match(/\[[^\]]*\[[^\]]*\]/g);return r&&t.push(`Nested dynamic segments are not supported: ${r.join(`, `)}`),t}export function extractParamsFromPattern(e){let t=[],n=e.matchAll(/:([^/]+)/g);for(let e of n)t.push(e[1]);return e.includes(`**`)&&t.push(`slug`),t}export function matchRoutePattern(e,t){let n={},r=e.replace(/\/$/,``)||`/`,i=t.replace(/\/$/,``)||`/`,a=r.split(`/`).filter(e=>e),o=i.split(`/`).filter(e=>e),s=0,c=0;for(;s<a.length;){let e=a[s];if(e===`**`)return n.slug=o.slice(c).join(`/`),{matches:!0,params:n};if(c>=o.length)return{matches:!1,params:{}};let t=o[c];if(e.startsWith(`:`)){let r=e.slice(1);n[r]=t}else if(e!==t)return{matches:!1,params:{}};s++,c++}return c<o.length?{matches:!1,params:{}}:{matches:!0,params:n}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export class HttpError extends Error{statusCode;data;constructor(e,t,n){super(t),this.name=`HttpError`,this.statusCode=e,this.data=n}}export function createNotFoundError(t=`Not Found`){return new HttpError(404,t)}export function createMethodNotAllowedError(t){return new HttpError(405,`Method Not Allowed`,{allowed:t})}export function createInternalError(t=`Internal Server Error`){return new HttpError(500,t)}export function isHttpError(t){return t instanceof HttpError}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export async function collectCssFromModuleGraph(e,r){let i=[],a=new Set,o=await e.moduleGraph.getModuleByUrl(r);if(!o)return i;let s=[o];for(;s.length>0;){let r=s.shift(),o=r.id??r.url;if(!a.has(o)){if(a.add(o),t(o)){let t=await n(e,r);t&&i.push(t)}for(let e of r.importedModules){let t=e.id??e.url;a.has(t)||s.push(e)}}}return i}function t(e){let t=e.split(`?`)[0];return t.endsWith(`.css`)||t.endsWith(`.scss`)||t.endsWith(`.sass`)||t.endsWith(`.less`)||t.endsWith(`.styl`)||t.endsWith(`.stylus`)}async function n(e,t){try{let n=t.url,i=await e.transformRequest(n+`?direct`);return i&&typeof i.code==`string`?r(i.code):null}catch{return null}}function r(e){let t=new RegExp(/const\s+__vite__css\s*=\s*"((?:[^"\\]|\\.)*)"/).exec(e);if(t)return i(t[1]);let n=new RegExp(/__vite_ssr_exports__\.default\s*=\s*"((?:[^"\\]|\\.)*)"/).exec(e);if(n)return i(n[1]);let r=new RegExp(/export\s+default\s+"((?:[^"\\]|\\.)*)"/).exec(e);return r?i(r[1]):!e.includes(`export `)&&!e.includes(`__vite`)?e:null}function i(e){return e.replaceAll(String.raw`\n`,`
|
|
2
|
+
`).replaceAll(String.raw`\t`,` `).replaceAll(String.raw`\r`,`\r`).replaceAll(String.raw`\"`,`"`).replaceAll(`\\\\`,`\\`)}export function injectSsrCss(e,t){if(t.length===0)return e;let n=t.map(e=>`<style data-avalon-ssr-css>${o(e)}</style>`).join(`
|
|
3
|
+
`);return e.includes(`</head>`)?e.replace(`</head>`,`${n}\n</head>`):e.includes(`<head>`)?e.replace(`<head>`,`<head>\n${n}`):n+e}function o(e){return e.replaceAll(/<\/style/gi,String.raw`<\/style`)}
|
|
@@ -1,27 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Shared error page HTML templates for development mode.
|
|
3
|
-
* Extracted from nitro-integration.ts to keep that file focused on coordination.
|
|
4
|
-
*
|
|
5
|
-
* @module render/error-pages
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Escapes HTML special characters
|
|
10
|
-
*/
|
|
11
|
-
function escapeHtml(str: string): string {
|
|
12
|
-
return str
|
|
13
|
-
.replaceAll('&', "&")
|
|
14
|
-
.replaceAll('<', "<")
|
|
15
|
-
.replaceAll('>', ">")
|
|
16
|
-
.replaceAll('"', """)
|
|
17
|
-
.replaceAll('\'', "'");
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Generates a styled 500 error page for development with stack trace.
|
|
22
|
-
*/
|
|
23
|
-
export function generateErrorPage(error: Error): string {
|
|
24
|
-
return `<!DOCTYPE html>
|
|
1
|
+
function e(e){return e.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`>`,`>`).replaceAll(`"`,`"`).replaceAll(`'`,`'`)}export function generateErrorPage(t){return`<!DOCTYPE html>
|
|
25
2
|
<html lang="en">
|
|
26
3
|
<head>
|
|
27
4
|
<meta charset="utf-8">
|
|
@@ -60,20 +37,12 @@ export function generateErrorPage(error: Error): string {
|
|
|
60
37
|
<body>
|
|
61
38
|
<div class="error-container">
|
|
62
39
|
<h1>SSR Error</h1>
|
|
63
|
-
<p class="message">${
|
|
64
|
-
${
|
|
40
|
+
<p class="message">${e(t.message)}</p>
|
|
41
|
+
${t.stack?`
|
|
65
42
|
<div class="stack-title">Stack Trace</div>
|
|
66
|
-
<pre>${
|
|
67
|
-
|
|
43
|
+
<pre>${e(t.stack)}</pre>
|
|
44
|
+
`:``}
|
|
68
45
|
</div>
|
|
69
|
-
<script type="module" src="/@vite/client"
|
|
46
|
+
<script type="module" src="/@vite/client"><\/script>
|
|
70
47
|
</body>
|
|
71
|
-
</html
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Generates a minimal fallback 404 page when the error handler itself fails.
|
|
76
|
-
*/
|
|
77
|
-
export function generateFallback404(url: string): string {
|
|
78
|
-
return `<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1>404 - Page Not Found</h1><p>The page ${escapeHtml(url)} was not found.</p></body></html>`;
|
|
79
|
-
}
|
|
48
|
+
</html>`}export function generateFallback404(t){return`<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1>404 - Page Not Found</h1><p>The page ${e(t)} was not found.</p></body></html>`}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{render as e}from"preact-render-to-string";import{readFile as t}from"node:fs/promises";import{EnhancedFrameworkDetector as n}from"../core/components/enhanced-framework-detector.js";import{toImportSpecifier as r}from"../middleware/executor.js";export class IsolatedSSRRenderer{contexts;detector;config;activeContext=null;constructor(e={}){this.contexts=new Map,this.detector=new n,this.config={enableStrictIsolation:!0,allowedCrossFrameworkImports:[`preact`,`preact-render-to-string`],errorHandling:`fallback`,debugLogging:!1,...e},this.initializeFrameworkContexts()}async renderWithIsolation(e){let t=[],n=[];try{let r=await this.resolveFramework(e,n);return await this.renderInContext(e,r,t,n)}catch(r){return t.push(`SSR rendering failed: ${r instanceof Error?r.message:String(r)}`),await this.tryFallbackRender(e,t,n)}}async resolveFramework(e,t){if(e.framework)return e.framework;try{let n=await this.getComponentContent(e.componentPath),r=this.detector.detectFramework(e.componentPath,n);return r.confidence===`low`&&t.push(`Low confidence framework detection for ${e.componentPath}: ${r.framework}`),this.config.debugLogging&&(console.log(`[SSR Isolation] Detected framework: ${r.framework} for ${e.componentPath}`),console.log(`[SSR Isolation] Evidence: ${r.evidence.join(`, `)}`)),r.framework}catch{return t.push(`Could not read component file for framework detection: ${e.componentPath}, defaulting to preact`),`preact`}}async renderInContext(e,t,n,r){let i=this.getFrameworkContext(t);if(!i)throw Error(`No SSR context available for framework: ${t}`);await this.switchToContext(t);try{let a=e.component(),o=a instanceof Promise?await a:a;return{html:await i.renderFunction(o,e.props||{}),framework:t,success:!0,errors:n,warnings:r}}finally{this.cleanupContext(t)}}async tryFallbackRender(t,n,r){if(this.config.errorHandling!==`fallback`)return{html:``,framework:t.framework||`unknown`,success:!1,errors:n,warnings:r};try{let i=e(await t.component());return r.push(`Fell back to Preact rendering due to framework-specific error`),{html:i,framework:`preact`,success:!0,errors:n,warnings:r}}catch(e){return n.push(`Fallback rendering also failed: ${e instanceof Error?e.message:String(e)}`),{html:``,framework:t.framework||`unknown`,success:!1,errors:n,warnings:r}}}initializeFrameworkContexts(){this.contexts.set(`preact`,{framework:`preact`,imports:new Map,renderFunction:t=>Promise.resolve(e(t)),cleanup:()=>{this.clearFrameworkGlobals(`preact`)},isActive:!1}),this.contexts.set(`solid`,{framework:`solid`,imports:new Map,renderFunction:async e=>{try{let t=await this.importFrameworkModule(`solid-js/web`,`solid`);if(t&&typeof t.renderToString==`function`)return t.renderToString(()=>e);throw Error(`Solid renderToString not available`)}catch(e){throw Error(`Solid SSR failed: ${e instanceof Error?e.message:String(e)}`)}},cleanup:()=>{this.clearFrameworkGlobals(`solid`)},isActive:!1}),this.contexts.set(`vue`,{framework:`vue`,imports:new Map,renderFunction:async e=>{try{let t=await this.importFrameworkModule(`vue/server-renderer`,`vue`);if(t&&typeof t.renderToString==`function`)return await t.renderToString(e);throw Error(`Vue renderToString not available`)}catch(e){throw Error(`Vue SSR failed: ${e instanceof Error?e.message:String(e)}`)}},cleanup:()=>{this.clearFrameworkGlobals(`vue`)},isActive:!1}),this.contexts.set(`svelte`,{framework:`svelte`,imports:new Map,renderFunction:e=>{try{if(e&&typeof e==`object`&&`render`in e){let t=e.render();return Promise.resolve(t.html||``)}throw Error(`Svelte component does not have render method`)}catch(e){throw Error(`Svelte SSR failed: ${e instanceof Error?e.message:String(e)}`)}},cleanup:()=>{this.clearFrameworkGlobals(`svelte`)},isActive:!1}),this.contexts.set(`unknown`,{framework:`unknown`,imports:new Map,renderFunction:t=>Promise.resolve(e(t)),cleanup:()=>{},isActive:!1})}getFrameworkContext(e){return this.contexts.get(e)||this.contexts.get(`unknown`)||null}async switchToContext(e){this.activeContext&&this.activeContext!==e&&this.cleanupContext(this.activeContext);let t=this.contexts.get(e);if(!t)throw Error(`Framework context not found: ${e}`);t.isActive=!0,this.activeContext=e,await this.setupFrameworkEnvironment(e)}cleanupContext(e){let t=this.contexts.get(e);t&&(t.cleanup(),t.isActive=!1,t.imports.clear(),this.activeContext===e&&(this.activeContext=null))}async setupFrameworkEnvironment(e){switch(e){case`solid`:await this.ensureSolidEnvironment();break;case`vue`:await this.ensureVueEnvironment();break;case`svelte`:this.ensureSvelteEnvironment();break;default:break}}async importFrameworkModule(e,t){let n=this.contexts.get(t);if(!n)throw Error(`No context for framework: ${t}`);if(n.imports.has(e))return n.imports.get(e);if(this.config.enableStrictIsolation&&!this.isImportAllowed(e,t))throw Error(`Import not allowed in ${t} context: ${e}`);try{let i=await import(r(e));return n.imports.set(e,i),this.config.debugLogging&&console.log(`[SSR Isolation] Imported ${e} in ${t} context`),i}catch(n){throw Error(`Failed to import ${e} in ${t} context: ${n instanceof Error?n.message:String(n)}`)}}isImportAllowed(e,t){let n=this.detector.getFrameworkConfigs().get(t);return n&&[...n.ssrModules,...n.hydrationModules].some(t=>e.startsWith(t))?!0:this.config.allowedCrossFrameworkImports.some(t=>e.startsWith(t))}clearFrameworkGlobals(e){let t=globalThis;switch(e){case`solid`:typeof globalThis<`u`&&(delete t._$HY,delete t.Solid);break;case`vue`:typeof globalThis<`u`&&(delete t.__VUE__,delete t.Vue);break;case`svelte`:typeof globalThis<`u`&&delete t.__SVELTE__;break}}async ensureSolidEnvironment(){try{await this.importFrameworkModule(`solid-js/web`,`solid`)}catch(e){this.config.debugLogging&&console.warn(`[SSR Isolation] Failed to set up Solid environment:`,e)}}async ensureVueEnvironment(){try{await this.importFrameworkModule(`vue/server-renderer`,`vue`)}catch(e){this.config.debugLogging&&console.warn(`[SSR Isolation] Failed to set up Vue environment:`,e)}}ensureSvelteEnvironment(){try{this.config.debugLogging&&console.log(`[SSR Isolation] Svelte environment ready`)}catch(e){this.config.debugLogging&&console.warn(`[SSR Isolation] Failed to set up Svelte environment:`,e)}}async getComponentContent(e){try{let n=e;e.startsWith(`/`)&&(n=e.substring(1));let r=[n,`src/islands/${n.split(`/`).pop()}`,`islands/${n.split(`/`).pop()}`,`examples/${n.split(`/`).pop()}`];for(let e of r)try{return await t(e,`utf-8`)}catch{continue}throw Error(`Component file not found: ${e}`)}catch(e){throw Error(`Failed to read component content: ${e instanceof Error?e.message:String(e)}`)}}getActiveContext(){return this.activeContext}getContexts(){return new Map(this.contexts)}updateConfig(e){this.config={...this.config,...e}}resetAllContexts(){for(let[e]of this.contexts)this.cleanupContext(e);this.activeContext=null}async renderWithFallback(e,t){let n=[],r=[];try{let i={componentPath:`fallback-component`,component:e,framework:t},a=await this.renderWithIsolation(i);if(a.success)return a;n.push(...a.errors),r.push(...a.warnings)}catch(e){n.push(`Preferred framework (${t}) failed: ${e instanceof Error?e.message:String(e)}`)}for(let i of[`preact`,`unknown`])if(i!==t)try{let a={componentPath:`fallback-component`,component:e,framework:i},o=await this.renderWithIsolation(a);if(o.success)return r.push(`Fell back to ${i} rendering from ${t}`),{...o,warnings:[...r,...o.warnings]};n.push(...o.errors)}catch(e){n.push(`Fallback framework (${i}) failed: ${e instanceof Error?e.message:String(e)}`)}return{html:``,framework:t,success:!1,errors:n,warnings:r}}async validateFrameworkContext(e){if(!this.contexts.get(e))return!1;try{return await this.setupFrameworkEnvironment(e),!0}catch(t){return this.config.debugLogging&&console.warn(`[SSR Isolation] Framework context validation failed for ${e}:`,t),!1}}getErrorRecoveryStrategies(e){return{solid:[`Ensure solid-js and solid-js/web are installed`,`Check that Solid components use proper JSX import source: /** @jsxImportSource solid-js */`,`Verify Solid components export default function`],vue:[`Ensure vue and vue/server-renderer are installed`,`Check that Vue components have proper <template>, <script>, and <style> sections`,`Verify Vue components are properly compiled for SSR`],svelte:[`Ensure svelte is installed and components are compiled`,`Check that Svelte components export default class or function`,`Verify Svelte components have proper script and style sections`],preact:[`Ensure preact and preact-render-to-string are installed`,`Check that Preact components use proper JSX import source: /** @jsxImportSource preact */`,`Verify Preact components export default function`]}[e]||[`Check that the framework is properly installed`,`Verify component syntax is correct for the detected framework`,`Consider adding explicit framework detection hints`]}}
|