@useavalon/avalon 0.3.2-canary.14 → 0.3.2-canary.15
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/post-build/cloudflare-worker-patch.js +1 -1
- package/dist/src/server-islands/encryption.js +1 -1
- package/dist/src/server-islands/endpoint.js +3 -3
- package/dist/src/server-islands/renderer.js +1 -1
- package/dist/src/server-islands/route.d.ts +3 -1
- package/dist/src/server-islands/route.js +1 -1
- package/dist/src/types/virtual-modules.d.ts +2 -2
- package/dist/src/types/vite-env.d.ts +4 -0
- package/dist/src/vite-plugin/nitro-integration.js +1 -1
- package/dist/src/vite-plugin/server-islands-plugin.js +1 -1
- package/dist/src/vite-plugin/ssr-dom-shim-module.d.ts +20 -2
- package/dist/src/vite-plugin/ssr-dom-shim-module.js +90 -19
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as e,readdirSync as t,readFileSync as n,statSync as r,writeFileSync as i}from"node:fs";import{join as a}from"node:path";import{
|
|
1
|
+
import{existsSync as e,readdirSync as t,readFileSync as n,statSync as r,writeFileSync as i}from"node:fs";import{join as a}from"node:path";import{ssrDomStubFileSource as o}from"../vite-plugin/ssr-dom-shim-module.js";const s=/createRequire\(\s*import\.meta\.url\s*\)/g,c=`_dom_stub.mjs`;function l(n,r=[]){if(!e(n))return r;for(let e of t(n,{withFileTypes:!0})){let t=a(n,e.name);if(e.isDirectory()){l(t,r);continue}e.isFile()&&/\.(?:m?js)$/.test(e.name)&&r.push(t)}return r}export function patchCloudflareCreateRequire(e){let t=0;for(let r of l(e)){let e=n(r,`utf-8`);if(!s.test(e))continue;s.lastIndex=0;let a=e.replaceAll(s,`createRequire(import.meta.url || "file:///")`);a!==e&&(i(r,a),t+=1)}return t}export function patchCloudflareWranglerJson(t,o){let s=a(t,`wrangler.json`);if(!e(s)||!r(s).isFile())return!1;let c=JSON.parse(n(s,`utf-8`));c.compatibility_date=o.compatibilityDate;let l=new Set(c.compatibility_flags??[]);for(let e of o.compatibilityFlags)l.add(e);return c.compatibility_flags=[...l],i(s,`${JSON.stringify(c,null,2)}\n`),!0}function u(t,a){if(!e(t)||!r(t).isFile())return!1;let o=n(t,`utf-8`),s=`import "${a}";\n`;return o.startsWith(s)||o.includes(`import "${a}"`)?!1:(i(t,`${s}${o}`),!0)}export function injectCloudflareDomStub(n){i(a(n,c),`${o().trim()}\n`);let r=!1;r=u(a(n,`index.js`),`./${c}`)||r,r=u(a(n,`_ssr`,`ssr.mjs`),`../${c}`)||r;let s=a(n,`_libs`,`@lit-labs`);if(e(s))for(let e of t(s))e.startsWith(`ssr`)&&(r=u(a(s,e),`../../${c}`)||r);return r}export function patchCloudflareRoutesForStaticHtml(t){let n=a(t,`dist`,`_routes.json`);if(!e(n))return!1;let r=new Set([`/api/*`,`/_server-islands/*`,`/_actions/*`]);e(a(t,`dist`,`_worker.js`,`_routes`,`api`))&&r.add(`/api/*`);let o={version:1,include:[...r],exclude:[`/`,`/assets/*`,`/islands/*`,`/pagefind/*`,`/*.html`,`/*.svg`,`/*.ico`,`/*.txt`,`/*.xml`,`/*.css`,`/*.js`]};return i(n,`${JSON.stringify(o,null,2)}\n`),!0}export function patchCloudflareWorkerOutput(t,n={compatibilityDate:`2026-09-04`,compatibilityFlags:[`nodejs_compat`,`enable_nodejs_fs_module`]}){let i=a(t,`dist`,`_worker.js`);if(!e(i))return!1;let o=r(i).isDirectory()?i:null;if(!o)return!1;let s=patchCloudflareCreateRequire(o),c=patchCloudflareWranglerJson(o,n),l=injectCloudflareDomStub(o),u=patchCloudflareRoutesForStaticHtml(t);return s>0&&console.log(`[cloudflare] Patched createRequire(import.meta.url) in ${s} worker file(s)`),c&&console.log(`[cloudflare] Synced wrangler.json compatibility_date=${n.compatibilityDate}`),l&&console.log(`[cloudflare] Injected _dom_stub.mjs before Lit / SSR imports`),u&&console.log(`[cloudflare] Limited _routes.json include to dynamic SSR paths`),s>0||c||l||u}
|
|
@@ -1 +1 @@
|
|
|
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`)}
|
|
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`)}function c(){try{let e=globalThis.process?.env;if(e&&typeof e==`object`)return e}catch{}return{}}export function getKey(){let e=c(),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===`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 l(e){return e.replaceAll(`+`,`-`).replaceAll(`/`,`_`).replace(/=+$/,``)}function u(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),c=Buffer.concat([s.update(t,`utf8`),s.final()]),u=s.getAuthTag();return l(Buffer.concat([o,c,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(u(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),l=t(i,r,o);return l.setAuthTag(s),Buffer.concat([l.update(c),l.final()]).toString(`utf8`)}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{serverIslandCSS as
|
|
1
|
+
import{ensureServerIslandIntegrations as e}from"virtual:server-island-integrations";import{serverIslandCSS as t,serverIslandLoaders as n,serverIslandManifest as r}from"virtual:server-island-manifest";import{h as i}from"preact";import a from"preact-render-to-string";import{loadIntegration as o}from"../islands/integration-loader.js";import{escapeJsonForScript as s,generatePerIslandScript as c}from"../islands/per-island-script.js";import{decrypt as l}from"./encryption.js";import{lookupComponent as u}from"./manifest.js";const d=n??{};function f(){return d}function p(e,t){return new Response(e,{status:t,headers:{"Content-Type":`text/plain`}})}export function defineServerIslandHandler(t={}){let{isDev:n=process.env.NODE_ENV!==`production`,defaultCacheControl:i=`private, no-store`}=t;return async t=>{e();let a=x(t);if(!a)return p(`Missing component ID`,400);let o=await h(t);if(o instanceof Response)return o;let s=g(o,n);if(s instanceof Response)return s;let{props:c,islandMeta:l,srcPath:d}=s,f=u(a)??r?.[a]??(n?d:void 0);if(!f)return p(`Component not found`,404);let m=await _(a,f,n,!!l);if(m instanceof Response)return m;let y=await v({componentModule:m,props:c,islandMeta:l,componentId:a,modulePath:f,isDev:n});if(y instanceof Response)return y;let S=y.html;return l&&(S+=b({componentId:a,islandMeta:l,modulePath:f,props:c,ssrFailed:y.ssrFailed,hydrationRenderId:y.hydrationRenderId,isDev:n})),new Response(S,{status:200,headers:{"Content-Type":`text/html`,"Cache-Control":i}})}}async function h(e){let t;try{t=await w(e)}catch{return p(`Failed to read request body`,400)}return t||p(`Missing encrypted props`,400)}function g(e,t){try{let n;n=t&&e.startsWith(`dev.`)?Buffer.from(e.slice(4),`base64url`).toString(`utf8`):l(e);let r=JSON.parse(n),i={props:r};return r.__island&&(i.islandMeta=r.__island,delete r.__island),r.__src&&(i.srcPath=r.__src,delete r.__src),i}catch{return p(`Bad Request: decryption failed`,400)}}async function _(e,t,n,r){try{let r=f()[e],i;if(r?i=await r():(n&&console.log(`[server-islands] Loading component from:`,t),i=await import(t)),!i.default)throw TypeError(`Module "${t}" does not have a default export`);return i}catch(e){return r&&n?(console.warn(`[server-islands] Component import failed (will render client-side):`,t,e instanceof Error?e.message:e),{default:null}):p(n&&e instanceof Error?e.message:`Component import failed`,500)}}async function v(e){let{componentModule:t,props:n,islandMeta:r,componentId:o,modulePath:s,isDev:c}=e;if(!t.default)return{html:``,ssrFailed:!0};let l=r?.framework??`preact`;try{if(l===`preact`||l===`react`){let e=t.default;return{html:a(i(e,n)),ssrFailed:!1}}return await y({framework:l,component:t.default,props:n,islandMeta:r,componentId:o,modulePath:s,isDev:c})}catch(e){if(r&&c)return{html:``,ssrFailed:!0};let t=c&&e instanceof Error?`${e.message}\n${e.stack}`:``;return console.error(`[server-islands] Render error for`,s,e),p(t||`Internal Server Error`,500)}}async function y(e){let{framework:n,component:r,props:i,islandMeta:a,componentId:s,modulePath:c,isDev:l}=e,u=await(await o(n)).render({component:r,props:i,src:c,condition:a?.condition??`on:client`,ssrOnly:!1,viteServer:void 0,isDev:l}),d=u.html;u.css?d=`${d}<style>${u.css}</style>`:t[s]&&(d=`${d}<style>${t[s]}</style>`);let f=u.hydrationData?.renderId;return{html:d,ssrFailed:!1,hydrationRenderId:f}}function b(e){let{componentId:t,islandMeta:n,modulePath:r,props:i,ssrFailed:a,hydrationRenderId:o,isDev:l}=e,u=n.elementId??`si-${t}`,d=n.componentSrc??r,f;try{f=JSON.stringify(i)}catch(e){let n=e instanceof Error?e.message:String(e);throw Error(`Failed to serialize props for server island (componentId=${t}, module=${r}, elementId=${u}): ${n}`)}if(l){let e=a?`on:client`:n.condition??`on:client`,t=new URL(`../client/server-island-hydrate.ts`,import.meta.url).pathname,r=n.framework??`preact`,i=o?JSON.stringify(o):`undefined`;return`<script type="module">
|
|
2
2
|
import{hydrateServerIsland}from"/@fs${t}";
|
|
3
|
-
hydrateServerIsland(${JSON.stringify(u)},${JSON.stringify(d)},${
|
|
4
|
-
<\/script>`}return
|
|
3
|
+
hydrateServerIsland(${JSON.stringify(u)},${JSON.stringify(d)},${s(f)},${JSON.stringify(e)},${JSON.stringify(r)},${i});
|
|
4
|
+
<\/script>`}return c({islandId:u,componentSrc:d,framework:n.framework,condition:n.condition,conditionArg:n.conditionArg,propsJson:f})}function x(e){let t=e.context?.params;if(t?.componentId)return t.componentId;let n=S(e);return/\/_server-islands\/([^/?]+)/.exec(n)?.[1]}function S(e){if(e.url)return e.url.pathname;let t=e.req?.url;return t?new URL(t,`http://localhost`).pathname:`/`}function C(e){return e.req?.method??`GET`}async function w(e){let t=C(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 T(e.node.req);if(e._body!==void 0)return String(e._body)}}function T(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";
|
|
1
|
+
import e from"preact-render-to-string";import{encrypt as t}from"./encryption.js";function n(){try{if(import.meta.env?.DEV===!0)return!0;if(import.meta.env?.PROD===!0)return!1}catch{}return!1}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;
|
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
* - GET: encrypted props in the `p` query parameter
|
|
10
10
|
* - POST: encrypted props in the request body
|
|
11
11
|
*
|
|
12
|
+
* Framework SSR integrations are registered via the import in `endpoint.ts`
|
|
13
|
+
* (`virtual:server-island-integrations`).
|
|
14
|
+
*
|
|
12
15
|
* @module server-islands/route
|
|
13
16
|
*/
|
|
14
|
-
import "virtual:server-island-integrations";
|
|
15
17
|
declare const handler: (event: import("h3").H3Event) => Promise<Response>;
|
|
16
18
|
export default handler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import{defineServerIslandHandler as e}from"./endpoint.js";const t=e();export default t;
|
|
@@ -80,8 +80,8 @@ declare module "virtual:server-island-key" {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
declare module "virtual:server-island-integrations" {
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
/** Registers framework SSR integrations into the global registry (idempotent). */
|
|
84
|
+
export function ensureServerIslandIntegrations(): void;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
declare module "virtual:avalon-actions-manifest" {
|
|
@@ -6,7 +6,7 @@ import{existsSync as e,readdirSync as t,readFileSync as n,rmSync as r}from"node:
|
|
|
6
6
|
`)}function fe(e,t){try{let n;if(e.startsWith(`dev.`)){let t=e.slice(4);n=Buffer.from(t,`base64url`).toString(`utf8`)}else n=t(e);let r=JSON.parse(n),i,a;return r.__island&&(i=r.__island,delete r.__island),r.__src&&(a=r.__src,delete r.__src),{ok:!0,props:r,srcPath:a,islandMeta:i}}catch{return{ok:!1}}}function pe(e,t,n,r){let i=e.split(`/`)[2]?.split(`?`)[0]||``,a=t.elementId??`si-${i}`,o=t.componentSrc??n,s=JSON.stringify(r),c=t.condition??`on:client`,l=t.framework??`preact`;return`<script type="module">
|
|
7
7
|
import{hydrateServerIsland}from"/@fs${P(`src/client/server-island-hydrate.ts`)}";
|
|
8
8
|
hydrateServerIsland(${JSON.stringify(a)},${JSON.stringify(o)},${s},${JSON.stringify(c)},${JSON.stringify(l)});
|
|
9
|
-
<\/script>`}function P(t){let n=s(o(a(import.meta.url).resolve(`@useavalon/avalon`)),t);if(t.endsWith(`.ts`)&&!e(n)){let t=n.replace(/\.ts$/,`.js`);if(e(t))return t}return n}function me(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`,DEV_CSS_HMR:`virtual:avalon/dev-css-hmr`,INTEGRATION_LOADER:`virtual:avalon/integration-loader`,ACTIONS:`virtual:avalon/actions`,SSR_DOM:O};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}`,DEV_CSS_HMR:`\0${VIRTUAL_MODULE_IDS.DEV_CSS_HMR}`,INTEGRATION_LOADER:`\0${VIRTUAL_MODULE_IDS.INTEGRATION_LOADER}`,ACTIONS:`\0${VIRTUAL_MODULE_IDS.ACTIONS}`,SSR_DOM:`\0${VIRTUAL_MODULE_IDS.SSR_DOM}`};function he(e){return e===`react`?[]:[/^react/,/^react-dom/]}function ge(e){return e===`react`?[`import { createElement as h } from 'react';`,`import { renderToString as preactRenderToString } from 'react-dom/server';`]:[`import { h } from 'preact';`,`import preactRenderToString from 'preact-render-to-string';`]}function _e(e){return e===`react`?[`import { setShellRenderToString, setShellElementFactory } from '@useavalon/avalon/render/shell-engine';`,`import { renderToString as __reactRenderToString } from 'react-dom/server';`,`import { createElement as __reactCreateElement, Fragment as __reactFragment } from 'react';`,`setShellRenderToString((vnode) => __reactRenderToString(vnode));`,`setShellElementFactory(__reactCreateElement, __reactFragment);`]:[]}function ve(e){return e===`react`?`@useavalon/react/client`:`@useavalon/preact/client`}function ye(e){let t=P(`src/core/integrations/registry.ts`),n=[`solid`,`vue`,`svelte`,`lit`].filter(t=>e.includes(t));return`${[...n.includes(`lit`)?[`import "${O}";`]:[],`import { registry } from "${t}";`,...n.map(e=>`import { ${e}Integration } from "@useavalon/${e}";`)
|
|
9
|
+
<\/script>`}function P(t){let n=s(o(a(import.meta.url).resolve(`@useavalon/avalon`)),t);if(t.endsWith(`.ts`)&&!e(n)){let t=n.replace(/\.ts$/,`.js`);if(e(t))return t}return n}function me(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`,DEV_CSS_HMR:`virtual:avalon/dev-css-hmr`,INTEGRATION_LOADER:`virtual:avalon/integration-loader`,ACTIONS:`virtual:avalon/actions`,SSR_DOM:O};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}`,DEV_CSS_HMR:`\0${VIRTUAL_MODULE_IDS.DEV_CSS_HMR}`,INTEGRATION_LOADER:`\0${VIRTUAL_MODULE_IDS.INTEGRATION_LOADER}`,ACTIONS:`\0${VIRTUAL_MODULE_IDS.ACTIONS}`,SSR_DOM:`\0${VIRTUAL_MODULE_IDS.SSR_DOM}`};function he(e){return e===`react`?[]:[/^react/,/^react-dom/]}function ge(e){return e===`react`?[`import { createElement as h } from 'react';`,`import { renderToString as preactRenderToString } from 'react-dom/server';`]:[`import { h } from 'preact';`,`import preactRenderToString from 'preact-render-to-string';`]}function _e(e){return e===`react`?[`import { setShellRenderToString, setShellElementFactory } from '@useavalon/avalon/render/shell-engine';`,`import { renderToString as __reactRenderToString } from 'react-dom/server';`,`import { createElement as __reactCreateElement, Fragment as __reactFragment } from 'react';`,`setShellRenderToString((vnode) => __reactRenderToString(vnode));`,`setShellElementFactory(__reactCreateElement, __reactFragment);`]:[]}function ve(e){return e===`react`?`@useavalon/react/client`:`@useavalon/preact/client`}function ye(e){let t=P(`src/core/integrations/registry.ts`),n=[`solid`,`vue`,`svelte`,`lit`].filter(t=>e.includes(t));return`${[...n.includes(`lit`)?[`import "${O}";`]:[],`import { registry } from "${t}";`,...n.map(e=>`import { ${e}Integration } from "@useavalon/${e}";`),`let registered = false;`,`export function ensureServerIslandIntegrations() {`,` if (registered) return;`,` registered = true;`,...n.map(e=>` if (${e}Integration) registry.register(${e}Integration);`),`}`].join(`
|
|
10
10
|
`)}\n`}function be(e,t,n,r,i,a){let o={preset:e.preset,serverDir:t.serverDir??e.serverDir??`./server`,routeRules:e.routeRules,runtimeConfig:e.runtimeConfig,compatibilityDate:e.compatibilityDate,scanDirs:[`.`],noExternals:[`estree-walker`,/^@useavalon\//,/^estree-util/,/^preact/,...he(r.core),/^vue/,/^@vue\//],handlers:[{route:`/_server-islands/**`,handler:i},{route:`/_actions/**`,handler:a}],virtual:{"virtual:server-island-manifest":()=>ie(n),"virtual:avalon-actions-manifest":()=>ue(n),"virtual:server-island-key":()=>{let e=process.env.AVALON_KEY??``;return`export const serverIslandKey = ${JSON.stringify(e)};\n`},"virtual:server-island-integrations":()=>ye(r.integrations),[O]:()=>k()},traceDeps:[...new Set([`undici`,...e.traceDeps??[]])]};return we(o,e,t),o}function xe(e,t,n){if(n.renderer===!1){e.renderer=!1;return}t.renderer&&(e.renderer=t.renderer)}function Se(){return process.argv.includes(`build`)||process.env.NODE_ENV===`production`}function Ce(e,t){t.experimentalTasks&&Se()&&(e.experimental={...e.experimental,tasks:!0},t.tasks&&Object.keys(t.tasks).length>0&&(e.tasks=t.tasks),t.scheduledTasks&&Object.keys(t.scheduledTasks).length>0&&(e.scheduledTasks=t.scheduledTasks))}function we(e,t,n){xe(e,t,n),t.publicRuntimeConfig&&(e.publicRuntimeConfig=t.publicRuntimeConfig),t.publicAssets&&(e.publicAssets=t.publicAssets),t.compressPublicAssets&&(e.compressPublicAssets=t.compressPublicAssets),t.serverEntry&&(e.serverEntry=t.serverEntry),Ce(e,t),t.prerender&&(e.prerender={routes:[],crawlLinks:!1})}export function createNitroIntegration(e,t={}){let n=v(t,e),r=c(be(n,t,process.cwd(),e,P(`src/server-islands/route.ts`),P(`src/actions/route.ts`))),i=createNitroCoordinationPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),a=createVirtualModulesPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),o=b(e,t),s=y(e,{verbose:e.verbose,generatePreloadHints:!0}),l=S(x(t.preset??`node_server`,e.isDev)),u=d(t.cron,e.verbose);return{nitroOptions:n,plugins:[te(),...Array.isArray(r)?r:[r],i,a,o,s,l,u]}}export function createNitroCoordinationPlugin(e){let{avalonConfig:t,verbose:n}=e;return{name:`avalon:nitro-coordination`,enforce:`pre`,config(e,{command:t}){if(t===`serve`)return{server:{watch:{ignored:[`**/.output/**`,`**/dist/**`,`**/.netlify/**`,`**/.vercel/**`,`**/.cloudflare/**`,`**/.wrangler/**`,`**/.firebase/**`,`**/.amplify-hosting/**`]},fs:{deny:[`.output`,`dist`,`.netlify`,`.vercel`,`.cloudflare`,`.wrangler`,`.firebase`,`.amplify-hosting`]}}}},configResolved(e){globalThis.__avalonHydrationMode=e.command===`serve`?`entry-client`:`per-island`;try{u(e.root||process.cwd())}catch{}},configureServer(e){globalThis.__viteDevServer=e;let i=e.config.root||process.cwd(),a=e=>{if(e.includes(`/actions/`))try{u(i)}catch{}};e.watcher.on(`add`,a),e.watcher.on(`unlink`,a);let o=e.config.root||process.cwd(),c=e.config.build?.outDir?s(o,e.config.build.outDir):s(o,`dist`);try{r(c,{recursive:!0,force:!0})}catch{}try{r(s(o,`.output`),{recursive:!0,force:!0})}catch{}let d=!1,f=new Promise(t=>{let n=()=>{(e.environments?.nitro)?.devServer?.entry||d?(d=!0,t()):setTimeout(n,50)};setTimeout(n,100),setTimeout(()=>{d=!0,t()},15e3)});e.middlewares.use(async(e,t,n)=>{if(d)return n();let r=e.url||`/`;if(r.startsWith(`/@`)||r.startsWith(`/__`)||/\/[^/]+\.[a-z0-9]+(\?|$)/i.test(r))return n();await f,n()});let p=null;async function m(){return p||=await g({baseDir:`${e.config.root||process.cwd()}/src`,devMode:!1}),p}function h(){p=null}ke(e,t,n,h),m().catch(e=>{console.warn(`[middleware] Failed to discover middleware:`,e)});let _=e.environments?.ssr,v=!!_&&l(_);v&&De(e,t.integrations,n).catch(e=>{console.error(`[prewarm] Core modules pre-warm failed:`,e)}),e.middlewares.use(async(n,r,i)=>{let a=n.url||`/`;if(!a.startsWith(`/_server-islands/`)||!v)return i();try{let{decrypt:i}=await e.ssrLoadModule(P(`src/server-islands/encryption.ts`)),{h:o,renderToString:s}=await U(e,t.core),c=new URL(a,`http://${n.headers.host||`localhost`}`).searchParams.get(`p`)||``;if(!c&&n.method===`POST`&&(c=await A(n,`Timed out reading server island request body`)),!c){r.statusCode=400,r.setHeader(`Content-Type`,`text/plain`),r.end(`Missing encrypted props`);return}let l=fe(c,i);if(!l.ok){r.statusCode=400,r.setHeader(`Content-Type`,`text/plain`),r.end(`Bad Request: decryption failed`);return}let{props:u,srcPath:d,islandMeta:f}=l;if(!d){r.statusCode=404,r.setHeader(`Content-Type`,`text/plain`),r.end(`Component not found (no __src in payload)`);return}let p=(await e.ssrLoadModule(d)).default;if(typeof p!=`function`){r.statusCode=500,r.setHeader(`Content-Type`,`text/plain`),r.end(`Module "${d}" does not export a default component function`);return}let m=s(o(p,u));f&&(m+=pe(a,f,d,u)),r.statusCode=200,r.setHeader(`Content-Type`,`text/html`),r.setHeader(`Cache-Control`,`private, no-store`),r.end(m)}catch(e){console.error(`[server-islands] Dev handler error:`,e),r.statusCode=500,r.setHeader(`Content-Type`,`text/plain`),r.end(`Server island render failed: ${e instanceof Error?e.message:String(e)}`)}}),e.middlewares.use(async(t,n,r)=>{let i=t.url||`/`;if(!i.startsWith(`/_actions/`)||!v)return r();try{let r=N(e.config.root||process.cwd()),[a,o,s]=await Promise.all([e.ssrLoadModule(P(`src/actions/endpoint.ts`)),e.ssrLoadModule(P(`src/actions/registry.ts`)),r?e.ssrLoadModule(r):Promise.resolve({server:{}})]),c=o.flattenActions(s.server),l=a.defineActionHandler({registry:c,isDev:!0}),u=new URL(i,`http://${t.headers.host||`localhost`}`),d=(t.method||`GET`).toUpperCase(),f;d===`POST`&&(f=await A(t,`Timed out reading action request body`));let p=await l({url:u,web:{request:new Request(u,{method:d,headers:t.headers,body:f})},context:{}});n.statusCode=p.status,p.headers.forEach((e,t)=>{n.setHeader(t,e)}),n.end(await p.text())}catch(e){console.error(`[actions] Dev handler error:`,e),n.statusCode=500,n.setHeader(`Content-Type`,`application/json`),n.end(JSON.stringify({error:{code:`INTERNAL_SERVER_ERROR`,message:e instanceof Error?e.message:String(e)}}))}}),e.middlewares.use(async(r,i,a)=>{if(!v)return a();let o=r.url||`/`;if(o.endsWith(`.html`)&&(o=o.slice(0,-5)||`/`),o===`/index`&&(o=`/`),o.startsWith(`/@`)||o.startsWith(`/__`)||o.startsWith(`/node_modules/`)||o.startsWith(`/src/client/`)||o.startsWith(`/packages/`)||o.includes(`.`)&&!o.endsWith(`/`)||o.startsWith(`/api/`))return a();try{if(await Te(e,o,r,i,m,n)||await qe(e,o,t,i))return;let a=await Je(e,o,t);if(a){i.statusCode=200,i.setHeader(`Content-Type`,`text/html`),i.end(a);return}await Ee(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 Ee(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(ee(t))}}async function De(e,t,n){let r=performance.now(),i=[{path:P(`src/render/ssr.ts`),assignTo:`ssr`},{path:P(`src/core/layout/enhanced-layout-resolver.ts`),assignTo:`layout`},{path:P(`src/middleware/index.ts`),assignTo:null},...t.map(e=>({path:me(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`&&(V=r),n===`layout`&&(H=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,i=null;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.DEV_CSS_HMR?RESOLVED_VIRTUAL_IDS.DEV_CSS_HMR:e===VIRTUAL_MODULE_IDS.INTEGRATION_LOADER?RESOLVED_VIRTUAL_IDS.INTEGRATION_LOADER:e===VIRTUAL_MODULE_IDS.ACTIONS?RESOLVED_VIRTUAL_IDS.ACTIONS:e===VIRTUAL_MODULE_IDS.SSR_DOM?RESOLVED_VIRTUAL_IDS.SSR_DOM:null},async load(e){return e===RESOLVED_VIRTUAL_IDS.PAGE_ROUTES?await Ae(t,r):e===RESOLVED_VIRTUAL_IDS.PAGE_LOADER?await je(t,r):e===RESOLVED_VIRTUAL_IDS.ISLAND_MANIFEST?Me():e===RESOLVED_VIRTUAL_IDS.RUNTIME_CONFIG?Ne(t,n):e===RESOLVED_VIRTUAL_IDS.CONFIG?generateConfigModule(t,n):e===RESOLVED_VIRTUAL_IDS.LAYOUTS?(i||=await Pe(t,n),i):e===RESOLVED_VIRTUAL_IDS.ASSETS?Fe(n):e===RESOLVED_VIRTUAL_IDS.RENDERER?Ie(t):e===RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY?await ze(t,n):e===RESOLVED_VIRTUAL_IDS.DEV_CSS_HMR?ne():e===RESOLVED_VIRTUAL_IDS.INTEGRATION_LOADER?generateIntegrationLoaderModule(t):e===RESOLVED_VIRTUAL_IDS.ACTIONS?de():e===RESOLVED_VIRTUAL_IDS.SSR_DOM?k():null},handleHotUpdate({file:e,server:t}){let{isPage:n,isComponent:r,isLayout:a,isCss:o}=z(e);o&&(i=null),n&&(I(t,RESOLVED_VIRTUAL_IDS.PAGE_ROUTES),I(t,RESOLVED_VIRTUAL_IDS.PAGE_LOADER),L(t)),(n||r||a)&&(i=null,I(t,RESOLVED_VIRTUAL_IDS.LAYOUTS),a&&F(t,RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY),setTimeout(()=>{t.ws.send({type:`full-reload`,path:`*`})},500)),Oe(e)&&F(t,RESOLVED_VIRTUAL_IDS.CONFIG)}}}function F(e,t){let n=e.moduleGraph.getModuleById(t);n&&e.moduleGraph.invalidateModule(n)}function I(e,t){F(e,t);let n=e.environments;if(n)for(let e of Object.values(n)){let n=e.moduleGraph;if(n)try{let e=n.getModuleById(t);e&&n.invalidateModule(e)}catch{}}}async function L(e){let t=e.environments?.nitro;if(t)try{t.devServer?.sendMessage?.({type:`full-reload`}),await t.devServer?.reloadRoutes?.()}catch{}}function R(e){I(e,RESOLVED_VIRTUAL_IDS.PAGE_ROUTES),I(e,RESOLVED_VIRTUAL_IDS.PAGE_LOADER),L(e),setTimeout(()=>{e.ws.send({type:`full-reload`,path:`*`})},500)}function z(e){let t=e.endsWith(`.css`);return{isPage:e.includes(`/pages/`)&&!t,isComponent:e.includes(`/components/`)&&/\.[tj]sx?$/.test(e),isLayout:(e.includes(`/layouts/`)||e.includes(`_layout`))&&/\.[tj]sx?$/.test(e),isCss:t}}function Oe(e){return e.includes(`vite.config`)||e.includes(`avalon.config`)||e.includes(`nitro.config`)}function ke(e,t,n,r){e.watcher.on(`change`,e=>{e.includes(`_middleware`)&&(h(),r?.()),(e.includes(`/render/`)||e.includes(`/layout/`)||e.includes(`/islands/`))&&(V=null,H=null),(e.includes(`/layouts/`)||e.includes(`_layout`))&&globalThis.__avalonLayoutResolver?.clearCache?.()}),e.watcher.on(`add`,t=>{t.includes(`_middleware`)&&(h(),r?.()),isPageFile(t)&&R(e)}),e.watcher.on(`unlink`,t=>{t.includes(`_middleware`)&&(h(),r?.()),isPageFile(t)&&R(e)})}export function isPageFile(e){return z(e).isPage}async function Ae(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 = [];
|
|
11
11
|
export default pageRoutes;
|
|
12
12
|
`}}async function je(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(`,
|
|
@@ -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:
|
|
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 = {
|
|
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)`)}}}
|
|
@@ -2,8 +2,26 @@
|
|
|
2
2
|
* Separate module so ESM evaluates this stub before `@useavalon/lit`
|
|
3
3
|
* (and `lit-html`, which reads `document` at module eval). Imports in the
|
|
4
4
|
* same file are hoisted together; a dedicated first import is the only
|
|
5
|
-
* ordering guarantee.
|
|
6
|
-
*
|
|
5
|
+
* ordering guarantee.
|
|
6
|
+
*
|
|
7
|
+
* Prefer `@lit-labs/ssr-dom-shim` for HTMLElement / customElements so Lit SSR
|
|
8
|
+
* can emit declarative shadow DOM. A no-op `customElements.define` left Lit
|
|
9
|
+
* islands as empty tags until client hydration.
|
|
10
|
+
*
|
|
11
|
+
* Cloudflare's on-disk `_dom_stub.mjs` cannot use bare package imports (the
|
|
12
|
+
* Pages worker has no node_modules). Use {@link ssrDomStubFileSource} there.
|
|
7
13
|
*/
|
|
8
14
|
export declare const SSR_DOM_VIRTUAL_ID = "virtual:avalon/ssr-dom";
|
|
15
|
+
/**
|
|
16
|
+
* Nitro virtual module + prerender Node wrapper: real ssr-dom-shim classes.
|
|
17
|
+
* Rolldown / Node resolve `@lit-labs/ssr-dom-shim` from the project graph.
|
|
18
|
+
* CSSStyleSheet must exist before CustomElementRegistry.define runs Lit
|
|
19
|
+
* finalizeStyles (constructable stylesheets).
|
|
20
|
+
*/
|
|
9
21
|
export declare function ssrDomShimModuleSource(): string;
|
|
22
|
+
/**
|
|
23
|
+
* Self-contained stub for Cloudflare `_dom_stub.mjs` (no bare imports).
|
|
24
|
+
* Keeps a working customElements Map so dynamic Lit SSR in the Worker does not
|
|
25
|
+
* fall back to empty tags when the real shim package is unavailable.
|
|
26
|
+
*/
|
|
27
|
+
export declare function ssrDomStubFileSource(): string;
|
|
@@ -1,24 +1,13 @@
|
|
|
1
|
-
export const SSR_DOM_VIRTUAL_ID=`virtual:avalon/ssr-dom`;
|
|
2
|
-
if (typeof globalThis.
|
|
3
|
-
globalThis.
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
globalThis.EventTarget = class EventTarget {};
|
|
10
|
-
}
|
|
11
|
-
if (typeof globalThis.Event === "undefined") {
|
|
12
|
-
globalThis.Event = class Event { constructor(type) { this.type = type; } };
|
|
13
|
-
}
|
|
14
|
-
if (typeof globalThis.CustomEvent === "undefined") {
|
|
15
|
-
globalThis.CustomEvent = class CustomEvent extends Event {
|
|
16
|
-
constructor(type, init) { super(type); this.detail = init?.detail; }
|
|
1
|
+
export const SSR_DOM_VIRTUAL_ID=`virtual:avalon/ssr-dom`;function e(){return`
|
|
2
|
+
if (typeof globalThis.CSSStyleSheet === "undefined") {
|
|
3
|
+
globalThis.CSSStyleSheet = class CSSStyleSheet {
|
|
4
|
+
constructor() { this.cssRules = []; }
|
|
5
|
+
replaceSync() {}
|
|
6
|
+
replace() { return Promise.resolve(this); }
|
|
7
|
+
insertRule() { return 0; }
|
|
8
|
+
deleteRule() {}
|
|
17
9
|
};
|
|
18
10
|
}
|
|
19
|
-
if (typeof globalThis.customElements === "undefined") {
|
|
20
|
-
globalThis.customElements = { define() {}, get() { return undefined; }, whenDefined() { return Promise.resolve(); } };
|
|
21
|
-
}
|
|
22
11
|
if (typeof globalThis.document === "undefined") {
|
|
23
12
|
const createEl = () => ({
|
|
24
13
|
nodeType: 1,
|
|
@@ -47,4 +36,86 @@ if (typeof globalThis.document === "undefined") {
|
|
|
47
36
|
if (typeof globalThis.Node === "undefined") {
|
|
48
37
|
globalThis.Node = class Node {};
|
|
49
38
|
}
|
|
39
|
+
`}export function ssrDomShimModuleSource(){return`
|
|
40
|
+
${e()}
|
|
41
|
+
import {
|
|
42
|
+
CustomElementRegistry,
|
|
43
|
+
CustomEvent as ShimCustomEvent,
|
|
44
|
+
Element as ShimElement,
|
|
45
|
+
Event as ShimEvent,
|
|
46
|
+
EventTarget as ShimEventTarget,
|
|
47
|
+
HTMLElement as ShimHTMLElement,
|
|
48
|
+
} from "@lit-labs/ssr-dom-shim";
|
|
49
|
+
|
|
50
|
+
globalThis.HTMLElement = ShimHTMLElement;
|
|
51
|
+
globalThis.Element = ShimElement;
|
|
52
|
+
globalThis.EventTarget = ShimEventTarget;
|
|
53
|
+
globalThis.Event = ShimEvent;
|
|
54
|
+
globalThis.CustomEvent = ShimCustomEvent;
|
|
55
|
+
globalThis.customElements = new CustomElementRegistry();
|
|
56
|
+
`}export function ssrDomStubFileSource(){return`
|
|
57
|
+
if (typeof globalThis.HTMLElement === "undefined") {
|
|
58
|
+
globalThis.HTMLElement = class HTMLElement {};
|
|
59
|
+
}
|
|
60
|
+
if (typeof globalThis.Element === "undefined") {
|
|
61
|
+
globalThis.Element = class Element {};
|
|
62
|
+
}
|
|
63
|
+
if (typeof globalThis.EventTarget === "undefined") {
|
|
64
|
+
globalThis.EventTarget = class EventTarget {
|
|
65
|
+
addEventListener() {}
|
|
66
|
+
removeEventListener() {}
|
|
67
|
+
dispatchEvent() { return true; }
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (typeof globalThis.Event === "undefined") {
|
|
71
|
+
globalThis.Event = class Event { constructor(type) { this.type = type; } };
|
|
72
|
+
}
|
|
73
|
+
if (typeof globalThis.CustomEvent === "undefined") {
|
|
74
|
+
globalThis.CustomEvent = class CustomEvent extends Event {
|
|
75
|
+
constructor(type, init) { super(type); this.detail = init?.detail; }
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (typeof globalThis.customElements === "undefined") {
|
|
79
|
+
const registry = new Map();
|
|
80
|
+
globalThis.customElements = {
|
|
81
|
+
define(name, ctor) { registry.set(name, ctor); },
|
|
82
|
+
get(name) { return registry.get(name); },
|
|
83
|
+
whenDefined(name) {
|
|
84
|
+
const ctor = registry.get(name);
|
|
85
|
+
return ctor ? Promise.resolve(ctor) : Promise.resolve();
|
|
86
|
+
},
|
|
87
|
+
getName(ctor) {
|
|
88
|
+
for (const [name, registered] of registry) {
|
|
89
|
+
if (registered === ctor) return name;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
} else if (typeof globalThis.customElements.get === "function") {
|
|
95
|
+
const probeName = "avalon-ce-probe";
|
|
96
|
+
try {
|
|
97
|
+
const Probe = class extends globalThis.HTMLElement {};
|
|
98
|
+
globalThis.customElements.define(probeName, Probe);
|
|
99
|
+
if (globalThis.customElements.get(probeName) !== Probe) {
|
|
100
|
+
const registry = new Map();
|
|
101
|
+
globalThis.customElements = {
|
|
102
|
+
define(name, ctor) { registry.set(name, ctor); },
|
|
103
|
+
get(name) { return registry.get(name); },
|
|
104
|
+
whenDefined(name) {
|
|
105
|
+
const ctor = registry.get(name);
|
|
106
|
+
return ctor ? Promise.resolve(ctor) : Promise.resolve();
|
|
107
|
+
},
|
|
108
|
+
getName(ctor) {
|
|
109
|
+
for (const [name, registered] of registry) {
|
|
110
|
+
if (registered === ctor) return name;
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
} catch {
|
|
117
|
+
/* leave existing registry */
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
${e()}
|
|
50
121
|
`}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useavalon/avalon",
|
|
3
|
-
"version": "0.3.2-canary.
|
|
3
|
+
"version": "0.3.2-canary.15",
|
|
4
4
|
"description": "Multi-framework islands architecture for the modern web",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
},
|
|
165
165
|
"dependencies": {
|
|
166
166
|
"@mdx-js/rollup": "^3.0.0",
|
|
167
|
-
"@useavalon/core": "^0.3.2-canary.
|
|
167
|
+
"@useavalon/core": "^0.3.2-canary.15",
|
|
168
168
|
"h3": "^2.0.1-rc.16",
|
|
169
169
|
"marked": "^17.0.4",
|
|
170
170
|
"oxc-parser": "^0.120.0",
|