rosefc 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/deploy/Dockerfile.node +25 -0
- package/deploy/Dockerfile.static +34 -0
- package/deploy/api/rosefd.ts +19 -0
- package/deploy/cloudflare/functions/[[path]].ts +59 -0
- package/deploy/cloudflare/wrangler.toml +14 -0
- package/deploy/docker-compose.yml +45 -0
- package/deploy/fly.toml +28 -0
- package/deploy/k8s/rosefd.yaml +128 -0
- package/deploy/native/RosefdApp.xcscheme +87 -0
- package/deploy/native/android.yml +62 -0
- package/deploy/native/flutter.yml +96 -0
- package/deploy/native/ios.yml +67 -0
- package/deploy/netlify/functions/rosefd.ts +36 -0
- package/deploy/netlify.toml +17 -0
- package/deploy/server.cjs +4 -0
- package/deploy/vercel.json +13 -0
- package/dist-cli/compiler.mjs +1693 -0
- package/dist-cli/edge.mjs +199 -0
- package/dist-cli/export.mjs +12287 -0
- package/dist-cli/rosefd.mjs +12783 -0
- package/dist-cli/runtime.mjs +6 -0
- package/dist-cli/test.mjs +1885 -0
- package/package.json +110 -4
- package/src/FRAMEWORK_VERSION +1 -0
- package/src/cli/content.ts +188 -0
- package/src/cli/edge.ts +298 -0
- package/src/cli/hot-vary.ts +27 -0
- package/src/cli/origin.ts +10 -0
- package/src/cli/prod-server.ts +817 -0
- package/src/cli/shell.ts +610 -0
- package/src/cli/shutdown.ts +56 -0
- package/src/cli/validator.ts +53 -0
- package/src/hash.ts +9 -0
- package/src/runtime/db.ts +166 -0
- package/src/runtime/index.ts +2992 -0
- package/src/runtime/lorawan.ts +149 -0
- package/src/types/rosefd.d.ts +327 -0
- package/README.md +0 -3
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import{pathToFileURL as Te}from"url";import{join as B}from"path";import*as _ from"fs";import*as $ from"path";import*as se from"esbuild";import{createHash as X}from"crypto";function K(e){let n=2166136261,t=typeof e=="string"?new TextEncoder().encode(e):e;for(let s=0;s<t.length;s++)n^=t[s],n=Math.imul(n,16777619);return(n>>>0).toString(36)}var q=$.join(process.cwd(),"dist"),C=null,Z=new Map,re=!1,P=!1;function oe(e){re=e==="split",P=e==="sliced"}var ee="",te="";function ne(){let e=_e;return ee!==""&&(e=e.replace("connect-src 'self'",`connect-src 'self' ${ee}`)),te!==""&&(e=e.replace("img-src 'self' data: https://fastly.picsum.photos",`img-src 'self' data: https://fastly.picsum.photos ${te}`)),e}function J(e,n=q){if(re)return null;let t=P&&e?$.join(n,"slices",`${e}.js`):$.join(n,"client.js");try{let s=_.statSync(t);if(P&&e){let r=Z.get(e+"\0"+n);if(r&&r.mtimeMs===s.mtimeMs)return r.source;let l=_.readFileSync(t,"utf-8");return Z.set(e+"\0"+n,{mtimeMs:s.mtimeMs,source:l}),l}return(!C||C.for!==n||C.mtimeMs!==s.mtimeMs)&&(C={for:n,mtimeMs:s.mtimeMs,source:_.readFileSync(t,"utf-8")}),C.source}catch{return P&&e?J(null,n):null}}var N=null;function D(){try{let e=$.join(q,"client.js"),n=_.statSync(e);return(!N||N.mtimeMs!==n.mtimeMs)&&(N={mtimeMs:n.mtimeMs,v:K(_.readFileSync(e))}),N.v}catch{return""}}function ie(){let e=D();return e?`/client.js?v=${e}`:"/client.js"}var j=null;function ae(){let e=$.join(q,"styles.css");try{let n=_.statSync(e);return(!j||j.mtimeMs!==n.mtimeMs)&&(j={mtimeMs:n.mtimeMs,source:_.readFileSync(e,"utf-8")}),j.source}catch{return""}}var V=`
|
|
2
|
+
// shell = false: the document's SSR content sits directly in <body> - no
|
|
3
|
+
// #app wrapper, no demo styles, so a real theme's CSS owns the document from
|
|
4
|
+
// the first byte (and a JS-less visitor never sees either). The bundle still
|
|
5
|
+
// runs, and it still needs its container: wrap the content once, here, before
|
|
6
|
+
// any theme script executes (module scripts run before DOMContentLoaded). The
|
|
7
|
+
// wrapper is a plain unstyled div, so the re-parent is visually inert; every
|
|
8
|
+
// later path - adoption, navigation, forms - is then the ordinary one.
|
|
9
|
+
let __app = document.getElementById('app');
|
|
10
|
+
if (!__app) {
|
|
11
|
+
__app = document.createElement('div');
|
|
12
|
+
__app.id = 'app';
|
|
13
|
+
// scripts stay outside the wrapper, exactly where the dressed document
|
|
14
|
+
// keeps them: the state element and the running module must survive a
|
|
15
|
+
// navigation's innerHTML swap (they are the document's, not the route's).
|
|
16
|
+
for (const node of Array.from(document.body.children)) {
|
|
17
|
+
if (node.tagName !== 'SCRIPT') __app.appendChild(node);
|
|
18
|
+
}
|
|
19
|
+
document.body.appendChild(__app);
|
|
20
|
+
}
|
|
21
|
+
// Native View Transitions around client-side navigation (progressive:
|
|
22
|
+
// browsers without the API navigate normally, no polyfill, no CSS required).
|
|
23
|
+
// F35: stash the CURRENT entry's scroll position into its history state
|
|
24
|
+
// before a new push - the browser only restores scroll on full page loads; a
|
|
25
|
+
// pjax swap would land wherever the swap left it.
|
|
26
|
+
function __saveScroll() {
|
|
27
|
+
try {
|
|
28
|
+
const s = history.state || {};
|
|
29
|
+
history.replaceState(Object.assign({}, s, { __rosefdScroll: window.scrollY }), '');
|
|
30
|
+
} catch (e) { /* history state unavailable (file:// edge): best effort */ }
|
|
31
|
+
}
|
|
32
|
+
function __navigate(pathname, restore) {
|
|
33
|
+
const paint = () => {
|
|
34
|
+
const p = start(__app, pathname);
|
|
35
|
+
if (restore) {
|
|
36
|
+
// back/forward: restore the entry's scroll (top when it has none)
|
|
37
|
+
const s = history.state || {};
|
|
38
|
+
const y = typeof s.__rosefdScroll === 'number' ? s.__rosefdScroll : 0;
|
|
39
|
+
return Promise.resolve(p).then(() => { window.scrollTo(0, y); }, () => { window.scrollTo(0, y); });
|
|
40
|
+
}
|
|
41
|
+
// a fresh navigation starts at the top, like a full page load
|
|
42
|
+
window.scrollTo(0, 0);
|
|
43
|
+
return p;
|
|
44
|
+
};
|
|
45
|
+
if (document.startViewTransition) {
|
|
46
|
+
return document.startViewTransition(paint).updateCallbackDone;
|
|
47
|
+
}
|
|
48
|
+
return paint();
|
|
49
|
+
}
|
|
50
|
+
window.addEventListener('popstate', () => __navigate(window.location.pathname, true));
|
|
51
|
+
document.addEventListener('click', (e) => {
|
|
52
|
+
const a = e.target.tagName === 'A' ? e.target : e.target.closest && e.target.closest('a');
|
|
53
|
+
if (a && a.getAttribute('href') && a.getAttribute('href').startsWith('/')) {
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
__saveScroll();
|
|
56
|
+
history.pushState(null, '', a.getAttribute('href'));
|
|
57
|
+
__navigate(window.location.pathname);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
// Prefetch the target route's full render (including $data) on hover, keyboard
|
|
61
|
+
// focus, or touch - the click that follows paints from cache: no await, no
|
|
62
|
+
// request. Other frameworks prefetch data only; Rosefd prefetches the render
|
|
63
|
+
// because the inlined bundle already contains every route.
|
|
64
|
+
function __prefetchHandler(e) {
|
|
65
|
+
const a = e.target.closest && e.target.closest('a[href^="/"]');
|
|
66
|
+
if (a && prefetch) prefetch(a.getAttribute('href'), 'hover');
|
|
67
|
+
}
|
|
68
|
+
document.addEventListener('mouseover', __prefetchHandler);
|
|
69
|
+
document.addEventListener('focusin', __prefetchHandler);
|
|
70
|
+
document.addEventListener('touchstart', __prefetchHandler, { passive: true });
|
|
71
|
+
// Viewport + idle prefetch (viewport-triggered): once a link scrolls into view and the
|
|
72
|
+
// browser is idle, its route renders ahead of any interaction. trade-off: both
|
|
73
|
+
// APIs are feature-detected; without them the hover/focus/touch path above
|
|
74
|
+
// still covers every link.
|
|
75
|
+
if (prefetch && 'IntersectionObserver' in window && 'requestIdleCallback' in window) {
|
|
76
|
+
const io = new IntersectionObserver((entries) => {
|
|
77
|
+
for (const e of entries) {
|
|
78
|
+
if (!e.isIntersecting) continue;
|
|
79
|
+
io.unobserve(e.target); // one-shot per element; fresh links re-observe after nav
|
|
80
|
+
requestIdleCallback(() => prefetch(e.target.getAttribute('href'), 'viewport'));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
// observing an already-observed element is a no-op, so re-sweeping is cheap
|
|
84
|
+
const observeLinks = () => {
|
|
85
|
+
for (const a of document.querySelectorAll('a[href^="/"]')) io.observe(a);
|
|
86
|
+
};
|
|
87
|
+
observeLinks();
|
|
88
|
+
// navigation swaps the container's innerHTML: re-observe the fresh links
|
|
89
|
+
const __rawNav = __navigate;
|
|
90
|
+
__navigate = (p) => __rawNav(p).then(observeLinks, () => {});
|
|
91
|
+
}
|
|
92
|
+
// Progressive-enhancement forms: <form method="POST"> backed by a server
|
|
93
|
+
// action. With JS the submit is intercepted and handed to postForm (one
|
|
94
|
+
// request, in-place adopt). Without JS the browser performs the native POST
|
|
95
|
+
// and the server re-renders the page: the same form works with JavaScript
|
|
96
|
+
// disabled, which Server Actions in other frameworks do not.
|
|
97
|
+
document.addEventListener('submit', (e) => {
|
|
98
|
+
const f = e.target;
|
|
99
|
+
if (!f || f.tagName !== 'FORM' || f.hasAttribute('data-on-submit')) return;
|
|
100
|
+
if ((f.getAttribute('method') || '').toLowerCase() !== 'post') return;
|
|
101
|
+
e.preventDefault();
|
|
102
|
+
postForm(new FormData(f));
|
|
103
|
+
});
|
|
104
|
+
// Dev seam: the live signal graph, readable as JSON. Three callers, one
|
|
105
|
+
// implementation: the dev server's reload bridge snapshots it before a
|
|
106
|
+
// rebuild-triggered reload so the edit lands on the state the developer had,
|
|
107
|
+
// and the devtools extension (devtools/) reads it the same way - the signal
|
|
108
|
+
// graph plus the prefetch counters, which is the whole observable state of a
|
|
109
|
+
// running page. Both are DIRECT references (no wrapper arrow): the names take
|
|
110
|
+
// no arguments, so the call is identical and every document that carries the
|
|
111
|
+
// bundle pays eleven bytes for the pair instead of forty.
|
|
112
|
+
window.__rosefd = { state: serializeState, prefetch: prefetchStats };
|
|
113
|
+
// initial=true: DOM is SSR output, resume state + wire markers (zero hydration).
|
|
114
|
+
// If the document was rendered for a DIFFERENT route (a static-file server's
|
|
115
|
+
// SPA fallback serves index.html for unknown paths), adopt nothing - let the
|
|
116
|
+
// client router render the requested route from scratch.
|
|
117
|
+
const __st = document.getElementById('__rosefd_state');
|
|
118
|
+
let __state = __st ? JSON.parse(__st.textContent || '{}') : {};
|
|
119
|
+
// The dev server's reload bridge hands the pre-reload signal graph back inside
|
|
120
|
+
// the next document (window.__rosefd_resume). The resumed values win over the
|
|
121
|
+
// fresh render's, but the ROUTE stays the one the server just rendered - and
|
|
122
|
+
// the route renders client-side from the bundle rather than adopting the SSR
|
|
123
|
+
// DOM, because a resumed list can be longer than the document's rows and
|
|
124
|
+
// adoption could not add them. Absent in every non-dev document.
|
|
125
|
+
const __resumed = window.__rosefd_resume ? JSON.parse(window.__rosefd_resume) : null;
|
|
126
|
+
if (__resumed) {
|
|
127
|
+
const __route = __state.__route;
|
|
128
|
+
__state = Object.assign(__state, __resumed);
|
|
129
|
+
__state.__route = __route;
|
|
130
|
+
}
|
|
131
|
+
// A NOT-FOUND document (the server stamps __notFound onto its state) boots
|
|
132
|
+
// into the app's own 404 route: the URL matches no route - or a catch-all
|
|
133
|
+
// whose resolver threw notFound(), whose key sits null in the resumed state
|
|
134
|
+
// and whose template would dereference it into a 500. startNotFound paints
|
|
135
|
+
// the not-found route from the resumed state instead (zero requests).
|
|
136
|
+
if (__state.__notFound) {
|
|
137
|
+
startNotFound(__app, window.location.pathname);
|
|
138
|
+
} else if (__resumed) {
|
|
139
|
+
start(__app, window.location.pathname);
|
|
140
|
+
} else if (__state.__route === window.location.pathname) {
|
|
141
|
+
// Lazy hydration (opt-in via export const lazyHydration = true in the root
|
|
142
|
+
// layout): defer the initial wire() until the browser is idle so the SSR
|
|
143
|
+
// paint is interactive-to-paint without blocking on the event wiring. Falls
|
|
144
|
+
// back to eager wiring where requestIdleCallback is unavailable.
|
|
145
|
+
if (window.__rosefdLazy && typeof requestIdleCallback === 'function') {
|
|
146
|
+
requestIdleCallback(() => start(__app, window.location.pathname, true));
|
|
147
|
+
} else {
|
|
148
|
+
start(__app, window.location.pathname, true);
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
start(__app, window.location.pathname);
|
|
152
|
+
}
|
|
153
|
+
`,H=null;function le(){if(H===null)if(globalThis.__ROSEFD_SKIP_MINIFY)H=V;else try{H=se.transformSync(V,{minify:!0}).code}catch{H=V}return H}var _e="style-src 'unsafe-inline'; img-src 'self' data: https://fastly.picsum.photos; font-src 'self' data:; connect-src 'self'; form-action 'self'; base-uri 'none'; frame-ancestors 'none'; object-src 'none'",Se={"x-content-type-options":"nosniff","x-frame-options":"DENY","referrer-policy":"strict-origin-when-cross-origin","permissions-policy":"accelerometer=(), autoplay=(), camera=(), display-capture=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), usb=(), xr-spatial-tracking=()"},O=null,I=null;function ce(){let e=D();return(I===null||I.v!==e)&&(I={v:e,s:`
|
|
154
|
+
import { start, startNotFound, prefetch, postForm, prefetchStats, serializeState } from '${ie()}';
|
|
155
|
+
${le()}`}),I.s}var U=null;function ue(e){if(U!==null&&U.for===e)return U.out;let n=/\bexport\s*\{([^}]*)\}\s*;?\s*$/.exec(e),t=e,s="";n&&(t=e.slice(0,n.index)+e.slice(n.index+n[0].length),s=n[1].split(",").map(l=>{let u=l.split(" as ").map(d=>d.trim());return u.length===1||u[0]===u[1]?"":u[0]&&u[1]?`var ${u[1]} = ${u[0]};`:""}).join(""));let r=`
|
|
156
|
+
${t}
|
|
157
|
+
${s}
|
|
158
|
+
${le()}`;return U={for:e,out:r},r}function z(){let e=new Uint8Array(16);crypto.getRandomValues(e);let n="";for(let t of e)n+=String.fromCharCode(t);return btoa(n)}function de(e,n=""){let t={...Se};if(n)return t["Content-Security-Policy"]=`script-src 'nonce-${n}' 'strict-dynamic'; ${ne()}`,t;if(!O||O.for!==e||O.v!==(e?"":D())){let s=e?`'sha256-${X("sha256").update(ue(e),"utf-8").digest("base64")}'${P?" 'self'":""}`:`'self' 'sha256-${X("sha256").update(ce(),"utf-8").digest("base64")}'`;O={for:e,v:e?"":D(),value:`script-src ${s}; ${ne()}`}}return t["Content-Security-Policy"]=O.value,t}var he=`<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>">`,Re=`
|
|
159
|
+
body { font-family: system-ui, sans-serif; margin: 0; padding: 2rem; }
|
|
160
|
+
button { padding: 0.5rem 1rem; font-size: 1rem; margin-right: 0.5rem; }
|
|
161
|
+
a { color: #e91e63; text-decoration: none; font-weight: bold; }
|
|
162
|
+
a:hover { text-decoration: underline; }
|
|
163
|
+
nav a { margin-right: 1rem; }
|
|
164
|
+
.rh { border-bottom: 2px solid #e91e63; margin-bottom: 1.5rem; padding-bottom: 0.75rem; }
|
|
165
|
+
.rb { font-size: 1.25rem; }
|
|
166
|
+
.rn { display: inline-block; margin-left: 1.5rem; }
|
|
167
|
+
.rf { margin-top: 2rem; color: #888; font-size: 0.85rem; }
|
|
168
|
+
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .18s; }
|
|
169
|
+
`;var pe=Re.replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^"']+/g,e=>e[0]==='"'||e[0]==="'"?e:e.replace(/\s+/g," ").replace(/\s*([:;{},])\s*/g,"$1").trim()).trim();function ke(e){let n=new Map,t=[],s=new Map,r=(l,u)=>{n.has(l)||(n.set(l,u),t.push(l))};for(let l of e){for(let u of l.matchAll(/<title[^>]*>[\s\S]*?<\/title>/gi))r("title",u[0]);for(let u of l.matchAll(/<(\w+)((?:\s+[\w:-]+(?:=(?:"[^"]*"|'[^']*'|[^\s"'>]+))?)*)\s*(?:\/>|>([\s\S]*?)<\/\1\s*>|>)/gi)){let d=u[1].toLowerCase();if(d==="title")continue;let b=u[2],p=S=>{let R=b.match(new RegExp(`\\s${S}=(?:"([^"]*)"|'([^']*)')`,"i"));return R?R[1]??R[2]:null},i=b.match(/\sid=(?:"([^"]*)"|'([^']*)')/i),m=p("name"),o=p("property"),f=p("rel"),w=p("charset"),c;m!==null?c=`${d}:${m}`:o!==null?c=`${d}:${o}`:f!==null?c=`${d}:${f}${$e(f,p)}`:w!==null?c=`${d}:${w}`:i?c=`${d}:${i[1]??i[2]}`:(c=`${d}:#${s.get(d)??0}`,s.set(d,(s.get(d)??0)+1)),c=c.replace(/"/g,"");let v=u[0].replace(/^<\w+/,S=>`${S} data-rosefd-head="${c}"`);r(c,v)}}return t.map(l=>n.get(l)).join(`
|
|
170
|
+
`)}function $e(e,n){return/(^|\s)canonical(\s|$)/i.test(e)?"":`@${n("href")??n("type")??n("as")??""}`}function Y(e,n=""){let t=n?` nonce="${n}"`:"";if(e)return`<script type="module"${t}>${ue(e)}</script>`;let s=ie();return`${`<link rel="modulepreload" href="${s}" crossorigin>`}
|
|
171
|
+
<script type="module"${t} src="${s}" fetchpriority="high"></script>
|
|
172
|
+
<script type="module"${t}>${ce()}</script>`}function fe(e=ae(),n="en",t="",s=!0){let r=e?`
|
|
173
|
+
<style>${e}</style>`:"",l=s?`
|
|
174
|
+
<style>${pe}</style>`:"",u=s?`
|
|
175
|
+
<div id="app">`:"";return`<!DOCTYPE html>
|
|
176
|
+
<html lang="${n}"${t?` dir="${t}"`:""}>
|
|
177
|
+
<head>
|
|
178
|
+
<meta charset="UTF-8">
|
|
179
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
180
|
+
<title>Rosefd</title>${l}${r}
|
|
181
|
+
${he}
|
|
182
|
+
</head>
|
|
183
|
+
<body>${u}`}function me(e,n,t,s=[],r=ae(),l=!0,u="en",d="",b="",p=!0){let i=ke(s),m=b?i.replace(/<script\b([^>]*)>/gi,(T,a)=>/\bnonce=/.test(a)?T:`<script${a} nonce="${b}">`):i,o=` lang="${u}"${d?` dir="${d}"`:""}`,f="",w=m.replace(/<(html|body)\b([^>]*)>/gi,(T,a,h)=>{let y=h.replace(/\s*data-rosefd-head="[^"]*"/,"");return a==="html"?o=y:f=y,""}),c=/<title>/i.test(i)?"":"<title>Rosefd</title>",v=/rel=["']?icon/i.test(i)?"":`
|
|
184
|
+
${he}`,S=w?`
|
|
185
|
+
${w}`:"",R=r?`
|
|
186
|
+
<style>${r}</style>`:"",A=n.replace(/</g,"\\u003c"),Q=l?`
|
|
187
|
+
<script type="application/json" id="__rosefd_state">${A}</script>
|
|
188
|
+
${Y(t,b)}`:"",g=l&&p?'<div id="app">':"",F=l&&p?"</div>":"",x=l&&p?`
|
|
189
|
+
<style>${pe}</style>`:"";return`<!DOCTYPE html>
|
|
190
|
+
<html${o}>
|
|
191
|
+
<head>
|
|
192
|
+
<meta charset="UTF-8">
|
|
193
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">${S}${v}
|
|
194
|
+
${c}${x}${R}
|
|
195
|
+
</head>
|
|
196
|
+
<body${f}>
|
|
197
|
+
${g}${e}${F}${Q}
|
|
198
|
+
</body>
|
|
199
|
+
</html>`}function ge(e,n,t){let s=String(t("accept-language")??"").trim().toLowerCase(),r=n?.(e)??[];return r.length?[s,...r.map(l=>String(t(l)??"").trim())]:[s]}var M=[],E=null;globalThis.__rosefdOnShutdown=we;globalThis.__rosefdRunShutdownHooks=ye;function we(e,n){let t={name:e,fn:n};return M.push(t),()=>{let s=M.indexOf(t);s!==-1&&M.splice(s,1)}}function ye(e){return E||(E=(async()=>{let n=[];for(let t of M.slice())try{await t.fn(),n.push({name:t.name,ok:!0})}catch(s){let r=s instanceof Error?s.message:String(s);n.push({name:t.name,ok:!1,error:r}),console.error(`[rosefd] shutdown hook ${t.name} failed (${e}):`,r)}return n})().finally(()=>{E=null}),E)}function xe(){return M.length}function Ce(e){let n=e.method;if(n!=="POST"&&n!=="PUT"&&n!=="PATCH"&&n!=="DELETE")return null;let t=e.headers.get("origin");if(t){let r;try{r=new URL(t).host}catch{return new Response("Cross-site request blocked (unparsable Origin header)",{status:403})}return r===new URL(e.url).host?null:new Response("Cross-site request blocked (Origin does not match Host)",{status:403})}let s=e.headers.get("sec-fetch-site");return s&&s!=="same-origin"&&s!=="same-site"&&s!=="none"?new Response(`Cross-site request blocked (sec-fetch-site: ${s})`,{status:403}):null}var be=Promise.resolve(),He=e=>{let n=be,t;return be=new Promise(s=>{t=s}),n.then(e).finally(t)};async function De(e,n){let t=n?.server??await import(Te(B(e,"server.js")).href),s=null,r="";if(n&&"client"in n)s=n.client??null;else try{s=await(await import("fs/promises")).readFile(B(e,"client.js"),"utf-8")}catch{s=null}s&&s.includes("chunks/")&&(s=null);let l=typeof t.sliceKeyFor=="function";l&&oe("sliced");let u=p=>l?J(t.sliceKeyFor(p),e):s;if(n&&"styles"in n)r=n.styles??"";else try{r=await(await import("fs/promises")).readFile(B(e,"styles.css"),"utf-8")}catch{r=""}let d=new Set;if(n&&"broken"in n)d=new Set(n.broken);else try{d=new Set(JSON.parse(await(await import("fs/promises")).readFile(B(e,"broken.json"),"utf-8")))}catch{d=new Set}let b=(p,i="")=>{let m={};for(let[f,w]of Object.entries(de(u(p),i)))m[f.toLowerCase()]=w;m["cache-control"]||(m["cache-control"]="no-cache");let o=t.headersFor?.(p);if(o)for(let[f,w]of Object.entries(o))m[f.toLowerCase()]=w;return m};return async function(i){let m=Ce(i);if(m)return m;let{pathname:o,searchParams:f}=new URL(i.url),w=o.replace(/\/+$/,"")||"/";return w!==o?new Response(null,{status:308,headers:{location:w+new URL(i.url).search}}):He(async()=>{t.setQuery?.(Object.fromEntries(f));let c=t.hasRequestHooks||t.hasResponseHooks?{request:i,url:new URL(i.url),method:i.method,pathname:o,state:{}}:null;if(c){let a=await t.runRequestHooks(c);if(a)return t.runResponseHooks(c,a)}if(t.middleware){let a=await t.runMiddleware(i);if(a)return c?t.runResponseHooks(c,a):a}if(o==="/__rosefd/data"&&i.method==="GET"){let a=f.get("path")||"/";try{if(t.middleware){let k=await t.runMiddleware(new Request(new URL(a,i.url),{method:"GET",headers:i.headers}));if(k){let L=new Headers(k.headers);return L.set("access-control-allow-origin","*"),new Response(await k.arrayBuffer(),{status:k.status,headers:L})}}t.setQuery?.(Object.fromEntries(new URL("http://x"+a).searchParams));let h=await t.renderPage(a,void 0,{withState:!0}),y={};try{y=JSON.parse(h?.state||"{}")}catch{y={}}return new Response(JSON.stringify({path:a,status:h?.status??200,state:y}),{status:200,headers:{"content-type":"application/json; charset=utf-8","access-control-allow-origin":"*","cache-control":"no-store"}})}catch(h){return new Response(JSON.stringify({error:String(h?.message??h).slice(0,200)}),{status:500,headers:{"content-type":"application/json; charset=utf-8","access-control-allow-origin":"*"}})}}if(t.isApi(o)){if(i.method!=="GET"){let h=t.invalidateRenderCache;typeof h=="function"&&h()}let a=await t.handleApi(i.method,o,i);return c?t.runResponseHooks(c,a):a}let v=i.method==="POST"?await i.formData():void 0;if(v){let a=t.invalidateRenderCache;typeof a=="function"&&a()}if(!v&&!d.has(o)&&!t.isBuffered?.(o)&&t.canStream(o)&&!t.isNoJs(o)&&!i.headers.get("x-pjax")){let a=t.cspNonce?.(o)?z():"",h=new Response(null,{status:200,headers:{"content-type":"text/html; charset=utf-8",...b(o,a)}}),y=c?await t.runResponseHooks(c,h):h,k=new TextEncoder,L=new ReadableStream({async start(W){let G=t.docAttrs(o);await t.renderPageStream(o,ve=>W.enqueue(k.encode(ve)),fe(r,G.lang,G.dir,!t.shellOff?.(o)),Y(u(o),a)),W.close()}});return new Response(L,{status:y.status,headers:y.headers})}let S=i.headers.get("cookie")||"",R=f.toString(),A=ge(o,t.hotVaryFor,a=>i.headers.get(a)).join("\0"),g=(!v&&t.isCachedRoute?.(o)?t.peekRenderCache?.(o,S,R,A):null)??(t.renderPageCached&&!v?await t.renderPageCached(o,S,R,A):await t.renderPage(o,v)),F=t.cspNonce?.(o)?z():"";if(g.redirect){let a=g.redirect,h=new URL(a,i.url),y=`<!DOCTYPE html><title>Redirecting</title><p>Redirecting to <a href="${a}">${a}</a>.</p>`;return new Response(y,{status:g.status??302,headers:{"content-type":"text/html; charset=utf-8",location:h.pathname+h.search}})}let x=me(g.html,g.state,u(o),g.head,r,g.csr!==!1,g.lang,g.dir,F,g.shell!==!1);i.headers.get("x-pjax")&&(x=Oe(x));let T=new Response(x,{status:g.status??200,headers:{"content-type":"text/html; charset=utf-8",...b(o,F)}});return c?t.runResponseHooks(c,T):T})}}function Oe(e){let n=e.indexOf('<main id="sk-main"');if(n<0)return e;let t=e.indexOf("</main>",n);if(t<0)return e;let s=e.slice(n,t+7),r=e.match(/<title>([\s\S]*?)<\/title>/i);return(r?r[0]:"")+s}export{De as createEdgeHandler,we as onShutdown,ye as runShutdownHooks,xe as shutdownHookCount};
|