@useavalon/avalon 0.2.0 → 0.2.1-canary.2

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/bin/avalon.ts CHANGED
File without changes
package/dist/mod.d.ts CHANGED
@@ -32,7 +32,7 @@ export type { IslandDirective } from "./src/types/island-prop.d.ts";
32
32
  export type { NitroCoordinationPluginOptions, NitroIntegrationResult, } from "./src/vite-plugin/nitro-integration.ts";
33
33
  export { createNitroCoordinationPlugin, createNitroIntegration, createVirtualModulesPlugin, getAvalonConfig, getViteDevServer, isDevelopmentMode, RESOLVED_VIRTUAL_IDS, VIRTUAL_MODULE_IDS, } from "./src/vite-plugin/nitro-integration.ts";
34
34
  export { avalon, getLayoutsDir, getNitroConfig, getPagesDir, getResolvedConfig, isNitroEnabled, } from "./src/vite-plugin/plugin.ts";
35
- export type { AvalonNitroConfig, AvalonPluginConfig, AvalonRuntimeConfig, CacheOptions, IntegrationName, MDXConfig, NitroConfigOutput, ResolvedAvalonConfig, ResolvedMDXConfig, RouteRule, } from "./src/vite-plugin/types.ts";
35
+ export type { AvalonNitroConfig, AvalonPluginConfig, AvalonRuntimeConfig, CacheOptions, IntegrationName, MDXConfig, NitroConfigOutput, RenderEngine, ResolvedAvalonConfig, ResolvedMDXConfig, RouteRule, } from "./src/vite-plugin/types.ts";
36
36
  export declare function build(_options?: Record<string, unknown>): Promise<void>;
37
37
  export type { IslandErrorBoundaryProps } from "./src/components/IslandErrorBoundary.tsx";
38
38
  export { IslandErrorBoundary, withIslandErrorBoundary, } from "./src/components/IslandErrorBoundary.tsx";
@@ -1 +1 @@
1
- import{render as e}from"preact-render-to-string";import{defaultCacheConfig as t,LayoutCacheManager as n}from"./layout-cache-manager.js";import{LayoutComposer as r}from"./layout-composer.js";import{LayoutDataLoader as i}from"./layout-data-loader.js";import{LayoutDiscovery as a}from"./layout-discovery.js";import{LayoutMatcher as o}from"./layout-matcher.js";function s(e,t){return e(t)}export class EnhancedLayoutResolver{layoutDiscovery;layoutMatcher;layoutComposer;layoutDataLoader;cache;cacheManager;options;constructor(e){this.options={baseDirectory:e.baseDirectory,filePattern:e.filePattern||`_layout.tsx`,excludeDirectories:e.excludeDirectories||[`node_modules`,`.git`,`dist`],enableWatching:e.enableWatching||!1,developmentMode:e.developmentMode||!1,enableCaching:e.enableCaching??!0,cacheTTL:e.cacheTTL||300*1e3,maxCacheSize:e.maxCacheSize||1e3,enableMetrics:e.enableMetrics??!0,enableDebugInfo:e.enableDebugInfo||!1},this.layoutDiscovery=new a(this.options),this.layoutMatcher=new o({developmentMode:this.options.developmentMode}),this.layoutComposer=new r(this.options),this.layoutDataLoader=new i({developmentMode:this.options.developmentMode,enableParallelLoading:!0,continueOnError:!0}),this.cache={resolved:new Map,handlers:new Map,data:new Map,ttl:new Map},this.cacheManager=new n({...t,defaultTtl:this.options.cacheTTL,maxEntries:this.options.maxCacheSize,enableStats:this.options.enableMetrics})}async resolveLayouts(e,t,n){let r=performance.now(),i=this.generateCacheKey(e,t,n);if(this.options.enableCaching){let t=this.cacheManager.getResolvedLayout(i);if(t)return this.options.developmentMode&&console.log(`[EnhancedLayoutResolver] Cache hit for route: ${e}`),{...t,metadata:{...t.metadata,cacheHit:!0}}}let a=[],o=[];try{o=await this.layoutComposer.resolveLayouts(e,t);let r=await this.layoutDataLoader.loadLayoutData(o,n),{errors:i}=this.layoutDataLoader.processLoadingResults(r,o);a.push(...i)}catch(t){a.push({layoutPath:e,errorType:`rendering`,timestamp:Date.now()}),this.options.developmentMode&&console.warn(`[EnhancedLayoutResolver] Error resolving layouts:`,t)}let s=performance.now()-r,c={handlers:o,dataLoaders:o.map(e=>e.loader).filter(e=>e!==void 0),errorBoundaries:[],streamingComponents:[],metadata:{totalLayouts:o.length,resolutionTime:s,cacheHit:!1}};if(this.options.enableCaching){this.cacheManager.setResolvedLayout(i,c);for(let e of o)this.cacheManager.addDependency(i,e.path)}return this.options.developmentMode&&(a.length>0&&console.warn(`[EnhancedLayoutResolver] ${a.length} error(s) during layout resolution for ${e}`),console.log(`[EnhancedLayoutResolver] Resolved ${o.length} layouts for ${e} in ${s.toFixed(2)}ms`)),c}async resolveAndRender(e,t,n){let r=await this.resolveLayouts(e,t,n);this.options.developmentMode&&console.log(`[EnhancedLayoutResolver] Rendering ${r.handlers.length} layouts for ${e}`);let i=await this.layoutDataLoader.loadLayoutData(r.handlers,n),{data:a}=this.layoutDataLoader.processLoadingResults(i,r.handlers);return this.options.developmentMode&&this.renderLayoutsToString(r,t,n,a),r}renderLayoutsToString(t,n,r,i=[]){try{let a=n.default??(()=>null);for(let e=t.handlers.length-1;e>=0;e--){let r=t.handlers[e].component,o=a,c=i[e]||{};a=e=>s(r,{...e,data:c,frontmatter:n.frontmatter,children:s(o,e)})}return e(s(a,{children:null,data:{},route:{path:new URL(r.request.url).pathname,params:r.params,query:r.query}}))}catch(e){return this.options.developmentMode&&console.warn(`[EnhancedLayoutResolver] Rendering failed:`,e),``}}getCachedResolution(e){return this.cacheManager.getResolvedLayout(e)}invalidateCacheByFilePath(e){return this.cacheManager.invalidateByFilePath(e)}clearCache(){this.cacheManager.clear(),this.cache.resolved.clear(),this.cache.handlers.clear(),this.cache.data.clear(),this.cache.ttl.clear(),this.layoutDiscovery.clearCache(),this.layoutComposer.clearCache()}setCaching(e){this.options.enableCaching=e,e||this.clearCache()}generateCacheKey(e,t,n){return`${e}:${t.layoutConfig?JSON.stringify(t.layoutConfig):``}:${n.request.method}:${n.request.url}`}getResolverStats(){let e=this.cacheManager.getStats(),t=this.layoutDiscovery.getCacheStats();return{cacheSize:e.totalEntries,cacheHitRate:this.cacheManager.getHitRate(),totalResolutions:e.hits+e.misses,averageResolutionTime:0,errorCount:0,cacheStats:e,discoveryStats:t}}updateOptions(e){Object.assign(this.options,e),e.developmentMode!==void 0&&this.layoutDataLoader.updateOptions({developmentMode:e.developmentMode})}getOptions(){return{...this.options}}getLayoutDiscovery(){return this.layoutDiscovery}getLayoutMatcher(){return this.layoutMatcher}getLayoutComposer(){return this.layoutComposer}getLayoutDataLoader(){return this.layoutDataLoader}getCacheManager(){return this.cacheManager}destroy(){this.cacheManager.destroy()}}export function createEnhancedLayoutResolver(e){return new EnhancedLayoutResolver(e)}export const EnhancedLayoutResolverUtils={createBasicConfig(e,t=!1){return{baseDirectory:e,developmentMode:t,enableCaching:!0,enableMetrics:t,enableDebugInfo:t}},createProductionConfig(e){return{baseDirectory:e,developmentMode:!1,enableCaching:!0,enableMetrics:!1,enableDebugInfo:!1}}};
1
+ import{renderShell as e}from"../../render/shell-engine.js";import{defaultCacheConfig as t,LayoutCacheManager as n}from"./layout-cache-manager.js";import{LayoutComposer as r}from"./layout-composer.js";import{LayoutDataLoader as i}from"./layout-data-loader.js";import{LayoutDiscovery as a}from"./layout-discovery.js";import{LayoutMatcher as o}from"./layout-matcher.js";function s(e,t){return e(t)}export class EnhancedLayoutResolver{layoutDiscovery;layoutMatcher;layoutComposer;layoutDataLoader;cache;cacheManager;options;constructor(e){this.options={baseDirectory:e.baseDirectory,filePattern:e.filePattern||`_layout.tsx`,excludeDirectories:e.excludeDirectories||[`node_modules`,`.git`,`dist`],enableWatching:e.enableWatching||!1,developmentMode:e.developmentMode||!1,enableCaching:e.enableCaching??!0,cacheTTL:e.cacheTTL||300*1e3,maxCacheSize:e.maxCacheSize||1e3,enableMetrics:e.enableMetrics??!0,enableDebugInfo:e.enableDebugInfo||!1},this.layoutDiscovery=new a(this.options),this.layoutMatcher=new o({developmentMode:this.options.developmentMode}),this.layoutComposer=new r(this.options),this.layoutDataLoader=new i({developmentMode:this.options.developmentMode,enableParallelLoading:!0,continueOnError:!0}),this.cache={resolved:new Map,handlers:new Map,data:new Map,ttl:new Map},this.cacheManager=new n({...t,defaultTtl:this.options.cacheTTL,maxEntries:this.options.maxCacheSize,enableStats:this.options.enableMetrics})}async resolveLayouts(e,t,n){let r=performance.now(),i=this.generateCacheKey(e,t,n);if(this.options.enableCaching){let t=this.cacheManager.getResolvedLayout(i);if(t)return this.options.developmentMode&&console.log(`[EnhancedLayoutResolver] Cache hit for route: ${e}`),{...t,metadata:{...t.metadata,cacheHit:!0}}}let a=[],o=[];try{o=await this.layoutComposer.resolveLayouts(e,t);let r=await this.layoutDataLoader.loadLayoutData(o,n),{errors:i}=this.layoutDataLoader.processLoadingResults(r,o);a.push(...i)}catch(t){a.push({layoutPath:e,errorType:`rendering`,timestamp:Date.now()}),this.options.developmentMode&&console.warn(`[EnhancedLayoutResolver] Error resolving layouts:`,t)}let s=performance.now()-r,c={handlers:o,dataLoaders:o.map(e=>e.loader).filter(e=>e!==void 0),errorBoundaries:[],streamingComponents:[],metadata:{totalLayouts:o.length,resolutionTime:s,cacheHit:!1}};if(this.options.enableCaching){this.cacheManager.setResolvedLayout(i,c);for(let e of o)this.cacheManager.addDependency(i,e.path)}return this.options.developmentMode&&(a.length>0&&console.warn(`[EnhancedLayoutResolver] ${a.length} error(s) during layout resolution for ${e}`),console.log(`[EnhancedLayoutResolver] Resolved ${o.length} layouts for ${e} in ${s.toFixed(2)}ms`)),c}async resolveAndRender(e,t,n){let r=await this.resolveLayouts(e,t,n);this.options.developmentMode&&console.log(`[EnhancedLayoutResolver] Rendering ${r.handlers.length} layouts for ${e}`);let i=await this.layoutDataLoader.loadLayoutData(r.handlers,n),{data:a}=this.layoutDataLoader.processLoadingResults(i,r.handlers);return this.options.developmentMode&&this.renderLayoutsToString(r,t,n,a),r}renderLayoutsToString(t,n,r,i=[]){try{let a=n.default??(()=>null);for(let e=t.handlers.length-1;e>=0;e--){let r=t.handlers[e].component,o=a,c=i[e]||{};a=e=>s(r,{...e,data:c,frontmatter:n.frontmatter,children:s(o,e)})}return e(s(a,{children:null,data:{},route:{path:new URL(r.request.url).pathname,params:r.params,query:r.query}}))}catch(e){return this.options.developmentMode&&console.warn(`[EnhancedLayoutResolver] Rendering failed:`,e),``}}getCachedResolution(e){return this.cacheManager.getResolvedLayout(e)}invalidateCacheByFilePath(e){return this.cacheManager.invalidateByFilePath(e)}clearCache(){this.cacheManager.clear(),this.cache.resolved.clear(),this.cache.handlers.clear(),this.cache.data.clear(),this.cache.ttl.clear(),this.layoutDiscovery.clearCache(),this.layoutComposer.clearCache()}setCaching(e){this.options.enableCaching=e,e||this.clearCache()}generateCacheKey(e,t,n){return`${e}:${t.layoutConfig?JSON.stringify(t.layoutConfig):``}:${n.request.method}:${n.request.url}`}getResolverStats(){let e=this.cacheManager.getStats(),t=this.layoutDiscovery.getCacheStats();return{cacheSize:e.totalEntries,cacheHitRate:this.cacheManager.getHitRate(),totalResolutions:e.hits+e.misses,averageResolutionTime:0,errorCount:0,cacheStats:e,discoveryStats:t}}updateOptions(e){Object.assign(this.options,e),e.developmentMode!==void 0&&this.layoutDataLoader.updateOptions({developmentMode:e.developmentMode})}getOptions(){return{...this.options}}getLayoutDiscovery(){return this.layoutDiscovery}getLayoutMatcher(){return this.layoutMatcher}getLayoutComposer(){return this.layoutComposer}getLayoutDataLoader(){return this.layoutDataLoader}getCacheManager(){return this.cacheManager}destroy(){this.cacheManager.destroy()}}export function createEnhancedLayoutResolver(e){return new EnhancedLayoutResolver(e)}export const EnhancedLayoutResolverUtils={createBasicConfig(e,t=!1){return{baseDirectory:e,developmentMode:t,enableCaching:!0,enableMetrics:t,enableDebugInfo:t}},createProductionConfig(e){return{baseDirectory:e,developmentMode:!1,enableCaching:!0,enableMetrics:!1,enableDebugInfo:!1}}};
@@ -15,8 +15,22 @@ export interface LayoutContext {
15
15
  }
16
16
  export type LayoutData = Record<string, unknown>;
17
17
  export type LayoutLoader = (ctx: LayoutContext) => Promise<LayoutData>;
