what-server 0.10.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -0
- package/dist/actions.min.js +1 -2
- package/dist/index.min.js +5 -6
- package/dist/islands.min.js +0 -1
- package/package.json +4 -4
- package/src/action-handler.js +208 -21
- package/src/adapter/cloudflare.js +1 -1
- package/src/adapter/core.js +104 -11
- package/src/adapter/vercel.js +74 -10
- package/src/index.js +21 -2
- package/src/revalidation-registry.js +2 -2
- package/dist/actions.js +0 -384
- package/dist/actions.js.map +0 -7
- package/dist/actions.min.js.map +0 -7
- package/dist/index.js +0 -1150
- package/dist/index.js.map +0 -7
- package/dist/index.min.js.map +0 -7
- package/dist/islands.js +0 -355
- package/dist/islands.js.map +0 -7
- package/dist/islands.min.js.map +0 -7
package/README.md
CHANGED
|
@@ -101,6 +101,154 @@ const submitForm = formAction(async (formData) => {
|
|
|
101
101
|
});
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
+
## Request Handler & CSRF (on by default)
|
|
105
|
+
|
|
106
|
+
`createRequestHandler` is the full-stack entry: route match → render → action
|
|
107
|
+
dispatch, as a Web-Fetch `(Request) => Response` handler.
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
import { createRequestHandler } from 'what-server';
|
|
111
|
+
|
|
112
|
+
const handle = createRequestHandler({ routes }); // CSRF protection is ON — zero config
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
How the default CSRF wiring works (double-submit cookie):
|
|
116
|
+
|
|
117
|
+
1. Every HTML response ensures a `what-csrf` cookie (`SameSite=Lax`, readable
|
|
118
|
+
by JS so the fetch client can echo it).
|
|
119
|
+
2. Uncached HTML renders also embed `<meta name="what-csrf-token">` with the
|
|
120
|
+
same token (ISR-cached pages skip the meta tag so a per-user token is never
|
|
121
|
+
baked into shared cache entries — clients read the cookie instead).
|
|
122
|
+
3. `POST /__what_action` validates the client-supplied token (`X-CSRF-Token`
|
|
123
|
+
header for fetch clients, `_csrf` form field for plain HTML forms) against
|
|
124
|
+
the cookie. Mismatch or missing token → `403`.
|
|
125
|
+
|
|
126
|
+
Opt out explicitly (e.g. token-authed APIs behind another gateway):
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
createRequestHandler({ routes, csrf: false });
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Passing your own `actionHandler` also disables the auto-provisioning — a
|
|
133
|
+
custom handler owns its CSRF policy via `createActionHandler({ getCsrfToken })`
|
|
134
|
+
or `{ skipCsrf: true }`.
|
|
135
|
+
|
|
136
|
+
### Plain HTML form posts (progressive enhancement)
|
|
137
|
+
|
|
138
|
+
`POST /__what_action` accepts `application/x-www-form-urlencoded` bodies, so
|
|
139
|
+
forms work without any client JavaScript:
|
|
140
|
+
|
|
141
|
+
```html
|
|
142
|
+
<form method="post" action="/__what_action">
|
|
143
|
+
<input type="hidden" name="_action" value="my-action-id">
|
|
144
|
+
<input type="hidden" name="_csrf" value="{token from the what-csrf-token meta tag}">
|
|
145
|
+
<input type="hidden" name="_redirect" value="/thanks">
|
|
146
|
+
<input name="email">
|
|
147
|
+
<button>Subscribe</button>
|
|
148
|
+
</form>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
- Action id: `_action` (or `data-action`) hidden field, or `?action=` query param.
|
|
152
|
+
- The action receives **one argument**: the form fields as a plain object
|
|
153
|
+
(reserved `_action` / `_csrf` / `_redirect` fields stripped; repeated field
|
|
154
|
+
names become arrays).
|
|
155
|
+
- Success responds `303 See Other` (POST/redirect/GET) to `_redirect` (must be
|
|
156
|
+
a local path), else the Referer path, else `/`.
|
|
157
|
+
- Failures respond with an HTML error page and a matching status (`403` bad
|
|
158
|
+
CSRF, `404` unknown action, `500` action error).
|
|
159
|
+
|
|
160
|
+
The JSON path is unchanged: fetch clients send `X-What-Action` + JSON
|
|
161
|
+
`{ args }` and get JSON back.
|
|
162
|
+
|
|
163
|
+
## Deploying
|
|
164
|
+
|
|
165
|
+
All four deploy adapters wrap the same Web-Fetch core (`createRequestHandler`),
|
|
166
|
+
so routes, actions, CSRF, and ISR behave identically everywhere. Each adapter
|
|
167
|
+
below is covered by `test/deploy-readiness.test.js`.
|
|
168
|
+
|
|
169
|
+
### Node (self-hosted: VPS, Docker, Fly, Railway)
|
|
170
|
+
|
|
171
|
+
```js
|
|
172
|
+
// server.js
|
|
173
|
+
import { createServer } from 'what-server';
|
|
174
|
+
import { routes } from './routes.js';
|
|
175
|
+
|
|
176
|
+
createServer({ routes }).listen(process.env.PORT || 3000);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Run `node server.js`. That's the deploy. `createServer` accepts the same
|
|
180
|
+
options as `createRequestHandler` (`cache` for ISR, `scheduler` for background
|
|
181
|
+
revalidation — the scheduler is stopped cleanly on SIGTERM/SIGINT). To mount
|
|
182
|
+
inside an existing Express/connect app use `whatMiddleware(options)` (calls
|
|
183
|
+
`next()` on 404), or convert any Web-Fetch handler with `toNodeListener(handler)`.
|
|
184
|
+
|
|
185
|
+
### Static export (any CDN: Nginx, S3, GitHub Pages, Netlify)
|
|
186
|
+
|
|
187
|
+
```js
|
|
188
|
+
import { exportStatic } from 'what-server';
|
|
189
|
+
const { pages } = await exportStatic({ routes, outDir: 'dist' });
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Renders every `static`/`hybrid` route to `dist/<path>/index.html` plus a
|
|
193
|
+
`__what_data.json` per page (loader data for client-side navigation). Dynamic
|
|
194
|
+
routes need `getStaticPaths`. Upload `dist/` to any static host — no special
|
|
195
|
+
server config required (the layout is plain `path/index.html`). Note: server
|
|
196
|
+
actions and per-user CSRF need a runtime — pair a static export with one of
|
|
197
|
+
the runtime adapters if you use actions.
|
|
198
|
+
|
|
199
|
+
### Vercel
|
|
200
|
+
|
|
201
|
+
```js
|
|
202
|
+
// build.mjs — emit a Build Output API v3 directory
|
|
203
|
+
import { buildVercelOutput } from 'what-server';
|
|
204
|
+
|
|
205
|
+
await buildVercelOutput({
|
|
206
|
+
files: { 'index.mjs': bundledHandlerCode }, // your build bundles routes + createVercelHandler into this
|
|
207
|
+
staticDir: 'public', // optional: CDN-served assets
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The function entry must export the Web-Fetch handler:
|
|
212
|
+
|
|
213
|
+
```js
|
|
214
|
+
// (bundled into index.mjs)
|
|
215
|
+
import { createVercelHandler } from 'what-server';
|
|
216
|
+
import { routes } from './routes.js';
|
|
217
|
+
export default createVercelHandler({ routes });
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Then deploy the prebuilt output: `vercel deploy --prebuilt`. The emitted
|
|
221
|
+
layout is `config.json` (version 3, filesystem-first routing) +
|
|
222
|
+
`functions/render.func/{.vc-config.json,index.mjs}` + `static/`. ISR maps to
|
|
223
|
+
Vercel's native `s-maxage`/`stale-while-revalidate` headers emitted by the
|
|
224
|
+
cache engine. Calling `buildVercelOutput()` without `files` writes
|
|
225
|
+
`config.json` only (your build step owns `functions/` — backward compatible).
|
|
226
|
+
|
|
227
|
+
### Cloudflare Workers
|
|
228
|
+
|
|
229
|
+
```js
|
|
230
|
+
// worker.js
|
|
231
|
+
import { createCloudflareHandler } from 'what-server';
|
|
232
|
+
import { routes } from './routes.js';
|
|
233
|
+
export default createCloudflareHandler({ routes });
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
```toml
|
|
237
|
+
# wrangler.toml
|
|
238
|
+
name = "my-what-app"
|
|
239
|
+
main = "worker.js"
|
|
240
|
+
compatibility_date = "2026-01-01"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
`wrangler dev` to verify locally, `wrangler deploy` to ship. The handler is a
|
|
244
|
+
standard ES module worker (`{ fetch(request, env, ctx) }`); `env`/`ctx` are
|
|
245
|
+
exposed to loaders/renderers as `request.__env` / `request.__ctx` for KV/D1
|
|
246
|
+
bindings and `ctx.waitUntil`. For ISR across isolates, pass a KV/redis-backed
|
|
247
|
+
`what-isr` store as `cache` (in-memory caches don't survive isolate recycling).
|
|
248
|
+
Manual verification step (workerd is not a repo dependency): run
|
|
249
|
+
`wrangler dev worker.js` and load `/` — module shape and request handling are
|
|
250
|
+
covered by automated tests.
|
|
251
|
+
|
|
104
252
|
## Sub-path Exports
|
|
105
253
|
|
|
106
254
|
| Path | Contents |
|
package/dist/actions.min.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
import{signal as p,batch as v}from"what-core";var h=null,k=!(typeof process<"u");async function S(e,t){if(h&&h.revalidatePath)return h.revalidatePath(e,t);k&&console.warn(`[what] revalidatePath('${e}') had no effect: no cache engine is bound. Create a what-
|
|
2
|
-
//# sourceMappingURL=actions.min.js.map
|
|
1
|
+
import{signal as p,batch as v}from"what-core";var h=null,k=!(typeof process<"u");async function S(e,t){if(h&&h.revalidatePath)return h.revalidatePath(e,t);k&&console.warn(`[what] revalidatePath('${e}') had no effect: no cache engine is bound. Create a what-isr engine and bind it in your adapter (setRevalidationHandler).`)}async function b(e,t){if(h&&h.revalidateTag)return h.revalidateTag(e,t);k&&console.warn(`[what] revalidateTag('${e}') had no effect: no cache engine is bound.`)}var A=new Map;function P(){if(typeof document<"u"){let e=document.querySelector('meta[name="what-csrf-token"]');if(e)return e.getAttribute("content");let t=document.cookie.match(/(?:^|;\s*)what-csrf=([^;]+)/);if(t)return decodeURIComponent(t[1])}return null}function I(){if(typeof crypto<"u"&&crypto.randomUUID)return crypto.randomUUID();if(typeof crypto<"u"&&crypto.getRandomValues){let e=new Uint8Array(16);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}throw new Error("[what] No secure random source available for CSRF token generation")}function R(e,t){if(!e||!t||e.length!==t.length)return!1;let r=0;for(let n=0;n<e.length;n++)r|=e.charCodeAt(n)^t.charCodeAt(n);return r===0}function U(e){return`<meta name="what-csrf-token" content="${String(e).replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}">`}var T=0;function C(){return`a_${typeof crypto<"u"&&crypto.getRandomValues?Array.from(crypto.getRandomValues(new Uint8Array(6)),t=>t.toString(16).padStart(2,"0")).join(""):`c${(++T).toString(36)}_${Date.now().toString(36)}`}`}function O(e,t={}){let r=t.id||C(),{onError:n,onSuccess:l,revalidate:o}=t;typeof window>"u"&&A.set(r,{fn:e,options:t});async function a(...i){if(typeof window>"u")return e(...i);let s=t.timeout||3e4,u=new AbortController,c=setTimeout(()=>u.abort(),s);try{let f=P(),d={"Content-Type":"application/json","X-What-Action":r};f&&(d["X-CSRF-Token"]=f);let g=await fetch("/__what_action",{method:"POST",headers:d,credentials:"same-origin",signal:u.signal,body:JSON.stringify({args:i})});if(!g.ok){let w=await g.json().catch(()=>({message:"Action failed"}));throw new Error(w.message||"Action failed")}let y=await g.json();if(l&&l(y),o)for(let w of o)_(w);return y}catch(f){if(f.name==="AbortError"){let d=new Error(`Action "${r}" timed out after ${s}ms`);throw d.code="TIMEOUT",n&&n(d),d}throw n&&n(f),f}finally{clearTimeout(c)}}return a._actionId=r,a._isAction=!0,a}function x(e,t={}){let{onSuccess:r,onError:n,resetOnSuccess:l=!0}=t;return async o=>{let a,i;o instanceof Event?(o.preventDefault(),i=o.target,a=new FormData(i)):a=o;let s={},u=!1;for(let[c,f]of a.entries())typeof File<"u"&&f instanceof File&&(u=!0),s[c]?Array.isArray(s[c])?s[c].push(f):s[c]=[s[c],f]:s[c]=f;try{let c=u?await e(s,a):await e(s);return r&&r(c,i),l&&i&&i.reset(),c}catch(c){throw n&&n(c,i),c}}}function F(e){let t=p(!1),r=p(null),n=p(null);async function l(...o){t.set(!0),r.set(null);try{let a=await e(...o);return n.set(a),a}catch(a){throw r.set(a),a}finally{t.set(!1)}}return{trigger:l,isPending:()=>t(),error:()=>r(),data:()=>n(),reset:()=>{r.set(null),n.set(null)}}}function j(e,t={}){let{resetOnSuccess:r=!0}=t,n={current:null},l=F(x(e,{resetOnSuccess:r}));function o(a){a.preventDefault();let i=new FormData(a.target);return n.current=a.target,l.trigger(i)}return{...l,handleSubmit:o,formRef:n}}function M(e,t){let r=p(e),n=p([]),l=p(e);function o(u){let c=t(r.peek(),u);v(()=>{n.set([...n.peek(),u]),r.set(c)})}function a(u,c){v(()=>{if(n.set(n.peek().filter(f=>f!==u)),c!==void 0){l.set(c);let f=c;for(let d of n.peek())f=t(f,d);r.set(f)}})}function i(u,c){v(()=>{let f=n.peek().filter(y=>y!==u);n.set(f);let d=c!==void 0?c:l.peek();l.set(d);let g=d;for(let y of f)g=t(g,y);r.set(g)})}async function s(u,c){o(u);try{let f=await c();return a(u,f),f}catch(f){throw i(u),f}}return{value:()=>r(),isPending:()=>n().length>0,addOptimistic:o,resolve:a,rollback:i,withOptimistic:s,set:u=>{r.set(u),l.set(u)}}}var m=new Map;function N(e,t){return m.has(e)||m.set(e,new Set),m.get(e).add(t),()=>{m.get(e)?.delete(t)}}function _(e){let t=m.get(e);if(t)for(let r of t)try{r()}catch(n){console.error("[what] Revalidation error:",n)}}function H(e,t,r,n={}){let{csrfToken:l,skipCsrf:o=!1}=n;if(!o){if(!l)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=e?.headers?.["x-csrf-token"]||e?.headers?.["X-CSRF-Token"];if(!R(i,l))return Promise.resolve({status:403,body:{message:"Invalid CSRF token"}})}let a=A.get(t);return a?Array.isArray(r)?a.fn(...r).then(async i=>{let s=a.options||{};if(Array.isArray(s.revalidate))for(let u of s.revalidate)await S(u);if(Array.isArray(s.revalidateTags))for(let u of s.revalidateTags)await b(u);return{status:200,body:i}}).catch(i=>(console.error(`[what] Action "${t}" 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 V(){return[...A.keys()]}function X(e,t={}){let{onSuccess:r,onError:n,onSettled:l}=t,o={isPending:p(!1),error:p(null),data:p(null)};async function a(...i){o.isPending.set(!0),o.error.set(null);try{let s=await e(...i);return o.data.set(s),r&&r(s,...i),s}catch(s){throw o.error.set(s),n&&n(s,...i),s}finally{o.isPending.set(!1),l&&l(o.data.peek(),o.error.peek(),...i)}}return{mutate:a,isPending:()=>o.isPending(),error:()=>o.error(),data:()=>o.data(),reset:()=>{o.error.set(null),o.data.set(null)}}}export{O as action,U as csrfMetaTag,x as formAction,I as generateCsrfToken,V as getRegisteredActions,H as handleActionRequest,_ as invalidatePath,N as onRevalidate,F as useAction,j as useFormAction,X as useMutation,M as useOptimistic,R as validateCsrfToken};
|
package/dist/index.min.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import{h as at,runWithServerContext as x,beginHeadCollection as Xt,endHeadCollection as U}from"what-core";var dt=new RegExp("[<>&\\u2028\\u2029]","g"),lt={60:"\\u003c",62:"\\u003e",38:"\\u0026",8232:"\\u2028",8233:"\\u2029"};function k(t){return JSON.stringify(t).replace(dt,e=>lt[e.charCodeAt(0)])}import{mount as ae,signal as ie,batch as ce}from"what-core";var ft=new Map;function X(){let t={};for(let[e,n]of ft)t[e]=n._getSnapshot();return t}import{signal as b,batch as D}from"what-core";var S=null,Y=!(typeof process<"u");function H(t){S=t}function pt(){return S}async function I(t,e){if(S&&S.revalidatePath)return S.revalidatePath(t,e);Y&&console.warn(`[what] revalidatePath('${t}') had no effect: no cache engine is bound. Create a what-cache engine and bind it in your adapter (setRevalidationHandler).`)}async function j(t,e){if(S&&S.revalidateTag)return S.revalidateTag(t,e);Y&&console.warn(`[what] revalidateTag('${t}') had no effect: no cache engine is bound.`)}var M=new Map;function ht(){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 mt(){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 new Error("[what] No secure random source available for CSRF token generation")}function G(t,e){if(!t||!e||t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=t.charCodeAt(r)^e.charCodeAt(r);return n===0}function yt(t){return`<meta name="what-csrf-token" content="${String(t).replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}">`}var gt=0;function wt(){return`a_${typeof crypto<"u"&&crypto.getRandomValues?Array.from(crypto.getRandomValues(new Uint8Array(6)),e=>e.toString(16).padStart(2,"0")).join(""):`c${(++gt).toString(36)}_${Date.now().toString(36)}`}`}function bt(t,e={}){let n=e.id||wt(),{onError:r,onSuccess:a,revalidate:o}=e;typeof window>"u"&&M.set(n,{fn:t,options:e});async function s(...i){if(typeof window>"u")return t(...i);let c=e.timeout||3e4,u=new AbortController,d=setTimeout(()=>u.abort(),c);try{let l=ht(),f={"Content-Type":"application/json","X-What-Action":n};l&&(f["X-CSRF-Token"]=l);let p=await fetch("/__what_action",{method:"POST",headers:f,credentials:"same-origin",signal:u.signal,body:JSON.stringify({args:i})});if(!p.ok){let g=await p.json().catch(()=>({message:"Action failed"}));throw new Error(g.message||"Action failed")}let m=await p.json();if(a&&a(m),o)for(let g of o)K(g);return m}catch(l){if(l.name==="AbortError"){let f=new Error(`Action "${n}" timed out after ${c}ms`);throw f.code="TIMEOUT",r&&r(f),f}throw r&&r(l),l}finally{clearTimeout(d)}}return s._actionId=n,s._isAction=!0,s}function Q(t,e={}){let{onSuccess:n,onError:r,resetOnSuccess:a=!0}=e;return async o=>{let s,i;o instanceof Event?(o.preventDefault(),i=o.target,s=new FormData(i)):s=o;let c={},u=!1;for(let[d,l]of s.entries())typeof File<"u"&&l instanceof File&&(u=!0),c[d]?Array.isArray(c[d])?c[d].push(l):c[d]=[c[d],l]:c[d]=l;try{let d=u?await t(c,s):await t(c);return n&&n(d,i),a&&i&&i.reset(),d}catch(d){throw r&&r(d,i),d}}}function q(t){let e=b(!1),n=b(null),r=b(null);async function a(...o){e.set(!0),n.set(null);try{let s=await t(...o);return r.set(s),s}catch(s){throw n.set(s),s}finally{e.set(!1)}}return{trigger:a,isPending:()=>e(),error:()=>n(),data:()=>r(),reset:()=>{n.set(null),r.set(null)}}}function St(t,e={}){let{resetOnSuccess:n=!0}=e,r={current:null},a=q(Q(t,{resetOnSuccess:n}));function o(s){s.preventDefault();let i=new FormData(s.target);return r.current=s.target,a.trigger(i)}return{...a,handleSubmit:o,formRef:r}}function At(t,e){let n=b(t),r=b([]),a=b(t);function o(u){let d=e(n.peek(),u);D(()=>{r.set([...r.peek(),u]),n.set(d)})}function s(u,d){D(()=>{if(r.set(r.peek().filter(l=>l!==u)),d!==void 0){a.set(d);let l=d;for(let f of r.peek())l=e(l,f);n.set(l)}})}function i(u,d){D(()=>{let l=r.peek().filter(m=>m!==u);r.set(l);let f=d!==void 0?d:a.peek();a.set(f);let p=f;for(let m of l)p=e(p,m);n.set(p)})}async function c(u,d){o(u);try{let l=await d();return s(u,l),l}catch(l){throw i(u),l}}return{value:()=>n(),isPending:()=>r().length>0,addOptimistic:o,resolve:s,rollback:i,withOptimistic:c,set:u=>{n.set(u),a.set(u)}}}var v=new Map;function Tt(t,e){return v.has(t)||v.set(t,new Set),v.get(t).add(e),()=>{v.get(t)?.delete(e)}}function K(t){let e=v.get(t);if(e)for(let n of e)try{n()}catch(r){console.error("[what] Revalidation error:",r)}}function N(t,e,n,r={}){let{csrfToken:a,skipCsrf:o=!1}=r;if(!o){if(!a)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(!G(i,a))return Promise.resolve({status:403,body:{message:"Invalid CSRF token"}})}let s=M.get(e);return s?Array.isArray(n)?s.fn(...n).then(async i=>{let c=s.options||{};if(Array.isArray(c.revalidate))for(let u of c.revalidate)await I(u);if(Array.isArray(c.revalidateTags))for(let u of c.revalidateTags)await j(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 _t(){return[...M.keys()]}function kt(t,e={}){let{onSuccess:n,onError:r,onSettled:a}=e,o={isPending:b(!1),error:b(null),data:b(null)};async function s(...i){o.isPending.set(!0),o.error.set(null);try{let c=await t(...i);return o.data.set(c),n&&n(c,...i),c}catch(c){throw o.error.set(c),r&&r(c,...i),c}finally{o.isPending.set(!1),a&&a(o.data.peek(),o.error.peek(),...i)}}return{mutate:s,isPending:()=>o.isPending(),error:()=>o.error(),data:()=>o.data(),reset:()=>{o.error.set(null),o.data.set(null)}}}var vt="/__what_action",Et=1024*1024;function Rt(t){if(!t)return{};if(typeof t.forEach=="function"&&typeof t.get=="function"){let n={};return t.forEach((r,a)=>{n[a.toLowerCase()]=r}),n}let e={};for(let n in t)e[n.toLowerCase()]=t[n];return e}function L(t,e){return{status:t,headers:{"content-type":"application/json"},body:JSON.stringify(e)}}function E(t={}){let{getCsrfToken:e,skipCsrf:n=!1}=t;return async function(a){if((a.method||"POST").toUpperCase()!=="POST")return L(405,{message:"Method Not Allowed"});let s=Rt(a.headers),i=s["x-what-action"];if(!i)return L(400,{message:"Missing X-What-Action header"});let u=(a.body||{}).args,d=n?void 0:e?await e(a):void 0,l=await N({headers:s},i,u,{csrfToken:d,skipCsrf:n});return L(l.status,l.body)}}function xt(t={}){let e=t.basePath||vt,n=E(t);return async function(a,o,s){if((a.url||"").split("?")[0]!==e||(a.method||"").toUpperCase()!=="POST")return s?s():void 0;let c;try{c=await Ct(a)}catch(d){o.writeHead(d.code==="BODY_TOO_LARGE"?413:400,{"content-type":"application/json"}),o.end(JSON.stringify({message:d.code==="BODY_TOO_LARGE"?"Payload too large":"Invalid JSON body"}));return}let u=await n({method:a.method,headers:a.headers,body:c});o.writeHead(u.status,u.headers),o.end(u.body)}}function Ct(t){return new Promise((e,n)=>{let r=0,a=[];t.on("data",o=>{if(r+=o.length,r>Et){let s=new Error("Body too large");s.code="BODY_TOO_LARGE",n(s),t.destroy?.();return}a.push(o)}),t.on("end",()=>{if(a.length===0)return e({});try{e(JSON.parse(Buffer.concat(a).toString("utf8")))}catch(o){n(o)}}),t.on("error",n)})}function Pt(t={}){let e=E(t);return async function(n){let r={};try{r=await n.json()}catch{r={}}let a=await e({method:n.method,headers:n.headers,body:r});return new Response(a.body,{status:a.status,headers:a.headers})}}import{matchRoute as $t,parseQuery as Ot}from"what-router/match";var Ht="/__what_action",It="/__what_revalidate";function Z(t){let e={};return t&&typeof t.forEach=="function"&&t.forEach((n,r)=>{e[r.toLowerCase()]=n}),e}async function tt(t){try{return await t.json()}catch{return{}}}function jt(t){return async function(n){let{route:r,params:a,query:o,request:s}=n,i={default:r.component,loader:r.loader};return{html:await P(i,{params:a,query:o,request:s},t),status:200,tags:n.config&&n.config.tags||[],path:n.path}}}function A(t={}){let{routes:e=[],cache:n,render:r,actionHandler:a=E({skipCsrf:!0}),revalidateWebhook:o,document:s={},notFound:i,basePath:c=""}=t,u=r||jt(s);return n&&(n.revalidatePath||n.revalidateTag)&&H({revalidatePath:n.revalidatePath,revalidateTag:n.revalidateTag}),async function(l){let f=new URL(l.url,"http://localhost"),p=f.pathname;if(c&&p.startsWith(c)&&(p=p.slice(c.length)||"/"),l.method==="POST"&&p===Ht){let w=await tt(l),T=await a({method:"POST",headers:Z(l.headers),body:w});return new Response(T.body,{status:T.status,headers:T.headers})}if(l.method==="POST"&&p===It&&o){let w=await tt(l),T=await o({headers:Z(l.headers),body:w});return new Response(JSON.stringify(T.body),{status:T.status,headers:{"content-type":"application/json"}})}let m=$t(p,e);if(!m){let w=i?i():"<!DOCTYPE html><html><body><h1>404 \u2014 Not Found</h1></body></html>";return new Response(w,{status:404,headers:{"content-type":"text/html; charset=utf-8"}})}let{route:g,params:ut}=m,$=g.page||{mode:g.mode||"client"},O={path:p,query:Ot(f.search),config:$,route:g,params:ut,request:l};if(n&&$.mode!=="server"){let w=await n.handle(O,()=>u(O));return new Response(w.html,{status:w.status||200,headers:{"content-type":"text/html; charset=utf-8",...w.headers||{}}})}let B=await u(O),z={"content-type":"text/html; charset=utf-8"};return $.mode==="server"&&(z["Cache-Control"]="private, no-store"),new Response(B.html,{status:B.status||200,headers:z})}}import Dt from"node:http";async function et(t){let n=`http://${t.headers.host||"localhost"}${t.url}`,r=new Headers;for(let[o,s]of Object.entries(t.headers))s!=null&&r.set(o,Array.isArray(s)?s.join(", "):String(s));let a;if(t.method!=="GET"&&t.method!=="HEAD"){let o=[];for await(let s of t)o.push(s);o.length&&(a=Buffer.concat(o))}return new Request(n,{method:t.method,headers:r,body:a})}async function nt(t,e){t.statusCode=e.status,e.headers.forEach((r,a)=>t.setHeader(a,r));let n=await e.text();t.end(n)}function rt(t){return async function(n,r){try{let a=await et(n),o=await t(a);await nt(r,o)}catch(a){r.headersSent||r.writeHead(500,{"content-type":"text/html; charset=utf-8"}),r.end("<!DOCTYPE html><html><body><h1>500 \u2014 Server Error</h1></body></html>"),console.error("[what-server] request error:",a)}}}function Mt(t={}){let e=A(t);return async function(r,a,o){let s=await et(r),i=await e(s);if(i.status===404&&typeof o=="function")return o();await nt(a,i)}}function Nt(t={}){let e=A(t),n=Dt.createServer(rt(e)),{scheduler:r}=t;if(r){r.start();let a=()=>{try{r.stop()}catch{}n.close()};process.once("SIGTERM",a),process.once("SIGINT",a)}return n}import{mkdir as Lt,writeFile as ot}from"node:fs/promises";import{join as F}from"node:path";import{matchRoute as Ft}from"what-router/match";function Ut(t){return t.includes(":")||t.includes("*")||t.includes("[")}function Vt(t,e){return t.replace(/\[\.\.\.(\w+)\]/g,(n,r)=>e[r]??"").replace(/\[(\w+)\]/g,(n,r)=>e[r]??"").replace(/[:*](\w+)/g,(n,r)=>e[r]??"")}async function Jt({routes:t=[],outDir:e,render:n,documentOptions:r={}}={}){let a=[];for(let o of t){let s=o.page&&o.page.mode||o.mode;if(s!=="static"&&s!=="hybrid")continue;let i={default:o.component,loader:o.loader},c=[o.path];if(Ut(o.path)){if(typeof o.getStaticPaths!="function")continue;c=((await o.getStaticPaths()).paths||[]).map(d=>Vt(o.path,d.params||{}))}for(let u of c){let d=Ft(u,[o]),f={params:d?d.params:{},query:{}},p=n?await n(i,f):await P(i,f,r),m=F(e,u==="/"?"":u);if(await Lt(m,{recursive:!0}),await ot(F(m,"index.html"),p),typeof o.loader=="function"){let g=await o.loader(f);await ot(F(m,"__what_data.json"),k({loaderData:g}))}a.push(u)}}return{pages:a}}function Wt(t={}){let e=A(t);return{async fetch(n,r,a){return r&&(n.__env=r),a&&(n.__ctx=a),e(n)}}}function Bt(t={}){return A(t)}async function zt({outDir:t=".vercel/output",functionName:e="render"}={}){let{mkdir:n,writeFile:r}=await import("node:fs/promises"),{join:a}=await import("node:path");await n(t,{recursive:!0});let o={version:3,routes:[{src:"/.*",dest:`/${e}`}]};return await r(a(t,"config.json"),JSON.stringify(o,null,2)),{config:o,outDir:t}}function C(t){return{head:Xt(),loaderData:t,resources:new Map,resourceCounter:0,boundaryCounter:0,suspended:[]}}var st=0;function Yt(){st=0}function Gt(){return"h"+st++}function De(t){return Yt(),_(t)}function _(t){if(t==null||t===!1||t===!0)return"";if(typeof t=="string"||typeof t=="number")return h(String(t));if(typeof t=="function"&&t._signal)return`<!--$-->${_(t())}<!--/$-->`;if(typeof t=="function")try{return`<!--$-->${_(t())}<!--/$-->`}catch{return typeof process<"u","<!--$--><!--/$-->"}if(Array.isArray(t))return`<!--[]-->${t.map(_).join("")}<!--/[]-->`;if(typeof t.tag=="function"){let c=Gt(),u=t.tag({...t.props,children:t.children}),d=_(u);return Qt(d,c)}let{tag:e,props:n,children:r}=t,a=J(n||{}),o=`<${e}${a}>`;if(W.has(e))return o;let s=V(n),i=s!=null?String(s):r.map(_).join("");return`${o}${i}</${e}>`}function Qt(t,e){let n=t.match(/^((?:<!--.*?-->)*)<([a-zA-Z][a-zA-Z0-9-]*)/);if(n){let r=n[1],a=n[2],o=r.length+1+a.length;return t.slice(0,o)+` data-hk="${e}"`+t.slice(o)}return t}function y(t){if(t==null||t===!1||t===!0)return"";if(typeof t=="string"||typeof t=="number")return h(String(t));if(typeof t=="function"&&t._signal)return y(t());if(typeof t=="function")try{return y(t())}catch{return typeof process<"u",""}if(Array.isArray(t))return t.map(y).join("");if(t.tag==="__suspense")try{return(t.children||[]).map(y).join("")}catch(c){if(c&&typeof c.then=="function")return y(t.props&&t.props.fallback);throw c}if(typeof t.tag=="function"){let c=t.tag({...t.props,children:t.children});return y(c)}let{tag:e,props:n,children:r}=t,a=J(n||{}),o=`<${e}${a}>`;if(W.has(e))return o;let s=V(n),i=s!=null?String(s):r.map(y).join("");return`${o}${i}</${e}>`}function Me(t){let e=C(void 0);return{body:x(e,()=>y(t)),head:U(e.head)}}async function Ne(t,e={}){let n=t.default||t,r=typeof t.loader=="function"?await t.loader(e):void 0,a=C(r),o=e.params||{};return{body:x(a,()=>y(at(n,{...o,loaderData:r}))),head:U(a.head),loaderData:r}}var it=12;async function qt(t,e){e||(e=C(void 0));let n="";for(let a=0;a<it;a++){n=x(e,()=>y(t));let o=[...e.resources.values()].filter(s=>s.status==="pending").map(s=>s.promise);if(o.length===0)break;await Promise.all(o)}let r={};for(let[a,o]of e.resources)o.status==="ready"&&(r[a]=o.value);return{body:n,head:U(e.head),loaderData:e.loaderData,resources:r,ctx:e}}async function P(t,e={},n={}){let r=t.default||t,a=typeof t.loader=="function"?await t.loader(e):void 0,o=C(a),s=e.params||{},{body:i,head:c,resources:u}=await qt(at(r,{...s,loaderData:a}),o),d={loaderData:a??null,resources:u,islandStores:X()};return Kt({body:i,head:c,payload:d,options:n})}function Kt({body:t,head:e,payload:n,options:r={}}){let a=r.lang||"en",o=`<script id="__what_data" type="application/json">${k(n)}<\/script>`,s=r.clientEntry?`<script type="module" src="${h(r.clientEntry)}"><\/script>`:"",i=r.head||"",c=r.bodyClass?` class="${h(r.bodyClass)}"`:"";return`<!DOCTYPE html><html lang="${h(a)}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">${e||""}${i}</head><body${c}>${t}${o}${s}</body></html>`}async function*R(t,e){if(e===void 0&&(e=C(void 0)),t==null||t===!1||t===!0)return;if(typeof t=="string"||typeof t=="number"){yield h(String(t));return}if(typeof t=="function"&&t._signal){yield*R(t(),e);return}if(typeof t=="function"){try{yield*R(t(),e)}catch{typeof process<"u"}return}if(Array.isArray(t)){for(let s of t)yield*R(s,e);return}if(t.tag==="__suspense"){let s=null;for(let i=0;i<it&&s===null;i++){let c=null;try{s=x(e,()=>(t.children||[]).map(y).join(""))}catch(u){if(u&&typeof u.then=="function")c=u;else throw u}if(s===null){let u=[...e.resources.values()].filter(d=>d.status==="pending").map(d=>d.promise);await Promise.all([c,...u].filter(Boolean))}}s===null&&(s=x(e,()=>y(t.props&&t.props.fallback))),yield s;return}if(typeof t.tag=="function"){try{let s=t.tag({...t.props,children:t.children}),i=s instanceof Promise?await s:s;yield*R(i,e)}catch(s){typeof process<"u",yield ct?`<!-- SSR Error: ${h(s.message||"Component error")} -->`:"<!-- SSR Error -->"}return}let{tag:n,props:r,children:a}=t,o=J(r||{});if(yield`<${n}${o}>`,!W.has(n)){let s=V(r);if(s!=null)yield String(s);else for(let i of a)yield*R(i,e);yield`</${n}>`}}function Le(t){return{mode:"static",...t}}function Fe(t,e={}){let n=t.component(e),r=y(n),a=t.islands||[];return Zt({title:t.title||"",meta:t.meta||{},body:r,islands:a,scripts:t.mode==="static"?[]:t.scripts||[],styles:t.styles||[],mode:t.mode})}function Zt({title:t,meta:e,body:n,islands:r,scripts:a,styles:o,mode:s}){let i=Object.entries(e).map(([f,p])=>`<meta name="${h(f)}" content="${h(p)}">`).join(`
|
|
2
|
-
`),c=
|
|
1
|
+
import{h as St,runWithServerContext as H,beginHeadCollection as ie,endHeadCollection as tt}from"what-core";var kt=new RegExp("[<>&\\u2028\\u2029]","g"),Rt={60:"\\u003c",62:"\\u003e",38:"\\u0026",8232:"\\u2028",8233:"\\u2029"};function x(t){return JSON.stringify(t).replace(kt,e=>Rt[e.charCodeAt(0)])}import{mount as Se,signal as Ae,batch as ke}from"what-core";var _t=new Map;function it(){let t={};for(let[e,n]of _t)t[e]=n._getSnapshot();return t}import{signal as S,batch as z}from"what-core";var A=null,ct=!(typeof process<"u");function V(t){A=t}function Ct(){return A}async function J(t,e){if(A&&A.revalidatePath)return A.revalidatePath(t,e);ct&&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 W(t,e){if(A&&A.revalidateTag)return A.revalidateTag(t,e);ct&&console.warn(`[what] revalidateTag('${t}') had no effect: no cache engine is bound.`)}var X=new Map;function Et(){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 Y(){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 new Error("[what] No secure random source available for CSRF token generation")}function ut(t,e){if(!t||!e||t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=t.charCodeAt(r)^e.charCodeAt(r);return n===0}function G(t){return`<meta name="what-csrf-token" content="${String(t).replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}">`}var vt=0;function xt(){return`a_${typeof crypto<"u"&&crypto.getRandomValues?Array.from(crypto.getRandomValues(new Uint8Array(6)),e=>e.toString(16).padStart(2,"0")).join(""):`c${(++vt).toString(36)}_${Date.now().toString(36)}`}`}function Pt(t,e={}){let n=e.id||xt(),{onError:r,onSuccess:o,revalidate:a}=e;typeof window>"u"&&X.set(n,{fn:t,options:e});async function s(...i){if(typeof window>"u")return t(...i);let c=e.timeout||3e4,u=new AbortController,d=setTimeout(()=>u.abort(),c);try{let l=Et(),f={"Content-Type":"application/json","X-What-Action":n};l&&(f["X-CSRF-Token"]=l);let p=await fetch("/__what_action",{method:"POST",headers:f,credentials:"same-origin",signal:u.signal,body:JSON.stringify({args:i})});if(!p.ok){let m=await p.json().catch(()=>({message:"Action failed"}));throw new Error(m.message||"Action failed")}let h=await p.json();if(o&&o(h),a)for(let m of a)ft(m);return h}catch(l){if(l.name==="AbortError"){let f=new Error(`Action "${n}" timed out after ${c}ms`);throw f.code="TIMEOUT",r&&r(f),f}throw r&&r(l),l}finally{clearTimeout(d)}}return s._actionId=n,s._isAction=!0,s}function dt(t,e={}){let{onSuccess:n,onError:r,resetOnSuccess:o=!0}=e;return async a=>{let s,i;a instanceof Event?(a.preventDefault(),i=a.target,s=new FormData(i)):s=a;let c={},u=!1;for(let[d,l]of s.entries())typeof File<"u"&&l instanceof File&&(u=!0),c[d]?Array.isArray(c[d])?c[d].push(l):c[d]=[c[d],l]:c[d]=l;try{let d=u?await t(c,s):await t(c);return n&&n(d,i),o&&i&&i.reset(),d}catch(d){throw r&&r(d,i),d}}}function lt(t){let e=S(!1),n=S(null),r=S(null);async function o(...a){e.set(!0),n.set(null);try{let s=await t(...a);return r.set(s),s}catch(s){throw n.set(s),s}finally{e.set(!1)}}return{trigger:o,isPending:()=>e(),error:()=>n(),data:()=>r(),reset:()=>{n.set(null),r.set(null)}}}function Ot(t,e={}){let{resetOnSuccess:n=!0}=e,r={current:null},o=lt(dt(t,{resetOnSuccess:n}));function a(s){s.preventDefault();let i=new FormData(s.target);return r.current=s.target,o.trigger(i)}return{...o,handleSubmit:a,formRef:r}}function $t(t,e){let n=S(t),r=S([]),o=S(t);function a(u){let d=e(n.peek(),u);z(()=>{r.set([...r.peek(),u]),n.set(d)})}function s(u,d){z(()=>{if(r.set(r.peek().filter(l=>l!==u)),d!==void 0){o.set(d);let l=d;for(let f of r.peek())l=e(l,f);n.set(l)}})}function i(u,d){z(()=>{let l=r.peek().filter(h=>h!==u);r.set(l);let f=d!==void 0?d:o.peek();o.set(f);let p=f;for(let h of l)p=e(p,h);n.set(p)})}async function c(u,d){a(u);try{let l=await d();return s(u,l),l}catch(l){throw i(u),l}}return{value:()=>n(),isPending:()=>r().length>0,addOptimistic:a,resolve:s,rollback:i,withOptimistic:c,set:u=>{n.set(u),o.set(u)}}}var P=new Map;function Ht(t,e){return P.has(t)||P.set(t,new Set),P.get(t).add(e),()=>{P.get(t)?.delete(e)}}function ft(t){let e=P.get(t);if(e)for(let n of e)try{n()}catch(r){console.error("[what] Revalidation error:",r)}}function L(t,e,n,r={}){let{csrfToken:o,skipCsrf:a=!1}=r;if(!a){if(!o)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(!ut(i,o))return Promise.resolve({status:403,body:{message:"Invalid CSRF token"}})}let s=X.get(e);return s?Array.isArray(n)?s.fn(...n).then(async i=>{let c=s.options||{};if(Array.isArray(c.revalidate))for(let u of c.revalidate)await J(u);if(Array.isArray(c.revalidateTags))for(let u of c.revalidateTags)await W(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 It(){return[...X.keys()]}function jt(t,e={}){let{onSuccess:n,onError:r,onSettled:o}=e,a={isPending:S(!1),error:S(null),data:S(null)};async function s(...i){a.isPending.set(!0),a.error.set(null);try{let c=await t(...i);return a.data.set(c),n&&n(c,...i),c}catch(c){throw a.error.set(c),r&&r(c,...i),c}finally{a.isPending.set(!1),o&&o(a.data.peek(),a.error.peek(),...i)}}return{mutate:s,isPending:()=>a.isPending(),error:()=>a.error(),data:()=>a.data(),reset:()=>{a.error.set(null),a.data.set(null)}}}var Lt="/__what_action",ht=1024*1024;function Nt(t){if(!t)return{};if(typeof t.forEach=="function"&&typeof t.get=="function"){let n={};return t.forEach((r,o)=>{n[o.toLowerCase()]=r}),n}let e={};for(let n in t)e[n.toLowerCase()]=t[n];return e}function N(t,e){return{status:t,headers:{"content-type":"application/json"},body:JSON.stringify(e)}}function Z(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 pt(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 Dt(t,e){let n=pt(t&&t._redirect);if(n)return n;let r=e.referer||e.referrer;if(r)try{let o=new URL(r,"http://localhost"),a=pt(o.pathname+o.search);if(a)return a}catch{}return"/"}var Mt=new Set(["_action","data-action","_csrf","what-csrf-token","_redirect"]);function O(t={}){let{getCsrfToken:e,skipCsrf:n=!1}=t;return async function(o){if((o.method||"POST").toUpperCase()!=="POST")return N(405,{message:"Method Not Allowed"});let s=Nt(o.headers),i=s["x-what-action"],c=s["content-type"]||"",u=!i&&c.includes("application/x-www-form-urlencoded"),d=n?void 0:e?await e(o):void 0;if(u){let h=o.body||{},m=h._action||h["data-action"]||o.query&&o.query.action;if(!m)return Z(400,'Missing action name (add a hidden "_action" field or ?action= query param)');let w={...s},_=h._csrf??h["what-csrf-token"];if(_&&!w["x-csrf-token"]&&(w["x-csrf-token"]=String(_)),!n&&e&&!d)return Z(403,"Missing CSRF token");let C={};for(let[E,U]of Object.entries(h))Mt.has(E)||(C[E]=U);let R=await L({headers:w},m,[C],{csrfToken:d,skipCsrf:n});return R.status===200?{status:303,headers:{location:Dt(h,s)},body:""}:Z(R.status,R.body&&R.body.message||"Action failed")}if(!i)return N(400,{message:"Missing X-What-Action header"});if(!n&&e&&!d)return N(403,{message:"Missing CSRF token"});let f=(o.body||{}).args,p=await L({headers:s},i,f,{csrfToken:d,skipCsrf:n});return N(p.status,p.body)}}function Ft(t={}){let e=t.basePath||Lt,n=O(t);return async function(o,a,s){let[i,c]=(o.url||"").split("?");if(i!==e||(o.method||"").toUpperCase()!=="POST")return s?s():void 0;let u;try{let f=await Ut(o);u=D(f,o.headers["content-type"]||"")}catch(f){a.writeHead(f.code==="BODY_TOO_LARGE"?413:400,{"content-type":"application/json"}),a.end(JSON.stringify({message:f.code==="BODY_TOO_LARGE"?"Payload too large":"Invalid request body"}));return}let d=Object.fromEntries(new URLSearchParams(c||"")),l=await n({method:o.method,headers:o.headers,body:u,query:d});a.writeHead(l.status,l.headers),a.end(l.body)}}function D(t,e){if((e||"").includes("application/x-www-form-urlencoded")){let n={};for(let[r,o]of new URLSearchParams(String(t)))n[r]===void 0?n[r]=o:Array.isArray(n[r])?n[r].push(o):n[r]=[n[r],o];return n}return t==null||t===""?{}:JSON.parse(String(t))}async function K(t,e=ht){let n=Number(t.headers.get("content-length"));if(Number.isFinite(n)&&n>e)return{tooLarge:!0};let r=t.body;if(!r||typeof r.getReader!="function"){let i=await t.text();return Buffer.byteLength(i,"utf8")>e?{tooLarge:!0}:{raw:i}}let o=r.getReader(),a=[],s=0;for(;;){let{done:i,value:c}=await o.read();if(i)break;if(c){if(s+=c.byteLength,s>e){try{await o.cancel()}catch{}return{tooLarge:!0}}a.push(c)}}return{raw:Buffer.concat(a.map(i=>Buffer.from(i))).toString("utf8")}}function Ut(t){return new Promise((e,n)=>{let r=0,o=[];t.on("data",a=>{if(r+=a.length,r>ht){let s=new Error("Body too large");s.code="BODY_TOO_LARGE",n(s),t.destroy?.();return}o.push(a)}),t.on("end",()=>{if(o.length===0)return e("");e(Buffer.concat(o).toString("utf8"))}),t.on("error",n)})}function Bt(t={}){let e=O(t);return async function(n){let r={};try{let s=await K(n);if(s.tooLarge)return new Response(JSON.stringify({message:"Payload too large"}),{status:413,headers:{"content-type":"application/json"}});r=D(s.raw,n.headers.get("content-type")||"")}catch{r={}}let o={};try{o=Object.fromEntries(new URL(n.url,"http://localhost").searchParams)}catch{}let a=await e({method:n.method,headers:n.headers,body:r,query:o});return new Response(a.body,{status:a.status,headers:a.headers})}}import{matchRoute as Vt,parseQuery as Jt}from"what-router/match";var Wt="/__what_action",zt="/__what_revalidate",Q="what-csrf";function M(t){let e={};return t&&typeof t.forEach=="function"&&t.forEach((n,r)=>{e[r.toLowerCase()]=n}),e}function mt(t,e){if(!t)return null;let n=String(t).match(new RegExp(`(?:^|;\\s*)${e}=([^;]+)`));return n?decodeURIComponent(n[1]):null}async function Xt(t){try{let e=await K(t);return e.tooLarge?{tooLarge:!0}:D(e.raw,t.headers.get("content-type")||"")}catch{return{}}}async function Yt(t){try{return await t.json()}catch{return{}}}function Gt(t){return async function(n){let{route:r,params:o,query:a,request:s}=n,i={default:r.component,loader:r.loader},c=n.csrfToken?{...t,csrfToken:n.csrfToken}:t;return{html:await F(i,{params:o,query:a,request:s},c),status:200,tags:n.config&&n.config.tags||[],path:n.path}}}function k(t={}){let{routes:e=[],cache:n,render:r,revalidateWebhook:o,document:a={},notFound:s,basePath:i="",csrf:c=!0}=t,u=c!==!1&&!t.actionHandler,d=t.actionHandler||O(u?{getCsrfToken:f=>mt(f.headers&&f.headers.cookie,Q)}:{skipCsrf:!0}),l=r||Gt(a);return n&&(n.revalidatePath||n.revalidateTag)&&V({revalidatePath:n.revalidatePath,revalidateTag:n.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===Wt){let y=await Xt(p);if(y&&y.tooLarge)return new Response(JSON.stringify({message:"Payload too large"}),{status:413,headers:{"content-type":"application/json"}});let T=await d({method:"POST",headers:M(p.headers),body:y,query:Object.fromEntries(h.searchParams)});return new Response(T.body,{status:T.status,headers:T.headers})}let w=null,_=null;if(u&&(w=mt(M(p.headers).cookie,Q),!w)){w=Y();let T=M(p.headers)["x-forwarded-proto"]==="https"||h.protocol==="https:"||!0;_=`${Q}=${encodeURIComponent(w)}; Path=/; SameSite=Lax`+(T?"; Secure":"")}let C=y=>(_&&(y["set-cookie"]=_),y);if(p.method==="POST"&&m===zt&&o){let y=await Yt(p),T=await o({headers:M(p.headers),body:y});return new Response(JSON.stringify(T.body),{status:T.status,headers:{"content-type":"application/json"}})}let R=Vt(m,e);if(!R){let y=s?s():"<!DOCTYPE html><html><body><h1>404 \u2014 Not Found</h1></body></html>";return new Response(y,{status:404,headers:C({"content-type":"text/html; charset=utf-8"})})}let{route:E,params:U}=R,B=E.page||{mode:E.mode||"client"},j={path:m,query:Jt(h.search),config:B,route:E,params:U,request:p};if(n&&B.mode!=="server"){let y=await n.handle(j,()=>l(j));return new Response(y.html,{status:y.status||200,headers:C({"content-type":"text/html; charset=utf-8",...y.headers||{}})})}w&&(j.csrfToken=w);let at=await l(j),st=C({"content-type":"text/html; charset=utf-8"});return B.mode==="server"&&(st["Cache-Control"]="private, no-store"),new Response(at.html,{status:at.status||200,headers:st})}}import Zt from"node:http";async function yt(t){let n=`http://${t.headers.host||"localhost"}${t.url}`,r=new Headers;for(let[a,s]of Object.entries(t.headers))s!=null&&r.set(a,Array.isArray(s)?s.join(", "):String(s));let o;if(t.method!=="GET"&&t.method!=="HEAD"){let a=[];for await(let s of t)a.push(s);a.length&&(o=Buffer.concat(a))}return new Request(n,{method:t.method,headers:r,body:o})}async function gt(t,e){t.statusCode=e.status,e.headers.forEach((r,o)=>t.setHeader(o,r));let n=await e.text();t.end(n)}function wt(t){return async function(n,r){try{let o=await yt(n),a=await t(o);await gt(r,a)}catch(o){r.headersSent||r.writeHead(500,{"content-type":"text/html; charset=utf-8"}),r.end("<!DOCTYPE html><html><body><h1>500 \u2014 Server Error</h1></body></html>"),console.error("[what-server] request error:",o)}}}function Kt(t={}){let e=k(t);return async function(r,o,a){let s=await yt(r),i=await e(s);if(i.status===404&&typeof a=="function")return a();await gt(o,i)}}function Qt(t={}){let e=k(t),n=Zt.createServer(wt(e)),{scheduler:r}=t;if(r){r.start();let o=()=>{try{r.stop()}catch{}n.close()};process.once("SIGTERM",o),process.once("SIGINT",o)}return n}import{mkdir as qt,writeFile as bt}from"node:fs/promises";import{join as q}from"node:path";import{matchRoute as te}from"what-router/match";function ee(t){return t.includes(":")||t.includes("*")||t.includes("[")}function ne(t,e){return t.replace(/\[\.\.\.(\w+)\]/g,(n,r)=>e[r]??"").replace(/\[(\w+)\]/g,(n,r)=>e[r]??"").replace(/[:*](\w+)/g,(n,r)=>e[r]??"")}async function re({routes:t=[],outDir:e,render:n,documentOptions:r={}}={}){let o=[];for(let a of t){let s=a.page&&a.page.mode||a.mode;if(s!=="static"&&s!=="hybrid")continue;let i={default:a.component,loader:a.loader},c=[a.path];if(ee(a.path)){if(typeof a.getStaticPaths!="function")continue;c=((await a.getStaticPaths()).paths||[]).map(d=>ne(a.path,d.params||{}))}for(let u of c){let d=te(u,[a]),f={params:d?d.params:{},query:{}},p=n?await n(i,f):await F(i,f,r),h=q(e,u==="/"?"":u);if(await qt(h,{recursive:!0}),await bt(q(h,"index.html"),p),typeof a.loader=="function"){let m=await a.loader(f);await bt(q(h,"__what_data.json"),x({loaderData:m}))}o.push(u)}}return{pages:o}}function oe(t={}){let e=k(t);return{async fetch(n,r,o){return r&&(n.__env=r),o&&(n.__ctx=o),e(n)}}}function ae(t={}){return k(t)}async function se({outDir:t=".vercel/output",functionName:e="render",runtime:n="nodejs22.x",files:r=null,handler:o="index.mjs",staticDir:a=null}={}){let{mkdir:s,writeFile:i,cp:c}=await import("node:fs/promises"),{join:u,dirname:d}=await import("node:path");await s(t,{recursive:!0});let l={version:3,routes:[{handle:"filesystem"},{src:"/.*",dest:`/${e}`}]};await i(u(t,"config.json"),JSON.stringify(l,null,2)),a&&await c(a,u(t,"static"),{recursive:!0});let f=null;if(r&&typeof r=="object"){f=u(t,"functions",`${e}.func`),await s(f,{recursive:!0});let p={runtime:n,handler:o,launcherType:"Nodejs",shouldAddHelpers:!1,supportsResponseStreaming:!0};await i(u(f,".vc-config.json"),JSON.stringify(p,null,2));for(let[h,m]of Object.entries(r)){let w=u(f,h);await s(d(w),{recursive:!0}),await i(w,m)}o in r||console.warn(`[what-server] buildVercelOutput: files does not include the handler entry "${o}" \u2014 the deploy will 500 until your build emits it.`)}return{config:l,outDir:t,functionDir:f}}function I(t){return{head:ie(),loaderData:t,resources:new Map,resourceCounter:0,boundaryCounter:0,suspended:[]}}var Tt=0;function ce(){Tt=0}function ue(){return"h"+Tt++}function qe(t){return ce(),v(t)}function v(t){if(t==null||t===!1||t===!0)return"";if(typeof t=="string"||typeof t=="number")return g(String(t));if(typeof t=="function"&&t._signal)return`<!--$-->${v(t())}<!--/$-->`;if(typeof t=="function")try{return`<!--$-->${v(t())}<!--/$-->`}catch{return typeof process<"u","<!--$--><!--/$-->"}if(Array.isArray(t))return`<!--[]-->${t.map(v).join("")}<!--/[]-->`;if(typeof t.tag=="function"){let c=ue(),u=t.tag({...t.props,children:t.children}),d=v(u);return de(d,c)}let{tag:e,props:n,children:r}=t,o=rt(n||{}),a=`<${e}${o}>`;if(ot.has(e))return a;let s=nt(n),i=s!=null?String(s):r.map(v).join("");return`${a}${i}</${e}>`}function de(t,e){let n=t.match(/^((?:<!--.*?-->)*)<([a-zA-Z][a-zA-Z0-9-]*)/);if(n){let r=n[1],o=n[2],a=r.length+1+o.length;return t.slice(0,a)+` data-hk="${e}"`+t.slice(a)}return t}function b(t){if(t==null||t===!1||t===!0)return"";if(typeof t=="string"||typeof t=="number")return g(String(t));if(typeof t=="function"&&t._signal)return b(t());if(typeof t=="function")try{return b(t())}catch{return typeof process<"u",""}if(Array.isArray(t))return t.map(b).join("");if(t.tag==="__suspense")try{return(t.children||[]).map(b).join("")}catch(c){if(c&&typeof c.then=="function")return b(t.props&&t.props.fallback);throw c}if(typeof t.tag=="function"){let c=t.tag({...t.props,children:t.children});return b(c)}let{tag:e,props:n,children:r}=t,o=rt(n||{}),a=`<${e}${o}>`;if(ot.has(e))return a;let s=nt(n),i=s!=null?String(s):r.map(b).join("");return`${a}${i}</${e}>`}function tn(t){let e=I(void 0);return{body:H(e,()=>b(t)),head:tt(e.head)}}async function en(t,e={}){let n=t.default||t,r=typeof t.loader=="function"?await t.loader(e):void 0,o=I(r),a=e.params||{};return{body:H(o,()=>b(St(n,{...a,loaderData:r}))),head:tt(o.head),loaderData:r}}var At=12;async function le(t,e){e||(e=I(void 0));let n="";for(let o=0;o<At;o++){n=H(e,()=>b(t));let a=[...e.resources.values()].filter(s=>s.status==="pending").map(s=>s.promise);if(a.length===0)break;await Promise.all(a)}let r={};for(let[o,a]of e.resources)a.status==="ready"&&(r[o]=a.value);return{body:n,head:tt(e.head),loaderData:e.loaderData,resources:r,ctx:e}}async function F(t,e={},n={}){let r=t.default||t,o=typeof t.loader=="function"?await t.loader(e):void 0,a=I(o),s=e.params||{},{body:i,head:c,resources:u}=await le(St(r,{...s,loaderData:o}),a),d={loaderData:o??null,resources:u,islandStores:it()};return fe({body:i,head:c,payload:d,options:n})}function fe({body:t,head:e,payload:n,options:r={}}){let o=r.lang||"en",a=`<script id="__what_data" type="application/json">${x(n)}<\/script>`,s=r.clientEntry?`<script type="module" src="${g(r.clientEntry)}"><\/script>`:"",c=(r.csrfToken?G(r.csrfToken):"")+(r.head||""),u=r.bodyClass?` class="${g(r.bodyClass)}"`:"";return`<!DOCTYPE html><html lang="${g(o)}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">${e||""}${c}</head><body${u}>${t}${a}${s}</body></html>`}async function*$(t,e){if(e===void 0&&(e=I(void 0)),t==null||t===!1||t===!0)return;if(typeof t=="string"||typeof t=="number"){yield g(String(t));return}if(typeof t=="function"&&t._signal){yield*$(t(),e);return}if(typeof t=="function"){try{yield*$(t(),e)}catch{typeof process<"u"}return}if(Array.isArray(t)){for(let s of t)yield*$(s,e);return}if(t.tag==="__suspense"){let s=null;for(let i=0;i<At&&s===null;i++){let c=null;try{s=H(e,()=>(t.children||[]).map(b).join(""))}catch(u){if(u&&typeof u.then=="function")c=u;else throw u}if(s===null){let u=[...e.resources.values()].filter(d=>d.status==="pending").map(d=>d.promise);await Promise.all([c,...u].filter(Boolean))}}s===null&&(s=H(e,()=>b(t.props&&t.props.fallback))),yield s;return}if(typeof t.tag=="function"){try{let s=t.tag({...t.props,children:t.children}),i=s instanceof Promise?await s:s;yield*$(i,e)}catch(s){typeof process<"u",yield et?`<!-- SSR Error: ${g(s.message||"Component error")} -->`:"<!-- SSR Error -->"}return}let{tag:n,props:r,children:o}=t,a=rt(r||{});if(yield`<${n}${a}>`,!ot.has(n)){let s=nt(r);if(s!=null)yield String(s);else for(let i of o)yield*$(i,e);yield`</${n}>`}}function nn(t){return{mode:"static",...t}}function rn(t,e={}){let n=t.component(e),r=b(n),o=t.islands||[];return pe({title:t.title||"",meta:t.meta||{},body:r,islands:o,scripts:t.mode==="static"?[]:t.scripts||[],styles:t.styles||[],mode:t.mode})}function pe({title:t,meta:e,body:n,islands:r,scripts:o,styles:a,mode:s}){let i=Object.entries(e).map(([f,p])=>`<meta name="${g(f)}" content="${g(p)}">`).join(`
|
|
2
|
+
`),c=a.map(f=>`<link rel="stylesheet" href="${g(f)}">`).join(`
|
|
3
3
|
`),u=r.length>0?`
|
|
4
4
|
<script type="module">
|
|
5
5
|
import { hydrateIslands } from '/@what/islands.js';
|
|
6
6
|
hydrateIslands();
|
|
7
|
-
<\/script>`:"",d=
|
|
7
|
+
<\/script>`:"",d=o.map(f=>`<script type="module" src="${g(f)}"><\/script>`).join(`
|
|
8
8
|
`),l=s==="client"?`
|
|
9
9
|
<script type="module" src="/@what/client.js"><\/script>`:"";return`<!DOCTYPE html>
|
|
10
10
|
<html lang="en">
|
|
@@ -12,7 +12,7 @@ import{h as at,runWithServerContext as x,beginHeadCollection as Xt,endHeadCollec
|
|
|
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>${g(t)}</title>
|
|
16
16
|
${c}
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
@@ -21,5 +21,4 @@ import{h as at,runWithServerContext as x,beginHeadCollection as Xt,endHeadCollec
|
|
|
21
21
|
${d}
|
|
22
22
|
${l}
|
|
23
23
|
</body>
|
|
24
|
-
</html>`}function
|
|
25
|
-
//# sourceMappingURL=index.min.js.map
|
|
24
|
+
</html>`}function on(t){return t._server=!0,t}var et=!(typeof process<"u");function nt(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"&&et&&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 he=/^[a-zA-Z_:][a-zA-Z0-9:._-]*$/;function rt(t){let e="";for(let[n,r]of Object.entries(t))if(!(n==="key"||n==="ref"||n==="children"||n==="dangerouslySetInnerHTML"||n==="innerHTML")&&!(n.startsWith("on")&&n.length>2)&&!(r===!1||r==null)){if(!he.test(n)){et&&console.warn(`[what-server] Skipping invalid attribute name in SSR: ${JSON.stringify(n)}`);continue}if(n==="className"||n==="class")e+=` class="${g(String(r))}"`;else if(n==="style"&&typeof r=="object"){let o=Object.entries(r).map(([a,s])=>`${ge(a)}:${s}`).join(";");e+=` style="${g(o)}"`}else if(r===!0)n.startsWith("aria-")||n==="role"?e+=` ${n}="true"`:e+=` ${n}`;else{if(me(n,r))continue;e+=` ${n}="${g(String(r))}"`}}return e}function me(t,e){let n=t.toLowerCase();if(!ye.has(n))return!1;let r=String(e).trim().replace(/[\u0000-\u001f\u007f\s]+/g,"").toLowerCase();return r.startsWith("javascript:")||r.startsWith("vbscript:")||r.startsWith("data:")}var ye=new Set(["href","src","action","formaction","xlink:href"]);function g(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function ge(t){return t.startsWith("--")?t:t.replace(/([A-Z])/g,"-$1").toLowerCase()}var ot=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]);export{Pt as action,se as buildVercelOutput,O as createActionHandler,oe as createCloudflareHandler,k as createRequestHandler,Qt as createServer,ae as createVercelHandler,G as csrfMetaTag,nn as definePage,re as exportStatic,Bt as fetchActionHandler,dt as formAction,Y as generateCsrfToken,rn as generateStaticPage,It as getRegisteredActions,Ct as getRevalidationHandler,L as handleActionRequest,ft as invalidatePath,Ft as nodeActionMiddleware,Ht as onRevalidate,F as renderDocument,en as renderPage,qe as renderToHydratableString,$ as renderToStream,b as renderToString,le as renderToStringAsync,tn as renderToStringWithHead,J as revalidatePath,W as revalidateTag,x as serializeState,on as server,V as setRevalidationHandler,wt as toNodeListener,lt as useAction,Ot as useFormAction,jt as useMutation,$t as useOptimistic,ut as validateCsrfToken,Kt as whatMiddleware};
|
package/dist/islands.min.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
1
|
import{mount as C,signal as O,batch as S}from"what-core";var E=new RegExp("[<>&\\u2028\\u2029]","g"),I={60:"\\u003c",62:"\\u003e",38:"\\u0026",8232:"\\u2028",8233:"\\u2029"};function v(e){return JSON.stringify(e).replace(E,o=>I[o.charCodeAt(0)])}var y=new Map,m=new Set,l=[],b=!1,p=new Map;function q(e,o){if(p.has(e))return p.get(e);let t={},s={};for(let[n,r]of Object.entries(o))s[n]=O(r),Object.defineProperty(t,n,{get:()=>s[n](),set:a=>s[n].set(a),enumerable:!0});return t._signals=s,t._subscribe=(n,r)=>{if(s[n])return s[n].subscribe(r)},t._batch=n=>S(n),t._getSnapshot=()=>{let n={};for(let[r,a]of Object.entries(s))n[r]=a.peek();return n},t._hydrate=n=>{S(()=>{for(let[r,a]of Object.entries(n))s[r]&&s[r].set(a)})},p.set(e,t),t}function w(e,o={}){return p.has(e)?p.get(e):q(e,o)}function J(){return v(A())}function A(){let e={};for(let[o,t]of p)e[o]=t._getSnapshot();return e}function M(e){try{let o=typeof e=="string"?JSON.parse(e):e;for(let[t,s]of Object.entries(o))w(t,s)._hydrate(s)}catch(o){console.warn("[what] Failed to hydrate island stores:",o)}}function P(e,o,t={}){y.set(e,{loader:o,mode:t.mode||"idle",media:t.media||null,priority:t.priority||0,stores:t.stores||[]})}function T({name:e,props:o={},children:t,mode:s,priority:n,stores:r}){let a=y.get(e),i=s||a?.mode||"idle",d=n??a?.priority??0,c=r||a?.stores||[];return{tag:"div",props:{"data-island":e,"data-island-mode":i,"data-island-props":JSON.stringify(o),"data-island-priority":d,"data-island-stores":JSON.stringify(c)},children:t||[],key:null,_vnode:!0}}function f(e){let o=!1;for(let t=0;t<l.length;t++)if(e.priority>l[t].priority){l.splice(t,0,e),o=!0;break}o||l.push(e),x()}function x(){if(b||l.length===0)return;b=!0;let e=l.shift();Promise.resolve(e.hydrate()).catch(o=>console.error("[what] Island hydration failed:",e.name,o)).finally(()=>{b=!1,queueMicrotask(x)})}function D(e,o=100){for(let t of l)if(t.name===e){t.priority=o,l.sort((s,n)=>n.priority-s.priority);break}}function k(){let e=document.querySelector("script[data-island-stores]");e&&M(e.textContent);let o=document.querySelectorAll("[data-island]");for(let t of o){let s=t.dataset.island,n=t.dataset.islandMode||"idle",r=JSON.parse(t.dataset.islandProps||"{}"),a=parseInt(t.dataset.islandPriority||"0",10),i=JSON.parse(t.dataset.islandStores||"[]"),d=y.get(s);if(!d){console.warn(`[what] Island "${s}" not registered`);continue}m.has(t)||N(t,d,r,n,a,s,i)}}function N(e,o,t,s,n,r,a){let i=async()=>{if(m.has(e))return;m.add(e);let d=await o.loader(),c=d.default||d,u={};for(let g of a)u[g]=w(g);let h=c({...t,...u});e.childNodes.length>0?i(h,e):C(h,e),e.removeAttribute("data-island"),e.removeAttribute("data-island-mode"),e.removeAttribute("data-island-props"),e.removeAttribute("data-island-priority"),e.removeAttribute("data-island-stores"),e.dispatchEvent(new CustomEvent("island:hydrated",{bubbles:!0,detail:{name:r,mode:s}}))};switch(s){case"load":f({name:r,priority:n+1e3,hydrate:i});break;case"idle":"requestIdleCallback"in window?requestIdleCallback(()=>{f({name:r,priority:n,hydrate:i})}):setTimeout(()=>{f({name:r,priority:n,hydrate:i})},200);break;case"visible":{new IntersectionObserver((c,u)=>{for(let h of c)if(h.isIntersecting){u.disconnect(),f({name:r,priority:n,hydrate:i});break}},{rootMargin:"200px"}).observe(e);break}case"media":{let d=window.matchMedia(o.media||"(max-width: 768px)");d.matches?f({name:r,priority:n,hydrate:i}):d.addEventListener("change",c=>{c.matches&&f({name:r,priority:n,hydrate:i})},{once:!0});break}case"action":{let d=["click","focus","mouseover","touchstart"],c=()=>{d.forEach(u=>e.removeEventListener(u,c)),f({name:r,priority:n+500,hydrate:i})};d.forEach(u=>e.addEventListener(u,c,{once:!0,passive:!0}));break}case"static":break;default:f({name:r,priority:n,hydrate:i})}}function H(e){for(let[o,t]of Object.entries(e))P(o,t.loader||t,{mode:t.mode||"idle",media:t.media,priority:t.priority||0,stores:t.stores||[]});typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",k):k())}function _(e,o){if(typeof document>"u")return;let t=document.querySelectorAll(e);for(let s of t)s.dataset.enhanced||(s.dataset.enhanced="true",o(s))}function Q(e="form[data-enhance]"){_(e,o=>{o.addEventListener("submit",async t=>{t.preventDefault();let s=new FormData(o),n=o.method.toUpperCase()||"POST",r=o.action||location.href;try{let a=document.querySelector('meta[name="csrf-token"]')||document.querySelector('meta[name="what-csrf-token"]'),i=a?a.getAttribute("content"):null,d=o.getAttribute("data-no-csrf")==="true";if(!i&&!d){console.warn('[what] Form submission blocked: no CSRF token found. Add a <meta name="csrf-token"> tag or set data-no-csrf="true" on the form to opt out.'),o.dispatchEvent(new CustomEvent("form:error",{bubbles:!0,detail:{error:new Error("Missing CSRF token")}}));return}let c={"X-Requested-With":"XMLHttpRequest"};i&&(c["X-CSRF-Token"]=i);let u=await fetch(r,{method:n,body:n==="GET"?void 0:s,headers:c});o.dispatchEvent(new CustomEvent("form:response",{bubbles:!0,detail:{response:u,ok:u.ok}}))}catch(a){o.dispatchEvent(new CustomEvent("form:error",{bubbles:!0,detail:{error:a}}))}})})}function X(){return{registered:[...y.keys()],hydrated:m.size,pending:l.length,queue:l.map(o=>({name:o.name,priority:o.priority})),stores:[...p.keys()]}}export{T as Island,H as autoIslands,D as boostIslandPriority,q as createIslandStore,_ as enhance,Q as enhanceForms,X as getIslandStatus,A as getIslandStoresSnapshot,M as hydrateIslandStores,k as hydrateIslands,P as island,J as serializeIslandStores,w as useIslandStore};
|
|
2
|
-
//# sourceMappingURL=islands.min.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "what-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "What Framework - SSR, islands architecture, static generation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
"files": [
|
|
24
24
|
"src",
|
|
25
|
-
"dist",
|
|
25
|
+
"dist/**/*.min.js",
|
|
26
26
|
"index.d.ts"
|
|
27
27
|
],
|
|
28
28
|
"sideEffects": false,
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"author": "ZVN DEV (https://zvndev.com)",
|
|
37
37
|
"license": "MIT",
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"what-core": "^0.
|
|
40
|
-
"what-router": "^0.
|
|
39
|
+
"what-core": "^0.11.1",
|
|
40
|
+
"what-router": "^0.11.1"
|
|
41
41
|
},
|
|
42
42
|
"peerDependenciesMeta": {
|
|
43
43
|
"what-router": {
|