@useavalon/avalon 0.1.93-canary.0 → 0.1.93-canary.1

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.
@@ -1,4 +1,4 @@
1
1
  import{existsSync as e,readdirSync as t,readFileSync as n,statSync as r}from"node:fs";import{dirname as i,relative as a,resolve as o}from"node:path";export function islandClientBundlerPlugin(e,t,n){let r=process.cwd(),i=new Map,a=!1,o=c(e,r);for(let e of o)d(e,r,i);let s=`\0avalon-island-entry:`,l=!1,u=[],f={},p=`dist`;return{name:`avalon:island-client-bundler`,enforce:`pre`,configResolved(e){l=e.command===`serve`,a=e.command===`build`,u=e.resolve?.alias??[],f=e.define??{},p=e.build?.outDir??`dist`},resolveId(e){return e.startsWith(s)?e:null},load(e){if(!e.startsWith(s))return null;let t=e.slice(21),n=JSON.stringify(t);if(t.includes(`.qwik.`))return a?[`export * from ${n};`,`export { _hW } from "@builder.io/qwik";`].join(`
2
2
  `):[`export * from ${n};`,`export { _hW } from "@builder.io/qwik";`,`import __C from ${n};`,`export default __C;`,`if(typeof globalThis<"u")globalThis.__avalonIsland=__C;`].join(`
3
3
  `);let r=t.includes(`.lit.`),i=t.includes(`.solid.`),o=t.includes(`.preact.`),c=t.includes(`.react.`),l=t.includes(`.vue.`)||t.endsWith(`.vue`),u=t.includes(`.svelte.`)||t.endsWith(`.svelte`),d=[];if(r&&a&&d.push(`import "@useavalon/lit/client";`),d.push(`import __C from ${n};`,`var Component = __C;`,`export { Component as default, Component };`,`if(typeof globalThis<"u")globalThis.__avalonIsland=Component;`),a){let e={solid:`@useavalon/solid/client`,preact:`@useavalon/preact/client`,react:`@useavalon/react/client`,vue:`@useavalon/vue/client`,svelte:`@useavalon/svelte/client`,lit:`@useavalon/lit/client`},t=i?`solid`:o?`preact`:c?`react`:l?`vue`:u?`svelte`:r?`lit`:null;t&&e[t]?d.push(`export { hydrate as __hydrateIsland } from ${JSON.stringify(e[t])};`):d.push(`export { loadIntegrationModule } from "virtual:avalon/integration-loader";`)}return d.join(`
4
- `)},async buildStart(){if(l)return;let t=this.environment;if(!(t&&t.name!==`client`)&&i.size>0){for(let[,e]of i)this.emitFile({type:`chunk`,id:s+e.filePath,fileName:`islands/${e.bundleKey}.js`,preserveSignature:`exports-only`});e.verbose&&console.log(`🏝️ Emitting ${i.size} island client bundles`)}},async closeBundle(){if(l||!a||i.size===0||globalThis.__avalonIslandsRebuilt)return;globalThis.__avalonIslandsRebuilt=!0;let{buildIsolatedIslands:e}=await import(`../post-build/isolated-island-builder.js`),t=new Map;for(let[e,n]of i){let r=n.filePath.includes(`.solid.`)?`solid`:n.filePath.includes(`.preact.`)?`preact`:n.filePath.includes(`.react.`)?`react`:n.filePath.includes(`.vue.`)||n.filePath.endsWith(`.vue`)?`vue`:n.filePath.includes(`.svelte.`)||n.filePath.endsWith(`.svelte`)?`svelte`:n.filePath.includes(`.lit.`)?`lit`:n.filePath.includes(`.qwik.`)?`qwik`:`preact`;t.set(e,{...n,framework:r})}await e(r,p,t,u,f,n?{treeshake:n}:void 0)}}}function c(n,r){let i=[];if(n.pagesDir){let t=o(r,n.pagesDir);e(t)&&i.push(t)}if(n.layoutsDir){let t=o(r,n.layoutsDir);e(t)&&i.push(t)}if(n.modules){let a=o(r,n.modules.dir);if(e(a))try{for(let n of t(a,{withFileTypes:!0}))if(n.isDirectory())for(let t of[`pages`,`layouts`,`components`]){let r=o(a,n.name,t);e(r)&&i.push(r)}}catch{}}return i}const l=[`.qwik.`];function u(e){return l.some(t=>e.includes(t))}function d(e,r,i){let a;try{a=t(e,{withFileTypes:!0})}catch{return}for(let t of a){let a=o(e,t.name);if(t.isDirectory()){d(a,r,i);continue}if(/\.(tsx?|jsx?|mdx?)$/.test(t.name))try{let e=n(a,`utf-8`),t=e.includes(`island=`)||e.includes(`island `),o=/import\s+\w+\s+from\s+['"][^'"]*\.qwik\.[^'"]*['"]/m.test(e);if(!t&&!o)continue;f(e,a,r,i)}catch{}}}function f(e,t,n,r){let i=/<([A-Z]\w*)\s+[^>]*\bisland\b/g,o=new Set,s=null;for(s=i.exec(e);s!==null;s=i.exec(e))o.add(s[1]);let c=/import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g,l=new Set,d=[];for(s=c.exec(e);s!==null;s=c.exec(e))d.push([s[1],s[2]]),u(s[2])&&RegExp(`<${s[1]}[\\s/>]`).test(e)&&l.add(s[1]);if(!(o.size===0&&l.size===0))for(let[e,i]of d){if(!o.has(e)&&!l.has(e))continue;let s=p(i,t,n);if(!s)continue;let c=a(n,s).replaceAll(`\\`,`/`).replace(/\.(tsx?|jsx?)$/,``);r.has(s)||r.set(s,{filePath:s,bundleKey:c})}}function p(t,n,a,s=[]){let c;for(let n of s){let i=n.find;if(typeof i==`string`){if(t===i||t.startsWith(`${i}/`)){let s=t.slice(i.length);if(c=o(a,n.replacement+s),e(c)&&r(c).isFile())return c;for(let t of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(e(c+t))return c+t}}else if(i instanceof RegExp&&i.test(t)){if(c=o(a,t.replace(i,n.replacement)),e(c)&&r(c).isFile())return c;for(let t of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(e(c+t))return c+t}}if(t.startsWith(`@shared/`))c=o(a,`app/shared`,t.slice(8));else if(t.startsWith(`@modules/`))c=o(a,`app/modules`,t.slice(9));else if(t.startsWith(`@/`))c=o(a,`app`,t.slice(2));else if(t.startsWith(`.`))c=o(i(n),t);else return null;if(e(c)&&r(c).isFile())return c;for(let t of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(e(c+t))return c+t;return null}
4
+ `)},async buildStart(){if(l)return;let t=this.environment;if(!(t&&t.name!==`client`)&&i.size>0){for(let[,e]of i)this.emitFile({type:`chunk`,id:s+e.filePath,fileName:`islands/${e.bundleKey}.js`,preserveSignature:`exports-only`});e.verbose&&console.log(`🏝️ Emitting ${i.size} island client bundles`)}},async closeBundle(){if(l||!a||i.size===0||globalThis.__avalonIslandsRebuilt)return;globalThis.__avalonIslandsRebuilt=!0;let{buildIsolatedIslands:e}=await import(`../post-build/isolated-island-builder.js`),t=new Map;for(let[e,n]of i){let r=n.filePath.includes(`.solid.`)?`solid`:n.filePath.includes(`.preact.`)?`preact`:n.filePath.includes(`.react.`)?`react`:n.filePath.includes(`.vue.`)||n.filePath.endsWith(`.vue`)?`vue`:n.filePath.includes(`.svelte.`)||n.filePath.endsWith(`.svelte`)?`svelte`:n.filePath.includes(`.lit.`)?`lit`:n.filePath.includes(`.qwik.`)?`qwik`:`preact`;t.set(e,{...n,framework:r})}await e(r,p,t,u,f,n?{treeshake:n}:void 0)}}}function c(n,r){let i=[];if(n.pagesDir){let t=o(r,n.pagesDir);e(t)&&i.push(t)}if(n.layoutsDir){let t=o(r,n.layoutsDir);e(t)&&i.push(t)}if(n.modules){let a=o(r,n.modules.dir);if(e(a))try{for(let n of t(a,{withFileTypes:!0}))if(n.isDirectory())for(let t of[`pages`,`layouts`,`components`]){let r=o(a,n.name,t);e(r)&&i.push(r)}}catch{}}return i}const l=[`.qwik.`];function u(e){return l.some(t=>e.includes(t))}function d(e,r,i){let a;try{a=t(e,{withFileTypes:!0})}catch{return}for(let t of a){let a=o(e,t.name);if(t.isDirectory()){d(a,r,i);continue}if(/\.(tsx?|jsx?|mdx?)$/.test(t.name))try{let e=n(a,`utf-8`),t=e.includes(`island=`)||e.includes(`island `),o=/import\s+\w+\s+from\s+['"][^'"]*\.qwik\.[^'"]*['"]/m.test(e);if(!t&&!o)continue;f(e,a,r,i)}catch{}}}function f(e,t,n,r){let i=/<([A-Z]\w*)\s[^>]*\bisland\s*[={]/g,o=/<([A-Z]\w*)\s[\s\S]{0,2000}?\bisland\s*[={]/g,s=new Set,c=null;for(c=i.exec(e);c!==null;c=i.exec(e))s.add(c[1]);for(c=o.exec(e);c!==null;c=o.exec(e))s.add(c[1]);let l=/import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g,d=new Set,f=[];for(c=l.exec(e);c!==null;c=l.exec(e))f.push([c[1],c[2]]),u(c[2])&&RegExp(`<${c[1]}[\\s/>]`).test(e)&&d.add(c[1]);if(!(s.size===0&&d.size===0))for(let[e,i]of f){if(!s.has(e)&&!d.has(e))continue;let o=p(i,t,n);if(!o)continue;let c=a(n,o).replaceAll(`\\`,`/`).replace(/\.(tsx?|jsx?)$/,``);r.has(o)||r.set(o,{filePath:o,bundleKey:c})}}function p(t,n,a,s=[]){let c;for(let n of s){let i=n.find;if(typeof i==`string`){if(t===i||t.startsWith(`${i}/`)){let s=t.slice(i.length);if(c=o(a,n.replacement+s),e(c)&&r(c).isFile())return c;for(let t of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(e(c+t))return c+t}}else if(i instanceof RegExp&&i.test(t)){if(c=o(a,t.replace(i,n.replacement)),e(c)&&r(c).isFile())return c;for(let t of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(e(c+t))return c+t}}if(t.startsWith(`@shared/`))c=o(a,`app/shared`,t.slice(8));else if(t.startsWith(`@modules/`))c=o(a,`app/modules`,t.slice(9));else if(t.startsWith(`@/`))c=o(a,`app`,t.slice(2));else if(t.startsWith(`.`))c=o(i(n),t);else return null;if(e(c)&&r(c).isFile())return c;for(let t of[`.tsx`,`.ts`,`.jsx`,`.js`,`.vue`,`.svelte`])if(e(c+t))return c+t;return null}
@@ -1 +1 @@
1
- import{createCipheriv as e,createDecipheriv as t,randomBytes as n}from"node:crypto";const r=`aes-256-gcm`;let i,a=!1;export function generateKey(){return n(32).toString(`base64`)}export function getKey(){let e=process.env.AVALON_KEY;if(e){let t=Buffer.from(e,`base64`);if(t.length!==32)throw Error(`AVALON_KEY must be a base64-encoded 256-bit (32-byte) key. Got ${t.length} bytes.`);return e}if(process.env.NODE_ENV===`production`)throw Error("AVALON_KEY is required in production for server islands. Generate one with `npx avalon key` and set it as an environment variable so all server instances share the same encryption secret.");return a||(a=!0,console.warn(`[avalon] AVALON_KEY not set — using a per-process key for server islands. This only works for single-process development. Set AVALON_KEY for production.`)),i||=generateKey(),i}function s(e){return e.replaceAll(`+`,`-`).replaceAll(`/`,`_`).replace(/=+$/,``)}function c(e){let t=e.replaceAll(`-`,`+`).replaceAll(`_`,`/`),n=t.length%4;return n===2?t+=`==`:n===3&&(t+=`=`),t}export function encrypt(t,i){let a=Buffer.from(i??getKey(),`base64`);if(a.length!==32)throw Error(`Encryption key must be 32 bytes. Got ${a.length} bytes.`);let o=n(12),c=e(r,a,o),l=Buffer.concat([c.update(t,`utf8`),c.final()]),u=c.getAuthTag();return s(Buffer.concat([o,l,u]).toString(`base64`))}export function decrypt(e,n){let i=Buffer.from(n??getKey(),`base64`);if(i.length!==32)throw Error(`Encryption key must be 32 bytes. Got ${i.length} bytes.`);let a=Buffer.from(c(e),`base64`);if(a.length<28)throw Error(`Invalid encrypted data: too short`);let o=a.subarray(0,12),s=a.subarray(a.length-16),l=a.subarray(12,a.length-16),u=t(r,i,o);return u.setAuthTag(s),Buffer.concat([u.update(l),u.final()]).toString(`utf8`)}
1
+ import{createCipheriv as e,createDecipheriv as t,randomBytes as n}from"node:crypto";let r=``;try{r=(await import(`virtual:server-island-key`)).serverIslandKey??``}catch{}const i=`aes-256-gcm`;let a,o=!1;export function generateKey(){return n(32).toString(`base64`)}export function getKey(){let e=globalThis.process?.env??{},t=e.AVALON_KEY;if(t){let e=Buffer.from(t,`base64`);if(e.length!==32)throw Error(`AVALON_KEY must be a base64-encoded 256-bit (32-byte) key. Got ${e.length} bytes.`);return t}if(r&&Buffer.from(r,`base64`).length===32)return r;if((e.NODE_ENV??globalThis.process?.env?.NODE_ENV)===`production`)throw Error("AVALON_KEY is required in production for server islands. Generate one with `npx avalon key` and set it as an environment variable so all server instances share the same encryption secret.");return o||(o=!0,console.warn(`[avalon] AVALON_KEY not set — using a per-process key for server islands. This only works for single-process development. Set AVALON_KEY for production.`)),a||=generateKey(),a}function c(e){return e.replaceAll(`+`,`-`).replaceAll(`/`,`_`).replace(/=+$/,``)}function l(e){let t=e.replaceAll(`-`,`+`).replaceAll(`_`,`/`),n=t.length%4;return n===2?t+=`==`:n===3&&(t+=`=`),t}export function encrypt(t,r){let a=Buffer.from(r??getKey(),`base64`);if(a.length!==32)throw Error(`Encryption key must be 32 bytes. Got ${a.length} bytes.`);let o=n(12),s=e(i,a,o),l=Buffer.concat([s.update(t,`utf8`),s.final()]),u=s.getAuthTag();return c(Buffer.concat([o,l,u]).toString(`base64`))}export function decrypt(e,n){let r=Buffer.from(n??getKey(),`base64`);if(r.length!==32)throw Error(`Encryption key must be 32 bytes. Got ${r.length} bytes.`);let a=Buffer.from(l(e),`base64`);if(a.length<28)throw Error(`Invalid encrypted data: too short`);let o=a.subarray(0,12),s=a.subarray(a.length-16),c=a.subarray(12,a.length-16),u=t(i,r,o);return u.setAuthTag(s),Buffer.concat([u.update(c),u.final()]).toString(`utf8`)}
@@ -1,4 +1,4 @@
1
- import{serverIslandLoaders as e}from"virtual:server-island-manifest";import{h as t}from"preact";import n from"preact-render-to-string";import{loadIntegration as r}from"../islands/integration-loader.js";import{decrypt as i}from"./encryption.js";import{lookupComponent as a}from"./manifest.js";const o=e??{};function s(){return o}export function defineServerIslandHandler(e={}){let{isDev:o=process.env.NODE_ENV!==`production`,defaultCacheControl:c=`private, no-store`}=e;return async e=>{let u=l(e);if(!u)return new Response(`Missing component ID`,{status:400,headers:{"Content-Type":`text/plain`}});let d;try{d=await f(e)}catch{return new Response(`Failed to read request body`,{status:400,headers:{"Content-Type":`text/plain`}})}if(!d)return new Response(`Missing encrypted props`,{status:400,headers:{"Content-Type":`text/plain`}});let p,m,h;try{let e;if(d.startsWith(`dev.`)){let t=d.slice(4);e=Buffer.from(t,`base64url`).toString(`utf8`)}else e=i(d);let t=JSON.parse(e);t.__island&&(m=t.__island,delete t.__island),t.__src&&(h=t.__src,delete t.__src),p=t}catch{return new Response(`Bad Request: decryption failed`,{status:400,headers:{"Content-Type":`text/plain`}})}let g=a(u)??h;if(!g)return new Response(`Component not found`,{status:404,headers:{"Content-Type":`text/plain`}});let _;try{let e=s()[u];if(e?_=await e():(o&&console.log(`[server-islands] Loading component from:`,g),_=await import(g)),!_.default)throw TypeError(`Module "${g}" does not have a default export`)}catch(e){if(m&&o)console.warn(`[server-islands] Component import failed (will render client-side):`,g,e instanceof Error?e.message:e),_={default:null};else{let t=o&&e instanceof Error?e.message:`Component import failed`;return new Response(t,{status:500,headers:{"Content-Type":`text/plain`}})}}let v,y=!1,b,x=m?.framework??`preact`;if(_.default)try{if(x===`preact`||x===`react`){let e=_.default;v=n(t(e,p))}else{let e=await(await r(x)).render({component:_.default,props:p,src:g,condition:m?.condition??`on:client`,ssrOnly:!1,viteServer:void 0,isDev:o});v=e.html;let t=e.hydrationData;t?.renderId&&(b=t.renderId),e.css&&(v=`${v}<style>${e.css}</style>`)}}catch(e){if(m&&o)v=``,y=!0;else{let t=o&&e instanceof Error?`${e.message}\n${e.stack}`:``;return console.error(`[server-islands] Render error for`,g,e),new Response(t||`Internal Server Error`,{status:500,headers:{"Content-Type":`text/plain`}})}}else v=``,y=!0;if(m){let e=m.elementId??`si-${u}`,t=m.componentSrc??g,n;try{n=JSON.stringify(p)}catch(t){let n=t instanceof Error?t.message:String(t);throw Error(`Failed to serialize props for server island (componentId=${u}, module=${g}, elementId=${e}): ${n}`)}let r=y?`on:client`:m.condition??`on:client`;if(o){let i=new URL(`../client/server-island-hydrate.ts`,import.meta.url).pathname,a=m.framework??`preact`,o=b?JSON.stringify(b):`undefined`,s=`<script type="module">
1
+ import{serverIslandCSS as e,serverIslandLoaders as t}from"virtual:server-island-manifest";import{h as n}from"preact";import r from"preact-render-to-string";import{loadIntegration as i}from"../islands/integration-loader.js";import{generatePerIslandScript as a}from"../islands/per-island-script.js";import{decrypt as o}from"./encryption.js";import{lookupComponent as s}from"./manifest.js";const c=t??{};function l(){return c}export function defineServerIslandHandler(t={}){let{isDev:c=process.env.NODE_ENV!==`production`,defaultCacheControl:u=`private, no-store`}=t;return async t=>{let f=d(t);if(!f)return new Response(`Missing component ID`,{status:400,headers:{"Content-Type":`text/plain`}});let p;try{p=await m(t)}catch{return new Response(`Failed to read request body`,{status:400,headers:{"Content-Type":`text/plain`}})}if(!p)return new Response(`Missing encrypted props`,{status:400,headers:{"Content-Type":`text/plain`}});let h,g,_;try{let e;if(p.startsWith(`dev.`)){let t=p.slice(4);e=Buffer.from(t,`base64url`).toString(`utf8`)}else e=o(p);let t=JSON.parse(e);t.__island&&(g=t.__island,delete t.__island),t.__src&&(_=t.__src,delete t.__src),h=t}catch{return new Response(`Bad Request: decryption failed`,{status:400,headers:{"Content-Type":`text/plain`}})}let v=s(f)??_;if(!v)return new Response(`Component not found`,{status:404,headers:{"Content-Type":`text/plain`}});let y;try{let e=l()[f];if(e?y=await e():(c&&console.log(`[server-islands] Loading component from:`,v),y=await import(v)),!y.default)throw TypeError(`Module "${v}" does not have a default export`)}catch(e){if(g&&c)console.warn(`[server-islands] Component import failed (will render client-side):`,v,e instanceof Error?e.message:e),y={default:null};else{let t=c&&e instanceof Error?e.message:`Component import failed`;return new Response(t,{status:500,headers:{"Content-Type":`text/plain`}})}}let b,x=!1,S,C=g?.framework??`preact`;if(y.default)try{if(C===`preact`||C===`react`){let e=y.default;b=r(n(e,h))}else{let t=await(await i(C)).render({component:y.default,props:h,src:v,condition:g?.condition??`on:client`,ssrOnly:!1,viteServer:void 0,isDev:c});b=t.html;let n=t.hydrationData;n?.renderId&&(S=n.renderId),t.css?b=`${b}<style>${t.css}</style>`:e[f]&&(b=`${b}<style>${e[f]}</style>`)}}catch(e){if(g&&c)b=``,x=!0;else{let t=c&&e instanceof Error?`${e.message}\n${e.stack}`:``;return console.error(`[server-islands] Render error for`,v,e),new Response(t||`Internal Server Error`,{status:500,headers:{"Content-Type":`text/plain`}})}}else b=``,x=!0;if(g){let e=g.elementId??`si-${f}`,t=g.componentSrc??v,n;try{n=JSON.stringify(h)}catch(t){let n=t instanceof Error?t.message:String(t);throw Error(`Failed to serialize props for server island (componentId=${f}, module=${v}, elementId=${e}): ${n}`)}let r=x?`on:client`:g.condition??`on:client`;if(c){let i=new URL(`../client/server-island-hydrate.ts`,import.meta.url).pathname,a=g.framework??`preact`,o=S?JSON.stringify(S):`undefined`,s=`<script type="module">
2
2
  import{hydrateServerIsland}from"/@fs${i}";
3
3
  hydrateServerIsland(${JSON.stringify(e)},${JSON.stringify(t)},${n},${JSON.stringify(r)},${JSON.stringify(a)},${o});
4
- <\/script>`;v+=s}else{let{generatePerIslandScript:r}=await import(`../islands/per-island-script.ts`),i=r({islandId:e,componentSrc:t,framework:m.framework,condition:m.condition,conditionArg:m.conditionArg,propsJson:n});v+=i}}return new Response(v,{status:200,headers:{"Content-Type":`text/html`,"Cache-Control":c}})}}function l(e){let t=e.context?.params;if(t?.componentId)return t.componentId;let n=u(e);return/\/_server-islands\/([^/?]+)/.exec(n)?.[1]}function u(e){if(e.url)return e.url.pathname;let t=e.req?.url;return t?new URL(t,`http://localhost`).pathname:`/`}function d(e){return e.req?.method??`GET`}async function f(e){let t=d(e).toUpperCase();if(t===`GET`)return(e.url?e.url.searchParams:new URLSearchParams(``)).get(`p`)||void 0;if(t===`POST`){let t=e.web?.request;if(t)return await t.text();if(e.node?.req)return await p(e.node.req);if(e._body!==void 0)return String(e._body)}}function p(e){return new Promise((t,n)=>{let r=[];e.on(`data`,e=>r.push(e)),e.on(`end`,()=>t(Buffer.concat(r).toString(`utf8`))),e.on(`error`,n)})}
4
+ <\/script>`;b+=s}else{let r=a({islandId:e,componentSrc:t,framework:g.framework,condition:g.condition,conditionArg:g.conditionArg,propsJson:n});b+=r}}return new Response(b,{status:200,headers:{"Content-Type":`text/html`,"Cache-Control":u}})}}function d(e){let t=e.context?.params;if(t?.componentId)return t.componentId;let n=f(e);return/\/_server-islands\/([^/?]+)/.exec(n)?.[1]}function f(e){if(e.url)return e.url.pathname;let t=e.req?.url;return t?new URL(t,`http://localhost`).pathname:`/`}function p(e){return e.req?.method??`GET`}async function m(e){let t=p(e).toUpperCase();if(t===`GET`)return(e.url?e.url.searchParams:new URLSearchParams(``)).get(`p`)||void 0;if(t===`POST`){let t=e.web?.request;if(t)return await t.text();if(e.node?.req)return await h(e.node.req);if(e._body!==void 0)return String(e._body)}}function h(e){return new Promise((t,n)=>{let r=[];e.on(`data`,e=>r.push(e)),e.on(`end`,()=>t(Buffer.concat(r).toString(`utf8`))),e.on(`error`,n)})}
@@ -1,4 +1,4 @@
1
- import e from"preact-render-to-string";import{encrypt as t}from"./encryption.js";const n=process.env.NODE_ENV!==`production`;function r(e){return n?`dev.${Buffer.from(e,`utf8`).toString(`base64url`)}`:t(e)}let i=0;function a(e,t){try{return JSON.stringify(e)}catch(e){let n=e instanceof Error?e.message:String(e);throw Error(`Failed to serialize server island props (elementId=${t.elementId}, componentSrc=${t.componentSrc??`unknown`}, combinedIsland=${t.hasIsland}). Props must be JSON-serializable (no functions, circular refs, or BigInt): ${n}`)}}export function renderServerIsland(t,n,o,l,u,d,f){let p=`si-${t}-${i++}`,m={...n};d&&(m.__src=d),l&&(m.__island={condition:l.condition??`on:client`,conditionArg:l.conditionArg,framework:f??`preact`,componentSrc:u,elementId:p});let h=r(a(m,{componentSrc:u,elementId:p,hasIsland:!!l})),g=o.fallback?e(o.fallback):``,_=o.timeout??1e4,v=s({elementId:p,endpointPath:`/_server-islands/${t}`,timeout:_,islandProp:l});return`${`<avalon-server-island id="${p}" data-p="${c(h)}">`}${g}</avalon-server-island>\n${v}`}function s(e){let{elementId:t,endpointPath:n,timeout:r,islandProp:i}=e,a=i?`el.querySelectorAll('script[type="module"]').forEach(s=>{const n=document.createElement("script");n.type="module";n.textContent=s.textContent;s.replaceWith(n);});`:``;return`<script type="module">
1
+ import e from"preact-render-to-string";import{encrypt as t}from"./encryption.js";const n=(globalThis.process?.env??{}).NODE_ENV!==`production`;function r(e){return n?`dev.${Buffer.from(e,`utf8`).toString(`base64url`)}`:t(e)}let i=0;function a(e,t){try{return JSON.stringify(e)}catch(e){let n=e instanceof Error?e.message:String(e);throw Error(`Failed to serialize server island props (elementId=${t.elementId}, componentSrc=${t.componentSrc??`unknown`}, combinedIsland=${t.hasIsland}). Props must be JSON-serializable (no functions, circular refs, or BigInt): ${n}`)}}export function renderServerIsland(t,n,o,l,u,d,f){let p=`si-${t}-${i++}`,m={...n};d&&(m.__src=d),l&&(m.__island={condition:l.condition??`on:client`,conditionArg:l.conditionArg,framework:f??`preact`,componentSrc:u,elementId:p});let h=r(a(m,{componentSrc:u,elementId:p,hasIsland:!!l})),g=o.fallback?e(o.fallback):``,_=o.timeout??1e4,v=s({elementId:p,endpointPath:`/_server-islands/${t}`,timeout:_,islandProp:l});return`${`<avalon-server-island id="${p}" data-p="${c(h)}">`}${g}</avalon-server-island>\n${v}`}function s(e){let{elementId:t,endpointPath:n,timeout:r,islandProp:i}=e,a=i?`el.querySelectorAll('script[type="module"]').forEach(s=>{const n=document.createElement("script");n.type="module";n.textContent=s.textContent;s.replaceWith(n);});`:``;return`<script type="module">
2
2
  (async()=>{
3
3
  const el=document.getElementById("${t}");
4
4
  if(!el)return;
@@ -11,5 +11,6 @@
11
11
  *
12
12
  * @module server-islands/route
13
13
  */
14
+ import "virtual:server-island-integrations";
14
15
  declare const handler: (event: import("h3").H3Event) => Promise<Response>;
15
16
  export default handler;
@@ -1 +1 @@
1
- import{defineServerIslandHandler as e}from"./endpoint.js";const t=e();export default t;
1
+ import"virtual:server-island-integrations";import{defineServerIslandHandler as e}from"./endpoint.js";const t=e();export default t;
@@ -66,9 +66,16 @@ declare module "virtual:server-island-manifest" {
66
66
  export const serverIslandManifest: Record<string, string>;
67
67
  /** Lazy loaders that dynamically import each server island component, preventing tree-shaking */
68
68
  export const serverIslandLoaders: Record<string, () => Promise<{ default: unknown }>>;
69
+ /** Pre-extracted CSS for Svelte components (componentId → raw CSS string) */
70
+ export const serverIslandCSS: Record<string, string>;
69
71
  }
70
72
 
71
73
  declare module "virtual:server-island-key" {
72
74
  /** The AES-256-GCM encryption key (base64-encoded) embedded at build time */
73
75
  export const serverIslandKey: string;
74
76
  }
77
+
78
+ declare module "virtual:server-island-integrations" {
79
+ // Side-effect module that registers framework integrations in the global registry.
80
+ // No exports — import for side effects only.
81
+ }
@@ -1,6 +1,17 @@
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{getUniversalCSSForHead as f}from"../islands/universal-css-collector.js";import{getUniversalHeadForInjection as p,injectSolidHydrationScriptIfNeeded as m}from"../islands/universal-head-collector.js";import{clearMiddlewareCache as h,discoverScopedMiddleware as g,executeScopedMiddleware as _}from"../middleware/index.js";import{createNitroConfig as v}from"../nitro/config.js";import{createIslandManifestPlugin as y,createNitroBuildPlugin as b,createSourceMapConfig as x,createSourceMapPlugin as S}from"../nitro/index.js";import{collectCssFromModuleGraph as C,injectSsrCss as w}from"../render/collect-css.js";import{generateErrorPage as T,generateFallback404 as E}from"../render/error-pages.js";import{generateComponentId as D}from"../server-islands/manifest.js";import{resolveToRelativePath as O}from"./server-islands-plugin.js";function k(e){let t=P(e),n=Object.entries(t),r=`export const serverIslandManifest = ${JSON.stringify(t)};\n\n`;r+=`export const serverIslandLoaders = {
2
- `;for(let[e,t]of n)r+=` ${JSON.stringify(e)}: () => import(${JSON.stringify(t)}),\n`;return r+=`};
3
- `,r}const A=/^[ \t]*import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/gm,j=new Set([`node_modules`,`dist`,`.output`,`.netlify`,`.vercel`,`.cloudflare`,`.wrangler`,`.firebase`,`.amplify-hosting`,`.git`]);function M(e,t){return new RegExp(String.raw`<${t}\s[\s\S]*?\bserver\s*[={/>]`).test(e)}function N(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(j.has(t.name))continue;N(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 P(t){let r={},i=[];for(let n of[`app`,`src`]){let r=s(t,n);e(r)&&N(r,i)}for(let e of i){let i;try{i=n(e,`utf8`)}catch{continue}if(!/\bserver\s*[={/>]/.test(i))continue;A.lastIndex=0;let a=A.exec(i);for(;a!==null;a=A.exec(i)){let n=a[1],o=a[2].slice(1,-1);if(!M(i,n))continue;let s=O(o,e,t),c=D(s);c in r||(r[c]=s)}}return r}function F(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 ee(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`};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=v(t,e),r=process.cwd(),i=F(`src/server-islands/route.ts`),a={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}],virtual:{"virtual:server-island-manifest":()=>k(r)}};t.renderer===!1?a.renderer=!1:n.renderer&&(a.renderer=n.renderer),n.publicRuntimeConfig&&(a.publicRuntimeConfig=n.publicRuntimeConfig),n.publicAssets&&(a.publicAssets=n.publicAssets),n.compressPublicAssets&&(a.compressPublicAssets=n.compressPublicAssets),n.serverEntry&&(a.serverEntry=n.serverEntry);let o=n.traceDeps??[];a.traceDeps=[...new Set([`undici`,...o])],n.prerender&&(a.prerender={routes:[],crawlLinks:!1});let s=u(a),c=createNitroCoordinationPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),l=createVirtualModulesPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),d=b(e,t),f=y(e,{verbose:e.verbose,generatePreloadHints:!0}),p=S(x(t.preset??`node_server`,e.isDev));return{nitroOptions:n,plugins:[...Array.isArray(s)?s:[s],c,l,d,f,p]}}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`},configureServer(e){globalThis.__viteDevServer=e;let i=e.config.root||process.cwd(),a=e.config.build?.outDir?s(i,e.config.build.outDir):s(i,`dist`);try{r(a,{recursive:!0,force:!0})}catch{}try{r(s(i,`.output`),{recursive:!0,force:!0})}catch{}let o=!1,c=new Promise(t=>{let n=()=>{(e.environments?.nitro)?.devServer?.entry||o?(o=!0,t()):setTimeout(n,50)};setTimeout(n,100),setTimeout(()=>{o=!0,t()},15e3)});e.middlewares.use(async(e,t,n)=>{if(o)return n();let r=e.url||`/`;if(r.startsWith(`/@`)||r.startsWith(`/__`)||/\/[^/]+\.[a-z0-9]+(\?|$)/i.test(r))return n();await c,n()});let l=null;async function u(){return l||=await g({baseDir:`${e.config.root||process.cwd()}/src`,devMode:!1}),l}function f(){l=null}R(e,t,n,f),u().catch(e=>{console.warn(`[middleware] Failed to discover middleware:`,e)});let p=e.environments?.ssr,m=!!p&&d(p);m&&L(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/`)||!m)return r();try{let{decrypt:r}=await e.ssrLoadModule(F(`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">
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{getUniversalCSSForHead as f}from"../islands/universal-css-collector.js";import{getUniversalHeadForInjection as p,injectSolidHydrationScriptIfNeeded as m}from"../islands/universal-head-collector.js";import{clearMiddlewareCache as h,discoverScopedMiddleware as g,executeScopedMiddleware as _}from"../middleware/index.js";import{createNitroConfig as v}from"../nitro/config.js";import{createIslandManifestPlugin as y,createNitroBuildPlugin as b,createSourceMapConfig as x,createSourceMapPlugin as S}from"../nitro/index.js";import{collectCssFromModuleGraph as C,injectSsrCss as w}from"../render/collect-css.js";import{generateErrorPage as T,generateFallback404 as E}from"../render/error-pages.js";import{generateComponentId as D}from"../server-islands/manifest.js";import{resolveToRelativePath as O}from"./server-islands-plugin.js";function k(e){let t=P(e),r=Object.entries(t),i=`export const serverIslandManifest = ${JSON.stringify(t)};\n\n`;i+=`export const serverIslandLoaders = {
2
+ `;for(let[e,t]of r)i+=` ${JSON.stringify(e)}: () => import(${JSON.stringify(t)}),\n`;i+=`};
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 A=/^[ \t]*import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/gm,j=new Set([`node_modules`,`dist`,`.output`,`.netlify`,`.vercel`,`.cloudflare`,`.wrangler`,`.firebase`,`.amplify-hosting`,`.git`]);function M(e,t){return new RegExp(String.raw`<${t}\s[\s\S]*?\bserver\s*[={/>]`).test(e)}function N(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(j.has(t.name))continue;N(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 P(t){let r={},i=[];for(let n of[`app`,`src`]){let r=s(t,n);e(r)&&N(r,i)}for(let e of i){let i;try{i=n(e,`utf8`)}catch{continue}if(!/\bserver\s*[={/>]/.test(i))continue;A.lastIndex=0;let a=A.exec(i);for(;a!==null;a=A.exec(i)){let n=a[1],o=a[2].slice(1,-1);if(!M(i,n))continue;let s=O(o,e,t),c=D(s);c in r||(r[c]=s)}}return r}function F(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 ee(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`};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=v(t,e),r=process.cwd(),i=F(`src/server-islands/route.ts`),a={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}],virtual:{"virtual:server-island-manifest":()=>k(r),"virtual:server-island-key":()=>{let e=process.env.AVALON_KEY??``;return`export const serverIslandKey = ${JSON.stringify(e)};\n`},"virtual:server-island-integrations":()=>`
5
+ import { registry } from "${F(`src/core/integrations/registry.ts`)}";
6
+ import { solidIntegration } from "@useavalon/solid";
7
+ import { vueIntegration } from "@useavalon/vue";
8
+ import { svelteIntegration } from "@useavalon/svelte";
9
+ import { litIntegration } from "@useavalon/lit";
10
+ if (solidIntegration) registry.register(solidIntegration);
11
+ if (vueIntegration) registry.register(vueIntegration);
12
+ if (svelteIntegration) registry.register(svelteIntegration);
13
+ if (litIntegration) registry.register(litIntegration);
14
+ `}};t.renderer===!1?a.renderer=!1:n.renderer&&(a.renderer=n.renderer),n.publicRuntimeConfig&&(a.publicRuntimeConfig=n.publicRuntimeConfig),n.publicAssets&&(a.publicAssets=n.publicAssets),n.compressPublicAssets&&(a.compressPublicAssets=n.compressPublicAssets),n.serverEntry&&(a.serverEntry=n.serverEntry);let o=n.traceDeps??[];a.traceDeps=[...new Set([`undici`,...o])],n.prerender&&(a.prerender={routes:[],crawlLinks:!1});let s=u(a),c=createNitroCoordinationPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),l=createVirtualModulesPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),d=b(e,t),f=y(e,{verbose:e.verbose,generatePreloadHints:!0}),p=S(x(t.preset??`node_server`,e.isDev));return{nitroOptions:n,plugins:[...Array.isArray(s)?s:[s],c,l,d,f,p]}}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`},configureServer(e){globalThis.__viteDevServer=e;let i=e.config.root||process.cwd(),a=e.config.build?.outDir?s(i,e.config.build.outDir):s(i,`dist`);try{r(a,{recursive:!0,force:!0})}catch{}try{r(s(i,`.output`),{recursive:!0,force:!0})}catch{}let o=!1,c=new Promise(t=>{let n=()=>{(e.environments?.nitro)?.devServer?.entry||o?(o=!0,t()):setTimeout(n,50)};setTimeout(n,100),setTimeout(()=>{o=!0,t()},15e3)});e.middlewares.use(async(e,t,n)=>{if(o)return n();let r=e.url||`/`;if(r.startsWith(`/@`)||r.startsWith(`/__`)||/\/[^/]+\.[a-z0-9]+(\?|$)/i.test(r))return n();await c,n()});let l=null;async function u(){return l||=await g({baseDir:`${e.config.root||process.cwd()}/src`,devMode:!1}),l}function f(){l=null}R(e,t,n,f),u().catch(e=>{console.warn(`[middleware] Failed to discover middleware:`,e)});let p=e.environments?.ssr,m=!!p&&d(p);m&&L(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/`)||!m)return r();try{let{decrypt:r}=await e.ssrLoadModule(F(`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">
4
15
  import{hydrateServerIsland}from"/@fs${F(`src/client/server-island-hydrate.ts`)}";
5
16
  hydrateServerIsland(${JSON.stringify(t)},${JSON.stringify(n)},${r},${JSON.stringify(a)},${JSON.stringify(o)});
6
17
  <\/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(r,i,a)=>{if(!m)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 te(e,o,r,i,u,n)||await ne(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 I(e,o,i,t)}catch(e){console.error(`[SSR Error]`,e),i.statusCode=500,i.setHeader(`Content-Type`,`text/html`),i.end(T(e))}})},buildStart(){}}}async function te(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 _({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 I(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(E(t))}}async function L(e,t,n){let r=performance.now(),i=[{path:F(`src/render/ssr.ts`),assignTo:`ssr`},{path:F(`src/core/layout/enhanced-layout-resolver.ts`),assignTo:`layout`},{path:F(`src/middleware/index.ts`),assignTo:null},...t.map(e=>({path:ee(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`&&(J=r),n===`layout`&&(Y=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:null},async load(e){return e===RESOLVED_VIRTUAL_IDS.PAGE_ROUTES?await z(n,i):e===RESOLVED_VIRTUAL_IDS.PAGE_LOADER?await B(n,i):e===RESOLVED_VIRTUAL_IDS.ISLAND_MANIFEST?V():e===RESOLVED_VIRTUAL_IDS.RUNTIME_CONFIG?H(n,r):e===RESOLVED_VIRTUAL_IDS.CONFIG?generateConfigModule(n,r):e===RESOLVED_VIRTUAL_IDS.LAYOUTS?(a||=await U(n,r,p),a):e===RESOLVED_VIRTUAL_IDS.ASSETS?W(r):e===RESOLVED_VIRTUAL_IDS.RENDERER?G(n):e===RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY?await K(n,r):e===RESOLVED_VIRTUAL_IDS.INTEGRATION_LOADER?generateIntegrationLoaderModule(n):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 R(e,t,n,r){e.watcher.on(`change`,e=>{e.includes(`_middleware`)&&(h(),r?.()),(e.includes(`/render/`)||e.includes(`/layout/`)||e.includes(`/islands/`))&&(J=null,Y=null),(e.includes(`/layouts/`)||e.includes(`_layout`))&&globalThis.__avalonLayoutResolver?.clearCache?.()}),e.watcher.on(`add`,e=>{e.includes(`_middleware`)&&(h(),r?.())}),e.watcher.on(`unlink`,e=>{e.includes(`_middleware`)&&(h(),r?.())})}async function z(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 = [];
@@ -1,3 +1,3 @@
1
- import{dirname as e,relative as t,resolve as n}from"node:path";import{generateKey as r,getKey as i}from"../server-islands/encryption.js";import{addToManifest as a,clearManifest as o,generateComponentId as s,getManifest as c}from"../server-islands/manifest.js";const l=`virtual:server-island-manifest`,u=`\0`+l,d=`virtual:server-island-key`,f=`\0`+d,p=/<([A-Z][a-zA-Z0-9_$]*)\s[\s\S]*?\bserver\s*[={/>]/;function m(e){let t=[],n=/^[ \t]*import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/gm,r=null;for(r=n.exec(e);r!==null;r=n.exec(e))t.push({localName:r[1],importPath:r[2].slice(1,-1)});return t}function h(e,t){return new RegExp(String.raw`<${t}\s[\s\S]*?\bserver\s*[={/>]`).test(e)}export function resolveToRelativePath(r,i,a){return r.startsWith(`/src/`)||r.startsWith(`/app/`)?r:r.startsWith(`@/`)?`/app/${r.slice(2)}`:r.startsWith(`@shared/`)?`/app/shared/${r.slice(8)}`:r.startsWith(`@modules/`)?`/app/modules/${r.slice(9)}`:r.startsWith(`~/`)?`/src/${r.slice(2)}`:r.startsWith(`$components/`)?`/src/components/${r.slice(12)}`:r.startsWith(`$islands/`)?`/src/islands/${r.slice(9)}`:r.startsWith(`.`)?`/`+t(a,n(e(i),r)).replaceAll(`\\`,`/`):r}export function serverIslandsPlugin(e={}){let t,n,g=!!process.env.AVALON_KEY;return{name:`avalon:server-islands`,enforce:`pre`,config(){process.env.AVALON_KEY||(process.env.AVALON_KEY=r())},configResolved(e){t=e.root},buildStart(){o(),n=i(),e.verbose&&console.log(`[avalon:server-islands] Encryption key source: ${g?`AVALON_KEY env var`:`generated per-build`}`)},resolveId(e){return e===l?u:e===d?f:null},load(e){if(e===u){let e=c(),t=Object.entries(e),n=`export const serverIslandManifest = ${JSON.stringify(e)};\n\n`;n+=`export const serverIslandLoaders = {
1
+ import{dirname as e,relative as t,resolve as n}from"node:path";import{generateKey as r,getKey as i}from"../server-islands/encryption.js";import{addToManifest as a,clearManifest as o,generateComponentId as s,getManifest as c}from"../server-islands/manifest.js";const l=`virtual:server-island-manifest`,u=`\0`+l,d=`virtual:server-island-key`,f=`\0`+d,p=/<([A-Z][a-zA-Z0-9_$]*)\s[\s\S]*?\bserver\s*[={/>]/;function m(e){let t=[],n=/^[ \t]*import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/gm,r=null;for(r=n.exec(e);r!==null;r=n.exec(e))t.push({localName:r[1],importPath:r[2].slice(1,-1)});return t}function h(e,t){return new RegExp(String.raw`<${t}\s[\s\S]*?\bserver\s*[={/>]`).test(e)}export function resolveToRelativePath(r,i,a){return r.startsWith(`/src/`)||r.startsWith(`/app/`)?r:r.startsWith(`@/`)?`/app/${r.slice(2)}`:r.startsWith(`@shared/`)?`/app/shared/${r.slice(8)}`:r.startsWith(`@modules/`)?`/app/modules/${r.slice(9)}`:r.startsWith(`~/`)?`/src/${r.slice(2)}`:r.startsWith(`$components/`)?`/src/components/${r.slice(12)}`:r.startsWith(`$islands/`)?`/src/islands/${r.slice(9)}`:r.startsWith(`.`)?`/`+t(a,n(e(i),r)).replaceAll(`\\`,`/`):r}export function serverIslandsPlugin(e={}){let t,n,g=!!process.env.AVALON_KEY;return{name:`avalon:server-islands`,enforce:`pre`,config(){process.env.AVALON_KEY||(process.env.AVALON_KEY=r())},configResolved(e){t=e.root},buildStart(){o(),n=i(),e.verbose&&console.log(`[avalon:server-islands] Encryption key source: ${g?`AVALON_KEY env var`:`generated per-build`}`)},resolveId(e){return e===l?u:e===d?f:e===`virtual:server-island-integrations`?`\0virtual:server-island-integrations`:null},load(e){if(e===`\0virtual:server-island-integrations`)return`export {};`;if(e===u){let e=c(),t=Object.entries(e),n=`export const serverIslandManifest = ${JSON.stringify(e)};\n\n`;n+=`export const serverIslandLoaders = {
2
2
  `;for(let[e,r]of t)n+=` ${JSON.stringify(e)}: () => import(${JSON.stringify(r)}),\n`;return n+=`};
3
3
  `,n}return e===f?`export const serverIslandKey = ${JSON.stringify(n)};`:null},transform(n,r){if(!/\.(tsx|jsx)$/.test(r)||r.includes(`node_modules`)||!p.test(n))return null;let i=m(n);if(i.length===0)return null;for(let o of i)if(h(n,o.localName)){let n=resolveToRelativePath(o.importPath,r,t),i=s(n);a(i,n),e.verbose&&console.log(`[avalon:server-islands] Registered: ${o.localName} → ${i} (${n})`)}return null},generateBundle(){let t=c(),n=Object.keys(t).length;n>0&&e.verbose&&console.log(`[avalon:server-islands] Manifest contains ${n} server island(s)`)}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useavalon/avalon",
3
- "version": "0.1.93-canary.0",
3
+ "version": "0.1.93-canary.1",
4
4
  "description": "Multi-framework islands architecture for the modern web",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -147,7 +147,7 @@
147
147
  }
148
148
  },
149
149
  "dependencies": {
150
- "@useavalon/core": "^0.1.11-canary.0",
150
+ "@useavalon/core": "^0.1.11-canary.1",
151
151
  "@mdx-js/rollup": "^3.0.0",
152
152
  "h3": "^2.0.1-rc.16",
153
153
  "marked": "^17.0.4",