@useavalon/avalon 0.1.55 → 0.1.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/client/main-slim.js +1 -0
- package/dist/src/client/main.js +3 -3
- package/dist/src/client/strategies.js +1 -0
- package/dist/src/islands/universal-head-collector.d.ts +25 -0
- package/dist/src/islands/universal-head-collector.js +1 -1
- package/dist/src/nitro/config.d.ts +1 -1
- package/dist/src/nitro/config.js +1 -1
- package/dist/src/render/ssr.js +12 -12
- package/dist/src/vite-plugin/nitro-integration.d.ts +9 -0
- package/dist/src/vite-plugin/nitro-integration.js +15 -15
- package/package.json +9 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{loadIntegrationModule as e,preLitHydration as t}from"virtual:avalon/integration-loader";(function(){var n=document.querySelectorAll(`[data-framework]`);if(!n.length)return;var r=!1;n.forEach(function(e){var t=e.dataset.framework,n=e.dataset.condition||`on:client`;e.dataset.renderStrategy!==`ssr-only`&&(n===`on:client`?i(e,t):r=!0)}),r&&import(`./strategies.js`).then(function(e){n.forEach(function(t){var n=t.dataset.condition||`on:client`;n!==`on:client`&&t.dataset.renderStrategy!==`ssr-only`&&!t.dataset.hydrated&&e.setup(t,t.dataset.framework,n,i)})});async function i(n,r){if(!n.dataset.hydrated){var i=n.dataset.src;if(i)try{var a=n.dataset.props?JSON.parse(n.dataset.props):{};r===`lit`&&await t();var o=await import(i),s=o.default||Object.values(o).find(function(e){return typeof e==`function`&&e.prototype})||o,c=await e(r);c.hydrate&&await c.hydrate(n,s,a),n.dataset.hydrated=`true`}catch(e){console.error(`Hydration error for `+r+` island `+i+`:`,e)}}}})();
|
package/dist/src/client/main.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{loadHMRAdapter as e,loadIntegrationModule as t,preLitHydration as n}from"virtual:avalon/integration-loader";import{executeCustomDirective as r,hasClientDirective as i}from"./custom-directives.js";document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,a):a();function a(){let e=document.querySelectorAll(`[data-framework]`);e.length!==0&&e.forEach(e=>{try{let t=e.dataset.framework,n=e.dataset.condition||`on:client`;if(e.dataset.renderStrategy===`ssr-only`||!o(e,n))return;n===`on:client`?f(e,t):n===`on:visible`?s(e,t):n===`on:interaction`?c(e,t):n===`on:idle`?l(e,t):n.startsWith(`media:`)?u(e,t,n.slice(6)):e.dataset.customDirective||i(n)?r(e,n,()=>{f(e,t)})||(console.warn(`[avalon] Unknown hydration condition: "${n}". Hydrating immediately.`),f(e,t)):f(e,t)}catch(t){console.error(`Error processing island:`,t),p(e,e.dataset.framework||`unknown`,e.dataset.src||`unknown`,t)}})}function o(e,t){if(!t||t===`on:client`)return!0;if(t.startsWith(`media:`)){let e=t.slice(6);try{return globalThis.matchMedia(e).matches}catch(t){return console.error(`Invalid media query:`,e,t),!0}}return t===`on:visible`||t===`on:interaction`||t===`on:idle`||console.warn(`Unknown hydration condition:`,t),!0}function s(e,t){try{let n=new IntersectionObserver(r=>{r[0].isIntersecting&&(f(e,t),n.disconnect())},{rootMargin:`50px`,threshold:0});n.observe(e)}catch(n){console.error(`Failed to setup intersection observer:`,n),f(e,t)}}function c(e,t){let n=[`click`,`touchstart`,`mouseenter`,`focusin`],r=!1,i=()=>{r||(r=!0,n.forEach(t=>{e.removeEventListener(t,i)}),f(e,t))};try{n.forEach(t=>{e.addEventListener(t,i,{once:!0,passive:!0})})}catch(n){console.error(`Failed to setup interaction observer:`,n),f(e,t)}}function l(e,t){try{`requestIdleCallback`in globalThis?globalThis.requestIdleCallback(()=>{f(e,t)},{timeout:5e3}):document.readyState===`complete`?setTimeout(()=>{f(e,t)},200):globalThis.addEventListener(`load`,()=>{setTimeout(()=>{f(e,t)},200)},{once:!0})}catch(n){console.error(`Failed to setup idle callback:`,n),f(e,t)}}function u(e,t,n){try{let r=globalThis.matchMedia(n);if(r.matches){f(e,t);return}let i=n=>{n.matches&&(f(e,t),r.removeEventListener(`change`,i))};r.addEventListener(`change`,i)}catch(r){console.error(`Failed to setup media query:`,n,r),f(e,t)}}function d(e,t){let n=e.default;if(!n){let t=Object.keys(e).filter(e=>e!==`default`);for(let r of t){let t=e[r];if(typeof t==`function`&&t.prototype){n=t;break}}n||=e}if(!n)throw Error(`Component ${t} has no default export`);return n}async function f(e,r){if(e.dataset.hydrated)return;let i=e.dataset.src,a=e.dataset.props;if(!i){console.warn(`Island missing data-src attribute`);return}try{let o=a?JSON.parse(a):{};r===`lit`&&await n();let s=d(await import(i),i);try{let n=await t(r);if(!n.hydrate||typeof n.hydrate!=`function`)throw Error(`Integration ${r} does not export a hydrate function`);await n.hydrate(e,s,o),e.dataset.hydrated=`true`}catch(t){import.meta.env?.DEV&&console.error(`Integration hydration failed for ${r}: ${i}`,t),e.dataset.hydrationStatus=`failed`,e.dataset.hydrationError=t.message,e.dispatchEvent(new CustomEvent(`hydration-error`,{detail:{framework:r,src:i,error:t.message,timestamp:Date.now(),hydrationType:`integration-level`},bubbles:!0}))}}catch(t){console.error(`❌ Critical error hydrating ${r} island ${i}:`,t),p(e,r,i,t)}}function p(e,t,n,r){console.error(`Hydration error for ${t} island:`,{src:n,error:r.message,stack:r.stack}),e.dataset.hydrationStatus=`failed`,e.dataset.renderStrategy=`ssr-only`,e.classList.add(`hydration-failed`),e.dispatchEvent(new CustomEvent(`hydration-error`,{detail:{framework:t,src:n,error:r.message,timestamp:Date.now()},bubbles:!0})),h()&&m(e,t,n,r)}function m(e,t,n,r){let i=document.createElement(`div`);i.className=`hydration-error-indicator`,i.style.cssText=`
|
|
2
2
|
position: absolute;
|
|
3
3
|
top: 0;
|
|
4
4
|
right: 0;
|
|
@@ -11,7 +11,7 @@ import{executeCustomDirective as e,hasClientDirective as t}from"./custom-directi
|
|
|
11
11
|
z-index: 9999;
|
|
12
12
|
cursor: pointer;
|
|
13
13
|
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
|
14
|
-
`,i.textContent=`❌ ${t}`,i.title=`Hydration failed: ${n}\n${r.message}\nClick for details`,i.addEventListener(`click`,()=>{alert(`Hydration Error\n\nFramework: ${t}\nComponent: ${n}\n\nError: ${r.message}\n\nStack:\n${r.stack}`)}),globalThis.getComputedStyle(e).position===`static`&&(e.style.position=`relative`),e.appendChild(i)}function h(){return import.meta.env?.DEV||import.meta.env?.MODE===`development`||globalThis.location?.hostname===`localhost`||globalThis.location?.hostname===`127.0.0.1`}function g(e){let t=e.dataset.framework,n=e.dataset.src;if(!n)return null;let r={framework:t,src:n,props:e.dataset.props,scrollPosition:{x:globalThis.scrollX,y:globalThis.scrollY},focusedElement:document.activeElement?.id||null};try{t===`vue`&&e.__vue__?r.vueData=structuredClone(e.__vue__.$data||{}):t===`svelte`&&e.__svelte__?r.svelteState=e.__svelte__:t===`lit`&&e.tagName?.includes(`-`)&&(e.querySelector(`[data-lit-element]`)||e)._$litElement$&&(r.litProperties={})}catch(e){console.warn(`Failed to preserve island state:`,e)}return r}function _(e,t){if(t)try{if(t.scrollPosition&&globalThis.scrollTo(t.scrollPosition.x,t.scrollPosition.y),t.focusedElement){let e=document.getElementById(t.focusedElement);e&&e.focus()}e.dataset.framework===`vue`&&t.vueData&&e.__vue__&&Object.assign(e.__vue__.$data,t.vueData)}catch(e){console.warn(`Failed to restore island state:`,e)}}async function v(e,
|
|
14
|
+
`,i.textContent=`❌ ${t}`,i.title=`Hydration failed: ${n}\n${r.message}\nClick for details`,i.addEventListener(`click`,()=>{alert(`Hydration Error\n\nFramework: ${t}\nComponent: ${n}\n\nError: ${r.message}\n\nStack:\n${r.stack}`)}),globalThis.getComputedStyle(e).position===`static`&&(e.style.position=`relative`),e.appendChild(i)}function h(){return import.meta.env?.DEV||import.meta.env?.MODE===`development`||globalThis.location?.hostname===`localhost`||globalThis.location?.hostname===`127.0.0.1`}function g(e){let t=e.dataset.framework,n=e.dataset.src;if(!n)return null;let r={framework:t,src:n,props:e.dataset.props,scrollPosition:{x:globalThis.scrollX,y:globalThis.scrollY},focusedElement:document.activeElement?.id||null};try{t===`vue`&&e.__vue__?r.vueData=structuredClone(e.__vue__.$data||{}):t===`svelte`&&e.__svelte__?r.svelteState=e.__svelte__:t===`lit`&&e.tagName?.includes(`-`)&&(e.querySelector(`[data-lit-element]`)||e)._$litElement$&&(r.litProperties={})}catch(e){console.warn(`Failed to preserve island state:`,e)}return r}function _(e,t){if(t)try{if(t.scrollPosition&&globalThis.scrollTo(t.scrollPosition.x,t.scrollPosition.y),t.focusedElement){let e=document.getElementById(t.focusedElement);e&&e.focus()}e.dataset.framework===`vue`&&t.vueData&&e.__vue__&&Object.assign(e.__vue__.$data,t.vueData)}catch(e){console.warn(`Failed to restore island state:`,e)}}async function v(e,r,i,a){let o=e.dataset.props,s=o?JSON.parse(o):{};r===`lit`&&await n();let c=d(await import(i),a),l=await t(r);if(!l.hydrate||typeof l.hydrate!=`function`)throw Error(`Integration ${r} does not export a hydrate function`);l.hydrate(e,c,s),e.dataset.hydrated=`true`}function y(e,t,n,r){let i=e.querySelector(`.hmr-error-indicator`);i&&i.remove();let a=document.createElement(`div`);a.className=`hmr-error-indicator`,a.style.cssText=`
|
|
15
15
|
position: absolute;
|
|
16
16
|
top: 0;
|
|
17
17
|
left: 0;
|
|
@@ -36,4 +36,4 @@ import{executeCustomDirective as e,hasClientDirective as t}from"./custom-directi
|
|
|
36
36
|
cursor: pointer;
|
|
37
37
|
font-size: 14px;
|
|
38
38
|
line-height: 1;
|
|
39
|
-
`,c.onclick=()=>a.remove(),a.appendChild(o),a.appendChild(s),a.appendChild(c),globalThis.getComputedStyle(e).position===`static`&&(e.style.position=`relative`),e.insertBefore(a,e.firstChild)}import.meta.hot&&(import.meta.hot.accept(),import(`./hmr-coordinator.js`).then(async({initializeHMR:
|
|
39
|
+
`,c.onclick=()=>a.remove(),a.appendChild(o),a.appendChild(s),a.appendChild(c),globalThis.getComputedStyle(e).position===`static`&&(e.style.position=`relative`),e.insertBefore(a,e.firstChild)}import.meta.hot&&(import.meta.hot.accept(),import(`./hmr-coordinator.js`).then(async({initializeHMR:t,getHMRCoordinator:n})=>{t();let r=n(),i=new Set;document.querySelectorAll(`[data-framework]`).forEach(e=>{let t=e.dataset.framework;t&&i.add(t)});for(let t of i)try{let n=await e(t);n&&r.registerAdapter(t,n)}catch(e){console.warn(`[HMR] Failed to load adapter for ${t}:`,e)}}).catch(e=>{console.error(`[HMR] Failed to initialize:`,e)}),x());async function b(e,t,n,r){try{let{showHMRErrorOverlay:e}=await import(`./hmr-error-overlay.js`);e({framework:t,src:n,error:r,filePath:n})}catch{y(e,t,n,r)}}function x(){if(!import.meta.hot)return;let e=new Map;async function t(e){let t=e.replaceAll(`\\`,`/`),r=document.querySelectorAll(`[data-src*="${t}"], [data-src$="${t}"]`);if(r.length===0){let e=document.querySelectorAll(`[data-src]`);for(let r of e){let e=r.dataset.src;e&&(e.includes(t)||t.includes(e.replace(/^\//,``)))&&await n(r)}return}for(let e of r)await n(e)}async function n(t){let n=t.dataset.framework,r=t.dataset.src;if(!(!r||!n))try{let i=g(t);e.set(r,i),delete t.dataset.hydrated,delete t.dataset.hydrationStatus;let a=t.querySelector(`.hydration-error-indicator`);a&&a.remove();let o=Date.now();await v(t,n,r.includes(`?`)?`${r}&t=${o}`:`${r}?t=${o}`,r);let s=e.get(r);s&&(_(t,s),e.delete(r)),t.dispatchEvent(new CustomEvent(`hmr-update`,{detail:{framework:n,src:r,timestamp:Date.now(),success:!0},bubbles:!0}))}catch(e){console.error(`[HMR] Failed for ${n} island ${r}:`,e),t.dispatchEvent(new CustomEvent(`hmr-error`,{detail:{framework:n,src:r,error:e.message,timestamp:Date.now()},bubbles:!0})),h()&&b(t,n,r,e)}}import.meta.hot.on(`vite:beforeUpdate`,e=>{for(let n of e.updates||[]){let e=n.path||n.acceptedPath;e&&(e.includes(`/islands/`)||e.includes(`\\islands\\`))&&t(e)}}),import.meta.hot.on(`vite:beforeFullReload`,()=>{let e=document.querySelectorAll(`[data-hydrated="true"]`),t={};for(let n of e){let e=n.dataset.src;e&&(t[e]=g(n))}try{sessionStorage.setItem(`__avalon_hmr_states__`,JSON.stringify(t))}catch{}});try{let e=sessionStorage.getItem(`__avalon_hmr_states__`);if(e){let t=JSON.parse(e);sessionStorage.removeItem(`__avalon_hmr_states__`),setTimeout(()=>{for(let[e,n]of Object.entries(t)){let t=document.querySelector(`[data-src="${e}"]`);t&&n&&_(t,n)}},100)}}catch{}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function setup(e,t,n,r){if(n===`on:visible`)try{var i=new IntersectionObserver(function(n){n[0].isIntersecting&&(r(e,t),i.disconnect())},{rootMargin:`50px`,threshold:0});i.observe(e)}catch{r(e,t)}else if(n===`on:interaction`){var a=[`click`,`touchstart`,`mouseenter`,`focusin`],o=!1,s=function(){o||(o=!0,a.forEach(function(t){e.removeEventListener(t,s)}),r(e,t))};a.forEach(function(t){e.addEventListener(t,s,{once:!0,passive:!0})})}else if(n===`on:idle`){var c=function(){r(e,t)};`requestIdleCallback`in globalThis?globalThis.requestIdleCallback(c,{timeout:5e3}):document.readyState===`complete`?setTimeout(c,200):globalThis.addEventListener(`load`,function(){setTimeout(c,200)},{once:!0})}else if(n.startsWith(`media:`)){var l=n.slice(6);try{var u=globalThis.matchMedia(l);u.matches?r(e,t):u.addEventListener(`change`,function n(i){i.matches&&(r(e,t),u.removeEventListener(`change`,n))})}catch{r(e,t)}}else e.dataset.customDirective?import(`./custom-directives.js`).then(function(i){i.hasClientDirective&&i.hasClientDirective(n)?i.executeCustomDirective(e,n,function(){r(e,t)}):r(e,t)}).catch(function(){r(e,t)}):r(e,t)}
|
|
@@ -39,4 +39,29 @@ export declare function clearUniversalHead(): void;
|
|
|
39
39
|
* Get the current size of the head collector
|
|
40
40
|
*/
|
|
41
41
|
export declare function getHeadCollectorSize(): number;
|
|
42
|
+
declare global {
|
|
43
|
+
var __solidHydrationScript: string | undefined;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Store the Solid hydration bootstrap script for conditional injection.
|
|
47
|
+
*
|
|
48
|
+
* Called by the Solid renderer once per SSR lifecycle. The script is
|
|
49
|
+
* cached globally and only injected into pages that contain Solid islands.
|
|
50
|
+
*
|
|
51
|
+
* @param script - The hydration script from `generateHydrationScript()`
|
|
52
|
+
*/
|
|
53
|
+
export declare function setSolidHydrationScript(script: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* Conditionally inject the Solid hydration bootstrap script into HTML.
|
|
56
|
+
*
|
|
57
|
+
* The `window._$HY` script (~300 bytes) is only needed when Solid islands
|
|
58
|
+
* are present on the page. Instead of having the Solid renderer add it to
|
|
59
|
+
* the head collector on every render (which would inject it on every page),
|
|
60
|
+
* this function checks the final HTML for Solid islands and injects the
|
|
61
|
+
* script only when needed.
|
|
62
|
+
*
|
|
63
|
+
* @param html - The rendered HTML string to check and potentially modify
|
|
64
|
+
* @returns The HTML with the Solid hydration script injected if needed
|
|
65
|
+
*/
|
|
66
|
+
export declare function injectSolidHydrationScriptIfNeeded(html: string): string;
|
|
42
67
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
function e(){return globalThis.__universalSSRHead||(globalThis.__universalSSRHead=new Map),globalThis.__universalSSRHead}export function addUniversalHead(t,n,r,i=`other`){let a=e(),o=`${r}-${n}-${i}`;a.set(o,{content:t,src:n,framework:r,type:i})}export function getUniversalHeadForInjection(t=!1){let n=e();if(n.size===0)return``;let r=Array.from(n.values()),i=r.filter(e=>e.type===`script`),a=r.filter(e=>e.type===`meta`),o=r.filter(e=>e.type===`link`),s=r.filter(e=>e.type===`other`),c=[];a.length>0&&(c.push(`<!-- Framework Meta Tags -->`),c.push(...a.map(e=>e.content))),o.length>0&&(c.push(`<!-- Framework Links -->`),c.push(...o.map(e=>e.content))),i.length>0&&(c.push(`<!-- Framework Hydration Scripts -->`),c.push(...i.map(e=>{let t=e.content.trim();return t.startsWith(`<script`)?t:`<script>${t}<\/script>`}))),s.length>0&&(c.push(`<!-- Framework Head Content -->`),c.push(...s.map(e=>e.content)));let l=c.join(`
|
|
2
|
-
`);return t&&n.clear(),l}export function clearUniversalHead(){e().clear()}export function getHeadCollectorSize(){return e().size}
|
|
2
|
+
`);return t&&n.clear(),l}export function clearUniversalHead(){e().clear()}export function getHeadCollectorSize(){return e().size}export function setSolidHydrationScript(e){globalThis.__solidHydrationScript=e}export function injectSolidHydrationScriptIfNeeded(e){if(!e.includes(`data-framework="solid"`)||e.includes(`window._$HY`)||e.includes(`_$HY=`))return e;let t=globalThis.__solidHydrationScript;if(!t)return e;let n=t.trim().startsWith(`<script`)?t:`<script>${t}<\/script>`;return e.includes(`</head>`)?e.replace(`</head>`,`${n}\n</head>`):e}
|
|
@@ -277,7 +277,7 @@ export declare function resolvePresetName(preset: string): string;
|
|
|
277
277
|
/**
|
|
278
278
|
* Default Nitro configuration values
|
|
279
279
|
*/
|
|
280
|
-
export declare const DEFAULT_NITRO_CONFIG: Required<Pick<AvalonNitroConfig, "preset" | "serverDir" | "streaming">>;
|
|
280
|
+
export declare const DEFAULT_NITRO_CONFIG: Required<Pick<AvalonNitroConfig, "preset" | "serverDir" | "streaming" | "compressPublicAssets">>;
|
|
281
281
|
/**
|
|
282
282
|
* Creates a Nitro configuration from Avalon plugin config and Nitro-specific options
|
|
283
283
|
*
|
package/dist/src/nitro/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DEFAULT_STATIC_ASSETS_CONFIG={publicDir:`public`,buildDir:`dist`,compression:!0,cacheControl:`public, max-age=31536000, immutable`,mutableCacheControl:`public, max-age=0, must-revalidate`,headers:{}};export const VALID_V3_PRESETS=[`node_server`,`node_middleware`,`vercel`,`cloudflare_module`,`cloudflare_pages`,`deno_deploy`,`deno_server`,`netlify`,`netlify_functions`,`netlify_edge`,`aws_lambda`,`azure_swa`,`firebase_functions`,`render_com`,`static`,`browser`];export function resolvePresetName(e){if(VALID_V3_PRESETS.includes(e))return e;throw Error(`Unknown Nitro preset: "${e}". Valid presets: ${VALID_V3_PRESETS.join(`, `)}`)}export const DEFAULT_NITRO_CONFIG={preset:`node_server`,serverDir:`server`,streaming:!0};export function createNitroConfig(t,i){let a=t.pagesDir??i.pagesDir,o=i.layoutsDir,s={streaming:t.streaming??DEFAULT_NITRO_CONFIG.streaming,pagesDir:a,layoutsDir:o};if(t.runtimeConfig&&`nitro`in t.runtimeConfig)throw Error(`The "nitro" key in runtimeConfig is reserved by Nitro v3 and cannot be used.`);let c={avalon:s,...t.runtimeConfig},l={...DEFAULT_STATIC_ASSETS_CONFIG,...t.staticAssets},u=mergeRouteRules(createDefaultStaticAssetRouteRules(l),t.routeRules??{}),d=[{dir:l.publicDir??DEFAULT_STATIC_ASSETS_CONFIG.publicDir,baseURL:`/`,maxAge:0}],f=t.renderer===!1?!1:t.renderer?{...t.renderer}:void 0;return{preset:resolvePresetName(process.env.NITRO_PRESET??t.preset??DEFAULT_NITRO_CONFIG.preset),serverDir:t.serverDir??DEFAULT_NITRO_CONFIG.serverDir,routeRules:u,runtimeConfig:c,publicRuntimeConfig:t.publicRuntimeConfig,renderer:f,compatibilityDate:t.compatibilityDate,traceDeps:t.traceDeps,rolldownConfig:t.rolldownConfig,serverEntry:t.serverEntry,compressPublicAssets:t.compressPublicAssets,publicAssets:d,staticAssets:l,prerender:t.prerender}}export function createDefaultStaticAssetRouteRules(t){let n=t.cacheControl??DEFAULT_STATIC_ASSETS_CONFIG.cacheControl,r=t.mutableCacheControl??DEFAULT_STATIC_ASSETS_CONFIG.mutableCacheControl;return{"/assets/**":{headers:{"Cache-Control":n,...t.headers}},"/islands/**":{headers:{"Cache-Control":n,...t.headers}},"/chunks/**":{headers:{"Cache-Control":n,...t.headers}},"/_nuxt/**":{headers:{"Cache-Control":n,...t.headers}},"/**/*.woff":{headers:{"Cache-Control":n,...t.headers}},"/**/*.woff2":{headers:{"Cache-Control":n,...t.headers}},"/**/*.html":{headers:{"Cache-Control":r,...t.headers}},"/favicon.ico":{headers:{"Cache-Control":`public, max-age=86400`,...t.headers}},"/**/*.css":{headers:{"Cache-Control":r,...t.headers}}}}export function isValidPreset(e){return VALID_V3_PRESETS.includes(e)}export function mergeRouteRules(e,t){let n={...e};for(let[e,r]of Object.entries(t))n[e]?n[e]={...n[e],...r,headers:{...n[e].headers,...r.headers}}:n[e]=r;return n}
|
|
1
|
+
export const DEFAULT_STATIC_ASSETS_CONFIG={publicDir:`public`,buildDir:`dist`,compression:!0,cacheControl:`public, max-age=31536000, immutable`,mutableCacheControl:`public, max-age=0, must-revalidate`,headers:{}};export const VALID_V3_PRESETS=[`node_server`,`node_middleware`,`vercel`,`cloudflare_module`,`cloudflare_pages`,`deno_deploy`,`deno_server`,`netlify`,`netlify_functions`,`netlify_edge`,`aws_lambda`,`azure_swa`,`firebase_functions`,`render_com`,`static`,`browser`];export function resolvePresetName(e){if(VALID_V3_PRESETS.includes(e))return e;throw Error(`Unknown Nitro preset: "${e}". Valid presets: ${VALID_V3_PRESETS.join(`, `)}`)}export const DEFAULT_NITRO_CONFIG={preset:`node_server`,serverDir:`server`,streaming:!0,compressPublicAssets:!0};export function createNitroConfig(t,i){let a=t.pagesDir??i.pagesDir,o=i.layoutsDir,s={streaming:t.streaming??DEFAULT_NITRO_CONFIG.streaming,pagesDir:a,layoutsDir:o};if(t.runtimeConfig&&`nitro`in t.runtimeConfig)throw Error(`The "nitro" key in runtimeConfig is reserved by Nitro v3 and cannot be used.`);let c={avalon:s,...t.runtimeConfig},l={...DEFAULT_STATIC_ASSETS_CONFIG,...t.staticAssets},u=mergeRouteRules(createDefaultStaticAssetRouteRules(l),t.routeRules??{}),d=[{dir:l.publicDir??DEFAULT_STATIC_ASSETS_CONFIG.publicDir,baseURL:`/`,maxAge:0}],f=t.renderer===!1?!1:t.renderer?{...t.renderer}:void 0;return{preset:resolvePresetName(process.env.NITRO_PRESET??t.preset??DEFAULT_NITRO_CONFIG.preset),serverDir:t.serverDir??DEFAULT_NITRO_CONFIG.serverDir,routeRules:u,runtimeConfig:c,publicRuntimeConfig:t.publicRuntimeConfig,renderer:f,compatibilityDate:t.compatibilityDate,traceDeps:t.traceDeps,rolldownConfig:t.rolldownConfig,serverEntry:t.serverEntry,compressPublicAssets:t.compressPublicAssets??DEFAULT_NITRO_CONFIG.compressPublicAssets,publicAssets:d,staticAssets:l,prerender:t.prerender}}export function createDefaultStaticAssetRouteRules(t){let n=t.cacheControl??DEFAULT_STATIC_ASSETS_CONFIG.cacheControl,r=t.mutableCacheControl??DEFAULT_STATIC_ASSETS_CONFIG.mutableCacheControl;return{"/assets/**":{headers:{"Cache-Control":n,...t.headers}},"/islands/**":{headers:{"Cache-Control":n,...t.headers}},"/chunks/**":{headers:{"Cache-Control":n,...t.headers}},"/_nuxt/**":{headers:{"Cache-Control":n,...t.headers}},"/**/*.woff":{headers:{"Cache-Control":n,...t.headers}},"/**/*.woff2":{headers:{"Cache-Control":n,...t.headers}},"/**/*.html":{headers:{"Cache-Control":r,...t.headers}},"/favicon.ico":{headers:{"Cache-Control":`public, max-age=86400`,...t.headers}},"/**/*.css":{headers:{"Cache-Control":r,...t.headers}}}}export function isValidPreset(e){return VALID_V3_PRESETS.includes(e)}export function mergeRouteRules(e,t){let n={...e};for(let[e,r]of Object.entries(t))n[e]?n[e]={...n[e],...r,headers:{...n[e].headers,...r.headers}}:n[e]=r;return n}
|
package/dist/src/render/ssr.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import{h as e}from"preact";import{render as t}from"preact-render-to-string";import{readFile as n}from"node:fs/promises";import{getUniversalCSSForHead as r}from"../islands/universal-css-collector.js";import{getUniversalHeadForInjection as i}from"../islands/universal-head-collector.js";import{analyzeComponentContent as
|
|
2
|
-
`)||``}function
|
|
3
|
-
`)||``}function
|
|
4
|
-
`)||``}function
|
|
5
|
-
<script type="module" src="${e?`/src/client/main.js`:`/dist/client.js`}"><\/script>`}function
|
|
1
|
+
import{h as e}from"preact";import{render as t}from"preact-render-to-string";import{readFile as n}from"node:fs/promises";import{getUniversalCSSForHead as r}from"../islands/universal-css-collector.js";import{getUniversalHeadForInjection as i,injectSolidHydrationScriptIfNeeded as a}from"../islands/universal-head-collector.js";import{analyzeComponentContent as o}from"../core/components/component-analyzer.js";import{IsolatedSSRRenderer as s}from"./isolated-ssr-renderer.js";function c(e){let t=e;if(!(e.includes(`data-framework=`)||e.includes(`data-src=`)))return e;if(!e.includes(`data-universal-ssr="true"`)){let n=r(!0);n&&e.includes(`</head>`)&&(t=t.replace(`</head>`,`${n}\n</head>`))}let n=i(!0);if(n&&e.includes(`</head>`)&&(t=t.replace(`</head>`,` ${n}\n</head>`)),t=a(t),e.includes(`/src/client/main.js`)||e.includes(`main.js`))return t;let o=`<script type="module" src="/src/client/main.js"><\/script>`;return t.includes(`</body>`)?t.replace(`</body>`,`${o}\n</body>`):t+o}const l={solid:[`solid-js`,`SolidIsland`,`createSignal`,`.solid.`,`data-solid-hydrate`],vue:[`data-vue-hydrate`,`.vue`,`Vue`],svelte:[`data-framework="svelte"`,`.svelte`,`s-`]};let u=null;function d(){return u||=new s({enableStrictIsolation:!0,allowedCrossFrameworkImports:[`preact`,`preact-render-to-string`],errorHandling:`fallback`,debugLogging:process.env.NODE_ENV!==`production`}),u}function f(e){return{solid:l.solid.some(t=>e.includes(t)),vue:l.vue.some(t=>e.includes(t)),svelte:l.svelte.some(t=>e.includes(t))}}function p(e,t,n){let r=[],i=/^import\s[^'"]*['"]([^'"]+)['"]/gm,a=[],o;for(;(o=i.exec(t))!==null;)a.push(o[1]);let s=n;e.includes(`.solid.`)?s=`solid`:e.includes(`.preact.`)&&(s=`preact`);let c=new Map([[`preact`,[`solid-js`,`solid-js/web`,`vue`,`svelte`]],[`solid`,[`preact`,`preact-render-to-string`,`vue`,`svelte`]],[`vue`,[`preact`,`solid-js`,`svelte`]],[`svelte`,[`preact`,`solid-js`,`vue`]]]).get(s)||[];for(let t of a)for(let n of c)t.startsWith(n)&&r.push(`Cross-framework import detected: ${s} component (${e}) importing ${t}`);return r}function m(e,t){return t.type===`ssr-only`?e.replaceAll(/data-hydrate="[^"]*"\s*/g,``).replace(`>`,` data-render-strategy="${t.type}" data-ssr-reason="${t.reason}">`):e.replace(`>`,` data-render-strategy="${t.type}" data-hydrate-reason="${t.reason}">`)}async function h(e,t={}){let n=/(<[^>]*data-hydrate="([^"]*)"[^>]*>)/g,r=e,i=Array.from(e.matchAll(n));for(let e of i){let[n,i,a]=e;try{if(n.includes(`data-render-strategy`))continue;let e=await _(a,t);await g(a,t),r=r.replace(n,m(n,e)),t.logDecisions===!0&&(console.log(`[SSR Strategy] ${a} -> ${e.type.toUpperCase()}: ${e.reason}`),e.warnings&&e.warnings.length>0&&!t.suppressWarnings&&e.warnings.forEach(e=>console.warn(`[SSR Warning] ${a}: ${e}`)))}catch(e){console.warn(`Failed to analyze component ${a}:`,e);let t=n.replace(`>`,` data-render-strategy="hydrate" data-error="analysis-failed">`);r=r.replace(n,t)}}return r}async function g(e,t={}){try{let r,i=e;e.startsWith(`/`)&&(i=e.substring(1));let a=[i,`examples/${i.split(`/`).pop()}`,`src/islands/${i.split(`/`).pop()}`,`islands/${i.split(`/`).pop()}`],o=``;for(let e of a)try{r=await n(e,`utf-8`),o=e;break}catch{continue}if(!o||!r)return;let s=f(r),c=`preact`;s.solid?c=`solid`:s.vue?c=`vue`:s.svelte&&(c=`svelte`);let l=p(o,r,c);l.length>0&&!t.suppressWarnings&&l.forEach(e=>console.warn(`[Import Validation] ${e}`))}catch(n){t.logDecisions!==!1&&console.warn(`Import validation failed for ${e}:`,n)}}async function _(e,t={}){if(t.forceSSROnly)return{type:`ssr-only`,reason:`Explicitly configured for SSR-only rendering`};if(e.includes(`NoHydrate`)||e.includes(`Static`)||e.includes(`SSROnly`))return{type:`ssr-only`,reason:`Component name explicitly indicates SSR-only rendering`};if(t.detectScripts===!1)return{type:`hydrate`,reason:`Script detection disabled, defaulting to hydration`};try{let r,i=e;e.startsWith(`/`)&&(i=e.substring(1));let a=[i,`examples/${i.split(`/`).pop()}`,`src/islands/${i.split(`/`).pop()}`,`islands/${i.split(`/`).pop()}`],s=null;for(let e of a)try{r=await n(e,`utf-8`);let i={forceSSROnly:t.forceSSROnly,detectScripts:t.detectScripts,suppressWarnings:t.suppressWarnings,logDecisions:!1};s=o(e,r,i);break}catch{continue}return s?{type:s.decision.shouldHydrate?`hydrate`:`ssr-only`,reason:s.decision.reason,warnings:s.decision.warnings}:v(e)}catch(t){return console.warn(`Component analysis failed for ${e}:`,t),{type:`ssr-only`,reason:`Analysis failed, defaulting to SSR-only for safety`,warnings:[`Component analysis error: ${t instanceof Error?t.message:String(t)}`]}}}function v(e){return e.endsWith(`.vue`)||e.endsWith(`.svelte`)||e.endsWith(`.tsx`)||e.endsWith(`.jsx`)?{type:`ssr-only`,reason:`Framework component detected, defaulting to SSR-only (hydration requires explicit hydrate function)`}:{type:`ssr-only`,reason:`Unknown component type, defaulting to SSR-only for safety`}}function y(e){return e.meta?.map(({name:e,content:t})=>`<meta name="${e}" content="${t}">`).join(`
|
|
2
|
+
`)||``}function b(e){return e.styles?.map(e=>`<link rel="stylesheet" href="${e}">`).join(`
|
|
3
|
+
`)||``}function x(e){return e.scripts?.map(e=>typeof e==`string`?`<script src="${e}" defer><\/script>`:`<script ${e.src?`src="${e.src}"`:``} ${e.type?`type="${e.type}"`:``}>${e.content||``}<\/script>`).join(`
|
|
4
|
+
`)||``}function S(e,t){return`
|
|
5
|
+
<script type="module" src="${e?`/src/client/main.js`:`/dist/client.js`}"><\/script>`}function C(e,t){return e&&t?`
|
|
6
6
|
<script type="module">
|
|
7
7
|
if (import.meta.hot) {
|
|
8
8
|
import.meta.hot.accept();
|
|
9
9
|
}
|
|
10
|
-
<\/script>`:``}function
|
|
10
|
+
<\/script>`:``}function w(e){return e.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`>`,`>`).replaceAll(`"`,`"`).replaceAll(`'`,`'`)}function T(e,t,n){let a=process.env.NODE_ENV!==`production`,o=y(e),s=b(e),c=x(e),l=S(a,t),u=C(a,n),d=r(!0),f=i(!0);return`
|
|
11
11
|
<head>
|
|
12
12
|
<meta charset="utf-8">
|
|
13
13
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
14
14
|
${o}
|
|
15
|
-
<title>${
|
|
15
|
+
<title>${w(String(e.title||`Avalon App`))}</title>
|
|
16
16
|
|
|
17
17
|
<script type="importmap">
|
|
18
18
|
{
|
|
@@ -29,13 +29,13 @@ import{h as e}from"preact";import{render as t}from"preact-render-to-string";impo
|
|
|
29
29
|
${d}
|
|
30
30
|
${f}
|
|
31
31
|
${c}${l}${u}
|
|
32
|
-
</head>`.trim()}export async function renderToHtml(e,n={},r,i={}){try{let
|
|
32
|
+
</head>`.trim()}export async function renderToHtml(e,n={},r,i={}){try{let o,s;if(i.forceSSROnly===!0){let n=e.component();o=t(n instanceof Promise?await n:n),s=f(o)}else ({content:o,frameworks:s}=await O(e,i));o=await h(o,i);let c=`<!DOCTYPE html>\n<html lang="en">\n${T({...n,...e.options},s,r)}\n<body>\n${o}\n</body>\n</html>`;return c=a(c),c}catch(e){throw console.error(`Error rendering component:`,e),Error(`Failed to render component`)}}export async function renderToHtmlWithLayouts(e,t,n,r,i={},a,o={}){try{let s=e,c={default:e.component,layoutConfig:s.layoutConfig,loader:s.loader,frontmatter:e.frontmatter},l=await t.resolveAndRender(r,c,n);return l.handlers.length===0?await renderToHtml(e,i,a,o):E(await h(await j(await A(e,r,o),l,c,n,r),o),e,i,a)}catch(t){console.error(`Error rendering component with layouts:`,t);try{return await renderToHtml(e,i,a,o)}catch(e){throw console.error(`Fallback rendering also failed:`,e),Error(`Failed to render component with layouts and fallback failed`)}}}function E(e,t,n,r){if(e.trim().startsWith(`<!DOCTYPE html>`)||e.trim().startsWith(`<html`))return c(e);let i=f(e);return c(`<!DOCTYPE html>\n<html lang="en">\n${T({...n,...t.options},i,r)}\n<body>\n${e}\n</body>\n</html>`)}async function D(e,n,r,i){let a,o;if(i.forceSSROnly===!0){let n=e.component();a=t(n instanceof Promise?await n:n),o=f(a)}else ({content:a,frameworks:o}=await O(e,i));return a=await h(a,i),{head:T({...n,...e.options},o,r),content:a}}async function O(e,n){try{let t=await d().renderWithIsolation({componentPath:`route-component`,component:e.component});if(!t.success)throw Error(`Isolated rendering failed: ${t.errors.join(`, `)}`);return t.warnings.length>0&&!n.suppressWarnings&&t.warnings.forEach(e=>console.warn(`[SSR Isolation] ${e}`)),{content:t.html,frameworks:f(t.html)}}catch(n){console.warn(`[SSR] Isolated rendering failed, falling back to standard rendering:`,n);let r=e.component(),i=t(r instanceof Promise?await r:r);return{content:i,frameworks:f(i)}}}function k(e,t,n,r,i,a=`Streaming Error`,o=`route-component`){if(console.error(`[${a}]`,{message:e.message,stack:e.stack,shellSent:t,timestamp:new Date().toISOString()}),i.onError?.(e),t){console.log(`[${a}] Mid-stream error detected, injecting error boundary`);try{n.enqueue(r.encode(N(e,o))),n.enqueue(r.encode(`
|
|
33
33
|
</body>
|
|
34
|
-
</html>`))}catch(e){console.error(`[${a}] Failed to inject error boundary:`,e)}}else i.onShellError?.(e),n.enqueue(r.encode(
|
|
34
|
+
</html>`))}catch(e){console.error(`[${a}] Failed to inject error boundary:`,e)}}else i.onShellError?.(e),n.enqueue(r.encode(M(e)));n.close()}export async function renderToHtmlStream(e,t={},n,r={}){let i=new TextEncoder,a=null,o=!1;return new ReadableStream({async start(s){a=s;try{let{head:s,content:c}=await D(e,t,n,r);a.enqueue(i.encode(`<!DOCTYPE html>\n<html lang="en">\n${s}\n<body>\n`)),o=!0,r.onShellReady?.(),a.enqueue(i.encode(c)),a.enqueue(i.encode(`
|
|
35
35
|
</body>
|
|
36
|
-
</html>`)),r.onAllReady?.(),a.close()}catch(e){
|
|
36
|
+
</html>`)),r.onAllReady?.(),a.close()}catch(e){k(e instanceof Error?e:Error(String(e)),o,a,i,r)}},cancel(){try{a?.close()}catch{}}})}export async function renderToHtmlStreamWithLayouts(e,t,n,r,i={},a,o={}){let s=new TextEncoder,l=null,u=!1;return new ReadableStream({async start(d){l=d;try{let d=e,p={default:e.component,layoutConfig:d.layoutConfig,loader:d.loader,frontmatter:e.frontmatter},m=await t.resolveAndRender(r,p,n);if(m.handlers.length===0){let t=(await renderToHtmlStream(e,i,a,o)).getReader();try{for(;;){let{done:e,value:n}=await t.read();if(e)break;l.enqueue(n)}}finally{t.releaseLock()}l.close();return}let g=await h(await j(await A(e,r,o),m,p,n,r),o);if(g.trim().startsWith(`<!DOCTYPE html>`)||g.trim().startsWith(`<html`)){let e=c(g);l.enqueue(s.encode(e)),u=!0,o.onShellReady?.(),o.onAllReady?.(),l.close();return}let _=f(g),v=T({...i,...e.options},_,a);l.enqueue(s.encode(`<!DOCTYPE html>\n<html lang="en">\n${v}\n<body>\n`)),u=!0,o.onShellReady?.(),l.enqueue(s.encode(g)),l.enqueue(s.encode(`
|
|
37
37
|
</body>
|
|
38
|
-
</html>`)),o.onAllReady?.(),l.close()}catch(e){
|
|
38
|
+
</html>`)),o.onAllReady?.(),l.close()}catch(e){k(e instanceof Error?e:Error(String(e)),u,l,s,o,`Streaming Error with Layouts`,`layout-${r}`)}},cancel(){try{l?.close()}catch{}}})}async function A(e,n,r){if(r.forceSSROnly===!0){let n=e.component();return t(n instanceof Promise?await n:n)}try{let t=await d().renderWithIsolation({componentPath:n,component:e.component});if(!t.success)throw Error(`Isolated rendering failed: ${t.errors.join(`, `)}`);return t.warnings.length>0&&!r.suppressWarnings&&t.warnings.forEach(e=>console.warn(`[SSR Isolation] ${e}`)),t.html}catch(n){console.warn(`[SSR] Isolated page rendering failed, falling back to standard rendering:`,n);let r=e.component();return t(r instanceof Promise?await r:r)}}async function j(n,r,i,a,o){let s=e(`avalon-page-content`,{dangerouslySetInnerHTML:{__html:n}}),c=null;for(let n=r.handlers.length-1;n>=0;n--){let l=r.handlers[n],u={data:r.dataLoaders[n]?await r.dataLoaders[n](a):{},frontmatter:i.frontmatter||{},route:{path:o,params:a.params,query:a.query}},d=l.component,f=d({...u,children:s});if(f instanceof Promise){let r=t(await f);n===0?c=r:s=e(`avalon-layout-fragment`,{dangerouslySetInnerHTML:{__html:r}})}else s=e(d,u,s)}if(c!==null)return c;try{let e=await d().renderWithIsolation({componentPath:`layout-chain-${o}`,component:()=>s});if(e.success)return e.html}catch{}return t(s)}function M(e){let t=process.env.NODE_ENV!==`production`;return`<!DOCTYPE html>
|
|
39
39
|
<html lang="en">
|
|
40
40
|
<head>
|
|
41
41
|
<meta charset="utf-8">
|
|
@@ -76,7 +76,7 @@ import{h as e}from"preact";import{render as t}from"preact-render-to-string";impo
|
|
|
76
76
|
${t&&e.stack?`<pre>${e.stack}</pre>`:``}
|
|
77
77
|
</div>
|
|
78
78
|
</body>
|
|
79
|
-
</html>`}function
|
|
79
|
+
</html>`}function N(e,t){let n=process.env.NODE_ENV!==`production`,r=t?`<p><strong>Component ID:</strong> ${t}</p>`:``,i=e.stack?`<pre style="background:#f5f5f5;padding:10px;border-radius:4px;overflow-x:auto;font-size:12px;margin-top:10px">${e.stack}</pre>`:``,a=n?`<details style="margin-top:15px"><summary style="cursor:pointer;color:#856404;font-weight:bold">Error Details (Development Mode)</summary><div style="margin-top:10px">${r}<p><strong>Error:</strong> ${e.message}</p>${i}</div></details>`:``;return`
|
|
80
80
|
<div class="streaming-error-boundary" data-error-boundary="true"${t?` data-component-id="${t}"`:``}>
|
|
81
81
|
<div class="error-boundary-container" style="background:#fff3cd;border:2px solid #ffc107;border-radius:8px;padding:20px;margin:20px 0;font-family:system-ui,-apple-system,sans-serif">
|
|
82
82
|
<div class="error-boundary-header" style="display:flex;align-items:center;gap:10px;margin-bottom:10px">
|
|
@@ -60,6 +60,15 @@ export declare function createNitroCoordinationPlugin(options: NitroCoordination
|
|
|
60
60
|
*/
|
|
61
61
|
export declare function createVirtualModulesPlugin(options: NitroCoordinationPluginOptions): Plugin;
|
|
62
62
|
export declare function generateConfigModule(avalonConfig: ResolvedAvalonConfig, nitroConfig: AvalonNitroConfig): string;
|
|
63
|
+
/**
|
|
64
|
+
* Generate the integration loader virtual module.
|
|
65
|
+
*
|
|
66
|
+
* Only includes dynamic import() calls for frameworks that are actually
|
|
67
|
+
* configured in the avalon() config. This prevents Vite from trying to
|
|
68
|
+
* resolve @useavalon/vue/client, @useavalon/svelte/client, etc. when
|
|
69
|
+
* only preact is configured.
|
|
70
|
+
*/
|
|
71
|
+
export declare function generateIntegrationLoaderModule(avalonConfig: ResolvedAvalonConfig): string;
|
|
63
72
|
export declare function getViteDevServer(): ViteDevServer | undefined;
|
|
64
73
|
export declare function getAvalonConfig(): ResolvedAvalonConfig | undefined;
|
|
65
74
|
export declare function isDevelopmentMode(): boolean;
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import{existsSync as e}from"node:fs";import{stat as t}from"node:fs/promises";import{createRequire as n}from"node:module";import{dirname as r,join as i}from"node:path";import{nitro as a}from"nitro/vite";import{isRunnableDevEnvironment as o}from"vite";import{getUniversalCSSForHead as s}from"../islands/universal-css-collector.js";import{getUniversalHeadForInjection as c}from"../islands/universal-head-collector.js";import{clearMiddlewareCache as
|
|
1
|
+
import{existsSync as e}from"node:fs";import{stat as t}from"node:fs/promises";import{createRequire as n}from"node:module";import{dirname as r,join as i}from"node:path";import{nitro as a}from"nitro/vite";import{isRunnableDevEnvironment as o}from"vite";import{getUniversalCSSForHead as s}from"../islands/universal-css-collector.js";import{getUniversalHeadForInjection as c,injectSolidHydrationScriptIfNeeded as l}from"../islands/universal-head-collector.js";import{clearMiddlewareCache as u,discoverScopedMiddleware as d,executeScopedMiddleware as f}from"../middleware/index.js";import{createNitroConfig as p}from"../nitro/config.js";import{createIslandManifestPlugin as m,createNitroBuildPlugin as h,createSourceMapConfig as g,createSourceMapPlugin as _}from"../nitro/index.js";import{collectCssFromModuleGraph as v,injectSsrCss as y}from"../render/collect-css.js";import{generateErrorPage as b,generateFallback404 as x}from"../render/error-pages.js";function S(t){let a=i(r(n(import.meta.url).resolve(`@useavalon/avalon`)),t);if(t.endsWith(`.ts`)&&!e(a)){let t=a.replace(/\.ts$/,`.js`);if(e(t))return t}return a}function C(t,a){let o=i(r(n(i(process.cwd(),`package.json`)).resolve(`@useavalon/${t}`)),a);if(a.endsWith(`.ts`)&&!e(o)){let t=o.replace(/\.ts$/,`.js`);if(e(t))return t}return o}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`};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};export function createNitroIntegration(e,t={}){let n=p(t,e),r={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/]};t.renderer===!1?r.renderer=!1:n.renderer&&(r.renderer=n.renderer),n.publicRuntimeConfig&&(r.publicRuntimeConfig=n.publicRuntimeConfig),n.publicAssets&&(r.publicAssets=n.publicAssets),n.compressPublicAssets&&(r.compressPublicAssets=n.compressPublicAssets),n.serverEntry&&(r.serverEntry=n.serverEntry);let i=n.traceDeps??[];r.traceDeps=[...new Set([`undici`,...i])],n.prerender&&(r.prerender={routes:[],crawlLinks:!1});let o=a(r),s=createNitroCoordinationPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),c=createVirtualModulesPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),l=h(e,t),u=m(e,{verbose:e.verbose,generatePreloadHints:!0}),d=_(g(t.preset??`node_server`,e.isDev));return{nitroOptions:n,plugins:[...Array.isArray(o)?o:[o],s,c,l,u,d]}}export function createNitroCoordinationPlugin(e){let{avalonConfig:t,verbose:n}=e;return{name:`avalon:nitro-coordination`,enforce:`pre`,configResolved(e){globalThis.__avalonConfig=t},configureServer(e){globalThis.__viteDevServer=e;let r=null;async function i(){return r||=await d({baseDir:`${e.config.root||process.cwd()}/src`,devMode:!1}),r}function a(){r=null}M(e,t,n,a),i().catch(e=>{console.warn(`[middleware] Failed to discover middleware:`,e)});let s=e.environments?.ssr,c=!!s&&o(s);c&&A(e,t.integrations,n).catch(e=>{console.error(`[prewarm] Core modules pre-warm failed:`,e)}),e.middlewares.use(async(r,a,o)=>{if(!c)return o();let s=r.url||`/`;if(s.endsWith(`.html`)&&(s=s.slice(0,-5)||`/`),s===`/index`&&(s=`/`),s.startsWith(`/@`)||s.startsWith(`/__`)||s.startsWith(`/node_modules/`)||s.startsWith(`/src/client/`)||s.startsWith(`/packages/`)||s.includes(`.`)&&!s.endsWith(`/`)||s.startsWith(`/api/`))return o();try{if(await O(e,s,r,a,i,n)||await W(e,s,t,a))return;let o=await G(e,s,t);if(o){a.statusCode=200,a.setHeader(`Content-Type`,`text/html`),a.end(o);return}await k(e,s,a,t)}catch(e){console.error(`[SSR Error]`,e),a.statusCode=500,a.setHeader(`Content-Type`,`text/html`),a.end(b(e))}})},buildStart(){}}}async function O(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 f({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 k(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(x(t))}}async function A(e,t,n){let r=performance.now(),i=[{path:S(`src/render/ssr.ts`),assignTo:`ssr`},{path:S(`src/core/layout/enhanced-layout-resolver.ts`),assignTo:`layout`},{path:S(`src/middleware/index.ts`),assignTo:null},...t.map(e=>({path:C(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`&&(H=r),n===`layout`&&(U=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:t,nitroConfig:n,verbose:r}=e;return{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:null},async load(e){return e===RESOLVED_VIRTUAL_IDS.PAGE_ROUTES?await N(t,r):e===RESOLVED_VIRTUAL_IDS.PAGE_LOADER?await P(t,r):e===RESOLVED_VIRTUAL_IDS.ISLAND_MANIFEST?F():e===RESOLVED_VIRTUAL_IDS.RUNTIME_CONFIG?I(t,n):e===RESOLVED_VIRTUAL_IDS.CONFIG?generateConfigModule(t,n):e===RESOLVED_VIRTUAL_IDS.LAYOUTS?await L(t):e===RESOLVED_VIRTUAL_IDS.ASSETS?R(n):e===RESOLVED_VIRTUAL_IDS.RENDERER?z(t):e===RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY?await B(t,n):e===RESOLVED_VIRTUAL_IDS.INTEGRATION_LOADER?generateIntegrationLoaderModule(t):null},handleHotUpdate({file:e,server:n}){if(e.includes(t.pagesDir)){let e=n.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.PAGE_ROUTES);e&&n.moduleGraph.invalidateModule(e)}if(e.includes(`/layouts/`)||e.includes(`_layout`)){let e=n.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.LAYOUTS);e&&n.moduleGraph.invalidateModule(e);let t=n.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY);t&&n.moduleGraph.invalidateModule(t)}if(e.includes(`vite.config`)||e.includes(`avalon.config`)||e.includes(`nitro.config`)){let e=n.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.CONFIG);e&&n.moduleGraph.invalidateModule(e)}}}}function M(e,t,n,r){e.watcher.on(`change`,e=>{e.includes(`_middleware`)&&(u(),r?.()),(e.includes(`/render/`)||e.includes(`/layout/`)||e.includes(`/islands/`))&&(H=null,U=null),(e.includes(`/layouts/`)||e.includes(`_layout`))&&globalThis.__avalonLayoutResolver?.clearCache?.()}),e.watcher.on(`add`,e=>{e.includes(`_middleware`)&&(u(),r?.())}),e.watcher.on(`unlink`,e=>{e.includes(`_middleware`)&&(u(),r?.())})}async function N(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 = [];
|
|
2
2
|
export default pageRoutes;
|
|
3
|
-
`}}async function
|
|
3
|
+
`}}async function P(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(`,
|
|
4
4
|
`),`];`,``,`/**`,` * 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(`
|
|
5
5
|
`)}catch(e){return console.error(`[page-loader] Failed to generate page loader:`,e),`export function loadPage() { return null; }
|
|
6
6
|
export default { loadPage, routes: [] };
|
|
7
|
-
`}}function
|
|
7
|
+
`}}function F(){return`export const islandManifest = { islands: {}, clientEntry: "", css: [] };
|
|
8
8
|
export default islandManifest;
|
|
9
|
-
`}function
|
|
10
|
-
`),`];`,``,`function getLayoutsForPath(pathname) {`,` for (const entry of moduleLayouts) {`,` if (entry.prefix === '/' ? pathname === '/' : pathname.startsWith(entry.prefix)) {`,` return entry;`,` }`,` }`,` return null;`,`}`,``,`function injectUniversalAssets(html) {`,` 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>');`,` }`,` 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) {`,` const title = String(frontmatter.title || 'Avalon');`,`
|
|
11
|
-
`)}function
|
|
12
|
-
`)}function
|
|
13
|
-
`)}async function
|
|
14
|
-
`)}function
|
|
15
|
-
`)}export function getViteDevServer(){return globalThis.__viteDevServer}export function getAvalonConfig(){return globalThis.__avalonConfig}export function isDevelopmentMode(){return globalThis.__avalonConfig?.isDev??!0}const V=`<!--AVALON_STREAM_BOUNDARY-->`;let H=null,U=null;async function W(e,t,n,r){if(!n.modules)return!1;let i=t.split(`?`)[0],a=await Y(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,
|
|
16
|
-
`)}</style>`;
|
|
17
|
-
`+
|
|
9
|
+
`}function I(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={streaming:t.streaming??!0,pagesDir:e.pagesDir,layoutsDir:e.layoutsDir,isDev:e.isDev,...t.runtimeConfig};return`const config = ${JSON.stringify(n,null,2)};\nexport function useAvalonConfig() { return config; }\nexport default config;\n`}async function L(e){let{getAllLayoutDirs:t}=await import(`./module-discovery.js`),{relative:n,resolve:r}=await import(`node:path`),{stat:a}=await import(`node:fs/promises`),o=process.cwd(),s=await t(e.layoutsDir,e.modules,o),c=[],l=0,u=r(o,e.layoutsDir);for(let{dir:t,prefix:r}of s){let s=i(t,`_layout.tsx`);try{if(!(await a(s)).isFile())continue}catch{continue}let d=n(o,s).replaceAll(`\\`,`/`),f=d.startsWith(`/`)?d:`/`+d,p=t.startsWith(u),m=p&&!e.modules?`RootLayout`:`Layout_${l}`;c.push({prefix:r,importPath:f,varName:m,isShared:p}),l++}let d=c.filter(e=>e.isShared),f=c.filter(e=>!e.isShared),p=c.map(e=>`import ${e.varName} from '${e.importPath}';`),m=f.sort((e,t)=>t.prefix.length-e.prefix.length).map(e=>{let t=e.prefix===`/`;return` { prefix: ${JSON.stringify(e.prefix)}, Layout: ${e.varName}, skipRoot: ${t} }`}),h=d.length>0?d[0].varName:`null`;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';`,...p,``,`const RootLayoutComponent = ${h};`,``,`const moduleLayouts = [`,m.join(`,
|
|
10
|
+
`),`];`,``,`function getLayoutsForPath(pathname) {`,` for (const entry of moduleLayouts) {`,` if (entry.prefix === '/' ? pathname === '/' : pathname.startsWith(entry.prefix)) {`,` return entry;`,` }`,` }`,` return null;`,`}`,``,`function injectUniversalAssets(html) {`,` 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('div', { 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 {`,` 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('div', { 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 (!layoutEntry.skipRoot && RootLayoutComponent) {`,` const rootProps = {`,` children: h('div', { 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(`
|
|
11
|
+
`)}function R(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 ?? [])`,` .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(`
|
|
12
|
+
`)}function z(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();`,``,`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(`
|
|
13
|
+
`)}async function B(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=[`// Auto-generated by Avalon — do not edit`,`// Island hydration runtime`,`import '${e.isDev===!0?`@useavalon/avalon/client/main`:`@useavalon/avalon/client/main-slim`}';`,``],u=t.globalCSS??[];for(let e of u){let t=e.startsWith(`/`)?e:`/`+e;l.push(`// Global CSS`),l.push(`import '${t}';`)}if(u.length>0&&l.push(``),c.length>0){l.push(`// Layout CSS (auto-discovered)`);for(let e of c)l.push(`import '${e}';`)}return l.push(``),l.join(`
|
|
14
|
+
`)}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=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(`
|
|
15
|
+
`)}export function getViteDevServer(){return globalThis.__viteDevServer}export function getAvalonConfig(){return globalThis.__avalonConfig}export function isDevelopmentMode(){return globalThis.__avalonConfig?.isDev??!0}const V=`<!--AVALON_STREAM_BOUNDARY-->`;let H=null,U=null;async function W(e,t,n,r){if(!n.modules)return!1;let i=t.split(`?`)[0],a=await Y(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,u=await v(e,a),d=await J(i,e),f=[];for(let t of d){let n=await e.ssrLoadModule(t);f.push({file:t,module:n})}for(let t of d){let n=await v(e,t);u.push(...n)}if(f.length===0)return!1;let{render:p}=await e.ssrLoadModule(`preact-render-to-string`),{h:m}=await e.ssrLoadModule(`preact`),h=o?.skipLayouts||[],g=f.filter(({file:e})=>{let t=e.split(`/`).pop()?.replace(/\.[^.]+$/,``)||``;return!h.includes(t)}),_=t.frontmatter,y=t.metadata,b={children:null,frontmatter:{..._,...y,currentPath:i},params:{},url:i},x=[],S=[];for(let e of g){let t=e.module.default;if(!(!t||typeof t!=`function`))try{let n=t({...b,children:m(`div`,null,`test`)}),r=p(n instanceof Promise?await n:n);r.trim().startsWith(`<html`)||r.includes(`<!DOCTYPE`)?x.push(e):S.push(e)}catch{S.push(e)}}if(x.length===0)return!1;let{module:C}=x[x.length-1],w=C.default;if(!w||typeof w!=`function`)return!1;let T;try{let e=w({...b,children:m(`div`,{dangerouslySetInnerHTML:{__html:V}})});T=p(e instanceof Promise?await e:e)}catch{return!1}let E=T.indexOf(V);if(E===-1)return!1;let D=T.slice(0,E),O=T.slice(E+29),k=D;if(u.length>0){let e=`<style data-avalon-ssr-css>${u.join(`
|
|
16
|
+
`)}</style>`;k=D.includes(`</head>`)?D.replace(`</head>`,`${e}\n</head>`):D+e}k.trim().toLowerCase().startsWith(`<!doctype`)||(k=`<!DOCTYPE html>
|
|
17
|
+
`+k);let A=s(!0);A&&k.includes(`</head>`)&&(k=k.replace(`</head>`,`${A}\n</head>`));let j=c(!0);j&&k.includes(`</head>`)&&(k=k.replace(`</head>`,`${j}\n</head>`)),k=l(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=p(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 S){let t=e.default;if(!(!t||typeof t!=`function`))try{let e=t({...b,children:m(`div`,{dangerouslySetInnerHTML:{__html:N}})});N=p(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
18
|
<script type="module" src="/@vite/client"><\/script>
|
|
19
19
|
<script type="module" src="/src/client/main.js"><\/script>
|
|
20
|
-
`+
|
|
20
|
+
`+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 G(e,t,n){let r=t.split(`?`)[0],i=await Y(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 v(e,i),s=await J(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 v(e,t);o.push(...n)}let l;return l=n.modules&&c.length>0?await K(a,t,c,r,n,e):await X(a,t,r,n,e),o.length>0&&(l=y(l,o)),l}catch(e){throw console.error(`[SSR] Error rendering ${i}:`,e),e}}async function K(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 q(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 q(g);let _=t.metadata||{},v=_.title||`Avalon App`,y=_.description||``;return`<!DOCTYPE html>
|
|
21
21
|
<html lang="en">
|
|
22
22
|
<head>
|
|
23
23
|
<meta charset="utf-8">
|
|
@@ -31,12 +31,12 @@ export default islandManifest;
|
|
|
31
31
|
<script type="module" src="/src/client/main.js"><\/script>
|
|
32
32
|
</body>
|
|
33
33
|
</html>`}function q(e){let t=e;if(t.trim().toLowerCase().startsWith(`<!doctype`)||(t=`<!DOCTYPE html>
|
|
34
|
-
`+t),!t.includes(`data-universal-ssr="true"`)){let e=s(!0);e&&t.includes(`</head>`)&&(t=t.replace(`</head>`,`${e}\n</head>`))}let n=c(!0);if(n&&t.includes(`</head>`)&&(t=t.replace(`</head>`,`${n}\n</head>`)),t.includes(`/src/client/main.js`)||t.includes(`/@vite/client`))return t;let r=t.lastIndexOf(`</body>`);return r===-1?t+`
|
|
34
|
+
`+t),!t.includes(`data-universal-ssr="true"`)){let e=s(!0);e&&t.includes(`</head>`)&&(t=t.replace(`</head>`,`${e}\n</head>`))}let n=c(!0);if(n&&t.includes(`</head>`)&&(t=t.replace(`</head>`,`${n}\n</head>`)),t=l(t),t.includes(`/src/client/main.js`)||t.includes(`/@vite/client`))return t;let r=t.lastIndexOf(`</body>`);return r===-1?t+`
|
|
35
35
|
<script type="module" src="/@vite/client"><\/script>
|
|
36
36
|
<script type="module" src="/src/client/main.js"><\/script>`:t.slice(0,r)+`
|
|
37
37
|
<script type="module" src="/@vite/client"><\/script>
|
|
38
38
|
<script type="module" src="/src/client/main.js"><\/script>
|
|
39
|
-
`+t.slice(r)}async function J(e,n){let r=n.config.root||process.cwd(),i=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 t(e)).isFile()){let t=e.slice(r.length);o.includes(t)||o.push(t)}}catch{}}if(i?.layoutsDir&&await l(`${`${r}/${i.layoutsDir}`}/${a}`),i?.modules){let e=`${r}/${i.modules.dir}`,t=i.modules.layoutsDirName,n=s[0]||``,o=[`home`,`root`,`main`,`index`];if(!n||o.includes(n.toLowerCase()))for(let n of o)await l(`${e}/${n}/${t}/${a}`);else await l(`${e}/${n}/${t}/${a}`)}let u=`${r}/src/layouts`;for(let e of c)await l(e===``?`${u}/${a}`:`${u}${e}/${a}`);return o}async function Y(e,n,r){let i=e;i.endsWith(`/`)&&i!==`/`&&(i=i.slice(0,-1)),i===`/`&&(i=`/index`);let a=[`.tsx`,`.ts`,`.jsx`,`.js`,`.mdx`,`.md`],o=r.config.root||process.cwd();async function s(e){try{if((await t(`${o}/${e}`)).isFile())return`/${e}`}catch{}return null}if(n.modules){let t=n.modules.dir,r=n.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=i;else{u=c;let e=o.slice(1);d=e.length>0?`/`+e.join(`/`):`/index`}for(let e of a){let n=await s(`${t}/${u}/${r}${d}${e}`);if(n)return n}if(!d.endsWith(`/index`))for(let e of a){let n=await s(`${t}/${u}/${r}${d}/index${e}`);if(n)return n}}let c=n.pagesDir;for(let e of a){let t=await s(`${c}${i}${e}`);if(t)return t}if(!i.endsWith(`/index`))for(let e of a){let t=await s(`${c}${i}/index${e}`);if(t)return t}return null}async function X(e,t,n,r,i){let a=t.metadata||{};try{H||=await i.ssrLoadModule(
|
|
39
|
+
`+t.slice(r)}async function J(e,n){let r=n.config.root||process.cwd(),i=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 t(e)).isFile()){let t=e.slice(r.length);o.includes(t)||o.push(t)}}catch{}}if(i?.layoutsDir&&await l(`${`${r}/${i.layoutsDir}`}/${a}`),i?.modules){let e=`${r}/${i.modules.dir}`,t=i.modules.layoutsDirName,n=s[0]||``,o=[`home`,`root`,`main`,`index`];if(!n||o.includes(n.toLowerCase()))for(let n of o)await l(`${e}/${n}/${t}/${a}`);else await l(`${e}/${n}/${t}/${a}`)}let u=`${r}/src/layouts`;for(let e of c)await l(e===``?`${u}/${a}`:`${u}${e}/${a}`);return o}async function Y(e,n,r){let i=e;i.endsWith(`/`)&&i!==`/`&&(i=i.slice(0,-1)),i===`/`&&(i=`/index`);let a=[`.tsx`,`.ts`,`.jsx`,`.js`,`.mdx`,`.md`],o=r.config.root||process.cwd();async function s(e){try{if((await t(`${o}/${e}`)).isFile())return`/${e}`}catch{}return null}if(n.modules){let t=n.modules.dir,r=n.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=i;else{u=c;let e=o.slice(1);d=e.length>0?`/`+e.join(`/`):`/index`}for(let e of a){let n=await s(`${t}/${u}/${r}${d}${e}`);if(n)return n}if(!d.endsWith(`/index`))for(let e of a){let n=await s(`${t}/${u}/${r}${d}/index${e}`);if(n)return n}}let c=n.pagesDir;for(let e of a){let t=await s(`${c}${i}${e}`);if(t)return t}if(!i.endsWith(`/index`))for(let e of a){let t=await s(`${c}${i}/index${e}`);if(t)return t}return null}async function X(e,t,n,r,i){let a=t.metadata||{};try{H||=await i.ssrLoadModule(S(`src/render/ssr.ts`));let o=H;U||=await i.ssrLoadModule(S(`src/core/layout/enhanced-layout-resolver.ts`));let s=U,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: ${Z(n)}</p>`}return`<!DOCTYPE html>
|
|
40
40
|
<html lang="en">
|
|
41
41
|
<head>
|
|
42
42
|
<meta charset="utf-8">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useavalon/avalon",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.58",
|
|
4
4
|
"description": "Multi-framework islands architecture for the modern web",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -48,6 +48,14 @@
|
|
|
48
48
|
"types": "./dist/src/client/main.d.ts",
|
|
49
49
|
"default": "./dist/src/client/main.js"
|
|
50
50
|
},
|
|
51
|
+
"./client/main-slim": {
|
|
52
|
+
"types": "./dist/src/client/main-slim.d.ts",
|
|
53
|
+
"default": "./dist/src/client/main-slim.js"
|
|
54
|
+
},
|
|
55
|
+
"./client/strategies": {
|
|
56
|
+
"types": "./dist/src/client/strategies.d.ts",
|
|
57
|
+
"default": "./dist/src/client/strategies.js"
|
|
58
|
+
},
|
|
51
59
|
"./client/hmr": {
|
|
52
60
|
"types": "./dist/src/client/framework-adapter.d.ts",
|
|
53
61
|
"default": "./dist/src/client/framework-adapter.js"
|