what-server 0.13.6 → 0.13.9
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/node.min.js +5 -5
- package/package.json +3 -3
- package/src/adapter/static.js +14 -5
package/dist/node.min.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import{AsyncLocalStorage as ze}from"node:async_hooks";import{__installServerContextStorage as Ge}from"what-core";import{h as at,_isAriaAttr as we,_beginComponentSSR as st,_endComponentSSR as it,_mapArrayToArray as ct,getServerContext as vt,runWithServerContext as S,beginHeadCollection as Se,endHeadCollection as ut}from"what-core";var Lt=new RegExp("[<>&\\u2028\\u2029]","g"),Mt={60:"\\u003c",62:"\\u003e",38:"\\u0026",8232:"\\u2028",8233:"\\u2029"};function N(t){return JSON.stringify(t).replace(Lt,e=>Mt[e.charCodeAt(0)])}import{mount as Ke,hydrate as Ze,signal as Qe,batch as qe,getServerContext as Ft}from"what-core";var Ut=new Map;function Bt(t){let e=t||Ft();return e&&e.islandStores instanceof Map?e.islandStores:null}function bt(t){let e=typeof document<"u"?Ut:Bt(t),r={};for(let[n,s]of e||[])r[n]=s._getSnapshot();return r}import{signal as R,batch as q}from"what-core";var M=Symbol.for("what.revalidationHandler"),_t=!(typeof process<"u");function K(t){globalThis[M]=t}function Jt(){return globalThis[M]??null}async function Z(t,e){let r=globalThis[M];if(r&&r.revalidatePath)return r.revalidatePath(t,e);_t&&console.warn(`[what] revalidatePath('${t}') had no effect: no cache engine is bound. Create a what-isr engine and bind it in your adapter (setRevalidationHandler).`)}async function Q(t,e){let r=globalThis[M];if(r&&r.revalidateTag)return r.revalidateTag(t,e);_t&&console.warn(`[what] revalidateTag('${t}') had no effect: no cache engine is bound.`)}var tt=new Map;function Vt(){if(typeof document<"u"){let t=document.querySelector('meta[name="what-csrf-token"]');if(t)return t.getAttribute("content");let e=document.cookie.match(/(?:^|;\s*)what-csrf=([^;]+)/);if(e)return decodeURIComponent(e[1])}return null}function et(){if(typeof crypto<"u"&&crypto.randomUUID)return crypto.randomUUID();if(typeof crypto<"u"&&crypto.getRandomValues){let t=new Uint8Array(16);return crypto.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}throw Object.assign(new Error("[what] No secure random source available for CSRF token generation"),{code:"ERR_NO_SECURE_RANDOM"})}function Rt(t,e){if(!t||!e||t.length!==e.length)return!1;let r=0;for(let n=0;n<t.length;n++)r|=t.charCodeAt(n)^e.charCodeAt(n);return r===0}function rt(t){return`<meta name="what-csrf-token" content="${String(t).replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}">`}var Wt=0,zt=!1;function Gt(){return!zt&&typeof process<"u",`a_${typeof crypto<"u"&&crypto.getRandomValues?Array.from(crypto.getRandomValues(new Uint8Array(6)),e=>e.toString(16).padStart(2,"0")).join(""):`c${(++Wt).toString(36)}_${Date.now().toString(36)}`}`}function Xt(t,e={}){let r=e.id||Gt(),{onError:n,onSuccess:s,revalidate:a}=e;typeof window>"u"&&tt.set(r,{fn:t,options:e});async function o(...i){if(typeof window>"u")return t(...i);let c=e.timeout||3e4,u=new AbortController,d=setTimeout(()=>u.abort(),c);try{let f=Vt(),l={"Content-Type":"application/json","X-What-Action":r};f&&(l["X-CSRF-Token"]=f);let p=await fetch("/__what_action",{method:"POST",headers:l,credentials:"same-origin",signal:u.signal,body:JSON.stringify({args:i})});if(!p.ok){let m=await p.json().catch(()=>({message:"Action failed"}));throw Object.assign(new Error(m.message||"Action failed"),{code:"ERR_ACTION_FAILED"})}let h=await p.json();if(s&&s(h),a)for(let m of a)Tt(m);return h}catch(f){if(f.name==="AbortError"){let l=new Error(`Action "${r}" timed out after ${c}ms`);throw l.code="TIMEOUT",n&&n(l),l}throw n&&n(f),f}finally{clearTimeout(d)}}return o._actionId=r,o._isAction=!0,o}function Et(t,e={}){let{onSuccess:r,onError:n,resetOnSuccess:s=!0}=e;return async a=>{let o,i;a instanceof Event?(a.preventDefault(),i=a.target,o=new FormData(i)):o=a;let c={},u=!1;for(let[d,f]of o.entries())typeof File<"u"&&f instanceof File&&(u=!0),c[d]?Array.isArray(c[d])?c[d].push(f):c[d]=[c[d],f]:c[d]=f;try{let d=u?await t(c,o):await t(c);return r&&r(d,i),s&&i&&i.reset(),d}catch(d){throw n&&n(d,i),d}}}function At(t){let e=R(!1),r=R(null),n=R(null);async function s(...a){e.set(!0),r.set(null);try{let o=await t(...a);return n.set(o),o}catch(o){throw r.set(o),o}finally{e.set(!1)}}return{trigger:s,isPending:()=>e(),error:()=>r(),data:()=>n(),reset:()=>{r.set(null),n.set(null)}}}function Yt(t,e={}){let{resetOnSuccess:r=!0}=e,n={current:null},s=At(Et(t,{resetOnSuccess:r}));function a(o){o.preventDefault();let i=new FormData(o.target);return n.current=o.target,s.trigger(i)}return{...s,handleSubmit:a,formRef:n}}function Kt(t,e){let r=R(t),n=R([]),s=R(t);function a(u){let d=e(r.peek(),u);q(()=>{n.set([...n.peek(),u]),r.set(d)})}function o(u,d){q(()=>{if(n.set(n.peek().filter(f=>f!==u)),d!==void 0){s.set(d);let f=d;for(let l of n.peek())f=e(f,l);r.set(f)}})}function i(u,d){q(()=>{let f=n.peek().filter(h=>h!==u);n.set(f);let l=d!==void 0?d:s.peek();s.set(l);let p=l;for(let h of f)p=e(p,h);r.set(p)})}async function c(u,d){a(u);try{let f=await d();return o(u,f),f}catch(f){throw i(u),f}}return{value:()=>r(),isPending:()=>n().length>0,addOptimistic:a,resolve:o,rollback:i,withOptimistic:c,set:u=>{r.set(u),s.set(u)}}}var j=new Map;function Zt(t,e){return j.has(t)||j.set(t,new Set),j.get(t).add(e),()=>{j.get(t)?.delete(e)}}function Tt(t){let e=j.get(t);if(e)for(let r of e)try{r()}catch(n){console.error("[what] Revalidation error:",n)}}function F(t,e,r,n={}){let{csrfToken:s,skipCsrf:a=!1}=n;if(!a){if(!s)return Promise.resolve({status:500,body:{message:"[what] CSRF token not configured. Pass { csrfToken: sessionToken } to handleActionRequest, or { skipCsrf: true } to explicitly opt out."}});let i=t?.headers?.["x-csrf-token"]||t?.headers?.["X-CSRF-Token"];if(!Rt(i,s))return Promise.resolve({status:403,body:{message:"Invalid CSRF token"}})}let o=tt.get(e);return o?Array.isArray(r)?o.fn(...r).then(async i=>{let c=o.options||{};if(Array.isArray(c.revalidate))for(let u of c.revalidate)await Z(u);if(Array.isArray(c.revalidateTags))for(let u of c.revalidateTags)await Q(u);return{status:200,body:i}}).catch(i=>(console.error(`[what] Action "${e}" error:`,i),{status:500,body:{message:"Action failed"}})):Promise.resolve({status:400,body:{message:"Invalid action arguments"}}):Promise.resolve({status:404,body:{message:"Action not found"}})}function Qt(){return[...tt.keys()]}function qt(t,e={}){let{onSuccess:r,onError:n,onSettled:s}=e,a={isPending:R(!1),error:R(null),data:R(null)};async function o(...i){a.isPending.set(!0),a.error.set(null);try{let c=await t(...i);return a.data.set(c),r&&r(c,...i),c}catch(c){throw a.error.set(c),n&&n(c,...i),c}finally{a.isPending.set(!1),s&&s(a.data.peek(),a.error.peek(),...i)}}return{mutate:o,isPending:()=>a.isPending(),error:()=>a.error(),data:()=>a.data(),reset:()=>{a.error.set(null),a.data.set(null)}}}import{h as U}from"what-core";var kt="/__what_action";function te(t){if(typeof t=="string")return t;if(typeof t=="function"){let e=t._actionId;if(e)return e;throw Object.assign(new Error("[what] <Form action={fn}>: that function is not a server action. Wrap it with action() from what-server, or pass the action id as a string."),{code:"ERR_FORM_ACTION_NOT_REGISTERED"})}throw Object.assign(new Error("[what] <Form> requires an `action` prop: a server action or its id."),{code:"ERR_FORM_ACTION_MISSING"})}function ee(){if(typeof document>"u")return null;let t=document.querySelector('meta[name="what-csrf-token"]');if(t)return t.getAttribute("content");let e=document.cookie.match(/(?:^|;\s*)what-csrf=([^;]+)/);return e?decodeURIComponent(e[1]):null}function re({action:t,csrfToken:e,redirect:r,method:n="post",enhance:s=!0,children:a,...o}){let i=te(t),c=e!==void 0?e:ee();c==null&&typeof process<"u";let u=[U("input",{type:"hidden",name:"_action",value:i}),U("input",{type:"hidden",name:"what-csrf-token",value:c||""})];r&&u.push(U("input",{type:"hidden",name:"_redirect",value:r}));let d={...o,method:n,action:o.action||kt,"data-action":i};s&&(d["data-enhance"]="");let f=a==null?[]:Array.isArray(a)?a:[a];return U("form",d,...u,...f)}var ne="/__what_action",H=1024*1024;function oe(t){if(!t)return{};if(typeof t.forEach=="function"&&typeof t.get=="function"){let r={};return t.forEach((n,s)=>{r[s.toLowerCase()]=n}),r}let e={};for(let r in t)e[r.toLowerCase()]=t[r];return e}function B(t,e){return{status:t,headers:{"content-type":"application/json"},body:JSON.stringify(e)}}function nt(t,e){return{status:t,headers:{"content-type":"text/html; charset=utf-8"},body:`<!DOCTYPE html><html><body><h1>${t}</h1><p>${String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}</p></body></html>`}}function Ot(t){if(typeof t!="string"||!t.startsWith("/")||/^[/\\]{2}/.test(t)||t.includes("\\"))return null;try{let e=new URL(t,"http://localhost");return e.origin!=="http://localhost"?null:e.pathname+e.search}catch{return null}}function ae(t,e){let r=Ot(t&&t._redirect);if(r)return r;let n=e.referer||e.referrer;if(n)try{let s=new URL(n,"http://localhost"),a=Ot(s.pathname+s.search);if(a)return a}catch{}return"/"}var se=new Set(["_action","data-action","_csrf","what-csrf-token","_redirect"]);function D(t={}){let{getCsrfToken:e,skipCsrf:r=!1}=t;return async function(s){if((s.method||"POST").toUpperCase()!=="POST")return B(405,{message:"Method Not Allowed"});let o=oe(s.headers),i=o["x-what-action"],c=o["content-type"]||"",u=!i&&c.includes("application/x-www-form-urlencoded"),d=r?void 0:e?await e(s):void 0;if(u){let h=s.body||{},m=h._action||h["data-action"]||s.query&&s.query.action;if(!m)return nt(400,'Missing action name (add a hidden "_action" field or ?action= query param)');let b={...o},C=h._csrf??h["what-csrf-token"];if(C&&!b["x-csrf-token"]&&(b["x-csrf-token"]=String(C)),!r&&e&&!d)return nt(403,"Missing CSRF token");let v={};for(let[x,G]of Object.entries(h))se.has(x)||(v[x]=G);let O=await F({headers:b},m,[v],{csrfToken:d,skipCsrf:r});return O.status===200?{status:303,headers:{location:ae(h,o)},body:""}:nt(O.status,O.body&&O.body.message||"Action failed")}if(!i)return B(400,{message:"Missing X-What-Action header"});if(!r&&e&&!d)return B(403,{message:"Missing CSRF token"});let l=(s.body||{}).args,p=await F({headers:o},i,l,{csrfToken:d,skipCsrf:r});return B(p.status,p.body)}}function ie(t={}){let e=t.basePath||ne,r=D(t);return async function(s,a,o){let[i,c]=(s.url||"").split("?");if(i!==e||(s.method||"").toUpperCase()!=="POST")return o?o():void 0;let u;try{let l=await ce(s);u=J(l,s.headers["content-type"]||"")}catch(l){a.writeHead(l.code==="BODY_TOO_LARGE"?413:400,{"content-type":"application/json"}),a.end(JSON.stringify({message:l.code==="BODY_TOO_LARGE"?"Payload too large":"Invalid request body"}));return}let d=Object.fromEntries(new URLSearchParams(c||"")),f=await r({method:s.method,headers:s.headers,body:u,query:d});a.writeHead(f.status,f.headers),a.end(f.body)}}function J(t,e){if((e||"").includes("application/x-www-form-urlencoded")){let r={};for(let[n,s]of new URLSearchParams(String(t)))r[n]===void 0?r[n]=s:Array.isArray(r[n])?r[n].push(s):r[n]=[r[n],s];return r}return t==null||t===""?{}:JSON.parse(String(t))}async function V(t,e=H){let r=Number(t.headers.get("content-length"));if(Number.isFinite(r)&&r>e)return{tooLarge:!0};let n=t.body;if(!n||typeof n.getReader!="function"){let i=await t.text();return Buffer.byteLength(i,"utf8")>e?{tooLarge:!0}:{raw:i}}let s=n.getReader(),a=[],o=0;for(;;){let{done:i,value:c}=await s.read();if(i)break;if(c){if(o+=c.byteLength,o>e){try{await s.cancel()}catch{}return{tooLarge:!0}}a.push(c)}}return{raw:Buffer.concat(a.map(i=>Buffer.from(i))).toString("utf8")}}function ce(t){return new Promise((e,r)=>{let n=0,s=[];t.on("data",a=>{if(n+=a.length,n>H){let o=new Error("Body too large");o.code="BODY_TOO_LARGE",r(o),t.destroy?.();return}s.push(a)}),t.on("end",()=>{if(s.length===0)return e("");e(Buffer.concat(s).toString("utf8"))}),t.on("error",r)})}function ue(t={}){let e=D(t);return async function(r){let n={};try{let o=await V(r);if(o.tooLarge)return new Response(JSON.stringify({message:"Payload too large"}),{status:413,headers:{"content-type":"application/json"}});n=J(o.raw,r.headers.get("content-type")||"")}catch{n={}}let s={};try{s=Object.fromEntries(new URL(r.url,"http://localhost").searchParams)}catch{}let a=await e({method:r.method,headers:r.headers,body:n,query:s});return new Response(a.body,{status:a.status,headers:a.headers})}}import{matchRoute as de,parseQuery as fe}from"what-router/match";var le="/__what_action",pe="/__what_revalidate",ot="what-csrf";function L(t){let e={};return t&&typeof t.forEach=="function"&&t.forEach((r,n)=>{e[n.toLowerCase()]=r}),e}function Ct(t,e){if(!t)return null;let r=String(t).match(new RegExp(`(?:^|;\\s*)${e}=([^;]+)`));return r?decodeURIComponent(r[1]):null}async function he(t){try{let e=await V(t);return e.tooLarge?{tooLarge:!0}:J(e.raw,t.headers.get("content-type")||"")}catch{return{}}}async function me(t){let e;try{e=await V(t)}catch{return{json:{}}}if(e.tooLarge)return{tooLarge:!0};try{return{json:JSON.parse(e.raw??"")}}catch{return{json:{}}}}function ye(t){return async function(r){let{route:n,params:s,query:a,request:o,csrfToken:i}=r,c={default:n.component,loader:n.loader},u=i?{params:s,query:a,request:o,csrfToken:i}:{params:s,query:a,request:o},d=i?{...t,csrfToken:i}:t;return{html:await W(c,u,d),status:200,tags:r.config&&r.config.tags||[],path:r.path}}}function T(t={}){let{routes:e=[],cache:r,render:n,revalidateWebhook:s,document:a={},notFound:o,basePath:i="",csrf:c=!0}=t,u=c!==!1&&!t.actionHandler,d=t.actionHandler||D(u?{getCsrfToken:l=>Ct(l.headers&&l.headers.cookie,ot)}:{skipCsrf:!0}),f=n||ye(a);return r&&(r.revalidatePath||r.revalidateTag)&&K({revalidatePath:r.revalidatePath,revalidateTag:r.revalidateTag}),async function(p){let h=new URL(p.url,"http://localhost"),m=h.pathname;if(i&&m.startsWith(i)&&(m=m.slice(i.length)||"/"),p.method==="POST"&&m===le){let g=await he(p);if(g&&g.tooLarge)return new Response(JSON.stringify({message:"Payload too large"}),{status:413,headers:{"content-type":"application/json"}});let A=await d({method:"POST",headers:L(p.headers),body:g,query:Object.fromEntries(h.searchParams)});return new Response(A.body,{status:A.status,headers:A.headers})}let b=null,C=null;if(u&&(b=Ct(L(p.headers).cookie,ot),!b)){b=et();let A=L(p.headers)["x-forwarded-proto"]==="https"||h.protocol==="https:"||!0;C=`${ot}=${encodeURIComponent(b)}; Path=/; SameSite=Lax`+(A?"; Secure":"")}let v=g=>(C&&(g["set-cookie"]=C),g);if(p.method==="POST"&&m===pe&&s){let g=await me(p);if(g.tooLarge)return new Response(JSON.stringify({message:"Payload too large"}),{status:413,headers:{"content-type":"application/json"}});let A=await s({headers:L(p.headers),body:g.json});return new Response(JSON.stringify(A.body),{status:A.status,headers:{"content-type":"application/json"}})}let O=de(m,e);if(!O){let g=o?o():"<!DOCTYPE html><html><body><h1>404 \u2014 Not Found</h1></body></html>";return new Response(g,{status:404,headers:v({"content-type":"text/html; charset=utf-8"})})}let{route:x,params:G}=O,X=x.page||{mode:x.mode||"client"},I={path:m,query:fe(h.search),config:X,route:x,params:G,request:p};if(r&&X.mode!=="server"){I.varyHeaders=L(p.headers);let g=await r.handle(I,()=>f(I));return new Response(g.html,{status:g.status||200,headers:v({"content-type":"text/html; charset=utf-8",...g.headers||{}})})}b&&(I.csrfToken=b);let Y=await f(I),St=v({"content-type":"text/html; charset=utf-8",...Y.headers||{}});return X.mode==="server"&&(St["Cache-Control"]="private, no-store"),new Response(Y.html,{status:Y.status||200,headers:St})}}function ge(t={}){let e=T(t);return{async fetch(r,n,s){return n&&(r.__env=n),s&&(r.__ctx=s),e(r)}}}function k(t){return{head:Se(),loaderData:t,resources:new Map,islandStores:new Map,resourceCounter:0,boundaryCounter:0,suspended:[]}}var xt=0;function be(){xt=0}function _e(){return"h"+xt++}function Re(t){if(!vt()){let e=k(void 0);return S(e,()=>Re(t))}return be(),E(t)}var Pt=new Set(["__errorBoundary","__suspense"]),dt=new Set(["__portal"]);function ft(t){let e=t.children;return!e||e.length===0?{...t.props}:{...t.props,children:e}}function lt(t,e){let r=t.props&&t.props.fallback;if(typeof r!="function")return r;let n=t.props&&t.props.reset||(()=>{});try{return r({error:e,reset:n})}catch(s){return _(s),$&&console.warn(`[what-server] <ErrorBoundary> fallback threw during SSR: ${s.message}`),null}}function E(t){if(t==null||t===!1||t===!0)return"";if(typeof t=="string"||typeof t=="number")return w(String(t));if(typeof t=="function"&&t._signal)return`<!--$-->${E(t())}<!--/$-->`;if(typeof t=="function"&&t._mapArray)try{return`<!--$-->${E(ct(t))}<!--/$-->`}catch(c){return _(c),typeof process<"u","<!--$--><!--/$-->"}if(typeof t=="function")try{return`<!--$-->${E(t())}<!--/$-->`}catch(c){return _(c),typeof process<"u","<!--$--><!--/$-->"}if(Array.isArray(t))return`<!--[]-->${t.map(E).join("")}<!--/[]-->`;if(dt.has(t.tag))return"";if(Pt.has(t.tag))try{return(t.children||[]).map(E).join("")}catch(c){_(c);let u=c&&typeof c.then=="function";if(u&&t.tag==="__errorBoundary"||!u&&t.tag==="__suspense")throw c;return E(lt(t,u?null:c))}if(typeof t.tag=="function"){let c=_e(),u=st(t.tag),d;try{d=E(t.tag(ft(t)))}finally{it(u)}return Ee(d,c)}let{tag:e,props:r,children:n}=t;ht(e,t);let s=mt(r||{}),a=`<${e}${s}>`;if(yt.has(e))return a;let o=pt(r),i=o!=null?String(o):n.map(E).join("");return`${a}${i}</${e}>`}function Ee(t,e){let r=t.match(/^((?:<!--.*?-->)*)<([a-zA-Z][a-zA-Z0-9-]*)/);if(r){let n=r[1],s=r[2],a=n.length+1+s.length,o=t.indexOf(">",a),i=t.slice(a,o===-1?void 0:o);return/[\s"']data-hk\s*=/.test(i)||/^\s*data-hk\s*=/.test(i)?t:t.slice(0,a)+` data-hk="${e}"`+t.slice(a)}return t}function y(t){if(!vt()){let c=k(void 0);return S(c,()=>y(t))}if(t==null||t===!1||t===!0)return"";if(typeof t=="string"||typeof t=="number")return w(String(t));if(typeof t=="function"&&t._signal)return y(t());if(typeof t=="function"&&t._mapArray)try{return y(ct(t))}catch(c){return _(c),typeof process<"u",""}if(typeof t=="function")try{return y(t())}catch(c){return _(c),typeof process<"u",""}if(Array.isArray(t))return t.map(y).join("");if(dt.has(t.tag))return"";if(Pt.has(t.tag))try{return(t.children||[]).map(y).join("")}catch(c){_(c);let u=c&&typeof c.then=="function";if(u&&t.tag==="__errorBoundary"||!u&&t.tag==="__suspense")throw c;return y(lt(t,u?null:c))}if(typeof t.tag=="function"){let c=st(t.tag);try{return y(t.tag(ft(t)))}finally{it(c)}}let{tag:e,props:r,children:n}=t;ht(e,t);let s=mt(r||{}),a=`<${e}${s}>`;if(yt.has(e))return a;let o=pt(r),i=o!=null?String(o):n.map(y).join("");return`${a}${i}</${e}>`}function _r(t){let e=k(void 0);return{body:S(e,()=>y(t)),head:ut(e.head)}}async function Rr(t,e={}){let r=t.default||t,n=typeof t.loader=="function"?await t.loader(e):void 0,s=k(n),a=e.params||{};return{body:S(s,()=>y(at(r,{...a,loaderData:n}))),head:ut(s.head),loaderData:n}}var $t=12;async function Ae(t,e){e||(e=k(void 0));let r="",n=e.resourceCounter;for(let a=0;a<$t;a++){e.resourceCounter=n,r=S(e,()=>y(t));let o=[...e.resources.values()].filter(i=>i.status==="pending").map(i=>i.promise);if(o.length===0)break;await Promise.all(o)}let s={};for(let[a,o]of e.resources)o.status==="ready"&&(s[a]=o.value);return{body:r,head:ut(e.head),loaderData:e.loaderData,resources:s,ctx:e}}async function W(t,e={},r={}){let n=t.default||t,s=typeof t.loader=="function"?await t.loader(e):void 0,a=k(s),o=e.params||{},{body:i,head:c,resources:u}=await Ae(at(n,{...o,loaderData:s}),a),d={loaderData:s??null,resources:u,islandStores:bt(a)};return Te({body:i,head:c,payload:d,options:r})}function Te({body:t,head:e,payload:r,options:n={}}){let s=n.lang||"en",a=`<script id="__what_data" type="application/json">${N(r)}<\/script>`,o=n.clientEntry?`<script type="module" src="${w(n.clientEntry)}"><\/script>`:"",c=(n.csrfToken?rt(n.csrfToken):"")+(n.head||""),u=n.bodyClass?` class="${w(n.bodyClass)}"`:"";return`<!DOCTYPE html><html lang="${w(s)}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">${e||""}${c}</head><body${u}>${t}${a}${o}</body></html>`}async function*P(t,e){if(e===void 0&&(e=k(void 0)),t==null||t===!1||t===!0)return;if(typeof t=="string"||typeof t=="number"){yield w(String(t));return}if(typeof t=="function"&&t._signal){let o=S(e,()=>t());yield*P(o,e);return}if(typeof t=="function"&&t._mapArray){let o=null;try{o=S(e,()=>ct(t))}catch(i){_(i),typeof process<"u"}o&&(yield*P(o,e));return}if(typeof t=="function"){try{let o=S(e,()=>t());yield*P(o,e)}catch(o){_(o),typeof process<"u"}return}if(Array.isArray(t)){for(let o of t)yield*P(o,e);return}if(dt.has(t.tag))return;if(t.tag==="__errorBoundary"){let o;try{o=S(e,()=>(t.children||[]).map(y).join(""))}catch(i){if(_(i),i&&typeof i.then=="function")throw i;o=S(e,()=>y(lt(t,i)))}yield o;return}if(t.tag==="__suspense"){let o=null,i=e.resourceCounter;for(let c=0;c<$t&&o===null;c++){e.resourceCounter=i;let u=null;try{o=S(e,()=>(t.children||[]).map(y).join(""))}catch(d){if(d&&typeof d.then=="function")u=d;else throw d}if(o===null){let d=[...e.resources.values()].filter(f=>f.status==="pending").map(f=>f.promise);await Promise.all([u,...d].filter(Boolean))}}o===null&&(o=S(e,()=>y(t.props&&t.props.fallback))),yield o;return}if(typeof t.tag=="function"){let o=st(t.tag);try{let i=S(e,()=>t.tag(ft(t))),c=i instanceof Promise?await i:i;yield*P(c,e)}catch(i){_(i),typeof process<"u",yield $?`<!-- SSR Error: ${w(i.message||"Component error")} -->`:"<!-- SSR Error -->"}finally{it(o)}return}let{tag:r,props:n,children:s}=t;ht(r,t);let a=mt(n||{});if(yield`<${r}${a}>`,!yt.has(r)){let o=pt(n);if(o!=null)yield String(o);else for(let i of s)yield*P(i,e);yield`</${r}>`}}function Er(t){return{mode:"static",...t}}function Ar(t,e={}){let r=k(e),n=S(r,()=>y(at(t.component,e))),s=t.islands||[];return ke({title:t.title||"",meta:t.meta||{},body:n,islands:s,scripts:t.mode==="static"?[]:t.scripts||[],styles:t.styles||[],mode:t.mode})}function ke({title:t,meta:e,body:r,islands:n,scripts:s,styles:a,mode:o}){let i=Object.entries(e).map(([l,p])=>`<meta name="${w(l)}" content="${w(p)}">`).join(`
|
|
2
|
-
`),c=a.map(l=>`<link rel="stylesheet" href="${
|
|
1
|
+
import{AsyncLocalStorage as ze}from"node:async_hooks";import{__installServerContextStorage as Ge}from"what-core";import{h as at,_isAriaAttr as we,_beginComponentSSR as st,_endComponentSSR as it,_mapArrayToArray as ct,getServerContext as vt,runWithServerContext as b,beginHeadCollection as Se,endHeadCollection as ut}from"what-core";var Lt=new RegExp("[<>&\\u2028\\u2029]","g"),Mt={60:"\\u003c",62:"\\u003e",38:"\\u0026",8232:"\\u2028",8233:"\\u2029"};function N(t){return JSON.stringify(t).replace(Lt,e=>Mt[e.charCodeAt(0)])}import{mount as Ke,hydrate as Ze,signal as Qe,batch as qe,getServerContext as Ft}from"what-core";var Ut=new Map;function Bt(t){let e=t||Ft();return e&&e.islandStores instanceof Map?e.islandStores:null}function bt(t){let e=typeof document<"u"?Ut:Bt(t),r={};for(let[n,s]of e||[])r[n]=s._getSnapshot();return r}import{signal as E,batch as q}from"what-core";var M=Symbol.for("what.revalidationHandler"),_t=!(typeof process<"u");function K(t){globalThis[M]=t}function Jt(){return globalThis[M]??null}async function Z(t,e){let r=globalThis[M];if(r&&r.revalidatePath)return r.revalidatePath(t,e);_t&&console.warn(`[what] revalidatePath('${t}') had no effect: no cache engine is bound. Create a what-isr engine and bind it in your adapter (setRevalidationHandler).`)}async function Q(t,e){let r=globalThis[M];if(r&&r.revalidateTag)return r.revalidateTag(t,e);_t&&console.warn(`[what] revalidateTag('${t}') had no effect: no cache engine is bound.`)}var tt=new Map;function Vt(){if(typeof document<"u"){let t=document.querySelector('meta[name="what-csrf-token"]');if(t)return t.getAttribute("content");let e=document.cookie.match(/(?:^|;\s*)what-csrf=([^;]+)/);if(e)return decodeURIComponent(e[1])}return null}function et(){if(typeof crypto<"u"&&crypto.randomUUID)return crypto.randomUUID();if(typeof crypto<"u"&&crypto.getRandomValues){let t=new Uint8Array(16);return crypto.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}throw Object.assign(new Error("[what] No secure random source available for CSRF token generation"),{code:"ERR_NO_SECURE_RANDOM"})}function Rt(t,e){if(!t||!e||t.length!==e.length)return!1;let r=0;for(let n=0;n<t.length;n++)r|=t.charCodeAt(n)^e.charCodeAt(n);return r===0}function rt(t){return`<meta name="what-csrf-token" content="${String(t).replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}">`}var Wt=0,zt=!1;function Gt(){return!zt&&typeof process<"u",`a_${typeof crypto<"u"&&crypto.getRandomValues?Array.from(crypto.getRandomValues(new Uint8Array(6)),e=>e.toString(16).padStart(2,"0")).join(""):`c${(++Wt).toString(36)}_${Date.now().toString(36)}`}`}function Xt(t,e={}){let r=e.id||Gt(),{onError:n,onSuccess:s,revalidate:a}=e;typeof window>"u"&&tt.set(r,{fn:t,options:e});async function o(...i){if(typeof window>"u")return t(...i);let c=e.timeout||3e4,u=new AbortController,d=setTimeout(()=>u.abort(),c);try{let f=Vt(),l={"Content-Type":"application/json","X-What-Action":r};f&&(l["X-CSRF-Token"]=f);let p=await fetch("/__what_action",{method:"POST",headers:l,credentials:"same-origin",signal:u.signal,body:JSON.stringify({args:i})});if(!p.ok){let m=await p.json().catch(()=>({message:"Action failed"}));throw Object.assign(new Error(m.message||"Action failed"),{code:"ERR_ACTION_FAILED"})}let h=await p.json();if(s&&s(h),a)for(let m of a)Tt(m);return h}catch(f){if(f.name==="AbortError"){let l=new Error(`Action "${r}" timed out after ${c}ms`);throw l.code="TIMEOUT",n&&n(l),l}throw n&&n(f),f}finally{clearTimeout(d)}}return o._actionId=r,o._isAction=!0,o}function Et(t,e={}){let{onSuccess:r,onError:n,resetOnSuccess:s=!0}=e;return async a=>{let o,i;a instanceof Event?(a.preventDefault(),i=a.target,o=new FormData(i)):o=a;let c={},u=!1;for(let[d,f]of o.entries())typeof File<"u"&&f instanceof File&&(u=!0),c[d]?Array.isArray(c[d])?c[d].push(f):c[d]=[c[d],f]:c[d]=f;try{let d=u?await t(c,o):await t(c);return r&&r(d,i),s&&i&&i.reset(),d}catch(d){throw n&&n(d,i),d}}}function At(t){let e=E(!1),r=E(null),n=E(null);async function s(...a){e.set(!0),r.set(null);try{let o=await t(...a);return n.set(o),o}catch(o){throw r.set(o),o}finally{e.set(!1)}}return{trigger:s,isPending:()=>e(),error:()=>r(),data:()=>n(),reset:()=>{r.set(null),n.set(null)}}}function Yt(t,e={}){let{resetOnSuccess:r=!0}=e,n={current:null},s=At(Et(t,{resetOnSuccess:r}));function a(o){o.preventDefault();let i=new FormData(o.target);return n.current=o.target,s.trigger(i)}return{...s,handleSubmit:a,formRef:n}}function Kt(t,e){let r=E(t),n=E([]),s=E(t);function a(u){let d=e(r.peek(),u);q(()=>{n.set([...n.peek(),u]),r.set(d)})}function o(u,d){q(()=>{if(n.set(n.peek().filter(f=>f!==u)),d!==void 0){s.set(d);let f=d;for(let l of n.peek())f=e(f,l);r.set(f)}})}function i(u,d){q(()=>{let f=n.peek().filter(h=>h!==u);n.set(f);let l=d!==void 0?d:s.peek();s.set(l);let p=l;for(let h of f)p=e(p,h);r.set(p)})}async function c(u,d){a(u);try{let f=await d();return o(u,f),f}catch(f){throw i(u),f}}return{value:()=>r(),isPending:()=>n().length>0,addOptimistic:a,resolve:o,rollback:i,withOptimistic:c,set:u=>{r.set(u),s.set(u)}}}var j=new Map;function Zt(t,e){return j.has(t)||j.set(t,new Set),j.get(t).add(e),()=>{j.get(t)?.delete(e)}}function Tt(t){let e=j.get(t);if(e)for(let r of e)try{r()}catch(n){console.error("[what] Revalidation error:",n)}}function F(t,e,r,n={}){let{csrfToken:s,skipCsrf:a=!1}=n;if(!a){if(!s)return Promise.resolve({status:500,body:{message:"[what] CSRF token not configured. Pass { csrfToken: sessionToken } to handleActionRequest, or { skipCsrf: true } to explicitly opt out."}});let i=t?.headers?.["x-csrf-token"]||t?.headers?.["X-CSRF-Token"];if(!Rt(i,s))return Promise.resolve({status:403,body:{message:"Invalid CSRF token"}})}let o=tt.get(e);return o?Array.isArray(r)?o.fn(...r).then(async i=>{let c=o.options||{};if(Array.isArray(c.revalidate))for(let u of c.revalidate)await Z(u);if(Array.isArray(c.revalidateTags))for(let u of c.revalidateTags)await Q(u);return{status:200,body:i}}).catch(i=>(console.error(`[what] Action "${e}" error:`,i),{status:500,body:{message:"Action failed"}})):Promise.resolve({status:400,body:{message:"Invalid action arguments"}}):Promise.resolve({status:404,body:{message:"Action not found"}})}function Qt(){return[...tt.keys()]}function qt(t,e={}){let{onSuccess:r,onError:n,onSettled:s}=e,a={isPending:E(!1),error:E(null),data:E(null)};async function o(...i){a.isPending.set(!0),a.error.set(null);try{let c=await t(...i);return a.data.set(c),r&&r(c,...i),c}catch(c){throw a.error.set(c),n&&n(c,...i),c}finally{a.isPending.set(!1),s&&s(a.data.peek(),a.error.peek(),...i)}}return{mutate:o,isPending:()=>a.isPending(),error:()=>a.error(),data:()=>a.data(),reset:()=>{a.error.set(null),a.data.set(null)}}}import{h as U}from"what-core";var kt="/__what_action";function te(t){if(typeof t=="string")return t;if(typeof t=="function"){let e=t._actionId;if(e)return e;throw Object.assign(new Error("[what] <Form action={fn}>: that function is not a server action. Wrap it with action() from what-server, or pass the action id as a string."),{code:"ERR_FORM_ACTION_NOT_REGISTERED"})}throw Object.assign(new Error("[what] <Form> requires an `action` prop: a server action or its id."),{code:"ERR_FORM_ACTION_MISSING"})}function ee(){if(typeof document>"u")return null;let t=document.querySelector('meta[name="what-csrf-token"]');if(t)return t.getAttribute("content");let e=document.cookie.match(/(?:^|;\s*)what-csrf=([^;]+)/);return e?decodeURIComponent(e[1]):null}function re({action:t,csrfToken:e,redirect:r,method:n="post",enhance:s=!0,children:a,...o}){let i=te(t),c=e!==void 0?e:ee();c==null&&typeof process<"u";let u=[U("input",{type:"hidden",name:"_action",value:i}),U("input",{type:"hidden",name:"what-csrf-token",value:c||""})];r&&u.push(U("input",{type:"hidden",name:"_redirect",value:r}));let d={...o,method:n,action:o.action||kt,"data-action":i};s&&(d["data-enhance"]="");let f=a==null?[]:Array.isArray(a)?a:[a];return U("form",d,...u,...f)}var ne="/__what_action",H=1024*1024;function oe(t){if(!t)return{};if(typeof t.forEach=="function"&&typeof t.get=="function"){let r={};return t.forEach((n,s)=>{r[s.toLowerCase()]=n}),r}let e={};for(let r in t)e[r.toLowerCase()]=t[r];return e}function B(t,e){return{status:t,headers:{"content-type":"application/json"},body:JSON.stringify(e)}}function nt(t,e){return{status:t,headers:{"content-type":"text/html; charset=utf-8"},body:`<!DOCTYPE html><html><body><h1>${t}</h1><p>${String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}</p></body></html>`}}function Ot(t){if(typeof t!="string"||!t.startsWith("/")||/^[/\\]{2}/.test(t)||t.includes("\\"))return null;try{let e=new URL(t,"http://localhost");return e.origin!=="http://localhost"?null:e.pathname+e.search}catch{return null}}function ae(t,e){let r=Ot(t&&t._redirect);if(r)return r;let n=e.referer||e.referrer;if(n)try{let s=new URL(n,"http://localhost"),a=Ot(s.pathname+s.search);if(a)return a}catch{}return"/"}var se=new Set(["_action","data-action","_csrf","what-csrf-token","_redirect"]);function D(t={}){let{getCsrfToken:e,skipCsrf:r=!1}=t;return async function(s){if((s.method||"POST").toUpperCase()!=="POST")return B(405,{message:"Method Not Allowed"});let o=oe(s.headers),i=o["x-what-action"],c=o["content-type"]||"",u=!i&&c.includes("application/x-www-form-urlencoded"),d=r?void 0:e?await e(s):void 0;if(u){let h=s.body||{},m=h._action||h["data-action"]||s.query&&s.query.action;if(!m)return nt(400,'Missing action name (add a hidden "_action" field or ?action= query param)');let w={...o},T=h._csrf??h["what-csrf-token"];if(T&&!w["x-csrf-token"]&&(w["x-csrf-token"]=String(T)),!r&&e&&!d)return nt(403,"Missing CSRF token");let k={};for(let[O,G]of Object.entries(h))se.has(O)||(k[O]=G);let R=await F({headers:w},m,[k],{csrfToken:d,skipCsrf:r});return R.status===200?{status:303,headers:{location:ae(h,o)},body:""}:nt(R.status,R.body&&R.body.message||"Action failed")}if(!i)return B(400,{message:"Missing X-What-Action header"});if(!r&&e&&!d)return B(403,{message:"Missing CSRF token"});let l=(s.body||{}).args,p=await F({headers:o},i,l,{csrfToken:d,skipCsrf:r});return B(p.status,p.body)}}function ie(t={}){let e=t.basePath||ne,r=D(t);return async function(s,a,o){let[i,c]=(s.url||"").split("?");if(i!==e||(s.method||"").toUpperCase()!=="POST")return o?o():void 0;let u;try{let l=await ce(s);u=J(l,s.headers["content-type"]||"")}catch(l){a.writeHead(l.code==="BODY_TOO_LARGE"?413:400,{"content-type":"application/json"}),a.end(JSON.stringify({message:l.code==="BODY_TOO_LARGE"?"Payload too large":"Invalid request body"}));return}let d=Object.fromEntries(new URLSearchParams(c||"")),f=await r({method:s.method,headers:s.headers,body:u,query:d});a.writeHead(f.status,f.headers),a.end(f.body)}}function J(t,e){if((e||"").includes("application/x-www-form-urlencoded")){let r={};for(let[n,s]of new URLSearchParams(String(t)))r[n]===void 0?r[n]=s:Array.isArray(r[n])?r[n].push(s):r[n]=[r[n],s];return r}return t==null||t===""?{}:JSON.parse(String(t))}async function V(t,e=H){let r=Number(t.headers.get("content-length"));if(Number.isFinite(r)&&r>e)return{tooLarge:!0};let n=t.body;if(!n||typeof n.getReader!="function"){let i=await t.text();return Buffer.byteLength(i,"utf8")>e?{tooLarge:!0}:{raw:i}}let s=n.getReader(),a=[],o=0;for(;;){let{done:i,value:c}=await s.read();if(i)break;if(c){if(o+=c.byteLength,o>e){try{await s.cancel()}catch{}return{tooLarge:!0}}a.push(c)}}return{raw:Buffer.concat(a.map(i=>Buffer.from(i))).toString("utf8")}}function ce(t){return new Promise((e,r)=>{let n=0,s=[];t.on("data",a=>{if(n+=a.length,n>H){let o=new Error("Body too large");o.code="BODY_TOO_LARGE",r(o),t.destroy?.();return}s.push(a)}),t.on("end",()=>{if(s.length===0)return e("");e(Buffer.concat(s).toString("utf8"))}),t.on("error",r)})}function ue(t={}){let e=D(t);return async function(r){let n={};try{let o=await V(r);if(o.tooLarge)return new Response(JSON.stringify({message:"Payload too large"}),{status:413,headers:{"content-type":"application/json"}});n=J(o.raw,r.headers.get("content-type")||"")}catch{n={}}let s={};try{s=Object.fromEntries(new URL(r.url,"http://localhost").searchParams)}catch{}let a=await e({method:r.method,headers:r.headers,body:n,query:s});return new Response(a.body,{status:a.status,headers:a.headers})}}import{matchRoute as de,parseQuery as fe}from"what-router/match";var le="/__what_action",pe="/__what_revalidate",ot="what-csrf";function L(t){let e={};return t&&typeof t.forEach=="function"&&t.forEach((r,n)=>{e[n.toLowerCase()]=r}),e}function Ct(t,e){if(!t)return null;let r=String(t).match(new RegExp(`(?:^|;\\s*)${e}=([^;]+)`));return r?decodeURIComponent(r[1]):null}async function he(t){try{let e=await V(t);return e.tooLarge?{tooLarge:!0}:J(e.raw,t.headers.get("content-type")||"")}catch{return{}}}async function me(t){let e;try{e=await V(t)}catch{return{json:{}}}if(e.tooLarge)return{tooLarge:!0};try{return{json:JSON.parse(e.raw??"")}}catch{return{json:{}}}}function ye(t){return async function(r){let{route:n,params:s,query:a,request:o,csrfToken:i}=r,c={default:n.component,loader:n.loader},u=i?{params:s,query:a,request:o,csrfToken:i}:{params:s,query:a,request:o},d=i?{...t,csrfToken:i}:t;return{html:await W(c,u,d),status:200,tags:r.config&&r.config.tags||[],path:r.path}}}function v(t={}){let{routes:e=[],cache:r,render:n,revalidateWebhook:s,document:a={},notFound:o,basePath:i="",csrf:c=!0}=t,u=c!==!1&&!t.actionHandler,d=t.actionHandler||D(u?{getCsrfToken:l=>Ct(l.headers&&l.headers.cookie,ot)}:{skipCsrf:!0}),f=n||ye(a);return r&&(r.revalidatePath||r.revalidateTag)&&K({revalidatePath:r.revalidatePath,revalidateTag:r.revalidateTag}),async function(p){let h=new URL(p.url,"http://localhost"),m=h.pathname;if(i&&m.startsWith(i)&&(m=m.slice(i.length)||"/"),p.method==="POST"&&m===le){let g=await he(p);if(g&&g.tooLarge)return new Response(JSON.stringify({message:"Payload too large"}),{status:413,headers:{"content-type":"application/json"}});let C=await d({method:"POST",headers:L(p.headers),body:g,query:Object.fromEntries(h.searchParams)});return new Response(C.body,{status:C.status,headers:C.headers})}let w=null,T=null;if(u&&(w=Ct(L(p.headers).cookie,ot),!w)){w=et();let C=L(p.headers)["x-forwarded-proto"]==="https"||h.protocol==="https:"||!0;T=`${ot}=${encodeURIComponent(w)}; Path=/; SameSite=Lax`+(C?"; Secure":"")}let k=g=>(T&&(g["set-cookie"]=T),g);if(p.method==="POST"&&m===pe&&s){let g=await me(p);if(g.tooLarge)return new Response(JSON.stringify({message:"Payload too large"}),{status:413,headers:{"content-type":"application/json"}});let C=await s({headers:L(p.headers),body:g.json});return new Response(JSON.stringify(C.body),{status:C.status,headers:{"content-type":"application/json"}})}let R=de(m,e);if(!R){let g=o?o():"<!DOCTYPE html><html><body><h1>404 \u2014 Not Found</h1></body></html>";return new Response(g,{status:404,headers:k({"content-type":"text/html; charset=utf-8"})})}let{route:O,params:G}=R,X=O.page||{mode:O.mode||"client"},I={path:m,query:fe(h.search),config:X,route:O,params:G,request:p};if(r&&X.mode!=="server"){I.varyHeaders=L(p.headers);let g=await r.handle(I,()=>f(I));return new Response(g.html,{status:g.status||200,headers:k({"content-type":"text/html; charset=utf-8",...g.headers||{}})})}w&&(I.csrfToken=w);let Y=await f(I),St=k({"content-type":"text/html; charset=utf-8",...Y.headers||{}});return X.mode==="server"&&(St["Cache-Control"]="private, no-store"),new Response(Y.html,{status:Y.status||200,headers:St})}}function ge(t={}){let e=v(t);return{async fetch(r,n,s){return n&&(r.__env=n),s&&(r.__ctx=s),e(r)}}}function x(t){return{head:Se(),loaderData:t,resources:new Map,islandStores:new Map,resourceCounter:0,boundaryCounter:0,suspended:[]}}var xt=0;function be(){xt=0}function _e(){return"h"+xt++}function Re(t){if(!vt()){let e=x(void 0);return b(e,()=>Re(t))}return be(),A(t)}var Pt=new Set(["__errorBoundary","__suspense"]),dt=new Set(["__portal"]);function ft(t){let e=t.children;return!e||e.length===0?{...t.props}:{...t.props,children:e}}function lt(t,e){let r=t.props&&t.props.fallback;if(typeof r!="function")return r;let n=t.props&&t.props.reset||(()=>{});try{return r({error:e,reset:n})}catch(s){return _(s),$&&console.warn(`[what-server] <ErrorBoundary> fallback threw during SSR: ${s.message}`),null}}function A(t){if(t==null||t===!1||t===!0)return"";if(typeof t=="string"||typeof t=="number")return S(String(t));if(typeof t=="function"&&t._signal)return`<!--$-->${A(t())}<!--/$-->`;if(typeof t=="function"&&t._mapArray)try{return`<!--$-->${A(ct(t))}<!--/$-->`}catch(c){return _(c),typeof process<"u","<!--$--><!--/$-->"}if(typeof t=="function")try{return`<!--$-->${A(t())}<!--/$-->`}catch(c){return _(c),typeof process<"u","<!--$--><!--/$-->"}if(Array.isArray(t))return`<!--[]-->${t.map(A).join("")}<!--/[]-->`;if(dt.has(t.tag))return"";if(Pt.has(t.tag))try{return(t.children||[]).map(A).join("")}catch(c){_(c);let u=c&&typeof c.then=="function";if(u&&t.tag==="__errorBoundary"||!u&&t.tag==="__suspense")throw c;return A(lt(t,u?null:c))}if(typeof t.tag=="function"){let c=_e(),u=st(t.tag),d;try{d=A(t.tag(ft(t)))}finally{it(u)}return Ee(d,c)}let{tag:e,props:r,children:n}=t;ht(e,t);let s=mt(r||{}),a=`<${e}${s}>`;if(yt.has(e))return a;let o=pt(r),i=o!=null?String(o):n.map(A).join("");return`${a}${i}</${e}>`}function Ee(t,e){let r=t.match(/^((?:<!--.*?-->)*)<([a-zA-Z][a-zA-Z0-9-]*)/);if(r){let n=r[1],s=r[2],a=n.length+1+s.length,o=t.indexOf(">",a),i=t.slice(a,o===-1?void 0:o);return/[\s"']data-hk\s*=/.test(i)||/^\s*data-hk\s*=/.test(i)?t:t.slice(0,a)+` data-hk="${e}"`+t.slice(a)}return t}function y(t){if(!vt()){let c=x(void 0);return b(c,()=>y(t))}if(t==null||t===!1||t===!0)return"";if(typeof t=="string"||typeof t=="number")return S(String(t));if(typeof t=="function"&&t._signal)return y(t());if(typeof t=="function"&&t._mapArray)try{return y(ct(t))}catch(c){return _(c),typeof process<"u",""}if(typeof t=="function")try{return y(t())}catch(c){return _(c),typeof process<"u",""}if(Array.isArray(t))return t.map(y).join("");if(dt.has(t.tag))return"";if(Pt.has(t.tag))try{return(t.children||[]).map(y).join("")}catch(c){_(c);let u=c&&typeof c.then=="function";if(u&&t.tag==="__errorBoundary"||!u&&t.tag==="__suspense")throw c;return y(lt(t,u?null:c))}if(typeof t.tag=="function"){let c=st(t.tag);try{return y(t.tag(ft(t)))}finally{it(c)}}let{tag:e,props:r,children:n}=t;ht(e,t);let s=mt(r||{}),a=`<${e}${s}>`;if(yt.has(e))return a;let o=pt(r),i=o!=null?String(o):n.map(y).join("");return`${a}${i}</${e}>`}function _r(t){let e=x(void 0);return{body:b(e,()=>y(t)),head:ut(e.head)}}async function Rr(t,e={}){let r=t.default||t,n=typeof t.loader=="function"?await t.loader(e):void 0,s=x(n),a=e.params||{};return{body:b(s,()=>y(at(r,{...a,loaderData:n}))),head:ut(s.head),loaderData:n}}var $t=12;async function Ae(t,e){e||(e=x(void 0));let r="",n=e.resourceCounter;for(let a=0;a<$t;a++){e.resourceCounter=n,r=b(e,()=>y(t));let o=[...e.resources.values()].filter(i=>i.status==="pending").map(i=>i.promise);if(o.length===0)break;await Promise.all(o)}let s={};for(let[a,o]of e.resources)o.status==="ready"&&(s[a]=o.value);return{body:r,head:ut(e.head),loaderData:e.loaderData,resources:s,ctx:e}}async function W(t,e={},r={}){let n=t.default||t,s=typeof t.loader=="function"?await t.loader(e):void 0,a=x(s),o=e.params||{},{body:i,head:c,resources:u}=await Ae(at(n,{...o,loaderData:s}),a),d={loaderData:s??null,resources:u,islandStores:bt(a)};return Te({body:i,head:c,payload:d,options:r})}function Te({body:t,head:e,payload:r,options:n={}}){let s=n.lang||"en",a=`<script id="__what_data" type="application/json">${N(r)}<\/script>`,o=n.clientEntry?`<script type="module" src="${S(n.clientEntry)}"><\/script>`:"",c=(n.csrfToken?rt(n.csrfToken):"")+(n.head||""),u=n.bodyClass?` class="${S(n.bodyClass)}"`:"";return`<!DOCTYPE html><html lang="${S(s)}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">${e||""}${c}</head><body${u}>${t}${a}${o}</body></html>`}async function*P(t,e){if(e===void 0&&(e=x(void 0)),t==null||t===!1||t===!0)return;if(typeof t=="string"||typeof t=="number"){yield S(String(t));return}if(typeof t=="function"&&t._signal){let o=b(e,()=>t());yield*P(o,e);return}if(typeof t=="function"&&t._mapArray){let o=null;try{o=b(e,()=>ct(t))}catch(i){_(i),typeof process<"u"}o&&(yield*P(o,e));return}if(typeof t=="function"){try{let o=b(e,()=>t());yield*P(o,e)}catch(o){_(o),typeof process<"u"}return}if(Array.isArray(t)){for(let o of t)yield*P(o,e);return}if(dt.has(t.tag))return;if(t.tag==="__errorBoundary"){let o;try{o=b(e,()=>(t.children||[]).map(y).join(""))}catch(i){if(_(i),i&&typeof i.then=="function")throw i;o=b(e,()=>y(lt(t,i)))}yield o;return}if(t.tag==="__suspense"){let o=null,i=e.resourceCounter;for(let c=0;c<$t&&o===null;c++){e.resourceCounter=i;let u=null;try{o=b(e,()=>(t.children||[]).map(y).join(""))}catch(d){if(d&&typeof d.then=="function")u=d;else throw d}if(o===null){let d=[...e.resources.values()].filter(f=>f.status==="pending").map(f=>f.promise);await Promise.all([u,...d].filter(Boolean))}}o===null&&(o=b(e,()=>y(t.props&&t.props.fallback))),yield o;return}if(typeof t.tag=="function"){let o=st(t.tag);try{let i=b(e,()=>t.tag(ft(t))),c=i instanceof Promise?await i:i;yield*P(c,e)}catch(i){_(i),typeof process<"u",yield $?`<!-- SSR Error: ${S(i.message||"Component error")} -->`:"<!-- SSR Error -->"}finally{it(o)}return}let{tag:r,props:n,children:s}=t;ht(r,t);let a=mt(n||{});if(yield`<${r}${a}>`,!yt.has(r)){let o=pt(n);if(o!=null)yield String(o);else for(let i of s)yield*P(i,e);yield`</${r}>`}}function Er(t){return{mode:"static",...t}}function Ar(t,e={}){let r=x(e),n=b(r,()=>y(at(t.component,e))),s=t.islands||[];return ke({title:t.title||"",meta:t.meta||{},body:n,islands:s,scripts:t.mode==="static"?[]:t.scripts||[],styles:t.styles||[],mode:t.mode})}function ke({title:t,meta:e,body:r,islands:n,scripts:s,styles:a,mode:o}){let i=Object.entries(e).map(([l,p])=>`<meta name="${S(l)}" content="${S(p)}">`).join(`
|
|
2
|
+
`),c=a.map(l=>`<link rel="stylesheet" href="${S(l)}">`).join(`
|
|
3
3
|
`),u=n.length>0?`
|
|
4
4
|
<script type="module">
|
|
5
5
|
import { hydrateIslands } from '/@what/islands.js';
|
|
6
6
|
hydrateIslands();
|
|
7
|
-
<\/script>`:"",d=s.map(l=>`<script type="module" src="${
|
|
7
|
+
<\/script>`:"",d=s.map(l=>`<script type="module" src="${S(l)}"><\/script>`).join(`
|
|
8
8
|
`),f=o==="client"?`
|
|
9
9
|
<script type="module" src="/@what/client.js"><\/script>`:"";return`<!DOCTYPE html>
|
|
10
10
|
<html lang="en">
|
|
@@ -12,7 +12,7 @@ import{AsyncLocalStorage as ze}from"node:async_hooks";import{__installServerCont
|
|
|
12
12
|
<meta charset="UTF-8">
|
|
13
13
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
14
14
|
${i}
|
|
15
|
-
<title>${
|
|
15
|
+
<title>${S(t)}</title>
|
|
16
16
|
${c}
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
@@ -21,4 +21,4 @@ import{AsyncLocalStorage as ze}from"node:async_hooks";import{__installServerCont
|
|
|
21
21
|
${d}
|
|
22
22
|
${f}
|
|
23
23
|
</body>
|
|
24
|
-
</html>`}function Tr(t){return t._server=!0,t}var $=!(typeof process<"u");function pt(t){return t?t.dangerouslySetInnerHTML?t.dangerouslySetInnerHTML.__html??null:t.innerHTML&&typeof t.innerHTML=="object"&&"__html"in t.innerHTML?t.innerHTML.__html??null:(t.innerHTML!=null&&typeof t.innerHTML=="string"&&$&&console.warn("[what-server] innerHTML received a raw string. This is a security risk (XSS). Use innerHTML={{ __html: trustedString }} or dangerouslySetInnerHTML={{ __html: trustedString }} instead."),null):null}var Oe=/^[a-zA-Z_:][a-zA-Z0-9:._-]*$/,Ce=/^[a-zA-Z_][a-zA-Z0-9._:-]*$/;function _(t){if(t&&t.code==="ERR_COMPILED_JSX_IN_SSR")throw t}function ve(t){return!!t&&typeof t=="object"&&typeof t.nodeType=="number"}function ht(t,e){if(!(typeof t=="string"&&Ce.test(t)))throw ve(e)?Object.assign(new Error('[what-server] Cannot server-render a DOM node. A component compiled by what-compiler returns a cloned template (finished DOM), not a vnode, so it has no server-rendered form. Author server-rendered views with h(), or compile them with the automatic JSX runtime (jsxImportSource: "what-framework") instead of what-compiler.'),{code:"ERR_COMPILED_JSX_IN_SSR"}):Object.assign(new Error(`[what-server] Invalid tag name in SSR: ${JSON.stringify(t)}`),{code:"ERR_INVALID_SSR_TAG"})}function mt(t){let e="";for(let[r,n]of Object.entries(t)){if(r==="key"||r==="ref"||r==="children"||r==="dangerouslySetInnerHTML"||r==="innerHTML")continue;let s=r.toLowerCase();if(s.startsWith("on")&&r.length>2)continue;let a=n;if(typeof a=="function"){try{a=a()}catch(o){$&&console.warn(`[what-server] Skipping attribute ${JSON.stringify(r)}: its value threw during SSR: ${o.message}`);continue}if(typeof a=="function")continue}if(a===!1&&(we(r)||r.startsWith("data-"))){e+=` ${r}="false"`;continue}if(!(a===!1||a==null)){if(!Oe.test(r)){$&&console.warn(`[what-server] Skipping invalid attribute name in SSR: ${JSON.stringify(r)}`);continue}if($e.has(s)){$&&console.warn(`[what-server] Skipping unsafe attribute in SSR: ${JSON.stringify(r)}`);continue}if(r==="className"||r==="class")e+=` class="${
|
|
24
|
+
</html>`}function Tr(t){return t._server=!0,t}var $=!(typeof process<"u");function pt(t){return t?t.dangerouslySetInnerHTML?t.dangerouslySetInnerHTML.__html??null:t.innerHTML&&typeof t.innerHTML=="object"&&"__html"in t.innerHTML?t.innerHTML.__html??null:(t.innerHTML!=null&&typeof t.innerHTML=="string"&&$&&console.warn("[what-server] innerHTML received a raw string. This is a security risk (XSS). Use innerHTML={{ __html: trustedString }} or dangerouslySetInnerHTML={{ __html: trustedString }} instead."),null):null}var Oe=/^[a-zA-Z_:][a-zA-Z0-9:._-]*$/,Ce=/^[a-zA-Z_][a-zA-Z0-9._:-]*$/;function _(t){if(t&&t.code==="ERR_COMPILED_JSX_IN_SSR")throw t}function ve(t){return!!t&&typeof t=="object"&&typeof t.nodeType=="number"}function ht(t,e){if(!(typeof t=="string"&&Ce.test(t)))throw ve(e)?Object.assign(new Error('[what-server] Cannot server-render a DOM node. A component compiled by what-compiler returns a cloned template (finished DOM), not a vnode, so it has no server-rendered form. Author server-rendered views with h(), or compile them with the automatic JSX runtime (jsxImportSource: "what-framework") instead of what-compiler.'),{code:"ERR_COMPILED_JSX_IN_SSR"}):Object.assign(new Error(`[what-server] Invalid tag name in SSR: ${JSON.stringify(t)}`),{code:"ERR_INVALID_SSR_TAG"})}function mt(t){let e="";for(let[r,n]of Object.entries(t)){if(r==="key"||r==="ref"||r==="children"||r==="dangerouslySetInnerHTML"||r==="innerHTML")continue;let s=r.toLowerCase();if(s.startsWith("on")&&r.length>2)continue;let a=n;if(typeof a=="function"){try{a=a()}catch(o){$&&console.warn(`[what-server] Skipping attribute ${JSON.stringify(r)}: its value threw during SSR: ${o.message}`);continue}if(typeof a=="function")continue}if(a===!1&&(we(r)||r.startsWith("data-"))){e+=` ${r}="false"`;continue}if(!(a===!1||a==null)){if(!Oe.test(r)){$&&console.warn(`[what-server] Skipping invalid attribute name in SSR: ${JSON.stringify(r)}`);continue}if($e.has(s)){$&&console.warn(`[what-server] Skipping unsafe attribute in SSR: ${JSON.stringify(r)}`);continue}if(r==="className"||r==="class")e+=` class="${S(String(a))}"`;else if(r==="style"&&typeof a=="object"){let o=Object.entries(a).map(([i,c])=>`${Ie(i)}:${c}`).join(";");e+=` style="${S(o)}"`}else if(a===!0)r.startsWith("aria-")||r==="role"||r.startsWith("data-")?e+=` ${r}="true"`:e+=` ${r}`;else{if(xe(r,a))continue;e+=` ${r}="${S(String(a))}"`}}}return e}function xe(t,e){let r=t.toLowerCase();if(!Pe.has(r))return!1;let n=String(e).trim().replace(/[\u0000-\u001f\u007f\s]+/g,"").toLowerCase();return n.startsWith("javascript:")||n.startsWith("vbscript:")||n.startsWith("data:")}var Pe=new Set(["href","src","action","formaction","data","ping","xlink:href"]),$e=new Set(["srcdoc"]);function S(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function Ie(t){return t.startsWith("--")?t:t.replace(/([A-Z])/g,"-$1").toLowerCase()}var yt=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]);import Ne from"node:http";var gt=Symbol("what.bodyTooLarge"),It=()=>new Response(JSON.stringify({message:"Payload too large"}),{status:413,headers:{"content-type":"application/json"}});async function Nt(t){let r=`http://${t.headers.host||"localhost"}${t.url}`,n=new Headers;for(let[a,o]of Object.entries(t.headers))o!=null&&n.set(a,Array.isArray(o)?o.join(", "):String(o));let s;if(t.method!=="GET"&&t.method!=="HEAD"){let a=Number(t.headers["content-length"]),o=Number.isFinite(a)&&a>H,i=[],c=0;for await(let u of t)if(!o){if(c+=u.length,c>H){o=!0,i.length=0;continue}i.push(u)}if(o)return gt;i.length&&(s=Buffer.concat(i))}return new Request(r,{method:t.method,headers:n,body:s})}async function z(t,e){t.statusCode=e.status,e.headers.forEach((n,s)=>t.setHeader(s,n));let r=await e.text();t.end(r)}function jt(t){return async function(r,n){try{let s=await Nt(r);if(s===gt)return await z(n,It());let a=await t(s);await z(n,a)}catch(s){n.headersSent||n.writeHead(500,{"content-type":"text/html; charset=utf-8"}),n.end("<!DOCTYPE html><html><body><h1>500 \u2014 Server Error</h1></body></html>"),console.error("[what-server] request error:",s)}}}function je(t={}){let e=v(t);return async function(n,s,a){let o=await Nt(n);if(o===gt)return await z(s,It());let i=await e(o);if(i.status===404&&typeof a=="function")return a();await z(s,i)}}function He(t={}){let e=v(t),r=Ne.createServer(jt(e)),{scheduler:n}=t;if(n){n.start();let s=()=>{try{n.stop()}catch{}r.close()};process.once("SIGTERM",s),process.once("SIGINT",s)}return r}import{mkdir as De,writeFile as Ht}from"node:fs/promises";import{join as wt,resolve as Dt,sep as Le}from"node:path";import{matchRoute as Me}from"what-router/match";function Fe(t){return t.includes(":")||t.includes("*")||t.includes("[")}function Ue(t,e){return t.replace(/\[\.\.\.(\w+)\]/g,(r,n)=>e[n]??"").replace(/\[(\w+)\]/g,(r,n)=>e[n]??"").replace(/[:*](\w+)/g,(r,n)=>e[n]??"")}function Be(t,e){let r=Dt(t),n=Dt(wt(t,e==="/"?"":e));if(n!==r&&!n.startsWith(r+Le))throw Object.assign(new Error(`[what-server] Refusing to write outside outDir: ${e}`),{code:"ERR_STATIC_WRITE_ESCAPE"});return n}async function Je({routes:t=[],outDir:e,render:r,documentOptions:n={}}={}){let s=[];for(let a of t){let o=a.page&&a.page.mode||a.mode;if(o!=="static"&&o!=="hybrid")continue;let i=[a.path];if(Fe(a.path)){if(typeof a.getStaticPaths!="function")continue;i=((await a.getStaticPaths()).paths||[]).map(u=>Ue(a.path,u.params||{}))}for(let c of i){let u=Be(e,c),d=Me(c,[a]),l={params:d?d.params:{},query:{}},p={default:a.component,loader:a.loader},h=typeof p.loader=="function";if(h){let T=p.loader,k;p.loader=R=>k??=new Promise(O=>{O(T.call(p,R))})}let m=r?await r(p,l):await W(p,l,n),w=h?await p.loader(l):void 0;await De(u,{recursive:!0}),await Ht(wt(u,"index.html"),m),h&&await Ht(wt(u,"__what_data.json"),N({loaderData:w})),s.push(c)}}return{pages:s}}function Ve(t={}){return v(t)}async function We({outDir:t=".vercel/output",functionName:e="render",runtime:r="nodejs22.x",files:n=null,handler:s="index.mjs",staticDir:a=null}={}){let{mkdir:o,writeFile:i,cp:c}=await import("node:fs/promises"),{join:u,dirname:d}=await import("node:path");await o(t,{recursive:!0});let f={version:3,routes:[{handle:"filesystem"},{src:"/.*",dest:`/${e}`}]};await i(u(t,"config.json"),JSON.stringify(f,null,2)),a&&await c(a,u(t,"static"),{recursive:!0});let l=null;if(n&&typeof n=="object"){l=u(t,"functions",`${e}.func`),await o(l,{recursive:!0});let p={runtime:r,handler:s,launcherType:"Nodejs",shouldAddHelpers:!1,supportsResponseStreaming:!0};await i(u(l,".vc-config.json"),JSON.stringify(p,null,2));for(let[h,m]of Object.entries(n)){let w=u(l,h);await o(d(w),{recursive:!0}),await i(w,m)}s in n||console.warn(`[what-server] buildVercelOutput: files does not include the handler entry "${s}" \u2014 the deploy will 500 until your build emits it.`)}return{config:f,outDir:t,functionDir:l}}Ge(new ze);export{kt as ACTION_ENDPOINT,re as Form,Xt as action,We as buildVercelOutput,D as createActionHandler,ge as createCloudflareHandler,v as createRequestHandler,He as createServer,Ve as createVercelHandler,rt as csrfMetaTag,Er as definePage,Je as exportStatic,ue as fetchActionHandler,Et as formAction,et as generateCsrfToken,Ar as generateStaticPage,Qt as getRegisteredActions,Jt as getRevalidationHandler,F as handleActionRequest,Tt as invalidatePath,ie as nodeActionMiddleware,Zt as onRevalidate,W as renderDocument,Rr as renderPage,Re as renderToHydratableString,P as renderToStream,y as renderToString,Ae as renderToStringAsync,_r as renderToStringWithHead,Z as revalidatePath,Q as revalidateTag,N as serializeState,Tr as server,K as setRevalidationHandler,jt as toNodeListener,At as useAction,Yt as useFormAction,qt as useMutation,Kt as useOptimistic,Rt as validateCsrfToken,je as whatMiddleware};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "what-server",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.9",
|
|
4
4
|
"description": "What Framework - SSR, islands architecture, static generation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
"author": "ZVN DEV (https://zvndev.com)",
|
|
52
52
|
"license": "MIT",
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"what-core": "^0.13.
|
|
55
|
-
"what-router": "^0.13.
|
|
54
|
+
"what-core": "^0.13.9",
|
|
55
|
+
"what-router": "^0.13.9"
|
|
56
56
|
},
|
|
57
57
|
"peerDependenciesMeta": {
|
|
58
58
|
"what-router": {
|
package/src/adapter/static.js
CHANGED
|
@@ -50,8 +50,6 @@ export async function exportStatic({ routes = [], outDir, render, documentOption
|
|
|
50
50
|
const mode = (route.page && route.page.mode) || route.mode;
|
|
51
51
|
if (mode !== 'static' && mode !== 'hybrid') continue;
|
|
52
52
|
|
|
53
|
-
const pageModule = { default: route.component, loader: route.loader };
|
|
54
|
-
|
|
55
53
|
let concrete = [route.path];
|
|
56
54
|
if (isDynamic(route.path)) {
|
|
57
55
|
if (typeof route.getStaticPaths !== 'function') continue; // can't enumerate
|
|
@@ -64,18 +62,29 @@ export async function exportStatic({ routes = [], outDir, render, documentOption
|
|
|
64
62
|
const matched = matchRoute(urlPath, [route]);
|
|
65
63
|
const params = matched ? matched.params : {};
|
|
66
64
|
const reqCtx = { params, query: {} };
|
|
65
|
+
const pageModule = { default: route.component, loader: route.loader };
|
|
66
|
+
const hasLoader = typeof pageModule.loader === 'function';
|
|
67
|
+
// One snapshot per concrete page, shared with default/custom renderers
|
|
68
|
+
// and client navigation. Custom renderers may prepare the context first.
|
|
69
|
+
if (hasLoader) {
|
|
70
|
+
const loader = pageModule.loader;
|
|
71
|
+
let snapshot;
|
|
72
|
+
pageModule.loader = (context) => snapshot ??= new Promise((resolve) => {
|
|
73
|
+
resolve(loader.call(pageModule, context));
|
|
74
|
+
});
|
|
75
|
+
}
|
|
67
76
|
|
|
68
77
|
const html = render
|
|
69
78
|
? await render(pageModule, reqCtx)
|
|
70
79
|
: await renderDocument(pageModule, reqCtx, documentOptions);
|
|
80
|
+
const loaderData = hasLoader ? await pageModule.loader(reqCtx) : undefined;
|
|
71
81
|
|
|
72
82
|
await mkdir(dirPath, { recursive: true });
|
|
73
83
|
await writeFile(join(dirPath, 'index.html'), html);
|
|
74
84
|
|
|
75
85
|
// data.json for client-side navigation (loader data without a round-trip)
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
await writeFile(join(dirPath, '__what_data.json'), serializeState({ loaderData: data }));
|
|
86
|
+
if (hasLoader) {
|
|
87
|
+
await writeFile(join(dirPath, '__what_data.json'), serializeState({ loaderData }));
|
|
79
88
|
}
|
|
80
89
|
|
|
81
90
|
written.push(urlPath);
|