18
- export interface LayoutProps {
19
- children: import("preact").ComponentChildren;
18
+ /**
19
+ * Props passed to a layout component.
20
+ *
21
+ * `TChildren` is the shell engine's node type. It defaults to Preact's
22
+ * `ComponentChildren` (the default engine). Under `core: "react"`, type your
23
+ * layout with `LayoutProps<ReactNode>` so `children` matches react-dom:
24
+ *
25
+ * ```tsx
26
+ * import type { ReactNode } from "react";
27
+ * import type { LayoutProps } from "@useavalon/avalon";
28
+ *
29
+ * export default function RootLayout({ children }: LayoutProps<ReactNode>) { ... }
30
+ * ```
31
+ */
32
+ export interface LayoutProps<TChildren = import("preact").ComponentChildren> {
33
+ children: TChildren;
20
34
  data: LayoutData;
21
35
  frontmatter?: Record<string, unknown>;
22
36
  route: {
@@ -1 +1 @@
1
- import{Fragment as e,h as t}from"preact";import{getIslandBundlePath as n}from"../build/island-manifest.js";import{addToManifest as r,generateComponentId as i}from"../server-islands/manifest.js";import{renderServerIsland as a}from"../server-islands/renderer.js";import{devError as o,devLog as s,devWarn as c,isDev as l,logRenderTiming as u}from"../utils/dev-logger.js";import{analyzeComponentFile as d,renderComponentSSROnly as f}from"./component-analysis.js";import{detectFramework as p}from"./framework-detection.js";import{isCustomDirective as m,serializeDirectiveScript as h}from"./hydration-directives.js";import{detectFrameworkFromPath as g,loadIntegration as _}from"./integration-loader.js";import{addModulepreload as v}from"./modulepreload-collector.js";import{generatePerIslandScript as y}from"./per-island-script.js";import{addUniversalCSS as b}from"./universal-css-collector.js";import{addUniversalHead as x}from"./universal-head-collector.js";function S(e){return`island-${e.replaceAll(/[^a-zA-Z0-9]/g,`-`)}`}function C(){return globalThis.__avalonHydrationMode===void 0?globalThis.__viteDevServer?!1:typeof __AVALON_PER_ISLAND__<`u`?__AVALON_PER_ISLAND__:!l():globalThis.__avalonHydrationMode===`per-island`}function w(r,i){if(!C()||i.shouldSkipHydration)return r;let a=n(i.src);i.condition===`on:client`&&v(a);let o=m(i.condition),s=o?h(i.condition):void 0;return t(e,null,r,t(`div`,{dangerouslySetInnerHTML:{__html:y({islandId:i.islandId,componentSrc:a,framework:i.framework,condition:i.condition,conditionArg:i.conditionArg,propsJson:JSON.stringify(i.props),isCustomDirective:o,directiveScript:s??void 0})},"data-island-script":``}))}function T(e){let t={};e.renderId&&(t[`data-solid-render-id`]=e.renderId);let n=e.metadata;return n?.tagName&&(t[`data-tag-name`]=n.tagName),t}function E(e,t,r,i,a){let o={"data-condition":t,"data-src":n(e),"data-props":JSON.stringify(r),"data-render-strategy":`hydrate`,...T(i)};if(m(t)){o[`data-custom-directive`]=t;let e=h(t);e&&(o[`data-directive-script`]=e)}return a&&(o[`data-condition-arg`]=a),o}function D(e){return e.startsWith(`<script`)?`script`:e.startsWith(`<style`)?`style`:e.startsWith(`<meta`)?`meta`:e.startsWith(`<link`)?`link`:e.includes(`window._$HY`)||e.includes(`_$HY=`)?`script`:`other`}function O(e){let t=e.match(/<style[^>]*>([\s\S]*?)<\/style>/i);return t?t[1].trim():null}function k(e,t,n,r){if(e.css&&b(e.css,t,n,e.scopeId),e.head){let i=e.head.trim(),a=D(i);if(a===`style`){let a=O(i);a&&(s(`${r} Extracting CSS from head <style> tag`),b(a,t,n,e.scopeId));return}x(e.head,t,n,a)}}function A(e){let{islandId:n,detectedFramework:r,shouldSkipHydration:i,src:a,condition:o,conditionArg:c,props:l,hydrationData:u,children:d}=e,f={id:n,"data-framework":r},p=i?{"data-render-strategy":`ssr-only`}:E(a,o,l,u,c);r===`lit`&&s(`🔍 [Island Component] ${a} - Lit hydration data:`,{hydrationDataKeys:Object.keys(u),metadata:u.metadata});let m={...f,...p},h;return h=typeof d==`string`?t(`avalon-island`,{...m,dangerouslySetInnerHTML:{__html:d}}):t(`avalon-island`,m,d),w(h,{islandId:n,src:a,condition:o,conditionArg:c,props:l,framework:r,shouldSkipHydration:i})}function j(e){let{islandId:r,detectedFramework:i,shouldSkipHydration:a,src:o,condition:s,props:c,hydrationData:l,conditionArg:u}=e;if(a)return t(`avalon-island`,{id:r,"data-render-strategy":`ssr-only`,"data-framework":i});let d={id:r,"data-condition":s,"data-src":n(o),"data-props":JSON.stringify(c),"data-render-strategy":`hydrate`,"data-framework":i,...T(l)};if(m(s)){d[`data-custom-directive`]=s;let e=h(s);e&&(d[`data-directive-script`]=e)}return u&&(d[`data-condition-arg`]=u),w(t(`avalon-island`,d),{islandId:r,src:o,condition:s,conditionArg:u,props:c,framework:i,shouldSkipHydration:a})}export default function M({src:e,condition:t=`on:client`,conditionArg:n,props:r={},children:i,ssr:a=t!==`on:client`,framework:o,ssrOnly:l=!1,renderOptions:u={},hydrationData:d={}}){let f=S(e),p=l||!!u.forceSSROnly,m=o||g(e),h=i!=null&&i!==``;return s(`🔍 [Island Component] ${e}`,{ssr:a,ssrOnly:l,hasChildren:h,framework:o,condition:t}),a&&h?A({islandId:f,detectedFramework:m,shouldSkipHydration:p,src:e,condition:t,conditionArg:n,props:r,hydrationData:d,children:i}):(a&&!h&&p&&c(`${e}: SSR-only component has no rendered content. This may indicate a rendering error.`),j({islandId:f,detectedFramework:m,shouldSkipHydration:p,src:e,condition:t,props:r,hydrationData:d,conditionArg:n}))}function N(e,r){let i=r instanceof Error?r.message:String(r);return o(`🚨 Island SSR failed for ${e}:`,r),r instanceof Error&&r.stack&&o(`Stack trace:`,r.stack),t(`avalon-island`,{id:S(e),"data-src":n(e),"data-ssr-error":i,"data-render-strategy":`client-only`})}async function P({src:e,condition:t,conditionArg:n,props:r,children:i,ssr:a,framework:s,ssrOnly:c,renderOptions:u,component:d}){let f=`🏝️ [${e}]`;if(!a||i)return M({src:e,condition:t,conditionArg:n,props:r,children:i,ssr:a,framework:s,ssrOnly:c,renderOptions:u});let p;try{p=await _(s)}catch(i){return o(`${f} Failed to load ${s} integration:`,i),M({src:e,condition:t,conditionArg:n,props:r,ssr:!1,framework:s,ssrOnly:c,renderOptions:u})}try{let i=await p.render({component:d??null,props:r,src:e,condition:t,ssrOnly:c,viteServer:globalThis.__viteDevServer,isDev:l()});return k(i,e,s,f),M({src:e,condition:t,conditionArg:n,props:r,children:i.html,ssr:!0,framework:s,ssrOnly:c,renderOptions:u,hydrationData:c?void 0:i.hydrationData})}catch(i){return o(`${f} Fast path SSR failed:`,i),M({src:e,condition:t,conditionArg:n,props:r,ssr:!1,framework:s,ssrOnly:c,renderOptions:u})}}async function F(e,t,n,r){if(t||n.detectScripts===!1)return t;try{let t=await d(e,n);if(t.decision.warnings?.length)for(let e of t.decision.warnings)c(`${r} Analysis warning: ${e}`);return!t.decision.shouldHydrate}catch(e){return c(`${r} Component analysis failed:`,e),t}}async function I(e){return e.endsWith(`.vue`)?`vue`:e.endsWith(`.svelte`)?`svelte`:e.endsWith(`.tsx`)||e.endsWith(`.jsx`)||e.endsWith(`.ts`)||e.endsWith(`.js`)?p(e):`unknown`}async function L(e,t,n,r,i,a,o){let s=await I(e),c=s,u=await(await R(s,a)).render({component:o??null,props:n,src:e,condition:t,ssrOnly:r,viteServer:globalThis.__viteDevServer,isDev:l()});return k(u,e,s,a),M({src:e,condition:t,props:n,children:u.html,ssr:!0,framework:c,ssrOnly:r,renderOptions:i,hydrationData:r?void 0:u.hydrationData})}async function R(e,t){try{s(`${t} Loading integration for framework: ${e}`);let n=await _(e);return s(`${t} ✅ Integration loaded successfully`),n}catch(n){throw o(`${t} Failed to load ${e} integration:`,n),Error(`Failed to load integration for framework '${e}'. Make sure @useavalon/${e} is installed.\nInstall it with: deno add @useavalon/${e}`,{cause:n})}}export async function renderIsland({src:o,condition:s=`on:client`,conditionArg:c,props:d={},children:f,ssr:p=s!==`on:client`,framework:m,ssrOnly:h=!1,renderOptions:_={},component:v,server:y,island:b}){let x=l()?performance.now():0,S=`🏝️ [${o}]`;try{if(y){let s=i(o);r(s,o);let c=m||g(o);return t(e,null,t(`div`,{dangerouslySetInnerHTML:{__html:a(s,d,y,b,b?n(o):void 0,o,c)},"data-server-island-wrapper":``}))}return h&&!p&&(p=!0),m?await P({src:o,condition:s,conditionArg:c,props:d,children:f,ssr:p,framework:m,ssrOnly:h,renderOptions:_,component:v}):await z({src:o,condition:s,conditionArg:c,props:d,children:f,ssr:p,ssrOnly:h,renderOptions:_,logPrefix:S,component:v})}catch(e){return N(o,e)}finally{l()&&u(o,performance.now()-x)}}async function z(e){let{src:t,condition:n,conditionArg:r,props:i,children:a,ssr:c,ssrOnly:l,renderOptions:u,logPrefix:d,component:f}=e;if(s(`🔍 [renderIsland] ${t} - Starting render (slow path)`,{ssr:c,ssrOnly:l,hasChildren:!!a,condition:n}),await F(t,l,u,d))return B(t,n,i,a,c,u,d);if(!c||a)return M({src:t,condition:n,conditionArg:r,props:i,children:a,ssr:c,renderOptions:u});try{return await L(t,n,i,l,u,d,f)}catch(e){let a=await I(t);return o(`${d} Framework rendering failed:`,e),M({src:t,condition:n,conditionArg:r,props:i,ssr:!1,framework:a,renderOptions:u})}}function B(e,t,n,r,i,a,s){return i&&!r?f({src:e,condition:t,props:n,renderOptions:a}).catch(r=>(o(`${s} SSR failed for SSR-only component:`,r),M({src:e,condition:t,props:n,ssr:!1,ssrOnly:!0,renderOptions:a}))):M({src:e,condition:t,props:n,children:r,ssr:i,ssrOnly:!0,renderOptions:a})}
1
+ import{getIslandBundlePath as e}from"../build/island-manifest.js";import{shellH as t,shellFragment as n}from"../render/shell-engine.js";import{addToManifest as r,generateComponentId as i}from"../server-islands/manifest.js";import{renderServerIsland as a}from"../server-islands/renderer.js";import{devError as o,devLog as s,devWarn as c,isDev as l,logRenderTiming as u}from"../utils/dev-logger.js";import{analyzeComponentFile as d,renderComponentSSROnly as f}from"./component-analysis.js";import{detectFramework as p}from"./framework-detection.js";import{isCustomDirective as m,serializeDirectiveScript as h}from"./hydration-directives.js";import{detectFrameworkFromPath as g,loadIntegration as _}from"./integration-loader.js";import{addModulepreload as v}from"./modulepreload-collector.js";import{generatePerIslandScript as y}from"./per-island-script.js";import{addUniversalCSS as b}from"./universal-css-collector.js";import{addUniversalHead as x}from"./universal-head-collector.js";function S(e){return`island-${e.replaceAll(/[^a-zA-Z0-9]/g,`-`)}`}function C(){return globalThis.__avalonHydrationMode===void 0?globalThis.__viteDevServer?!1:typeof __AVALON_PER_ISLAND__<`u`?__AVALON_PER_ISLAND__:!l():globalThis.__avalonHydrationMode===`per-island`}function w(r,i){if(!C()||i.shouldSkipHydration)return r;let a=e(i.src);i.condition===`on:client`&&v(a);let o=m(i.condition),s=o?h(i.condition):void 0,c=y({islandId:i.islandId,componentSrc:a,framework:i.framework,condition:i.condition,conditionArg:i.conditionArg,propsJson:JSON.stringify(i.props),isCustomDirective:o,directiveScript:s??void 0});return t(n(),null,r,t(`div`,{dangerouslySetInnerHTML:{__html:c},"data-island-script":``}))}function T(e){let t={};e.renderId&&(t[`data-solid-render-id`]=e.renderId);let n=e.metadata;return n?.tagName&&(t[`data-tag-name`]=n.tagName),t}function E(t,n,r,i,a){let o={"data-condition":n,"data-src":e(t),"data-props":JSON.stringify(r),"data-render-strategy":`hydrate`,...T(i)};if(m(n)){o[`data-custom-directive`]=n;let e=h(n);e&&(o[`data-directive-script`]=e)}return a&&(o[`data-condition-arg`]=a),o}function D(e){return e.startsWith(`<script`)?`script`:e.startsWith(`<style`)?`style`:e.startsWith(`<meta`)?`meta`:e.startsWith(`<link`)?`link`:e.includes(`window._$HY`)||e.includes(`_$HY=`)?`script`:`other`}function O(e){let t=e.match(/<style[^>]*>([\s\S]*?)<\/style>/i);return t?t[1].trim():null}function k(e,t,n,r){if(e.css&&b(e.css,t,n,e.scopeId),e.head){let i=e.head.trim(),a=D(i);if(a===`style`){let a=O(i);a&&(s(`${r} Extracting CSS from head <style> tag`),b(a,t,n,e.scopeId));return}x(e.head,t,n,a)}}function A(e){let{islandId:n,detectedFramework:r,shouldSkipHydration:i,src:a,condition:o,conditionArg:c,props:l,hydrationData:u,children:d}=e,f={id:n,"data-framework":r},p=i?{"data-render-strategy":`ssr-only`}:E(a,o,l,u,c);r===`lit`&&s(`🔍 [Island Component] ${a} - Lit hydration data:`,{hydrationDataKeys:Object.keys(u),metadata:u.metadata});let m={...f,...p},h;return h=typeof d==`string`?t(`avalon-island`,{...m,dangerouslySetInnerHTML:{__html:d}}):t(`avalon-island`,m,d),w(h,{islandId:n,src:a,condition:o,conditionArg:c,props:l,framework:r,shouldSkipHydration:i})}function j(n){let{islandId:r,detectedFramework:i,shouldSkipHydration:a,src:o,condition:s,props:c,hydrationData:l,conditionArg:u}=n;if(a)return t(`avalon-island`,{id:r,"data-render-strategy":`ssr-only`,"data-framework":i});let d={id:r,"data-condition":s,"data-src":e(o),"data-props":JSON.stringify(c),"data-render-strategy":`hydrate`,"data-framework":i,...T(l)};if(m(s)){d[`data-custom-directive`]=s;let e=h(s);e&&(d[`data-directive-script`]=e)}return u&&(d[`data-condition-arg`]=u),w(t(`avalon-island`,d),{islandId:r,src:o,condition:s,conditionArg:u,props:c,framework:i,shouldSkipHydration:a})}export default function M({src:e,condition:t=`on:client`,conditionArg:n,props:r={},children:i,ssr:a=t!==`on:client`,framework:o,ssrOnly:l=!1,renderOptions:u={},hydrationData:d={}}){let f=S(e),p=l||!!u.forceSSROnly,m=o||g(e),h=i!=null&&i!==``;return s(`🔍 [Island Component] ${e}`,{ssr:a,ssrOnly:l,hasChildren:h,framework:o,condition:t}),a&&h?A({islandId:f,detectedFramework:m,shouldSkipHydration:p,src:e,condition:t,conditionArg:n,props:r,hydrationData:d,children:i}):(a&&!h&&p&&c(`${e}: SSR-only component has no rendered content. This may indicate a rendering error.`),j({islandId:f,detectedFramework:m,shouldSkipHydration:p,src:e,condition:t,props:r,hydrationData:d,conditionArg:n}))}function N(n,r){let i=r instanceof Error?r.message:String(r);return o(`🚨 Island SSR failed for ${n}:`,r),r instanceof Error&&r.stack&&o(`Stack trace:`,r.stack),t(`avalon-island`,{id:S(n),"data-src":e(n),"data-ssr-error":i,"data-render-strategy":`client-only`})}async function P({src:e,condition:t,conditionArg:n,props:r,children:i,ssr:a,framework:s,ssrOnly:c,renderOptions:u,component:d}){let f=`🏝️ [${e}]`;if(!a||i)return M({src:e,condition:t,conditionArg:n,props:r,children:i,ssr:a,framework:s,ssrOnly:c,renderOptions:u});let p;try{p=await _(s)}catch(i){return o(`${f} Failed to load ${s} integration:`,i),M({src:e,condition:t,conditionArg:n,props:r,ssr:!1,framework:s,ssrOnly:c,renderOptions:u})}try{let i=await p.render({component:d??null,props:r,src:e,condition:t,ssrOnly:c,viteServer:globalThis.__viteDevServer,isDev:l()});return k(i,e,s,f),M({src:e,condition:t,conditionArg:n,props:r,children:i.html,ssr:!0,framework:s,ssrOnly:c,renderOptions:u,hydrationData:c?void 0:i.hydrationData})}catch(i){return o(`${f} Fast path SSR failed:`,i),M({src:e,condition:t,conditionArg:n,props:r,ssr:!1,framework:s,ssrOnly:c,renderOptions:u})}}async function F(e,t,n,r){if(t||n.detectScripts===!1)return t;try{let t=await d(e,n);if(t.decision.warnings?.length)for(let e of t.decision.warnings)c(`${r} Analysis warning: ${e}`);return!t.decision.shouldHydrate}catch(e){return c(`${r} Component analysis failed:`,e),t}}async function I(e){return e.endsWith(`.vue`)?`vue`:e.endsWith(`.svelte`)?`svelte`:e.endsWith(`.tsx`)||e.endsWith(`.jsx`)||e.endsWith(`.ts`)||e.endsWith(`.js`)?p(e):`unknown`}async function L(e,t,n,r,i,a,o){let s=await I(e),c=s,u=await(await R(s,a)).render({component:o??null,props:n,src:e,condition:t,ssrOnly:r,viteServer:globalThis.__viteDevServer,isDev:l()});return k(u,e,s,a),M({src:e,condition:t,props:n,children:u.html,ssr:!0,framework:c,ssrOnly:r,renderOptions:i,hydrationData:r?void 0:u.hydrationData})}async function R(e,t){try{s(`${t} Loading integration for framework: ${e}`);let n=await _(e);return s(`${t} ✅ Integration loaded successfully`),n}catch(n){throw o(`${t} Failed to load ${e} integration:`,n),Error(`Failed to load integration for framework '${e}'. Make sure @useavalon/${e} is installed.\nInstall it with: deno add @useavalon/${e}`,{cause:n})}}export async function renderIsland({src:o,condition:s=`on:client`,conditionArg:c,props:d={},children:f,ssr:p=s!==`on:client`,framework:m,ssrOnly:h=!1,renderOptions:_={},component:v,server:y,island:b}){let x=l()?performance.now():0,S=`🏝️ [${o}]`;try{if(y){let s=i(o);r(s,o);let c=m||g(o),l=a(s,d,y,b,b?e(o):void 0,o,c);return t(n(),null,t(`div`,{dangerouslySetInnerHTML:{__html:l},"data-server-island-wrapper":``}))}return h&&!p&&(p=!0),m?await P({src:o,condition:s,conditionArg:c,props:d,children:f,ssr:p,framework:m,ssrOnly:h,renderOptions:_,component:v}):await z({src:o,condition:s,conditionArg:c,props:d,children:f,ssr:p,ssrOnly:h,renderOptions:_,logPrefix:S,component:v})}catch(e){return N(o,e)}finally{l()&&u(o,performance.now()-x)}}async function z(e){let{src:t,condition:n,conditionArg:r,props:i,children:a,ssr:c,ssrOnly:l,renderOptions:u,logPrefix:d,component:f}=e;if(s(`🔍 [renderIsland] ${t} - Starting render (slow path)`,{ssr:c,ssrOnly:l,hasChildren:!!a,condition:n}),await F(t,l,u,d))return B(t,n,i,a,c,u,d);if(!c||a)return M({src:t,condition:n,conditionArg:r,props:i,children:a,ssr:c,renderOptions:u});try{return await L(t,n,i,l,u,d,f)}catch(e){let a=await I(t);return o(`${d} Framework rendering failed:`,e),M({src:t,condition:n,conditionArg:r,props:i,ssr:!1,framework:a,renderOptions:u})}}function B(e,t,n,r,i,a,s){return i&&!r?f({src:e,condition:t,props:n,renderOptions:a}).catch(r=>(o(`${s} SSR failed for SSR-only component:`,r),M({src:e,condition:t,props:n,ssr:!1,ssrOnly:!0,renderOptions:a}))):M({src:e,condition:t,props:n,children:r,ssr:i,ssrOnly:!0,renderOptions:a})}
@@ -1,4 +1,4 @@
1
- import{getRequestURL as e}from"h3";import{h as t}from"preact";import n from"preact-render-to-string";import{inlineCriticalCSS as r}from"../islands/critical-css.js";import{injectModulepreloadLinks as i}from"../islands/modulepreload-collector.js";import{discoverScopedMiddleware as a,executeScopedMiddleware as o}from"../middleware/index.js";import{discoverErrorPages as s,handleRenderError as c}from"./error-handler.js";import{createNotFoundError as l,isHttpError as u}from"./types.js";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 createRenderContextFromRequest(e,t={}){let n=new URL(e.url,`http://localhost`),r={method:e.method,path:n.pathname+n.search,context:{params:t}};return{url:n,params:t,query:Object.fromEntries(n.searchParams),request:e,event:r}}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 n=u(e)?e.statusCode:500;if(t){let t=_(e,n);return new Response(t,{status:n,headers:{"Content-Type":`text/html; charset=utf-8`}})}let r=v(n);return new Response(r,{status:n,headers:{"Content-Type":`text/html; charset=utf-8`}})}function _(e,t){return`<!DOCTYPE html>
1
+ import{getRequestURL as e}from"h3";import{inlineCriticalCSS as t}from"../islands/critical-css.js";import{injectModulepreloadLinks as n}from"../islands/modulepreload-collector.js";import{discoverScopedMiddleware as r,executeScopedMiddleware as i}from"../middleware/index.js";import{renderShell as a}from"../render/shell-engine.js";import{discoverErrorPages as o,handleRenderError as s}from"./error-handler.js";import{createNotFoundError as c,isHttpError as l}from"./types.js";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 createRenderContextFromRequest(e,t={}){let n=new URL(e.url,`http://localhost`),r={method:e.method,path:n.pathname+n.search,context:{params:t}};return{url:n,params:t,query:Object.fromEntries(n.searchParams),request:e,event:r}}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 n=l(e)?e.statusCode:500;if(t){let t=_(e,n);return new Response(t,{status:n,headers:{"Content-Type":`text/html; charset=utf-8`}})}let r=v(n);return new Response(r,{status:n,headers:{"Content-Type":`text/html; charset=utf-8`}})}function _(e,t){return`<!DOCTYPE html>
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8">
@@ -118,21 +118,21 @@ import{getRequestURL as e}from"h3";import{h as t}from"preact";import n from"prea
118
118
  </div>
119
119
  </body>
120
120
  </html>`}function y(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 b(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`>`,`&gt;`).replaceAll(`"`,`&quot;`).replaceAll(`'`,`&#039;`)}export function extractIslandMarkers(e){let t=[],n=/<[^>]*data-framework="([^"]+)"[^>]*>/g,r=n.exec(e);for(;r!==null;){let i=r[0],a=r[1],o=/data-src="([^"]+)"/.exec(i),s=o?o[1]:``,c=/data-props="([^"]*)"/.exec(i),l=c?c[1]:void 0,u=/data-hydrate="([^"]+)"/.exec(i),d=u?u[1]:void 0;t.push({framework:a,src:s,props:l,hydrate:d}),r=n.exec(e)}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}function x(e){return e.replaceAll(/<div[^>]*\bdata-island-script\b[^>]*>(<script[\s\S]*?<\/script>)<\/div>/g,`$1`)}export function injectHydrationScript(e,t,n={}){if(globalThis.__avalonHydrationMode===`per-island`||!t)return x(e);if(!(e.includes(`data-framework=`)||e.includes(`data-src=`))&&!n.forceInject||[`/src/client/main.js`,`/dist/client.js`,`client/main.js`,`entry-client`].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={},r){try{let i={};return e.getServerSideProps&&(i=await e.getServerSideProps(t)),{html:await S(e,i,t,n,r),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 S(e,r,i,a,o){let s=e.default,c=e.metadata||{},l=process.env.NODE_ENV!==`production`,u;try{let e=s(r);u=e instanceof Promise?await e:e}catch(e){console.error(`[renderer] Error calling page component:`,e),u=t(`div`,null,`Error rendering page`)}let d;try{d=n(u)}catch(e){console.error(`[renderer] Error in preactRenderToString:`,e),d=`<div>Error rendering page</div>`}if(o)return await o(d,e,i);let f=l?`
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={},r){try{let i={};return e.getServerSideProps&&(i=await e.getServerSideProps(t)),{html:await S(e,i,t,n,r),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 S(e,t,n,r,i){let o=e.default,s=e.metadata||{},c=process.env.NODE_ENV!==`production`,l,u=!1;try{let e=o(t);l=e instanceof Promise?await e:e}catch(e){console.error(`[renderer] Error calling page component:`,e),u=!0}let d;if(u)d=`<div>Error rendering page</div>`;else try{d=a(l)}catch(e){console.error(`[renderer] Error rendering page shell:`,e),d=`<div>Error rendering page</div>`}if(i)return await i(d,e,n);let f=c?`
122
122
  <script type="module" src="/src/client/main.js"><\/script>`:``;return`<!DOCTYPE html>
123
123
  <html lang="en">
124
124
  <head>
125
125
  <meta charset="utf-8">
126
126
  <meta name="viewport" content="width=device-width, initial-scale=1">
127
- <title>${b(String(c.title||`Avalon App`))}</title>
128
- ${c.description?`<meta name="description" content="${b(String(c.description))}">`:``}
127
+ <title>${b(String(s.title||`Avalon App`))}</title>
128
+ ${s.description?`<meta name="description" content="${b(String(s.description))}">`:``}
129
129
  </head>
130
130
  <body>
131
131
  <div id="app">
132
132
  ${d}
133
133
  </div>${f}
134
134
  </body>
135
- </html>`}export async function renderPageStream(e,t,r={}){let i=new TextEncoder,a=null,o={shellSent:!1,contentSent:!1,closed:!1,error:null},s=r.shellReadyTimeout,c=r.allReadyTimeout,l=null,u=null,d=()=>{l&&=(clearTimeout(l),null),u&&=(clearTimeout(u),null)};function f(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=E(e);r.enqueue(i.encode(t));let n=T();r.enqueue(i.encode(n))}else{let t=_(e,500);r.enqueue(i.encode(t))}n.closed=!0,r.close()}}async function p(s){a=s;let p={};e.getServerSideProps&&(p=await e.getServerSideProps(t));let m=C(e.metadata||{},t);if(o.closed||(s.enqueue(i.encode(m)),o.shellSent=!0,l&&=(clearTimeout(l),null),r.onShellReady&&r.onShellReady()),c&&c>0&&(u=setTimeout(()=>{!o.contentSent&&!o.closed&&f(Error(`All ready timeout after ${c}ms`),!1,o,a,i,d,r)},c)),!o.closed){let t=e.default;if(t&&typeof t==`function`){let r=t(p);if(r&&typeof r.then==`function`)try{let e=n(await r);s.enqueue(i.encode(` <div id="app">${e}</div>\n`))}catch(t){console.error(`[streaming] Async component error:`,t);let n=w(e,p);s.enqueue(i.encode(n))}else{let t=w(e,p);s.enqueue(i.encode(t))}}else{let t=w(e,p);s.enqueue(i.encode(t))}o.contentSent=!0}if(!o.closed){let e=T();s.enqueue(i.encode(e))}d(),r.onAllReady&&!o.closed&&r.onAllReady(),o.closed||(o.closed=!0,s.close())}return new ReadableStream({async start(e){a=e,s&&s>0&&(l=setTimeout(()=>{!o.shellSent&&!o.closed&&f(Error(`Shell ready timeout after ${s}ms`),!0,o,a,i,d,r)},s));try{await p(e)}catch(e){f(e instanceof Error?e:Error(String(e)),!o.shellSent,o,a,i,d,r)}},cancel(){if(d(),!o.closed&&a){o.closed=!0;try{a.close()}catch{}}}})}function C(e,t){return`<!DOCTYPE html>
135
+ </html>`}export async function renderPageStream(e,t,n={}){let r=new TextEncoder,i=null,o={shellSent:!1,contentSent:!1,closed:!1,error:null},s=n.shellReadyTimeout,c=n.allReadyTimeout,l=null,u=null,d=()=>{l&&=(clearTimeout(l),null),u&&=(clearTimeout(u),null)};function f(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=E(e);r.enqueue(i.encode(t));let n=T();r.enqueue(i.encode(n))}else{let t=_(e,500);r.enqueue(i.encode(t))}n.closed=!0,r.close()}}async function p(s){i=s;let p={};e.getServerSideProps&&(p=await e.getServerSideProps(t));let m=C(e.metadata||{},t);if(o.closed||(s.enqueue(r.encode(m)),o.shellSent=!0,l&&=(clearTimeout(l),null),n.onShellReady&&n.onShellReady()),c&&c>0&&(u=setTimeout(()=>{!o.contentSent&&!o.closed&&f(Error(`All ready timeout after ${c}ms`),!1,o,i,r,d,n)},c)),!o.closed){let t=e.default;if(t&&typeof t==`function`){let n=t(p);if(n&&typeof n.then==`function`)try{let e=a(await n);s.enqueue(r.encode(` <div id="app">${e}</div>\n`))}catch(t){console.error(`[streaming] Async component error:`,t);let n=w(e,p);s.enqueue(r.encode(n))}else{let t=w(e,p);s.enqueue(r.encode(t))}}else{let t=w(e,p);s.enqueue(r.encode(t))}o.contentSent=!0}if(!o.closed){let e=T();s.enqueue(r.encode(e))}d(),n.onAllReady&&!o.closed&&n.onAllReady(),o.closed||(o.closed=!0,s.close())}return new ReadableStream({async start(e){i=e,s&&s>0&&(l=setTimeout(()=>{!o.shellSent&&!o.closed&&f(Error(`Shell ready timeout after ${s}ms`),!0,o,i,r,d,n)},s));try{await p(e)}catch(e){f(e instanceof Error?e:Error(String(e)),!o.shellSent,o,i,r,d,n)}},cancel(){if(d(),!o.closed&&i){o.closed=!0;try{i.close()}catch{}}}})}function C(e,t){return`<!DOCTYPE html>
136
136
  <html lang="en">
137
137
  <head>
138
138
  <meta charset="utf-8">
@@ -141,9 +141,9 @@ import{getRequestURL as e}from"h3";import{h as t}from"preact";import n from"prea
141
141
  ${e.description?`<meta name="description" content="${b(String(e.description))}">`:``}
142
142
  </head>
143
143
  <body>
144
- `}function w(e,t){let r=e.default;if(r&&typeof r==`function`)try{let e=r(t);if(e&&typeof e.then==`function`){let e=r.name||`Page`;return` <div id="app" data-page="${b(String(e))}" data-props='${b(JSON.stringify(t))}'>
144
+ `}function w(e,t){let n=e.default;if(n&&typeof n==`function`)try{let e=n(t);if(e&&typeof e.then==`function`){let e=n.name||`Page`;return` <div id="app" data-page="${b(String(e))}" data-props='${b(JSON.stringify(t))}'>
145
145
  <!-- Async component — awaiting hydration -->
146
- </div>\n`}return` <div id="app">${n(e)}</div>\n`}catch(e){console.error(`[streaming] Error rendering page component:`,e)}let i=e.default?.name||`Page`;return` <div id="app" data-page="${b(String(i))}" data-props='${b(JSON.stringify(t))}'>
146
+ </div>\n`}return` <div id="app">${a(e)}</div>\n`}catch(e){console.error(`[streaming] Error rendering page component:`,e)}let r=e.default?.name||`Page`;return` <div id="app" data-page="${b(String(r))}" data-props='${b(JSON.stringify(t))}'>
147
147
  <!-- Component render fallback -->
148
148
  </div>\n`}function T(){return` </body>
149
149
  </html>`}function E(e){let t=process.env.NODE_ENV!==`production`,n=e.stack?`<pre style="
@@ -181,4 +181,4 @@ import{getRequestURL as e}from"h3";import{h as t}from"preact";import n from"prea
181
181
  </details>
182
182
  `:``}
183
183
  </div>
184
- `}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 D(e,t,n){return async()=>(e.value??=await a({baseDir:t,devMode:n}),e.value)}function O(e,t,n){return async(r,i)=>e?c(r,i,t):createErrorResponse(r,n)}export function createNitroRenderer(e){let{avalonConfig:t,isDev:n=!1,enableCustomErrorPages:a=!0}=e,c={isDev:n,avalonConfig:t,loadPageModule:e.loadPageModule,pagesDir:t.pagesDir};a&&s(c).catch(e=>{console.warn(`[renderer] Failed to discover error pages:`,e)});let u=D({value:null},t.srcDir||`src`,n),m=O(a,c,n);async function h(a){let s=getRequestURL(a).pathname;if(s.startsWith(`/_server-islands/`))return new Response(`Not handled by renderer`,{status:404});try{let c=await o(a,await u(),{devMode:n});if(c)return n&&console.log(`[renderer] Middleware terminated request for ${s}`),c;let f=a.context.route,p=null;if(p=f||(e.resolvePageRoute?await e.resolvePageRoute(s,t.pagesDir):await k(s,t.pagesDir)),!p)return m(l(`Page not found: ${s}`),a);let h=e.loadPageModule?await e.loadPageModule(p.filePath):await A(p.filePath),g=createRenderContext(a,a.context.params||p.params);if(e.resolveLayouts&&(g.layoutContext={layouts:await e.resolveLayouts(s,t)}),t.streaming&&!e.wrapWithLayouts){let e=await renderPageStream(h,g,{onShellReady:()=>{setResponseHeader(a,`Content-Type`,`text/html; charset=utf-8`)}});return new Response(e,{headers:{"Content-Type":`text/html; charset=utf-8`}})}else{let t=await renderPage(h,g,{},e.wrapWithLayouts),a=injectHydrationScript(t.html,n);return a=r(a),a=i(a),new Response(a,{status:t.statusCode,headers:t.headers})}}catch(e){return console.error(`[Nitro Renderer Error]`,e),m(e instanceof Error?e:Error(String(e)),a)}}return Object.assign(h,{async fetch(a){let o=new URL(a.url,`http://localhost`).pathname;if(o.startsWith(`/_server-islands/`))return new Response(`Not handled by renderer`,{status:404});try{let s=null;if(s=e.resolvePageRoute?await e.resolvePageRoute(o,t.pagesDir):await k(o,t.pagesDir),!s)return createErrorResponse(l(`Page not found: ${o}`),n);let c=await renderPage(e.loadPageModule?await e.loadPageModule(s.filePath):await A(s.filePath),createRenderContextFromRequest(a,s.params),{},e.wrapWithLayouts),u=injectHydrationScript(c.html,n);return u=r(u),u=i(u),new Response(u,{status:c.statusCode,headers:c.headers})}catch(e){return console.error(`[Nitro Renderer .fetch() Error]`,e),createErrorResponse(e instanceof Error?e:Error(String(e)),n)}}})}async function k(e,t){return e===`/`||e===``?{filePath:`src/pages/index.tsx`,pattern:`/`,params:{}}:{filePath:`src/pages/${e.replace(/^\//,``).replace(/\/$/,``)}.tsx`,pattern:e,params:{}}}async function A(e){return{default:()=>null,metadata:{title:`Avalon Page`}}}export function createNitroCatchAllRenderer(e){let{avalonConfig:t,isDev:n=!1,loadPageModule:a,resolveLayouts:c,enableCustomErrorPages:u=!0}=e,m={isDev:n,avalonConfig:t,loadPageModule:a,pagesDir:t.pagesDir};u&&s(m).catch(e=>{console.warn(`[renderer] Failed to discover error pages:`,e)});let h=D({value:null},t.srcDir||`src`,n),_=O(u,m,n);async function v(s){let u=getRequestURL(s).pathname;if(u.startsWith(`/_server-islands/`))return new Response(`Not handled by renderer`,{status:404});try{let f=await o(s,await h(),{devMode:n});if(f)return n&&console.log(`[renderer] Middleware terminated request for ${u}`),f;let p=s.context.params||{},m=p.slug||u.replace(/^\//,``)||`index`,g=`${t.pagesDir}/${m}.tsx`,v;try{v=await a(g)}catch(e){try{v=await a(`${t.pagesDir}/${m}/index.tsx`)}catch(r){return n&&(console.debug(`[renderer] Page not found: ${g}`,e),console.debug(`[renderer] Index fallback not found: ${t.pagesDir}/${m}/index.tsx`,r)),_(l(`Page not found: ${u}`),s)}}let y=createRenderContext(s,p);if(c&&(y.layoutContext={layouts:await c(u,t)}),t.streaming&&!e.wrapWithLayouts){let e=await renderPageStream(v,y,{onShellReady:()=>{setResponseHeader(s,`Content-Type`,`text/html; charset=utf-8`)}});return new Response(e,{headers:{"Content-Type":`text/html; charset=utf-8`}})}else{let t=await renderPage(v,y,{},e.wrapWithLayouts),a=injectHydrationScript(t.html,n);return a=r(a),a=i(a),new Response(a,{status:t.statusCode,headers:t.headers})}}catch(e){return console.error(`[Nitro Catch-All Renderer Error]`,e),_(e instanceof Error?e:Error(String(e)),s)}}return Object.assign(v,{async fetch(o){let s=new URL(o.url,`http://localhost`).pathname;if(s.startsWith(`/_server-islands/`))return new Response(`Not handled by renderer`,{status:404});try{let c=s.replace(/^\//,``)||`index`,u=`${t.pagesDir}/${c}.tsx`,d;try{d=await a(u)}catch{try{d=await a(`${t.pagesDir}/${c}/index.tsx`)}catch{return createErrorResponse(l(`Page not found: ${s}`),n)}}let p=createRenderContextFromRequest(o),m=await renderPage(d,p,{},e.wrapWithLayouts),h=injectHydrationScript(m.html,n);return h=r(h),h=i(h),new Response(h,{status:m.statusCode,headers:m.headers})}catch(e){return console.error(`[Nitro CatchAll .fetch() Error]`,e),createErrorResponse(e instanceof Error?e:Error(String(e)),n)}}})}export{clearMiddlewareCache as clearRendererMiddlewareCache}from"../middleware/index.js";
184
+ `}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 D(e,t,n){return async()=>(e.value??=await r({baseDir:t,devMode:n}),e.value)}function O(e,t,n){return async(r,i)=>e?s(r,i,t):createErrorResponse(r,n)}export function createNitroRenderer(e){let{avalonConfig:r,isDev:a=!1,enableCustomErrorPages:s=!0}=e,l={isDev:a,avalonConfig:r,loadPageModule:e.loadPageModule,pagesDir:r.pagesDir};s&&o(l).catch(e=>{console.warn(`[renderer] Failed to discover error pages:`,e)});let p=D({value:null},r.srcDir||`src`,a),m=O(s,l,a);async function _(o){let s=getRequestURL(o).pathname;if(s.startsWith(`/_server-islands/`))return new Response(`Not handled by renderer`,{status:404});try{let l=await i(o,await p(),{devMode:a});if(l)return a&&console.log(`[renderer] Middleware terminated request for ${s}`),l;let d=o.context.route,f=null;if(f=d||(e.resolvePageRoute?await e.resolvePageRoute(s,r.pagesDir):await k(s,r.pagesDir)),!f)return m(c(`Page not found: ${s}`),o);let g=e.loadPageModule?await e.loadPageModule(f.filePath):await A(f.filePath),_=createRenderContext(o,o.context.params||f.params);if(e.resolveLayouts&&(_.layoutContext={layouts:await e.resolveLayouts(s,r)}),r.streaming&&!e.wrapWithLayouts){let e=await renderPageStream(g,_,{onShellReady:()=>{setResponseHeader(o,`Content-Type`,`text/html; charset=utf-8`)}});return new Response(e,{headers:{"Content-Type":`text/html; charset=utf-8`}})}else{let r=await renderPage(g,_,{},e.wrapWithLayouts),i=injectHydrationScript(r.html,a);return i=t(i),i=n(i),new Response(i,{status:r.statusCode,headers:r.headers})}}catch(e){return console.error(`[Nitro Renderer Error]`,e),m(e instanceof Error?e:Error(String(e)),o)}}return Object.assign(_,{async fetch(i){let o=new URL(i.url,`http://localhost`).pathname;if(o.startsWith(`/_server-islands/`))return new Response(`Not handled by renderer`,{status:404});try{let s=null;if(s=e.resolvePageRoute?await e.resolvePageRoute(o,r.pagesDir):await k(o,r.pagesDir),!s)return createErrorResponse(c(`Page not found: ${o}`),a);let l=await renderPage(e.loadPageModule?await e.loadPageModule(s.filePath):await A(s.filePath),createRenderContextFromRequest(i,s.params),{},e.wrapWithLayouts),u=injectHydrationScript(l.html,a);return u=t(u),u=n(u),new Response(u,{status:l.statusCode,headers:l.headers})}catch(e){return console.error(`[Nitro Renderer .fetch() Error]`,e),createErrorResponse(e instanceof Error?e:Error(String(e)),a)}}})}async function k(e,t){return e===`/`||e===``?{filePath:`src/pages/index.tsx`,pattern:`/`,params:{}}:{filePath:`src/pages/${e.replace(/^\//,``).replace(/\/$/,``)}.tsx`,pattern:e,params:{}}}async function A(e){return{default:()=>null,metadata:{title:`Avalon Page`}}}export function createNitroCatchAllRenderer(e){let{avalonConfig:r,isDev:a=!1,loadPageModule:s,resolveLayouts:l,enableCustomErrorPages:p=!0}=e,m={isDev:a,avalonConfig:r,loadPageModule:s,pagesDir:r.pagesDir};p&&o(m).catch(e=>{console.warn(`[renderer] Failed to discover error pages:`,e)});let _=D({value:null},r.srcDir||`src`,a),v=O(p,m,a);async function y(o){let d=getRequestURL(o).pathname;if(d.startsWith(`/_server-islands/`))return new Response(`Not handled by renderer`,{status:404});try{let f=await i(o,await _(),{devMode:a});if(f)return a&&console.log(`[renderer] Middleware terminated request for ${d}`),f;let p=o.context.params||{},m=p.slug||d.replace(/^\//,``)||`index`,g=`${r.pagesDir}/${m}.tsx`,y;try{y=await s(g)}catch(e){try{y=await s(`${r.pagesDir}/${m}/index.tsx`)}catch(t){return a&&(console.debug(`[renderer] Page not found: ${g}`,e),console.debug(`[renderer] Index fallback not found: ${r.pagesDir}/${m}/index.tsx`,t)),v(c(`Page not found: ${d}`),o)}}let b=createRenderContext(o,p);if(l&&(b.layoutContext={layouts:await l(d,r)}),r.streaming&&!e.wrapWithLayouts){let e=await renderPageStream(y,b,{onShellReady:()=>{setResponseHeader(o,`Content-Type`,`text/html; charset=utf-8`)}});return new Response(e,{headers:{"Content-Type":`text/html; charset=utf-8`}})}else{let r=await renderPage(y,b,{},e.wrapWithLayouts),i=injectHydrationScript(r.html,a);return i=t(i),i=n(i),new Response(i,{status:r.statusCode,headers:r.headers})}}catch(e){return console.error(`[Nitro Catch-All Renderer Error]`,e),v(e instanceof Error?e:Error(String(e)),o)}}return Object.assign(y,{async fetch(i){let o=new URL(i.url,`http://localhost`).pathname;if(o.startsWith(`/_server-islands/`))return new Response(`Not handled by renderer`,{status:404});try{let l=o.replace(/^\//,``)||`index`,u=`${r.pagesDir}/${l}.tsx`,f;try{f=await s(u)}catch{try{f=await s(`${r.pagesDir}/${l}/index.tsx`)}catch{return createErrorResponse(c(`Page not found: ${o}`),a)}}let p=createRenderContextFromRequest(i),m=await renderPage(f,p,{},e.wrapWithLayouts),h=injectHydrationScript(m.html,a);return h=t(h),h=n(h),new Response(h,{status:m.statusCode,headers:m.headers})}catch(e){return console.error(`[Nitro CatchAll .fetch() Error]`,e),createErrorResponse(e instanceof Error?e:Error(String(e)),a)}}})}export{clearMiddlewareCache as clearRendererMiddlewareCache}from"../middleware/index.js";
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Shell render engine.
3
+ *
4
+ * The "shell" is the page/layout/island-wrapper tree that Avalon renders to
5
+ * HTML on the server. By default this uses Preact (`preact-render-to-string`
6
+ * + `preact`'s `h`/`Fragment`), but when a project sets `core: "react"` the
7
+ * app's SSR bundle overrides these with `react-dom/server` +
8
+ * `react`'s `createElement`/`Fragment` via the setters below.
9
+ *
10
+ * Keeping these as injected functions means the core `@useavalon/avalon`
11
+ * package never has to depend on React — the React renderer is provided by the
12
+ * app bundle (which has React installed) through the generated
13
+ * `virtual:avalon/renderer` module.
14
+ */
15
+ import { type VNode } from "preact";
16
+ /** A function that renders a shell vnode/element to an HTML string. */
17
+ export type ShellRenderToString = (vnode: unknown) => string;
18
+ /**
19
+ * A createElement/`h`-style factory. Preact's `h` and React's `createElement`
20
+ * are call-compatible; the return is typed as Preact's `VNode` (the default
21
+ * engine) so consumers like island.tsx type-check cleanly.
22
+ */
23
+ export type ShellCreateElement = (type: unknown, props?: unknown, ...children: unknown[]) => VNode;
24
+ /**
25
+ * Override the shell renderer. Called once at SSR-bundle load time by the
26
+ * generated renderer module when `core: "react"`.
27
+ */
28
+ export declare function setShellRenderToString(fn: ShellRenderToString): void;
29
+ /**
30
+ * Override the shell element factory + fragment. Called once at SSR-bundle load
31
+ * time by the generated renderer module when `core: "react"` so island/layout
32
+ * wrappers are created as React elements.
33
+ */
34
+ export declare function setShellElementFactory(createElement: ShellCreateElement, fragment: unknown): void;
35
+ /** Render a shell vnode/element to an HTML string using the active engine. */
36
+ export declare function renderShell(vnode: unknown): string;
37
+ /** Create a shell element (delegates to the active engine's createElement/h). */
38
+ export declare const shellH: ShellCreateElement;
39
+ /** The active engine's Fragment. Access via getter so overrides are picked up. */
40
+ export declare function shellFragment(): unknown;
@@ -0,0 +1 @@
1
+ import{Fragment as e,h as t}from"preact";import n from"preact-render-to-string";let r=e=>n(e),i=t,a=e;export function setShellRenderToString(e){r=e}export function setShellElementFactory(e,t){i=e,a=t}export function renderShell(e){return r(e)}export const shellH=(e,t,...n)=>i(e,t,...n);export function shellFragment(){return a}
@@ -23,9 +23,9 @@ export declare const ScriptConfigSchema: z.ZodUnion<readonly [z.ZodString, z.Zod
23
23
  integrity: z.ZodOptional<z.ZodString>;
24
24
  nomodule: z.ZodOptional<z.ZodBoolean>;
25
25
  referrerpolicy: z.ZodOptional<z.ZodEnum<{
26
- origin: "origin";
27
26
  "no-referrer": "no-referrer";
28
27
  "no-referrer-when-downgrade": "no-referrer-when-downgrade";
28
+ origin: "origin";
29
29
  "origin-when-cross-origin": "origin-when-cross-origin";
30
30
  "same-origin": "same-origin";
31
31
  "strict-origin": "strict-origin";
@@ -53,9 +53,9 @@ export declare const RenderOptionsSchema: z.ZodObject<{
53
53
  integrity: z.ZodOptional<z.ZodString>;
54
54
  nomodule: z.ZodOptional<z.ZodBoolean>;
55
55
  referrerpolicy: z.ZodOptional<z.ZodEnum<{
56
- origin: "origin";
57
56
  "no-referrer": "no-referrer";
58
57
  "no-referrer-when-downgrade": "no-referrer-when-downgrade";
58
+ origin: "origin";
59
59
  "origin-when-cross-origin": "origin-when-cross-origin";
60
60
  "same-origin": "same-origin";
61
61
  "strict-origin": "strict-origin";
@@ -18,6 +18,17 @@ declare module "preact" {
18
18
  }
19
19
  }
20
20
 
21
+ // React 19 exposes the JSX namespace on the `react` module itself (rather than
22
+ // the global `JSX`), so `core: "react"` projects need this augmentation.
23
+ declare module "react" {
24
+ namespace JSX {
25
+ interface IntrinsicAttributes {
26
+ island?: Expand<IslandDirective>;
27
+ server?: Expand<ServerIslandProp>;
28
+ }
29
+ }
30
+ }
31
+
21
32
  declare global {
22
33
  namespace JSX {
23
34
  interface IntrinsicAttributes {
@@ -1 +1 @@
1
- import{existsSync as e}from"node:fs";import{resolve as t}from"node:path";import n from"node:process";export const DEFAULT_MDX_CONFIG={jsxImportSource:`preact`,syntaxHighlighting:!0,remarkPlugins:[],rehypePlugins:[]};export const DEFAULT_IMAGE_CONFIG={enabled:!0,defaultFormat:`webp`,quality:80,widths:[200,400,600,800,1200],removeMetadata:!0,include:/^[^?]+\.(heif|avif|jpeg|jpg|png|tiff|webp|gif)(\?.*)?$/,exclude:`public/**/*`};export const DEFAULT_CONFIG={pagesDir:`src/pages`,layoutsDir:`src/layouts`,modules:null,integrations:[],mdx:DEFAULT_MDX_CONFIG,image:DEFAULT_IMAGE_CONFIG,verbose:!1,autoDiscoverIntegrations:!0,validateIntegrations:!0,showWarnings:!0,lazyIntegrations:!0};export const DEFAULT_MODULES_CONFIG={pagesDirName:`pages`,layoutsDirName:`layouts`};function s(e){return e?typeof e==`string`?{dir:e,pagesDirName:DEFAULT_MODULES_CONFIG.pagesDirName,layoutsDirName:DEFAULT_MODULES_CONFIG.layoutsDirName}:{dir:e.dir,pagesDirName:e.pagesDirName??DEFAULT_MODULES_CONFIG.pagesDirName,layoutsDirName:e.layoutsDirName??DEFAULT_MODULES_CONFIG.layoutsDirName}:null}function c(e){return e===!1?{...DEFAULT_IMAGE_CONFIG,enabled:!1}:e===void 0||e===!0?DEFAULT_IMAGE_CONFIG:{enabled:e.enabled??DEFAULT_IMAGE_CONFIG.enabled,defaultFormat:e.defaultFormat??DEFAULT_IMAGE_CONFIG.defaultFormat,quality:e.quality??DEFAULT_IMAGE_CONFIG.quality,widths:e.widths??DEFAULT_IMAGE_CONFIG.widths,removeMetadata:e.removeMetadata??DEFAULT_IMAGE_CONFIG.removeMetadata,include:e.include??DEFAULT_IMAGE_CONFIG.include,exclude:e.exclude??DEFAULT_IMAGE_CONFIG.exclude}}export function resolveConfig(e,t){let n=e??{},i=s(n.modules),o=c(n.image);return{pagesDir:n.pagesDir??DEFAULT_CONFIG.pagesDir,layoutsDir:n.layoutsDir??DEFAULT_CONFIG.layoutsDir,modules:i,integrations:n.integrations??DEFAULT_CONFIG.integrations,mdx:{jsxImportSource:n.mdx?.jsxImportSource??DEFAULT_MDX_CONFIG.jsxImportSource,syntaxHighlighting:n.mdx?.syntaxHighlighting??DEFAULT_MDX_CONFIG.syntaxHighlighting,remarkPlugins:n.mdx?.remarkPlugins??DEFAULT_MDX_CONFIG.remarkPlugins,rehypePlugins:n.mdx?.rehypePlugins??DEFAULT_MDX_CONFIG.rehypePlugins},image:o,verbose:n.verbose??DEFAULT_CONFIG.verbose,autoDiscoverIntegrations:n.autoDiscoverIntegrations??DEFAULT_CONFIG.autoDiscoverIntegrations,validateIntegrations:n.validateIntegrations??DEFAULT_CONFIG.validateIntegrations,showWarnings:n.showWarnings??DEFAULT_CONFIG.showWarnings,lazyIntegrations:n.lazyIntegrations??DEFAULT_CONFIG.lazyIntegrations,isDev:t}}export function checkDirectoriesExist(r,i=n.cwd()){let a=[];!r.modules&&r.pagesDir&&a.push({path:r.pagesDir,type:`pages`}),r.layoutsDir&&a.push({path:r.layoutsDir,type:`layouts`});let o=[];for(let{path:n,type:s}of a){let a=t(i,n),c=e(a);o.push({path:n,absolutePath:a,exists:c,type:s}),!c&&r.showWarnings&&console.warn(`⚠️ Avalon: ${s} directory '${n}' does not exist (resolved to: ${a}). This directory will be skipped.`)}return o}export function logDirectoryCheckSummary(e,t){let n=e.filter(e=>!e.exists),r=e.filter(e=>e.exists);t&&(r.length>0&&console.log(` ✅ Found directories: ${r.map(e=>e.path).join(`, `)}`),n.length>0&&console.log(` ⚠️ Missing directories: ${n.map(e=>e.path).join(`, `)}`))}
1
+ import{existsSync as e}from"node:fs";import{resolve as t}from"node:path";import n from"node:process";export const DEFAULT_MDX_CONFIG={jsxImportSource:`preact`,syntaxHighlighting:!0,remarkPlugins:[],rehypePlugins:[]};export const DEFAULT_IMAGE_CONFIG={enabled:!0,defaultFormat:`webp`,quality:80,widths:[200,400,600,800,1200],removeMetadata:!0,include:/^[^?]+\.(heif|avif|jpeg|jpg|png|tiff|webp|gif)(\?.*)?$/,exclude:`public/**/*`};export const DEFAULT_CONFIG={core:`preact`,pagesDir:`src/pages`,layoutsDir:`src/layouts`,modules:null,integrations:[],mdx:DEFAULT_MDX_CONFIG,image:DEFAULT_IMAGE_CONFIG,verbose:!1,autoDiscoverIntegrations:!0,validateIntegrations:!0,showWarnings:!0,lazyIntegrations:!0};export const DEFAULT_MODULES_CONFIG={pagesDirName:`pages`,layoutsDirName:`layouts`};function s(e){return e?typeof e==`string`?{dir:e,pagesDirName:DEFAULT_MODULES_CONFIG.pagesDirName,layoutsDirName:DEFAULT_MODULES_CONFIG.layoutsDirName}:{dir:e.dir,pagesDirName:e.pagesDirName??DEFAULT_MODULES_CONFIG.pagesDirName,layoutsDirName:e.layoutsDirName??DEFAULT_MODULES_CONFIG.layoutsDirName}:null}function c(e){return e===!1?{...DEFAULT_IMAGE_CONFIG,enabled:!1}:e===void 0||e===!0?DEFAULT_IMAGE_CONFIG:{enabled:e.enabled??DEFAULT_IMAGE_CONFIG.enabled,defaultFormat:e.defaultFormat??DEFAULT_IMAGE_CONFIG.defaultFormat,quality:e.quality??DEFAULT_IMAGE_CONFIG.quality,widths:e.widths??DEFAULT_IMAGE_CONFIG.widths,removeMetadata:e.removeMetadata??DEFAULT_IMAGE_CONFIG.removeMetadata,include:e.include??DEFAULT_IMAGE_CONFIG.include,exclude:e.exclude??DEFAULT_IMAGE_CONFIG.exclude}}export function resolveConfig(e,t){let n=e??{},i=s(n.modules),o=c(n.image),l=n.core??DEFAULT_CONFIG.core;return{core:l,pagesDir:n.pagesDir??DEFAULT_CONFIG.pagesDir,layoutsDir:n.layoutsDir??DEFAULT_CONFIG.layoutsDir,modules:i,integrations:n.integrations??DEFAULT_CONFIG.integrations,mdx:{jsxImportSource:n.mdx?.jsxImportSource??l,syntaxHighlighting:n.mdx?.syntaxHighlighting??DEFAULT_MDX_CONFIG.syntaxHighlighting,remarkPlugins:n.mdx?.remarkPlugins??DEFAULT_MDX_CONFIG.remarkPlugins,rehypePlugins:n.mdx?.rehypePlugins??DEFAULT_MDX_CONFIG.rehypePlugins},image:o,verbose:n.verbose??DEFAULT_CONFIG.verbose,autoDiscoverIntegrations:n.autoDiscoverIntegrations??DEFAULT_CONFIG.autoDiscoverIntegrations,validateIntegrations:n.validateIntegrations??DEFAULT_CONFIG.validateIntegrations,showWarnings:n.showWarnings??DEFAULT_CONFIG.showWarnings,lazyIntegrations:n.lazyIntegrations??DEFAULT_CONFIG.lazyIntegrations,isDev:t}}export function checkDirectoriesExist(r,i=n.cwd()){let a=[];!r.modules&&r.pagesDir&&a.push({path:r.pagesDir,type:`pages`}),r.layoutsDir&&a.push({path:r.layoutsDir,type:`layouts`});let o=[];for(let{path:n,type:s}of a){let a=t(i,n),c=e(a);o.push({path:n,absolutePath:a,exists:c,type:s}),!c&&r.showWarnings&&console.warn(`⚠️ Avalon: ${s} directory '${n}' does not exist (resolved to: ${a}). This directory will be skipped.`)}return o}export function logDirectoryCheckSummary(e,t){let n=e.filter(e=>!e.exists),r=e.filter(e=>e.exists);t&&(r.length>0&&console.log(` ✅ Found directories: ${r.map(e=>e.path).join(`, `)}`),n.length>0&&console.log(` ⚠️ Missing directories: ${n.map(e=>e.path).join(`, `)}`))}
@@ -44,13 +44,6 @@ export interface NitroCoordinationPluginOptions {
44
44
  nitroConfig: AvalonNitroConfig;
45
45
  verbose?: boolean;
46
46
  }
47
- /**
48
- * Creates the Nitro integration for Avalon — configuration, virtual modules,
49
- * build plugins, and SSR coordination.
50
- *
51
- * Uses the Nitro v3 Vite plugin from `nitro/vite` for server route discovery,
52
- * SSR rendering pipeline, and Rolldown-optimized bundling.
53
- */
54
47
  export declare function createNitroIntegration(avalonConfig: ResolvedAvalonConfig, nitroConfig?: AvalonNitroConfig): NitroIntegrationResult;
55
48
  /**
56
49
  * Coordination plugin: stores config/server refs, sets up SSR middleware and HMR,
@@ -62,14 +55,6 @@ export declare function createNitroCoordinationPlugin(options: NitroCoordination
62
55
  */
63
56
  export declare function createVirtualModulesPlugin(options: NitroCoordinationPluginOptions): Plugin;
64
57
  export declare function generateConfigModule(avalonConfig: ResolvedAvalonConfig, nitroConfig: AvalonNitroConfig): string;
65
- /**
66
- * Generate the integration loader virtual module.
67
- *
68
- * Only includes dynamic import() calls for frameworks that are actually
69
- * configured in the avalon() config. This prevents Vite from trying to
70
- * resolve @useavalon/vue/client, @useavalon/svelte/client, etc. when
71
- * only preact is configured.
72
- */
73
58
  export declare function generateIntegrationLoaderModule(avalonConfig: ResolvedAvalonConfig): string;
74
59
  export declare function getViteDevServer(): ViteDevServer | undefined;
75
60
  export declare function getAvalonConfig(): ResolvedAvalonConfig | undefined;
@@ -1,40 +1,31 @@
1
- import{existsSync as e,readdirSync as t,readFileSync as n,rmSync as r}from"node:fs";import{stat as i}from"node:fs/promises";import{createRequire as a}from"node:module";import{dirname as o,join as s,relative as c,resolve as l}from"node:path";import{nitro as u}from"nitro/vite";import{isRunnableDevEnvironment as d}from"vite";import{generateActionTypes as f}from"../build/actions-types-generator.js";import{getUniversalCSSForHead as p}from"../islands/universal-css-collector.js";import{getUniversalHeadForInjection as m,injectSolidHydrationScriptIfNeeded as h}from"../islands/universal-head-collector.js";import{clearMiddlewareCache as g,discoverScopedMiddleware as _,executeScopedMiddleware as v}from"../middleware/index.js";import{createNitroConfig as y}from"../nitro/config.js";import{createIslandManifestPlugin as b,createNitroBuildPlugin as x,createSourceMapConfig as S,createSourceMapPlugin as C}from"../nitro/index.js";import{collectCssFromModuleGraph as w,injectSsrCss as T}from"../render/collect-css.js";import{generateErrorPage as E,generateFallback404 as D}from"../render/error-pages.js";import{generateComponentId as O}from"../server-islands/manifest.js";import{resolveToRelativePath as k}from"./server-islands-plugin.js";function A(e){let t=ee(e),r=Object.entries(t),i=`export const serverIslandManifest = ${JSON.stringify(t)};\n\n`;i+=`export const serverIslandLoaders = {
1
+ import{existsSync as e,readdirSync as t,readFileSync as n,rmSync as r}from"node:fs";import{stat as i}from"node:fs/promises";import{createRequire as a}from"node:module";import{dirname as o,join as s,relative as c,resolve as l}from"node:path";import{nitro as u}from"nitro/vite";import{isRunnableDevEnvironment as d}from"vite";import{generateActionTypes as f}from"../build/actions-types-generator.js";import{getUniversalCSSForHead as p}from"../islands/universal-css-collector.js";import{getUniversalHeadForInjection as m,injectSolidHydrationScriptIfNeeded as h}from"../islands/universal-head-collector.js";import{clearMiddlewareCache as g,discoverScopedMiddleware as _,executeScopedMiddleware as v}from"../middleware/index.js";import{createNitroConfig as y}from"../nitro/config.js";import{createIslandManifestPlugin as b,createNitroBuildPlugin as x,createSourceMapConfig as S,createSourceMapPlugin as C}from"../nitro/index.js";import{collectCssFromModuleGraph as w,injectSsrCss as T}from"../render/collect-css.js";import{generateErrorPage as E,generateFallback404 as D}from"../render/error-pages.js";import{generateComponentId as O}from"../server-islands/manifest.js";import{resolveToRelativePath as ee}from"./server-islands-plugin.js";function te(e){let t=ae(e),r=Object.entries(t),i=`export const serverIslandManifest = ${JSON.stringify(t)};\n\n`;i+=`export const serverIslandLoaders = {
2
2
  `;for(let[e,t]of r)i+=` ${JSON.stringify(e)}: () => import(${JSON.stringify(t)}),\n`;i+=`};
3
3
 
4
- `;let a={};for(let[t,i]of r)if(i.endsWith(`.svelte`))try{let r=n(s(e,i.startsWith(`/`)?i.slice(1):i),`utf8`).match(/<style[^>]*>([\s\S]*?)<\/style>/);r&&(a[t]=r[1].trim())}catch{}return i+=`export const serverIslandCSS = ${JSON.stringify(a)};\n`,i}const j=/^[ \t]*import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/gm,M=new Set([`node_modules`,`dist`,`.output`,`.netlify`,`.vercel`,`.cloudflare`,`.wrangler`,`.firebase`,`.amplify-hosting`,`.git`]);function N(e,t){return new RegExp(String.raw`<${t}\s[\s\S]*?\bserver\s*[={/>]`).test(e)}function P(e,n){let r;try{r=t(e,{withFileTypes:!0})}catch{return}for(let t of r){let r=s(e,t.name);if(t.isDirectory()){if(M.has(t.name))continue;P(r,n)}else if(t.isFile()){if(!/\.(tsx|jsx)$/.test(t.name)||/\.(test|spec)\.[jt]sx$/.test(t.name)||r.includes(`__tests__`))continue;n.push(r)}}}function ee(t){let r={},i=[];for(let n of[`app`,`src`]){let r=s(t,n);e(r)&&P(r,i)}for(let e of i){let i;try{i=n(e,`utf8`)}catch{continue}if(!/\bserver\s*[={/>]/.test(i))continue;j.lastIndex=0;let a=j.exec(i);for(;a!==null;a=j.exec(i)){let n=a[1],o=a[2].slice(1,-1);if(!N(i,n))continue;let s=k(o,e,t),c=O(s);c in r||(r[c]=s)}}return r}function F(t){let n=[`ts`,`tsx`,`js`,`jsx`,`mts`,`mjs`];for(let r of[`app`,`src`])for(let i of n){let n=`/${r}/actions/index.${i}`;if(e(s(t,n.slice(1))))return n}}function I(e){let t=F(e);return t?`export { server } from ${JSON.stringify(t)};\n`:`export const server = {};
5
- `}function te(){return[`import { createActionClient } from "@useavalon/avalon/actions";`,`export const actions = createActionClient();`,`export default actions;`,``].join(`
6
- `)}function L(t){let n=s(o(a(import.meta.url).resolve(`@useavalon/avalon`)),t);if(t.endsWith(`.ts`)&&!e(n)){let t=n.replace(/\.ts$/,`.js`);if(e(t))return t}return n}function ne(t,n){let r=s(o(a(s(process.cwd(),`package.json`)).resolve(`@useavalon/${t}`)),n);if(n.endsWith(`.ts`)&&!e(r)){let t=r.replace(/\.ts$/,`.js`);if(e(t))return t}return r}export const VIRTUAL_MODULE_IDS={PAGE_ROUTES:`virtual:avalon/page-routes`,PAGE_LOADER:`virtual:avalon/page-loader`,ISLAND_MANIFEST:`virtual:avalon/island-manifest`,RUNTIME_CONFIG:`virtual:avalon/runtime-config`,CONFIG:`virtual:avalon/config`,LAYOUTS:`virtual:avalon/layouts`,ASSETS:`virtual:avalon/assets`,RENDERER:`virtual:avalon/renderer`,CLIENT_ENTRY:`virtual:avalon/client-entry`,INTEGRATION_LOADER:`virtual:avalon/integration-loader`,ACTIONS:`virtual:avalon/actions`};export const RESOLVED_VIRTUAL_IDS={PAGE_ROUTES:`\0${VIRTUAL_MODULE_IDS.PAGE_ROUTES}`,PAGE_LOADER:`\0${VIRTUAL_MODULE_IDS.PAGE_LOADER}`,ISLAND_MANIFEST:`\0${VIRTUAL_MODULE_IDS.ISLAND_MANIFEST}`,RUNTIME_CONFIG:`\0${VIRTUAL_MODULE_IDS.RUNTIME_CONFIG}`,CONFIG:`\0${VIRTUAL_MODULE_IDS.CONFIG}`,LAYOUTS:`\0${VIRTUAL_MODULE_IDS.LAYOUTS}`,ASSETS:`\0${VIRTUAL_MODULE_IDS.ASSETS}`,RENDERER:`\0${VIRTUAL_MODULE_IDS.RENDERER}`,CLIENT_ENTRY:`\0${VIRTUAL_MODULE_IDS.CLIENT_ENTRY}`,INTEGRATION_LOADER:`\0${VIRTUAL_MODULE_IDS.INTEGRATION_LOADER}`,ACTIONS:`\0${VIRTUAL_MODULE_IDS.ACTIONS}`};export function createNitroIntegration(e,t={}){let n=y(t,e),r=process.cwd(),i=L(`src/server-islands/route.ts`),a=L(`src/actions/route.ts`),o={preset:n.preset,serverDir:t.serverDir??n.serverDir??`./server`,routeRules:n.routeRules,runtimeConfig:n.runtimeConfig,compatibilityDate:n.compatibilityDate,scanDirs:[`.`],noExternals:[`estree-walker`,/^@useavalon\//,/^estree-util/,/^preact/,/^react/,/^react-dom/,/^vue/,/^@vue\//],handlers:[{route:`/_server-islands/**`,handler:i},{route:`/_actions/**`,handler:a}],virtual:{"virtual:server-island-manifest":()=>A(r),"virtual:avalon-actions-manifest":()=>I(r),"virtual:server-island-key":()=>{let e=process.env.AVALON_KEY??``;return`export const serverIslandKey = ${JSON.stringify(e)};\n`},"virtual:server-island-integrations":()=>`
7
- import { registry } from "${L(`src/core/integrations/registry.ts`)}";
8
- import { solidIntegration } from "@useavalon/solid";
9
- import { vueIntegration } from "@useavalon/vue";
10
- import { svelteIntegration } from "@useavalon/svelte";
11
- import { litIntegration } from "@useavalon/lit";
12
- if (solidIntegration) registry.register(solidIntegration);
13
- if (vueIntegration) registry.register(vueIntegration);
14
- if (svelteIntegration) registry.register(svelteIntegration);
15
- if (litIntegration) registry.register(litIntegration);
16
- `}};t.renderer===!1?o.renderer=!1:n.renderer&&(o.renderer=n.renderer),n.publicRuntimeConfig&&(o.publicRuntimeConfig=n.publicRuntimeConfig),n.publicAssets&&(o.publicAssets=n.publicAssets),n.compressPublicAssets&&(o.compressPublicAssets=n.compressPublicAssets),n.serverEntry&&(o.serverEntry=n.serverEntry);let s=n.traceDeps??[];o.traceDeps=[...new Set([`undici`,...s])],n.prerender&&(o.prerender={routes:[],crawlLinks:!1});let c=u(o),l=createNitroCoordinationPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),d=createVirtualModulesPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),f=x(e,t),p=b(e,{verbose:e.verbose,generatePreloadHints:!0}),m=C(S(t.preset??`node_server`,e.isDev));return{nitroOptions:n,plugins:[...Array.isArray(c)?c:[c],l,d,f,p,m]}}export function createNitroCoordinationPlugin(e){let{avalonConfig:t,verbose:n}=e;return{name:`avalon:nitro-coordination`,enforce:`pre`,config(e,{command:t}){if(t===`serve`)return{server:{watch:{ignored:[`**/.output/**`,`**/dist/**`,`**/.netlify/**`,`**/.vercel/**`,`**/.cloudflare/**`,`**/.wrangler/**`,`**/.firebase/**`,`**/.amplify-hosting/**`]},fs:{deny:[`.output`,`dist`,`.netlify`,`.vercel`,`.cloudflare`,`.wrangler`,`.firebase`,`.amplify-hosting`]}}}},configResolved(e){globalThis.__avalonHydrationMode=e.command===`serve`?`entry-client`:`per-island`;try{f(e.root||process.cwd())}catch{}},configureServer(e){globalThis.__viteDevServer=e;let i=e.config.root||process.cwd(),a=e=>{if(e.includes(`/actions/`))try{f(i)}catch{}};e.watcher.on(`add`,a),e.watcher.on(`unlink`,a);let o=e.config.root||process.cwd(),c=e.config.build?.outDir?s(o,e.config.build.outDir):s(o,`dist`);try{r(c,{recursive:!0,force:!0})}catch{}try{r(s(o,`.output`),{recursive:!0,force:!0})}catch{}let l=!1,u=new Promise(t=>{let n=()=>{(e.environments?.nitro)?.devServer?.entry||l?(l=!0,t()):setTimeout(n,50)};setTimeout(n,100),setTimeout(()=>{l=!0,t()},15e3)});e.middlewares.use(async(e,t,n)=>{if(l)return n();let r=e.url||`/`;if(r.startsWith(`/@`)||r.startsWith(`/__`)||/\/[^/]+\.[a-z0-9]+(\?|$)/i.test(r))return n();await u,n()});let p=null;async function m(){return p||=await _({baseDir:`${e.config.root||process.cwd()}/src`,devMode:!1}),p}function h(){p=null}oe(e,t,n,h),m().catch(e=>{console.warn(`[middleware] Failed to discover middleware:`,e)});let g=e.environments?.ssr,v=!!g&&d(g);v&&ae(e,t.integrations,n).catch(e=>{console.error(`[prewarm] Core modules pre-warm failed:`,e)}),e.middlewares.use(async(t,n,r)=>{let i=t.url||`/`;if(!i.startsWith(`/_server-islands/`)||!v)return r();try{let{decrypt:r}=await e.ssrLoadModule(L(`src/server-islands/encryption.ts`)),{h:a}=await e.ssrLoadModule(`preact`),o=(await e.ssrLoadModule(`preact-render-to-string`)).default,s=new URL(i,`http://${t.headers.host||`localhost`}`).searchParams.get(`p`)||``;if(!s&&t.method===`POST`&&(s=await new Promise((e,n)=>{let r=[],i=e=>r.push(e),a=()=>{c(),e(Buffer.concat(r).toString(`utf8`))},o=e=>{c(),n(e)},s=setTimeout(()=>{c(),n(Error(`Timed out reading server island request body`))},15e3);function c(){clearTimeout(s),t.off(`data`,i),t.off(`end`,a),t.off(`error`,o)}t.on(`data`,i),t.on(`end`,a),t.on(`error`,o)})),!s){n.statusCode=400,n.setHeader(`Content-Type`,`text/plain`),n.end(`Missing encrypted props`);return}let c,l,u;try{let e;if(s.startsWith(`dev.`)){let t=s.slice(4);e=Buffer.from(t,`base64url`).toString(`utf8`)}else e=r(s);let t=JSON.parse(e);t.__island&&(u=t.__island,delete t.__island),t.__src&&(l=t.__src,delete t.__src),c=t}catch{n.statusCode=400,n.setHeader(`Content-Type`,`text/plain`),n.end(`Bad Request: decryption failed`);return}if(!l){n.statusCode=404,n.setHeader(`Content-Type`,`text/plain`),n.end(`Component not found (no __src in payload)`);return}let d=(await e.ssrLoadModule(l)).default;if(typeof d!=`function`){n.statusCode=500,n.setHeader(`Content-Type`,`text/plain`),n.end(`Module "${l}" does not export a default component function`);return}let f=o(a(d,c));if(u){let e=i.split(`/`)[2]?.split(`?`)[0]||``,t=u.elementId??`si-${e}`,n=u.componentSrc??l,r=JSON.stringify(c),a=u.condition??`on:client`,o=u.framework??`preact`,s=`<script type="module">
17
- import{hydrateServerIsland}from"/@fs${L(`src/client/server-island-hydrate.ts`)}";
18
- hydrateServerIsland(${JSON.stringify(t)},${JSON.stringify(n)},${r},${JSON.stringify(a)},${JSON.stringify(o)});
19
- <\/script>`;f+=s}n.statusCode=200,n.setHeader(`Content-Type`,`text/html`),n.setHeader(`Cache-Control`,`private, no-store`),n.end(f)}catch(e){console.error(`[server-islands] Dev handler error:`,e),n.statusCode=500,n.setHeader(`Content-Type`,`text/plain`),n.end(`Server island render failed: ${e instanceof Error?e.message:String(e)}`)}}),e.middlewares.use(async(t,n,r)=>{let i=t.url||`/`;if(!i.startsWith(`/_actions/`)||!v)return r();try{let r=F(e.config.root||process.cwd()),[a,o,s]=await Promise.all([e.ssrLoadModule(L(`src/actions/endpoint.ts`)),e.ssrLoadModule(L(`src/actions/registry.ts`)),r?e.ssrLoadModule(r):Promise.resolve({server:{}})]),c=o.flattenActions(s.server),l=a.defineActionHandler({registry:c,isDev:!0}),u=new URL(i,`http://${t.headers.host||`localhost`}`),d=(t.method||`GET`).toUpperCase(),f;d===`POST`&&(f=await new Promise((e,n)=>{let r=[],i=e=>r.push(e),a=()=>{c(),e(Buffer.concat(r).toString(`utf8`))},o=e=>{c(),n(e)},s=setTimeout(()=>{c(),n(Error(`Timed out reading action request body`))},15e3);function c(){clearTimeout(s),t.off(`data`,i),t.off(`end`,a),t.off(`error`,o)}t.on(`data`,i),t.on(`end`,a),t.on(`error`,o)}));let p=await l({url:u,web:{request:new Request(u,{method:d,headers:t.headers,body:f})},context:{}});n.statusCode=p.status,p.headers.forEach((e,t)=>{n.setHeader(t,e)}),n.end(await p.text())}catch(e){console.error(`[actions] Dev handler error:`,e),n.statusCode=500,n.setHeader(`Content-Type`,`application/json`),n.end(JSON.stringify({error:{code:`INTERNAL_SERVER_ERROR`,message:e instanceof Error?e.message:String(e)}}))}}),e.middlewares.use(async(r,i,a)=>{if(!v)return a();let o=r.url||`/`;if(o.endsWith(`.html`)&&(o=o.slice(0,-5)||`/`),o===`/index`&&(o=`/`),o.startsWith(`/@`)||o.startsWith(`/__`)||o.startsWith(`/node_modules/`)||o.startsWith(`/src/client/`)||o.startsWith(`/packages/`)||o.includes(`.`)&&!o.endsWith(`/`)||o.startsWith(`/api/`))return a();try{if(await re(e,o,r,i,m,n)||await se(e,o,t,i))return;let a=await Y(e,o,t);if(a){i.statusCode=200,i.setHeader(`Content-Type`,`text/html`),i.end(a);return}await ie(e,o,i,t)}catch(e){console.error(`[SSR Error]`,e),i.statusCode=500,i.setHeader(`Content-Type`,`text/html`),i.end(E(e))}})},buildStart(){}}}async function re(e,t,n,r,i,a){let o=performance.now(),s=await i();if(s.length===0)return!1;let c={};for(let[e,t]of Object.entries(n.headers))typeof t==`string`?c[e]=t:Array.isArray(t)&&(c[e]=t.join(`, `));let l=`http://${n.headers.host||`localhost`}${t}`,u=await v({url:l,method:n.method||`GET`,path:t,node:{req:n,res:r},req:new Request(l,{method:n.method||`GET`,headers:c}),context:{}},s,{devMode:!1}),d=performance.now()-o;return d>100&&console.warn(`⚠️ Slow middleware: ${d.toFixed(0)}ms for ${t}`),u?(r.statusCode=u.status,u.headers.forEach((e,t)=>{r.setHeader(t,e)}),r.end(await u.text()),!0):!1}async function ie(e,t,n,r){try{let{discoverErrorPages:i,getErrorPageModule:a,generateDefaultErrorPage:o}=await import(`../nitro/error-handler.js`),s=a(404,await i({isDev:r.isDev,pagesDir:r.pagesDir,loadPageModule:async t=>await e.ssrLoadModule(t)}));if(s?.default&&typeof s.default==`function`){let{renderToHtml:e}=await import(`../render/ssr.js`),r=s.default,i=await e({component:()=>r({statusCode:404,message:`Page not found: ${t}`,url:t})},{});n.statusCode=404,n.setHeader(`Content-Type`,`text/html`),n.end(i);return}let c=o(404,`Page not found: ${t}`,r.isDev);n.statusCode=404,n.setHeader(`Content-Type`,`text/html`),n.end(c)}catch{n.statusCode=404,n.setHeader(`Content-Type`,`text/html`),n.end(D(t))}}async function ae(e,t,n){let r=performance.now(),i=[{path:L(`src/render/ssr.ts`),assignTo:`ssr`},{path:L(`src/core/layout/enhanced-layout-resolver.ts`),assignTo:`layout`},{path:L(`src/middleware/index.ts`),assignTo:null},...t.map(e=>({path:ne(e,`server/renderer.ts`),assignTo:null}))],a=(await Promise.allSettled(i.map(async({path:t,assignTo:n})=>{let r=await e.ssrLoadModule(t);n===`ssr`&&(q=r),n===`layout`&&(J=r)}))).filter(e=>e.status===`fulfilled`).length,o=performance.now()-r;n&&a>0&&console.log(`🔥 SSR ready in ${o.toFixed(0)}ms (${a}/${i.length} core modules)`)}export function createVirtualModulesPlugin(e){let{avalonConfig:n,nitroConfig:r,verbose:i}=e,a=null,o=s,u=c,d=l,f=process.cwd(),p=[];function m(e){try{let n=t(e,{withFileTypes:!0});for(let t of n){let n=o(e,t.name);if(t.isDirectory()&&t.name!==`node_modules`&&!t.name.startsWith(`.`))m(n);else if(t.isFile()&&t.name.endsWith(`.css`)){let e=u(f,n).replaceAll(`\\`,`/`);p.push(e.startsWith(`/`)?e:`/${e}`)}}}catch{}}function h(){p.length=0;for(let e of r.globalCSS??[])p.push(e.startsWith(`/`)?e:`/${e}`);n.modules&&m(d(f,n.modules.dir)),m(d(f,n.layoutsDir));let e=d(f,n.layoutsDir,`..`);e!==f&&e!==d(f,n.layoutsDir)&&e.startsWith(f)&&m(e)}return n.isDev&&h(),{name:`avalon:nitro-virtual-modules`,enforce:`pre`,resolveId(e){return e===VIRTUAL_MODULE_IDS.PAGE_ROUTES?RESOLVED_VIRTUAL_IDS.PAGE_ROUTES:e===VIRTUAL_MODULE_IDS.PAGE_LOADER?RESOLVED_VIRTUAL_IDS.PAGE_LOADER:e===VIRTUAL_MODULE_IDS.ISLAND_MANIFEST?RESOLVED_VIRTUAL_IDS.ISLAND_MANIFEST:e===VIRTUAL_MODULE_IDS.RUNTIME_CONFIG?RESOLVED_VIRTUAL_IDS.RUNTIME_CONFIG:e===VIRTUAL_MODULE_IDS.CONFIG?RESOLVED_VIRTUAL_IDS.CONFIG:e===VIRTUAL_MODULE_IDS.LAYOUTS?RESOLVED_VIRTUAL_IDS.LAYOUTS:e===VIRTUAL_MODULE_IDS.ASSETS?RESOLVED_VIRTUAL_IDS.ASSETS:e===VIRTUAL_MODULE_IDS.RENDERER?RESOLVED_VIRTUAL_IDS.RENDERER:e===VIRTUAL_MODULE_IDS.CLIENT_ENTRY?RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY:e===VIRTUAL_MODULE_IDS.INTEGRATION_LOADER?RESOLVED_VIRTUAL_IDS.INTEGRATION_LOADER:e===VIRTUAL_MODULE_IDS.ACTIONS?RESOLVED_VIRTUAL_IDS.ACTIONS:null},async load(e){return e===RESOLVED_VIRTUAL_IDS.PAGE_ROUTES?await R(n,i):e===RESOLVED_VIRTUAL_IDS.PAGE_LOADER?await z(n,i):e===RESOLVED_VIRTUAL_IDS.ISLAND_MANIFEST?B():e===RESOLVED_VIRTUAL_IDS.RUNTIME_CONFIG?V(n,r):e===RESOLVED_VIRTUAL_IDS.CONFIG?generateConfigModule(n,r):e===RESOLVED_VIRTUAL_IDS.LAYOUTS?(a||=await H(n,r,p),a):e===RESOLVED_VIRTUAL_IDS.ASSETS?U(r):e===RESOLVED_VIRTUAL_IDS.RENDERER?W(n):e===RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY?await G(n,r):e===RESOLVED_VIRTUAL_IDS.INTEGRATION_LOADER?generateIntegrationLoaderModule(n):e===RESOLVED_VIRTUAL_IDS.ACTIONS?te():null},handleHotUpdate({file:e,server:t}){let n=e.includes(`/pages/`)&&!e.endsWith(`.css`),r=e.includes(`/components/`)&&/\.[tj]sx?$/.test(e),i=(e.includes(`/layouts/`)||e.includes(`_layout`))&&/\.[tj]sx?$/.test(e),o=e.endsWith(`.css`);if(n||r||i||o){if(n){let e=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.PAGE_ROUTES);e&&t.moduleGraph.invalidateModule(e);let n=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.PAGE_LOADER);n&&t.moduleGraph.invalidateModule(n)}if(i){a=null,h();let e=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.LAYOUTS);e&&t.moduleGraph.invalidateModule(e);let n=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY);n&&t.moduleGraph.invalidateModule(n)}setTimeout(()=>{t.ws.send({type:`full-reload`,path:`*`})},500)}if(e.includes(`vite.config`)||e.includes(`avalon.config`)||e.includes(`nitro.config`)){let e=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.CONFIG);e&&t.moduleGraph.invalidateModule(e)}}}}function oe(e,t,n,r){e.watcher.on(`change`,e=>{e.includes(`_middleware`)&&(g(),r?.()),(e.includes(`/render/`)||e.includes(`/layout/`)||e.includes(`/islands/`))&&(q=null,J=null),(e.includes(`/layouts/`)||e.includes(`_layout`))&&globalThis.__avalonLayoutResolver?.clearCache?.()}),e.watcher.on(`add`,e=>{e.includes(`_middleware`)&&(g(),r?.())}),e.watcher.on(`unlink`,e=>{e.includes(`_middleware`)&&(g(),r?.())})}async function R(e,t){try{let{getAllPageDirs:t}=await import(`./module-discovery.js`),{discoverPageRoutesFromMultipleDirs:n}=await import(`../nitro/route-discovery.js`),r=await n(await t(e.pagesDir,e.modules,process.cwd()),{developmentMode:e.isDev});return`export const pageRoutes = ${JSON.stringify(r,null,2)};\nexport default pageRoutes;\n`}catch{return`export const pageRoutes = [];
4
+ `;let a={};for(let[t,i]of r)if(i.endsWith(`.svelte`))try{let r=n(s(e,i.startsWith(`/`)?i.slice(1):i),`utf8`).match(/<style[^>]*>([\s\S]*?)<\/style>/);r&&(a[t]=r[1].trim())}catch{}return i+=`export const serverIslandCSS = ${JSON.stringify(a)};\n`,i}function k(e,t){return new Promise((n,r)=>{let i=[],a=e=>i.push(e),o=()=>{l(),n(Buffer.concat(i).toString(`utf8`))},s=e=>{l(),r(e)},c=setTimeout(()=>{l(),r(Error(t))},15e3);function l(){clearTimeout(c),e.off(`data`,a),e.off(`end`,o),e.off(`error`,s)}e.on(`data`,a),e.on(`end`,o),e.on(`error`,s)})}const A=/^[ \t]*import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/gm,ne=new Set([`node_modules`,`dist`,`.output`,`.netlify`,`.vercel`,`.cloudflare`,`.wrangler`,`.firebase`,`.amplify-hosting`,`.git`]);function j(e,t){return new RegExp(String.raw`<${t}\s[\s\S]*?\bserver\s*[={/>]`).test(e)}function re(e,t){return!(!/\.(tsx|jsx)$/.test(e)||/\.(test|spec)\.[jt]sx$/.test(e)||t.includes(`__tests__`))}function M(e,n){let r;try{r=t(e,{withFileTypes:!0})}catch{return}for(let t of r){let r=s(e,t.name);t.isDirectory()?ne.has(t.name)||M(r,n):t.isFile()&&re(t.name,r)&&n.push(r)}}function ie(e,t,n,r){A.lastIndex=0;let i=A.exec(t);for(;i!==null;i=A.exec(t)){let a=i[1],o=i[2].slice(1,-1);if(!j(t,a))continue;let s=ee(o,e,n),c=O(s);c in r||(r[c]=s)}}function ae(t){let r={},i=[];for(let n of[`app`,`src`]){let r=s(t,n);e(r)&&M(r,i)}for(let e of i){let i;try{i=n(e,`utf8`)}catch{continue}/\bserver\s*[={/>]/.test(i)&&ie(e,i,t,r)}return r}function N(t){let n=[`ts`,`tsx`,`js`,`jsx`,`mts`,`mjs`];for(let r of[`app`,`src`])for(let i of n){let n=`/${r}/actions/index.${i}`;if(e(s(t,n.slice(1))))return n}}function oe(e){let t=N(e);return t?`export { server } from ${JSON.stringify(t)};\n`:`export const server = {};
5
+ `}function se(){return[`import { createActionClient } from "@useavalon/avalon/actions";`,`export const actions = createActionClient();`,`export default actions;`,``].join(`
6
+ `)}function ce(e,t){try{let n;if(e.startsWith(`dev.`)){let t=e.slice(4);n=Buffer.from(t,`base64url`).toString(`utf8`)}else n=t(e);let r=JSON.parse(n),i,a;return r.__island&&(i=r.__island,delete r.__island),r.__src&&(a=r.__src,delete r.__src),{ok:!0,props:r,srcPath:a,islandMeta:i}}catch{return{ok:!1}}}function le(e,t,n,r){let i=e.split(`/`)[2]?.split(`?`)[0]||``,a=t.elementId??`si-${i}`,o=t.componentSrc??n,s=JSON.stringify(r),c=t.condition??`on:client`,l=t.framework??`preact`;return`<script type="module">
7
+ import{hydrateServerIsland}from"/@fs${P(`src/client/server-island-hydrate.ts`)}";
8
+ hydrateServerIsland(${JSON.stringify(a)},${JSON.stringify(o)},${s},${JSON.stringify(c)},${JSON.stringify(l)});
9
+ <\/script>`}function P(t){let n=s(o(a(import.meta.url).resolve(`@useavalon/avalon`)),t);if(t.endsWith(`.ts`)&&!e(n)){let t=n.replace(/\.ts$/,`.js`);if(e(t))return t}return n}function ue(t,n){let r=s(o(a(s(process.cwd(),`package.json`)).resolve(`@useavalon/${t}`)),n);if(n.endsWith(`.ts`)&&!e(r)){let t=r.replace(/\.ts$/,`.js`);if(e(t))return t}return r}export const VIRTUAL_MODULE_IDS={PAGE_ROUTES:`virtual:avalon/page-routes`,PAGE_LOADER:`virtual:avalon/page-loader`,ISLAND_MANIFEST:`virtual:avalon/island-manifest`,RUNTIME_CONFIG:`virtual:avalon/runtime-config`,CONFIG:`virtual:avalon/config`,LAYOUTS:`virtual:avalon/layouts`,ASSETS:`virtual:avalon/assets`,RENDERER:`virtual:avalon/renderer`,CLIENT_ENTRY:`virtual:avalon/client-entry`,INTEGRATION_LOADER:`virtual:avalon/integration-loader`,ACTIONS:`virtual:avalon/actions`};export const RESOLVED_VIRTUAL_IDS={PAGE_ROUTES:`\0${VIRTUAL_MODULE_IDS.PAGE_ROUTES}`,PAGE_LOADER:`\0${VIRTUAL_MODULE_IDS.PAGE_LOADER}`,ISLAND_MANIFEST:`\0${VIRTUAL_MODULE_IDS.ISLAND_MANIFEST}`,RUNTIME_CONFIG:`\0${VIRTUAL_MODULE_IDS.RUNTIME_CONFIG}`,CONFIG:`\0${VIRTUAL_MODULE_IDS.CONFIG}`,LAYOUTS:`\0${VIRTUAL_MODULE_IDS.LAYOUTS}`,ASSETS:`\0${VIRTUAL_MODULE_IDS.ASSETS}`,RENDERER:`\0${VIRTUAL_MODULE_IDS.RENDERER}`,CLIENT_ENTRY:`\0${VIRTUAL_MODULE_IDS.CLIENT_ENTRY}`,INTEGRATION_LOADER:`\0${VIRTUAL_MODULE_IDS.INTEGRATION_LOADER}`,ACTIONS:`\0${VIRTUAL_MODULE_IDS.ACTIONS}`};function de(e){return e===`react`?[]:[/^react/,/^react-dom/]}function fe(e){return e===`react`?[`import { createElement as h } from 'react';`,`import { renderToString as preactRenderToString } from 'react-dom/server';`]:[`import { h } from 'preact';`,`import preactRenderToString from 'preact-render-to-string';`]}function pe(e){return e===`react`?[`import { setShellRenderToString, setShellElementFactory } from '@useavalon/avalon/render/shell-engine';`,`import { renderToString as __reactRenderToString } from 'react-dom/server';`,`import { createElement as __reactCreateElement, Fragment as __reactFragment } from 'react';`,`setShellRenderToString((vnode) => __reactRenderToString(vnode));`,`setShellElementFactory(__reactCreateElement, __reactFragment);`]:[]}function me(e){return e===`react`?`@useavalon/react/client`:`@useavalon/preact/client`}function he(e){let t=P(`src/core/integrations/registry.ts`),n=[`solid`,`vue`,`svelte`,`lit`].filter(t=>e.includes(t));return`${[`import { registry } from "${t}";`,...n.map(e=>`import { ${e}Integration } from "@useavalon/${e}";`),...n.map(e=>`if (${e}Integration) registry.register(${e}Integration);`)].join(`
10
+ `)}\n`}export function createNitroIntegration(e,t={}){let n=y(t,e),r=process.cwd(),i=P(`src/server-islands/route.ts`),a=P(`src/actions/route.ts`),o={preset:n.preset,serverDir:t.serverDir??n.serverDir??`./server`,routeRules:n.routeRules,runtimeConfig:n.runtimeConfig,compatibilityDate:n.compatibilityDate,scanDirs:[`.`],noExternals:[`estree-walker`,/^@useavalon\//,/^estree-util/,/^preact/,...de(e.core),/^vue/,/^@vue\//],handlers:[{route:`/_server-islands/**`,handler:i},{route:`/_actions/**`,handler:a}],virtual:{"virtual:server-island-manifest":()=>te(r),"virtual:avalon-actions-manifest":()=>oe(r),"virtual:server-island-key":()=>{let e=process.env.AVALON_KEY??``;return`export const serverIslandKey = ${JSON.stringify(e)};\n`},"virtual:server-island-integrations":()=>he(e.integrations)}};t.renderer===!1?o.renderer=!1:n.renderer&&(o.renderer=n.renderer),n.publicRuntimeConfig&&(o.publicRuntimeConfig=n.publicRuntimeConfig),n.publicAssets&&(o.publicAssets=n.publicAssets),n.compressPublicAssets&&(o.compressPublicAssets=n.compressPublicAssets),n.serverEntry&&(o.serverEntry=n.serverEntry);let s=n.traceDeps??[];o.traceDeps=[...new Set([`undici`,...s])],n.prerender&&(o.prerender={routes:[],crawlLinks:!1});let c=u(o),l=createNitroCoordinationPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),d=createVirtualModulesPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),f=x(e,t),p=b(e,{verbose:e.verbose,generatePreloadHints:!0}),m=C(S(t.preset??`node_server`,e.isDev));return{nitroOptions:n,plugins:[...Array.isArray(c)?c:[c],l,d,f,p,m]}}export function createNitroCoordinationPlugin(e){let{avalonConfig:t,verbose:n}=e;return{name:`avalon:nitro-coordination`,enforce:`pre`,config(e,{command:t}){if(t===`serve`)return{server:{watch:{ignored:[`**/.output/**`,`**/dist/**`,`**/.netlify/**`,`**/.vercel/**`,`**/.cloudflare/**`,`**/.wrangler/**`,`**/.firebase/**`,`**/.amplify-hosting/**`]},fs:{deny:[`.output`,`dist`,`.netlify`,`.vercel`,`.cloudflare`,`.wrangler`,`.firebase`,`.amplify-hosting`]}}}},configResolved(e){globalThis.__avalonHydrationMode=e.command===`serve`?`entry-client`:`per-island`;try{f(e.root||process.cwd())}catch{}},configureServer(e){globalThis.__viteDevServer=e;let i=e.config.root||process.cwd(),a=e=>{if(e.includes(`/actions/`))try{f(i)}catch{}};e.watcher.on(`add`,a),e.watcher.on(`unlink`,a);let o=e.config.root||process.cwd(),c=e.config.build?.outDir?s(o,e.config.build.outDir):s(o,`dist`);try{r(c,{recursive:!0,force:!0})}catch{}try{r(s(o,`.output`),{recursive:!0,force:!0})}catch{}let l=!1,u=new Promise(t=>{let n=()=>{(e.environments?.nitro)?.devServer?.entry||l?(l=!0,t()):setTimeout(n,50)};setTimeout(n,100),setTimeout(()=>{l=!0,t()},15e3)});e.middlewares.use(async(e,t,n)=>{if(l)return n();let r=e.url||`/`;if(r.startsWith(`/@`)||r.startsWith(`/__`)||/\/[^/]+\.[a-z0-9]+(\?|$)/i.test(r))return n();await u,n()});let p=null;async function m(){return p||=await _({baseDir:`${e.config.root||process.cwd()}/src`,devMode:!1}),p}function h(){p=null}ye(e,t,n,h),m().catch(e=>{console.warn(`[middleware] Failed to discover middleware:`,e)});let g=e.environments?.ssr,v=!!g&&d(g);v&&I(e,t.integrations,n).catch(e=>{console.error(`[prewarm] Core modules pre-warm failed:`,e)}),e.middlewares.use(async(n,r,i)=>{let a=n.url||`/`;if(!a.startsWith(`/_server-islands/`)||!v)return i();try{let{decrypt:i}=await e.ssrLoadModule(P(`src/server-islands/encryption.ts`)),{h:o,renderToString:s}=await V(e,t.core),c=new URL(a,`http://${n.headers.host||`localhost`}`).searchParams.get(`p`)||``;if(!c&&n.method===`POST`&&(c=await k(n,`Timed out reading server island request body`)),!c){r.statusCode=400,r.setHeader(`Content-Type`,`text/plain`),r.end(`Missing encrypted props`);return}let l=ce(c,i);if(!l.ok){r.statusCode=400,r.setHeader(`Content-Type`,`text/plain`),r.end(`Bad Request: decryption failed`);return}let{props:u,srcPath:d,islandMeta:f}=l;if(!d){r.statusCode=404,r.setHeader(`Content-Type`,`text/plain`),r.end(`Component not found (no __src in payload)`);return}let p=(await e.ssrLoadModule(d)).default;if(typeof p!=`function`){r.statusCode=500,r.setHeader(`Content-Type`,`text/plain`),r.end(`Module "${d}" does not export a default component function`);return}let m=s(o(p,u));f&&(m+=le(a,f,d,u)),r.statusCode=200,r.setHeader(`Content-Type`,`text/html`),r.setHeader(`Cache-Control`,`private, no-store`),r.end(m)}catch(e){console.error(`[server-islands] Dev handler error:`,e),r.statusCode=500,r.setHeader(`Content-Type`,`text/plain`),r.end(`Server island render failed: ${e instanceof Error?e.message:String(e)}`)}}),e.middlewares.use(async(t,n,r)=>{let i=t.url||`/`;if(!i.startsWith(`/_actions/`)||!v)return r();try{let r=N(e.config.root||process.cwd()),[a,o,s]=await Promise.all([e.ssrLoadModule(P(`src/actions/endpoint.ts`)),e.ssrLoadModule(P(`src/actions/registry.ts`)),r?e.ssrLoadModule(r):Promise.resolve({server:{}})]),c=o.flattenActions(s.server),l=a.defineActionHandler({registry:c,isDev:!0}),u=new URL(i,`http://${t.headers.host||`localhost`}`),d=(t.method||`GET`).toUpperCase(),f;d===`POST`&&(f=await k(t,`Timed out reading action request body`));let p=await l({url:u,web:{request:new Request(u,{method:d,headers:t.headers,body:f})},context:{}});n.statusCode=p.status,p.headers.forEach((e,t)=>{n.setHeader(t,e)}),n.end(await p.text())}catch(e){console.error(`[actions] Dev handler error:`,e),n.statusCode=500,n.setHeader(`Content-Type`,`application/json`),n.end(JSON.stringify({error:{code:`INTERNAL_SERVER_ERROR`,message:e instanceof Error?e.message:String(e)}}))}}),e.middlewares.use(async(r,i,a)=>{if(!v)return a();let o=r.url||`/`;if(o.endsWith(`.html`)&&(o=o.slice(0,-5)||`/`),o===`/index`&&(o=`/`),o.startsWith(`/@`)||o.startsWith(`/__`)||o.startsWith(`/node_modules/`)||o.startsWith(`/src/client/`)||o.startsWith(`/packages/`)||o.includes(`.`)&&!o.endsWith(`/`)||o.startsWith(`/api/`))return a();try{if(await ge(e,o,r,i,m,n)||await Le(e,o,t,i))return;let a=await Re(e,o,t);if(a){i.statusCode=200,i.setHeader(`Content-Type`,`text/html`),i.end(a);return}await F(e,o,i,t)}catch(e){console.error(`[SSR Error]`,e),i.statusCode=500,i.setHeader(`Content-Type`,`text/html`),i.end(E(e))}})},buildStart(){}}}async function ge(e,t,n,r,i,a){let o=performance.now(),s=await i();if(s.length===0)return!1;let c={};for(let[e,t]of Object.entries(n.headers))typeof t==`string`?c[e]=t:Array.isArray(t)&&(c[e]=t.join(`, `));let l=`http://${n.headers.host||`localhost`}${t}`,u=await v({url:l,method:n.method||`GET`,path:t,node:{req:n,res:r},req:new Request(l,{method:n.method||`GET`,headers:c}),context:{}},s,{devMode:!1}),d=performance.now()-o;return d>100&&console.warn(`⚠️ Slow middleware: ${d.toFixed(0)}ms for ${t}`),u?(r.statusCode=u.status,u.headers.forEach((e,t)=>{r.setHeader(t,e)}),r.end(await u.text()),!0):!1}async function F(e,t,n,r){try{let{discoverErrorPages:i,getErrorPageModule:a,generateDefaultErrorPage:o}=await import(`../nitro/error-handler.js`),s=a(404,await i({isDev:r.isDev,pagesDir:r.pagesDir,loadPageModule:async t=>await e.ssrLoadModule(t)}));if(s?.default&&typeof s.default==`function`){let{renderToHtml:e}=await import(`../render/ssr.js`),r=s.default,i=await e({component:()=>r({statusCode:404,message:`Page not found: ${t}`,url:t})},{});n.statusCode=404,n.setHeader(`Content-Type`,`text/html`),n.end(i);return}let c=o(404,`Page not found: ${t}`,r.isDev);n.statusCode=404,n.setHeader(`Content-Type`,`text/html`),n.end(c)}catch{n.statusCode=404,n.setHeader(`Content-Type`,`text/html`),n.end(D(t))}}async function I(e,t,n){let r=performance.now(),i=[{path:P(`src/render/ssr.ts`),assignTo:`ssr`},{path:P(`src/core/layout/enhanced-layout-resolver.ts`),assignTo:`layout`},{path:P(`src/middleware/index.ts`),assignTo:null},...t.map(e=>({path:ue(e,`server/renderer.ts`),assignTo:null}))],a=(await Promise.allSettled(i.map(async({path:t,assignTo:n})=>{let r=await e.ssrLoadModule(t);n===`ssr`&&(z=r),n===`layout`&&(B=r)}))).filter(e=>e.status===`fulfilled`).length,o=performance.now()-r;n&&a>0&&console.log(`🔥 SSR ready in ${o.toFixed(0)}ms (${a}/${i.length} core modules)`)}export function createVirtualModulesPlugin(e){let{avalonConfig:n,nitroConfig:r,verbose:i}=e,a=null,o=s,u=c,d=l,f=process.cwd(),p=[];function m(e){try{let n=t(e,{withFileTypes:!0});for(let t of n){let n=o(e,t.name);if(t.isDirectory()&&t.name!==`node_modules`&&!t.name.startsWith(`.`))m(n);else if(t.isFile()&&t.name.endsWith(`.css`)){let e=u(f,n).replaceAll(`\\`,`/`);p.push(e.startsWith(`/`)?e:`/${e}`)}}}catch{}}function h(){p.length=0;for(let e of r.globalCSS??[])p.push(e.startsWith(`/`)?e:`/${e}`);n.modules&&m(d(f,n.modules.dir)),m(d(f,n.layoutsDir));let e=d(f,n.layoutsDir,`..`);e!==f&&e!==d(f,n.layoutsDir)&&e.startsWith(f)&&m(e)}return n.isDev&&h(),{name:`avalon:nitro-virtual-modules`,enforce:`pre`,resolveId(e){return e===VIRTUAL_MODULE_IDS.PAGE_ROUTES?RESOLVED_VIRTUAL_IDS.PAGE_ROUTES:e===VIRTUAL_MODULE_IDS.PAGE_LOADER?RESOLVED_VIRTUAL_IDS.PAGE_LOADER:e===VIRTUAL_MODULE_IDS.ISLAND_MANIFEST?RESOLVED_VIRTUAL_IDS.ISLAND_MANIFEST:e===VIRTUAL_MODULE_IDS.RUNTIME_CONFIG?RESOLVED_VIRTUAL_IDS.RUNTIME_CONFIG:e===VIRTUAL_MODULE_IDS.CONFIG?RESOLVED_VIRTUAL_IDS.CONFIG:e===VIRTUAL_MODULE_IDS.LAYOUTS?RESOLVED_VIRTUAL_IDS.LAYOUTS:e===VIRTUAL_MODULE_IDS.ASSETS?RESOLVED_VIRTUAL_IDS.ASSETS:e===VIRTUAL_MODULE_IDS.RENDERER?RESOLVED_VIRTUAL_IDS.RENDERER:e===VIRTUAL_MODULE_IDS.CLIENT_ENTRY?RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY:e===VIRTUAL_MODULE_IDS.INTEGRATION_LOADER?RESOLVED_VIRTUAL_IDS.INTEGRATION_LOADER:e===VIRTUAL_MODULE_IDS.ACTIONS?RESOLVED_VIRTUAL_IDS.ACTIONS:null},async load(e){return e===RESOLVED_VIRTUAL_IDS.PAGE_ROUTES?await be(n,i):e===RESOLVED_VIRTUAL_IDS.PAGE_LOADER?await xe(n,i):e===RESOLVED_VIRTUAL_IDS.ISLAND_MANIFEST?Se():e===RESOLVED_VIRTUAL_IDS.RUNTIME_CONFIG?Ce(n,r):e===RESOLVED_VIRTUAL_IDS.CONFIG?generateConfigModule(n,r):e===RESOLVED_VIRTUAL_IDS.LAYOUTS?(a||=await we(n,r,p),a):e===RESOLVED_VIRTUAL_IDS.ASSETS?Te(r):e===RESOLVED_VIRTUAL_IDS.RENDERER?Ee(n):e===RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY?await ke(n,r):e===RESOLVED_VIRTUAL_IDS.INTEGRATION_LOADER?generateIntegrationLoaderModule(n):e===RESOLVED_VIRTUAL_IDS.ACTIONS?se():null},handleHotUpdate({file:e,server:t}){let{isPage:n,isComponent:r,isLayout:i,isCss:o}=_e(e);(n||r||i||o)&&(n&&(L(t,RESOLVED_VIRTUAL_IDS.PAGE_ROUTES),L(t,RESOLVED_VIRTUAL_IDS.PAGE_LOADER)),i&&(a=null,h(),L(t,RESOLVED_VIRTUAL_IDS.LAYOUTS),L(t,RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY)),setTimeout(()=>{t.ws.send({type:`full-reload`,path:`*`})},500)),ve(e)&&L(t,RESOLVED_VIRTUAL_IDS.CONFIG)}}}function L(e,t){let n=e.moduleGraph.getModuleById(t);n&&e.moduleGraph.invalidateModule(n)}function _e(e){let t=e.endsWith(`.css`);return{isPage:e.includes(`/pages/`)&&!t,isComponent:e.includes(`/components/`)&&/\.[tj]sx?$/.test(e),isLayout:(e.includes(`/layouts/`)||e.includes(`_layout`))&&/\.[tj]sx?$/.test(e),isCss:t}}function ve(e){return e.includes(`vite.config`)||e.includes(`avalon.config`)||e.includes(`nitro.config`)}function ye(e,t,n,r){e.watcher.on(`change`,e=>{e.includes(`_middleware`)&&(g(),r?.()),(e.includes(`/render/`)||e.includes(`/layout/`)||e.includes(`/islands/`))&&(z=null,B=null),(e.includes(`/layouts/`)||e.includes(`_layout`))&&globalThis.__avalonLayoutResolver?.clearCache?.()}),e.watcher.on(`add`,e=>{e.includes(`_middleware`)&&(g(),r?.())}),e.watcher.on(`unlink`,e=>{e.includes(`_middleware`)&&(g(),r?.())})}async function be(e,t){try{let{getAllPageDirs:t}=await import(`./module-discovery.js`),{discoverPageRoutesFromMultipleDirs:n}=await import(`../nitro/route-discovery.js`),r=await n(await t(e.pagesDir,e.modules,process.cwd()),{developmentMode:e.isDev});return`export const pageRoutes = ${JSON.stringify(r,null,2)};\nexport default pageRoutes;\n`}catch{return`export const pageRoutes = [];
20
11
  export default pageRoutes;
21
- `}}async function z(e,t){try{let{getAllPageDirs:t}=await import(`./module-discovery.js`),{discoverPageRoutesFromMultipleDirs:n}=await import(`../nitro/route-discovery.js`),{relative:r}=await import(`node:path`),i=process.cwd(),a=await n(await t(e.pagesDir,e.modules,i),{developmentMode:e.isDev}),o=[],s=[];for(let e=0;e<a.length;e++){let t=a[e],n=`page_${e}`,c=r(i,t.filePath).replaceAll(`\\`,`/`),l=c.startsWith(`/`)?c:`/${c}`;o.push(`import * as ${n} from '${l}';`),s.push(` { pattern: ${JSON.stringify(t.pattern)}, params: ${JSON.stringify(t.params)}, module: ${n} }`)}return[...o,``,`const routes = [`,s.join(`,
22
- `),`];`,``,`/**`,` * Match a pathname against discovered routes and return the page module.`,` * Uses the same pattern matching as Avalon's route discovery.`,` */`,`export function loadPage(pathname) {`,` const cleanPath = pathname.split('?')[0];`,` for (const route of routes) {`,` if (matchRoute(cleanPath, route.pattern, route.params)) {`,` return route.module;`,` }`,` }`,` return null;`,`}`,``,`function matchRoute(pathname, pattern, paramNames) {`,` // Exact match`,` if (pattern === pathname) return true;`,` // Normalize trailing slashes`,` const normPath = pathname === '/' ? '/' : pathname.replace(/\\/$/, '');`,` const normPattern = pattern === '/' ? '/' : pattern.replace(/\\/$/, '');`,` if (normPath === normPattern) return true;`,` // Dynamic segments: /users/:id matches /users/123`,` if (paramNames.length > 0) {`,` const patternParts = normPattern.split('/');`,` const pathParts = normPath.split('/');`,` if (patternParts.length !== pathParts.length) return false;`,` return patternParts.every((part, i) => part.startsWith(':') || part === pathParts[i]);`,` }`,` return false;`,`}`,``,`export default { loadPage, routes };`,``].join(`
12
+ `}}async function xe(e,t){try{let{getAllPageDirs:t}=await import(`./module-discovery.js`),{discoverPageRoutesFromMultipleDirs:n}=await import(`../nitro/route-discovery.js`),{relative:r}=await import(`node:path`),i=process.cwd(),a=await n(await t(e.pagesDir,e.modules,i),{developmentMode:e.isDev}),o=[],s=[];for(let e=0;e<a.length;e++){let t=a[e],n=`page_${e}`,c=r(i,t.filePath).replaceAll(`\\`,`/`),l=c.startsWith(`/`)?c:`/${c}`;o.push(`import * as ${n} from '${l}';`),s.push(` { pattern: ${JSON.stringify(t.pattern)}, params: ${JSON.stringify(t.params)}, module: ${n} }`)}return[...o,``,`const routes = [`,s.join(`,
13
+ `),`];`,``,`/**`,` * Match a pathname against discovered routes and return the page module.`,` * Uses the same pattern matching as Avalon's route discovery.`,` */`,`export function loadPage(pathname) {`,` const cleanPath = pathname.split('?')[0];`,` for (const route of routes) {`,` if (matchRoute(cleanPath, route.pattern, route.params)) {`,` return route.module;`,` }`,` }`,` return null;`,`}`,``,`function matchRoute(pathname, pattern, paramNames) {`,` // Exact match`,` if (pattern === pathname) return true;`,` // Normalize trailing slashes`,String.raw` const normPath = pathname === '/' ? '/' : pathname.replace(/\/$/, '');`,String.raw` const normPattern = pattern === '/' ? '/' : pattern.replace(/\/$/, '');`,` if (normPath === normPattern) return true;`,` // Dynamic segments: /users/:id matches /users/123`,` if (paramNames.length > 0) {`,` const patternParts = normPattern.split('/');`,` const pathParts = normPath.split('/');`,` if (patternParts.length !== pathParts.length) return false;`,` return patternParts.every((part, i) => part.startsWith(':') || part === pathParts[i]);`,` }`,` return false;`,`}`,``,`export default { loadPage, routes };`,``].join(`
23
14
  `)}catch(e){return console.error(`[page-loader] Failed to generate page loader:`,e),`export function loadPage() { return null; }
24
15
  export default { loadPage, routes: [] };
25
- `}}function B(){return`export const islandManifest = { islands: {}, clientEntry: "", css: [] };
16
+ `}}function Se(){return`export const islandManifest = { islands: {}, clientEntry: "", css: [] };
26
17
  export default islandManifest;
27
- `}function V(e,t){let n={avalon:{streaming:t.streaming??!0,pagesDir:e.pagesDir,layoutsDir:e.layoutsDir,isDev:e.isDev},...t.runtimeConfig};return`export const runtimeConfig = ${JSON.stringify(n,null,2)};\nexport function useRuntimeConfig() { return runtimeConfig; }\nexport default runtimeConfig;\n`}export function generateConfigModule(e,t){let n=globalThis.__avalonConfig?.isDev??e.isDev,r={streaming:t.streaming??!0,pagesDir:e.pagesDir,layoutsDir:e.layoutsDir,isDev:n,...t.runtimeConfig};return`globalThis.__avalonHydrationMode = "${n?`entry-client`:`per-island`}";\nconst config = ${JSON.stringify(r,null,2)};\nexport function useAvalonConfig() { return config; }\nexport default config;\n`}async function H(e,t,n){let{getAllLayoutDirs:r}=await import(`./module-discovery.js`),{relative:i,resolve:a}=await import(`node:path`),{stat:o,readFile:c}=await import(`node:fs/promises`),l=process.cwd(),u=await r(e.layoutsDir,e.modules,l),d=[],f=0,p=a(l,e.layoutsDir);for(let{dir:t,prefix:n}of u){let r=s(t,`_layout.tsx`);try{if(!(await o(r)).isFile())continue}catch{continue}let a=i(l,r).replaceAll(`\\`,`/`),c=a.startsWith(`/`)?a:`/${a}`,u=t.startsWith(p),m=u&&!e.modules?`RootLayout`:`Layout_${f}`;d.push({prefix:n,importPath:c,varName:m,isShared:u,filePath:r}),f++}let m=d.filter(e=>e.isShared),h=d.filter(e=>!e.isShared),g=new Map;for(let e of h)try{let t=(await c(e.filePath,`utf8`)).match(/layoutConfig\s*=\s*{[\s\S]*?skipLayouts\s*:\s*\[([^\]]*)\]/)?.[1]??``,n=/['"`]_layout['"`]/.test(t);g.set(e.importPath,n)}catch{g.set(e.importPath,!1)}let _=d.map(e=>`import ${e.varName} from '${e.importPath}';`),v=h.toSorted((e,t)=>t.prefix.length-e.prefix.length).map(e=>{let t=e.prefix===`/`,n=g.get(e.importPath)??!1,r=t||n;return` { prefix: ${JSON.stringify(e.prefix)}, Layout: ${e.varName}, skipRoot: ${r} }`}),y=m.length>0?m[0].varName:`null`,b=JSON.stringify(n);return[`// Auto-generated by Avalon — do not edit`,`import { h } from 'preact';`,`import preactRenderToString from 'preact-render-to-string';`,`import { getUniversalCSSForHead } from '@useavalon/avalon/islands/universal-css-collector';`,`import { getUniversalHeadForInjection, injectSolidHydrationScriptIfNeeded } from '@useavalon/avalon/islands/universal-head-collector';`,..._,``,`const RootLayoutComponent = ${y};`,`const _cssLinks = ${b};`,``,`const moduleLayouts = [`,v.join(`,
28
- `),`];`,``,`function getLayoutsForPath(pathname) {`,` for (const entry of moduleLayouts) {`,` if (entry.prefix === '/' ? pathname === '/' : pathname.startsWith(entry.prefix)) {`,` return entry;`,` }`,` }`,` return null;`,`}`,``,`function injectUniversalAssets(html) {`,` // In dev, inject <link> tags for all discovered CSS files.`,` // The ?direct suffix makes Vite return raw CSS (text/css) instead`,` // of a JS module wrapper, so <link rel="stylesheet"> works.`,` if (process.env.NODE_ENV !== 'production' && _cssLinks.length > 0) {`,` var links = _cssLinks.map(function(href) {`,` return '<link rel="stylesheet" href="' + href + '?direct">';`,` }).join('\\n');`,` if (html.includes('</head>')) {`,` html = html.replace('</head>', links + '\\n</head>');`,` }`,` }`,` const universalCSS = getUniversalCSSForHead(true);`,` if (universalCSS && html.includes('</head>')) {`,` html = html.replace('</head>', universalCSS + '\\n</head>');`,` }`,` const universalHead = getUniversalHeadForInjection(true);`,` if (universalHead && html.includes('</head>')) {`,` html = html.replace('</head>', universalHead + '\\n</head>');`,` }`,` html = injectSolidHydrationScriptIfNeeded(html);`,` return html;`,`}`,``,`export async function wrapWithLayouts(pageHtml, pageModule, context, injectAssets) {`,` const pathname = context.url.pathname;`,` const frontmatter = {`,` ...(pageModule.frontmatter || {}),`,` ...(pageModule.metadata || {}),`,` currentPath: pathname,`,` };`,` const pageLayoutConfig = pageModule.layoutConfig;`,` const skipAll = pageLayoutConfig?.skipLayouts?.includes('_layout');`,``,` const layoutEntry = getLayoutsForPath(pathname);`,` const routeInfo = { path: pathname, params: context.params, query: context.url.searchParams };`,` let html;`,``,` if (!layoutEntry || skipAll) {`,` if (RootLayoutComponent && !skipAll) {`,` const rootProps = {`,` children: h('avalon-page', { id: 'app', dangerouslySetInnerHTML: { __html: pageHtml } }),`,` frontmatter,`,` data: {},`,` route: routeInfo,`,` };`,` const rootResult = RootLayoutComponent(rootProps);`,` const resolvedRoot = rootResult instanceof Promise ? await rootResult : rootResult;`,` html = '<!DOCTYPE html>\\n' + preactRenderToString(resolvedRoot);`,` } else {`,` // skipAll is true — page provides its own HTML shell or needs a minimal one`,` if (pageHtml.trimStart().startsWith('<html')) {`,` html = '<!DOCTYPE html>\\n' + pageHtml;`,` } else {`,` const title = String(frontmatter.title || 'Avalon');`,` html = [`,` '<!DOCTYPE html>',`,` '<html lang="en">',`,` '<head>',`,` '<meta charset="utf-8">',`,` '<meta name="viewport" content="width=device-width, initial-scale=1">',`,` '<title>' + title + '</title>',`,` '</head>',`,` '<body>',`,` '<div id="app">' + pageHtml + '</div>',`,` '</body>',`,` '</html>',`,` ].join('\\n');`,` }`,` }`,` } else {`,` const layoutProps = {`,` children: h('avalon-page', { dangerouslySetInnerHTML: { __html: pageHtml } }),`,` frontmatter,`,` data: {},`,` route: routeInfo,`,` };`,` const layoutResult = layoutEntry.Layout(layoutProps);`,` const resolvedLayout = layoutResult instanceof Promise ? await layoutResult : layoutResult;`,` let wrappedHtml = preactRenderToString(resolvedLayout);`,``,` // If the layout provides its own HTML shell (starts with <html),`,` // skip root wrapping regardless of skipRoot flag — the layout IS the document.`,` const layoutProvidesShell = wrappedHtml.trimStart().startsWith('<html');`,``,` if (!layoutProvidesShell && !layoutEntry.skipRoot && RootLayoutComponent) {`,` const rootProps = {`,` children: h('avalon-page', { dangerouslySetInnerHTML: { __html: wrappedHtml } }),`,` frontmatter,`,` data: {},`,` route: routeInfo,`,` };`,` const rootResult = RootLayoutComponent(rootProps);`,` const resolvedRoot = rootResult instanceof Promise ? await rootResult : rootResult;`,` wrappedHtml = preactRenderToString(resolvedRoot);`,` }`,``,` html = '<!DOCTYPE html>\\n' + wrappedHtml;`,` }`,``,` if (injectAssets) {`,` html = injectAssets(html);`,` }`,` return injectUniversalAssets(html);`,`}`,``,`export default { wrapWithLayouts };`,``].join(`
29
- `)}function U(e){let t=e.clientEntry??`app/entry-client`;return[`// Auto-generated by Avalon — do not edit`,`// @ts-ignore — virtual import resolved by Nitro's Vite assets plugin at build time`,`import clientAssets from '${t.startsWith(`/`)?t:`/${t}`}?assets=client';`,``,`function buildAssetTags() {`,` const cssLinks = (clientAssets?.css ?? [])`,` .filter(attr => {`,` const href = attr.href || '';`,` // The SSR build produces ssr-index-*.css containing all global, reset,`,` // token, and layout CSS module styles. The client build may also emit`,` // entry-client-*.css (a subset) and index-*.css. To avoid duplicates,`,` // prefer ssr-index when it exists; otherwise fall back to the others.`,` var hasSsrIndex = (clientAssets?.css ?? []).some(function(a) { return (a.href || '').includes('ssr-index'); });`,` if (hasSsrIndex) return href.includes('ssr-index');`,` if (href.includes('entry-client') && href.endsWith('.css')) return true;`,` if (/\\/index-[^/]+\\.css$/.test(href)) return true;`,` return false;`,` })`,` .map(attr => '<link rel="stylesheet" href="' + attr.href + '">')`,` .join('\\n');`,` const jsPreloads = (clientAssets?.js ?? [])`,` .map(attr => '<link rel="modulepreload" href="' + attr.href + '">')`,` .join('\\n');`,` const entryScript = clientAssets?.entry`,` ? '<script type="module" src="' + clientAssets.entry + '"><\/script>'`,` : '';`,` return { cssLinks, jsPreloads, entryScript };`,`}`,``,`export function injectAssets(html) {`,` const { cssLinks, jsPreloads, entryScript } = buildAssetTags();`,` if (html.includes('</head>')) {`,` html = html.replace('</head>', cssLinks + '\\n' + jsPreloads + '\\n</head>');`,` }`,` if (html.includes('</body>')) {`,` html = html.replace('</body>', entryScript + '\\n</body>');`,` }`,` return html;`,`}`,``,`export { clientAssets };`,`export default { injectAssets, clientAssets };`,``].join(`
30
- `)}function W(e){let t=Array.isArray(e.integrations)?e.integrations:[],n=[],r=[];for(let e of t){let t=`${e}Integration`;n.push(`import { ${t} } from '@useavalon/${e}';`),r.push(`registry.register(${t});`)}return[`// Auto-generated by Avalon — do not edit`,`import { createNitroRenderer } from '@useavalon/avalon/nitro/renderer';`,`import { registerBuiltinDirectives } from '@useavalon/avalon';`,`import { registry } from '@useavalon/avalon/islands/integration-registry';`,`import avalonConfig from 'virtual:avalon/config';`,`import { loadPage } from 'virtual:avalon/page-loader';`,`import { wrapWithLayouts } from 'virtual:avalon/layouts';`,`import { injectAssets } from 'virtual:avalon/assets';`,...n,``,`// Pre-register framework integrations for SSR`,...r,``,`// Register built-in custom hydration directives (on:delay, on:scroll, etc.)`,`registerBuiltinDirectives();`,``,`// Set hydration mode flag — intentionally duplicated from virtual:avalon/config`,`// for module-load-order resilience (config import may be tree-shaken or deferred).`,`globalThis.__avalonHydrationMode = avalonConfig.isDev ? "entry-client" : "per-island";`,``,`export default createNitroRenderer({`,` avalonConfig,`,` isDev: avalonConfig.isDev,`,` resolvePageRoute: async (pathname) => {`,` const mod = loadPage(pathname);`,` if (!mod || !('default' in mod)) return null;`,` return { filePath: '[virtual:' + pathname + ']', pattern: pathname, params: {} };`,` },`,` loadPageModule: async (filePath) => {`,` const match = filePath.match(/^\\[virtual:(.+)\\]$/);`,` const pathname = match ? match[1] : filePath;`,` const mod = loadPage(pathname);`,` if (mod) return mod;`,` return { default: () => null, metadata: { title: 'Avalon' } };`,` },`,` wrapWithLayouts: (pageHtml, pageModule, context) =>`,` wrapWithLayouts(pageHtml, pageModule, context, injectAssets),`,`});`,``].join(`
31
- `)}async function G(e,t){let{getAllLayoutDirs:n}=await import(`./module-discovery.js`),{readdir:r}=await import(`node:fs/promises`),{relative:i,join:a}=await import(`node:path`),o=process.cwd(),s=await n(e.layoutsDir,e.modules,o),c=[];for(let{dir:e}of s)try{let t=await r(e,{withFileTypes:!0});for(let n of t){if(!n.isFile()||!n.name.endsWith(`.css`))continue;let t=i(o,a(e,n.name)).replaceAll(`\\`,`/`),r=t.startsWith(`/`)?t:`/${t}`;c.push(r)}}catch{}let l=globalThis.__avalonConfig?.isDev??e.isDev?`@useavalon/avalon/client/main`:`@useavalon/avalon/client/main-slim`,u=[`// Auto-generated by Avalon — do not edit`,`// Island hydration runtime`];(globalThis.__avalonHydrationMode??`entry-client`)===`entry-client`?u.push(`import '${l}';`):u.push(`// Per-island hydration mode — no shared runtime needed`),u.push(``);let d=t.globalCSS??[];for(let e of d){let t=e.startsWith(`/`)?e:`/${e}`;u.push(`// Global CSS`),u.push(`import '${t}';`)}if(d.length>0&&u.push(``),c.length>0){u.push(`// Layout CSS (auto-discovered)`);let e=0;for(let t of c)t.includes(`.module.`)?(u.push(`import _lcss${e} from '${t}';`),e++):u.push(`import '${t}';`)}return u.push(``),u.join(`
32
- `)}export function generateIntegrationLoaderModule(e){let t=(e.integrations??[]).map(e=>typeof e==`string`?e:e.name),n={preact:`@useavalon/preact/client`,react:`@useavalon/preact/client`,vue:`@useavalon/vue/client`,svelte:`@useavalon/svelte/client`,solid:`@useavalon/solid/client`,lit:`@useavalon/lit/client`,qwik:`@useavalon/qwik/client`},r={preact:`@useavalon/preact/client/hmr`,react:`@useavalon/react/client/hmr`,vue:`@useavalon/vue/client/hmr`,svelte:`@useavalon/svelte/client/hmr`,solid:`@useavalon/solid/client/hmr`,lit:`@useavalon/lit/client/hmr`,qwik:`@useavalon/qwik/client/hmr`},i=t.includes(`lit`),a=t.includes(`solid`),o=(globalThis.__avalonConfig?.isDev??e.isDev)===!0,s=[`// Auto-generated by Avalon — only includes configured integrations`,``];a&&!o&&(s.push(`// --- Inlined Solid adapter (production) ---`),s.push(`// Eliminates a separate chunk + network request for the Solid client adapter.`),s.push(`// Only imports hydrate/createComponent — no render() fallback (saves ~1-2 KiB).`),s.push(`function _ensureHydrationContext() {`),s.push(` if (!globalThis._$HY) {`),s.push(` globalThis._$HY = { events: [], completed: new WeakSet(), r: {}, fe() {} };`),s.push(` }`),s.push(`}`),s.push(``),s.push(`async function _solidHydrate(container, Component, props) {`),s.push(` if (!container) throw new Error("Container element is required for hydration");`),s.push(` if (!Component || typeof Component !== "function") {`),s.push(` throw new Error("Invalid Solid component: expected function, got " + typeof Component);`),s.push(` }`),s.push(` var el = container;`),s.push(` var renderId = el.dataset.solidRenderId || el.dataset.renderId;`),s.push(` var { hydrate: solidHydrate, createComponent } = await import("solid-js/web");`),s.push(` _ensureHydrationContext();`),s.push(` solidHydrate(function() { return createComponent(Component, props || {}); }, el, { renderId: renderId || "" });`),s.push(`}`),s.push(``),s.push(`var _solidModule = { hydrate: _solidHydrate };`),s.push(``)),s.push(`// --- loadIntegrationModule ---`),s.push(`export async function loadIntegrationModule(framework) {`),s.push(` switch (framework) {`);for(let e of t){let t=n[e];t&&(e===`solid`&&!o?(s.push(` case "solid":`),s.push(` return _solidModule;`)):e===`react`?s.push(` case "react":`):e===`preact`?(s.push(` case "preact":`),s.push(` return import("${t}");`)):(s.push(` case "${e}":`),s.push(` return import("${t}");`)))}t.includes(`react`)&&!t.includes(`preact`)&&s.push(` return import("${n.react}");`),s.push(` default:`),s.push(" throw new Error(`Unknown or unconfigured framework: ${framework}`);"),s.push(` }`),s.push(`}`),s.push(``),s.push(`// --- Lit hydration pre-load (only if Lit is configured) ---`),i?(s.push(`export async function preLitHydration() {`),s.push(` await import("@useavalon/lit/client");`),s.push(`}`)):s.push(`export async function preLitHydration() {}`),s.push(``),s.push(`// --- HMR adapter loader ---`),s.push(`export async function loadHMRAdapter(framework) {`),s.push(` switch (framework) {`);for(let e of t){let t=r[e];t&&(s.push(` case "${e}":`),s.push(` return import("${t}").then(m => m.${e}Adapter);`))}return s.push(` default: return null;`),s.push(` }`),s.push(`}`),s.join(`
33
- `)}export function getViteDevServer(){return globalThis.__viteDevServer}export function getAvalonConfig(){return globalThis.__avalonConfig}export function isDevelopmentMode(){return globalThis.__avalonConfig?.isDev??!0}const K=`<!--AVALON_STREAM_BOUNDARY-->`;let q=null,J=null;async function se(e,t,n,r){if(!n.modules)return!1;let i=t.split(`?`)[0],a=await Q(i,n,e);if(!a)return!1;try{let t=await e.ssrLoadModule(a),n=t.default;if(!n)return!1;let o=t.layoutConfig,s=await w(e,a),c=await Z(i,e),l=[];for(let t of c){let n=await e.ssrLoadModule(t);l.push({file:t,module:n})}for(let t of c){let n=await w(e,t);s.push(...n)}if(l.length===0)return!1;let{render:u}=await e.ssrLoadModule(`preact-render-to-string`),{h:d}=await e.ssrLoadModule(`preact`),f=o?.skipLayouts||[],g=l.filter(({file:e})=>{let t=e.split(`/`).pop()?.replace(/\.[^.]+$/,``)||``;return!f.includes(t)}),_=t.frontmatter,v=t.metadata,y={children:null,frontmatter:{..._,...v,currentPath:i},params:{},url:i},b=[],x=[];for(let e of g){let t=e.module.default;if(!(!t||typeof t!=`function`))try{let n=t({...y,children:d(`div`,null,`test`)}),r=u(n instanceof Promise?await n:n);r.trim().startsWith(`<html`)||r.includes(`<!DOCTYPE`)?b.push(e):x.push(e)}catch{x.push(e)}}if(b.length===0)return!1;let{module:S}=b[b.length-1],C=S.default;if(!C||typeof C!=`function`)return!1;let T;try{let e=C({...y,children:d(`div`,{dangerouslySetInnerHTML:{__html:K}})});T=u(e instanceof Promise?await e:e)}catch{return!1}let E=T.indexOf(K);if(E===-1)return!1;let D=T.slice(0,E),O=T.slice(E+29),k=D;if(s.length>0){let e=`<style data-avalon-ssr-css>${s.join(`
34
- `)}</style>`;k=D.includes(`</head>`)?D.replace(`</head>`,`${e}\n</head>`):D+e}k.trim().toLowerCase().startsWith(`<!doctype`)||(k=`<!DOCTYPE html>\n${k}`);let A=p(!0);A&&k.includes(`</head>`)&&(k=k.replace(`</head>`,`${A}\n</head>`));let j=m(!0);j&&k.includes(`</head>`)&&(k=k.replace(`</head>`,`${j}\n</head>`)),k=h(k),r.statusCode=200,r.setHeader(`Content-Type`,`text/html; charset=utf-8`),r.setHeader(`Transfer-Encoding`,`chunked`),r.setHeader(`X-Avalon-Streaming`,`1`),r.flushHeaders(),r.write(k);let M;try{let e=typeof n==`function`?n():n;M=u(e instanceof Promise?await e:e)}catch(e){console.error(`[SSR Streaming] Error rendering page component:`,e),M=`<div>Error rendering page</div>`}if(M.trim().startsWith(`<!DOCTYPE html>`)||M.trim().startsWith(`<html`))return r.end(M),!0;let N=M;for(let{module:e}of x){let t=e.default;if(!(!t||typeof t!=`function`))try{let e=t({...y,children:d(`div`,{dangerouslySetInnerHTML:{__html:N}})});N=u(e instanceof Promise?await e:e)}catch(e){console.error(`[SSR Streaming] Error rendering wrapper layout:`,e)}}let P=N+O;if(!P.includes(`/src/client/main.js`)&&!P.includes(`/@vite/client`)){let e=P.lastIndexOf(`</body>`);e!==-1&&(P=P.slice(0,e)+`
18
+ `}function Ce(e,t){let n={avalon:{streaming:t.streaming??!0,pagesDir:e.pagesDir,layoutsDir:e.layoutsDir,isDev:e.isDev},...t.runtimeConfig};return`export const runtimeConfig = ${JSON.stringify(n,null,2)};\nexport function useRuntimeConfig() { return runtimeConfig; }\nexport default runtimeConfig;\n`}export function generateConfigModule(e,t){let n=globalThis.__avalonConfig?.isDev??e.isDev,r={streaming:t.streaming??!0,pagesDir:e.pagesDir,layoutsDir:e.layoutsDir,isDev:n,...t.runtimeConfig};return`globalThis.__avalonHydrationMode = "${n?`entry-client`:`per-island`}";\nconst config = ${JSON.stringify(r,null,2)};\nexport function useAvalonConfig() { return config; }\nexport default config;\n`}async function we(e,t,n){let{getAllLayoutDirs:r}=await import(`./module-discovery.js`),{relative:i,resolve:a}=await import(`node:path`),{stat:o,readFile:c}=await import(`node:fs/promises`),l=process.cwd(),u=await r(e.layoutsDir,e.modules,l),d=[],f=0,p=a(l,e.layoutsDir);for(let{dir:t,prefix:n}of u){let r=s(t,`_layout.tsx`);try{if(!(await o(r)).isFile())continue}catch{continue}let a=i(l,r).replaceAll(`\\`,`/`),c=a.startsWith(`/`)?a:`/${a}`,u=t.startsWith(p),m=u&&!e.modules?`RootLayout`:`Layout_${f}`;d.push({prefix:n,importPath:c,varName:m,isShared:u,filePath:r}),f++}let m=d.filter(e=>e.isShared),h=d.filter(e=>!e.isShared),g=new Map;for(let e of h)try{let t=(await c(e.filePath,`utf8`)).match(/layoutConfig\s*=\s*{[\s\S]*?skipLayouts\s*:\s*\[([^\]]*)\]/)?.[1]??``,n=/['"`]_layout['"`]/.test(t);g.set(e.importPath,n)}catch{g.set(e.importPath,!1)}let _=d.map(e=>`import ${e.varName} from '${e.importPath}';`),v=h.toSorted((e,t)=>t.prefix.length-e.prefix.length).map(e=>{let t=e.prefix===`/`,n=g.get(e.importPath)??!1,r=t||n;return` { prefix: ${JSON.stringify(e.prefix)}, Layout: ${e.varName}, skipRoot: ${r} }`}),y=m.length>0?m[0].varName:`null`,b=JSON.stringify(n);return[`// Auto-generated by Avalon — do not edit`,...fe(e.core),`import { getUniversalCSSForHead } from '@useavalon/avalon/islands/universal-css-collector';`,`import { getUniversalHeadForInjection, injectSolidHydrationScriptIfNeeded } from '@useavalon/avalon/islands/universal-head-collector';`,..._,``,`const RootLayoutComponent = ${y};`,`const _cssLinks = ${b};`,``,`const moduleLayouts = [`,v.join(`,
19
+ `),`];`,``,`function getLayoutsForPath(pathname) {`,` for (const entry of moduleLayouts) {`,` if (entry.prefix === '/' ? pathname === '/' : pathname.startsWith(entry.prefix)) {`,` return entry;`,` }`,` }`,` return null;`,`}`,``,`function injectUniversalAssets(html) {`,` // In dev, inject <link> tags for all discovered CSS files.`,` // The ?direct suffix makes Vite return raw CSS (text/css) instead`,` // of a JS module wrapper, so <link rel="stylesheet"> works.`,` if (process.env.NODE_ENV !== 'production' && _cssLinks.length > 0) {`,` var links = _cssLinks.map(function(href) {`,` return '<link rel="stylesheet" href="' + href + '?direct">';`,String.raw` }).join('\n');`,` if (html.includes('</head>')) {`,String.raw` html = html.replace('</head>', links + '\n</head>');`,` }`,` }`,` const universalCSS = getUniversalCSSForHead(true);`,` if (universalCSS && html.includes('</head>')) {`,String.raw` html = html.replace('</head>', universalCSS + '\n</head>');`,` }`,` const universalHead = getUniversalHeadForInjection(true);`,` if (universalHead && html.includes('</head>')) {`,String.raw` html = html.replace('</head>', universalHead + '\n</head>');`,` }`,` html = injectSolidHydrationScriptIfNeeded(html);`,` return html;`,`}`,``,`export async function wrapWithLayouts(pageHtml, pageModule, context, injectAssets) {`,` const pathname = context.url.pathname;`,` const frontmatter = {`,` ...(pageModule.frontmatter || {}),`,` ...(pageModule.metadata || {}),`,` currentPath: pathname,`,` };`,` const pageLayoutConfig = pageModule.layoutConfig;`,` const skipAll = pageLayoutConfig?.skipLayouts?.includes('_layout');`,``,` const layoutEntry = getLayoutsForPath(pathname);`,` const routeInfo = { path: pathname, params: context.params, query: context.url.searchParams };`,` let html;`,``,` if (!layoutEntry || skipAll) {`,` if (RootLayoutComponent && !skipAll) {`,` const rootProps = {`,` children: h('avalon-page', { id: 'app', dangerouslySetInnerHTML: { __html: pageHtml } }),`,` frontmatter,`,` data: {},`,` route: routeInfo,`,` };`,` const rootResult = RootLayoutComponent(rootProps);`,` const resolvedRoot = rootResult instanceof Promise ? await rootResult : rootResult;`,String.raw` html = '<!DOCTYPE html>\n' + preactRenderToString(resolvedRoot);`,` } else {`,` // skipAll is true — page provides its own HTML shell or needs a minimal one`,` if (pageHtml.trimStart().startsWith('<html')) {`,String.raw` html = '<!DOCTYPE html>\n' + pageHtml;`,` } else {`,` const title = String(frontmatter.title || 'Avalon');`,` html = [`,` '<!DOCTYPE html>',`,` '<html lang="en">',`,` '<head>',`,` '<meta charset="utf-8">',`,` '<meta name="viewport" content="width=device-width, initial-scale=1">',`,` '<title>' + title + '</title>',`,` '</head>',`,` '<body>',`,` '<div id="app">' + pageHtml + '</div>',`,` '</body>',`,` '</html>',`,String.raw` ].join('\n');`,` }`,` }`,` } else {`,` const layoutProps = {`,` children: h('avalon-page', { dangerouslySetInnerHTML: { __html: pageHtml } }),`,` frontmatter,`,` data: {},`,` route: routeInfo,`,` };`,` const layoutResult = layoutEntry.Layout(layoutProps);`,` const resolvedLayout = layoutResult instanceof Promise ? await layoutResult : layoutResult;`,` let wrappedHtml = preactRenderToString(resolvedLayout);`,``,` // If the layout provides its own HTML shell (starts with <html),`,` // skip root wrapping regardless of skipRoot flag — the layout IS the document.`,` const layoutProvidesShell = wrappedHtml.trimStart().startsWith('<html');`,``,` if (!layoutProvidesShell && !layoutEntry.skipRoot && RootLayoutComponent) {`,` const rootProps = {`,` children: h('avalon-page', { dangerouslySetInnerHTML: { __html: wrappedHtml } }),`,` frontmatter,`,` data: {},`,` route: routeInfo,`,` };`,` const rootResult = RootLayoutComponent(rootProps);`,` const resolvedRoot = rootResult instanceof Promise ? await rootResult : rootResult;`,` wrappedHtml = preactRenderToString(resolvedRoot);`,` }`,``,String.raw` html = '<!DOCTYPE html>\n' + wrappedHtml;`,` }`,``,` if (injectAssets) {`,` html = injectAssets(html);`,` }`,` return injectUniversalAssets(html);`,`}`,``,`export default { wrapWithLayouts };`,``].join(`
20
+ `)}function Te(e){let t=e.clientEntry??`app/entry-client`;return[`// Auto-generated by Avalon — do not edit`,`// @ts-ignore — virtual import resolved by Nitro's Vite assets plugin at build time`,`import clientAssets from '${t.startsWith(`/`)?t:`/${t}`}?assets=client';`,``,`function buildAssetTags() {`,` const cssLinks = (clientAssets?.css ?? [])`,` .filter(attr => {`,` const href = attr.href || '';`,` // The SSR build produces ssr-index-*.css containing all global, reset,`,` // token, and layout CSS module styles. The client build may also emit`,` // entry-client-*.css (a subset) and index-*.css. To avoid duplicates,`,` // prefer ssr-index when it exists; otherwise fall back to the others.`,` var hasSsrIndex = (clientAssets?.css ?? []).some(function(a) { return (a.href || '').includes('ssr-index'); });`,` if (hasSsrIndex) return href.includes('ssr-index');`,` if (href.includes('entry-client') && href.endsWith('.css')) return true;`,String.raw` if (/\/index-[^/]+\.css$/.test(href)) return true;`,` return false;`,` })`,` .map(attr => '<link rel="stylesheet" href="' + attr.href + '">')`,String.raw` .join('\n');`,` const jsPreloads = (clientAssets?.js ?? [])`,` .map(attr => '<link rel="modulepreload" href="' + attr.href + '">')`,String.raw` .join('\n');`,` const entryScript = clientAssets?.entry`,` ? '<script type="module" src="' + clientAssets.entry + '"><\/script>'`,` : '';`,` return { cssLinks, jsPreloads, entryScript };`,`}`,``,`export function injectAssets(html) {`,` const { cssLinks, jsPreloads, entryScript } = buildAssetTags();`,` if (html.includes('</head>')) {`,String.raw` html = html.replace('</head>', cssLinks + '\n' + jsPreloads + '\n</head>');`,` }`,` if (html.includes('</body>')) {`,String.raw` html = html.replace('</body>', entryScript + '\n</body>');`,` }`,` return html;`,`}`,``,`export { clientAssets };`,`export default { injectAssets, clientAssets };`,``].join(`
21
+ `)}function Ee(e){let t=Array.isArray(e.integrations)?e.integrations:[],n=[],r=[];for(let e of t){let t=`${e}Integration`;n.push(`import { ${t} } from '@useavalon/${e}';`),r.push(`registry.register(${t});`)}let i=pe(e.core);return[`// Auto-generated by Avalon — do not edit`,`import { createNitroRenderer } from '@useavalon/avalon/nitro/renderer';`,`import { registerBuiltinDirectives } from '@useavalon/avalon';`,`import { registry } from '@useavalon/avalon/islands/integration-registry';`,`import avalonConfig from 'virtual:avalon/config';`,`import { loadPage } from 'virtual:avalon/page-loader';`,`import { wrapWithLayouts } from 'virtual:avalon/layouts';`,`import { injectAssets } from 'virtual:avalon/assets';`,...n,``,...i,``,`// Pre-register framework integrations for SSR`,...r,``,`// Register built-in custom hydration directives (on:delay, on:scroll, etc.)`,`registerBuiltinDirectives();`,``,`// Set hydration mode flag — intentionally duplicated from virtual:avalon/config`,`// for module-load-order resilience (config import may be tree-shaken or deferred).`,`globalThis.__avalonHydrationMode = avalonConfig.isDev ? "entry-client" : "per-island";`,``,`export default createNitroRenderer({`,` avalonConfig,`,` isDev: avalonConfig.isDev,`,` resolvePageRoute: async (pathname) => {`,` const mod = loadPage(pathname);`,` if (!mod || !('default' in mod)) return null;`,` return { filePath: '[virtual:' + pathname + ']', pattern: pathname, params: {} };`,` },`,` loadPageModule: async (filePath) => {`,String.raw` const match = filePath.match(/^\[virtual:(.+)\]$/);`,` const pathname = match ? match[1] : filePath;`,` const mod = loadPage(pathname);`,` if (mod) return mod;`,` return { default: () => null, metadata: { title: 'Avalon' } };`,` },`,` wrapWithLayouts: (pageHtml, pageModule, context) =>`,` wrapWithLayouts(pageHtml, pageModule, context, injectAssets),`,`});`,``].join(`
22
+ `)}async function De(e,t){let{readdir:n}=await import(`node:fs/promises`),{relative:r,join:i}=await import(`node:path`),a=[];for(let{dir:o}of e){let e;try{e=await n(o,{withFileTypes:!0})}catch{continue}for(let n of e){if(!n.isFile()||!n.name.endsWith(`.css`))continue;let e=r(t,i(o,n.name)).replaceAll(`\\`,`/`);a.push(e.startsWith(`/`)?e:`/${e}`)}}return a}function Oe(e){if(e.length===0)return[];let t=[`// Layout CSS (auto-discovered)`],n=0;for(let r of e)r.includes(`.module.`)?(t.push(`import _lcss${n} from '${r}';`),n++):t.push(`import '${r}';`);return t}async function ke(e,t){let{getAllLayoutDirs:n}=await import(`./module-discovery.js`),r=process.cwd(),i=await De(await n(e.layoutsDir,e.modules,r),r),a=globalThis.__avalonConfig?.isDev??e.isDev?`@useavalon/avalon/client/main`:`@useavalon/avalon/client/main-slim`,o=[`// Auto-generated by Avalon — do not edit`,`// Island hydration runtime`];(globalThis.__avalonHydrationMode??`entry-client`)===`entry-client`?o.push(`import '${a}';`):o.push(`// Per-island hydration mode — no shared runtime needed`),o.push(``);let s=t.globalCSS??[];for(let e of s){let t=e.startsWith(`/`)?e:`/${e}`;o.push(`// Global CSS`,`import '${t}';`)}return s.length>0&&o.push(``),o.push(...Oe(i),``),o.join(`
23
+ `)}function Ae(){return[`// --- Inlined Solid adapter (production) ---`,`// Eliminates a separate chunk + network request for the Solid client adapter.`,`// Only imports hydrate/createComponent — no render() fallback (saves ~1-2 KiB).`,`function _ensureHydrationContext() {`,` if (!globalThis._$HY) {`,` globalThis._$HY = { events: [], completed: new WeakSet(), r: {}, fe() {} };`,` }`,`}`,``,`async function _solidHydrate(container, Component, props) {`,` if (!container) throw new Error("Container element is required for hydration");`,` if (!Component || typeof Component !== "function") {`,` throw new Error("Invalid Solid component: expected function, got " + typeof Component);`,` }`,` var el = container;`,` var renderId = el.dataset.solidRenderId || el.dataset.renderId;`,` var { hydrate: solidHydrate, createComponent } = await import("solid-js/web");`,` _ensureHydrationContext();`,` solidHydrate(function() { return createComponent(Component, props || {}); }, el, { renderId: renderId || "" });`,`}`,``,`var _solidModule = { hydrate: _solidHydrate };`,``]}function je(e,t,n){let r=[];for(let i of e){let e=t[i];e&&(i===`solid`&&!n?r.push(` case "solid":`,` return _solidModule;`):i===`react`?r.push(` case "react":`):r.push(` case "${i}":`,` return import("${e}");`))}return e.includes(`react`)&&!e.includes(`preact`)&&r.push(` return import("${t.react}");`),r}function Me(e,t){let n=[];for(let r of e){let e=t[r];e&&n.push(` case "${r}":`,` return import("${e}").then(m => m.${r}Adapter);`)}return n}export function generateIntegrationLoaderModule(e){let t=(e.integrations??[]).map(e=>typeof e==`string`?e:e.name),n={preact:`@useavalon/preact/client`,react:me(e.core),vue:`@useavalon/vue/client`,svelte:`@useavalon/svelte/client`,solid:`@useavalon/solid/client`,lit:`@useavalon/lit/client`,qwik:`@useavalon/qwik/client`},r={preact:`@useavalon/preact/client/hmr`,react:`@useavalon/react/client/hmr`,vue:`@useavalon/vue/client/hmr`,svelte:`@useavalon/svelte/client/hmr`,solid:`@useavalon/solid/client/hmr`,lit:`@useavalon/lit/client/hmr`,qwik:`@useavalon/qwik/client/hmr`},i=t.includes(`lit`),a=t.includes(`solid`),o=(globalThis.__avalonConfig?.isDev??e.isDev)===!0,s=[`// Auto-generated by Avalon — only includes configured integrations`,``];return a&&!o&&s.push(...Ae()),s.push(`// --- loadIntegrationModule ---`,`export async function loadIntegrationModule(framework) {`,` switch (framework) {`,...je(t,n,o),` default:`," throw new Error(`Unknown or unconfigured framework: ${framework}`);",` }`,`}`,``,`// --- Lit hydration pre-load (only if Lit is configured) ---`),i?s.push(`export async function preLitHydration() {`,` await import("@useavalon/lit/client");`,`}`):s.push(`export async function preLitHydration() {}`),s.push(``,`// --- HMR adapter loader ---`,`export async function loadHMRAdapter(framework) {`,` switch (framework) {`,...Me(t,r),` default: return null;`,` }`,`}`),s.join(`
24
+ `)}export function getViteDevServer(){return globalThis.__viteDevServer}export function getAvalonConfig(){return globalThis.__avalonConfig}export function isDevelopmentMode(){return globalThis.__avalonConfig?.isDev??!0}const R=`<!--AVALON_STREAM_BOUNDARY-->`;let z=null,B=null;async function V(e,t){if(t===`react`){let e=await import(`react`),t=await import(`react-dom/server`),n=e.default??e,r=t.default??t;return{h:e.createElement??n.createElement,renderToString:t.renderToString??r.renderToString}}let n=await e.ssrLoadModule(`preact`),r=await e.ssrLoadModule(`preact-render-to-string`);return{h:n.h,renderToString:r.render??r.default}}function H(e){return e.split(`/`).pop()?.replace(/\.[^.]+$/,``)||``}async function U(e,t,n){let r=[];for(let n of t){let t=await e.ssrLoadModule(n);r.push({file:n,module:t})}for(let r of t){let t=await w(e,r);n.push(...t)}return r}async function W(e,t,n,r){let i=[],a=[];for(let o of e){let e=o.module.default;if(!(!e||typeof e!=`function`))try{let s=e({...t,children:n(`div`,null,`test`)}),c=r(s instanceof Promise?await s:s);c.trim().startsWith(`<html`)||c.includes(`<!DOCTYPE`)?i.push(o):a.push(o)}catch{a.push(o)}}return{shellLayouts:i,wrapperLayouts:a}}async function Ne(e,t,n,r){try{let i=e({...t,children:n(`div`,{dangerouslySetInnerHTML:{__html:R}})});return r(i instanceof Promise?await i:i)}catch{return null}}function Pe(e,t){let n=e;if(t.length>0){let e=`<style data-avalon-ssr-css>${t.join(`
25
+ `)}</style>`;n.includes(`</head>`)?n=n.replace(`</head>`,`${e}\n</head>`):n+=e}n.trim().toLowerCase().startsWith(`<!doctype`)||(n=`<!DOCTYPE html>\n${n}`);let r=p(!0);r&&n.includes(`</head>`)&&(n=n.replace(`</head>`,`${r}\n</head>`));let i=m(!0);return i&&n.includes(`</head>`)&&(n=n.replace(`</head>`,`${i}\n</head>`)),h(n)}async function G(e,t,n){try{let n=typeof e==`function`?e():e;return t(n instanceof Promise?await n:n)}catch(e){return console.error(`${n} Error rendering page component:`,e),`<div>Error rendering page</div>`}}async function K(e,t,n,r,i,a){let o=e;for(let{module:e}of t){let t=e.default;if(!(!t||typeof t!=`function`))try{let e=t({...n,children:r(`div`,{dangerouslySetInnerHTML:{__html:o}})});o=i(e instanceof Promise?await e:e)}catch(e){console.error(`${a} Error rendering wrapper layout:`,e)}}return o}async function Fe(e,t,n,r,i){if(t.length===0)return e;let{module:a}=t.at(-1),o=a.default;if(!o||typeof o!=`function`)return e;try{let t=o({...n,children:r(`div`,{dangerouslySetInnerHTML:{__html:e}})});return i(t instanceof Promise?await t:t)}catch(t){return console.error(`[SSR] Error rendering shell layout:`,t),e}}function Ie(e){if(e.includes(`/src/client/main.js`)||e.includes(`/@vite/client`))return e;let t=e.lastIndexOf(`</body>`);return t===-1?e:e.slice(0,t)+`
35
26
  <script type="module" src="/@vite/client"><\/script>
36
27
  <script type="module" src="/src/client/main.js"><\/script>
37
- `+P.slice(e))}return r.end(P),!0}catch(e){return r.headersSent?(r.end(`<div>Streaming SSR error: ${e.message}</div></body></html>`),!0):!1}}async function Y(e,t,n){let r=t.split(`?`)[0],i=await Q(r,n,e);if(!i)return null;try{let t=await e.ssrLoadModule(i),a=t.default;if(!a)return console.warn(`[SSR] Page ${i} has no default export`),null;let o=await w(e,i),s=await Z(r,e),c=[];for(let t of s){let n=await e.ssrLoadModule(t);c.push({file:t,module:n})}for(let t of s){let n=await w(e,t);o.push(...n)}let l;return l=n.modules&&c.length>0?await ce(a,t,c,r,n,e):await le(a,t,r,n,e),o.length>0&&(l=T(l,o)),l}catch(e){throw console.error(`[SSR] Error rendering ${i}:`,e),e}}async function ce(e,t,n,r,i,a){let{render:o}=await a.ssrLoadModule(`preact-render-to-string`),{h:s}=await a.ssrLoadModule(`preact`),c=t.layoutConfig?.skipLayouts||[],l=n.filter(({file:e})=>{let t=e.split(`/`).pop()?.replace(/\.[^.]+$/,``)||``;return!c.includes(t)}),u;try{let t=typeof e==`function`?e():e;u=o(t instanceof Promise?await t:t)}catch(e){console.error(`[SSR] Error rendering page component:`,e),u=`<div>Error rendering page</div>`}if(u.trim().startsWith(`<!DOCTYPE html>`)||u.trim().startsWith(`<html`))return X(u);let d=t.frontmatter,f=t.metadata,p={children:null,frontmatter:{...d,...f,currentPath:r},params:{},url:r},m=[],h=[];for(let e of l){let t=e.module.default;if(!(!t||typeof t!=`function`))try{let n=t({...p,children:s(`div`,null,`test`)}),r=o(n instanceof Promise?await n:n);r.trim().startsWith(`<html`)||r.includes(`<!DOCTYPE`)?m.push(e):h.push(e)}catch{h.push(e)}}let g=u;for(let{module:e}of h){let t=e.default;if(!(!t||typeof t!=`function`))try{let e=t({...p,children:s(`div`,{dangerouslySetInnerHTML:{__html:g}})});g=o(e instanceof Promise?await e:e)}catch(e){console.error(`[SSR] Error rendering wrapper layout:`,e)}}if(m.length>0){let{module:e}=m[m.length-1],t=e.default;if(t&&typeof t==`function`)try{let e=t({...p,children:s(`div`,{dangerouslySetInnerHTML:{__html:g}})});g=o(e instanceof Promise?await e:e)}catch(e){console.error(`[SSR] Error rendering shell layout:`,e)}}if(g.trim().startsWith(`<!DOCTYPE html>`)||g.trim().startsWith(`<html`))return X(g);let _=t.metadata||{},v=_.title||`Avalon App`,y=_.description||``;return`<!DOCTYPE html>
28
+ `+e.slice(t)}async function Le(e,t,n,r){if(!n.modules)return!1;let i=t.split(`?`)[0],a=await Q(i,n,e);if(!a)return!1;try{let t=await e.ssrLoadModule(a),o=t.default;if(!o)return!1;let s=t.layoutConfig,c=await w(e,a),l=await U(e,await J(i,e),c);if(l.length===0)return!1;let{h:u,renderToString:d}=await V(e,n.core),f=s?.skipLayouts||[],p=l.filter(({file:e})=>!f.includes(H(e))),m=t.frontmatter,h=t.metadata,g={children:null,frontmatter:{...m,...h,currentPath:i},params:{},url:i},{shellLayouts:_,wrapperLayouts:v}=await W(p,g,u,d);if(_.length===0)return!1;let{module:y}=_.at(-1),b=y.default;if(!b||typeof b!=`function`)return!1;let x=await Ne(b,g,u,d);if(x===null)return!1;let S=x.indexOf(R);if(S===-1)return!1;let C=x.slice(0,S),T=x.slice(S+29),E=Pe(C,c);r.statusCode=200,r.setHeader(`Content-Type`,`text/html; charset=utf-8`),r.setHeader(`Transfer-Encoding`,`chunked`),r.setHeader(`X-Avalon-Streaming`,`1`),r.flushHeaders(),r.write(E);let D=await G(o,d,`[SSR Streaming]`);if(D.trim().startsWith(`<!DOCTYPE html>`)||D.trim().startsWith(`<html`))return r.end(D),!0;let O=Ie(await K(D,v,g,u,d,`[SSR Streaming]`)+T);return r.end(O),!0}catch(e){return r.headersSent?(r.end(`<div>Streaming SSR error: ${e.message}</div></body></html>`),!0):!1}}async function Re(e,t,n){let r=t.split(`?`)[0],i=await Q(r,n,e);if(!i)return null;try{let t=await e.ssrLoadModule(i),a=t.default;if(!a)return console.warn(`[SSR] Page ${i} has no default export`),null;let o=await w(e,i),s=await U(e,await J(r,e),o),c;return c=n.modules&&s.length>0?await ze(a,t,s,r,n,e):await We(a,t,r,n,e),o.length>0&&(c=T(c,o)),c}catch(e){throw console.error(`[SSR] Error rendering ${i}:`,e),e}}async function ze(e,t,n,r,i,a){let{h:o,renderToString:s}=await V(a,i.core),c=t.layoutConfig?.skipLayouts||[],l=n.filter(({file:e})=>!c.includes(H(e))),u=await G(e,s,`[SSR]`);if(u.trim().startsWith(`<!DOCTYPE html>`)||u.trim().startsWith(`<html`))return q(u);let d=t.frontmatter,f=t.metadata,p={children:null,frontmatter:{...d,...f,currentPath:r},params:{},url:r},{shellLayouts:m,wrapperLayouts:h}=await W(l,p,o,s),g=await Fe(await K(u,h,p,o,s,`[SSR]`),m,p,o,s);if(g.trim().startsWith(`<!DOCTYPE html>`)||g.trim().startsWith(`<html`))return q(g);let _=t.metadata||{},v=_.title||`Avalon App`,y=_.description||``;return`<!DOCTYPE html>
38
29
  <html lang="en">
39
30
  <head>
40
31
  <meta charset="utf-8">
@@ -47,22 +38,22 @@ export default islandManifest;
47
38
  ${g}
48
39
  <script type="module" src="/src/client/main.js"><\/script>
49
40
  </body>
50
- </html>`}function X(e){let t=e;if(t.trim().toLowerCase().startsWith(`<!doctype`)||(t=`<!DOCTYPE html>\n${t}`),!t.includes(`data-universal-ssr="true"`)){let e=p(!0);e&&t.includes(`</head>`)&&(t=t.replace(`</head>`,`${e}\n</head>`))}let n=m(!0);if(n&&t.includes(`</head>`)&&(t=t.replace(`</head>`,`${n}\n</head>`)),t=h(t),t.includes(`/src/client/main.js`)||t.includes(`/@vite/client`))return t;let r=t.lastIndexOf(`</body>`);return r===-1?t+`
41
+ </html>`}function q(e){let t=e;if(t.trim().toLowerCase().startsWith(`<!doctype`)||(t=`<!DOCTYPE html>\n${t}`),!t.includes(`data-universal-ssr="true"`)){let e=p(!0);e&&t.includes(`</head>`)&&(t=t.replace(`</head>`,`${e}\n</head>`))}let n=m(!0);if(n&&t.includes(`</head>`)&&(t=t.replace(`</head>`,`${n}\n</head>`)),t=h(t),t.includes(`/src/client/main.js`)||t.includes(`/@vite/client`))return t;let r=t.lastIndexOf(`</body>`);return r===-1?t+`
51
42
  <script type="module" src="/@vite/client"><\/script>
52
43
  <script type="module" src="/src/client/main.js"><\/script>`:t.slice(0,r)+`
53
44
  <script type="module" src="/@vite/client"><\/script>
54
45
  <script type="module" src="/src/client/main.js"><\/script>
55
- `+t.slice(r)}async function Z(e,t){let n=t.config.root||process.cwd(),r=globalThis.__avalonConfig,a=`_layout.tsx`,o=[],s=e.split(`/`).filter(Boolean),c=[``];for(let e=0;e<s.length;e++)c.push(`/${s.slice(0,e+1).join(`/`)}`);async function l(e){try{if((await i(e)).isFile()){let t=e.slice(n.length);o.includes(t)||o.push(t)}}catch{}}if(r?.layoutsDir&&await l(`${`${n}/${r.layoutsDir}`}/${a}`),r?.modules){let e=`${n}/${r.modules.dir}`,t=r.modules.layoutsDirName,i=s[0]||``,o=[`home`,`root`,`main`,`index`];if(!i||o.includes(i.toLowerCase()))for(let n of o)await l(`${e}/${n}/${t}/${a}`);else await l(`${e}/${i}/${t}/${a}`)}let u=`${n}/src/layouts`;for(let e of c)await l(e===``?`${u}/${a}`:`${u}${e}/${a}`);return o}async function Q(e,t,n){let r=e;r.endsWith(`/`)&&r!==`/`&&(r=r.slice(0,-1)),r===`/`&&(r=`/index`);let a=[`.tsx`,`.ts`,`.jsx`,`.js`,`.mdx`,`.md`],o=n.config.root||process.cwd();async function s(e){try{if((await i(`${o}/${e}`)).isFile())return`/${e}`}catch{}return null}if(t.modules){let n=t.modules.dir,i=t.modules.pagesDirName,o=e.split(`/`).filter(Boolean),c=o[0]||``,l=[`home`,`root`,`main`,`index`],u,d;if(!c||l.includes(c.toLowerCase()))u=`home`,d=r;else{u=c;let e=o.slice(1);d=e.length>0?`/${e.join(`/`)}`:`/index`}for(let e of a){let t=await s(`${n}/${u}/${i}${d}${e}`);if(t)return t}if(!d.endsWith(`/index`))for(let e of a){let t=await s(`${n}/${u}/${i}${d}/index${e}`);if(t)return t}}let c=t.pagesDir;for(let e of a){let t=await s(`${c}${r}${e}`);if(t)return t}if(!r.endsWith(`/index`))for(let e of a){let t=await s(`${c}${r}/index${e}`);if(t)return t}return null}async function le(e,t,n,r,i){let a=t.metadata||{};try{q||=await i.ssrLoadModule(L(`src/render/ssr.ts`));let o=q;J||=await i.ssrLoadModule(L(`src/core/layout/enhanced-layout-resolver.ts`));let s=J,c={component:()=>typeof e==`function`?e():e,options:{title:a.title||`Avalon App`},frontmatter:t.frontmatter};if(o.renderToHtmlWithLayouts&&s.EnhancedLayoutResolver&&s.EnhancedLayoutResolverUtils)try{let e=i.config.root||process.cwd();if(!globalThis.__avalonLayoutResolver){let t=s.EnhancedLayoutResolver,n=r.layoutsDir||`src/layouts`;globalThis.__avalonLayoutResolver=new t({baseDirectory:`${e}/${n}`,filePattern:`_layout.tsx`,excludeDirectories:[`node_modules`,`.git`,`dist`,`build`],enableWatching:!0,developmentMode:!1,enableCaching:!0,cacheTTL:60*1e3,maxCacheSize:100,enableStreaming:!0,enableErrorBoundaries:!0,enableMetrics:!1,enableDebugInfo:!1,modulesDir:r.modules?`${e}/${r.modules.dir}`:void 0,modulesLayoutsDirName:r.modules?.layoutsDirName})}let t=`http://localhost${n}`,l={params:{},query:{},url:t,request:{method:`GET`,url:t,headers:new Headers}};return await o.renderToHtmlWithLayouts(c,globalThis.__avalonLayoutResolver,l,n,{title:a.title||`Avalon App`},void 0,{suppressWarnings:!0})}catch{}if(o.renderToHtml)return await o.renderToHtml(c,{title:a.title||`Avalon App`},void 0,{suppressWarnings:!0})}catch{}let o=a.title||`Avalon App`,s=a.description||``,c=``;try{let t=await i.ssrLoadModule(`preact-render-to-string`);t.render&&typeof e==`function`&&(c=t.render(e()))}catch{c=`<p>Loading page: ${$(n)}</p>`}return`<!DOCTYPE html>
46
+ `+t.slice(r)}async function J(e,t){let n=t.config.root||process.cwd(),r=globalThis.__avalonConfig,a=`_layout.tsx`,o=[],s=e.split(`/`).filter(Boolean),c=[``];for(let e=0;e<s.length;e++)c.push(`/${s.slice(0,e+1).join(`/`)}`);async function l(e){try{if((await i(e)).isFile()){let t=e.slice(n.length);o.includes(t)||o.push(t)}}catch{}}if(r?.layoutsDir&&await l(`${`${n}/${r.layoutsDir}`}/${a}`),r?.modules){let e=`${n}/${r.modules.dir}`,t=r.modules.layoutsDirName,i=s[0]||``,o=[`home`,`root`,`main`,`index`];if(!i||o.includes(i.toLowerCase()))for(let n of o)await l(`${e}/${n}/${t}/${a}`);else await l(`${e}/${i}/${t}/${a}`)}let u=`${n}/src/layouts`;for(let e of c)await l(e===``?`${u}/${a}`:`${u}${e}/${a}`);return o}async function Y(e,t){try{if((await i(`${e}/${t}`)).isFile())return`/${t}`}catch{}return null}async function X(e,t,n){for(let r of n){let n=await Y(e,`${t}${r}`);if(n)return n}if(!t.endsWith(`/index`))for(let r of n){let n=await Y(e,`${t}/index${r}`);if(n)return n}return null}function Z(e,t,n){let r=t.split(`/`).filter(Boolean),i=r[0]||``,a=[`home`,`root`,`main`,`index`],o,s;if(!i||a.includes(i.toLowerCase()))o=`home`,s=n;else{o=i;let e=r.slice(1);s=e.length>0?`/${e.join(`/`)}`:`/index`}return`${e.dir}/${o}/${e.pagesDirName}${s}`}async function Q(e,t,n){let r=e;r.endsWith(`/`)&&r!==`/`&&(r=r.slice(0,-1)),r===`/`&&(r=`/index`);let i=[`.tsx`,`.ts`,`.jsx`,`.js`,`.mdx`,`.md`],a=n.config.root||process.cwd();if(t.modules){let n=await X(a,Z(t.modules,e,r),i);if(n)return n}return X(a,`${t.pagesDir}${r}`,i)}function Be(e,t,n){if(globalThis.__avalonLayoutResolver)return;let r=e.EnhancedLayoutResolver,i=t.layoutsDir||`src/layouts`;globalThis.__avalonLayoutResolver=new r({baseDirectory:`${n}/${i}`,filePattern:`_layout.tsx`,excludeDirectories:[`node_modules`,`.git`,`dist`,`build`],enableWatching:!0,developmentMode:!1,enableCaching:!0,cacheTTL:60*1e3,maxCacheSize:100,enableStreaming:!0,enableErrorBoundaries:!0,enableMetrics:!1,enableDebugInfo:!1,modulesDir:t.modules?`${n}/${t.modules.dir}`:void 0,modulesLayoutsDirName:t.modules?.layoutsDirName})}async function Ve(e,t,n,r){try{let{renderToString:r}=await V(t,n.core);return typeof e==`function`?r(e()):``}catch{return`<p>Loading page: ${$(r)}</p>`}}async function He(e,t,n,r,i,a,o){if(!e.renderToHtmlWithLayouts||!t.EnhancedLayoutResolver||!t.EnhancedLayoutResolverUtils)return null;try{Be(t,r,i.config.root||process.cwd());let s=`http://localhost${a}`,c={params:{},query:{},url:s,request:{method:`GET`,url:s,headers:new Headers}};return await e.renderToHtmlWithLayouts(n,globalThis.__avalonLayoutResolver,c,a,{title:o.title||`Avalon App`},void 0,{suppressWarnings:!0})}catch{return null}}async function Ue(e,t,n,r,i,a){try{z||=await i.ssrLoadModule(P(`src/render/ssr.ts`));let o=z;B||=await i.ssrLoadModule(P(`src/core/layout/enhanced-layout-resolver.ts`));let s=B,c={component:()=>typeof e==`function`?e():e,options:{title:a.title||`Avalon App`},frontmatter:t.frontmatter},l=await He(o,s,c,r,i,n,a);if(l!==null)return l;if(o.renderToHtml)return await o.renderToHtml(c,{title:a.title||`Avalon App`},void 0,{suppressWarnings:!0})}catch{}return null}async function We(e,t,n,r,i){let a=t.metadata||{},o=await Ue(e,t,n,r,i,a);if(o!==null)return o;let s=a.title||`Avalon App`,c=a.description||``,l=await Ve(e,i,r,n);return`<!DOCTYPE html>
56
47
  <html lang="en">
57
48
  <head>
58
49
  <meta charset="utf-8">
59
50
  <meta name="viewport" content="width=device-width, initial-scale=1">
60
- <title>${$(o)}</title>
61
- ${s?`<meta name="description" content="${$(s)}">`:``}
51
+ <title>${$(s)}</title>
52
+ ${c?`<meta name="description" content="${$(c)}">`:``}
62
53
  <script type="module" src="/@vite/client"><\/script>
63
54
  </head>
64
55
  <body>
65
- <div id="app">${c}</div>
56
+ <div id="app">${l}</div>
66
57
  <script type="module" src="/src/client/main.js"><\/script>
67
58
  </body>
68
59
  </html>`}function $(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`>`,`&gt;`).replaceAll(`"`,`&quot;`).replaceAll(`'`,`&#039;`)}
@@ -1 +1 @@
1
- import{createRequire as e}from"node:module";import{dirname as t,join as n}from"node:path";import{islandClientBundlerPlugin as r}from"../build/island-client-bundler.js";import{islandCodeSplittingPlugin as i}from"../build/island-code-splitting.js";import{mdxIslandTransform as a}from"../build/mdx-island-transform.js";import{createMDXPlugin as o}from"../build/mdx-plugin.js";import{pageIslandTransform as s}from"../build/page-island-transform.js";import{registry as c}from"../core/integrations/registry.js";import{discoverIntegrationsFromIslandUsage as l}from"./auto-discover.js";import{checkDirectoriesExist as u,resolveConfig as d}from"./config.js";import{createImagePlugin as f}from"./image-optimization.js";import{activateIntegrations as p,activateSingleIntegration as m}from"./integration-activator.js";import{islandSidecarPlugin as h}from"./island-sidecar-plugin.js";import{createNitroIntegration as g}from"./nitro-integration.js";import{serverIslandsPlugin as _}from"./server-islands-plugin.js";import{formatValidationResults as v,validateActiveIntegrations as y}from"./validation.js";export async function collectIntegrationPlugins(e,t=!1){let n=[],r=[];for(let i of e){let e=await b(i,t);i===`lit`?r.push(...e):n.push(...e)}return[...r,...n]}async function b(e,t){let n=c.get(e);if(!n||typeof n.vitePlugin!=`function`)return[];try{let e=await n.vitePlugin();return(Array.isArray(e)?e:[e]).filter(e=>e!=null)}catch(t){return console.warn(`[avalon] Failed to load vite plugin for ${e}:`,t instanceof Error?t.message:t),[]}}async function x(e,t){let n=new Set;try{let r=await l(e.pagesDir,e.layoutsDir,t,e.modules?.dir);for(let t of r)e.integrations.includes(t)&&n.add(t)}catch{for(let t of e.integrations)n.add(t)}return n}async function S(e){if(!e.lazyIntegrations||e.integrations.length===0)return[...e.integrations];let t=await x(e);return t.size===0?[...e.integrations]:Array.from(t)}async function C(e){try{let t=await o({jsxImportSource:e.mdx.jsxImportSource,syntaxHighlighting:e.mdx.syntaxHighlighting,remarkPlugins:e.mdx.remarkPlugins,rehypePlugins:e.mdx.rehypePlugins,development:!0});return t.push(a({verbose:e.verbose})),t}catch(t){return e.showWarnings&&console.warn(`⚠️ Could not configure MDX plugin:`,t),[]}}function w(e,t,n){let{plugins:r,nitroOptions:i}=g(e,t);return globalThis.__nitroConfig=i,{plugins:r,options:i}}async function T(e,t,n){if(e.autoDiscoverIntegrations)try{let r=await l(e.pagesDir,e.layoutsDir,t,e.modules?.dir);for(let t of r)if(!n.has(t))try{await m(t,n,e.verbose)}catch(n){e.showWarnings&&console.warn(` ⚠️ Could not auto-load integration: ${t}`,n)}}catch(t){e.showWarnings&&console.warn(` ⚠️ Auto-discovery failed:`,t)}}function E(e,t){if(!e.validateIntegrations||t.size===0)return;let n=y(t,e.showWarnings);n.allValid||(console.error(v(n)),e.showWarnings&&console.warn(` ⚠️ Some integrations have validation issues.`))}export async function avalon(a){let o,c,l=new Set,m=d(a,!0),g=await S(m);g.length>0&&await p({...m,integrations:g},l);let v=await C(m),y=await f(m.image,m.verbose),b=[];l.size>0&&(b=await collectIntegrationPlugins(l,m.verbose));let x=[];if(a?.nitro){let{plugins:e}=w(m,a.nitro,m.verbose);x=e}let D=h({verbose:m.verbose}),O=_({verbose:m.verbose}),k=e(import.meta.url),A=null;try{A=n(t(k.resolve(`@useavalon/avalon/client`)),`main.js`)}catch{}let j=new Set([`preact`,`react`,`vue`,`svelte`,`solid`,`lit`,`qwik`].flatMap(e=>[`/@useavalon/${e}/client`,`/@useavalon/${e}/client/hmr`,`@useavalon/${e}/client`,`@useavalon/${e}/client/hmr`])),M={name:`avalon`,enforce:`pre`,config(e,{command:t}){let n={preact:[`preact`,`preact/hooks`],react:[`react`,`react-dom`,`react-dom/client`],vue:[`vue`],svelte:[`svelte`,`svelte/internal`],solid:[`solid-js`,`solid-js/web`],lit:[`lit`,`@lit-labs/ssr-client`],qwik:[`@builder.io/qwik`]},r=g.flatMap(e=>n[e]??[]);return{define:{__AVALON_PER_ISLAND__:JSON.stringify(t===`build`)},oxc:{exclude:[/node_modules\/@useavalon\/.*\.tsx?$/]},ssr:{noExternal:[/^@useavalon\//]},optimizeDeps:{exclude:[`@useavalon/avalon`,...g.map(e=>`@useavalon/${e}`)],include:r}}},configResolved(e){c=e,o=d(a,e.command===`serve`),globalThis.__avalonConfig=o,u(o,e.root)},async resolveId(e){if(e===`/src/client/main.js`&&A)return A;if(j.has(e)){let t=e.startsWith(`/`)?e.slice(1):e;return(await this.resolve(t))?.id??null}return null},async transform(e,t){if(t.includes(`@useavalon/`)&&/\.tsx?$/.test(t)){let{transform:n}=await import(`oxc-transform`),r=await n(t,e,{sourcemap:!0,typescript:{onlyRemoveTypeImports:!1}});return{code:r.code,map:r.map,moduleType:`js`}}},async buildStart(){await T(o,c?.root,l),E(o,l)},configureServer(e){globalThis.__viteDevServer=e}},N=b.filter(e=>e.name?.includes(`lit`)),P=b.filter(e=>!e.name?.includes(`lit`));return[s({pagesDir:m.pagesDir,layoutsDir:m.layoutsDir,modules:m.modules,verbose:m.verbose}),r(m,a?.nitro),i(m,a?.nitro),...y,...N,...v,M,D,O,...x,...P]}export function getResolvedConfig(){return globalThis.__avalonConfig}export function getPagesDir(){return globalThis.__avalonConfig?.pagesDir??`src/pages`}export function getLayoutsDir(){return globalThis.__avalonConfig?.layoutsDir??`src/layouts`}export function getNitroConfig(){return globalThis.__nitroConfig}export function isNitroEnabled(){return globalThis.__nitroConfig!==void 0}
1
+ import{createRequire as e}from"node:module";import{dirname as t,join as n}from"node:path";import{islandClientBundlerPlugin as r}from"../build/island-client-bundler.js";import{islandCodeSplittingPlugin as i}from"../build/island-code-splitting.js";import{mdxIslandTransform as a}from"../build/mdx-island-transform.js";import{createMDXPlugin as o}from"../build/mdx-plugin.js";import{pageIslandTransform as s}from"../build/page-island-transform.js";import{registry as c}from"../core/integrations/registry.js";import{discoverIntegrationsFromIslandUsage as l}from"./auto-discover.js";import{checkDirectoriesExist as u,resolveConfig as d}from"./config.js";import{createImagePlugin as f}from"./image-optimization.js";import{activateIntegrations as p,activateSingleIntegration as m}from"./integration-activator.js";import{islandSidecarPlugin as h}from"./island-sidecar-plugin.js";import{createNitroIntegration as g}from"./nitro-integration.js";import{serverIslandsPlugin as _}from"./server-islands-plugin.js";import{formatValidationResults as v,validateActiveIntegrations as y}from"./validation.js";export async function collectIntegrationPlugins(e,t=!1){let n=[],r=[];for(let i of e){let e=await b(i,t);i===`lit`?r.push(...e):n.push(...e)}return[...r,...n]}async function b(e,t){let n=c.get(e);if(!n||typeof n.vitePlugin!=`function`)return[];try{let e=await n.vitePlugin();return(Array.isArray(e)?e:[e]).filter(e=>e!=null)}catch(t){return console.warn(`[avalon] Failed to load vite plugin for ${e}:`,t instanceof Error?t.message:t),[]}}async function x(e,t){let n=new Set;try{let r=await l(e.pagesDir,e.layoutsDir,t,e.modules?.dir);for(let t of r)e.integrations.includes(t)&&n.add(t)}catch{for(let t of e.integrations)n.add(t)}return n}async function S(e){if(!e.lazyIntegrations||e.integrations.length===0)return[...e.integrations];let t=await x(e);return t.size===0?[...e.integrations]:Array.from(t)}async function C(e){try{let t=await o({jsxImportSource:e.mdx.jsxImportSource,syntaxHighlighting:e.mdx.syntaxHighlighting,remarkPlugins:e.mdx.remarkPlugins,rehypePlugins:e.mdx.rehypePlugins,development:!0});return t.push(a({verbose:e.verbose})),t}catch(t){return e.showWarnings&&console.warn(`⚠️ Could not configure MDX plugin:`,t),[]}}function w(e,t,n){let{plugins:r,nitroOptions:i}=g(e,t);return globalThis.__nitroConfig=i,{plugins:r,options:i}}async function T(e,t,n){if(e.autoDiscoverIntegrations)try{let r=await l(e.pagesDir,e.layoutsDir,t,e.modules?.dir);for(let t of r)if(!n.has(t))try{await m(t,n,e.verbose)}catch(n){e.showWarnings&&console.warn(` ⚠️ Could not auto-load integration: ${t}`,n)}}catch(t){e.showWarnings&&console.warn(` ⚠️ Auto-discovery failed:`,t)}}function E(e,t){if(!e.validateIntegrations||t.size===0)return;let n=y(t,e.showWarnings);n.allValid||(console.error(v(n)),e.showWarnings&&console.warn(` ⚠️ Some integrations have validation issues.`))}export async function avalon(a){let o,c,l=new Set,m=d(a,!0),g=await S(m);g.length>0&&await p({...m,integrations:g},l);let v=await C(m),y=await f(m.image,m.verbose),b=[];l.size>0&&(b=await collectIntegrationPlugins(l,m.verbose));let x=[];if(a?.nitro){let{plugins:e}=w(m,a.nitro,m.verbose);x=e}let D=h({verbose:m.verbose}),O=_({verbose:m.verbose}),k=e(import.meta.url),A=null;try{A=n(t(k.resolve(`@useavalon/avalon/client`)),`main.js`)}catch{}let j=new Set([`preact`,`react`,`vue`,`svelte`,`solid`,`lit`,`qwik`].flatMap(e=>[`/@useavalon/${e}/client`,`/@useavalon/${e}/client/hmr`,`@useavalon/${e}/client`,`@useavalon/${e}/client/hmr`])),M={name:`avalon`,enforce:`pre`,config(e,{command:t}){let n={preact:[`preact`,`preact/hooks`],react:[`react`,`react-dom`,`react-dom/client`],vue:[`vue`],svelte:[`svelte`,`svelte/internal`],solid:[`solid-js`,`solid-js/web`],lit:[`lit`,`@lit-labs/ssr-client`],qwik:[`@builder.io/qwik`]},r=g.flatMap(e=>n[e]??[]);return a?.core===`react`&&r.push(`react-dom/server`,`react/jsx-runtime`),{define:{__AVALON_PER_ISLAND__:JSON.stringify(t===`build`)},oxc:{exclude:[/node_modules\/@useavalon\/.*\.tsx?$/]},ssr:{noExternal:[/^@useavalon\//]},optimizeDeps:{exclude:[`@useavalon/avalon`,...g.map(e=>`@useavalon/${e}`)],include:r}}},configResolved(e){c=e,o=d(a,e.command===`serve`),globalThis.__avalonConfig=o,u(o,e.root)},async resolveId(e){if(e===`/src/client/main.js`&&A)return A;if(j.has(e)){let t=e.startsWith(`/`)?e.slice(1):e;return(await this.resolve(t))?.id??null}return null},async transform(e,t){if(t.includes(`@useavalon/`)&&/\.tsx?$/.test(t)){let{transform:n}=await import(`oxc-transform`),r=await n(t,e,{sourcemap:!0,typescript:{onlyRemoveTypeImports:!1}});return{code:r.code,map:r.map,moduleType:`js`}}},async buildStart(){await T(o,c?.root,l),E(o,l)},configureServer(e){globalThis.__viteDevServer=e}},N=b.filter(e=>e.name?.includes(`lit`)),P=b.filter(e=>!e.name?.includes(`lit`));return[s({pagesDir:m.pagesDir,layoutsDir:m.layoutsDir,modules:m.modules,verbose:m.verbose}),r(m,a?.nitro),i(m,a?.nitro),...y,...N,...v,M,D,O,...x,...P]}export function getResolvedConfig(){return globalThis.__avalonConfig}export function getPagesDir(){return globalThis.__avalonConfig?.pagesDir??`src/pages`}export function getLayoutsDir(){return globalThis.__avalonConfig?.layoutsDir??`src/layouts`}export function getNitroConfig(){return globalThis.__nitroConfig}export function isNitroEnabled(){return globalThis.__nitroConfig!==void 0}
@@ -71,6 +71,21 @@ export interface ResolvedImageConfig {
71
71
  * These correspond to the @useavalon/* packages
72
72
  */
73
73
  export type IntegrationName = "react" | "preact" | "vue" | "svelte" | "solid" | "lit" | "qwik";
74
+ /**
75
+ * The core rendering engine used for pages and layouts (the "page shell").
76
+ *
77
+ * - `"preact"` (default): pages/layouts render with `preact-render-to-string`,
78
+ * JSX defaults to `preact`, and React-ecosystem libraries run through
79
+ * `preact/compat` aliases. Smallest runtime.
80
+ * - `"react"`: pages/layouts render with real `react-dom/server`, JSX defaults
81
+ * to `react`, and no `preact/compat` alias is applied. Use this when you want
82
+ * React libraries (e.g. Radix UI / shadcn/ui) to run on real React with full
83
+ * fidelity and native SSR.
84
+ *
85
+ * Islands can still be authored in any framework regardless of this setting;
86
+ * `core` only controls what renders the page/layout shell.
87
+ */
88
+ export type RenderEngine = "preact" | "react";
74
89
  /**
75
90
  * MDX configuration options
76
91
  */
@@ -119,6 +134,16 @@ export interface ModulesConfig {
119
134
  * Configuration options for the Avalon Vite plugin
120
135
  */
121
136
  export interface AvalonPluginConfig {
137
+ /**
138
+ * Core rendering engine for pages and layouts.
139
+ *
140
+ * - `"preact"` (default) — render the page shell with Preact.
141
+ * - `"react"` — render the page shell with real React (`react-dom/server`),
142
+ * enabling React libraries like Radix UI / shadcn/ui to work natively.
143
+ *
144
+ * @default "preact"
145
+ */
146
+ core?: RenderEngine;
122
147
  /**
123
148
  * Directory containing page components for file-system routing
124
149
  * @default "src/pages"
@@ -261,6 +286,7 @@ export interface ResolvedModulesConfig {
261
286
  * Fully resolved configuration with defaults applied
262
287
  */
263
288
  export interface ResolvedAvalonConfig {
289
+ core: RenderEngine;
264
290
  pagesDir: string;
265
291
  layoutsDir: string;
266
292
  modules: ResolvedModulesConfig | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useavalon/avalon",
3
- "version": "0.2.0",
3
+ "version": "0.2.1-canary.2",
4
4
  "description": "Multi-framework islands architecture for the modern web",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -112,6 +112,10 @@
112
112
  "./render/collect-css": {
113
113
  "types": "./dist/src/render/collect-css.d.ts",
114
114
  "default": "./dist/src/render/collect-css.js"
115
+ },
116
+ "./render/shell-engine": {
117
+ "types": "./dist/src/render/shell-engine.d.ts",
118
+ "default": "./dist/src/render/shell-engine.js"
115
119
  }
116
120
  },
117
121
  "typesVersions": {
@@ -151,7 +155,7 @@
151
155
  }
152
156
  },
153
157
  "dependencies": {
154
- "@useavalon/core": "^0.2.0",
158
+ "@useavalon/core": "^0.2.1-canary.2",
155
159
  "@mdx-js/rollup": "^3.0.0",
156
160
  "h3": "^2.0.1-rc.16",
157
161
  "marked": "^17.0.4",