rosefc 0.0.0-stage → 0.2.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.
@@ -0,0 +1,1885 @@
1
+ import*as ue from"fs";import*as Ws from"os";import*as re from"path";import{pathToFileURL as Js}from"url";import*as P from"fs";import*as _ from"path";import*as ws from"os";import{pathToFileURL as fr,fileURLToPath as Tt}from"url";import*as pt from"esbuild";var M=class extends Error{code;file;line;hint;constructor(s,t,n={}){super(t),this.name="RoseError",this.code=s,this.file=n.file,this.line=n.line,this.hint=n.hint}info(){let s={code:this.code};return this.file!==void 0&&(s.file=this.file),this.line!==void 0&&(s.line=this.line),s.message=this.message,this.hint!==void 0&&(s.hint=this.hint),s}};function at(e,s){let t=1,n=Math.min(s,e.length);for(let r=0;r<n;r++)e[r]===`
2
+ `&&t++;return t}function Te(e,s){return s&&s.index!==void 0?at(e,s.index):void 0}function Ys(e,s){return`$setState('${e}', ${s})`}function er(e){if(!e)return[];let s=[];for(let t of e.matchAll(/\b(?:let|const|var)\s+([A-Za-z_$][\w$]*)\s*(?::[^=;\n]*)?=\s*\$derived\b/g))s.includes(t[1])||s.push(t[1]);return s}function tr(e){let s="",t=0;for(;t<e.length;){let n=e[t];if(n==="/"&&(e[t+1]==="/"||e[t+1]==="*")){let r=e[t+1]==="/"?e.indexOf(`
3
+ `,t)<0?e.length:e.indexOf(`
4
+ `,t):e.indexOf("*/",t)<0?e.length:e.indexOf("*/",t)+2;s+=e.slice(t,r).replace(/[^\n]/g," "),t=r;continue}if(n==="'"||n==='"'||n==="`"){let r=t+1;for(;r<e.length&&e[r]!==n;)e[r]==="\\"?r+=2:r++;r=Math.min(r+1,e.length),s+=n+" ".repeat(Math.max(0,r-t-2))+(r-t>1?n:""),t=r;continue}s+=n,t++}return s}function Dn(e){if(!e)return null;let s=tr(e);for(let t of er(e))if(new RegExp(`(?<![\\w$.]|\\b(?:let|const|var)\\s{1,4})\\b${t}\\s*(?:\\+\\+|--|\\+=|-=|\\*=|/=|%=|=(?!=))|(?:\\+\\+|--)(?:\\s{1,4})${t}\\b(?![\\w$.])`).test(s))return t;return null}var nr=["+=","-=","*=","/=","%="],Fn=[/[(,.<>=!&|+\-*/%?:]$/,/(?:&&|\|\||=>|\.\.)$/];function ln(e,s,t=Ys){if(!e)return e;let n=/(?:^|[^\w$])(?:let|const|var|function|class|new|case|import|export|interface|type)\s+$/,r=f=>!!f&&/[A-Za-z_$]/.test(f),i="",o="",c=(f,h)=>{if(i+=f,!h)return;let p=f.replace(/\s+$/,"");p&&(o=(o+p).slice(-64))},a=()=>o.endsWith("=>")?"=>":o.replace(/\s+$/,"").slice(-1),u=0,g=f=>{let h=e[f],p=f+1;for(;p<e.length&&e[p]!==h;){if(e[p]==="\\"){p+=2;continue}if(h==="`"&&e[p]==="$"&&e[p+1]==="{"){let w=1;for(p+=2;p<e.length&&w>0;)e[p]==="{"?w++:e[p]==="}"&&w--,p++;continue}p++}return Math.min(p+1,e.length)},l=f=>{let h=f,p=0;for(;h<e.length;){let w=e[h];if(w==="'"||w==='"'||w==="`"){h=g(h);continue}if(w==="/"&&(e[h+1]==="/"||e[h+1]==="*")){h=e[h+1]==="/"?e.indexOf(`
5
+ `,h)<0?e.length:e.indexOf(`
6
+ `,h):e.indexOf("*/",h)<0?e.length:e.indexOf("*/",h)+2;continue}if(w==="("||w==="["||w==="{"){p++,h++;continue}if(w===")"||w==="]"||w==="}"){if(p===0)return h;p--,h++;continue}if(p>0){h++;continue}if(w===";")return h;if(w===`
7
+ `){let b=e.slice(f,h).replace(/\s+$/,"");if(b===""||Fn[0].test(b)||Fn[1].test(b)){h++;continue}return h}h++}return h};for(;u<e.length;){let f=e[u];if(f==="'"||f==='"'||f==="`"){let x=g(u);c(e.slice(u,x),!0),u=x;continue}if(f==="/"&&e[u+1]==="/"){let x=e.indexOf(`
8
+ `,u),E=x<0?e.length:x;c(e.slice(u,E),!1),u=E;continue}if(f==="/"&&e[u+1]==="*"){let x=e.indexOf("*/",u),E=x<0?e.length:x+2;c(e.slice(u,E),!1),u=E;continue}if((f==="+"||f==="-")&&e[u+1]===f&&["",";","{","}","(",",","=>"].includes(a())){let x=u+2;for(;x<e.length&&e[x]!==`
9
+ `&&/[ \t]/.test(e[x]);)x++;if(r(e[x])&&!(x>0&&/[\w$.]/.test(e[x-1]))){let E=x;for(;E<e.length&&/[\w$]/.test(e[E]);)E++;let N=e.slice(x,E);if(s(N)&&!n.test(o)){c(t(N,`${N}() ${f==="-"?"-":"+"} 1`),!0),u=E;continue}}c(f,!0),u++;continue}if(!r(f)||u>0&&/[\w$.]/.test(e[u-1])){c(f,!0),u++;continue}let h=u;for(;h<e.length&&/[\w$]/.test(e[h]);)h++;let p=e.slice(u,h);if(!s(p)||n.test(o)){c(p,!0),u=h;continue}let w=e.slice(h).match(/^[ \t]*/)[0].length,b=e.slice(h+w),m=a();if((b.startsWith("++")||b.startsWith("--"))&&!/[\w$.]/.test(b.slice(2,3))&&["",";","{","}","(",")",",","=>"].includes(m)){c(t(p,`${p}() ${b.startsWith("--")?"-":"+"} 1`),!0),u=h+w+2;continue}let v=null,k=1;for(let x of nr)if(b.startsWith(x)){v=x.slice(0,-1),k=2;break}if((v!==null||/^=(?!=)/.test(b))&&["",";","{","}",")","=>"].includes(m)){let x=h+w+k,E=l(x),N=e.slice(x,E).trim();if(N){if(v===null){let R=new RegExp(`^(?:--\\s*${p}$|${p}\\s*--$)`).test(N),U=new RegExp(`^\\+\\+\\s*${p}$|^${p}\\s*\\+\\+$`).test(N);if(R||U){c(t(p,`${p}() ${R?"-":"+"} 1`),!0),u=E;continue}}c(t(p,v===null?N:`${p}() ${v} (${N})`),!0),u=E;continue}}c(p,!0),u=h}return i}import Rt from"node:fs";import un from"node:path";var qn=64,sr=30*60*1e3;async function rr(e){for(let s=0;;s++)try{await Rt.promises.rm(e,{force:!0});return}catch(t){if(s>=2||!/EPERM|EBUSY|EACCES/.test(String(t)))throw t;await new Promise(n=>setTimeout(n,50*(s+1)))}}async function or(e){for(let s=0;s<e.length;s+=qn)await Promise.all(e.slice(s,s+qn).map(rr))}async function ir(e){try{return await Rt.promises.readdir(e,{withFileTypes:!0})}catch{return[]}}async function At(e){let s=await ir(e),t=[],n=[];for(let r of s)r.isDirectory()?n.push(un.join(e,r.name)):t.push(un.join(e,r.name));await or(t),await Promise.all(n.map(r=>At(r))),await Rt.promises.rmdir(e).catch(()=>{})}function Bn(e){Rt.promises.readdir(e).then(s=>{let t=Date.now();for(let n of s){let r=un.join(e,n);Rt.promises.stat(r).then(i=>{i.isDirectory()&&t-i.mtimeMs>sr&&At(r).catch(()=>{})}).catch(()=>{})}}).catch(()=>{})}function ct(e){let s=2166136261,t=typeof e=="string"?new TextEncoder().encode(e):e;for(let n=0;n<t.length;n++)s^=t[n],s=Math.imul(s,16777619);return(s>>>0).toString(36)}var Hn={"mini-program":["weapp","qq","alipay","baidu","toutiao"],miniprogram:["weapp","qq","alipay","baidu","toutiao"],native:["flutter","android","arkts","xcode"],desktop:["electron","python","dotnet","java","cpp"],web:["web"]},ar=new Set(["weapp","qq","alipay","baidu","toutiao","flutter","android","arkts","xcode","electron","python","dotnet","java","cpp","web"]),Jn={"mp-weixin":"weapp","mp-qq":"qq","mp-alipay":"alipay","mp-baidu":"baidu","mp-toutiao":"toutiao"};function Wn(e,s){let t=s.toLowerCase(),n=e.trim().toLowerCase(),r=Jn[n]??n,i=Hn[r];return i?i.includes(t):r===t}function zn(e){let s=e.trim().toLowerCase();return Jn[s]?!0:Hn[s]!==void 0||ar.has(s)}function Un(e,s="web",t=[]){let n=/^[ \t]*(?:\/\/|<!--|\/\*)\s*#(ifdef|ifndef|endif)\b([ \t\S]*?)(?:\*\/|-->)?[ \t]*$/gm,r=e.split(`
10
+ `),i=[],o=[],c=()=>o.every(Boolean);for(let a of r){let u=n.exec(a);if(n.lastIndex=0,u){let g=u[1],l=(u[2]??"").trim().split(/\s+/)[0].toLowerCase();if(g==="endif"){o.length?o.pop():t.push("#endif with no matching #ifdef - left as written");continue}zn(l)||t.push(`#${g} ${l} names an unknown target or family - treated as false`);let f=Wn(l,s);o.push(g==="ifdef"?f:!f);continue}c()&&i.push(a)}return o.length&&t.push(`${o.length} #ifdef without #endif - the tail is kept as written`),i.join(`
11
+ `)}function Vn(e,s="web",t=[]){let n=s.toLowerCase(),r=e;for(let i=0;i<40;i++){let o=/\{#(ifdef|ifndef)\s+([^}]*)\}/.exec(r);if(!o)break;let c=o[1],a=o[2].trim().toLowerCase(),u=Wn(a,n),g=c==="ifdef"?u:!u;zn(a)||t.push(`{#${c} ${a}} names an unknown target or family - treated as false`);let l=o.index+o[0].length,f=1,h=-1,p=-1,w=/\{#(ifdef|ifndef)\b|\{:(else)\b|\{\/(ifdef|ifndef)\}/g;w.lastIndex=l;for(let v=w.exec(r);v;v=w.exec(r))if(v[1])f++;else if(v[3]){if(f--,f===0){p=v.index;break}}else v[2]&&f===1&&(h=v.index);if(p<0){t.push(`{#${c} ${a}} has no {/${c}} - left as written`);break}let b=h>=0?h+7:p,m=h>=0?g?r.slice(l,h):r.slice(b,p):g?r.slice(l,p):"";r=r.slice(0,o.index)+m+r.slice(p+c.length+3)}return r}import Ke from"node:fs";function Gn(e){try{let s=Ke.openSync(e,"r"),t=Buffer.alloc(64),n=Ke.readSync(s,t,0,64,0);return Ke.closeSync(s),n<24?null:t[0]===137&&t[1]===80&&t[2]===78&&t[3]===71?{width:t.readUInt32BE(16),height:t.readUInt32BE(20)}:t.slice(0,3).toString("latin1")==="GIF"?{width:t.readUInt16LE(6),height:t.readUInt16LE(8)}:t.slice(0,4).toString("latin1")==="RIFF"&&t.slice(8,12).toString("latin1")==="WEBP"?cr(t):t[0]===255&&t[1]===216?lr(e):null}catch{return null}}function cr(e){let s=e.slice(12,16).toString("latin1");if(s==="VP8 ")return{width:e.readUInt16LE(26)&16383,height:e.readUInt16LE(28)&16383};if(s==="VP8L"){let t=e.readUInt32LE(21);return{width:(t&16383)+1,height:(t>>14&16383)+1}}if(s==="VP8X"){let t=e.readUIntLE(24,3)+1,n=e.readUIntLE(27,3)+1;return{width:t,height:n}}return null}function lr(e){let s=Ke.openSync(e,"r");try{let t=Buffer.alloc(4),n=2;for(let r=0;r<64;r++){if(Ke.readSync(s,t,0,4,n)<4)return null;if(t[0]!==255){n+=1;continue}let i=t[1];if(i===216||i===1||i>=208&&i<=215){n+=2;continue}let o=Ke.readSync(s,t,0,2,n+2)<2?0:t.readUInt16BE(2);if(i>=192&&i<=207&&i!==196&&i!==200&&i!==204){let c=Buffer.alloc(8);return Ke.readSync(s,c,0,8,n+4),{width:c.readUInt16BE(3),height:c.readUInt16BE(1)}}n+=2+o}return null}finally{Ke.closeSync(s)}}import Ut from"node:fs";import Zn from"node:path";function ur(e){if(!e.startsWith("---"))return{frontmatter:{},body:e};let s=e.indexOf(`
12
+ ---`,3);if(s<0)return{frontmatter:{},body:e};let t=e.slice(4,s),n=e.slice(e.indexOf(`
13
+ `,s+1)+1).replace(/^\s*\n/,""),r={};for(let i of t.split(`
14
+ `)){let o=/^(\w[\w-]*):\s*(.*)$/.exec(i.trim());if(!o)continue;let[,c,a]=o,u=/^\[(.+)\]$/.exec(a.trim());r[c]=u?u[1].split(",").map(g=>g.trim().replace(/^["']|["']$/g,"")):a.trim().replace(/^["']|["']$/g,"")}return{frontmatter:r,body:n}}function dr(e,s){return e.replace(/{{(\w[\w.]*)}}/g,(t,n)=>{let r=n.split(".").reduce((i,o)=>i==null?i:i[o],s);return r==null?"":String(r)})}function Xn(e,s){s&&(e=dr(e,s));let t=[],n=e.replace(/```(\w*)\n([\s\S]*?)```/g,(a,u,g)=>(t.push(`<pre data-lang="${u}"><code>${g.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}</code></pre>`),`\0CODE${t.length-1}\0`)),r=a=>a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/`([^`]+)`/g,"<code>$1</code>").replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>").replace(/\*([^*]+)\*/g,"<em>$1</em>").replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" rel="noopener">$1</a>'),i=[],o=null,c=()=>{o&&(i.push(`</${o}>`),o=null)};for(let a of n.split(`
15
+ `)){let u=/^(#{1,4})\s+(.*)$/.exec(a),g=/^\s*[-*]\s+(.*)$/.exec(a),l=/^\s*\d+\.\s+(.*)$/.exec(a);u?(c(),i.push(`<h${u[1].length}>${r(u[2])}</h${u[1].length}>`)):g?(o!=="ul"&&(c(),i.push("<ul>"),o="ul"),i.push(`<li>${r(g[1])}</li>`)):l?(o!=="ol"&&(c(),i.push("<ol>"),o="ol"),i.push(`<li>${r(l[1])}</li>`)):a.trim()===""?c():a.startsWith("\0CODE")?(c(),i.push(a)):(c(),i.push(`<p>${r(a)}</p>`))}return c(),i.join(`
16
+ `).replace(/\u0000CODE(\d+)\u0000/g,(a,u)=>t[Number(u)])}function Qn(e){let s={};if(!Ut.existsSync(e))return s;for(let t of Ut.readdirSync(e,{withFileTypes:!0})){if(!t.isDirectory())continue;let n=[],r=Zn.join(e,t.name);for(let i of Ut.readdirSync(r)){if(!i.endsWith(".md"))continue;let o=Ut.readFileSync(Zn.join(r,i),"utf-8"),{frontmatter:c,body:a}=ur(o);if(String(c.draft??"").toLowerCase()==="true")continue;let u=i.replace(/\.md$/,""),g=Xn(a),l=a.replace(/[#*`\[\]()>-]/g," ").split(/\s+/).filter(Boolean).length,f=[],h=g.replace(/<h([1-4])>([^<]+)<\/h\1>/g,(p,w,b)=>{let m=b.toLowerCase().replace(/[^\w\s-]/g,"").trim().replace(/\s+/g,"-");return f.push({level:Number(w),text:b,id:m}),`<h${w} id="${m}">${b}</h${w}>`});n.push({slug:u,frontmatter:c,body:a,html:h,readingTime:Math.max(1,Math.round(l/200)),wordCount:l,toc:f,excerpt:String(c.summary??"")||(g.match(/<p>([\s\S]*?)<\/p>/)?.[1]??"").replace(/<[^>]+>/g,"").slice(0,160)})}n.sort((i,o)=>String(o.frontmatter.date??"").localeCompare(String(i.frontmatter.date??""))),s[t.name]=n}return s}globalThis.__rosefcContentMk=Xn;var dn=new Map;function nt(e,s,t){let n=$r(),r={...s,define:{..._r(),...s.define??{}}};if(e+=`|env:${n}`,!t||s.splitting)return pt.build(r);let i=dn.get(e);return i?i.rebuild().catch(o=>{throw dn.delete(e),o}):pt.context(r).then(o=>(dn.set(e,o),o.rebuild()))}var Ot=/<script>([\s\S]*?)<\/script>/,ys=/<template>([\s\S]*?)<\/template>/,gn=/<head>([\s\S]*?)<\/head>/,mn=/<style>([\s\S]*?)<\/style>/,Kn=/(?<=^|[;}{\n])[ \t]*(?:let|const|var)\s+(\w+)[^\n;{}=]*=\s*\$(state|data|kv|persist|derived)\b/g,hr=/^\s+as\s+[^;\n]+/,pr=/\$setState\(([^,]+),\s*([^)]+)\)/g;var gr=/<slot\s*\/>|<slot>([\s\S]*?)<\/slot>/g,mr=/<slot\s+((?=[^>]*\bname\s*=)[^>]*?)(?:\/>|>([\s\S]*?)<\/slot>)/g;function Yn(e){let s=/\bname\s*=\s*["'](\w+)["']/.exec(e)?.[1];if(!s)throw new M("E-TEMPLATE",'<slot> with attributes must declare a name: <slot name="row" ... />',{hint:'a slot carrying attributes is a NAMED slot - it must declare which one: <slot name="row" item={post} />'});let t=[...e.matchAll(/\b(\w+)\s*=\s*\{([^}]*)\}/g)].filter(n=>n[1]!=="name").map(n=>`['${n[1]}', (${n[2].trim()})]`);return`${JSON.stringify(s)}, [${t.join(", ")}]`}var wr="<p>This section failed to render.</p>",yr=new Set(["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"]),lt={loader:{".js":"ts"}},jt="ROSEFC_PUBLIC_",br=/^[A-Za-z_$][\w$]*$/,Sn=()=>Object.entries(process.env).filter(e=>e[0].startsWith(jt)&&typeof e[1]=="string").sort(([e],[s])=>e<s?-1:e>s?1:0),$r=()=>Qt(JSON.stringify(Sn()));function _r(){let e=Object.fromEntries(Sn()),s={};for(let[t,n]of Object.entries(e))br.test(t)&&(s[`import.meta.env.${t}`]=JSON.stringify(n).replace(/</g,"\\u003c"));return s["import.meta.env"]=JSON.stringify(e).replace(/</g,"\\u003c"),s}function es(e){return[...e.matchAll(/\bimport\.meta\.env\.([A-Za-z_$][\w$]*)/g)].map(s=>s[1])}function fn(e,s){let t={"(":")","[":"]","{":"}"}[e[s]]??"";if(!t)return-1;let n=0;for(let r=s;r<e.length;r++)if(e[r]===e[s])n++;else if(e[r]===t&&(n--,n===0))return r;return-1}function xr(e,s){let t={")":"(","]":"[","}":"{"}[e[s]]??"";if(!t)return-1;let n=0;for(let r=s;r>=0;r--)if(e[r]===e[s])n++;else if(e[r]===t&&(n--,n===0))return r;return-1}function vr(e,s){let t=0;for(let n=s;n<e.length;n++){let r=e[n];if(r==="("||r==="["||r==="{"){t++;continue}if(r===")"||r==="]"||r==="}"){if(t===0)return n;t--;continue}if(t===0&&(r===","||r===";"))return n}return e.length}function kr(e){let s=Vt(e),t=[],n=(r,i)=>{let o=[];for(let c of s.slice(r,i).matchAll(/\b(?:const|let|var|function|class)\s+([A-Za-z_$][\w$]*)/g))o.push(c[1]);return o};for(let r of s.matchAll(/\bfunction\b/g)){let i=r.index+r[0].length;for(;i<s.length&&/\s/.test(s[i]);)i++;for(s[i]==="*"&&i++;i<s.length&&/[A-Za-z_$]/.test(s[i]);)i++;for(;i<s.length&&/\s/.test(s[i]);)i++;if(s[i]!=="(")continue;let o=fn(s,i);if(o<0)continue;let c=o+1;for(;c<s.length&&/\s/.test(s[c]);)c++;if(s[c]!=="{")continue;let a=fn(s,c);if(a<0)continue;let u=new Set(Nt(e.slice(i+1,o)));for(let g of n(c,a))u.add(g);t.push({start:i,end:a+1,names:u})}for(let r of s.matchAll(/=>/g)){let i=r.index,o=i-1;for(;o>=0&&/\s/.test(s[o]);)o--;let c="",a=i;if(s[o]===")"){let f=xr(s,o);if(f<0)continue;c=e.slice(f+1,o),a=f}else if(/[A-Za-z_$]/.test(s[o]??"")){let f=o;for(;f>=0&&/[\w$]/.test(s[f]);)f--;c=e.slice(f+1,o+1),a=f+1}else continue;let u=i+2;for(;u<s.length&&/\s/.test(s[u]);)u++;let g=s[u]==="{"?fn(s,u)+1:vr(s,u);if(g<=0)continue;let l=new Set(Nt(c));t.push({start:a,end:g,names:l})}return t.sort((r,i)=>r.start-i.start)}function Ve(e,s,t){if(s.length===0&&!t)return e;let n=kr(e),r=(o,c)=>{for(let a of n){if(a.start>o)break;if(o<a.end&&a.names.has(c))return!0}return!1},i=(o,c=0)=>{let a="",u=0;for(;u<o.length;){let g=o[u];if(g==="'"||g==='"'){let l=u+1;for(;l<o.length&&o[l]!==g;)o[l]==="\\"&&l++,l++;a+=o.slice(u,Math.min(l+1,o.length)),u=l+1;continue}if(g==="`"){for(a+=g,u++;u<o.length&&o[u]!=="`";){if(o[u]==="\\"){a+=o.slice(u,u+2),u+=2;continue}if(o[u]==="$"&&o[u+1]==="{"){let l=1,f=u+2;for(;f<o.length&&l>0&&(o[f]==="{"?l++:o[f]==="}"&&l--,l!==0);)f++;a+="${"+i(o.slice(u+2,f),c+u+2)+"}",u=f+1;continue}a+=o[u],u++}a+="`",u++;continue}if(g==="/"&&o[u+1]==="/"){let l=o.indexOf(`
17
+ `,u),f=l===-1?o.length:l;a+=o.slice(u,f),u=f;continue}if(g==="/"&&o[u+1]==="*"){let l=o.indexOf("*/",u+2),f=l===-1?o.length:l+2;a+=o.slice(u,f),u=f;continue}if(/[A-Za-z_$]/.test(g)){let l=u;for(;l<o.length&&/[\w$]/.test(o[l]);)l++;let f=o.slice(u,l),h=a.length?a[a.length-1]:"",p=o[l]??"",w=h==="@",b=!/[\w$.]/.test(h)&&!/[\w$:(]/.test(p),m=b&&!w&&s.includes(f)&&!r(c+u,f),v=b&&t!=null&&Object.prototype.hasOwnProperty.call(t,f);a+=m?`${f}()`:v?`${t[f]}()`:f,u=l;continue}a+=g,u++}return a};return i(e)}var bs=/^\s*#(?:if|each|await|key|snippet|boundary|island|defer)\b/,$s=/^\s*\/(?:if|each|await|key|snippet|boundary|island|defer)\s*$/,_s=/^\s*:(?:else|then|catch|fallback)\b/,Sr=/^\s*#each\s+([\s\S]+?)\s+as\s+(\{[^{}]*\}|\[[^[\]]*\]|\w+)(?:\s*,\s*(\w+))?(?:\s*\(([\s\S]+)\))?\s*$/,Er=/^\s*#snippet\s+(\w+)(?:\s*\(([\s\S]*)\))?\s*$/,Rr=/^\s*:(?:then|catch)\s+([A-Za-z_$][\w$]*)\s*$/;function Nt(e){return e.replace(/^[{[]/,"").replace(/[}\]]$/,"").split(",").map(t=>{let n=t.split("=")[0].trim(),r=n.indexOf(":");return r>=0?n.slice(r+1).trim():n}).filter(t=>/^[A-Za-z_$][\w$]*$/.test(t))}function xs(e,s){let t=[],n=0;for(;n<e.length;){let r=_o(e.slice(n),s);if(!r)break;if(r.selfClosing){n+=r.end;continue}let i=Zt(e,n+r.end,r.name),o=i>=0?i+r.name.length+3:e.length;t.push([n+r.start,o]),n=o}return t}function Ar(e,s){let t=[],n=0,r=s.size>0?xs(e,s):[],i=0,o=-1;for(let c of ft(e)){for(;i<r.length&&r[i][0]<=c.start;)o=r[i++][1];if(c.start<o)continue;let a=c.expr;if($s.test(a)){n>0&&n--;continue}if(bs.test(a)){n++;continue}if(!_s.test(a)&&n===0){let u=/^\s*@const\s+([A-Za-z_$][\w$]*)\s*=/.exec(a);u&&t.push(u[1])}}return t}function wn(e,s,t,n){if(s.length===0&&!t)return e;let r="",i=0,o=[new Set],c=()=>o[o.length-1],a=h=>o.some(p=>p.has(h)),u=n?.ownScope?h=>{for(let p=o.length-1;p>=0;p--)if(o[p].has(h))return p===0;return!1}:h=>!a(h),g=()=>[s.filter(h=>!a(h)),t?Object.fromEntries(Object.entries(t).filter(([h])=>u(h))):void 0],l=[];if(n?.comps&&n.comps.size>0)for(let[h,p]of xs(e,n.comps))l.push({pos:h,open:!0}),l.push({pos:p,open:!1});let f=0;for(let h of ft(e)){for(;f<l.length&&l[f].pos<=h.start;)l[f].open?o.push(new Set):o.length>1&&o.pop(),f++;let p=h.expr;if($s.test(p)){o.length>1&&o.pop(),r+=e.slice(i,h.end+1),i=h.end+1;continue}if(bs.test(p)){let v=Sr.exec(p);if(v){let[,E,N,R,U]=v,[L,q]=g(),X=` as ${N}${R?`, ${R}`:""}`;o.push(new Set([...Nt(N),...R?[R]:[]]));let Y=U!=null&&U.trim()!==""?` (${Ve(U,...g())})`:"";r+=e.slice(i,h.start)+`{#each ${Ve(E,L,q)}${X}${Y}}`,i=h.end+1;continue}let k=Er.exec(p);if(k){o.push(new Set(k[2]?Nt(k[2]):[])),r+=e.slice(i,h.end+1),i=h.end+1;continue}let[T,x]=g();r+=e.slice(i,h.start)+"{"+Ve(p,T,x)+"}",o.push(new Set),i=h.end+1;continue}if(_s.test(p)){c().clear();let v=Rr.exec(p);if(v){c().add(v[1]),r+=e.slice(i,h.end+1),i=h.end+1;continue}let[k,T]=g();r+=e.slice(i,h.start)+"{"+Ve(p,k,T)+"}",i=h.end+1;continue}let w=/^\s*@const\s+([A-Za-z_$][\w$]*)\s*=([\s\S]*)$/.exec(p),[b,m]=g();if(w){let v=w[2],k=Ve(v,b,m);c().add(w[1]),r+=e.slice(i,h.start)+(k===v?e.slice(h.start,h.end+1):`{@const ${w[1]} =${k}}`),i=h.end+1;continue}r+=e.slice(i,h.start)+"{"+Ve(p,b,m)+"}",i=h.end+1}return r+e.slice(i)}function ft(e){let s=[],t=0;for(;t<e.length;){if(e[t]==="{"){let n=Lt(e,t);if(n>t+1){s.push({start:t,end:n,expr:e.slice(t+1,n)}),t=n+1;continue}}t++}return s}function Cr(e,s){let t=s;for(;t<e.length;){if(e[t]==="{"){let n=Lt(e,t);if(n>t+1)return{index:t,end:n,expr:e.slice(t+1,n)}}t++}return null}function Lt(e,s){let t=0,n=s;for(;n<e.length;){let r=e[n];if(r==="'"||r==='"'){n=Ze(e,n);continue}if(r==="`"){n=Xt(e,n);continue}if(r==="/"){let i=st(e,n);if(i!==null){n=i;continue}}if(r==="{")t++;else if(r==="}"&&--t===0)return n;n++}return-1}function Ge(e,s){let t=s+2,n=1;for(;t<e.length;){let r=e[t];if(r==="'"||r==='"'){t=Ze(e,t);continue}if(r==="`"){t=Xt(e,t);continue}if(r==="{")n++;else if(r==="}"&&--n===0)return t+1;t++}return-1}function Ze(e,s){let t=e[s],n=s+1;for(;n<e.length;){if(e[n]==="\\"){n+=2;continue}if(e[n]===t)return n+1;n++}return n}function Xt(e,s){let t=s+1;for(;t<e.length;){let n=e[t];if(n==="\\"){t+=2;continue}if(n==="`")return t+1;if(n==="$"&&e[t+1]==="{"){let r=Lt(e,t+1);t=r<0?e.length:r+1;continue}t++}return t}function vs(e,s){let t=s;for(;t>=0&&/[\w$]/.test(e[t]);)t--;return t===s?"":e.slice(t+1,s+1)}function st(e,s){let t=e[s];if(t==='"'||t==="'")return Ze(e,s);if(t==="`")return Xt(e,s);if(t!=="/"||e[s+1]==="/"||e[s+1]==="*")return null;let n=s-1;for(;n>=0&&/\s/.test(e[n]);)n--;if(n>=0&&!"(,=:[!&|?{};+-*%~^".includes(e[n])){let o=vs(e,n);if(!["return","typeof","case","in","of","new","delete","void","do","else","instanceof","yield","await"].includes(o))return null}let r=s+1,i=!1;for(;r<e.length;){let o=e[r];if(o==="\\"){r+=2;continue}if(o===`
18
+ `)return null;if(i)o==="]"&&(i=!1);else if(o==="[")i=!0;else if(o==="/"){r++;break}r++}if(r>e.length)return null;for(;r<e.length&&/[dgimsuvy]/.test(e[r]);)r++;return r}function ts(e){let s="",t=0;for(;t<e.length;){let n=st(e,t);if(n!==null){s+=e.slice(t,n),t=n;continue}if(e.startsWith("//",t)){for(;t<e.length&&e[t]!==`
19
+ `;)t++;continue}if(e.startsWith("/*",t)){for(t+=2;t<e.length&&!e.startsWith("*/",t);)t++;t=Math.min(t+2,e.length);continue}if(e.startsWith("<!--",t)){for(t+=4;t<e.length&&!e.startsWith("-->",t);)t++;t=Math.min(t+3,e.length);continue}s+=e[t++]}return s}function Tr(e){let s=/typeof\s+(?:window|document|navigator|location|localStorage|sessionStorage)\s*(!==|===)\s*["']undefined["']/y,t=l=>{for(;l<e.length&&/\s/.test(e[l]);)l++;return l},n=l=>{let f=0,h=l+1;for(;h<e.length;){let p=e[h],w=st(e,h);if(w!==null){h=w;continue}if(p==="("||p==="["||p==="{")f++;else if(p===")"||p==="]"||p==="}"){if(f--,f<0)return-1}else{if(f===0&&p===":")return h;if(f===0&&p==="?"){let b=n(h);if(b<0)return-1;h=b+1;continue}}h++}return-1},r=l=>{let f=0;for(;l<e.length;){let h=e[l],p=st(e,l);if(p!==null){l=p;continue}if(h==="("||h==="["||h==="{")f++;else if(h===")"||h==="]"||h==="}"){if(f===0)return l;f--}else{if(f===0&&(h===","||h===";"))return l;if(f===0&&h==="?"){let w=n(l);if(w<0)return e.length;l=w+1;continue}}l++}return e.length},i=l=>{let f=0,h=l;for(;h<e.length;){let p=e[h],w=st(e,h);if(w!==null){h=w;continue}if(p==="{")f++;else if(p==="}"&&(f--,f===0))return h;h++}return e.length},o=l=>{let f=0;for(;l<e.length;){let h=e[l],p=st(e,l);if(p!==null){l=p;continue}if(h==="("||h==="["||h==="{")f++;else if(h===")"||h==="]"||h==="}"){if(f===0)return l;f--}else if(f===0&&(h===";"||h===`
20
+ `))return l;l++}return e.length},c=(l,f)=>{let h=f-1;for(;h>=0&&/\s/.test(l[h]);)h--;if(h<0||l[h]!=="(")return!1;for(h--;h>=0&&/\s/.test(l[h]);)h--;return h>=1&&l[h]==="f"&&l[h-1]==="i"&&(h<2||!/[\w$]/.test(l[h-2]))},a=[],u=0;for(;u<e.length;){let l=st(e,u);if(l!==null){u=l;continue}s.lastIndex=u;let f=s.exec(e);if(!f){u++;continue}let h=f[1]==="!==",p=t(u+f[0].length),w=e.slice(p,p+2);if(w==="&&"&&h)a.push([p+2,r(p+2)]);else if(w==="||"&&!h)a.push([p+2,r(p+2)]);else if(e[p]==="?"){let b=n(p);b<0?h&&a.push([p+1,e.length]):h?a.push([p+1,b]):a.push([b+1,r(b+1)])}else if(e[p]===")"&&c(e,u)){let b,m=t(p+1);e[m]==="{"?(b=i(m),h&&a.push([m+1,b])):(b=o(m),h&&a.push([m,b]));let v=t(b+1);if(e.startsWith("else",v)){let k=t(v+4);if(e[k]==="{"){let T=i(k);h||a.push([k+1,T])}else{let T=o(k);h||a.push([k,T])}}}u=p}if(a.length===0)return e;let g=[...e];for(let[l,f]of a)for(let h=l;h<f&&h<g.length;h++)g[h]!==`
21
+ `&&(g[h]=" ");return g.join("")}async function Or(e){let s=_.join(e,"rosefc.config.js");if(!P.existsSync(s))return{plugins:[],i18n:{}};let t=await import(fr(s).href+`?t=${Date.now()}`);return{plugins:t.default??[],i18n:t.i18n??{},pwa:t.pwa??void 0,brotli:t.brotli??void 0,csp:t.csp??void 0,watch:t.watch??void 0}}function ns(e,s,t){let n=[],r=(o,c)=>{let a=_.resolve(_.dirname(s),o),u=t.get(a);if(!u)throw new M("E-IMPORT",`${_.basename(s)}: cannot import '${o}' - no .rose file at ${a}. A component lives under src/components/ (or src/pages/) and is imported by relative path.`,{file:s,line:at(e,c),hint:`create ${a} (a .rose component) or fix the import path - a .rose import resolves to a file, never to a package`});return u},i=e.replace(/import\s+(\w+)\s+from\s*(['"])([^'"]+\.rose)\2/g,(o,c,a,u,g)=>{let l=r(u,g);return n.push({name:c,specifier:u,index:l.index}),`import { render as ${c} } from ${a}__rose_${l.index}__${a}`});return i=i.replace(/import\s*(\{[^}]*\})\s+from\s*(['"])([^'"]+\.rose)\2/g,(o,c,a,u,g)=>{let l=r(u,g),f=/\bas\s+(\w+)/.exec(c)?.[1]??"render";return n.push({name:f,specifier:u,index:l.index}),`import ${c} from ${a}__rose_${l.index}__${a}`}),{script:i,imports:n}}function hn(e,s){return e.replace(/from\s*(['"])__rose_(\d+)__\1/g,(t,n,r)=>`from ${n}./comp-${r}.${s}.js${n}`)}var jr=/^(?:node:|(?:fs|path|os|crypto|http|https|net|tls|stream|child_process|worker_threads|dns|cluster|better-sqlite3|sqlite3|pg|mysql2|mongodb|redis|ioredis)$)/;function Pr(e){let s=[];for(let t of e.matchAll(/import\s+(type\s+)?[\s\S]*?from\s*['"]([^'"]+)['"]/g))t[1]||jr.test(t[2])&&s.push(t[2]);return s}function Mr(e){let s=[];for(let t=0;;){let n=ut(e,"each",t);if(!n)break;t=n.index+1;let r=Ge(e,n.index),i=n[5];r<0||i==null||s.push({names:new Set([...Nt(n[2]??""),...n[3]?[n[3]]:[]]),contentStart:r,contentEnd:r+i.length})}return s}function Nr(e,s,t){let n=0;for(let r of e.slice(s,t).matchAll(/\{#(?:snippet|key|await)\b|\{\/(?:snippet|key|await)\s*\}/g))if(n+=r[0][1]==="/"?-1:1,n>0)return!0;return!1}function Lr(e,s,t="<template>",n=""){let r=[],i=0,o=null,c="",a=e,u=0,g={window:"w",document:"d"},l={preventDefault:()=>"e.preventDefault()",stopPropagation:()=>"e.stopPropagation()",self:p=>`const __self = e.target.closest && e.target.closest('[data-${p}-' + e.type + ']'); if (__self && e.target !== __self) return;`},f={once:p=>`const __o = e.target && e.target.closest ? e.target.closest('[data-${p}-' + e.type + ']') : null; if (__o) __o.removeAttribute('data-${p}-' + e.type);`},h=[...Object.keys(l),...Object.keys(f),...Object.keys(g)];for(;;){let p=/\bon:(\w+)((?:\|\w+)*)\s*=\s*\{/.exec(a);if(!p){c+=a;break}let w=!1,b=p[2]?p[2].slice(1).split("|"):[],m=b.filter(R=>g[R]);if(m.length>1)throw new M("E-TEMPLATE",`${t}: on:${p[1]} carries both |${m.join(" and |")}`,{hint:"a handler binds to one target - the element (default), |window or |document"});let v=m.length?"on"+g[m[0]]:"on";for(let R of b)if(!h.includes(R))throw new M("E-TEMPLATE",`${t}: unknown event modifier |${R}`,{hint:`the supported modifiers are ${h.map(U=>"|"+U).join(" ")} - capture/passive are listener options a delegated listener cannot carry per element; anything else belongs inside the handler body`});c+=a.slice(0,p.index);let k=p.index+p[0].length,T=1;for(;k<a.length;){let R=a[k];if(R==='"'||R==="'"){k=Ze(a,k);continue}if(R==="`"){k=Xt(a,k);continue}if(R==="{")T++;else if(R==="}"&&(T--,T===0))break;k++}let x=a.slice(p.index+p[0].length,k).trim(),E=new Set;for(let R of e.matchAll(/\{#each\s+[\s\S]+?\s+as\s+([A-Za-z_$][\w$]*)\s*(?:,\s*([A-Za-z_$][\w$]*))?/g))E.add(R[1]),R[2]&&E.add(R[2]);if(/=>/.test(x)&&!/^\w+$/.test(x)){let R=[...E].filter(U=>new RegExp(`\\b${U}\\b`).test(x));if(R.length>0){let U=u+p.index,L=(o??=Mr(e)).filter(X=>U>=X.contentStart&&U<X.contentEnd).sort((X,Y)=>X.contentStart-Y.contentStart).pop()??null;if(L!=null&&!Nr(e,L.contentStart,U)&&R.every(X=>L.names.has(X)))w=!0;else{let X=R.find(Y=>!L||!L.names.has(Y))??R[0];throw new M("E-TEMPLATE",`${t}: this inline handler reads the {#each} variable "${X}" but is hoisted to the page module, where it does not exist`,{file:t,line:at(e,u+p.index),hint:`name the handler in the script block (function onX(e) { ... }) and write on:${p[1]}={onX} - the named form closes over nothing and works for every item`})}}}let N=R=>{if(!b.length)return R;let U=b.filter(q=>l[q]).map(q=>l[q](v)),L=b.filter(q=>f[q]).map(q=>f[q](v));return`(e) => {${U.length?" "+U.join("; ")+";":""} (${R})(e);${L.length?" "+L.join("; ")+";":""} }`};if(b.length&&s.has(x))throw new M("E-TEMPLATE",`${t}: event modifiers are not supported on the server action ${x}`,{hint:"$action already preventDefaults - drop the modifiers, or bind a local handler that calls $action"});if(w){let R=n?`__rh_${n}_`:"__rh_";c+=`data-${v}-${p[1]}={__rhreg(${JSON.stringify(R)}, ${b.length?N(x):x})}`,i++}else if(b.length){let R=n?`__h_${n}_${r.length}`:`__h${r.length}`;c+=`data-${v}-${p[1]}="${R}"`,r.push({event:p[1],fn:`${R}: ${N(x)}`})}else if(s.has(x))c+=`data-on-${p[1]}="$action:${x}"`;else if(/^\w+$/.test(x))c+=`data-on-${p[1]}="${x}"`,r.push({event:p[1],fn:x});else{let R=n?`__h_${n}_${r.length}`:`__h${r.length}`;c+=`data-on-${p[1]}="${R}"`,r.push({event:p[1],fn:`${R}: ${x}`})}u+=k+1,a=a.slice(k+1)}return{template:c,bindings:r,inlineCount:i}}function Ir(e){let s;try{s=P.readFileSync(e,"utf-8")}catch{return[]}let n=s.replace(Ot,"").replace(mn,""),r=n.match(ys)?.[1]??n.replace(gn,"").trim(),i=[];for(let o of r.matchAll(/<slot\s+([^>]*?)\/?>/g)){let c=/\bname\s*=\s*["'](\w+)["']/.exec(o[1]);if(!c)continue;let a=[...o[1].matchAll(/\b(\w+)\s*=\s*\{/g)].map(u=>u[1]).filter(u=>u!=="name");i.push({name:c[1],props:a})}return i}function ss(e){let s=[],t=[],n=null,r=0,i=o=>r<=0&&/from\s*['"][^'"]+['"]\s*;?\s*$/.test(o);for(let o of e.split(`
22
+ `)){if(n){n.push(o);for(let c of o)c==="{"||c==="("?r++:(c==="}"||c===")")&&r--;i(o)&&(s.push(n.join(`
23
+ `)),n=null);continue}if(/^\s*import\b/.test(o)){n=[o],r=0;for(let c of o)c==="{"||c==="("?r++:(c==="}"||c===")")&&r--;i(o)&&(s.push(o),n=null);continue}t.push(o)}return n&&s.push(n.join(`
24
+ `)),{imports:s.join(`
25
+ `),rest:t.join(`
26
+ `)}}var Ct=new Map,rs=new Map;function ks(e){let s=rs.get(e);return s||(s=new Set,rs.set(e,s)),s}var Ss=[],Fr=2e3,os=new WeakMap,is=new WeakMap;function Dr(e){let s=os.get(e);if(s===void 0){let t=[];for(let[n,r]of e)t.push(`${n}#${r.index}:${r.scopeKey}:${r.slots.join("|")}`);s=t.join(";"),os.set(e,s)}return s}function qr(e){let s=is.get(e);if(s===void 0){let t=[];for(let n of e){if(!n.transform)continue;let r;try{r=String(n.transform)}catch{r="opaque"}t.push(`${n.name}${Qt(r)}`)}s=t.join(""),is.set(e,s)}return s}function Br(e,s,t,n,r){let i;try{i=P.statSync(e)}catch{return null}let o=[e,String(i.mtimeMs),String(i.size),s,t?"1":"0",Dr(n),qr(r)],c=ks(e);for(let a of c)try{o.push(`${a}${String(P.statSync(a).mtimeMs)}`)}catch{o.push(`${a}gone`)}for(let a of Ss)try{o.push(`watch:${a}${String(P.statSync(a).mtimeMs)}`)}catch{}return o.join("\0")}var Hr=(()=>{try{return String(P.statSync(Tt(import.meta.url)).mtimeMs)}catch{return"noid"}})(),dt=(()=>{try{let e=_.join(ws.tmpdir(),"rosefc-compile-cache");return P.mkdirSync(e,{recursive:!0}),e}catch{return null}})(),Jr=0;function Qt(e){let s=2166136261;for(let t=0;t<e.length;t++)s^=e.charCodeAt(t),s=Math.imul(s,16777619);return(s>>>0).toString(16).padStart(8,"0")}function Es(e){return _.join(dt,Qt(e+"|"+Hr)+".json")}function Wr(e){if(!dt||process.env.ROSEFC_NO_DISK_CACHE==="1")return null;try{let s=JSON.parse(P.readFileSync(Es(e),"utf-8"));if(s&&typeof s=="object"&&typeof s.ssr=="string")return s}catch{}return null}function zr(e,s){if(!dt||process.env.ROSEFC_NO_DISK_CACHE==="1")return;let t=Es(e),n=JSON.stringify(s);P.promises.writeFile(t,n).catch(()=>{P.promises.mkdir(dt,{recursive:!0}).then(()=>P.promises.writeFile(t,n)).catch(()=>{})});try{if(!(Jr++&511)){let r=P.readdirSync(dt);if(r.length>5e3)for(let i of r)try{P.unlinkSync(_.join(dt,i))}catch{}}}catch{}}async function Ur(e,s,t,n,r,i){let o=Br(e,t,n,i,r);if(o){let a=Ct.get(o);if(a)return{...a};let u=Wr(o);if(u)return u}let c=await Vr(e,s,t,n,r,i);if(o){if(Ct.size>=Fr){let a=Ct.keys().next().value;a!==void 0&&Ct.delete(a)}Ct.set(o,c),zr(o,c)}return c}function as(e,s){let t=e.match(/(?:^|\n)\s*export\s+(?:const|let|var)\s+hotVary\s*=\s*\[([\s\S]*?)\]\s*;?/);if(!t)return;let n=[];for(let r of t[1].split(",")){let i=r.trim().replace(/^['"`]|['"`]$/g,"");if(!i)continue;let o=i.toLowerCase();if(!/^[a-z0-9!#$%&'*+.^_`|~-]+$/.test(o))throw new M("E-EXPORT",`${s}: export const hotVary must list request header names (got '${i}')`,{file:s,line:Te(e,t),hint:"hotVary is a list of the request headers this route negotiates on, e.g. export const hotVary = ['x-locale', 'x-rv-url']"});if(o==="accept-encoding")throw new M("E-EXPORT",`${s}: hotVary must not name accept-encoding - the server stores raw bytes and re-negotiates the encoding on every request`,{file:s,line:Te(e,t),hint:"drop accept-encoding from hotVary; it is already handled per request"});o==="cookie"||o==="accept-language"||n.includes(o)||n.push(o)}return n.length?n:void 0}async function Vr(e,s,t,n=!1,r=[],i=new Map){let o=await P.promises.readFile(e,"utf-8");for(let $ of r)if($.transform)try{let S=await $.transform(o,e);if(typeof S=="string")o=S;else{o=S.code;for(let j of S.deps??[])ks(e).add(j)}}catch(S){throw new M("E-PLUGIN",`plugin ${$.name} failed on ${_.basename(e)}: ${S instanceof Error?S.message:String(S)}`,{file:e,hint:"the error above came from inside the plugin - fix its transform() (or remove the plugin from rosefc.config.js)"})}if(o=Un(o,"web"),n){let S=o.match(Ot)?.[1]??"",j=[...new Set([...[...S.matchAll(/(?:^|\n)\s*export\s+(?:async\s+)?function\s+(\w+)\s*\(/g)].map(Ce=>Ce[1]),...[...S.matchAll(/(?:^|\n)\s*export\s+(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s*)?(?:function\b|(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>)/g)].map(Ce=>Ce[1])])].filter(Ce=>yr.has(Ce)),G=/getContext\s*\(/.test(S)||/\$store\s*\(/.test(S)||/\$query\s*\(/.test(S),se=/\$store\s*\(/.test(S),oe=S.includes("__rosefcAuth"),_e=!G&&/(?:^|\n)\s*export\s+(?:const|let|var)\s+prerender\s*=\s*true\b/.test(S),Re=ss(ns(S,e,i).script),Fe=new Set([...S.matchAll(/import\s*\{([^}]*)\}\s*from\s*['"]\.\/runtime\.js['"]/g)].flatMap(Ce=>Ce[1].split(",").map(Ne=>Ne.trim().split(/\s+as\s+/)[0]).filter(Boolean))),Qe=Io.filter(Ce=>!Fe.has(Ce)),be=Qe.length>0?`import { ${Qe.join(", ")} } from './runtime.js';
27
+ `:"";return{ssr:"",client:"",stateKeys:[],actionNames:[],guardName:null,style:"",hasParams:!1,api:`${be}${hn(`${Re.imports}
28
+ ${Re.rest}`,"ssr").trim()}`,apiMethods:j,hasPrerender:_e,usesContext:G,usesStore:se,usesRosefcAuth:oe,hotVary:as(S,e)}}let c=o.replace(Ot,""),a=c.replace(gn,""),u=a.match(mn),g=t==="_layout"||t.endsWith("/_layout"),l=u?.[1]?g?Rs(u[1]):As(u[1],t):"",f=a.replace(mn,""),h=o.match(Ot),p=ns(h?.[1]??"",e,i),w=p.script,b=w.includes("__rosefcAuth"),m=p.imports,{imports:v,rest:k}=ss(w);if(_.basename(e)!=="_middleware.rose")for(let $ of Pr(v)){let S=v.indexOf($);throw new M("E-NODE-ONLY",`${e}: cannot import '${$}' in a page or component - it never reaches the browser. This module's script ships to the client (its $data bodies included), so move the import to src/pages/_middleware.rose or a pages/api/*.rose handler: those are server-only, and the rows travel to the page through getContext() / $data.`,{file:e,line:S>=0?at(v,S):void 0,hint:`'${$}' is a server-only module: import it inside src/pages/_middleware.rose (or a pages/api/*.rose handler) instead - a page/component script ships to the browser`})}let T=i.get(e)?.scopeKey.startsWith("components/")??!1;if(T&&/\$data\s*\(/.test(w))throw new M("E-EXPORT",`${e}: $data() is not allowed in a component - an imported component renders synchronously inside its parent. Fetch in the page's $data (or pages/_middleware.rose) and pass the value down as a prop: <Card user={user()}>.`,{file:e,hint:"move the fetch to the page (or the middleware) and pass the value down as a prop"});let x=/getContext\s*\(/.test(w)||/\$store\s*\(/.test(w)||/\$query\s*\(/.test(w),E=/\$store\s*\(/.test(w),N=/(?:^|\n)\s*export\s+(?:(?:const|let|var)\s+|(?:async\s+)?function\s+)params\b/.test(w),R=w.match(/(?:^|\n)\s*export\s+(?:const|let|var)\s+revalidate\s*=\s*(\d+)\s*;?/),U=R?Number(R[1]):void 0,L=w.match(/(?:^|\n)\s*export\s+(?:const|let|var)\s+cache\s*=\s*(\d+)\s*;?/),q=L?Number(L[1]):void 0,X=as(w,e),Y=w.match(/(?:^|\n)\s*export\s+(?:const|let|var)\s+prefetch\s*=\s*['"`](\w+)['"`]\s*;?/),pe=Y?Y[1]:void 0;if(pe&&!["off","hover","viewport","all"].includes(pe))throw new M("E-EXPORT",`${e}: export const prefetch must be 'off', 'hover', 'viewport' or 'all'`,{file:e,line:Te(w,Y),hint:"prefetch is the app-global link strategy, declared once in the root _layout.rose: 'off' | 'hover' (default) | 'viewport' | 'all'"});let O=w.match(/(?:^|\n)\s*export\s+(?:const|let|var)\s+lazyHydration\s*=\s*(true|false)\s*;?/),A=O?O[1]==="true":void 0;if(O&&!A)throw new M("E-EXPORT",`${e}: export const lazyHydration must be true (or be absent - hydration is eager by default)`,{file:e,line:Te(w,O),hint:"omit the export entirely, or set it to exactly true - lazy hydration is opt-in per app, declared once in the root _layout.rose"});let V=w.match(/(?:^|\n)\s*export\s+(?:const|let|var)\s+vitals\s*=\s*([^;\n]+)\s*;?/),Q=V?V[1].trim()==="true":void 0;if(V&&!Q)throw new M("E-EXPORT",`${e}: export const vitals must be true (or be absent - the hook ships only when an app asks for it)`,{file:e,line:Te(w,V),hint:"omit the export entirely, or set it to exactly true - the web-vitals hook is opt-in per app"});let ie=w.match(/(?:^|\n)\s*export\s+(?:const|let|var)\s+bundle\s*=\s*['"`](\w+)['"`]\s*;?/),ge=ie?ie[1]:void 0;if(ge&&!["inline","split","sliced"].includes(ge))throw new M("E-EXPORT",`${e}: export const bundle must be 'inline', 'split' or 'sliced'`,{file:e,line:Te(w,ie),hint:"'inline' (default) is the single-document mode; 'split' is mode B for large apps - route-level chunks, loaded on demand; 'sliced' inlines the runtime plus each route's own render chain and shares the rest via a nav chunk"});let ke=w.match(/(?:^|\n)\s*export\s+(?:const|let|var)\s+csr\s*=\s*(true|false)\s*;?/),Ae=ke?ke[1]!=="false":void 0,ce=w.match(/(?:^|\n)\s*export\s+(?:const|let|var)\s+shell\s*=\s*(true|false)\s*;?/),C=ce?ce[1]!=="false":void 0,$e=w.match(/(?:^|\n)\s*export\s+(?:const|let|var)\s+buffer\s*=\s*(true|false)\s*;?/),Oe=$e?$e[1]!=="false":void 0,Z=/\b(?:redirect|notFound)\s*\(/.test(w)||void 0;if(Ae===!1){let $=/\son:[a-z]+\s*=/.exec(o)??/\b(?:onMount|onCleanup|refresh)\s*\(/.exec(w);if($){let S=$===(/\son:[a-z]+\s*=/.exec(o)??void 0)?o:w;throw new M("E-EXPORT",`${e}: csr = false cannot ship ${$[0].trim()} - event wiring, onMount/onCleanup and refresh() all need the client bundle. (Forms still work without JS: a native POST runs the server action.)`,{file:e,line:Te(S,$),hint:'drop csr = false (let the compiler decide), or remove the client-only code - a native <form method="POST"> server action works without the bundle'})}}let I,J=us(w,"headers");if(J){let $;try{$=new Function(`return ${J}`)()}catch{throw new M("E-EXPORT",`${e}: export const headers must be an object literal`,{file:e,hint:"write it as one literal: export const headers = { 'x-robots-tag': 'noindex' }"})}if(!$||typeof $!="object"||Array.isArray($)||Object.values($).some(S=>typeof S!="string"))throw new M("E-EXPORT",`${e}: export const headers must be a flat map of string -> string`,{file:e,hint:"every value must be a string literal (a number or an array fails here instead of shipping verbatim)"});I=$}let te,le=us(w,"csp");if(le){let $;try{$=new Function(`return ${le}`)()}catch{throw new M("E-EXPORT",`${e}: export const csp must be an object literal`,{file:e,hint:"write it as one literal: export const csp = { nonce: true }"})}let S=$?.nonce;if(S!==void 0&&typeof S!="boolean")throw new M("E-EXPORT",`${e}: csp.nonce must be a boolean`,{file:e,hint:"csp.nonce is a switch: true (per-request nonce, the route becomes dynamic) or absent (the default hashed policy)"});te=S===!0}let{clean:ee,exports:de,actions:me,props:K,guard:fe}=Zr(k),F=ee,we=new Set(me.map($=>$.name)),ae=[];/\son:[a-z]+\s*=/.test(o)&&ae.push("event wiring (on:)"),(/<form[^>]*\son:[a-z]+\s*=/i.test(o)||/\$action:|data-on-/.test(o))&&ae.push("a form bound to a client dispatch ($action)");let Se=w.match(/\b(?:onMount|onCleanup|refresh|adopt)\s*\(|(?:\$action|\$effect)\s*\(/);Se&&ae.push(`${Se[0].replace(/\s*\($/,"")}()`),o.includes("{#defer")&&ae.push("{#defer} progressive content"),o.includes("{#await")&&ae.push("{#await} async block");let De=ae.length>0,je=[];if(!De){let $=ts(o),S=ts(w),j=Tr(S);/\son[a-z]+\s*=\s*["'][^"']*["']/i.test($)&&je.push('an inline on* attribute (e.g. onclick="...") - it cannot fire without the bundle; use on:click or set csr = true'),/javascript:/i.test($)&&je.push("a javascript: URL - it needs the bundle to run; link to a real route"),/\b(?:eval|new Function)\s*\(/.test(j)&&je.push("eval()/new Function() - client code the predicate cannot see"),/\b(?:document|window|localStorage|sessionStorage)\s*\.|\b(?:add|remove)EventListener\s*\(|\brequestAnimationFrame\s*\(|\bMutationObserver\b|\bnavigator\s*\.|\blocation\s*\.\s*(?:href|assign|replace|reload|pathname|search|hash|origin)\b|\b(?:setTimeout|setInterval)\s*\(/.test(j)&&je.push("browser-only code (document./window./addEventListener/a timer/...) - a JS-free document never ships this script to the browser, so it throws on the server or runs there and never reaches the client; if the route needs the browser, set csr = true")}let ye=f.match(ys),Pe=c.match(gn)?.[1]??"",Je=ye?ye[1]:f.replace(Ot,"").trim(),qe=l?Gr(ps(Je,s),t):ps(Je,s),Be=Qr(F),Xe=Be.filter($=>$.kind==="state"||$.kind==="kv"||$.kind==="persist"),Dt=Be.filter($=>$.kind==="derived").map($=>$.name),mt=[...Xe.map($=>$.name),...Dt],Me=new Map;Xe.forEach($=>Me.set($.name,`set${Ue($.name)}`));{let $=Vt(w),S=new Set;for(let j of $.matchAll(/(?:^|\n)\s*(?:export\s+)?(?:async\s+)?function\s+([A-Za-z_$][\w$]*)/g))S.add(j[1]);for(let j of $.matchAll(/(?:^|\n)\s*(?:export\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)/g))S.add(j[1]);for(let j of Xe){let G=Me.get(j.name);if(S.has(G))throw new M("E-SCRIPT",`${e}: the automatic setter "${G}" for $state("${j.name}") collides with a same-named declaration in the script`,{file:e,hint:`rename your function, or drop the auto setter and write $setState("${j.name}", v) - the explicit form never collides`})}}let wt=(()=>{let $=["state","derived","kv","persist"],S=Be.map((oe,_e)=>({d:oe,i:_e})).filter(({d:oe})=>$.includes(oe.kind)),j=new Set(S.map(({d:oe})=>oe.name)),G=[],se=new Set;for(let oe=0;oe<=S.length;oe++){let _e=!1;for(let{d:Re,i:Fe}of S){if(se.has(Re.name))continue;[...new Set([...Re.expr.matchAll(/\b([A-Za-z_$][\w$]*)\b/g)].map(be=>be[1]))].filter(be=>j.has(be)&&be!==Re.name).every(be=>se.has(be))&&(G.push(Fe),se.add(Re.name),_e=!0)}if(!_e)break}return G})(),Ye=$=>{let S=T?`${t}:${$.name}`:$.name;if($.kind==="state")return`const [${$.name}, ${Me.get($.name)}] = state(${JSON.stringify(S)}, ${$.expr});`;let G=$.expr.includes("=>")||$.expr.startsWith("function")?$.expr:`() => (${$.expr})`;if($.kind==="persist")return`const [${$.name}, ${Me.get($.name)}] = persistState(${JSON.stringify(S)}, ${$.expr});`;if($.kind==="derived")return`const ${$.name} = () => (${Ve($.expr,mt)});`;if($.kind==="kv"){let se=/^(.*)\s*,\s*(\d+)\s*$/s.exec($.expr),oe=se?se[1]:$.expr,_e=se?se[2]:"300";return`const __seeded_${$.name} = isSeeded(${JSON.stringify(S)});
29
+ const [${$.name}, set${Ue($.name)}] = state(${JSON.stringify(S)}, null);
30
+ if (!__seeded_${$.name}) { const __v_${$.name} = await globalThis.__rosefcKvApi.kvMemo(${JSON.stringify("__kvh:"+t+":"+$.name)}, ${oe}, ${_e}); set${Ue($.name)}(__v_${$.name}); markSeeded(${JSON.stringify(S)}); }`}return`const __seeded_${$.name} = isSeeded(${JSON.stringify(S)});
31
+ const [${$.name}, set${Ue($.name)}] = state(${JSON.stringify(S)}, null);
32
+ if (!__seeded_${$.name}) { const __v_${$.name} = await $data(${G}); set${Ue($.name)}(__v_${$.name}); markSeeded(${JSON.stringify(S)}); }`},yt=[],ot="",it=0;Be.forEach(($,S)=>{let j=Kr(F,$.start)===0;if(!j){if($.kind==="derived")throw new Error(`${e}: $derived must be a top-level declaration - inside a function body a plain const arrow already does this natively`);yt.push($)}ot+=F.slice(it,$.start)+(j?`'__rvdecl${S}__';`:""),it=$.end}),ot+=F.slice(it);let rn=new Set(Xe.map($=>$.name)),qt=$=>rn.has($),bt=Dn(F);if(bt)throw new M("E-STATE",`${e}: ${bt} is a $derived value and is written here - a $derived is read-only`,{hint:`make ${bt} a $state, or derive a different name from it`});let Le=ln(ot,qt).replace(pr,($,S,j)=>{let G=S.trim().replace(/^['"`]|['"`]$/g,"");if(Dt.includes(G))throw new Error(`${e}: $setState('${G}', ...) - a $derived value is read-only; make it $state or derive a different expression`);return`${Me.get(G)||`set${Ue(G)}`}(${j})`});if(Le=Ve(Le,mt),[...Le.matchAll(/'__rvdecl(\d+)__';/g)].length===wt.length){let S=0;Le=Le.replace(/'__rvdecl(\d+)__';/g,(j,G)=>Ye(Be[wt[S++]??Number(G)]))}else Le=Le.replace(/'__rvdecl(\d+)__';/g,(S,j)=>Ye(Be[Number(j)]));let $t=yt.filter($=>$.kind==="state").map(Ye).join(`
33
+ `),Ht=yt.filter($=>$.kind==="data").map(Ye).join(`
34
+ `),Jt=wn(ln(qe,qt),mt).replace(/<img\b(?![^>]*?\sloading=)/gi,'<img loading="lazy"').replace(/<img\b(?![^>]*?\sdecoding=)/gi,'<img decoding="async"'),on=e.replace(/[^\w]/g,"_").replace(/^_+|_+$/g,"").slice(-40),et=Lr(Jt,we,e,on),Wt=et.inlineCount,We=Be.filter($=>$.kind!=="derived").map($=>$.name),Ie=[],tt=0,zt=new Set(m.map($=>$.name)),_t=new Set(K.map($=>$.name)),xt=et.template.replace(/\sbind:(value|checked|this|open)\s*=\s*\{([\w$]+)(?:\(\))?\}/g,($,S,j,G,se)=>{let oe=se.lastIndexOf("<",G),_e=oe>=0?se.slice(oe,G):"",Re=/^<([a-zA-Z][^\s/>]*)/.exec(_e)?.[1]??"";if(!We.includes(j)&&!_t.has(j))throw new Error(`${e}: bind:${S}={${j}} must name a $state declaration`+(We.length?` (state keys here: ${We.join(", ")})`:" (this file declares no $state)"));if(S==="this")return` data-bind-this="${j}"`;if(!We.includes(j)){let Ne="on"+Ue(S)+"Change",xe=`__rvbind_${t.replace(/\W/g,"_")}_${tt++}`;return/^<select[\s>]/i.test(_e)&&/\smultiple\b/i.test(_e)?(Ie.push({event:"change",fn:`${xe}: (e) => __p.${Ne}?.(Array.from(e.target.selectedOptions, (o) => o.value))`}),` data-selmulti={(__rvlive('value', ${j}) || []).join(',')} data-on-change="${xe}"`):S==="checked"?(Ie.push({event:"change",fn:`${xe}: (e) => __p.${Ne}?.(e.target.checked)`}),` checked={__rvlive('checked', ${j})} data-on-change="${xe}"`):S==="open"?(Ie.push({event:"toggle",fn:`${xe}: (e) => __p.${Ne}?.(e.target.open)`}),` open={__rvlive('open', ${j})} data-on-toggle="${xe}"`):(Ie.push({event:"input",fn:`${xe}: (e) => { const t = e.target; const raw = t.type === 'number' || t.type === 'range' ? t.valueAsNumber : t.value; __p.${Ne}?.(typeof raw === 'number' && Number.isNaN(raw) ? null : raw); }`}),` value={__rvlive('value', ${j})} data-on-input="${xe}" data-on-change="${xe}"`)}if(Re&&zt.has(Re)){let Ne=Me.get(j),xe="on"+Ue(S)+"Change";return` ${S}={${j}()} __live-${S}={${j}} ${xe}={${Ne}}`}if(S==="value"&&/^<select[\s>]/i.test(_e)&&/\smultiple\b/i.test(_e)){let Ne=Me.get(j),xe=`__rvbind_${t.replace(/\W/g,"_")}_${tt++}`;return Ie.push({event:"change",fn:`${xe}: (e) => ${Ne}(Array.from(e.target.selectedOptions, (o) => o.value))`}),` data-selmulti={${j}().join(',')} data-on-change="${xe}"`}if(S==="open"){let Ne=Me.get(j),xe=`__rvbind_${t.replace(/\W/g,"_")}_${tt++}`;return Ie.push({event:"toggle",fn:`${xe}: (e) => ${Ne}(e.target.open)`}),` open={${j}()} data-on-toggle="${xe}"`}let Fe=Me.get(j),Qe=S==="checked"?"change":"input",be=`__rvbind_${t.replace(/\W/g,"_")}_${tt++}`;Ie.push({event:Qe,fn:S==="checked"?`${be}: (e) => ${Fe}(e.target.checked)`:`${be}: (e) => { const t = e.target; const raw = t.type === 'number' || t.type === 'range' ? t.valueAsNumber : t.value; ${Fe}(typeof raw === 'number' && Number.isNaN(raw) ? null : raw); }`});let Ce=S==="checked"?` data-on-change="${be}"`:` data-on-input="${be}" data-on-change="${be}"`;return` ${S}={${j}()}${Ce}`}),vt=new Map(m.map($=>{let S=_.resolve(_.dirname(e),$.specifier),j=i.get(S);return[$.name,{index:j.index,slots:j.slots}]})),kt=[],St=0,d=!_t.size||!/<(input|textarea|select)[\s>]/i.test(xt)?xt:ht(xt,$=>{let{tag:S,attrs:j}=$;if(!/^(input|textarea|select)$/i.test(S)||/\sdata-on-input=|\sdata-selmulti=/.test(j))return null;let G=/\svalue\s*=\s*\{([\w$]+)\}/.exec(j);if(!G||!_t.has(G[1]))return null;let se=G[1],oe=`__rvbind_${t.replace(/\W/g,"_")}_${tt++}`;Ie.push({event:"input",fn:`${oe}: (e) => { const t = e.target; const raw = t.type === 'number' || t.type === 'range' ? t.valueAsNumber : t.value; __p.onValueChange?.(typeof raw === 'number' && Number.isNaN(raw) ? null : raw); }`});let _e=/^select$/i.test(S)&&/\smultiple\b/i.test(j),Re=j.replace(G[0],` value={__rvlive('value', ${se})}`),Fe=_e?` data-selmulti={(__rvlive('value', ${se}) || []).join(',')} data-on-change="${oe}"`:` data-on-input="${oe}" data-on-change="${oe}"`;return Re+Fe}),y=d.includes("bind:group")?ht(d,$=>{let{tag:S,attrs:j}=$,G=/\sbind:group\s*=\s*\{([\w$]+)(?:\(\))?\}/.exec(j);if(!G)return null;let se=G[1],oe=!We.includes(se);if(oe&&!_t.has(se))throw new M("E-TEMPLATE",`${e}: bind:group={${se}} must name a $state declaration`,{hint:"the group state holds the selected value (radio) or an ARRAY of checked values (checkbox) - declare it: let "+se+' = $state("")'});if(!oe&&zt.has(S)){let Ks=Me.get(se);return j.replace(G[0],` group={${se}()} __live-group={${se}} onGroupChange={${Ks}}`)}if(!/\stype\s*=\s*["'](radio|checkbox)["']/.test(j))throw new M("E-TEMPLATE",`${e}: bind:group is for radio and checkbox inputs`,{hint:'<input type="radio" value="v" bind:group={state}> holds the selected value; type="checkbox" holds an ARRAY of the checked values (declare the state as $state([]))'});let _e=/\stype\s*=\s*["']checkbox["']/.test(j),Re=/\svalue\s*=\s*"([^"]*)"|\svalue\s*=\s*'([^']*)'/.exec(j);if(!Re||/\{/.test(Re[0]))throw new M("E-TEMPLATE",`${e}: a bind:group input needs a static value attribute`,{hint:'<input type="radio" value="free" bind:group={plan}> - the value IS what the state receives'});if(/\schecked\s*=/.test(j))throw new M("E-TEMPLATE",`${e}: a bind:group input cannot also carry checked=`,{hint:"the group state alone decides which inputs are checked"});let Fe=oe?"":Me.get(se),Qe=`__rvbg_${t.replace(/\W/g,"_")}_${St++}`,be=JSON.stringify(Re[1]??Re[2]),Ce=oe?`__rvlive('group', ${se})`:`${se}()`,Ne=_e?`${Ce}.includes(${be})`:`${Ce} === ${be}`,xe=_e?oe?`__p.onGroupChange?.(e.target.checked ? [...${Ce}, ${be}] : ${Ce}.filter((x) => x !== ${be}))`:`${Fe}(e.target.checked ? [...${se}(), ${be}] : ${se}().filter((x) => x !== ${be}))`:oe?"__p.onGroupChange?.(e.target.value)":`${Fe}(e.target.value)`;return kt.push({event:"change",fn:`${Qe}: (e) => { ${xe}; }`}),j.replace(G[0],` checked={${Ne}} data-on-change="${Qe}"`)}):d,D=et.bindings.concat(Ie,kt),W=y.replace(/\suse:([\w-]+)(\s*=\s*\{([\s\S]*?)\})?/g,($,S,j,G)=>j?` data-use="${S}" data-use-param={JSON.stringify(${G})}`:` data-use="${S}"`),z=Vn(W,"web"),B=oo(z,e),H=so(B),ne=co(H,e),Ee=io(ne,e),ve=ao(Ee,e),ze=to(ve,e),Us=uo(ze),an=fo(Us),cn=po(an.template,e),Vs=lo(cn.template,e),Cn=$o(Vs.replace(mr,($,S,j)=>{let G=`{__slot(${Yn(S)})}`;if(j){if(/\{[^{}]*\}/.test(j))throw new M("E-TEMPLATE",`${e}: slot fallback content must be static markup`,{hint:"a {expr} inside a slot fallback has no reactive scope here - render the dynamic part in the parent and pass it as the slot content"});return`{__slot(${Yn(S)}, ${JSON.stringify(j)})}`}return G}).replace(gr,($,S)=>S&&S.trim()?`{__slotDefault(${JSON.stringify(S)})}`:"{__slot__}"),vt);bo(Cn,e);let Tn=new Set;{let $=Vt(w),S=new Set(Xe.map(G=>G.name)),j=G=>/^(?:async\s*)?(?:function\b|\([^)]*\)\s*=>)/.test(G)||/^(?:async\s*)?\(/.test(G)&&G.includes("=>")||/^(?:async\s+)?[A-Za-z_$][\w$]*\s*=>/.test(G);for(let G of $.matchAll(/(?:^|\n)\s*(?:export\s+)?(?:const|let)\s+([A-Za-z_$][\w$]*)\s*=\s*([^;]{0,200})/g))S.has(G[1])||/^\s*\$state\b/.test(G[2])||j(G[2].trim())||Tn.add(G[1])}yn=0,Pt=e,Gt=new Set,bn=!0,xn=new Set(Tn);let On=He(Cn,"h","__c",null,0,!0,vt);bn=!1,xn=new Set;let jn=$n,Gs=_n;$n="",_n={},Gt=new Set;let Pn=vn;if(vn=null,Pn)throw new M("E-TEMPLATE",`${e}: {@const ${Pn}} is declared twice at the top level`,{file:e,hint:"a const cannot be redeclared in the same scope - rename one of them, or wrap the second in a block ({#if}/{#each}) where it shadows the first instead of colliding with it"});for(let $ of D)/^\w+$/.test($.fn)||($.fn=Ve($.fn,[],Gs));let Et=Pe.trim()?mo(Pe):"";if(!T&&l){let S=`<style id="${"rosefc-style-"+t.replace(/[^a-zA-Z0-9_-]/g,"-")}">${l}</style>`;Et=(Et?Et+`
35
+ `:"")+`__hd += ${JSON.stringify(S)};`}let Mn=/<slot\s+[^>]*\bname\s*=/.test(qe),Nn=me.length>0?`${de}
36
+ ${me.map($=>$.stmt).join(`
37
+ `)}`:de,Ln=fe?`
38
+ ${fe}`:"",Zs=_.basename(e)==="_middleware.rose",In=ho(an.count,an.holds)+(cn.blocks.length?`
39
+ `+go(cn.blocks):""),Xs=Zs?`${It}
40
+
41
+ ${v}
42
+
43
+ ${Nn}
44
+ ${Ln}
45
+
46
+ ${Le}
47
+ `:Fo(Le+In,On,$t,Nn,Et,K,Mn,v,T,Ln,me.length>0,Ht,jn,Wt>0),Qs=Do(Le+In,On,$t,D,de,Et,K,Mn,v,T,Ht,jn,Wt>0);return{ssr:hn(Xs,"ssr"),client:hn(Qs,"client"),stateKeys:We,actionNames:[...we],guardName:fe?"beforeAction":null,style:l,hasParams:N,usesContext:x,usesStore:E,revalidate:U,cache:q,hotVary:X,csr:Ae,shell:C,buffer:Oe,controlSignal:Z,prefetch:pe,lazyHydration:A,vitals:Q,bundle:ge,needsClient:De,clientReasons:ae,jsWarnings:je,headers:I,cspNonce:te,usesRosefcAuth:b,props:K,roseImports:m,isComponent:T}}function Rs(e){return e.replace(/(-?\d*\.?\d+)rpx/g,(s,t)=>{let n=Number(t)/2;return n===0?"0":`${Math.round(n*100)/100}px`})}function cs(e){return e.replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^"']+/g,s=>s[0]==='"'||s[0]==="'"?s:s.replace(/\s+/g," ").replace(/\s*([:;{},])\s*/g,"$1").trim()).trim()}function As(e,s){let t=`[data-rosefc-c="${s}"]`,n=a=>{let u=a.trim();if(!u.includes(":global"))return`${t} ${u}, ${t}${u}`;let g=u.replace(/:global\([^()]*\)/g,f=>f.slice(8,-1)).trim();return u.replace(/:global\([^()]*\)/g,"").trim()?`${t} ${g}, ${t}${g}`:g},r=Rs(e.replace(/\/\*[\s\S]*?\*\//g,"")),i="",o="",c=0;for(;c<r.length;){let a=r[c];if(a==="{"){let u=1,g=c+1;for(;g<r.length&&u>0;)r[g]==="{"?u++:r[g]==="}"&&u--,g++;let l=r.slice(c+1,g-1),f=o.trim();if(f.startsWith("@"))i+=`${f}{${/^@(?:-[\w]+-)?keyframes/.test(f)?cs(l):As(l,s)}}`;else if(f){let h=f.split(",").map(p=>n(p)).join(",");i+=`${h}{${cs(l)}}`}o="",c=g;continue}a!=="}"&&a!==`
48
+ `&&a!=="\r"?o+=a:a==="}"&&(o=""),c++}return i.trim()}function Gr(e,s){let t=` data-rosefc-c="${s}"`,n="",r=0,i=0;for(;i<e.length;){let o=e.indexOf("<",i);if(o===-1){n+=e.slice(i);break}n+=e.slice(i,o);let c=o+1,a="",u=0,g=0;for(;c<e.length;){let w=e[c];if(a)w===a&&(a="");else if(w==='"'||w==="'")a=w;else if(w==="(")u++;else if(w===")")u=Math.max(0,u-1);else if(w==="{")g++;else if(w==="}")g=Math.max(0,g-1);else if(w===">"&&u===0&&g===0)break;c++}let l=e.slice(o,c+1),f=/^<\//.test(l),h=l.match(/^<\/?([a-zA-Z][\w-]*)/),p=/\/>$/.test(l)||h&&Cs.has(h[1].toLowerCase());if(h&&!f&&r===0&&!p){let w=l.endsWith("/>")?l.length-2:l.length-1;n+=l.slice(0,w)+t+l.slice(w),r++}else n+=l,h&&(r+=f?-1:p?0:1);i=c+1}return n}var Cs=new Set(["img","br","hr","input","meta","link","source","wbr"]),ls=/^[ \t]*export\s+(?:(const|let|var)|(?:async\s+)?function)\s+(\w+)/gm;function us(e,s){let t=new RegExp(`(?:^|\\n)\\s*export\\s+(?:const|let|var)\\s+${s}\\s*=\\s*`).exec(e);if(!t)return null;let n=t.index+t[0].length;if(e[n]!=="{")return null;let r=n,i=0;for(;n<e.length;n++){let o=e[n];if(o==="{")i++;else if(o==="}"&&(i--,i===0)){n++;break}}return e.slice(r,n)}function Zr(e){let s=[],t=[],n=[],r=[],i="",o=0,c;for(ls.lastIndex=0;c=ls.exec(e);){let a=c[1],u=c.index+c[0].indexOf("export"),g=u+c[0].length-c[0].indexOf("export");if(a){let p=0;for(;g<e.length;){let w=e[g];if(w==="("||w==="{"||w==="[")p++;else if(w===")"||w==="}"||w==="]"){if(p--,p===0){g++;break}}else if(p===0&&w===";"){g++;break}else if(p===0&&w===`
49
+ `){let b=e.slice(g+1);if(!/^\s*[.([{+\-*/?:,=&|]/.test(b)){g++;break}}g++}e[g]===";"&&g++}else{for(;g<e.length&&e[g]!=="{";)g++;let p=0;for(;g<e.length;){let w=e[g];if(w==="{")p++;else if(w==="}"&&(p--,p===0)){g++;break}g++}}i+=e.slice(o,u);let l=e.slice(u,g).trim(),f=l.match(/^export\s+async\s+function\s+(\w+)/);if(l.match(/^export\s+(?:async\s+)?function\s+(\w+)/)?.[1]==="beforeAction")r.push(l);else if(f)t.push({name:f[1],stmt:l});else if(a==="let"){let p=l.match(/^export\s+let\s+(\w+)\s*(?:=\s*([\s\S]*?))?\s*;?$/);p?n.push({name:p[1],def:p[2]?.trim()??null}):s.push(l)}else s.push(l);o=g}return i+=e.slice(o),{clean:i,exports:s.join(`
50
+ `),actions:t,props:n,guard:r.join(`
51
+ `)}}var Xr=new Set("(,=:[!&|?{};+-*%<>~^".split(""));function Ts(e,s){let t=s-1;for(;t>=0&&/\s/.test(e[t]);)t--;if(t<0)return!0;let n=e[t];if(Xr.has(n))return!0;if(/[A-Za-z0-9_$]/.test(n)){let r=vs(e,t);return r?["return","typeof","instanceof","in","of","new","delete","void","throw","case","do","else"].includes(r):!1}return!1}function Qr(e){let s=[],t=Vt(e);Kn.lastIndex=0;let n;for(;n=Kn.exec(t);){let r=n.index+n[0].length,i=()=>{for(;r<e.length&&/\s/.test(e[r]);)r++};if(i(),e[r]==="<"){let l=0;for(;r<e.length;){let f=e[r];if(f==="<")l++;else if(f===">"&&e[r-1]!=="="){if(l--,l===0){r++;break}}else f==="="&&e[r+1]===">"&&r++;r++}i()}if(e[r]!=="(")continue;let o=r+1,c=1,a=o;for(;a<e.length&&c>0;){let l=e[a];l==="("?c++:l===")"&&c--,a++}let u=a,g=hr.exec(e.slice(a));g&&(u=a+g[0].length),e[u]===";"&&u++,s.push({name:n[1],kind:n[2],expr:e.slice(o,a-1).trim(),start:n.index,end:u})}return s}function Kr(e,s){let t=0,n=0;for(;n<s;){let r=e[n];if(r==="'"||r==='"'||r==="`"){let i=r;for(n++;n<s;){if(e[n]==="\\"){n+=2;continue}if(e[n]===i){n++;break}if(i==="`"&&e[n]==="$"&&e[n+1]==="{"){let o=1;for(n+=2;n<s&&o>0;)e[n]==="{"?o++:e[n]==="}"&&o--,n++;continue}n++}continue}if(r==="/"&&e[n+1]==="/"){let i=e.indexOf(`
52
+ `,n);n=i===-1?e.length:i;continue}if(r==="/"&&e[n+1]==="*"){let i=e.indexOf("*/",n+2);n=i===-1?e.length:i+2;continue}if(r==="/"&&Ts(e,n)){n++;let i=!1;for(;n<s;){let o=e[n];if(o==="\\"){n+=2;continue}if(i){o==="]"&&(i=!1),n++;continue}if(o==="["){i=!0,n++;continue}if(o==="/"){n++;break}if(o===`
53
+ `)break;n++}for(;n<s&&/[a-z]/.test(e[n]);)n++;continue}r==="{"?t++:r==="}"&&t--,n++}return t}function Vt(e){let s="",t=0,n=(r,i)=>{for(let o=r;o<i&&o<e.length;o++)s+=e[o]===`
54
+ `?`
55
+ `:" "};for(;t<e.length;){let r=e[t];if(r==="'"||r==='"'||r==="`"){let i=r,o=t+1;for(;o<e.length;){if(e[o]==="\\"){o+=2;continue}if(e[o]===i){o++;break}if(i==="`"&&e[o]==="$"&&e[o+1]==="{"){let c=Lt(e,o+1);o=c<0?e.length:c+1;continue}o++}n(t,Math.min(o,e.length)),t=o;continue}if(r==="/"&&e[t+1]==="/"){let i=e.indexOf(`
56
+ `,t),o=i===-1?e.length:i;n(t,o),t=o;continue}if(r==="/"&&e[t+1]==="*"){let i=e.indexOf("*/",t+2),o=i===-1?e.length:i+2;n(t,o),t=o;continue}if(r==="/"&&Ts(e,t)){let i=t+1,o=!1;for(;i<e.length;){let c=e[i];if(c==="\\"){i+=2;continue}if(o){c==="]"&&(o=!1),i++;continue}if(c==="[")o=!0;else if(c==="/"){i++;break}else if(c===`
57
+ `)break;i++}for(;i<e.length&&/[a-z]/.test(e[i]);)i++;n(t,i),t=i;continue}s+=r,t++}return s}var Yr=new Set(["true","false","null","undefined","NaN","Infinity"]);function ds(e){let s=e.trim();return/^[A-Za-z_$][\w$]*$/.test(s)&&xn.has(s)?s:/^[A-Za-z_$][\w$]*$/.test(s)&&s!=="__s"&&!Yr.has(s)?`${s}()`:s}var eo=!0;function to(e,s){if(!e.includes("{#key"))return e;for(let t=0;t<10;t++){let n=/\{#key\b/g;n.lastIndex=0;let r=n.exec(e);if(!r)return e;let i=Ge(e,r.index);if(i<0)return e;let o=e.slice(r.index+5,i-1).trim();if(!o)return e;let c=i,a=/\{[#\/](?:key|if|each|boundary|island)\b/g;a.lastIndex=c;let u=1,g=-1,l;for(;l=a.exec(e);){if(l[0].startsWith("{#")){let f=Ge(e,l.index);f>=0&&(a.lastIndex=f),u++;continue}if(u--,u===0){g=l.index;break}}if(g<0)throw new M("E-TEMPLATE",`${s}: {#key ${o}} is never closed`,{hint:"every {#key} needs its {/key}"});e=e.slice(0,r.index)+`{#each [${o}] as __rvkv}`+e.slice(c,g)+"{/each}"+e.slice(g+6)}return e}function no(e){let s=/\{#(?:if|each|boundary|island)\b|\{\/(?:if|each|boundary|island)\s*\}|\{:else(?:\s+if\s+[^}]*)?\}/g,t="",n=0,r=!1;for(;;){let i=e.slice(n),c=/\{#(if|each)\b/g.exec(i);if(!c){t+=e.slice(n);break}let a=c[1],u=Ge(i,c.index);if(u<0){t+=e.slice(n);break}let g=i.slice(c.index+2+a.length,u-1),l=n+c.index,f=n+u,h=En(a,g);if(!h){t+=e.slice(n,f),n=f;continue}let p=a==="if"?h[0].trim():"";t+=e.slice(n,l),s.lastIndex=f;let w=1,b=-1,m=0,v=[],k;for(;k=s.exec(e);){let L=k[0];if(L.startsWith("{:else")){if(w===1){let q=/^\{:else\s+if\s+([^}]*)\}$/.exec(L);v.push({at:k.index,len:L.length,cond:q?q[1].trim():null})}continue}if(L.startsWith("{#")){let q=Ge(e,k.index);q>=0&&(s.lastIndex=q),w++;continue}if(w--,w===0){b=k.index,m=L.length;break}}if(b<0){t+=e.slice(l);break}if(v.length===0){t+=e.slice(l,f),n=f,r=!0;continue}let T=e.slice(f,b);if(a==="each"){let L=[...v].reverse().find(O=>O.cond===null);if(!L){t+=e.slice(l,b+m),n=b+m;continue}let q=L.at-f,X=T.slice(0,q),Y=T.slice(q+L.len),pe=h[0];t+=e.slice(l,f)+X+`{/each}{#if !(${pe}.length)}${Y}{/if}`,n=b+m,r=!0;continue}let x=[],E=0;for(let L=0;L<v.length;L++){let q=v[L],X=q.at-f;x.push({cond:L===0?null:v[L-1].cond,body:T.slice(E,X)}),E=X+q.len}x.push({cond:v[v.length-1].cond,body:T.slice(E)});let N=x.shift(),R=L=>{if(!L.length)return"";let q=L[0],X=L.slice(1);if(q.cond==null)return q.body;let Y=`{#if ${q.cond}}${q.body}{/if}`;return X.length&&(Y+=`{#if !(${q.cond})}`+R(X)+"{/if}"),Y},U=`{#if ${p}}${N.body}{/if}`;x.length&&(U+=`{#if !(${p})}`+R(x)+"{/if}"),t+=U,n=b+m,r=!0}return{template:t,changed:r}}function so(e){if(!/\sclass\s*=\s*"/.test(e)||!/\sclass\s*=\s*\{/.test(e))return e;let s=/<([a-zA-Z][^\s>/]*)((?:[^>"']|"[^"]*"|'[^']*')*?)(\/?)>/g,t="",n=0,r;for(s.lastIndex=0;r=s.exec(e);){let[i,o,c,a]=r,u=/\sclass\s*=\s*"([^"]*)"/.exec(c);if(!u)continue;let g=/\sclass\s*=\s*\{/.exec(c);if(!g||g.index===u.index)continue;let l=c.indexOf("{",g.index),f=1,h=l+1;for(;h<c.length&&f>0;){let T=c[h];if(T==='"'||T==="'"){h=Ze(c,h);continue}T==="{"?f++:T==="}"&&f--,h++}if(f!==0)continue;let p=c.slice(l+1,h-1),w=JSON.stringify(u[1]),b=` class={((v) => v == null ? ${w} : typeof v === 'object' ? ({ ${w}: true, ...v }) : (${w} + ' ' + v))(${p})}`,m=Math.min(u.index,g.index),v=Math.max(u.index+u[0].length,h),k=c.slice(0,m)+b+c.slice(v);t+=e.slice(n,r.index)+`<${o}${k}${a}>`,n=r.index+i.length}return t+=e.slice(n),t}function ro(e,s){let t=/^<([a-zA-Z][^\s>/]*)/.exec(e.slice(s));if(!t)return null;let n=s+t[0].length,r="",i=0;for(;n<e.length;){let o=e[n];if(r)o===r&&(r="");else if(o==='"'||o==="'")r=o;else if(o==="{")i++;else if(o==="}")i=Math.max(0,i-1);else if(o===">"&&i===0){let a=e.slice(s,n+1).endsWith("/>")?"/":"",u=a?n-1:n;return{start:s,end:n+1,tag:t[1],attrs:e.slice(s+t[0].length,u),selfClose:a}}n++}return null}function ht(e,s){let t="",n=0,r=0;for(;r<e.length;){let i=e.indexOf("<",r);if(i<0)break;let o=ro(e,i);if(!o){r=i+1;continue}let c=s(o);t+=e.slice(n,o.start)+(c===null?e.slice(o.start,o.end):`<${o.tag}${c}${o.selfClose}>`),n=o.end,r=o.end}return t+=e.slice(n),t}function oo(e,s){return e.includes("class:")?ht(e,t=>{let n=t.attrs;if(!n.includes("class:"))return null;let r=[],i=/\sclass:([\w-]+)\s*=\s*\{/g,o;for(;o=i.exec(n);){let f=o.index+o[0].length,h=1;for(;f<n.length&&h>0;){let p=n[f];if(p==='"'||p==="'"){f=Ze(n,f);continue}p==="{"?h++:p==="}"&&h--,f++}if(h!==0)throw new M("E-TEMPLATE",`${s}: class:${o[1]}={...} is missing its closing brace`,{file:s,hint:"the binding expression needs a matching } before the tag ends"});r.push({name:o[1],expr:n.slice(o.index+o[0].length,f-1),start:o.index,end:f})}let c=/(\sclass\s*=\s*)("([^"]*)"|'([^']*)'|\{[^}]*\})/,a=c.exec(n);if(a&&a[2].startsWith("{"))throw new M("E-TEMPLATE",`${s}: <${t.tag}> has both class={...} and class: directives`,{file:s,hint:'merge them: move the dynamic part into a class:NAME={expr} and keep the rest in class="..."'});let u=a?a[3]??a[4]??"":"",g=`(${JSON.stringify(u)}`;for(let f of r)g+=`+((${f.expr})?${JSON.stringify(" "+f.name)}:'')`;g+=")";let l=n;for(let f=r.length-1;f>=0;f--)l=l.slice(0,r[f].start)+l.slice(r[f].end);return a?l=l.replace(c,` class={${g}}`):l=` class={${g}}`+l,l}):e}function io(e,s){return/\s(?:transition|in|out):/.test(e)?ht(e,t=>{let n=t.attrs;if(!n.includes("transition:")&&!/\s(?:in|out):/.test(n))return null;let r=[],i=/\s(transition|in|out):([\w-]+)(?:\s*=\s*\{)?/g,o;for(;o=i.exec(n);){let l=o.index,f=o.index+o[0].length,h="";if(o[0].endsWith("{")){let p=1,w=f;for(;w<n.length&&p>0;){let b=n[w];if(b==='"'||b==="'"){w=Ze(n,w);continue}b==="{"?p++:b==="}"&&p--,w++}if(p!==0)throw new M("E-TEMPLATE",`${s}: transition:${o[1]}={...} is missing its closing brace`,{file:s,hint:"the transition params expression needs a matching } before the tag ends"});h=n.slice(f,w-1),f=w}r.push({dir:o[1]==="transition"?"":o[1],name:o[2],params:h,start:l,end:f})}if(r.length===0)return null;let c="";for(let l of r)c&&(c+="|"),c+=(l.dir?l.dir+":":"")+l.name+(l.params?":"+l.params:"");let a=n;for(let l=r.length-1;l>=0;l--)a=a.slice(0,r[l].start)+a.slice(r[l].end);let u=/\sdata-transition\s*=\s*("([^"]*)"|'([^']*)'|\{[^}]*\})/,g=u.exec(a);if(g){let l=g[2]??g[3]??"";a=a.replace(u,` data-transition="${l}${c?(l?"|":"")+c:""}"`)}else a=` data-transition="${c}"`+a;return a}):e}function ao(e,s){return e.includes("animate:")?ht(e,t=>{let n=t.attrs;if(!n.includes("animate:"))return null;let r=[],i=/\sanimate:([\w-]+)(?:\s*=\s*\{)?/g,o;for(;o=i.exec(n);){let l=o.index,f=o.index+o[0].length,h="";if(o[0].endsWith("{")){let p=1,w=f;for(;w<n.length&&p>0;){let b=n[w];if(b==='"'||b==="'"){w=Ze(n,w);continue}b==="{"?p++:b==="}"&&p--,w++}if(p!==0)throw new M("E-TEMPLATE",`${s}: animate:${o[1]}={...} is missing its closing brace`,{file:s,hint:"the animate params expression needs a matching } before the tag ends"});h=n.slice(f,w-1),f=w}r.push({name:o[1],params:h,start:l,end:f})}let c="";for(let l of r)c&&(c+="|"),c+=l.name+(l.params?":"+l.params:"");let a=n;for(let l=r.length-1;l>=0;l--)a=a.slice(0,r[l].start)+a.slice(r[l].end);let u=/\sdata-animate\s*=\s*("([^"]*)"|'([^']*)'|\{[^}]*\})/,g=u.exec(a);if(g){let l=g[2]??g[3]??"";a=a.replace(u,` data-animate="${l}${c?(l?"|":"")+c:""}"`)}else a=` data-animate="${c}"`+a;return a}):e}function co(e,s){return e.includes("style:")?ht(e,t=>{let n=t.attrs;if(!n.includes("style:"))return null;let r=[],i=/\sstyle:([\w-]+)\s*=\s*\{/g,o;for(;o=i.exec(n);){let f=o.index+o[0].length,h=1;for(;f<n.length&&h>0;){let p=n[f];if(p==='"'||p==="'"){f=Ze(n,f);continue}p==="{"?h++:p==="}"&&h--,f++}if(h!==0)throw new M("E-TEMPLATE",`${s}: style:${o[1]}={...} is missing its closing brace`,{file:s,hint:"the binding expression needs a matching } before the tag ends"});r.push({prop:o[1],expr:n.slice(o.index+o[0].length,f-1),start:o.index,end:f})}let c=/(\sstyle\s*=\s*)("([^"]*)"|'([^']*)'|\{[^}]*\})/,a=c.exec(n);if(a&&a[2].startsWith("{"))throw new M("E-TEMPLATE",`${s}: <${t.tag}> has both style={...} and style: directives`,{file:s,hint:'keep the static declarations in style="..." and move the dynamic ones to style:PROP={expr}'});let u=a?a[3]??a[4]??"":"",g=`${JSON.stringify(u.endsWith(";")||u===""?u:u+";")}`;for(let f of r)g+=`+${JSON.stringify(f.prop+":")}+(${f.expr})+';'`;let l=n;for(let f=r.length-1;f>=0;f--)l=l.slice(0,r[f].start)+l.slice(r[f].end);return a?l=l.replace(c,` style={${g}}`):l=` style={${g}}`+l,l}):e}function lo(e,s){if(!e.includes("{:fallback"))return e;for(let t=0;t<10;t++){let n=/\{#boundary\}|\{\/boundary\}|\{:fallback\}/g,r="",i=0,o=!1,c;for(;c=n.exec(e);){if(c[0]!=="{#boundary}")continue;let a=c.index,u=a+c[0].length,g=1,l=-1,f;for(;f=n.exec(e);){if(f[0]==="{#boundary}"){g++;continue}if(f[0]==="{/boundary}"&&(g--,g===0)){l=f.index;break}}if(l<0)break;let h=e.slice(u,l),p=/\{#(boundary|if|each|key|island)(?:\s+[^}]*)?\}|\{\/(?:boundary|if|each|key|island)\s*\}|\{:fallback\}/g,w=["boundary"],b=1,m=-1,v=0,k;for(p.lastIndex=0;k=p.exec(h);){let N=k[0];if(N==="{:fallback}"){if(w[w.length-1]!=="boundary")throw new M("E-TEMPLATE",`${s}: {:fallback} must sit directly inside a {#boundary} block`,{hint:"move it out of the {#if}/{#each} it sits in, or keep the conditional fallback in the parent"});if(m>=0)throw new M("E-TEMPLATE",`${s}: a {#boundary} can carry only one {:fallback}`,{hint:"remove the extra {:fallback} segment"});m=k.index,v=N.length;continue}if(N.startsWith("{#")){b++,w.push(N.slice(2,N.length-1).trim().split(/\s/)[0]);continue}b--,w.pop()}if(m<0)continue;let T=h.slice(0,m),x=h.slice(m+v),E=Buffer.from(x,"utf-8").toString("base64");r+=e.slice(i,a)+`{#boundary __fb="${E}"}`+T+"{/boundary}",i=l+11,o=!0}if(!o)break;e=r+e.slice(i)}return e}function uo(e){for(let s=0;s<40;s++){if(!/\{:else\b/.test(e))return e;let t=no(e);if(e=t.template,!t.changed)return e}return e}function fo(e){if(!eo){let o=/\{#defer(?:\s+hold=\\d+)?\}/g,c="",a=0;for(;;){o.lastIndex=a;let u=o.exec(e);if(!u)break;let g=u.index,l=u[0].length,f=e.indexOf("{/defer}",g+l);if(f<0)break;c+=e.slice(a,g)+e.slice(g+l,f),a=f+8}return{template:a===0?e:c,count:0,holds:[]}}let s=0,t=[],n="",r=0,i=/\{#defer(?:\s+hold=(\d+))?\}/g;for(;;){i.lastIndex=r;let o=i.exec(e);if(!o)break;let c=o.index,a=o[0].length,u=o[1]?Number(o[1]):0,g=1,l=c+a,f=-1;for(;l<e.length;){i.lastIndex=l;let w=i.exec(e),b=w?w.index:-1,m=e.indexOf("{/defer}",l);if(m<0)break;if(b>=0&&b<m){g++,l=b+w[0].length;continue}if(g--,g===0){f=m;break}l=m+8}if(f<0)break;let h=e.slice(c+a,f);t.push(u);let p=++s;n+=e.slice(r,c),n+="{#if __rvDefer"+p+"()}"+h+`{/if}
58
+ {#if !__rvDefer`+p+'()}<div class="rv-defer-loading"></div>{/if}',r=f+8}return s===0?{template:e,count:0,holds:[]}:(n+=e.slice(r),{template:n,count:s,holds:t})}function ho(e,s=[]){let t="";for(let n=1;n<=e;n++){t+="const [__rvDefer"+n+", set__rvDefer"+n+'] = state("__rvdefer'+n+`", false);
59
+ `;let r=s[n-1]||0;t+=r>0?"onMount(function () { setTimeout(function () { set__rvDefer"+n+"(true); }, "+r+`); });
60
+ `:"onMount(function () { requestAnimationFrame(function () { requestAnimationFrame(function () { set__rvDefer"+n+`(true); }); }); });
61
+ `}return t}function po(e,s){let t="",n=0,r=0,i=[];for(;;){let o=e.indexOf("{#await",n);if(o<0)break;let c=o+7,a=1;for(;c<e.length&&a>0;){let Q=e[c];Q==="{"?a++:Q==="}"&&a--,c++}if(a!==0)break;let u=c-o,g=e.slice(o+7,c-1).trim();if(!g)throw new M("E-TEMPLATE",`${s}: {#await} needs a promise expression`,{file:s,hint:"write {#await fetchUsers()}...{:then users}...{/await}"});let l=/\b(then|catch)\s+[A-Za-z_$][\w$]*\s*$/.exec(g);if(l)throw new M("E-TEMPLATE",`${s}: {#await ${g}} puts the ${l[1]} branch in the opener`,{file:s,hint:`write the branch on its own line inside the block:
62
+ {#await ${g.replace(/\s+(then|catch)\s+[A-Za-z_$][\w$]*\s*$/,"")}}
63
+ \u95B3\u30EE\u6D0Aending\u95B3\u30EE\u6CDCn{:${l[1]} ${l[0].trim().split(/\s+/)[1]}}
64
+ \u95B3?{inlineBranch[1] === 'then' ? 'fulfilled' : 'rejected'}\u95B3\u30EE\u6CDCn{/await}`});let f=/\{\#(if|each|boundary|island|await)\b/g,h=/\{\/(if|each|boundary|island|await)\}/g,p=/\{:then\b([^}]*)\}/g,w=/\{:catch\b([^}]*)\}/g,b=1,m=c,v=-1,k=-1,T=-1,x="",E="";for(;;){f.lastIndex=m,h.lastIndex=m,p.lastIndex=m,w.lastIndex=m;let Q=f.exec(e),ie=h.exec(e),ge=p.exec(e),ke=w.exec(e),Ae=1/0,ce="",C=null,$e=(Oe,Z)=>{Oe&&Oe.index<Ae&&(Ae=Oe.index,ce=Z,C=Oe)};if($e(Q,"open"),$e(ie,"close"),$e(ge,"then"),$e(ke,"catch"),!C)break;if(ce==="open"){b++,m=C.index+C[0].length;continue}if(ce==="close"){if(b===1&&C[1]==="await"){T=C.index;break}b--,m=C.index+C[0].length;continue}b===1&&(ce==="then"&&v<0?(v=C.index,x=C[1]):ce==="catch"&&k<0&&(k=C.index,E=C[1])),m=C.index+C[0].length}if(T<0||v<0)break;let N=v+7+x.length,R=k>=0?k+8+E.length:-1,U=e.slice(c,v),L=e.slice(N,k>=0?k:T),q=k>=0?e.slice(R,T):"",X=x.trim(),Y=E.trim(),pe=/^\w+$/.test(X)?X:`__rvAwaitThen${r+1}`,O=k>=0?/^\w+$/.test(Y)?Y:`__rvAwaitCatch${r+1}`:"";r++;let A=r,V=`__rvAwait${A}`;i.push({n:A,expr:g,thenVar:pe,catchVar:O}),t+=e.slice(n,o),t+=`{#if ${V}().status === 'pending'}`+U+`{/if}
65
+ `,t+=`{#each (${V}().status === 'resolved' ? [${V}().value] : []) as ${pe}}`+L+`{/each}
66
+ `,k>=0&&(t+=`{#each (${V}().status === 'rejected' ? [${V}().error] : []) as ${O}}`+q+`{/each}
67
+ `),n=T+8}return r===0?{template:e,blocks:i}:(t+=e.slice(n),{template:t,blocks:i})}function go(e){let s="";for(let t of e){let n=`__rvAwait${t.n}`;s+=`const [${n}, set${n}] = state("__rvawait${t.n}", { status: 'pending', value: null, error: null });
68
+ `,s+=`onMount(function () {
69
+ `,s+=` Promise.resolve(${t.expr}).then(function (__rvAwaitVal) {
70
+ `,s+=` set${n}({ status: 'resolved', value: __rvAwaitVal });
71
+ `,s+=` }).catch(function (__rvAwaitErr) {
72
+ `,s+=` set${n}({ status: 'rejected', error: __rvAwaitErr });
73
+ `,s+=` });
74
+ `,s+=`});
75
+ `}return s}function En(e,s){if(e==="if"){let n=/^\s*([\s\S]+?)\s*$/.exec(s);return n?[n[1]]:null}if(e==="each"){let n=/^\s*([\s\S]+?)\s+as\s+(\{[^{}]*\}|\[[^[\]]*\]|\w+)(?:\s*,\s*(\w+))?(?:\s*\(([\s\S]+)\))?\s*$/.exec(s);return n?[n[1],n[2],n[3]??"",n[4]??""]:null}if(e==="boundary")return[s];if(e==="island"){let n=/^\s*(?:name="([^"]*)")?(?:\s*hydrate="([^"]*)")?\s*$/.exec(s);return n?[n[1]??"",n[2]??""]:null}let t=/^\s*(\w+)(?:\s*\(([\s\S]+)\))?\s*$/.exec(s);return t?[t[1],t[2]??""]:null}function ut(e,s,t){let n=new RegExp(`\\{#${s}\\b`,"g"),r=new RegExp(`\\{/${s}\\}`,"g");n.lastIndex=t;let i;for(;i=n.exec(e);){let o=i.index,c=Ge(e,o);if(c<0)continue;let a=En(s,e.slice(o+2+s.length,c-1));if(!a)continue;let u=1,g=c;for(;;){n.lastIndex=g,r.lastIndex=g;let l=n.exec(e),f=r.exec(e);if(!f)break;if(l&&l.index<f.index){let h=Ge(e,l.index);u++,g=h<0?l.index+l[0].length:h;continue}if(g=f.index+f[0].length,--u===0){let h=e.slice(c,f.index),p=[e.slice(o,g),...a,h];return p.index=o,p}}n.lastIndex=c}return null}function mo(e){let s=/<(style|script|noscript)\b[^>]*>/iy,t="",n="",r=0,i=0,o=()=>{n.trim()&&(t+=He(n,"__hd","__hc",null,r++,!1)),n=""};for(;i<e.length;){if(e.startsWith("<!--",i)){let a=e.indexOf("-->",i+4);i=a<0?e.length:a+3;continue}s.lastIndex=i;let c=s.exec(e);if(c){let a=c[1].toLowerCase(),u=e.toLowerCase().indexOf(`</${a}`,i+c[0].length),g=u<0?-1:e.indexOf(">",u),l=g<0?e.length:g+1;o(),t+=js(c[0],"__hd","__hc",null),t+=Eo(e.slice(i+c[0].length,l),"__hd","__hc",null),i=l;continue}n+=e[i++]}return o(),t}var wo=new Set(["if","each","boundary","island","await","snippet"]),fs=new Map;function yo(e){let s=fs.get(e);return s||(s={open:new RegExp(`\\{#${e}\\b`,"g"),close:new RegExp(`\\{/${e}\\}`,"g")},fs.set(e,s)),s}function bo(e,s){let t=[],n=/<(style|script|noscript)\b[^>]*>/gi,r;for(;r=n.exec(e);){let l=r[1].toLowerCase(),f=e.toLowerCase().indexOf(`</${l}`,r.index+r[0].length),h=f<0?-1:e.indexOf(">",f),p=h<0?e.length:h+1;t.push([r.index,p]),n.lastIndex=p}let i=/<!--[\s\S]*?-->/g,o;for(;o=i.exec(e);)t.push([o.index,o.index+o[0].length]);t.sort((l,f)=>l[0]-f[0]);let c=l=>t.some(([f,h])=>l>=f&&l<h),a=/\{([:/])(\w+)\}/g,u;for(;u=a.exec(e);){if(c(u.index))continue;let[,l,f]=u;if(!(l==="/"&&wo.has(f))){if(l==="/")throw new M("E-TEMPLATE",`${s}: {/${f}} does not close anything`,{file:s,line:Te(e,u),hint:"the closers are {/if}, {/each} and {/boundary} - one per block you opened"});if(f==="else"){let h=(b,m,v)=>{let k=0,T;for(b.lastIndex=0;(T=b.exec(e))&&!(T.index>=v);)c(T.index)||k++;let x=new RegExp(m,"g"),E=0;for(;(T=x.exec(e))&&!(T.index>=v);)c(T.index)||E++;return k-E},p=h(/\{#if\b/g,"\\{/if\\b",u.index),w=h(/\{#each\b/g,"\\{/each\\b",u.index);if(p<=0&&w<=0)throw new M("E-TEMPLATE",`${s}: a stray {:else} with no {#if} or {#each} above it`,{file:s,line:Te(e,u),hint:"{:else} belongs inside an {#if} ... {/if} or {#each} ... {/each} block"});continue}if(f==="fallback")throw new M("E-TEMPLATE",`${s}: a stray {:fallback} with no {#boundary} above it`,{file:s,line:Te(e,u),hint:"{:fallback} belongs directly inside a {#boundary} ... {/boundary} block"});if(f==="then"||f==="catch"){let h=(b,m)=>{b.lastIndex=0;let v=0,k;for(;(k=b.exec(e))&&!(k.index>=m);)c(k.index)||v++;return v},p=h(/\{#await\b/g,u.index),w=h(/\{\/await\b/g,u.index);if(p<=w)throw new M("E-TEMPLATE",`${s}: a stray {:${f}} with no {#await} above it`,{file:s,line:Te(e,u),hint:"{:then} / {:catch} belong inside an {#await} ... {/await} block"});continue}throw new M("E-TEMPLATE",`${s}: {:${f}} is not a Rosefc directive`,{file:s,line:Te(e,u),hint:"Rosefc templates support {#if}/{:else}, {#each} and {#boundary}"})}}let g=/\{#(if|each|boundary|island|await)\b/g;for(;u=g.exec(e);){if(c(u.index))continue;let l=u[1],f=Ge(e,u.index);if(f<0)continue;let h=e.slice(u.index+2+l.length,f-1);if(l==="each"&&!En("each",h))throw new M("E-TEMPLATE",`${s}: {#each ${h.trim()}} is missing its item name`,{file:s,line:Te(e,u),hint:"write {#each items() as item} - the name after `as` is what the block body reads (item.id, item.name)"});let{open:p,close:w}=yo(l),b=1,m=f;for(;;){p.lastIndex=m,w.lastIndex=m;let v=p.exec(e),k=w.exec(e);if(!k)break;if(v&&v.index<k.index){let T=Ge(e,v.index);m=T<0?v.index+v[0].length:T;continue}if(m=k.index+k[0].length,--b===0)break}if(b!==0)throw new M("E-TEMPLATE",`${s}: unclosed {#${l}} - every block needs its {/${l}}`,{file:s,line:Te(e,u),hint:`add the matching {/${l}} (an inner {#if} or {#each} closes first, deepest first)`})}}function $o(e,s){let t=/<([a-zA-Z][\w-]*)((?:\s+[\w:-]+(?:=(?:"[^"]*"|'[^']*'|`[^`]*`|[^\s"'>]+))?)*)\s*(\/?)>/g;return e.replace(t,(n,r,i,o)=>{if(s.has(r)||!/\{/.test(i))return n;let c=i.replace(/([\w:-]+)=("([^"]*)"|'([^']*)'|`([^`]*)`)/g,(a,u,g,l,f,h)=>{let p=l??f??h??"";if(!/\{/.test(p)||h===void 0&&p.includes("`"))return a;let w=ft(p);if(w.length===0)return a;let b="",m=0;for(let v of w)m<v.start&&(b+=(b?" + ":"")+JSON.stringify(p.slice(m,v.start))),b+=(b?" + ":"")+`(${v.expr})`,m=v.end+1;return m<p.length&&(b+=(b?" + ":"")+JSON.stringify(p.slice(m))),`${u}={${b}}`});return`<${r}${c}${o?" /":""}>`})}var yn=0,bn=!1,$n="",_n={},Gt=new Set,xn=new Set,vn=null,Pt="";function He(e,s,t,n,r,i=!0,o=new Map,c=0){let a="",u=e,g=0,l=0,f=0,h=/\{#island\b/.test(e),p=i&&(!h||c>0),w=()=>`${r}_${f++}`;r===0&&(a+=`const __snip = {};
76
+ `);let b=new Map,m=Ar(e,o),v=new Set(m).size===m.length;if(m.length>0&&v){let O={};for(let A of m){let V=`__rvct${yn++}`;b.set(A,V),O[A]=V}u=wn(e,[],O,{ownScope:!0,comps:o})}let k=O=>{let A,V=-1;return()=>((V!==l||A===void 0||A!==null&&A.index<g)&&(A=O(g),V=l),A)},T=/<(style|script|noscript)\b[^>]*>/g,x=null,E=k(O=>ut(u,"if",O)),N=k(O=>ut(u,"each",O)),R=k(O=>ut(u,"boundary",O)),U=k(O=>ut(u,"island",O)),L=k(O=>ut(u,"snippet",O)),q=k(O=>Cr(u,O)),X=k(O=>{let A=o.size>0?Os(u,O,o):null;return A?{index:A.start,tag:A}:null}),Y=k(O=>{T.lastIndex=O;let A=T.exec(u);return A?{index:A.index,tag:A[0],name:A[1].toLowerCase()}:null}),pe=k(O=>{let A=u.indexOf("<!--",O);if(A<0)return null;let V=u.indexOf("-->",A+4);return{index:A,end:V<0?u.length:V+3}});for(;g<u.length;){let O=E(),A=N(),V=R(),Q=q(),ie=Q?Object.assign([u.slice(Q.index,Q.end+1),Q.expr],{index:Q.index}):null,ge=X()?.tag??null,ke=U(),Ae=L(),ce=[];O?.index!==void 0&&ce.push({type:"if",match:O,index:O.index}),A?.index!==void 0&&ce.push({type:"each",match:A,index:A.index}),V?.index!==void 0&&ce.push({type:"boundary",match:V,index:V.index}),ke?.index!==void 0&&ce.push({type:"island",match:ke,index:ke.index}),Ae?.index!==void 0&&ce.push({type:"snippet",match:Ae,index:Ae.index}),ie?.index!==void 0&&ce.push({type:"expr",match:ie,index:ie.index}),ge&&ce.push({type:"comp",match:ie,index:ge.start,tag:ge});let C=ce.length>0?ce.reduce((Z,I)=>Z.index<=I.index?Z:I):null,$e=Y();if($e&&C&&$e.index<C.index){x===null&&(x=u.toLowerCase());let Z=x.indexOf(`</${$e.name}`,$e.index+$e.tag.length),I=Z<0?-1:u.indexOf(">",Z),J=I<0?u.length:I+1;a+=he(u.slice(g,$e.index),s,t,n),a+=js($e.tag,s,t,n),a+=he(u.slice($e.index+$e.tag.length,J),s,t,n),g=J;continue}let Oe=pe();if(Oe&&(!C||Oe.index<C.index)){a+=he(u.slice(g,Oe.end),s,t,n),g=Oe.end;continue}if(!C){a+=he(u.slice(g),s,t,n);break}if(C.type==="if"){let[,Z,I]=C.match,J=u.slice(g,C.index);J&&(a+=he(J,s,t,n));let te=ds(Z),le=w(),ee=n??"__s",de=He(I.trim(),"h","__c",ee,r+1,p,o,c);a+=`const __b${le} = (__s, __c) => { let h = ''; ${de} return h; };
77
+ `,p?a+=`${s} += ifMark(${t}, () => (${te}), __b${le}${n?`, ${n}`:""});
78
+ `:a+=`${s} += (${te}) ? __b${le}(${n??"undefined"}, []) : '';
79
+ `,g=C.index+C.match[0].length}else if(C.type==="each"){let[,Z,I,J,te,le]=C.match,ee=u.slice(g,C.index);ee&&(a+=he(ee,s,t,n));let de=ds(Z),me=w(),K=/^[{[]/.test(I),fe=K?null:new RegExp(`\\b${I}\\b`,"g"),F=J?new RegExp(`\\b${J}\\b`,"g"):null,we="",ae=0;for(let ye of ft(le.trim())){let Pe=fe?ye.expr.replace(fe,"__s"):ye.expr;F&&(Pe=Pe.replace(F,"__i")),we+=le.trim().slice(ae,ye.start)+"{"+Pe+"}",ae=ye.end+1}we+=le.trim().slice(ae);let Se=He(we,"h","__c","__s",r+1,p,o,c),De=K?`const ${I} = __s; ${Se}`:Se,je="";if(te){if(K)throw new M("E-TEMPLATE",`${Pt}: a keyed {#each} keys on a named item's property - write {#each xs as x (x.id)}, not a destructuring pattern`,{file:Pt,hint:"name the item first, then key on one of its properties"});let ye=te.trim();fe&&(ye=ye.replace(fe,"__s")),F&&(ye=ye.replace(F,"__i")),je=`, (__s, __i) => (${ye})`}if(a+=`const __b${me} = (__s, __c${J?", __i":""}) => { let h = ''; ${De} return h; };
80
+ `,p)a+=`${s} += eachMark(${t}, () => (${de}), __b${me}${je});
81
+ `;else{let ye=K?"__s":I;a+=`${s} += (${de}).map((${ye}${J?", __i":""}) => __b${me}(${ye}, []${J?", __i":""})).join('');
82
+ `}g=C.index+C.match[0].length}else if(C.type==="boundary"){let[,Z,I]=C.match,J="";if(Z){let fe=/__fb="([A-Za-z0-9+/=]*)"/.exec(Z);fe&&(J=Buffer.from(fe[1],"base64").toString("utf-8"))}let te=I,le=u.slice(g,C.index);le&&(a+=he(le,s,t,n));let ee=w(),de=/\$action:|<form[\s>]/.test(te),me=He(te.trim(),"h",t,n,r+1,p,o,c);a+=`const __b${ee} = (__c) => { let h = ''; ${me} return h; };
83
+ `;let K="";if(J.trim()){let fe=He(J.trim(),"h",t,n,r+1,p,o,c);K=`const __bf${ee} = (__c) => { let h = ''; ${fe} return h; };
84
+ `}a+=K,a+=`let __bd${ee} = '';
85
+ `,a+=de?`try { $actionErrorOrThrow(); __bd${ee} = __b${ee}(${t}); } catch (e) { $setBoundaryError(e); __bd${ee} = ${K?`__bf${ee}(${t})`:"$boundaryFallback(e)"}; }
86
+ `:`try { __bd${ee} = __b${ee}(${t}); } catch (e) { $setBoundaryError(e); __bd${ee} = ${K?`__bf${ee}(${t})`:JSON.stringify(wr)}; }
87
+ `,a+=`${s} += __bd${ee};
88
+ `,g=C.index+C.match[0].length}else if(C.type==="snippet"){let[,Z,I,J]=C.match,te=u.slice(g,C.index);te&&(a+=he(te,s,t,n));let le=w(),ee=I?I.split(",").map(me=>me.trim()).filter(Boolean).join(","):"",de=He(J.trim(),"h","__c","__s",r+1,p,o,c);a+=`__snip.${Z} = (__s, __c${ee?","+ee:""}) => { let h = ''; ${de} return h; };
89
+ `,g=C.index+C.match[0].length}else if(C.type==="comp"){let Z=C.tag;Z.start>g&&(a+=he(u.slice(g,Z.start),s,t,n));let I=o.get(Z.name),J=w(),te="";if(Z.selfClosing)g=Z.end;else{let F=Zt(u,Z.end,Z.name);if(F<0)throw new M("E-TEMPLATE",`unclosed <${Z.name}> - every component tag needs its matching close tag`,{hint:`add the matching </${Z.name}> (or close the tag with /> when it takes no children)`});te=u.slice(Z.end,F),g=F+Z.name.length+3}let{def:le,named:ee}=ko(te),de=le.trim().length>0;de&&(a+=`const __ch${J} = (__s, __c) => { let h = ''; ${He(le,"h","__c",n,r+1,p,o,c)} return h; };
90
+ `);let me=ee.map(([F,we])=>{let ae=I.slots.find(De=>De.name===F),Se=we;for(let De of ae?.props??[]){let je=new RegExp(`\\b${De}\\b`,"g"),ye="",Pe=0;for(let Je of ft(Se))ye+=Se.slice(Pe,Je.start)+"{"+Je.expr.replace(je,`__s.${De}`)+"}",Pe=Je.end+1;Se=ye+Se.slice(Pe)}return`${JSON.stringify(F)}: (__s, __c) => { let h = ''; ${He(Se,"h","__c",n,r+1,p,o,c)} return h; }`}),K=xo(Z.attrs).filter(F=>F.name!=="slot").map(F=>{if(F.kind==="spread")return`...(${F.value})`;let we=F.name.startsWith("on:")?`on${Ue(F.name.slice(3))}`:F.name,ae=F.kind==="expr"?`(${F.value})`:F.kind==="str"?JSON.stringify(F.value):"true";return`${JSON.stringify(we)}: ${ae}`}).join(", "),fe=de?`__ch${J}(${n??"undefined"}, ${t})`:"''";a+=`${s} += ${Z.name}(${t}, ${fe}, { ${K} }, { ${me.join(", ")} });
91
+ `}else if(C.type==="island"){let[,Z,I,J]=C.match,te=u.slice(g,C.index);te&&(a+=he(te,s,t,n));let le=I==="visible"||I==="idle"?` data-rv-island-hydrate="${I}"`:"";a+=`${s} += ${JSON.stringify(`<div data-rv-island="${Z||""}"${le}>`)};
92
+ `;let ee=He(J.trim(),"h","__c",n,r+1,i,o,c+1);a+=ee,a+=`${s} += '</div>';
93
+ `,g=C.index+C.match[0].length}else{let[,Z]=C.match,I=Z.trim(),J=u.slice(g,C.index),te=/^@const\s+([A-Za-z_$][\w$]*)\s*=\s*([\s\S]+)$/.exec(I);if(te){J&&(a+=he(J,s,t,n));let F=te[1],we=u.slice(C.index+C.match[0].length),ae=b.get(F);g=C.index+C.match[0].length,ae===void 0&&(ae=`__rvct${yn++}`,u=wn(we,[],{[F]:ae}),g=0,l++);let Se=`const ${ae} = () => (${te[2].trim()});
94
+ `;bn&&r===0?(Gt.has(F)?vn=F:Gt.add(F),$n+=Se,_n[F]=ae):a+=Se;continue}if(I==="__slot__"){J&&(a+=he(J,s,t,n)),a+=Lo(s),g=C.index+C.match[0].length;continue}let le=/^__slotDefault\(("(?:[^"\\]|\\.)*")\)$/.exec(I);if(le){J&&(a+=he(J,s,t,n)),a+=`${s} += __slotDefault(children, ${le[1]});
95
+ `,g=C.index+C.match[0].length;continue}let ee=/^__slot\((['"])(\w+)\1, \[([\s\S]*?)\](?:,\s*("(?:[^"\\]|\\.)*"))?\)$/.exec(I);if(ee){J&&(a+=he(J,s,t,n));let F=ee[4]?`, ${ee[4]}`:"";a+=`${s} += __slotBlock(${t}, __sl, ${JSON.stringify(ee[2])}, [${ee[3]}]${F});
96
+ `,g=C.index+C.match[0].length;continue}let de=/^@html\s+([\s\S]+)$/.exec(I);if(de){J&&(a+=he(J,s,t,n));let F=de[1].trim();if(!p)a+=`${s} += String(${F} ?? '');
97
+ `;else{let we=n?`(${n}) => (${F})`:`() => (${F})`;a+=`${s} += rawMark(${t}, ${we}${n?`, ${n}`:""});
98
+ `}g=C.index+C.match[0].length;continue}let me=/^@debug\b([\s\S]*)$/.exec(I);if(me){J&&(a+=he(J,s,t,n));let F=me[1].trim().replace(/,$/,"");a+=F?`console.log('[rosefc:debug]', { ${F} });
99
+ `:`console.log('[rosefc:debug]'); debugger;
100
+ `,g=C.index+C.match[0].length;continue}let K=/^@render\s+([A-Za-z_$][\w$]*)\s*\(([\s\S]*)\)\s*$/.exec(I);if(K){if(new RegExp(`\\{#snippet\\s+${K[1]}\\b`).test(u.slice(C.index+C.match[0].length)))throw new M("E-TEMPLATE",`${Pt}: {@render ${K[1]}} runs before its {#snippet ${K[1]}} is defined`,{file:Pt,hint:"move the {#snippet} definition above the {@render} call - definitions register as the statement stream reaches them"});J&&(a+=he(J,s,t,n));let we=K[2].trim();a+=`${s} += ((__snip && __snip.${K[1]}) ? __snip.${K[1]}(${n??"null"}, ${t}${we?", "+we:""}) : '');
101
+ `,g=C.index+C.match[0].length;continue}let fe=So(u,C.index)?/([\w-]+)=\s*$/.exec(J)??null:null;if(fe){let F=J.slice(0,J.length-fe[0].length);F&&(a+=he(F,s,t,n)),a+=No(fe[1],I,s,t,n,p)}else{J&&(a+=he(J,s,t,n));let F=u.slice(C.index+C.match[0].length);if(/=[\"'][^\"']*$/.test(J))a+=`${s} += esc(${I});
102
+ `;else{let ae=F.length>0&&!/^<[a-zA-Z/!]/.test(F)&&!F.startsWith("{");a+=Po(I,s,t,n,p,ae)}}g=C.index+C.match[0].length}}return a=a.replace(/\+= "\s*([a-zA-Z][\w-]*)=";\r?\n\s*\w+\s*\+=\s*textMark\((\w+), (.+?), 1, ([^;]+?)\);/g,(O,A,V,Q,ie)=>`+= attrMark(${V}, ${Q}, '${A}', ${ie});`),a}function Kt(e,s){let t=s+1,n="",r=0;for(;t<e.length;){let i=e[t];if(n)i===n&&(n="");else if(i==='"'||i==="'")n=i;else if(i==="{")r++;else if(i==="}")r=Math.max(0,r-1);else if(i===">"&&r===0)return t+1;t++}return-1}function Os(e,s,t){let n=s;for(;n<e.length;){let r=e.indexOf("<",n);if(r<0)return null;let i=/^<([a-zA-Z][\w-]*)/.exec(e.slice(r,r+64));if(i&&t.has(i[1])){let o=Kt(e,r);if(o>0){let c=e.slice(r,o),a=/\/>$/.test(c);return{start:r,end:o,name:i[1],attrs:c.slice(1+i[1].length,a?-2:-1),selfClosing:a}}}n=r+1}return null}function _o(e,s){return Os(e,0,s)}function Zt(e,s,t){let n=new RegExp(`<(/?)${t}(?=[\\s/>])`,"g");n.lastIndex=s;let r=1,i;for(;i=n.exec(e);){let o=Kt(e,i.index);if(o<0)return-1;if(i[1]==="/"){if(r--,r===0)return i.index}else/\/>$/.test(e.slice(i.index,o))||r++}return-1}function xo(e){let s=[],t=0;for(;t<e.length;){let n=/^\s*\{\.\.\.([^}]*)\}/.exec(e.slice(t));if(n){s.push({name:"...",kind:"spread",value:n[1].trim()}),t+=n[0].length;continue}let r=/^\s*([\w:.-]+)/.exec(e.slice(t));if(!r)break;t+=r[0].length;let i=/^\s*=\s*/.exec(e.slice(t));if(!i){s.push({name:r[1],kind:"bool",value:""});continue}t+=i[0].length;let o=e[t];if(o==="{"){let c=1,a=t+1;for(;a<e.length&&c>0;)e[a]==="{"?c++:e[a]==="}"&&c--,a++;s.push({name:r[1],kind:"expr",value:e.slice(t+1,a-1).trim()}),t=a}else if(o==='"'||o==="'"){let c=e.indexOf(o,t+1);s.push({name:r[1],kind:"str",value:e.slice(t+1,c<0?e.length:c)}),t=c<0?e.length:c+1}else break}return s}function vo(e,s){let t=0;for(;t<e.length;){let n=e.indexOf("<",t);if(n<0)return;let r=/^<(\/?)([a-zA-Z][\w-]*)/.exec(e.slice(n,n+64));if(!r){t=n+1;continue}let i=Kt(e,n);if(i<0)return;let o=/\bslot\s*=\s*["'](\w+)["']/.exec(e.slice(n,i));if(o&&r[1]!=="/")throw new M("E-TEMPLATE",`slot="${o[1]}" on <${r[2]}> is nested inside slot="${s}" - a slot must be a direct child of the component`,{hint:"move the inner <slot> out of the outer one - a slot is a direct child of the component tag, never nested in another slot"});t=i}}function ko(e){let s="",t=new Map,n=0,r=0,i=0,o=[];for(;n<e.length;){let c=e.indexOf("<",n),a=e.indexOf("{#",n),u=e.indexOf("{/",n),g=[c,a,u].filter(v=>v>=0);if(g.length===0){s+=e.slice(n);break}let l=Math.min(...g);if(l>n&&(s+=e.slice(n,l)),l===a||l===u){let v=e.indexOf("}",l),k=e.slice(l,v<0?e.length:v+1);if(l===a){let T=/^\{#(\w+)/.exec(k);o.push({header:k,type:T?T[1]:""}),i++}else i=Math.max(0,i-1),o.length&&o.pop();s+=k,n=l+k.length;continue}let f=/^<(\/?)([a-zA-Z][\w-]*)/.exec(e.slice(l,l+64));if(!f){s+="<",n=l+1;continue}let h=Kt(e,l);if(h<0){s+=e.slice(l);break}let p=e.slice(l,h),w=/\/>$/.test(p),b=Cs.has(f[2].toLowerCase());if(f[1]==="/"){r=Math.max(0,r-1),s+=p,n=h;continue}!w&&!b&&r++;let m=/\bslot\s*=\s*["'](\w+)["']/.exec(p)?.[1];if(m&&r===1&&i===0){if(w||b)t.set(m,(t.get(m)??"")+p.replace(/\s*slot\s*=\s*["']\w+["']/,""));else{let v=Zt(e,h,f[2]);if(v<0)throw new M("E-TEMPLATE",`unclosed <${f[2]}> inside slot="${m}"`,{hint:`add the matching </${f[2]}>`});let k=`</${f[2]}>`,T=e.slice(h,v);vo(T,m),t.set(m,(t.get(m)??"")+p.replace(/\s*slot\s*=\s*["']\w+["']/,"")+T+k),r=Math.max(0,r-1),n=v+k.length;continue}n=h;continue}if(m&&i>0){let v=p.replace(/\s*slot\s*=\s*["']\w+["']/,""),k="";for(let E of o)k+=E.header;if(k+=v,w||b){for(let E=o.length-1;E>=0;E--)k+=`{/${o[E].type}}`;t.set(m,(t.get(m)??"")+k),n=h;continue}let T=Zt(e,h,f[2]);if(T<0)throw new M("E-TEMPLATE",`unclosed <${f[2]}> inside slot="${m}"`,{hint:`add the matching </${f[2]}>`});let x=`</${f[2]}>`;k+=e.slice(h,T)+x;for(let E=o.length-1;E>=0;E--)k+=`{/${o[E].type}}`;t.set(m,(t.get(m)??"")+k),r=Math.max(0,r-1),n=T+x.length;continue}if(m)throw new M("E-TEMPLATE",`slot="${m}" on <${f[2]}> must be a direct child of the component, or wrapped only by an {#if}/{#each}/{#boundary} block - it is nested inside another element`,{hint:'place the element with slot="..." directly inside the component tag, or inside a single {#if}/{#each} block - wrapping it in another element is not yet supported'});s+=p,n=h}return{def:s,named:[...t.entries()]}}function So(e,s){let n=e.slice(0,s).lastIndexOf("<");if(n<0||!/^<[a-zA-Z]/.test(e.slice(n)))return!1;let r=n+1,i="",o=0;for(;r<s;){let c=e[r];if(i)c===i&&(i="");else if(c==='"'||c==="'")i=c;else if(c==="{")o++;else if(c==="}")o=Math.max(0,o-1);else if(c===">"&&o===0)return!1;r++}return!0}function he(e,s,t,n){return e?`${s} += ${JSON.stringify(e)};
103
+ `:""}function Eo(e,s,t,n){if(!e.includes("{@html"))return he(e,s,t,n);let r="",i=0,o=e.indexOf("{@html");for(;o!==-1;){let a=Lt(e,o);if(a<0)break;let u=/^@html\s+([\s\S]+)$/.exec(e.slice(o+1,a));if(u){let g=e.slice(i,o);g&&(r+=`${s} += ${JSON.stringify(g)};
104
+ `),r+=`${s} += String(${u[1].trim()} ?? '');
105
+ `,i=a+1}o=e.indexOf("{@html",a+1)}if(i===0)return he(e,s,t,n);let c=e.slice(i);return c&&(r+=`${s} += ${JSON.stringify(c)};
106
+ `),r}function js(e,s,t,n){let r=ft(e);if(r.length===0)return he(e,s,t,n);let i=`${s} += `,o=0;return r.forEach((c,a)=>{let u=e.slice(o,c.start),g=u.endsWith("=");a>0&&(i+=" + "),i+=JSON.stringify(g?u+'"':u),i+=` + esc(${c.expr})`,g&&(i+=` + '"'`),o=c.end+1}),o<e.length&&(i+=" + "+JSON.stringify(e.slice(o))),i+`;
107
+ `}var Ro=/<img\b(?:[^<>]|\{[^{}]*\})*>/g,Ao={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".ico":"image/x-icon"},Co=4096,To=16384;function Oo(e,s){let t=_.extname(s),n=_.basename(s,t),r=s.slice(0,s.length-(n+t).length),i;try{i=P.readdirSync(_.join(e,_.dirname(s)))}catch{return[]}let o=new RegExp("^"+n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"\\.w(\\d+)"+t.replace(".","\\.")+"$","i"),c=[];for(let a of i){let u=o.exec(a),g=u?Number(u[1]):0;g>0&&c.push({url:`${r}${n}.w${g}${t}`,width:g})}return c.sort((a,u)=>a.width-u.width)}var hs=new Map;function jo(e){let s;try{s=P.statSync(e)}catch{return null}let t=hs.get(e);if(t&&t.mtime===s.mtimeMs)return{buffer:t.buffer,dims:t.dims};let n;try{n=P.readFileSync(e)}catch{return null}let r=Gn(e),i={mtime:s.mtimeMs,buffer:n,dims:r};return hs.set(e,i),{buffer:n,dims:i.dims}}function ps(e,s){return e.replace(Ro,t=>{let n=t.match(/\bsrc="(\/[^"{}]+)"/);if(!n)return t;let r=_.extname(n[1]).toLowerCase(),i=Ao[r];if(!i)return t;let o=_.join(s,n[1]),c=jo(o);if(!c)return t;let a=c.buffer,g=/\swidth=/.test(t)||/\sheight=/.test(t)?null:c.dims,l=p=>g?p.replace(/<img\b/,`<img width="${g.width}" height="${g.height}"`):p,f=r===".svg"?To:Co;if(a.length>f){let w=/\ssrcset=/.test(t)||/\ssizes=/.test(t)?[]:Oo(s,n[1]);if(!w.length)return l(t);let b=w.map(m=>`${m.url} ${m.width}w`).join(", ");return l(t.replace(/<img\b/,`<img srcset="${b}"`))}let h=r===".svg"?`data:image/svg+xml,${a.toString("utf-8").replace(/%/g,"%25").replace(/#/g,"%23").replace(/"/g,"%22")}`:`data:${i};base64,${a.toString("base64")}`;return l(t.replace(n[0],`src="${h}"`))})}function Po(e,s,t,n,r=!0,i=!1){if(!r)return`${s} += esc(${e});
108
+ `;let o=n?`(${n}) => (${e})`:`() => (${e})`,c=i?", 1":n?", 0":"";return n&&(c+=`, ${n}`),`${s} += textMark(${t}, ${o}${c});
109
+ `}var Mo=new Set(["checked","disabled","readonly","required","selected","multiple","autofocus","open"]);function No(e,s,t,n,r,i=!0){if(!i)return`${t} += '${e}="' + esc(${s}) + '"';
110
+ `;let o=r?`(${r}) => (${s})`:`() => (${s})`,c=r?`, ${r}`:"";return Mo.has(e)?`${t} += boolAttrMark(${n}, ${o}, '${e}'${c});
111
+ `:`${t} += attrMark(${n}, ${o}, '${e}'${c});
112
+ `}function Lo(e){return`${e} += String(children);
113
+ `}var It="import { state, setState, persistState, $data, hasState, isSeeded, markSeeded, esc, refresh, onMount, onCleanup, $effect, getContext, $query, $t, bestLocale, localeDir, ensureLocale, loadLocale, handlers, directives, $cookies, $sessionCookie, $store, $udp, $tcp, $listen, $websocket, $mqtt, parseLoRaWAN, ActionError, $actionError, $actionErrorOrThrow, $actionPending, $boundaryFallback, $setBoundaryError, $boundaryError, $append, $prepend, $merge, applyStateDeltas, textMark, attrMark, boolAttrMark, ifMark, eachMark, headMark, rawMark, slotBlockMark, redirect, notFound, aggregate, loader, encodeSdui, decodeSdui } from './runtime.js';",Io=It.replace(/^import\s*\{/,"").replace(/\}\s*from[\s\S]*$/,"").split(",").map(e=>e.trim()).filter(Boolean);function Ps(e){return e.length===0?"":e.map(s=>`const ${s.name} = __p.${s.name}${s.def?` ?? (${s.def})`:""};`).join(`
114
+ `)}var Ms=`const __slot = (sl, name, pairs) => {
115
+ const fn = sl[name];
116
+ if (typeof fn !== 'function') return null;
117
+ const o = {};
118
+ for (let i = 0; i < pairs.length; i++) o[pairs[i][0]] = pairs[i][1];
119
+ return { o, fn };
120
+ };
121
+ const __slotBlock = (closes, sl, name, pairs, fallback) => {
122
+ const hit = __slot(sl, name, pairs);
123
+ if (hit) return slotBlockMark(closes, hit);
124
+ return fallback || '';
125
+ };
126
+ const __slotDefault = (children, fallback) => {
127
+ const c = children == null ? '' : String(children);
128
+ if (c.trim()) return c;
129
+ return fallback || '';
130
+ };`,Ns=`
131
+ // R259: an inline handler inside {#each} registers HERE, inside the render
132
+ // closure - the arrow captures the row's \`__s\` (the item), which module
133
+ // scope never had (BUG.md BE). The key is prefix + this document's shared
134
+ // closes-array counter: one array per document render, shared by every
135
+ // layout/page/component instance, so rows and instances never collide and
136
+ // the FIRST render's sequence matches the server's (adopt-by-index contract)
137
+ // - which is the key wire()'s direct listener captures at bind time. A
138
+ // closure mints once and re-evaluations (wire's attribute pass) reuse the
139
+ // minted key, so nothing re-mints and the registry does not grow per pass.
140
+ const __rhreg = (prefix, fn) => {
141
+ if (typeof fn === 'function' && fn.__rhk) return fn.__rhk;
142
+ const n = (closes.__rhn = (closes.__rhn || 0) + 1) - 1;
143
+ const k = prefix + n;
144
+ handlers[k] = fn;
145
+ if (typeof fn === 'function') fn.__rhk = k;
146
+ return k;
147
+ };
148
+ `;function Fo(e,s,t,n="",r="",i=[],o=!1,c="",a=!1,u="",g=!1,l="",f="",h=!1){let p=r?`
149
+ const __head = () => { let __hd = ''; ${r} return __hd; };
150
+ __html += headMark(closes, __head);`:"",w=g||h?`
151
+ const $setState = (key, value) => setState(key, value);`:"",b=h?Ns:"";return`
152
+ ${It}
153
+
154
+ ${c}
155
+
156
+ ${n}
157
+ ${u}
158
+ ${w}
159
+
160
+ ${o?Ms:""}
161
+
162
+ export ${a?"function":"async function"} render(closes, children, __props, __slots) {
163
+ ${i.length>0?"const __p = __props || {};":""}
164
+ ${o?"const __sl = __slots || {};":""}
165
+ ${Ps(i)}
166
+ ${i.length>0?"const __rvlive = (k, v) => { const g = __p['__live-' + k]; return typeof g === 'function' ? g() : v; };":""}
167
+ ${e}
168
+ ${t}
169
+ ${l}
170
+ ${f}
171
+ ${b}
172
+
173
+ ${a?"":"applyStateDeltas();"}
174
+ const __root = (__c, children) => { let h = ''; ${s} return h; };
175
+ let __html = ${a?"":"await "}__root(closes, children);${p}
176
+ return __html;
177
+ }
178
+ `}function Do(e,s,t,n,r="",i="",o=[],c=!1,a="",u=!1,g="",l="",f=!1){let h=new Set,p=n.filter(k=>h.has(k.fn)?!1:(h.add(k.fn),!0)),w=p.length>0?`Object.assign(handlers, { ${p.map(k=>k.fn).join(", ")} });`:"",b=p.length>0||f?"const $setState = (key, value) => setState(key, value);":"",m=f?Ns:"",v=i?`
179
+ const __head = () => { let __hd = ''; ${i} return __hd; };
180
+ __html += headMark(closes, __head);`:"";return`
181
+ ${It}
182
+
183
+ ${a}
184
+
185
+ ${r}
186
+ ${b?`
187
+ ${b}
188
+ `:""}
189
+ ${c?Ms:""}
190
+
191
+ export ${u?"function":"async function"} render(closes, children, __props, __slots) {
192
+ ${o.length>0?"const __p = __props || {};":""}
193
+ ${c?"const __sl = __slots || {};":""}
194
+ ${Ps(o)}
195
+ ${o.length>0?"const __rvlive = (k, v) => { const g = __p['__live-' + k]; return typeof g === 'function' ? g() : v; };":""}
196
+ ${e}
197
+ ${t}
198
+ ${g}
199
+ ${l}
200
+ ${w}
201
+ ${m}
202
+ const __root = (__c, children) => { let h = ''; ${s} return h; };
203
+ let __html = ${u?"":"await "}__root(closes, children);${v}
204
+ return __html;
205
+ }
206
+ `}var rt=(e,s)=>e.map((t,n)=>({li:t,i:n})).filter(({li:t})=>t.isLayout&&Jo(t.filePath,e[s].filePath)).sort((t,n)=>n.li.filePath.length-t.li.filePath.length).map(({i:t})=>t),Mt=(e,s,t)=>s[t].csr===!0||s[t].needsClient||kn(e,s,t)?!1:!rt(e,t).some(n=>s[n].needsClient),kn=(e,s,t)=>s[t].shell===!1||rt(e,t).some(n=>s[n].shell===!1);function qo(e,s){return e.map((t,n)=>({info:t,i:n})).filter(({info:t})=>!t.isLayout&&!t.isNotFound&&!t.isError&&!t.isApi&&!t.isMiddleware&&!t.isComponent).map(({info:t,i:n})=>{if(Mt(e,s,n))return`${t.routePath} zero-JS nothing in the chain needs the client`;let r=[n,...rt(e,n)].filter(o=>s[o].needsClient).map(o=>`${(s[o].clientReasons??["needs the client"]).join(" + ")} in ${_.basename(e[o].filePath)}`).join("; "),i=s[n].csr===!0?" (csr = true forces the bundle)":"";return`${t.routePath} client JS ${r}${i}`})}var gs=`
207
+
208
+ import { start, postForm } from '/client.js';
209
+
210
+ for (const el of document.querySelectorAll('[data-rosefc]')) {
211
+ const route = el.getAttribute('data-rosefc');
212
+ const doc = await fetch(route).then((r) => (r.ok ? r.text() : ''));
213
+ const parsed = new DOMParser().parseFromString(doc, 'text/html');
214
+ // A JS-shipping document wraps its content in #app; a zero-JS route's content is the body's own (no wrapper).
215
+ const app = parsed.getElementById('app');
216
+ if (app) {
217
+ el.innerHTML = app.innerHTML;
218
+ } else {
219
+ for (const node of Array.from(parsed.body.children)) {
220
+ if (!/^(?:SCRIPT|LINK|STYLE)$/.test(node.tagName)) el.appendChild(node);
221
+ }
222
+ }
223
+ // start() resumes from #__rosefc_state (zero hydration), so the state
224
+ const state = parsed.getElementById('__rosefc_state');
225
+ if (state) el.appendChild(state);
226
+
227
+ const rendered = state ? JSON.parse(state.textContent || '{}').__route : null;
228
+ await start(el, route, rendered === route);
229
+ if (state) state.remove();
230
+
231
+ el.addEventListener('click', (e) => {
232
+ const a = e.target.closest && e.target.closest('a[href^="/"]');
233
+ if (!a || !el.contains(a)) return;
234
+ e.preventDefault();
235
+ el.setAttribute('data-rosefc', a.getAttribute('href'));
236
+ start(el, a.getAttribute('href'), false);
237
+ });
238
+ // Progressive-enhancement forms work inside a mount too: the native POST would replace the HOST page.
239
+ el.addEventListener('submit', (e) => {
240
+ const f = e.target;
241
+ if (!f || f.tagName !== 'FORM' || f.hasAttribute('data-on-submit')) return;
242
+ if ((f.getAttribute('method') || '').toLowerCase() !== 'post') return;
243
+ e.preventDefault();
244
+ postForm(new FormData(f), el, el.getAttribute('data-rosefc'));
245
+ });
246
+ }
247
+ `,pn=new Map,ms=null;async function Ls(e,s,t={}){let n=_.resolve(e),r=_.resolve(s),i=t.minify!==!1,o=t.incremental===!0;await P.promises.mkdir(r,{recursive:!0});let c=(await P.promises.readdir(r)).filter(d=>/^(?:comp-\d+\.(?:ssr|client)|runtime|(?:server|client)-entry)\.js$/.test(d));await Promise.all(c.map(d=>P.promises.rm(_.join(r,d),{force:!0})));let[a,u]=await Promise.all([Bo(n),Ho(n)]),g=[...a,...u];if(a.length===0)throw new M("E-ROUTE",`no .rose pages found under ${_.join(n,"src","pages")} - run rosefc from a project root, or pass one: rosefc build <dir>`,{file:_.join(n,"src","pages"),hint:"create src/pages/index.rose in that directory (or run the command from the project root)"});let l=g.map(d=>({...Wo(d,n)})),f=await Or(n);Ss=(f.watch??[]).map(d=>_.isAbsolute(d)?d:_.join(n,d));let h=f.plugins,p=g.map((d,y)=>{let D=l[y].isComponent?_.join(n,"src"):_.join(n,"src","pages");return _.relative(D,d).replace(/\\/g,"/").replace(/\.rose$/,"")}),w=new Map(g.map((d,y)=>[d,{index:y,scopeKey:p[y],slots:Ir(d)}])),b=pt.transform("export default 0",{loader:"js"}).catch(()=>{}),m=await Promise.all(g.map((d,y)=>Ur(d,_.join(n,"public"),p[y],l[y].isApi,h,w)));await b;{let d=new Set(Sn().map(([W])=>W)),y=[],D=new Set;for(let W=0;W<m.length;W++)for(let z of[...es(m[W].ssr),...es(m[W].client)]){if(d.has(z)||D.has(z))continue;D.add(z);let B=`${_.relative(n,g[W]).replace(/\\/g,"/")} reads import.meta.env.${z}`;y.push(z.startsWith(jt)?` ${B}
248
+ -> it has the public prefix but is not set in this build's environment (an unset public var is undefined in the bundle; the server render does not fall back to it)`:` ${B}
249
+ -> only ${jt}* is exposed to the client; rename it to ${jt}${z} if it is public config, or keep it server-only (it stays undefined here, in dev and in the bundle)`)}y.length>0&&console.warn(`Rosefc warning: import.meta.env.<name> carries only ${jt}* variables:
250
+ ${y.join(`
251
+ `)}`)}let v=new Map;g.forEach((d,y)=>{let D=[];for(let W of m[y].roseImports??[]){let z=_.resolve(_.dirname(g[y]),W.specifier),B=w.get(z);B&&D.push(B.index)}v.set(y,D)});let k=(d,y=new Set)=>{if(m[d].needsClient)return _.basename(g[d]);if(y.has(d))return null;y.add(d);for(let D of v.get(d)??[]){let W=k(D,y);if(W)return W}return null};m.forEach((d,y)=>{if(d.needsClient)return;let D=k(y);D&&(d.needsClient=!0,d.clientReasons=[...d.clientReasons??[],`imported component ${D} needs the client`])});let T=new Set,x=d=>{if(!T.has(d)){T.add(d);for(let y of m[d].roseImports??[]){let D=_.resolve(_.dirname(g[d]),y.specifier),W=w.get(D);W&&x(W.index)}}};g.forEach((d,y)=>{l[y].isComponent||x(y)});let E=m.map((d,y)=>T.has(y)&&l[y].isComponent?d.style:"").filter(Boolean).join(`
252
+ `);E?await P.promises.writeFile(_.join(r,"styles.css"),E):await P.promises.rm(_.join(r,"styles.css"),{force:!0});let N={};try{let d=_.join(n,"src","locales"),y=(await P.promises.readdir(d)).filter(W=>W.endsWith(".json")),D=await Promise.all(y.map(async W=>[W.slice(0,-5),JSON.parse(await P.promises.readFile(_.join(d,W),"utf-8"))]));N=Object.fromEntries(D)}catch{N={}}let R=N.en?"en":Object.keys(N).sort()[0]??"en",U=JSON.stringify(N).replace(/</g,"\\u003c"),L=f.i18n.preload??Object.keys(N),q=Object.keys(N).filter(d=>!L.includes(d));for(let d of L)N[d]||console.warn(`Rosefc: i18n.preload lists '${d}' but there is no src/locales/${d}.json - ignored`);if(await P.promises.rm(_.join(r,"locales"),{recursive:!0,force:!0}),q.length>0){let d=_.join(r,"locales");await P.promises.mkdir(d,{recursive:!0});for(let y of q)await P.promises.writeFile(_.join(d,`${y}.json`),JSON.stringify(N[y]))}let X=Object.fromEntries(Object.keys(N).filter(d=>!q.includes(d)).map(d=>[d,N[d]])),Y=JSON.stringify(X).replace(/</g,"\\u003c"),pe=_.join(n,".rosefc-build"),O=_.join(pe,`${process.pid}-${Qt(_.resolve(n))}`),A=P.existsSync(O);await P.promises.mkdir(O,{recursive:!0});let V=new Date;await P.promises.utimes(O,V,V),(!A||ms!==O)&&(pn.clear(),ms=O),Bn(pe);let Q=[_.join(_.dirname(Tt(import.meta.url)),"..","cli","content.ts"),_.join(_.dirname(Tt(import.meta.url)),"..","src","cli","content.ts")],ie=Q.find(d=>P.existsSync(d))??Q[0];P.copyFileSync(ie,_.join(O,"content-md.ts"));let ge=h.filter(d=>d&&(d.onRequest||d.onResponse));if(ge.length>0){let d=_.relative(O,_.join(n,"rosefc.config.js")).replace(/\\/g,"/");await P.promises.writeFile(_.join(O,"plugins.js"),`
253
+ import config from ${JSON.stringify(d)};
254
+
255
+ const list = Array.isArray(config) ? config : [];
256
+ export const hooks = list
257
+ .filter((p) => p && (p.onRequest || p.onResponse))
258
+ .map((p) => ({ name: p.name, onRequest: p.onRequest ? p.onRequest.bind(p) : null, onResponse: p.onResponse ? p.onResponse.bind(p) : null }));
259
+
260
+ export const hasRequestHooks = hooks.some((p) => p.onRequest);
261
+ export const hasResponseHooks = hooks.some((p) => p.onResponse);
262
+ `)}let ke=["../runtime/index.ts","../src/runtime/index.ts"].map(d=>Tt(new URL(d,import.meta.url))).find(d=>P.existsSync(d));if(!ke)throw new M("E-INTERNAL","Rosefc: the runtime source (src/runtime/index.ts) was not found next to the compiler",{hint:"the published package ships src/ beside dist-cli/ - reinstall it, or run from a checkout"});let Ae=nt(ke,{entryPoints:[ke],bundle:!0,outfile:_.join(O,"runtime.js"),format:"esm",platform:"browser",write:!0},o),ce=(()=>{let d=_.dirname(Tt(import.meta.url));for(let y of[_.join(d,"..","cli","prod-server.ts"),_.join(d,"..","src","cli","prod-server.ts")])if(P.existsSync(y))return y;return _.join(d,"..","cli","prod-server.ts")})(),C="import { createRequire as __cr } from 'node:module'; import { fileURLToPath as __f2p } from 'node:url'; import { dirname as __dn } from 'node:path'; const require = __cr(import.meta.url); const __filename = __f2p(import.meta.url); const __dirname = __dn(__filename);",$e=o?Promise.resolve({}):nt(ce,{entryPoints:[ce],bundle:!0,outfile:_.join(r,"prod.mjs"),format:"esm",platform:"node",write:!0,banner:{js:C},...lt,...i?{minify:!0,keepNames:!0}:{}},o);Ae.catch(()=>{}),$e.catch(()=>{});let Oe=[],Z=(d,y)=>{pn.get(d)!==y&&(pn.set(d,y),Oe.push(P.promises.writeFile(_.join(O,d),y)))};for(let d=0;d<m.length;d++){let y=m[d].api??m[d].ssr;Z(`comp-${d}.ssr.js`,y),l[d].isApi||Z(`comp-${d}.client.js`,m[d].client)}for(let d=0;d<Oe.length;d+=64)await Promise.all(Oe.slice(d,d+64));let I=l.map((d,y)=>({info:d,i:y})).filter(({info:d})=>!d.isLayout&&!d.isNotFound&&!d.isError&&!d.isApi&&!d.isMiddleware&&!d.isComponent).sort((d,y)=>{let D=B=>{let H=B.split("/");return[H.filter(ne=>ne.startsWith("**")).length,H.filter(ne=>ne.startsWith("*")).length,H.filter(ne=>ne.startsWith(":")).length]},W=D(d.info.pattern),z=D(y.info.pattern);for(let B=0;B<3;B++)if(W[B]!==z[B])return W[B]-z[B];return d.info.filePath<y.info.filePath?-1:1}),J=l.map((d,y)=>({info:d,i:y})).filter(({info:d})=>d.isApi).sort((d,y)=>{let D=B=>{let H=B.split("/");return[H.filter(ne=>ne.startsWith("**")).length,H.filter(ne=>ne.startsWith("*")).length,H.filter(ne=>ne.startsWith(":")).length]},W=D(d.info.pattern),z=D(y.info.pattern);for(let B=0;B<3;B++)if(W[B]!==z[B])return W[B]-z[B];return d.info.filePath<y.info.filePath?-1:1}),te=d=>{let y=`render_${d}`;for(let D of rt(l,d))y=`(async (closes, children) => await render_${D}(closes, await (${y})(closes, children)))`;return y},le=_.join(n,"src","pages","_layout.rose"),ee=g.findIndex((d,y)=>m[y].bundle&&d!==le);if(ee>=0)throw new M("E-BUNDLE",`${_.basename(g[ee])}: export const bundle switches the whole app's bundle mode, so it belongs in the root layout (src/pages/_layout.rose)`,{file:g[ee],hint:"move `export const bundle = 'split'` (or 'inline') to src/pages/_layout.rose - the mode is per-app, not per-page"});let de=m[g.indexOf(le)]?.bundle??"inline",me=de==="split",K=de==="sliced",fe=d=>"s"+ct(d).toString(36),F=It.replace(/^import\s*\{/,"").replace(/\}\s*from[\s\S]*$/,"").split(",").map(d=>d.trim()).filter(Boolean),we=(()=>{let d=D=>D.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),y=new Set;for(let D of m){if(!D.client)continue;let W=D.client.replace(/^import\s*\{[^}]*\}\s*from\s*'\.\/runtime\.js';/m,"");for(let z of F)y.has(z)||new RegExp(`(?<![\\w$])${d(z)}(?![\\w$])`).test(W)&&y.add(z)}return F.filter(D=>y.has(D))})(),ae=d=>[d,...rt(l,d)],Se=d=>`load: () => loadChain([${ae(d).map(y=>`() => import('./comp-${y}.client.js')`).join(", ")}])`,De=d=>`{ ${Se(d)} }`,je=d=>Mt(l,m,d),ye=m.map((d,y)=>{if(!T.has(y))return"";if(l[y].isMiddleware)return`import * as middlewareMod from './comp-${y}.ssr.js';`;if(l[y].isApi){let Ee=(m[y].apiMethods??[]).map(ve=>`${ve} as ${ve}_${y}`).join(", ");return Ee?`import { ${Ee} } from './comp-${y}.ssr.js';`:`import './comp-${y}.ssr.js';`}let D=!l[y].isLayout&&!l[y].isNotFound,z=(D?m[y].actionNames:[]).map(ne=>`${ne} as ${ne}_${y}`).join(", "),B=D&&m[y].guardName?`beforeAction as beforeAction_${y}`:"",H=[z,B].filter(Boolean).join(", ");return H?`import { render as render_${y}, ${H} } from './comp-${y}.ssr.js';`:`import { render as render_${y} } from './comp-${y}.ssr.js';`}).join(`
263
+ `),Pe=l.map((d,y)=>({info:d,i:y})).filter(({info:d})=>d.isNotFound).map(({info:d,i:y})=>{let D=_.relative(_.join(n,"src","pages"),d.filePath).replace(/\\/g,"/"),W=_.posix.dirname(D),z=W==="."?"/":"/"+W,B=[];kn(l,m,y)&&B.push("shell: false"),Mt(l,m,y)&&B.push("csr: false");let H=B.length?`, { ${B.join(", ")} }`:"";return{prefix:z,render:te(y),flags:H}}).sort((d,y)=>y.prefix.length-d.prefix.length),Je=`[
264
+ ${Pe.map(d=>` ['${d.prefix}', ${d.render}${d.flags}],`).join(`
265
+ `)}
266
+ ]`,qe=l.findIndex(d=>d.isError),Be=qe>=0?te(qe):"null",Xe=qe>=0?Mt(l,m,qe):!1,Dt=l.findIndex(d=>d.isMiddleware),mt=I.map(({info:d,i:y})=>{let D=m[y].actionNames.map(ve=>`${ve}: ${ve}_${y}`).join(", ");if(m[y].csr===!1&&m[y].needsClient)throw new M("E-EXPORT",`${d.filePath}: csr = false but this route needs the client bundle (${(m[y].clientReasons??["needs the client"]).join(" + ")}).`,{file:d.filePath,hint:"remove csr = false (the compiler decides zero-JS by itself), or remove the client-only code listed above"});if(m[y].csr===!1){let ve=rt(l,y).find(ze=>m[ze].needsClient);if(ve!==void 0)throw new M("E-EXPORT",`${d.filePath}: csr = false cannot ship under ${l[ve].filePath} - the layout needs the client bundle (event wiring, onMount/onCleanup, refresh() or a server action).`,{file:d.filePath,hint:"a layout needing the runtime bundles every route under it - drop csr = false here, or make the layout content-only"})}let W=je(y)?", csr: false":"",z=kn(l,m,y)?", shell: false":"",B=m[y].buffer?", buffer: true":"",H=m[y].controlSignal?", signal: true":"",ne=m[y].guardName?`, guard: beforeAction_${y}`:"",Ee=K&&!je(y)?`, slice: '${fe(d.pattern)}'`:"";return`{ pattern: '${d.pattern}', path: '${d.routePath}', render: ${te(y)}, actions: ${D?`{ ${D} }`:"null"}${ne}${W}${z}${B}${H}${Ee} }`}).join(`,
267
+ `),Me=m.some(d=>d.usesRosefcAuth),wt=m.some(d=>/\$(?:udp|tcp|listen|mqtt)\s*\(/.test((d.ssr||"")+(d.client||"")+(d.api||""))),Ye=m.some(d=>/\$websocket\s*\(/.test((d.ssr||"")+(d.client||"")+(d.api||""))),yt=`
268
+ ${ye}
269
+ import { renderMarkdown } from './content-md.ts';
270
+ ${Me?"import crypto from 'node:crypto';":"// no route references __rosefcAuth: the node:crypto auth helpers are omitted, keeping the bundle edge-loadable"}
271
+ ${wt?`import * as __rosefcDgram from 'node:dgram';
272
+ import * as __rosefcNet from 'node:net';`:"// no route opens a network listener ($udp/$tcp/$listen): the node:dgram/node:net imports are omitted, keeping the bundle edge-loadable"}
273
+ ${Ye?`import * as __rosefcHttp from 'node:http';
274
+ import * as __rosefcCrypto from 'node:crypto';`:"// no route opens a WebSocket server ($websocket): the node:http/node:crypto imports are omitted, keeping the bundle edge-loadable"}
275
+ import { setState, persistState, clearRequestState, isolateRender, serializeState, resetRequestContext, installContextStore, setRequestQuery, getRequestQuery, getContext, isLocale, setLocales, localeList, localeDir, setStoreTransport, applyStorePatch, ActionError, StateDelta, setStateDelta, esc, __startNetwork, __stopNetwork, $udp, $tcp, $listen, $websocket, $mqtt } from './runtime.js';
276
+ export { __startNetwork, __stopNetwork };
277
+ ${ge.length>0?"import { hooks as __pluginHooks, hasRequestHooks as __hasRequestHooks, hasResponseHooks as __hasResponseHooks } from './plugins.js';":`// no plugin declares a runtime hook, so there is no plugins
278
+ // module to import - the runners below stay no-ops and the servers call them
279
+ // unconditionally (one code path, no flags to keep in sync).
280
+ const __pluginHooks = [];
281
+ const __hasRequestHooks = false;
282
+ const __hasResponseHooks = false;`}
283
+
284
+
285
+ export async function runRequestHooks(ctx) {
286
+ for (const p of __pluginHooks) {
287
+ if (!p.onRequest) continue;
288
+ try {
289
+ const r = await p.onRequest(ctx);
290
+ if (r instanceof Response) return r;
291
+ } catch (err) {
292
+ console.error('Rosefc: plugin', p.name, 'onRequest failed:', err instanceof Error ? err.message : err);
293
+ }
294
+ }
295
+ return null;
296
+ }
297
+
298
+ export async function runResponseHooks(ctx, res) {
299
+ let out = res;
300
+ for (const p of __pluginHooks) {
301
+ if (!p.onResponse) continue;
302
+ try {
303
+ const r = await p.onResponse(ctx, out);
304
+ if (r instanceof Response) out = r;
305
+ } catch (err) {
306
+ console.error('Rosefc: plugin', p.name, 'onResponse failed:', err instanceof Error ? err.message : err);
307
+ }
308
+ }
309
+ return out;
310
+ }
311
+
312
+
313
+ export const hasRequestHooks = __hasRequestHooks;
314
+ export const hasResponseHooks = __hasResponseHooks;
315
+
316
+ // P0-1: the query of the request being rendered, for $query().
317
+ export function setQuery(query) {
318
+ setRequestQuery(query || {});
319
+ }
320
+
321
+
322
+ setLocales(${U}, '${R}');
323
+
324
+
325
+ // Live store channel: every $store write fans out to the browsers holding an open
326
+ // SSE connection AND (when forked) to sibling workers. The client set lives on
327
+ // globalThis so a dev hot-re-import (a fresh module instance) keeps serving the
328
+ // same live connections. __addStoreClient/__removeStoreClient are called by the
329
+ // host (cli serve worker / devWrap) as SSE connections open and close.
330
+ const __storeClients: Set<any> = (globalThis as any).__rosefc_storeClients || ((globalThis as any).__rosefc_storeClients = new Set());
331
+ function __broadcastStore(name: string, value: unknown): void {
332
+ if (__storeClients.size === 0) return;
333
+ const frame = 'event: store\\ndata: ' + JSON.stringify({ name: name, value: value }) + '\\n\\n';
334
+ for (const res of __storeClients) {
335
+ try { res.write(frame); } catch { __storeClients.delete(res); }
336
+ }
337
+ }
338
+ setStoreTransport((name, value) => {
339
+ __broadcastStore(name, value);
340
+ if (typeof process !== 'undefined' && typeof process.send === 'function') process.send({ type: 'rosefc:store', name, value });
341
+ });
342
+ if (typeof process !== 'undefined' && typeof process.send === 'function') {
343
+ process.on('message', (msg) => {
344
+ if (msg && msg.type === 'rosefc:store') {
345
+ applyStorePatch(msg.name, msg.value);
346
+ __broadcastStore(msg.name, msg.value);
347
+ }
348
+ });
349
+ }
350
+ export function __addStoreClient(res: any): void { __storeClients.add(res); }
351
+ export function __removeStoreClient(res: any): void { __storeClients.delete(res); }
352
+
353
+
354
+ // (the cross-machine seam): the cluster relay above covers ONE machine.
355
+ export function __installStoreTransport(send: (name: string, value: unknown) => void): void {
356
+ // Wrap, not replace: a cross-machine transport (a plugin's LISTEN/NOTIFY bus)
357
+ // still fans out to this machine's live browsers on every patch.
358
+ setStoreTransport((name, value) => { __broadcastStore(name, value); send(name, value); });
359
+ }
360
+ export function __deliverStorePatch(name: string, value: unknown): void {
361
+ applyStorePatch(name, value);
362
+ __broadcastStore(name, value);
363
+ }
364
+
365
+ export { localeList };
366
+ export const defaultLocale = '${R}';
367
+
368
+ // Route params maps, re-exported for the build's prerender step: routePath -> the component's exported params (a static map or a function).
369
+ ${I.filter(({i:d})=>m[d].hasParams).map(({i:d})=>`import * as comp_${d} from './comp-${d}.ssr.js';`).join(`
370
+ `)}
371
+
372
+ export const routeParams = {
373
+ ${I.filter(({info:d,i:y})=>m[y].hasParams).map(({info:d,i:y})=>`'${d.routePath}': comp_${y}.params`).join(`,
374
+ `)}
375
+ };
376
+
377
+ // Routes whose component reads the request context (getContext()), mutates a shared store ($store()), reads the query ($query(), P0-1)
378
+ export const dynamicRoutes = [
379
+ ${I.filter(({i:d})=>m[d].usesContext||m[d].cspNonce||m[d].buffer||m[d].controlSignal||m[d].needsClient).map(({info:d})=>`'${d.routePath}'`).join(`,
380
+ `)}
381
+ ];
382
+
383
+ // Routes that the prerender function should skip (not bake into static files).
384
+ export const prerenderSkipRoutes = [
385
+ ${I.filter(({i:d})=>m[d].usesContext||m[d].cspNonce||m[d].buffer||m[d].controlSignal).map(({info:d})=>`'${d.routePath}'`).join(`,
386
+ `)}
387
+ ];
388
+
389
+ // Which api routes opt into build-time baking (export const prerender = true): routePath -> boolean.
390
+ ${J.filter(({i:d})=>m[d].hasPrerender).map(({i:d})=>`import * as api_${d} from './comp-${d}.ssr.js';`).join(`
391
+ `)}
392
+
393
+ export const apiPrerender = {
394
+ ${J.map(({info:d,i:y})=>`'${d.routePath}': ${m[y].hasPrerender?`api_${y}.prerender === true`:"false"}`).join(`,
395
+ `)}
396
+ };
397
+
398
+
399
+ export const revalidate = [
400
+ ${I.filter(({i:d})=>m[d].revalidate!==void 0&&!m[d].usesContext).map(({info:d,i:y})=>`{ pattern: '${d.pattern}', seconds: ${m[y].revalidate} }`).join(`,
401
+ `)}
402
+ ];
403
+
404
+ // Per-request render memo (export const cache = N): a dynamic route's whole renderPage result is memoized for N seconds.
405
+ // R256: a page that reads getContext() holds per-request state (the middleware
406
+ // put the caller's identity there), so its render must not be memoized: the
407
+ // second request in the window replayed the FIRST request's whole page -
408
+ // another user's context, in the same slot. The revalidate list above
409
+ // already refuses such a page; the memo did not, and now it does too.
410
+ export const routeCaches = [
411
+ ${I.filter(({i:d})=>m[d].cache!==void 0&&!m[d].usesContext).map(({info:d,i:y})=>`{ pattern: '${d.pattern}', seconds: ${m[y].cache} }`).join(`,
412
+ `)}
413
+ ];
414
+
415
+ // Hot-cache key dimensions (export const hotVary = ['x-locale']): the shared
416
+ // server caches key on URL + cookie + accept-language only, so a route whose
417
+ // representation is negotiated on its own private header had one client's
418
+ // bytes replayed to another for a whole TTL (BUG.md AB) - and the app's only
419
+ // exits were a query tag (?l=, ?rv=) or no-store, which switches the cache off
420
+ // for the route entirely. Naming the headers here folds them into the key AND
421
+ // into the warm render that fills it, so every value gets its own entry and
422
+ // the cache keeps working.
423
+ export const routeHotVary = [
424
+ ${[...I,...J].filter(({i:d})=>m[d].hotVary).map(({info:d,i:y})=>`{ pattern: '${d.pattern}', dims: ${JSON.stringify(m[y].hotVary)} }`).join(`,
425
+ `)}
426
+ ];
427
+ export function hotVaryFor(pathname: string): string[] | null {
428
+ for (const r of routeHotVary) if (matchRoute(r.pattern, pathname)) return r.dims;
429
+ return null;
430
+ }
431
+ const __dynCache = new Map();
432
+ export function invalidateRenderCache(): void {
433
+ __dynCache.clear();
434
+ }
435
+
436
+
437
+ // Application KV cache primitive (server-side, per-worker in-memory): a zero-dependency store for expensive computations.
438
+ const __kvStore = new Map<string, { v: unknown; exp: number }>();
439
+ // Content collections: src/content/<coll>/*.md scanned once at build time,
440
+ const contentCollections = ${JSON.stringify(Qn(_.join(n,"src","content")))};
441
+ export const kv = {
442
+ get(key: string): unknown {
443
+ const e = __kvStore.get(key);
444
+ if (!e) return undefined;
445
+ if (e.exp < Date.now()) { __kvStore.delete(key); return undefined; }
446
+ return e.v;
447
+ },
448
+ set(key: string, value: unknown, ttlSeconds = 300): void {
449
+ if (__kvStore.size > 1000) {
450
+ const cutoff = Date.now();
451
+ for (const [k, e] of __kvStore) { if (e.exp < cutoff) __kvStore.delete(k); }
452
+ if (__kvStore.size > 2000) __kvStore.clear();
453
+ }
454
+ __kvStore.set(key, { v: value, exp: Date.now() + ttlSeconds * 1000 });
455
+ },
456
+ del(key: string): void { __kvStore.delete(key); },
457
+ has(key: string): boolean {
458
+ const e = __kvStore.get(key);
459
+ return !!e && e.exp >= Date.now();
460
+ },
461
+ };
462
+ globalThis.__rosefcKvApi = { kv, kvMemo: $kv };
463
+ globalThis.__rosefcContent = {
464
+ list: (coll: string, filter?: { tag: string }) => {
465
+ let items = contentCollections[coll] ?? [];
466
+ if (filter?.tag) items = items.filter((e) => ((e.frontmatter.tags as string[] | undefined) ?? []).includes(filter.tag));
467
+ return items.map((e) => ({ slug: e.slug, ...e.frontmatter }));
468
+ },
469
+ rss: (coll: string, opts: { title: string; origin: string; description?: string }) => {
470
+ return buildRss(contentCollections[coll] ?? [], opts);
471
+ },
472
+ get: (coll: string, slug: string, vars?: Record<string, unknown>) => {
473
+ const e = (contentCollections[coll] ?? []).find((x) => x.slug === slug);
474
+ if (!e) return null;
475
+ return { slug: e.slug, ...e.frontmatter, html: renderMarkdown(e.body, vars), toc: e.toc, readingTime: e.readingTime, wordCount: e.wordCount, excerpt: e.excerpt };
476
+ },
477
+ };
478
+
479
+ const v = {
480
+ validate(body: Record<string, unknown>, rules: Record<string, string[]>): { ok: boolean; errors: Record<string, string>; values: Record<string, unknown> } {
481
+ const errors: Record<string, string> = {};
482
+ const values: Record<string, unknown> = {};
483
+ for (const [field, ruleList] of Object.entries(rules)) {
484
+ let val = body[field];
485
+ for (const rule of ruleList) {
486
+ if (val === undefined || val === null || val === "") {
487
+ if (rule === "required") errors[field] = field + " is required";
488
+ else if (rule.startsWith("default:")) val = rule.slice(8);
489
+ continue;
490
+ }
491
+ if (rule === "string") val = String(val);
492
+ else if (rule === "trim") val = String(val).trim();
493
+ else if (rule === "number") {
494
+ const num = Number(val);
495
+ if (Number.isNaN(num)) errors[field] = field + " must be a number";
496
+ else val = num;
497
+ } else if (rule === "email") {
498
+ if (!/^[^s@]+@[^s@]+.[^s@]+$/.test(String(val))) errors[field] = field + " must be a valid email";
499
+ } else if (rule.startsWith("min:")) {
500
+ const min = Number(rule.slice(4));
501
+ if (typeof val === "number" ? val < min : String(val).length < min) errors[field] = field + " must be at least " + min;
502
+ } else if (rule.startsWith("max:")) {
503
+ const max = Number(rule.slice(4));
504
+ if (typeof val === "number" ? val > max : String(val).length > max) errors[field] = field + " must be at most " + max;
505
+ }
506
+ }
507
+ values[field] = val;
508
+ }
509
+ return { ok: Object.keys(errors).length === 0, errors, values };
510
+ },
511
+ };
512
+
513
+ const jobs = {
514
+ _timers: new Map<string, ReturnType<typeof setInterval>>(),
515
+ every(name: string, seconds: number, fn: () => void | Promise<void>): void {
516
+ if (this._timers.has(name)) return;
517
+ const t = setInterval(() => { Promise.resolve(fn()).catch(() => {}); }, seconds * 1000);
518
+ this._timers.set(name, t as any);
519
+ },
520
+ cancel(name: string): void {
521
+ const t = this._timers.get(name);
522
+ if (t) { clearInterval(t); this._timers.delete(name); }
523
+ },
524
+ cancelAll(): void { for (const t of this._timers.values()) clearInterval(t); this._timers.clear(); }
525
+ };
526
+
527
+ function sse(handler: (send: (event: string, data: unknown) => void) => Promise<void> | void): Response {
528
+ const encoder = new TextEncoder();
529
+ const stream = new ReadableStream({
530
+ async start(controller) {
531
+ let closed = false;
532
+ const send = (event: string, data: unknown) => {
533
+ if (closed) return;
534
+ controller.enqueue(encoder.encode("event: " + event + "\\ndata: " + JSON.stringify(data) + "\\n\\n"));
535
+ };
536
+ try {
537
+ await handler(send);
538
+ } finally {
539
+ closed = true;
540
+ try { controller.close(); } catch { }
541
+ }
542
+ },
543
+ });
544
+ return new Response(stream, {
545
+ headers: { "content-type": "text/event-stream; charset=utf-8", "cache-control": "no-cache", "connection": "keep-alive" },
546
+ });
547
+ }
548
+ ${wt?`// The isomorphic runtime's $udp/$tcp reach Node's dgram/net only through these globals; injecting them at server boot is what lets __startNetwork() turn a registered spec into a bound socket.
549
+ (globalThis as any).__rosefc_dgram = __rosefcDgram;
550
+ (globalThis as any).__rosefc_net = __rosefcNet;`:""}
551
+ ${Ye?`// The isomorphic runtime's $websocket performs the RFC 6455 handshake (sha1) on a node:http upgrade socket; both reach it only through these globals.
552
+ (globalThis as any).__rosefc_http = __rosefcHttp;
553
+ (globalThis as any).__rosefc_crypto = __rosefcCrypto;`:""}
554
+ globalThis.__rosefcExtras = { v, jobs, sse, udp: $udp, tcp: $tcp, listen: $listen, websocket: $websocket, mqtt: $mqtt };
555
+ ${Me?`
556
+ const auth = {
557
+ hashPassword(password: string): string {
558
+ const salt = crypto.randomBytes(16).toString("hex");
559
+ const hash = crypto.scryptSync(password, salt, 32).toString("hex");
560
+ return salt + ":" + hash;
561
+ },
562
+ verifyPassword(password: string, stored: string): boolean {
563
+ const [salt, hash] = stored.split(":");
564
+ if (!salt || !hash) return false;
565
+ return crypto.timingSafeEqual(Buffer.from(hash, "hex"), crypto.scryptSync(password, salt, 32));
566
+ },
567
+ signSession(data: Record<string, unknown>, secret: string, ttlSeconds = 86400): string {
568
+ const payload = Buffer.from(JSON.stringify({ ...data, exp: Date.now() + ttlSeconds * 1000 })).toString("base64url");
569
+ const sig = crypto.createHmac("sha256", secret).update(payload).digest("base64url");
570
+ return payload + "." + sig;
571
+ },
572
+ verifySession<T = Record<string, unknown>>(token: string, secret: string): T | null {
573
+ const dot = token.lastIndexOf(".");
574
+ if (dot < 0) return null;
575
+ const payload = token.slice(0, dot);
576
+ const sig = token.slice(dot + 1);
577
+ const expect = crypto.createHmac("sha256", secret).update(payload).digest("base64url");
578
+ try {
579
+ if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expect))) return null;
580
+ } catch { return null; }
581
+ try {
582
+ const data = JSON.parse(Buffer.from(payload, "base64url").toString());
583
+ if (data.exp < Date.now()) return null;
584
+ return data as T;
585
+ } catch { return null; }
586
+ },
587
+ csrfToken(secret: string, sessionId: string): string {
588
+ return crypto.createHmac("sha256", secret).update(sessionId).digest("hex");
589
+ },
590
+ verifyCsrf(token: string, secret: string, sessionId: string): boolean {
591
+ try {
592
+ return crypto.timingSafeEqual(Buffer.from(token), Buffer.from(this.csrfToken(secret, sessionId)));
593
+ } catch { return false; }
594
+ },
595
+ };
596
+ globalThis.__rosefcAuth = auth;
597
+ `:"// __rosefcAuth helpers omitted: no route references them (keeps the bundle free of node:crypto and edge-loadable)"}
598
+
599
+ // Concurrent missers on a cold key share ONE compute through this inflight map - the check-then-set shape alone lets N simultaneous cold readers hammer.
600
+ const __kvInflight = new Map<string, Promise<unknown>>();
601
+ export async function $kv(key: string, compute: () => unknown | Promise<unknown>, ttlSeconds = 300): Promise<unknown> {
602
+ const hit = kv.get(key);
603
+ if (hit !== undefined) return hit;
604
+ let p = __kvInflight.get(key);
605
+ if (!p) {
606
+ p = (async () => {
607
+ const v = await compute();
608
+ if (v !== undefined) kv.set(key, v, ttlSeconds);
609
+ return v;
610
+ })();
611
+ __kvInflight.set(key, p);
612
+ p.finally(() => { __kvInflight.delete(key); }).catch(() => {});
613
+ }
614
+ return p;
615
+ }
616
+ export function isCachedRoute(pathname: string): boolean {
617
+ return routeClass(pathname).cache !== null;
618
+ }
619
+ export function invalidatePath(pathname: string): number {
620
+ let n = 0;
621
+ for (const key of [...__dynCache.keys()]) {
622
+ if (key.startsWith(pathname + '|')) { __dynCache.delete(key); n++; }
623
+ }
624
+ return n;
625
+ }
626
+ // The render memo is a shared store, so its key has to name the whole
627
+ // representation: URL + cookie alone let one visitor's render be replayed to
628
+ // another for the entire memo TTL whenever the route negotiates on a request
629
+ // header - accept-language first (BUG.md AB), then whatever the route itself
630
+ // declared with export const hotVary. dims is the caller-built negotiation
631
+ // fingerprint (accept-language plus the declared headers); it folds in here.
632
+ function __dynKey(pathname: string, cookieHeader: string, search: string, dims: string): string {
633
+ let h = 0x811c9dc5;
634
+ const c = (cookieHeader || '') + '\\u0000' + (dims || '');
635
+ for (let i = 0; i < c.length; i++) {
636
+ h ^= c.charCodeAt(i);
637
+ h = (h * 0x01000193) >>> 0;
638
+ }
639
+ // The query string is part of the cache key: routes like /search?q= or /archives?year= render different documents per query.
640
+ return pathname + '|' + (search || '') + '|' + h.toString(16);
641
+ }
642
+ export function peekRenderCache(pathname: string, cookieHeader: string, search = '', dims = ''): ReturnType<typeof renderPage> | null {
643
+ const cfg = routeClass(pathname).cache;
644
+ if (!cfg) return null;
645
+ const hit = __dynCache.get(__dynKey(pathname, cookieHeader, search, dims));
646
+ return hit && hit.expires > Date.now() ? hit.page : null;
647
+ }
648
+ // NOTE (R74): this memo caches renderPage's RETURN VALUE - pure HTML/state, NO
649
+ // set-cookie header (see the { html, state, head, status, ... } object at
650
+ // compiler/index.ts:5756). Set-Cookie is read only at the exit layer from the
651
+ // full Response (R57 list-header fix) and guarded at fillHot/refetchHot in
652
+ // R60, NOT here - there is nothing to guard in this layer. Do NOT add a
653
+ // set-cookie guard to this memo.
654
+ export async function renderPageCached(pathname: string, cookieHeader: string, search = '', dims = ''): Promise<ReturnType<typeof renderPage>> {
655
+ const cfg = routeClass(pathname).cache;
656
+ if (!cfg) return renderPage(pathname);
657
+ const key = __dynKey(pathname, cookieHeader, search, dims);
658
+ const hit = __dynCache.get(key);
659
+ if (hit && hit.expires > Date.now()) {
660
+ __dynCache.delete(key);
661
+ __dynCache.set(key, hit);
662
+ return hit.page;
663
+ }
664
+ // Stale-while-revalidate: an EXPIRED entry still answers instantly while one background render refreshes it - the TTL boundary never spikes.
665
+ if (hit && !hit.refreshing) {
666
+ hit.refreshing = true;
667
+ // BUG.md A: this refresh runs AFTER the live response returned, so the module-global
668
+ // requestQuery may already belong to a later request. Re-seed it from THIS entry's
669
+ // search and restore the snapshot afterward, so the cached refresh reflects this query.
670
+ const __q: Record<string, string> = {};
671
+ new URLSearchParams(search || '').forEach((v, k) => { __q[k] = v; });
672
+ const __prevQ = getRequestQuery();
673
+ setRequestQuery(__q);
674
+ renderPage(pathname).then((fresh: any) => {
675
+ setRequestQuery(__prevQ);
676
+ if (fresh.status === 200 && !fresh.redirect) {
677
+ __dynCache.set(key, { page: fresh, expires: Date.now() + cfg.seconds * 1000 });
678
+ } else {
679
+ __dynCache.delete(key);
680
+ }
681
+ }).catch(() => { setRequestQuery(__prevQ); __dynCache.delete(key); });
682
+ return hit.page;
683
+ }
684
+ // Miss: render with this request's query. The caller (edge/cli) already seeded
685
+ // requestQuery; re-seed from the key's search so the cached entry stays self-consistent
686
+ // even if a concurrent request overwrote the global during the await.
687
+ const __q0: Record<string, string> = {};
688
+ new URLSearchParams(search || '').forEach((v, k) => { __q0[k] = v; });
689
+ setRequestQuery(__q0);
690
+ const page = await renderPage(pathname);
691
+ if (page.status === 200 && !page.redirect) {
692
+ __dynCache.set(key, { page, expires: Date.now() + cfg.seconds * 1000 });
693
+ if (__dynCache.size > 300) {
694
+ __dynCache.delete(__dynCache.keys().next().value as string);
695
+ }
696
+ }
697
+ return page;
698
+ }
699
+
700
+ // Pages/_middleware.rose: a Web-standard request handler that runs before every render on the server (pages, POSTs, api calls alike).
701
+ export const middleware = ${Dt>=0?"middlewareMod.handle ?? null":"null"};
702
+
703
+ // Routes whose DOCUMENTS ship without the client bundle ( decided by the compiler since #29): HTML + CSS only - no runtime, no state script.
704
+ export const noJsRoutes = [
705
+ ${I.filter(({i:d})=>je(d)).map(({info:d})=>`'${d.pattern}'`).join(`,
706
+ `)}
707
+ ];
708
+
709
+ export function isNoJs(pathname) {
710
+ return routeClass(pathname).noJs;
711
+ }
712
+
713
+ // P0-2 (bug report): routes that exported "buffer = true".
714
+ export function isBuffered(pathname) {
715
+ return routeClass(pathname).buffered;
716
+ }
717
+
718
+
719
+ export const routeHeaders = [
720
+ ${I.filter(({i:d})=>m[d].headers).map(({info:d,i:y})=>`{ pattern: '${d.pattern}', headers: ${JSON.stringify(m[y].headers)} }`).join(`,
721
+ `)}
722
+ ];
723
+
724
+ export function headersFor(pathname) {
725
+ return routeClass(pathname).headers;
726
+ }
727
+
728
+
729
+ export const cspNonceRoutes = [
730
+ ${I.filter(({i:d})=>m[d].cspNonce).map(({info:d})=>`'${d.routePath}'`).join(`,
731
+ `)}
732
+ ];
733
+
734
+ export function cspNonce(pathname) {
735
+ return routeClass(pathname).nonce;
736
+ }
737
+
738
+ // A Web-standard Request from whatever the host provides: the edge adapter passes one already; the Node server passes its IncomingMessage (plus).
739
+ function toWebRequest(raw, form) {
740
+ if (raw instanceof Request) return raw;
741
+ const init = { method: raw.method || 'GET', headers: new Headers(raw.headers || {}) };
742
+ if (form) init.body = form;
743
+ let u = raw.url || '/';
744
+ if (u.startsWith('http://') || u.startsWith('https://')) {
745
+ try { const p = new URL(u); u = p.pathname + p.search; } catch { u = '/'; }
746
+ }
747
+ return new Request('http://' + (raw.headers?.host || 'localhost') + u, init);
748
+ }
749
+
750
+
751
+ export async function runMiddleware(rawReq, form) {
752
+ resetRequestContext();
753
+ if (!middleware || !rawReq) return null;
754
+ const res = await middleware(toWebRequest(rawReq, form));
755
+ return res || null;
756
+ }
757
+
758
+ const routes = [
759
+ ${mt}
760
+ ];
761
+
762
+ // API routes (pages/api/*.rose): pattern -> HTTP-method handlers. They never render HTML and never reach the client bundle.
763
+ const apiRoutes = [
764
+ ${J.map(({info:d,i:y})=>{let D=(m[y].apiMethods??[]).map(W=>`${W}: ${W}_${y}`).join(", ");return`{ pattern: '${d.pattern}', path: '${d.routePath}', handlers: { ${D} } }`}).join(`,
765
+ `)}
766
+ ];
767
+
768
+ // Not-found pages, deepest segment first: the root 404.rose ('/') and any
769
+ // pages/<seg>/_notfound.rose, each already composed with its layout chain.
770
+ // notFoundFor picks the nearest one up the path - an /admin miss answers
771
+ // the admin 404, a public miss the site's - and notFoundPage is the whole
772
+ // answer (real 404 status, or the built-in plain 404 when the app has none).
773
+ const notFoundRoutes = ${Je};
774
+ const notFoundFor = (pathname) => {
775
+ for (const [prefix, render] of notFoundRoutes) {
776
+ if (prefix === '/' || pathname === prefix || pathname.startsWith(prefix + '/')) return render;
777
+ }
778
+ return null;
779
+ };
780
+
781
+ const notFoundFlags = (pathname) => {
782
+ for (const [prefix, render, flags] of notFoundRoutes) {
783
+ if (prefix === '/' || pathname === prefix || pathname.startsWith(prefix + '/')) return flags || null;
784
+ }
785
+ return null;
786
+ };
787
+ const notFoundPage = async (pathname) => {
788
+ const nf = notFoundFor(pathname);
789
+ if (nf) {
790
+ const flags = notFoundFlags(pathname) || {};
791
+ // A zero-JS not-found document carries no state script (the shell drops it)
792
+ const noJs = flags.csr === false;
793
+ const page = await renderFallback(pathname, nf, noJs);
794
+ // __notFound stamps the document so the client boot paints THIS route instead of re-rendering the matched one: a catch-all whose resolver threw.
795
+ return { ...page, ...flags, status: 404, state: noJs ? '{}' : JSON.stringify({ __notFound: true, ...JSON.parse(page.state) }) };
796
+ }
797
+ return { html: '<h1>404</h1><p>Page not found</p>', state: JSON.stringify({ __route: pathname, __notFound: true }), head: [], status: 404, ...docAttrs(pathname) };
798
+ };
799
+
800
+
801
+ const errorPage = ${Be};
802
+
803
+
804
+ export function docAttrs(pathname) {
805
+ const c = routeClass(pathname);
806
+ return { lang: c.lang, dir: c.dir };
807
+ }
808
+
809
+ // Paint a fallback page (404/500) and serialize its state.
810
+ async function renderFallback(pathname, render, noJs = false) {
811
+ // Split mode: the not-found entry's render is a loader object \u95B3?resolve it through getRender (which memoizes the composed function) exactly like.
812
+ let fn = render;
813
+ if (typeof fn !== 'function' && fn && typeof fn.load === 'function') {
814
+
815
+ fn = (await fn.load()).render;
816
+ }
817
+ const { html, head } = extractHead(await fn([], ''));
818
+ const state = noJs ? '{}' : JSON.stringify({ __route: pathname, ...JSON.parse(serializeState()) });
819
+ return { html, state, head, ...docAttrs(pathname) };
820
+ }
821
+
822
+ export function matchRoute(pattern, pathname) {
823
+ // Q0 (bug report): one canonical URL per route.
824
+ pathname = pathname.replace(/\\/+$/, '') || '/';
825
+ const patternParts = pattern.split('/');
826
+ const pathParts = pathname.split('/');
827
+
828
+ const last = patternParts[patternParts.length - 1];
829
+ if (last && (last.startsWith('*') || last.startsWith('**'))) {
830
+ const fixed = patternParts.slice(0, -1);
831
+ if (pathParts.length < fixed.length) return false;
832
+ if (last.startsWith('*') && !last.startsWith('**') && pathParts.length === fixed.length) return false;
833
+ for (let i = 0; i < fixed.length; i++) {
834
+ if (fixed[i].startsWith(':')) continue;
835
+ if (fixed[i] !== pathParts[i]) return false;
836
+ }
837
+ return true;
838
+ }
839
+ if (patternParts.length !== pathParts.length) return false;
840
+ for (let i = 0; i < patternParts.length; i++) {
841
+ if (patternParts[i].startsWith(':')) continue;
842
+ if (patternParts[i] !== pathParts[i]) return false;
843
+ }
844
+ return true;
845
+ }
846
+
847
+ // Every predicate the servers ask before a render - canStream, isNoJs, isBuffered, shellOff, cspNonce, headersFor, docAttrs.
848
+ function routeClass(pathname) {
849
+ let c = __routeClass.get(pathname);
850
+ if (c) return c;
851
+ let route = null;
852
+ let stream = false;
853
+ let buffered = false;
854
+ let shell = false;
855
+ let lang = defaultLocale;
856
+ let dir = localeDir(defaultLocale);
857
+ let first = true;
858
+ for (const r of routes) {
859
+ if (!matchRoute(r.pattern, pathname)) continue;
860
+ if (route === null) route = r;
861
+ if (r.shell === false) shell = true;
862
+ if (r.buffer || r.signal) buffered = true;
863
+ const langIdx = r.pattern.split('/').indexOf(':lang');
864
+ if (langIdx < 0) {
865
+ stream = true;
866
+ } else if (isLocale(pathname.split('/')[langIdx])) {
867
+ stream = true;
868
+ // docAttrs answers from the FIRST matching route alone: its locale, or
869
+ if (first) {
870
+ const l = pathname.split('/')[langIdx];
871
+ lang = l;
872
+ dir = localeDir(l);
873
+ }
874
+ }
875
+ first = false;
876
+ }
877
+ let noJs = false;
878
+ for (const p of noJsRoutes) if (matchRoute(p, pathname)) { noJs = true; break; }
879
+ let nonce = false;
880
+ for (const p of cspNonceRoutes) if (matchRoute(p, pathname)) { nonce = true; break; }
881
+ let headers = null;
882
+ for (const r of routeHeaders) if (matchRoute(r.pattern, pathname)) { headers = r.headers; break; }
883
+ let cache = null;
884
+ for (const r of routeCaches) if (matchRoute(r.pattern, pathname)) { cache = r; break; }
885
+ c = { route, stream, buffered, shell, noJs, nonce, headers, cache, lang, dir, slice: route ? (route.slice ?? null) : null };
886
+ if (__routeClass.size >= 2000) {
887
+ const oldest = __routeClass.keys().next().value;
888
+ if (oldest !== undefined) __routeClass.delete(oldest);
889
+ }
890
+ __routeClass.set(pathname, c);
891
+ return c;
892
+ }
893
+ const __routeClass = new Map();
894
+
895
+ // Sliced inline: which dist/slices/<key>.js this pathname's document inlines.
896
+ // null for a path that matches no route (the 404 document inlines the
897
+ // runtime-only core) and for a zero-JS route (no script at all). The CLI and
898
+ // the edge adapter ask this instead of re-deriving pattern -> file; the
899
+ // export's existence is also how the edge adapter detects sliced mode.
900
+ ${K?`export function sliceKeyFor(pathname) {
901
+ return routeClass(pathname).slice;
902
+ }`:"// inline/split mode: no per-route bundle files exist"}
903
+
904
+ // Head blocks (one per component in the route chain) are pulled out of the page html: the shell injects them into <head>.
905
+ function extractHead(rendered) {
906
+ const head = [];
907
+ const html = rendered.replace(/<!--\u27E6h:(\\d+)\u27E7-->([\\s\\S]*?)<!--\u27E6\\/h:\\1\u27E7-->/g, (_, id, content) => {
908
+ head.push(content);
909
+ return '<!--\u27E6h:' + id + '\u27E7--><!--\u27E6/h:' + id + '\u27E7-->';
910
+ });
911
+ return { html, head };
912
+ }
913
+
914
+ // Form: the submitted FormData of a progressive-enhancement POST.
915
+ export async function renderPage(pathname, form, options) {
916
+ // Renders DO overlap in one process: prod-server warms every route in the background at startup.
917
+ return isolateRender(() => renderPageIsolated(pathname, form, options));
918
+ }
919
+
920
+ async function renderPageIsolated(pathname, form, options) {
921
+ clearRequestState();
922
+ // Cold-start readiness gate (Oboext #8): await the app's published DB-ready promise before any $data() read.
923
+ const appReady = globalThis.__rosefcAppReady;
924
+ if (appReady) await appReady;
925
+ const route = routeClass(pathname).route;
926
+ if (route) {
927
+ const patternParts = route.pattern.split('/');
928
+ const pathParts = pathname.split('/');
929
+ for (let i = 0; i < patternParts.length; i++) {
930
+ const seg = patternParts[i];
931
+ if (seg.startsWith(':')) setState(seg.slice(1), pathParts[i]);
932
+
933
+ else if (seg.startsWith('*')) setState(seg.replace(/^\\*+/, ''), pathParts.slice(i));
934
+ }
935
+ // I18n: a [lang] segment naming no dictionary is a 404 - the URL is the contract.
936
+ const langIdx = patternParts.indexOf(':lang');
937
+ if (langIdx >= 0 && !isLocale(pathParts[langIdx])) {
938
+
939
+ return await notFoundPage(pathname);
940
+ }
941
+
942
+ const docLang = langIdx >= 0 ? pathParts[langIdx] : defaultLocale;
943
+ // The action dispatch. The page's guard (exported beforeAction) runs FIRST and vetoes with an ActionError - the action-level permission check.
944
+ let actionStatus = 0;
945
+ if (form && route.actions) {
946
+ const actionName = form.get('__action') || 'action';
947
+ const fn = route.actions[actionName];
948
+ if (fn) {
949
+ try {
950
+ if (route.guard) await route.guard(actionName, form);
951
+ const patch = await fn(form);
952
+ if (patch && typeof patch === 'object') {
953
+ for (const key of Object.keys(patch)) {
954
+ const v = patch[key];
955
+ // An incremental patch is RECORDED, not applied: the render's own state declarations apply.
956
+ if (v instanceof StateDelta) setStateDelta(key, v);
957
+ else setState(key, v);
958
+ }
959
+ }
960
+ } catch (err) {
961
+ if (err instanceof ActionError) {
962
+ setState('actionError', { action: actionName, message: err.message, code: err.code, field: err.field });
963
+ actionStatus = err.code;
964
+ } else if (err && err.__rosefc === 'redirect') {
965
+
966
+ return { redirect: err.path, status: err.status ?? 303, ...docAttrs(pathname) };
967
+ } else if (err && err.__rosefc === 'notFound') {
968
+
969
+ return await notFoundPage(pathname);
970
+ } else {
971
+ throw err;
972
+ }
973
+ }
974
+ }
975
+ }
976
+ let rendered;
977
+ try {
978
+ rendered = extractHead(await route.render([], ''));
979
+ } catch (err) {
980
+ // The control-flow pair: redirect() and notFound() are THROWN from inside the render (a $data body resolving a slug that no longer exists).
981
+ const signal = err && err.__rosefc;
982
+ if (signal === 'redirect') {
983
+ return { redirect: err.path, status: err.status ?? 307, ...docAttrs(pathname) };
984
+ }
985
+ if (signal === 'notFound') {
986
+ return await notFoundPage(pathname);
987
+ }
988
+
989
+ console.error('Rosefc: render failed for', pathname, err instanceof Error ? err.message : err);
990
+ // F10: in dev the response body carries the real error \u95B3?message, file:line and the fix hint.
991
+ let devDetail = '';
992
+ if (process.env.ROSEFC_DEV === '1' && err) {
993
+ const msg = esc(err instanceof Error ? err.message : String(err));
994
+ const file = esc(String(err.file || ''));
995
+ const line = err.line != null ? esc(String(err.line)) : '';
996
+ const hint = esc(String(err.hint || ''));
997
+ const stack = esc(err instanceof Error ? (err.stack || '').split('\\n').slice(1, 7).join('\\n') : '');
998
+ devDetail = '<div style="margin:24px auto;max-width:860px;font:13px/1.6 ui-monospace,monospace;background:#1b1b1f;color:#e6e6ea;border:1px solid #3a3a42;border-radius:10px;padding:20px 24px;text-align:left;white-space:pre-wrap;word-break:break-word">'
999
+ + '<div style="font:600 15px/1.4 system-ui,sans-serif;color:#ff8b8b">Render failed: ' + esc(pathname) + '</div>'
1000
+ + '<div style="margin:10px 0 0;color:#ffd479">' + msg + '</div>'
1001
+ + (file ? '<div style="margin:6px 0 0;color:#9ad1ff">' + file + (line ? ':' + line : '') + '</div>' : '')
1002
+ + (hint ? '<div style="margin:10px 0 0;color:#9fe8b0">Fix: ' + hint + '</div>' : '')
1003
+ + (stack ? '<pre style="margin:12px 0 0;color:#8f8f9a">' + stack + '</pre>' : '')
1004
+ + '</div>';
1005
+ }
1006
+ if (errorPage) {
1007
+ // ErrorNoJs is a compile-time constant (see the errorNoJs declaration beside errorRender): a zero-JS site's 500 carries no state script.
1008
+ const fb = await renderFallback(pathname, errorPage, ${Xe});
1009
+ return { ...fb, html: fb.html + devDetail, status: 500${Xe?", csr: false":""} };
1010
+ }
1011
+ return { html: '<h1>500</h1><p>Something went wrong rendering this page.</p>' + devDetail, state: '{}', head: [], status: 500, ...docAttrs(pathname) };
1012
+ }
1013
+ // __route tells the bootstrap which route this document was rendered for.
1014
+ // A zero-JS route ships no state script - but a NATIVE client asking for the
1015
+ // JSON half of the render (the /__rosefc/data channel) still needs the values
1016
+ // its $data produced, so the withState option asks for them explicitly.
1017
+ const noJs = route.csr === false && !(options && options.withState);
1018
+ let state = '{}';
1019
+ if (!noJs || actionStatus !== 0) {
1020
+ const s = serializeState();
1021
+ state = '{"__route":' + JSON.stringify(pathname) + (s.length > 2 ? ',' + s.slice(1) : '}');
1022
+ }
1023
+ // Csr ( auto since #29): false when the compiler found nothing in the route's chain that needs the client (or the route asserted csr = false) .
1024
+ return { html: rendered.html, state, head: rendered.head, status: actionStatus || 200, csr: route.csr !== false, shell: route.shell !== false, lang: docLang, dir: localeDir(docLang) };
1025
+ }
1026
+ return await notFoundPage(pathname);
1027
+ }
1028
+
1029
+ // Would renderPageStream handle this path? (matched route = stream, anything
1030
+ export function canStream(pathname) {
1031
+ return routeClass(pathname).stream;
1032
+ }
1033
+
1034
+
1035
+ export function shellOff(pathname) {
1036
+ return routeClass(pathname).shell;
1037
+ }
1038
+
1039
+ // === API routes === The /api namespace answers JSON, never HTML: an API client that hits an unknown path must not receive the SPA shell.
1040
+ export function isApi(pathname) {
1041
+ return pathname === '/api' || pathname.startsWith('/api/');
1042
+ }
1043
+
1044
+ function toResponse(out) {
1045
+ if (out instanceof Response) return out;
1046
+ if (out === undefined || out === null) return new Response(null, { status: 204 });
1047
+ return new Response(JSON.stringify(out), {
1048
+ status: 200,
1049
+ headers: { 'content-type': 'application/json' },
1050
+ });
1051
+ }
1052
+
1053
+ export async function handleApi(method, pathname, request) {
1054
+ for (const route of apiRoutes) {
1055
+ if (matchRoute(route.pattern, pathname)) {
1056
+ // HEAD answers like GET with the body dropped by the host, which is the
1057
+ // HTTP contract every static server here already honors. It used to 405
1058
+ // on every route that only exported GET - the one method a health
1059
+ // check, an uptime monitor or a head-of-request probe actually sends.
1060
+ const verb = method === 'HEAD' && !route.handlers.HEAD ? 'GET' : method;
1061
+ // hasOwn, not a bare index: the handlers table is an object literal, so a
1062
+ // request line naming constructor, toString or valueOf used to find
1063
+ // Object.prototype's member and CALL it as the handler - a 200 whose
1064
+ // body was the prototype's return value, or a TypeError from the
1065
+ // dispatch. Not reachable through Node's HTTP parser (it rejects those
1066
+ // methods), but the edge adapter and rosefc/test pass the method through.
1067
+ const fn = Object.prototype.hasOwnProperty.call(route.handlers, verb) ? route.handlers[verb] : null;
1068
+ if (!fn) {
1069
+ return new Response(JSON.stringify({ error: 'method not allowed' }), {
1070
+ status: 405,
1071
+ headers: { 'content-type': 'application/json', allow: Object.keys(route.handlers).join(', ') },
1072
+ });
1073
+ }
1074
+ // A dynamic segment's value reaches the handler through the request
1075
+ // context: getContext().params.id for pages/api/posts/[id].rose. The
1076
+ // pattern MATCHED before, but the captured value went nowhere - the
1077
+ // docs promised "dynamic segments work", and a handler that cannot
1078
+ // read its own param is a 200-shaped lie. The bag is per-request
1079
+ // (the servers run each request in its own context scope), so this
1080
+ // cannot leak across requests.
1081
+ try {
1082
+ const patternParts = route.pattern.split('/');
1083
+ const pathParts = pathname.split('/');
1084
+ const params = {};
1085
+ for (let i = 0; i < patternParts.length && i < pathParts.length; i++) {
1086
+ const seg = patternParts[i];
1087
+ if (seg.startsWith(':')) params[seg.slice(1)] = decodeURIComponent(pathParts[i]);
1088
+ else if (seg.startsWith('*')) params[seg.replace(/^\\*+/, '')] = pathParts.slice(i).map(decodeURIComponent);
1089
+ }
1090
+ // The bag must describe THIS request: a host without a context store
1091
+ // (the edge adapter, rosefc/test) reuses one module-level object, so a
1092
+ // static route used to inherit the previous request's params - a
1093
+ // /api/posts/42 call made /api/health report an id it was never sent.
1094
+ // Assigning (rather than only when non-empty) drops the stale value.
1095
+ getContext().params = params;
1096
+ getContext().url = pathname + (new URL(request.url).search || '');
1097
+ } catch { /* a malformed segment must not kill the dispatch */ }
1098
+ try {
1099
+ // HEAD runs the GET handler and returns its Response untouched: the
1100
+ // host drops the body, and the headers a HEAD must report (the app's
1101
+ // own, plus the framework ETag the exit derives from the bytes) stay
1102
+ // exactly those of the GET. Returning an empty body here instead would
1103
+ // hand the caller a response with no validator at all.
1104
+ return toResponse(await fn(request));
1105
+ } catch (err) {
1106
+
1107
+ const signal = err && err.__rosefc;
1108
+ if (signal === 'redirect') {
1109
+ return new Response(JSON.stringify({ error: 'redirect', location: err.path }), {
1110
+ status: err.status ?? 307,
1111
+ headers: { 'content-type': 'application/json', location: err.path },
1112
+ });
1113
+ }
1114
+ if (signal === 'notFound') {
1115
+ return new Response(JSON.stringify({ error: 'not found' }), {
1116
+ status: 404,
1117
+ headers: { 'content-type': 'application/json' },
1118
+ });
1119
+ }
1120
+ throw err;
1121
+ }
1122
+ }
1123
+ }
1124
+ return new Response(JSON.stringify({ error: 'not found' }), {
1125
+ status: 404,
1126
+ headers: { 'content-type': 'application/json' },
1127
+ });
1128
+ }
1129
+
1130
+ // === Streaming SSR === The static shell (doctype, <head>, body + container open) flushes BEFORE the - possibly slow - render completes: the first byte.
1131
+ export async function renderPageStream(pathname, write, shellOpen, clientTag) {
1132
+ // Isolated for the same reason as renderPage: a streaming render awaits inside route.render()
1133
+ return isolateRender(() => renderPageStreamIsolated(pathname, write, shellOpen, clientTag));
1134
+ }
1135
+
1136
+ async function renderPageStreamIsolated(pathname, write, shellOpen, clientTag) {
1137
+ clearRequestState();
1138
+ // Cold-start readiness gate (Oboext #8): same contract as renderPage \u95B3?await the app's published DB-ready promise before streaming the shell.
1139
+ const appReady = globalThis.__rosefcAppReady;
1140
+ if (appReady) await appReady;
1141
+ const route = routeClass(pathname).route;
1142
+ if (route) {
1143
+ const patternParts = route.pattern.split('/');
1144
+ const pathParts = pathname.split('/');
1145
+ for (let i = 0; i < patternParts.length; i++) {
1146
+ const seg = patternParts[i];
1147
+ if (seg.startsWith(':')) setState(seg.slice(1), pathParts[i]);
1148
+
1149
+ else if (seg.startsWith('*')) setState(seg.replace(/^\\*+/, ''), pathParts.slice(i));
1150
+ }
1151
+ // i18n: an unknown locale must 404 BEFORE the shell flushes - a
1152
+ const langIdx = patternParts.indexOf(':lang');
1153
+ if (langIdx >= 0 && !isLocale(pathParts[langIdx])) return 404;
1154
+ write(shellOpen);
1155
+ let html;
1156
+ try {
1157
+ // nonce routes: an un-nonced inline <style> would be CSP-blocked, so strip to markers (applyHead re-injects under the nonce). Otherwise keep the head content in the streamed body so page/layout <style> applies on first paint (no FOUC) and no-JS routes stay styled.
1158
+ html = routeClass(pathname).nonce ? extractHead(await route.render([], '')).html : await route.render([], '');
1159
+ } catch (err) {
1160
+ console.error('Rosefc: render failed for', pathname, err instanceof Error ? err.message : err);
1161
+ // F10: dev carries the real error in the body here too \u95B3?the shell
1162
+ let devDetail = '';
1163
+ if (process.env.ROSEFC_DEV === '1' && err) {
1164
+ const msg = esc(err instanceof Error ? err.message : String(err));
1165
+ const file = esc(String(err.file || ''));
1166
+ const line = err.line != null ? esc(String(err.line)) : '';
1167
+ const hint = esc(String(err.hint || ''));
1168
+ const stack = esc(err instanceof Error ? (err.stack || '').split('\\n').slice(1, 7).join('\\n') : '');
1169
+ devDetail = '<div style="margin:24px auto;max-width:860px;font:13px/1.6 ui-monospace,monospace;background:#1b1b1f;color:#e6e6ea;border:1px solid #3a3a42;border-radius:10px;padding:20px 24px;text-align:left;white-space:pre-wrap;word-break:break-word">'
1170
+ + '<div style="font:600 15px/1.4 system-ui,sans-serif;color:#ff8b8b">Render failed: ' + esc(pathname) + '</div>'
1171
+ + '<div style="margin:10px 0 0;color:#ffd479">' + msg + '</div>'
1172
+ + (file ? '<div style="margin:6px 0 0;color:#9ad1ff">' + file + (line ? ':' + line : '') + '</div>' : '')
1173
+ + (hint ? '<div style="margin:10px 0 0;color:#9fe8b0">Fix: ' + hint + '</div>' : '')
1174
+ + (stack ? '<pre style="margin:12px 0 0;color:#8f8f9a">' + stack + '</pre>' : '')
1175
+ + '</div>';
1176
+ }
1177
+ html = errorPage ? (routeClass(pathname).nonce ? extractHead(await errorPage([], '')).html : await errorPage([], '')) + devDetail : '<h1>500</h1><p>Something went wrong rendering this page.</p>' + devDetail;
1178
+ }
1179
+ write(html);
1180
+ // Csr: false ( auto since #29): a no-JS route's document ends here - no state script, no inlined bundle.
1181
+ if (route.csr === false) {
1182
+ write('</div>\\n</body>\\n</html>');
1183
+ return 200;
1184
+ }
1185
+ const state = JSON.stringify({ __route: pathname, ...JSON.parse(serializeState()) });
1186
+ // P1-6 (bug report): the JSON data block is embedded in the document.
1187
+ const stateSafe = state.replace(/</g, '\\\\u003c');
1188
+ write('</div>\\n <script type="application/json" id="__rosefc_state">' + stateSafe + '</script>\\n ' + clientTag + '\\n</body>\\n</html>');
1189
+ return 200;
1190
+ }
1191
+ return 404;
1192
+ }
1193
+ // Prevent tree-shaking of invalidateRenderCache (called from prod-server.ts / edge.ts on non-GET writes).
1194
+ void invalidateRenderCache;
1195
+
1196
+ // Same reason, for the per-request context store: prod-server.ts installs an AsyncLocalStorage adapter.
1197
+ export { installContextStore };
1198
+ `;try{let d=[...I,...J].map(({info:Ee})=>Ee.pattern),y=[...new Set(d)].sort(),D=y.map(Ee=>JSON.stringify(Ee)).join(" | ")||"'/'",W=Ee=>(Ee.match(/:[\w]+|\*\*[\w]+|\*[\w]+/g)??[]).map(ve=>ve.replace(/^[*:]+/,"")),z=y.map(Ee=>{let ve=W(Ee);return ve.length?" "+JSON.stringify(Ee)+": { "+ve.map(ze=>ze+": string | number").join("; ")+` };
1199
+ `:""}).join(""),B=_.join(n,"src",".rosefc");await P.promises.mkdir(B,{recursive:!0});let H=["// GENERATED by rosefc build - do not edit.","export type RoutePath = "+D+";","export const routePatterns = "+JSON.stringify(y)+" as const;","export type RouteParams = {",z,"};","/** Build a URL from a route pattern and its params. */","export function url("," path: RoutePath,"," params: RouteParams[keyof RouteParams] = {} as never,","): string {"," let out = path as string;"," for (const [k, v] of Object.entries(params as Record<string, string | number>)) {"," out = out.replace(new RegExp('[:*]+' + k, 'g'), String(v));"," }"," return out;","}"].join(`
1200
+ `)+`
1201
+ `,ne=_.join(B,"routes.ts");try{await P.promises.readFile(ne,"utf8")!==H&&await P.promises.writeFile(ne,H)}catch{await P.promises.writeFile(ne,H)}}catch{}await P.promises.writeFile(_.join(O,"server-entry.js"),yt),await Ae;let ot=nt(_.join(O,"server-entry.js"),{entryPoints:[_.join(O,"server-entry.js")],bundle:!0,outfile:_.join(r,"server.js"),format:"esm",platform:"node",write:!0,...lt,...i?{minify:!0,keepNames:!0}:{}},o);ot.catch(()=>{});let it=m.map((d,y)=>({i:y})).filter(({i:d})=>!l[d].isApi&&!l[d].isMiddleware&&T.has(d)).map(({i:d})=>`import { render as render_${d} } from './comp-${d}.client.js';`).join(`
1202
+ `),rn=me||K?"":it,qt=me?I.map(({info:d,i:y})=>`{ pattern: '${d.pattern}', ${Se(y)} }`).join(`,
1203
+ `):I.map(({info:d,i:y})=>`{ pattern: '${d.pattern}', render: ${te(y)} }`).join(`,
1204
+ `),bt=d=>`load: () => __navRoute(${JSON.stringify(d)})`,Bt=d=>{let y=d===null?null:new Set(ae(d)),D=[K?`import { ${we.join(", ")} } from './runtime.js';`:"",y?m.map((z,B)=>({i:B})).filter(({i:z})=>y.has(z)&&!l[z].isApi&&!l[z].isMiddleware&&T.has(z)).map(({i:z})=>`import { render as render_${z} } from './comp-${z}.client.js';`).join(`
1205
+ `):""].filter(Boolean).join(`
1206
+ `),W=I.map(({info:z,i:B})=>d!==null&&B===d?`{ pattern: '${z.pattern}', render: ${te(B)} }`:`{ pattern: '${z.pattern}', ${bt(z.pattern)} }`).join(`,
1207
+ `);return{imports:D,routes:W}},Le=`[
1208
+ ${Pe.map(d=>` ['${d.prefix}', { load: () => __navNotFound(${JSON.stringify(d.prefix)}) }${d.flags}],`).join(`
1209
+ `)}
1210
+ ]`,$t=qe>=0?"{ load: () => __navError() }":"null",Ht=m.find(d=>d.prefetch)?.prefetch??"all",An=m.find(d=>d.lazyHydration)?.lazyHydration??!1,Jt=m.some(d=>d.vitals===!0),on=Jt?`
1211
+
1212
+
1213
+ reportVitals();
1214
+ `:"",et=l.some(d=>d.pattern.includes(":lang")),Wt=et?`
1215
+
1216
+
1217
+
1218
+
1219
+
1220
+ // (dist/mount.js) renders into a foreign page, whose language and
1221
+
1222
+ const seg = langIdx >= 0 ? pathname.split('/')[langIdx] : '';
1223
+ const known = !seg || isLocale(seg);
1224
+ if (container === document.getElementById('app')) {
1225
+ const docLang = known && seg ? seg : __defLocale;
1226
+ document.documentElement.lang = docLang;
1227
+ const docDir = localeDir(docLang);
1228
+ if (docDir) document.documentElement.setAttribute('dir', docDir);
1229
+ else document.documentElement.removeAttribute('dir');
1230
+ }
1231
+ if (!known) {`:" if (langIdx >= 0 && !isLocale(pathname.split('/')[langIdx])) {",We=d=>`
1232
+ ${d.imports}
1233
+ import { state, setState, resumeState, clearRequestState, resetEffects, wire, isolateStateAsync, restoreState, setRefreshHook, clearMounts, flushMounts, adoptCleanups, handlers, setActionDispatcher, setLocales, setLocalePacks, ensureLocale, isLocale, localeDir, setPrefetchOverride, serializeState, setFxOwner, resetContainerFx, esc, applyStorePatch } from './runtime.js';
1234
+ ${d.publish}
1235
+ ${m.some(y=>y.usesStore)?`
1236
+ // Live store channel: an app that reads a shared $store() keeps one EventSource to
1237
+ // /__rosefc_store. A server-side write ($store.set/update from a network listener,
1238
+ // a job, or an action) is pushed here as an {name,value} patch; applyStorePatch
1239
+ // writes it into the reactive store box, re-running the wire() effects that render
1240
+ // {store.get()} / {#each store.get()}. No store in the app - no connection.
1241
+ if (typeof window !== 'undefined' && typeof EventSource !== 'undefined') {
1242
+ try {
1243
+ var __storeEs = new EventSource('/__rosefc_store');
1244
+ __storeEs.addEventListener('store', function (m) {
1245
+ try { var p = JSON.parse(m.data); applyStorePatch(p.name, p.value); } catch (e) {}
1246
+ });
1247
+ } catch (e) {}
1248
+ }`:""}
1249
+
1250
+ // I18n: the dictionaries baked at build time - the client renders any PRELOADED locale from the bundle.
1251
+ setLocales(${Y}, '${R}');
1252
+ setLocalePacks(${JSON.stringify(q)});
1253
+ ${et?`// the default locale, kept beside setLocales' own copy so <html lang> can
1254
+ // follow a route that carries no [lang] segment (a non-i18n page)
1255
+ const __defLocale = '${R}';`:""}
1256
+ ${Jt?`// the app asked for web-vitals. The import is what keeps
1257
+ // reportVitals alive through minification and tree-shaking; the call is one
1258
+ // statement at boot, before the first render.
1259
+ import { reportVitals } from './runtime.js';`:""}
1260
+ // Lazy hydration: when the app opts in (export const lazyHydration = true in
1261
+ // the root _layout.rose), the bootstrap defers the initial wire() to
1262
+ // requestIdleCallback. The flag is set here (module eval runs before the
1263
+ // bootstrap's start() call) so the bootstrap can read it without a second channel.
1264
+ if (typeof window !== 'undefined') window.__rosefcLazy = ${JSON.stringify(An)};
1265
+ // The two pack doors, re-exported for an app that wants to warm a language before its visitor asks for it (ensureLocale) or to feed a dictionary.
1266
+ export { ensureLocale, loadLocale } from './runtime.js';
1267
+ ${d.prefetchDoor}
1268
+ ${on}
1269
+ ${d.nav}
1270
+ const routes = [
1271
+ ${d.routes}
1272
+ ];
1273
+
1274
+ // === Mode B: lazy route chunks === Split mode's registry entries arrive without a render function: loadChain loads the route's module graph (the page).
1275
+ const loadChain = async (loaders) => {
1276
+ const mods = await Promise.all(loaders.map((load) => load()));
1277
+ let expr = (closes, children) => mods[0].render(closes, children);
1278
+ for (let k = 1; k < mods.length; k++) {
1279
+ const inner = expr;
1280
+ const outer = mods[k].render;
1281
+ expr = async (closes, children) => await outer(closes, await inner(closes, children));
1282
+ }
1283
+ return { render: expr };
1284
+ };
1285
+ const getRender = async (route) => {
1286
+ if (typeof route === 'function') return route;
1287
+ // inline mode: the render itself
1288
+ return (route.render ??= (await route.load()).render);
1289
+ };
1290
+
1291
+ // Not-found pages, deepest segment first (the server's table, client half): the root 404.rose ('/') and any pages/<seg>/_notfound.rose.
1292
+ const notFoundRoutes = ${d.notFoundTable};
1293
+ const notFoundFor = (pathname) => {
1294
+ for (const [prefix, render] of notFoundRoutes) {
1295
+ if (prefix === '/' || pathname === prefix || pathname.startsWith(prefix + '/')) return render;
1296
+ }
1297
+ return null;
1298
+ };
1299
+
1300
+ // whose render throws degrades to this instead of failing the response.
1301
+ const errorPage = ${d.errorRender};
1302
+
1303
+ // Paint a fallback page (404/500) into the container, wired like any render.
1304
+ async function paintFallback(container, page, builtin, keepState = false) {
1305
+ if (!keepState) __navReset(container);
1306
+ clearMounts();
1307
+ // a failed render leaves stale mounts behind
1308
+ const render = page ? await getRender(page) : null;
1309
+ if (render) {
1310
+ // a packed locale's dictionary lands before the render
1311
+ const closes = [];
1312
+ await __withOwner(container, async () => {
1313
+
1314
+ const html = await render(closes, '');
1315
+ container.innerHTML = html;
1316
+ wire(container, closes);
1317
+ bindEvents(container);
1318
+ flushMounts();
1319
+ });
1320
+
1321
+ return;
1322
+ }
1323
+ container.innerHTML = builtin;
1324
+ }
1325
+
1326
+
1327
+ export async function startNotFound(container, pathname) {
1328
+ const el = document.getElementById('__rosefc_state');
1329
+ if (el) resumeState(el.textContent);
1330
+ await paintFallback(container, notFoundFor(pathname), '<h1>404</h1><p>Page not found</p>', true);
1331
+ }
1332
+
1333
+ export function matchRoute(pattern, pathname) {
1334
+ // Q0 (bug report): one canonical URL per route.
1335
+ pathname = pathname.replace(/\\/+$/, '') || '/';
1336
+ const patternParts = pattern.split('/');
1337
+ const pathParts = pathname.split('/');
1338
+
1339
+ const last = patternParts[patternParts.length - 1];
1340
+ if (last && (last.startsWith('*') || last.startsWith('**'))) {
1341
+ const fixed = patternParts.slice(0, -1);
1342
+ if (pathParts.length < fixed.length) return false;
1343
+ if (last.startsWith('*') && !last.startsWith('**') && pathParts.length === fixed.length) return false;
1344
+ for (let i = 0; i < fixed.length; i++) {
1345
+ if (fixed[i].startsWith(':')) continue;
1346
+ if (fixed[i] !== pathParts[i]) return false;
1347
+ }
1348
+ return true;
1349
+ }
1350
+ if (patternParts.length !== pathParts.length) return false;
1351
+ for (let i = 0; i < patternParts.length; i++) {
1352
+ if (patternParts[i].startsWith(':')) continue;
1353
+ if (patternParts[i] !== pathParts[i]) return false;
1354
+ }
1355
+ return true;
1356
+ }
1357
+
1358
+ // === Link prefetch === Hover / focus / touch an internal link and the target route renders NOW - $data included - against a throwaway signal map.
1359
+ let prefetchMode = ${JSON.stringify(Ht)};
1360
+ export function setPrefetchMode(mode) { prefetchMode = mode; }
1361
+ const PREFETCH_BUDGET = 8;
1362
+ const PREFETCH_MAX_CACHED = 4;
1363
+ const prefetchCache = new Map();
1364
+
1365
+ let prefetchQueue = Promise.resolve();
1366
+ let prefetchPending = 0;
1367
+
1368
+
1369
+ async function applyParams(route, pathname) {
1370
+ const patternParts = route.pattern.split('/');
1371
+ const pathParts = pathname.split('/');
1372
+ for (let i = 0; i < patternParts.length; i++) {
1373
+ const seg = patternParts[i];
1374
+ if (seg.startsWith(':')) setState(seg.slice(1), pathParts[i]);
1375
+
1376
+ else if (seg.startsWith('*')) setState(seg.replace(/^\\*+/, ''), pathParts.slice(i));
1377
+ }
1378
+ // streamed response cannot change its status afterwards
1379
+ const langIdx = patternParts.indexOf(':lang');
1380
+ if (langIdx >= 0) await ensureLocale(pathParts[langIdx]);
1381
+ }
1382
+
1383
+
1384
+ function __netOk() {
1385
+ const c = navigator.connection;
1386
+ if (!c) return true;
1387
+ if (c.saveData) return false;
1388
+ const t = c.effectiveType;
1389
+ return t !== 'slow-2g' && t !== '2g';
1390
+ }
1391
+
1392
+ export function prefetch(pathname, source = 'hover') {
1393
+ if (prefetchMode === 'off') return;
1394
+ if (prefetchMode === 'hover' && source !== 'hover') return;
1395
+ if (prefetchMode === 'viewport' && source !== 'viewport') return;
1396
+ if (!__netOk()) return;
1397
+ // save-data / 2g: no bytes before the click
1398
+ if (prefetchCache.has(pathname)) return;
1399
+ if (pathname === location.pathname) return;
1400
+
1401
+ const route = routes.find((r) => matchRoute(r.pattern, pathname));
1402
+ if (!route) return;
1403
+ if (prefetchPending >= PREFETCH_BUDGET) return;
1404
+ // Budget spent: drop it, a later hover retries P0-1: the link may carry a query (/search?q=cats).
1405
+ const qi = pathname.indexOf('?');
1406
+ const qOverride = qi >= 0 ? Object.fromEntries(new URLSearchParams(pathname.slice(qi))) : null;
1407
+ const p = prefetchQueue.then(async () => {
1408
+ try {
1409
+ setPrefetchOverride(qOverride);
1410
+ // The isolated render also captures the onMount callbacks the route queued and the onCleanup disposers it registered: the paint that consumes.
1411
+ const { result, state, mounts, cleanups } = await isolateStateAsync(async () => {
1412
+ await applyParams(route, pathname);
1413
+ const closes = [];
1414
+ const render = await getRender(route);
1415
+ const html = await render(closes, '');
1416
+ return { html, closes };
1417
+ });
1418
+ const entry = { ...result, state, mounts, cleanups };
1419
+ prefetchCache.set(pathname, entry);
1420
+ // Promise -> result evict oldest-first; in-flight promises are never evicted (evicting one would only force a duplicate render)
1421
+ while (prefetchCache.size > PREFETCH_MAX_CACHED) {
1422
+ const oldest = prefetchCache.keys().next().value;
1423
+ if (prefetchCache.get(oldest) instanceof Promise) break;
1424
+ prefetchCache.delete(oldest);
1425
+ }
1426
+ return entry;
1427
+ } catch {
1428
+ prefetchCache.delete(pathname);
1429
+ return null;
1430
+ } finally {
1431
+ setPrefetchOverride(null);
1432
+ prefetchPending--;
1433
+ }
1434
+ });
1435
+ prefetchPending++;
1436
+ prefetchCache.set(pathname, p);
1437
+ prefetchQueue = p;
1438
+ }
1439
+
1440
+ export function prefetchStats() {
1441
+ return { cached: prefetchCache.size, pending: prefetchPending, mode: prefetchMode, network: __netOk() };
1442
+ }
1443
+
1444
+ // One delegated listener per event type on the app container: survives DOM swaps and cloned blocks, so handlers never need re-binding.
1445
+ const DELEGATED = ['click', 'input', 'change', 'submit'];
1446
+ function bindEvents(container) {
1447
+ if (container.__rosefc_bound) return;
1448
+ container.__rosefc_bound = true;
1449
+ for (const ev of DELEGATED) {
1450
+ container.addEventListener(ev, (e) => {
1451
+ const el = e.target.closest('[data-on-' + ev + ']');
1452
+ if (!el || !container.contains(el)) return;
1453
+ const fn = el.getAttribute('data-on-' + ev);
1454
+ if (fn.startsWith('$action:')) return $action(fn.slice(8), e);
1455
+ const h = handlers[fn];
1456
+ if (h) h(e);
1457
+ });
1458
+ }
1459
+ }
1460
+
1461
+ // === Server actions from any event === POST the body to the current route and adopt the response in place: the server runs the selected action.
1462
+ async function postForm(body, container, pathname) {
1463
+
1464
+ const box = container || document.getElementById('app');
1465
+ const route = pathname || location.pathname;
1466
+ const res = await fetch(route, { method: 'POST', body });
1467
+ const html = await res.text();
1468
+ const doc = new DOMParser().parseFromString(html, 'text/html');
1469
+ const next = doc.getElementById('app');
1470
+ const st = doc.getElementById('__rosefc_state');
1471
+ const paint = () => {
1472
+ adopt(box, next ? next.innerHTML : '', st ? st.textContent : '{}', route);
1473
+ };
1474
+ if (document.startViewTransition) document.startViewTransition(paint);
1475
+ else paint();
1476
+ }
1477
+
1478
+ // Call a page's server action by name from any event handler: <button on:click={like}> compiles to $action('like').
1479
+ export async function $action(name, e) {
1480
+ if (e && e.preventDefault) e.preventDefault();
1481
+ // F34: the pending flag is ordinary signal state - {#if $actionPending()}
1482
+ const [__rvPending, __rvSetPending] = state('actionPending', false);
1483
+ __rvSetPending(true);
1484
+ const body = new FormData();
1485
+ body.append('__action', name);
1486
+ // An event inside a mount belongs to that mount - the attribute is kept in step with what is currently mounted.
1487
+ const box = e && e.target && e.target.closest ? e.target.closest('[data-rosefc]') : null;
1488
+ try {
1489
+ return await postForm(body, box || undefined, box ? box.getAttribute('data-rosefc') : undefined);
1490
+ } finally {
1491
+ __rvSetPending(false);
1492
+ }
1493
+ }
1494
+ // F17: hand the dispatcher to the runtime, so wire() can serve a server action bound to a non-delegated event (on:keydown="$action:save") the same way.
1495
+ setActionDispatcher($action);
1496
+
1497
+ export { postForm };
1498
+
1499
+ // The live signal graph as JSON - the same serializeState the zero-hydration resume uses.
1500
+ export { serializeState };
1501
+
1502
+
1503
+ // Initial=true: adopt the SSR DOM (zero hydration) - wire reactive markers to the existing nodes and bind events.
1504
+ function __ownsDoc(container) {
1505
+ return container === document.getElementById('app');
1506
+ }
1507
+ function __navReset(container) {
1508
+ if (__ownsDoc(container)) {
1509
+ resetEffects();
1510
+ clearRequestState();
1511
+ } else {
1512
+ resetContainerFx(container);
1513
+ }
1514
+ }
1515
+ // Attribute everything a render creates (state keys, effects, onCleanups) to
1516
+ async function __withOwner(container, fn) {
1517
+ if (__ownsDoc(container)) return fn();
1518
+ setFxOwner(container);
1519
+ try {
1520
+ return await fn();
1521
+ } finally {
1522
+ setFxOwner(null);
1523
+ }
1524
+ }
1525
+ // View Transition on SPA swaps (B9): the DOM swap rides one cross-fade when the browser supports it; reduced-motion users and environments without.
1526
+ async function __swap(container, html) {
1527
+ const reduce = typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;
1528
+ if (typeof document.startViewTransition === 'function' && !reduce) {
1529
+ const vt = document.startViewTransition(() => { container.innerHTML = html; });
1530
+ await vt.updateCallbackDone.catch(() => {});
1531
+ } else {
1532
+ container.innerHTML = html;
1533
+ }
1534
+ }
1535
+
1536
+ export async function start(container, pathname, initial) {
1537
+ clearMounts();
1538
+ // stale mounts from a failed render never fire
1539
+ if (initial) {
1540
+ const el = document.getElementById('__rosefc_state');
1541
+ if (el) resumeState(el.textContent);
1542
+ }
1543
+ for (const route of routes) {
1544
+ if (matchRoute(route.pattern, pathname)) {
1545
+ // I18n: an unknown locale paints the 404 page, same as the server (before the prefetch check: a cached entry for a bogus locale is discarded).
1546
+ const langIdx = route.pattern.split('/').indexOf(':lang');
1547
+ ${Wt}
1548
+
1549
+ await paintFallback(container, notFoundFor(pathname), '<h1>404</h1><p>Page not found</p>');
1550
+
1551
+ return;
1552
+ }
1553
+ // Prefetched on hover/focus/touch: the render already ran, so paint its HTML and adopt its signal entries - events then patch the very nodes we.
1554
+ let hit = initial ? undefined : prefetchCache.get(pathname);
1555
+ if (hit && typeof hit.then === 'function') hit = await hit;
1556
+ // in-flight: land it first
1557
+ if (hit) {
1558
+ prefetchCache.delete(pathname);
1559
+
1560
+ __navReset(container);
1561
+ restoreState(hit.state);
1562
+ await __swap(container, hit.html);
1563
+ await __withOwner(container, () => {
1564
+ wire(container, hit.closes);
1565
+ bindEvents(container);
1566
+ hit.mounts.forEach((fn) => fn());
1567
+ adoptCleanups(hit.cleanups);
1568
+ });
1569
+
1570
+ return;
1571
+ }
1572
+ if (!initial) __navReset(container);
1573
+ let broken = false;
1574
+ let signal = null;
1575
+ await __withOwner(container, async () => {
1576
+ await applyParams(route, pathname);
1577
+ const closes = [];
1578
+ let html;
1579
+ try {
1580
+ const render = await getRender(route);
1581
+
1582
+ html = await render(closes, '');
1583
+ } catch (err) {
1584
+
1585
+ if (err && err.__rosefc === 'notFound') { signal = 'notFound'; return; }
1586
+ if (err && err.__rosefc === 'redirect') { signal = err.path; return; }
1587
+
1588
+ console.error('Rosefc: client render failed for', pathname, err instanceof Error ? err.message : err);
1589
+ broken = true;
1590
+ return;
1591
+ }
1592
+ if (!initial) await __swap(container, html);
1593
+ wire(container, closes);
1594
+ bindEvents(container);
1595
+ flushMounts();
1596
+ });
1597
+ if (signal === 'notFound') {
1598
+ if (!initial) { try { location.assign(pathname); return; } catch { } }
1599
+ await paintFallback(container, notFoundFor(pathname), '<h1>404</h1><p>Page not found</p>');
1600
+ return;
1601
+ }
1602
+ if (signal) {
1603
+ location.href = signal;
1604
+ return;
1605
+ }
1606
+ if (broken) {
1607
+ await paintFallback(container, errorPage, '<h1>500</h1><p>Something went wrong rendering this page.</p>');
1608
+ }
1609
+ return;
1610
+ }
1611
+ }
1612
+ // Unmatched route: the nearest not-found page renders (with its head + interactivity) - a segment's _notfound.rose or the root 404.rose - else //.
1613
+ ${et?` // the same app-root gate as above - a mount never touches the
1614
+ // host document's language or direction.
1615
+ if (container === document.getElementById('app')) {
1616
+ document.documentElement.lang = __defLocale;
1617
+ document.documentElement.removeAttribute('dir');
1618
+ }`:""}
1619
+ await paintFallback(container, notFoundFor(pathname), '<h1>404</h1><p>Page not found</p>');
1620
+ }
1621
+
1622
+ // Adopt a server-rendered response in place - the JS-enabled half of progressive-enhancement forms: the bootstrap POSTs a <form method="POST">.
1623
+ export async function adopt(container, html, stateJson, pathname) {
1624
+
1625
+ const route0 = pathname || location.pathname;
1626
+ __navReset(container);
1627
+ clearMounts();
1628
+ // stale mounts from a failed render never fire
1629
+ resumeState(stateJson);
1630
+ container.innerHTML = html;
1631
+
1632
+ const st = document.getElementById('__rosefc_state');
1633
+ if (st) st.textContent = stateJson;
1634
+ for (const route of routes) {
1635
+ if (matchRoute(route.pattern, route0)) {
1636
+ await __withOwner(container, async () => {
1637
+ await applyParams(route, route0);
1638
+ const closes = [];
1639
+ try {
1640
+ const render = await getRender(route);
1641
+
1642
+ await render(closes, '');
1643
+ } catch {
1644
+ return;
1645
+ }
1646
+ wire(container, closes);
1647
+ bindEvents(container);
1648
+ flushMounts();
1649
+ });
1650
+ return;
1651
+ }
1652
+ }
1653
+ }
1654
+ // === refresh() implementation === Re-render the current route in place: the client half of router.refresh() (a router refresh) / (a full invalidation).
1655
+ setRefreshHook(async () => {
1656
+ prefetchCache.delete(location.pathname);
1657
+ await start(document.getElementById('app'), location.pathname, false);
1658
+ });
1659
+ `,Ie=K?`
1660
+ // === Sliced mode: the runtime bridge === The routes this document did NOT
1661
+ // inline ride the shared nav chunk, whose components resolve the runtime
1662
+ // through this object instead of bundling a second copy. Published before any
1663
+ // render runs; the chunk's shim throws if it loads first.
1664
+ globalThis.__rosefc_rt = { ${we.join(", ")} };`:"",tt=d=>K?`
1665
+ // === Sliced mode: the shared nav chunk === One file holds every route's
1666
+ // render chain this document did not inline, fetched on the first cross-route
1667
+ // navigation (or a hover prefetch). __rosefc_navImport is the override seam
1668
+ // (tests, or a host page with its own loader); the browser default is a plain
1669
+ // dynamic import of the versioned URL, which 'self' in the CSP allows.
1670
+ const __navUrl = ${JSON.stringify(d)};
1671
+ const __navImport = globalThis.__rosefc_navImport || ((u) => import(u));
1672
+ let __navMod = null;
1673
+ const __nav = async () => (__navMod ??= await __navImport(__navUrl));
1674
+ const __navRoute = async (pattern) => (await __nav()).navRenders[pattern];
1675
+ const __navNotFound = async (prefix) => (await __nav()).navNotFound[prefix];
1676
+ const __navError = async () => (await __nav()).navError;
1677
+ `:"",zt=We({imports:K?Bt(null).imports:rn,routes:K?Bt(null).routes:qt,publish:"",nav:"",notFoundTable:K?Le:Je,errorRender:K?$t:Be,prefetchDoor:""});K||await P.promises.writeFile(_.join(O,"client-entry.js"),zt);let xt=K?(async()=>{Z("runtime-global.js",["// Sliced-mode bridge (generated): the nav chunk resolves the runtime","// through the copy the route slice published, so a page runs exactly one","// runtime. Exports are tree-shaken to what the chunk references.","const __rt = globalThis.__rosefc_rt;","if (!__rt) throw new Error('rosefc: the sliced bundle bridge is missing - the route slice did not publish the runtime before the nav chunk loaded');",...F.map(H=>`export const ${H} = __rt.${H};`)].join(`
1678
+ `)+`
1679
+ `);let d=[];for(let H=0;H<m.length;H++)l[H].isApi||!T.has(H)||!m[H].client||d.push(P.promises.writeFile(_.join(O,`nav-comp-${H}.client.js`),m[H].client.replace(/from '\.\/runtime\.js'/g,"from './runtime-global.js'").replace(/from '\.\/comp-(\d+)\.client\.js'/g,"from './nav-comp-$1.client.js'")));let y=`
1680
+ ${it.replace(/from '\.\/comp-(\d+)\.client\.js'/g,"from './nav-comp-$1.client.js'")}
1681
+ export const navRenders = {
1682
+ ${I.map(({info:H,i:ne})=>`'${H.pattern}': { render: ${te(ne)} },`).join(`
1683
+ `)}
1684
+ };
1685
+ export const navNotFound = {
1686
+ ${Pe.map(H=>`'${H.prefix}': { render: ${H.render} },`).join(`
1687
+ `)}
1688
+ };
1689
+ export const navError = ${qe>=0?`{ render: ${te(qe)} }`:"null"};
1690
+ `;await Promise.all([...d,P.promises.writeFile(_.join(O,"nav-entry.js"),y)]),await nt(_.join(O,"nav-entry.js"),{entryPoints:[_.join(O,"nav-entry.js")],bundle:!0,outfile:_.join(r,"nav.js"),format:"esm",platform:"browser",minify:!0,write:!0,...lt},o);let D=await P.promises.readFile(_.join(r,"nav.js")),W="/nav.js?v="+ct(D);await At(_.join(r,"slices")),await P.promises.mkdir(_.join(r,"slices"),{recursive:!0});let z=[{entryFile:"client-entry.js",outFile:_.join(r,"client.js"),own:null},...I.map(({i:H})=>{let ne=fe(l[H].pattern);return{entryFile:`slice-entry-${ne}.js`,outFile:_.join(r,"slices",`${ne}.js`),own:H}})],B=[];for(let{entryFile:H,outFile:ne,own:Ee}of z){let ve=Bt(Ee),ze=_.join(O,H);await P.promises.writeFile(ze,We({imports:ve.imports,routes:ve.routes,publish:Ie,nav:tt(W),notFoundTable:Le,errorRender:$t,prefetchDoor:`
1691
+ export { setPrefetchOverride } from './runtime.js';`})),B.push(nt(ze+":slice",{entryPoints:[ze],bundle:!0,outfile:ne,format:"esm",platform:"browser",minify:!0,write:!0,...lt},o))}return await Promise.all(B),{}})():me?(async()=>(await At(_.join(r,"chunks")),nt(_.join(O,"client-entry.js")+":split",{entryPoints:[_.join(O,"client-entry.js")],bundle:!0,format:"esm",platform:"browser",minify:!0,splitting:!0,outdir:r,entryNames:"client",chunkNames:"chunks/[name]-[hash]",write:!0,...lt},o)))():nt(_.join(O,"client-entry.js"),{entryPoints:[_.join(O,"client-entry.js")],bundle:!0,outfile:_.join(r,"client.js"),format:"esm",platform:"browser",minify:!0,write:!0,...lt},o);await Promise.all([ot,xt,$e]);for(let d of[_.join(r,"server.js"),_.join(r,"prod.mjs")])try{if(!P.existsSync(d))continue;let y=await P.promises.readFile(d,"utf8");if(y.startsWith(C))continue;(/Dynamic require of/.test(y)||/(?<![\w$])require\s*\(/.test(y))&&await P.promises.writeFile(d,C+y,"utf8")}catch{}let vt=gs;try{let d=P.readFileSync(_.join(r,"client.js"));vt=gs.replace("from '/client.js'",`from '/client.js?v=${ct(d)}'`)}catch{}await P.promises.writeFile(_.join(r,"mount.js"),vt);let kt=_.join(n,"public");P.existsSync(kt)&&await P.promises.cp(kt,_.join(r,"public"),{recursive:!0}),console.log("Rosefc zero-JS report:");for(let d of qo(l,m))console.log(" "+d);let St=new Map;for(let{info:d,i:y}of I)if(Mt(l,m,y))for(let D of[y,...rt(l,y)])for(let W of m[D].jsWarnings??[]){let z=St.get(W);z||(z={why:W,files:new Map},St.set(W,z));let B=_.relative(n,l[D].filePath).replace(/\\/g,"/"),H=z.files.get(B);H||(H=new Set,z.files.set(B,H)),H.add(d.routePath)}for(let d of St.values()){let y=new Set;for(let B of d.files.values())for(let H of B)y.add(H);let D=[...d.files.entries()].sort((B,H)=>H[1].size-B[1].size).map(([B,H])=>`${B} (${H.size===1?[...H][0]:`${H.size} routes`})`),W=D.slice(0,4).join(", "),z=D.length>4?`, +${D.length-4} more files`:"";console.warn(`Rosefc warning: ${y.size} routes ship zero JavaScript while their chain contains ${d.why} - ${W}${z}`)}return{routes:I.map(({info:d})=>d),bundle:de,config:f}}async function Bo(e){let s=_.join(e,"src","pages");if(!P.existsSync(s))return[];async function t(n){let r=await P.promises.readdir(n,{withFileTypes:!0}),i=[];for(let o of r){let c=_.join(n,o.name);o.isDirectory()?i.push(...await t(c)):o.name.endsWith(".rose")&&i.push(c)}return i}return t(s)}async function Ho(e){let s=_.join(e,"src","components");if(!P.existsSync(s))return[];async function t(n){let r=await P.promises.readdir(n,{withFileTypes:!0}),i=[];for(let o of r){let c=_.join(n,o.name);o.isDirectory()?i.push(...await t(c)):o.name.endsWith(".rose")&&i.push(c)}return i}return t(s)}function Jo(e,s){let t=_.dirname(e),n=_.dirname(s);return n===t||n.startsWith(t+_.sep)}function Wo(e,s){let t=_.join(s,"src","pages"),r=_.relative(t,e).replace(/\\/g,"/").replace(/\.rose$/,""),i=_.posix.basename(r),o=e.replace(/\\/g,"/").includes("/src/components/"),c=!o&&i==="_layout",a=!o&&(i==="404"||i==="_notfound"),u=!o&&i==="500",g=!o&&(r==="api"||r.startsWith("api/")),l=!o&&r==="_middleware",f=r.split("/").filter(m=>m!=="_layout"&&m!=="_notfound");f.length>1&&f[f.length-1]==="index"&&(f=f.slice(0,-1));let h=/^\[\.\.\.(\w+)\]$/,p=/^\[\[\.\.\.(\w+)\]\]$/,w=f.map(m=>{let v=p.exec(m);if(v)return`**${v[1]}`;let k=h.exec(m);return k?`*${k[1]}`:m.startsWith("[")&&m.endsWith("]")?`:${m.slice(1,-1)}`:m}),b;return w.length===0||w.length===1&&w[0]==="index"?b="/":b="/"+w.join("/"),{filePath:e,routePath:b,pattern:b,paramNames:f.flatMap(m=>{let v=p.exec(m);if(v)return[v[1]];let k=h.exec(m);return k?[k[1]]:m.startsWith("[")&&m.endsWith("]")?[m.slice(1,-1)]:[]}),isLayout:c,isNotFound:a,isError:u,isApi:g,isMiddleware:l,isComponent:o}}function Ue(e){return e.charAt(0).toUpperCase()+e.slice(1)}import*as gt from"fs";import*as sn from"path";import*as Is from"esbuild";var Fs=sn.join(process.cwd(),"dist");var Yt=null;function Ds(){try{let e=sn.join(Fs,"client.js"),s=gt.statSync(e);return(!Yt||Yt.mtimeMs!==s.mtimeMs)&&(Yt={mtimeMs:s.mtimeMs,v:ct(gt.readFileSync(e))}),Yt.v}catch{return""}}function qs(){let e=Ds();return e?`/client.js?v=${e}`:"/client.js"}var en=null;function zo(){let e=sn.join(Fs,"styles.css");try{let s=gt.statSync(e);return(!en||en.mtimeMs!==s.mtimeMs)&&(en={mtimeMs:s.mtimeMs,source:gt.readFileSync(e,"utf-8")}),en.source}catch{return""}}var Rn=`
1692
+ // shell = false: the document's SSR content sits directly in <body> - no
1693
+ // #app wrapper, no demo styles, so a real theme's CSS owns the document from
1694
+ // the first byte (and a JS-less visitor never sees either). The bundle still
1695
+ // runs, and it still needs its container: wrap the content once, here, before
1696
+ // any theme script executes (module scripts run before DOMContentLoaded). The
1697
+ // wrapper is a plain unstyled div, so the re-parent is visually inert; every
1698
+ // later path - adoption, navigation, forms - is then the ordinary one.
1699
+ let __app = document.getElementById('app');
1700
+ if (!__app) {
1701
+ __app = document.createElement('div');
1702
+ __app.id = 'app';
1703
+ // scripts stay outside the wrapper, exactly where the dressed document
1704
+ // keeps them: the state element and the running module must survive a
1705
+ // navigation's innerHTML swap (they are the document's, not the route's).
1706
+ for (const node of Array.from(document.body.children)) {
1707
+ if (node.tagName !== 'SCRIPT') __app.appendChild(node);
1708
+ }
1709
+ document.body.appendChild(__app);
1710
+ }
1711
+ // Native View Transitions around client-side navigation (progressive:
1712
+ // browsers without the API navigate normally, no polyfill, no CSS required).
1713
+ // F35: stash the CURRENT entry's scroll position into its history state
1714
+ // before a new push - the browser only restores scroll on full page loads; a
1715
+ // pjax swap would land wherever the swap left it.
1716
+ function __saveScroll() {
1717
+ try {
1718
+ const s = history.state || {};
1719
+ history.replaceState(Object.assign({}, s, { __rosefcScroll: window.scrollY }), '');
1720
+ } catch (e) { /* history state unavailable (file:// edge): best effort */ }
1721
+ }
1722
+ function __navigate(pathname, restore) {
1723
+ const paint = () => {
1724
+ const p = start(__app, pathname);
1725
+ if (restore) {
1726
+ // back/forward: restore the entry's scroll (top when it has none)
1727
+ const s = history.state || {};
1728
+ const y = typeof s.__rosefcScroll === 'number' ? s.__rosefcScroll : 0;
1729
+ return Promise.resolve(p).then(() => { window.scrollTo(0, y); }, () => { window.scrollTo(0, y); });
1730
+ }
1731
+ // a fresh navigation starts at the top, like a full page load
1732
+ window.scrollTo(0, 0);
1733
+ return p;
1734
+ };
1735
+ if (document.startViewTransition) {
1736
+ return document.startViewTransition(paint).updateCallbackDone;
1737
+ }
1738
+ return paint();
1739
+ }
1740
+ window.addEventListener('popstate', () => __navigate(window.location.pathname, true));
1741
+ document.addEventListener('click', (e) => {
1742
+ const a = e.target.tagName === 'A' ? e.target : e.target.closest && e.target.closest('a');
1743
+ if (a && a.getAttribute('href') && a.getAttribute('href').startsWith('/')) {
1744
+ e.preventDefault();
1745
+ __saveScroll();
1746
+ history.pushState(null, '', a.getAttribute('href'));
1747
+ __navigate(window.location.pathname);
1748
+ }
1749
+ });
1750
+ // Prefetch the target route's full render (including $data) on hover, keyboard
1751
+ // focus, or touch - the click that follows paints from cache: no await, no
1752
+ // request. Other frameworks prefetch data only; Rosefc prefetches the render
1753
+ // because the inlined bundle already contains every route.
1754
+ function __prefetchHandler(e) {
1755
+ const a = e.target.closest && e.target.closest('a[href^="/"]');
1756
+ if (a && prefetch) prefetch(a.getAttribute('href'), 'hover');
1757
+ }
1758
+ document.addEventListener('mouseover', __prefetchHandler);
1759
+ document.addEventListener('focusin', __prefetchHandler);
1760
+ document.addEventListener('touchstart', __prefetchHandler, { passive: true });
1761
+ // Viewport + idle prefetch (viewport-triggered): once a link scrolls into view and the
1762
+ // browser is idle, its route renders ahead of any interaction. trade-off: both
1763
+ // APIs are feature-detected; without them the hover/focus/touch path above
1764
+ // still covers every link.
1765
+ if (prefetch && 'IntersectionObserver' in window && 'requestIdleCallback' in window) {
1766
+ const io = new IntersectionObserver((entries) => {
1767
+ for (const e of entries) {
1768
+ if (!e.isIntersecting) continue;
1769
+ io.unobserve(e.target); // one-shot per element; fresh links re-observe after nav
1770
+ requestIdleCallback(() => prefetch(e.target.getAttribute('href'), 'viewport'));
1771
+ }
1772
+ });
1773
+ // observing an already-observed element is a no-op, so re-sweeping is cheap
1774
+ const observeLinks = () => {
1775
+ for (const a of document.querySelectorAll('a[href^="/"]')) io.observe(a);
1776
+ };
1777
+ observeLinks();
1778
+ // navigation swaps the container's innerHTML: re-observe the fresh links
1779
+ const __rawNav = __navigate;
1780
+ __navigate = (p) => __rawNav(p).then(observeLinks, () => {});
1781
+ }
1782
+ // Progressive-enhancement forms: <form method="POST"> backed by a server
1783
+ // action. With JS the submit is intercepted and handed to postForm (one
1784
+ // request, in-place adopt). Without JS the browser performs the native POST
1785
+ // and the server re-renders the page: the same form works with JavaScript
1786
+ // disabled, which Server Actions in other frameworks do not.
1787
+ document.addEventListener('submit', (e) => {
1788
+ const f = e.target;
1789
+ if (!f || f.tagName !== 'FORM' || f.hasAttribute('data-on-submit')) return;
1790
+ if ((f.getAttribute('method') || '').toLowerCase() !== 'post') return;
1791
+ e.preventDefault();
1792
+ postForm(new FormData(f));
1793
+ });
1794
+ // Dev seam: the live signal graph, readable as JSON. Three callers, one
1795
+ // implementation: the dev server's reload bridge snapshots it before a
1796
+ // rebuild-triggered reload so the edit lands on the state the developer had,
1797
+ // and the devtools extension (devtools/) reads it the same way - the signal
1798
+ // graph plus the prefetch counters, which is the whole observable state of a
1799
+ // running page. Both are DIRECT references (no wrapper arrow): the names take
1800
+ // no arguments, so the call is identical and every document that carries the
1801
+ // bundle pays eleven bytes for the pair instead of forty.
1802
+ window.__rosefc = { state: serializeState, prefetch: prefetchStats };
1803
+ // initial=true: DOM is SSR output, resume state + wire markers (zero hydration).
1804
+ // If the document was rendered for a DIFFERENT route (a static-file server's
1805
+ // SPA fallback serves index.html for unknown paths), adopt nothing - let the
1806
+ // client router render the requested route from scratch.
1807
+ const __st = document.getElementById('__rosefc_state');
1808
+ let __state = __st ? JSON.parse(__st.textContent || '{}') : {};
1809
+ // The dev server's reload bridge hands the pre-reload signal graph back inside
1810
+ // the next document (window.__rosefc_resume). The resumed values win over the
1811
+ // fresh render's, but the ROUTE stays the one the server just rendered - and
1812
+ // the route renders client-side from the bundle rather than adopting the SSR
1813
+ // DOM, because a resumed list can be longer than the document's rows and
1814
+ // adoption could not add them. Absent in every non-dev document.
1815
+ const __resumed = window.__rosefc_resume ? JSON.parse(window.__rosefc_resume) : null;
1816
+ if (__resumed) {
1817
+ const __route = __state.__route;
1818
+ __state = Object.assign(__state, __resumed);
1819
+ __state.__route = __route;
1820
+ }
1821
+ // A NOT-FOUND document (the server stamps __notFound onto its state) boots
1822
+ // into the app's own 404 route: the URL matches no route - or a catch-all
1823
+ // whose resolver threw notFound(), whose key sits null in the resumed state
1824
+ // and whose template would dereference it into a 500. startNotFound paints
1825
+ // the not-found route from the resumed state instead (zero requests).
1826
+ if (__state.__notFound) {
1827
+ startNotFound(__app, window.location.pathname);
1828
+ } else if (__resumed) {
1829
+ start(__app, window.location.pathname);
1830
+ } else if (__state.__route === window.location.pathname) {
1831
+ // Lazy hydration (opt-in via export const lazyHydration = true in the root
1832
+ // layout): defer the initial wire() until the browser is idle so the SSR
1833
+ // paint is interactive-to-paint without blocking on the event wiring. Falls
1834
+ // back to eager wiring where requestIdleCallback is unavailable.
1835
+ if (window.__rosefcLazy && typeof requestIdleCallback === 'function') {
1836
+ requestIdleCallback(() => start(__app, window.location.pathname, true));
1837
+ } else {
1838
+ start(__app, window.location.pathname, true);
1839
+ }
1840
+ } else {
1841
+ start(__app, window.location.pathname);
1842
+ }
1843
+ `,Ft=null;function Bs(){if(Ft===null)if(globalThis.__ROSEFC_SKIP_MINIFY)Ft=Rn;else try{Ft=Is.transformSync(Rn,{minify:!0}).code}catch{Ft=Rn}return Ft}var tn=null;function Uo(){let e=Ds();return(tn===null||tn.v!==e)&&(tn={v:e,s:`
1844
+ import { start, startNotFound, prefetch, postForm, prefetchStats, serializeState } from '${qs()}';
1845
+ ${Bs()}`}),tn.s}var nn=null;function Vo(e){if(nn!==null&&nn.for===e)return nn.out;let s=/\bexport\s*\{([^}]*)\}\s*;?\s*$/.exec(e),t=e,n="";s&&(t=e.slice(0,s.index)+e.slice(s.index+s[0].length),n=s[1].split(",").map(i=>{let o=i.split(" as ").map(c=>c.trim());return o.length===1||o[0]===o[1]?"":o[0]&&o[1]?`var ${o[1]} = ${o[0]};`:""}).join(""));let r=`
1846
+ ${t}
1847
+ ${n}
1848
+ ${Bs()}`;return nn={for:e,out:r},r}var Go=`<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>\u{1F339}</text></svg>">`,Zo=`
1849
+ body { font-family: system-ui, sans-serif; margin: 0; padding: 2rem; }
1850
+ button { padding: 0.5rem 1rem; font-size: 1rem; margin-right: 0.5rem; }
1851
+ a { color: #e91e63; text-decoration: none; font-weight: bold; }
1852
+ a:hover { text-decoration: underline; }
1853
+ nav a { margin-right: 1rem; }
1854
+ .rh { border-bottom: 2px solid #e91e63; margin-bottom: 1.5rem; padding-bottom: 0.75rem; }
1855
+ .rb { font-size: 1.25rem; }
1856
+ .rn { display: inline-block; margin-left: 1.5rem; }
1857
+ .rf { margin-top: 2rem; color: #888; font-size: 0.85rem; }
1858
+ ::view-transition-old(root), ::view-transition-new(root) { animation-duration: .18s; }
1859
+ `;var Xo=Zo.replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^"']+/g,e=>e[0]==='"'||e[0]==="'"?e:e.replace(/\s+/g," ").replace(/\s*([:;{},])\s*/g,"$1").trim()).trim();function Qo(e){let s=new Map,t=[],n=new Map,r=(i,o)=>{s.has(i)||(s.set(i,o),t.push(i))};for(let i of e){for(let o of i.matchAll(/<title[^>]*>[\s\S]*?<\/title>/gi))r("title",o[0]);for(let o of i.matchAll(/<(\w+)((?:\s+[\w:-]+(?:=(?:"[^"]*"|'[^']*'|[^\s"'>]+))?)*)\s*(?:\/>|>([\s\S]*?)<\/\1\s*>|>)/gi)){let c=o[1].toLowerCase();if(c==="title")continue;let a=o[2],u=m=>{let v=a.match(new RegExp(`\\s${m}=(?:"([^"]*)"|'([^']*)')`,"i"));return v?v[1]??v[2]:null},g=a.match(/\sid=(?:"([^"]*)"|'([^']*)')/i),l=u("name"),f=u("property"),h=u("rel"),p=u("charset"),w;l!==null?w=`${c}:${l}`:f!==null?w=`${c}:${f}`:h!==null?w=`${c}:${h}${Ko(h,u)}`:p!==null?w=`${c}:${p}`:g?w=`${c}:${g[1]??g[2]}`:(w=`${c}:#${n.get(c)??0}`,n.set(c,(n.get(c)??0)+1)),w=w.replace(/"/g,"");let b=o[0].replace(/^<\w+/,m=>`${m} data-rosefc-head="${w}"`);r(w,b)}}return t.map(i=>s.get(i)).join(`
1860
+ `)}function Ko(e,s){return/(^|\s)canonical(\s|$)/i.test(e)?"":`@${s("href")??s("type")??s("as")??""}`}function Yo(e,s=""){let t=s?` nonce="${s}"`:"";if(e)return`<script type="module"${t}>${Vo(e)}</script>`;let n=qs();return`${`<link rel="modulepreload" href="${n}" crossorigin>`}
1861
+ <script type="module"${t} src="${n}" fetchpriority="high"></script>
1862
+ <script type="module"${t}>${Uo()}</script>`}function Hs(e,s,t,n=[],r=zo(),i=!0,o="en",c="",a="",u=!0){let g=Qo(n),l=a?g.replace(/<script\b([^>]*)>/gi,(R,U)=>/\bnonce=/.test(U)?R:`<script${U} nonce="${a}">`):g,f=` lang="${o}"${c?` dir="${c}"`:""}`,h="",p=l.replace(/<(html|body)\b([^>]*)>/gi,(R,U,L)=>{let q=L.replace(/\s*data-rosefc-head="[^"]*"/,"");return U==="html"?f=q:h=q,""}),w=/<title>/i.test(g)?"":"<title>Rosefc</title>",b=/rel=["']?icon/i.test(g)?"":`
1863
+ ${Go}`,m=p?`
1864
+ ${p}`:"",v=r?`
1865
+ <style>${r}</style>`:"",k=s.replace(/</g,"\\u003c"),T=i?`
1866
+ <script type="application/json" id="__rosefc_state">${k}</script>
1867
+ ${Yo(t,a)}`:"",x=i&&u?'<div id="app">':"",E=i&&u?"</div>":"",N=i&&u?`
1868
+ <style>${Xo}</style>`:"";return`<!DOCTYPE html>
1869
+ <html${f}>
1870
+ <head>
1871
+ <meta charset="UTF-8">
1872
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">${m}${b}
1873
+ ${w}${N}${v}
1874
+ </head>
1875
+ <body${h}>
1876
+ ${x}${e}${E}${T}
1877
+ </body>
1878
+ </html>`}var ei=["document","Node","NodeFilter","FormData","DOMParser","location","fetch","Event","CustomEvent","MutationObserver","requestAnimationFrame"];function ti(e){let s=re.dirname(re.resolve(e));for(;;){if(ue.existsSync(re.join(s,"src","pages")))return s;let t=re.dirname(s);if(t===s)throw new Error(`rosefc/test: ${e} is not inside a project (no src/pages found above it)`);s=t}}function ni(e,s){let t=re.relative(re.join(s,"src","pages"),re.resolve(e)).replace(/\\/g,"/").replace(/\.rose$/,"");return t==="index"?"/":"/"+t.split("/").map(r=>r.startsWith("[")&&r.endsWith("]")?`:${r.slice(1,-1)}`:r).join("/")}function zs(e,s){ue.mkdirSync(s,{recursive:!0});for(let t of ue.readdirSync(e,{withFileTypes:!0})){let n=re.join(e,t.name),r=re.join(s,t.name);t.isDirectory()?zs(n,r):ue.copyFileSync(n,r)}}function si(e){return Object.entries(e).map(([s,t])=>`${s}={${JSON.stringify(t)??"undefined"}}`).join(" ")}async function ri(e,s={}){let t=re.resolve(e);if(!ue.existsSync(t))throw new Error(`rosefc/test: no such file: ${t}`);let n=ti(t),r=re.relative(n,t).replace(/\\/g,"/"),i=r.startsWith("src/components/"),o=s.dir??ue.mkdtempSync(re.join(Ws.tmpdir(),"rosefc-test-"));for(let x of["src","public"]){let E=re.join(n,x);ue.existsSync(E)&&zs(E,re.join(o,x))}for(let x of["rosefc.config.js"]){let E=re.join(n,x);ue.existsSync(E)&&ue.copyFileSync(E,re.join(o,x))}let c;if(i){let x=re.relative(re.join(o,"src","pages"),re.join(o,r)).replace(/\\/g,"/"),E=si(s.props??{}),N=`<script>
1879
+ import Target from '${x}';
1880
+ </script>
1881
+
1882
+ <template>
1883
+ <Target ${E} />
1884
+ </template>
1885
+ `;ue.writeFileSync(re.join(o,"src","pages","__rosefc_test.rose"),N),c="/__rosefc_test"}else c=s.route??ni(t,n);let a=re.join(o,"dist");await Ls(o,a);let u=x=>{let E=x.replace(/\.js$/,".import.mjs");return ue.copyFileSync(x,E),E},g=u(re.join(a,"server.js")),l=u(re.join(a,"client.js")),f=await import(Js(g).href),h=ue.readFileSync(re.join(a,"client.js"),"utf-8"),p="";try{p=ue.readFileSync(re.join(a,"styles.css"),"utf-8")}catch{}s.keep&&console.log(`rosefc/test: built ${t} -> ${a}`),!s.dir&&!s.keep&&process.once("exit",()=>{try{ue.rmSync(o,{recursive:!0,force:!0})}catch{}});let w=(x,E)=>({status:x.status??200,html:x.html,state:x.state?JSON.parse(x.state):{},head:x.head??[],csr:x.csr,shell:x.shell,lang:x.lang??"en",dir:x.dir??"",document:Hs(x.html,x.state,h,x.head??[],p,x.csr!==!1,x.lang??"en",x.dir??"","",x.shell!==!1),redirect:E}),b=(x,E={},N)=>{let R=new Headers(E.headers??{});for(let[q,X]of Object.entries(E.cookies??{}))R.append("cookie",`${q}=${X}`);let U=E.method??"GET",L=U!=="GET"&&U!=="HEAD";return new Request(`http://localhost${x}`,{method:U,headers:R,body:L?N??void 0:void 0})},m=async(x,E,N)=>{let R=x.indexOf("?"),U=R>=0?Object.fromEntries(new URLSearchParams(x.slice(R+1))):null,L=R>=0?x.slice(0,R):x;R>=0?f.setQuery?.(U):f.setQuery?.({});let q="location"in globalThis,X=globalThis.location,Y=!1;if(q)try{globalThis.location=void 0,Y=!0}catch{}try{if(f.middleware){let O=await f.runMiddleware(b(x,E,N),N);if(O)return{status:O.status,html:await O.text(),state:{},head:[],lang:"en",dir:"",document:await O.text(),redirect:O.headers.get("location")??void 0}}let pe=await f.renderPage(L,N);return w(pe)}finally{Y&&(globalThis.location=X)}},v=0,k=c;return{route:c,dir:o,get:async(x=c,E)=>m(x,E??{}),post:async(x,E={})=>{let N=E.route??c,R=new FormData;for(let[U,L]of Object.entries(x??{}))R.append(U,String(L));return m(N,E,R)},api:async(x,E,N={})=>{if(f.middleware){let Y=await f.runMiddleware(b(E,N));if(Y)return{status:Y.status,body:await Y.text(),headers:{location:Y.headers.get("location")??""}}}let R=await f.handleApi(x,E,b(E,N)),U=await R.text(),L=U;try{L=JSON.parse(U)}catch{}let q={},X=R.headers.getSetCookie?.()??[];return R.headers.forEach((Y,pe)=>{X.length&&pe.toLowerCase()==="set-cookie"||(q[pe]=Y)}),X.length&&(q["set-cookie"]=X),{status:R.status,body:L,headers:q}},mount:async(x={})=>{let E=s.dom?.window??s.dom??globalThis;if(!E?.document||!E?.DOMParser)throw new Error('rosefc/test: mount() needs a DOM. Pass one - test("src/components/Counter.rose", { dom: new JSDOM() }) - or run under a jsdom environment.');let N=await m(c,x),R=E.document,U=R.getElementById("app")??R.body,L=R.getElementById("__rosefc_state");L||(L=R.createElement("script"),L.id="__rosefc_state",R.body.appendChild(L)),L.textContent=typeof N.state=="string"?N.state:JSON.stringify(N.state),U.innerHTML=N.html;let q=A=>{let V=A.indexOf("?");return{pathname:V>=0?A.slice(0,V):A,search:V>=0?A.slice(V):"",href:`http://localhost${A}`}},X=new Map;for(let A of ei)X.set(A,globalThis[A]),globalThis[A]=E[A]??globalThis[A];globalThis.location=q(k),globalThis.fetch=async(A,V)=>{let Q=String(A),ie=Q.startsWith("http")?new URL(Q):null,ge=ie?ie.pathname+ie.search:Q,ke=ge.indexOf("?"),Ae=ke>=0?ge.slice(0,ke):ge;if(Ae.startsWith("/locales/")&&Ae.endsWith(".json")){let C=re.join(a,Ae.slice(1));return ue.existsSync(C)?{ok:!0,json:async()=>JSON.parse(ue.readFileSync(C,"utf-8"))}:{ok:!1,json:async()=>({})}}v++;let ce=await m(ge,x,V?.body);return{ok:ce.status<400,status:ce.status,text:async()=>ce.document}};let Y=await import(Js(l).href);await Y.start(U,q(c).pathname,!0);let pe=A=>A?R.querySelector(A):U,O={route:c,document:R,window:E,text:A=>pe(A)?.textContent??"",html:A=>pe(A)?.outerHTML??null,exists:A=>!!R.querySelector(A),click:async A=>{let V=R.querySelector(A);if(!V)throw new Error(`rosefc/test: no element matches ${A}`);V.dispatchEvent(new E.MouseEvent("click",{bubbles:!0,cancelable:!0})),await new Promise(Q=>setTimeout(Q,0))},fill:(A,V)=>{let Q=R.querySelector(A);if(!Q)throw new Error(`rosefc/test: no element matches ${A}`);Q.value=V,Q.dispatchEvent(new E.Event("input",{bubbles:!0}))},key:(A,V,Q="keydown")=>{let ie=R.querySelector(A);if(!ie)throw new Error(`rosefc/test: no element matches ${A}`);ie.dispatchEvent(new E.KeyboardEvent(Q,{key:V,bubbles:!0,cancelable:!0}))},submit:async(A="form",V)=>{let Q=R.querySelector(A);if(!Q)throw new Error(`rosefc/test: no form matches ${A}`);let ie=new E.FormData(Q);for(let[ge,ke]of Object.entries(V??{}))ie.append(ge,String(ke));await Y.postForm(ie)},action:async(A,V)=>{let Q=new E.FormData;Q.append("__action",A);for(let[ie,ge]of Object.entries(V??{}))Q.append(ie,String(ge));await Y.postForm(Q)},navigate:async A=>{k=A,globalThis.location=q(A),await Y.start(U,q(A).pathname,!1)},state:()=>{let A=R.getElementById("__rosefc_state");return A?.textContent?JSON.parse(A.textContent):{}},requestCount:()=>v};return O.restore=()=>{for(let[A,V]of X)globalThis[A]=V},O}}}var Ii=ri;export{Ii as default,ri as test};