@absolutejs/absolute 0.20.0-beta.169 → 0.20.0-beta.170
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/CHANGELOG.md +80 -0
- package/README.md +232 -0
- package/changelog.json +228 -0
- package/dist/angular/browser.js +7 -8
- package/dist/angular/browser.js.map +6 -5
- package/dist/angular/components/core/streamingSlotRegistrar.js +6 -2
- package/dist/angular/components/core/streamingSlotRegistry.js +7 -3
- package/dist/angular/index.js +555 -156
- package/dist/angular/index.js.map +29 -23
- package/dist/angular/server.js +555 -156
- package/dist/angular/server.js.map +29 -23
- package/dist/build/buildWorker.js +14 -8
- package/dist/build.js +4949 -1941
- package/dist/build.js.map +72 -42
- package/dist/cli/{add-7azr0c83.js → add-6a7pjkn9.js} +11 -7
- package/dist/cli/{analyze-3cyek6v3.js → analyze-606fshwa.js} +1 -1
- package/dist/cli/{build-25rz8v25.js → build-g81xqbb9.js} +1 -1
- package/dist/cli/{compile-4jnfxts9.js → compile-9y1w9zpj.js} +3 -3
- package/dist/cli/config/server.js +10699 -1538
- package/dist/cli/{dev-9tk5hn2e.js → dev-hyeb89hp.js} +5 -1
- package/dist/cli/{doctor-4nv2c2j3.js → doctor-h55y9hj1.js} +1 -1
- package/dist/cli/{generate-v75p2fct.js → generate-20x1pkf7.js} +4 -4
- package/dist/cli/{htmx-427swtdz.js → htmx-6mz2h7k1.js} +2 -2
- package/dist/cli/{index-bhbs6d5z.js → index-32ge2w1f.js} +12 -4
- package/dist/cli/{index-a4ws2jwd.js → index-3wz3mktm.js} +1 -1
- package/dist/cli/{index-b7hjgknf.js → index-9sksd8c8.js} +13 -4
- package/dist/cli/{index-eyzwc7gz.js → index-qbrzvmh9.js} +4 -2
- package/dist/cli/index-qw98g1p6.js +269 -0
- package/dist/cli/{index-434b7j4a.js → index-vtp20gwf.js} +69 -1
- package/dist/cli/{index-h7qhz02e.js → index-wk0pyxrg.js} +3 -0
- package/dist/cli/{index-k3y8cb6c.js → index-z6f43b20.js} +1 -1
- package/dist/cli/index.js +16 -16
- package/dist/cli/{islands-8sgky9gh.js → islands-dc54e5y1.js} +1 -1
- package/dist/cli/{ls-4m4yqwww.js → ls-b6zz24nt.js} +1 -1
- package/dist/cli/{mobile-hcxjr2gf.js → mobile-ajnnvqtv.js} +3 -3
- package/dist/cli/prerender-fqpp0m1j.js +10 -0
- package/dist/cli/{remove-1ycjx85k.js → remove-t8x1mrxg.js} +4 -4
- package/dist/cli/{start-mbaejxhm.js → start-d6p831ny.js} +3 -3
- package/dist/cli/{typecheck-dr068pmh.js → typecheck-stbt0qt5.js} +6 -1
- package/dist/cli/{workspace-1sycp9g1.js → workspace-61hh6jq1.js} +1 -1
- package/dist/client/chunks/index-6b66nzyf.js +381 -0
- package/dist/client/chunks/index-6b66nzyf.js.map +11 -0
- package/dist/client/chunks/{islands-rc28k5sx.js → islands-s2ta5ajb.js} +5 -2
- package/dist/client/chunks/{islands-rc28k5sx.js.map → islands-s2ta5ajb.js.map} +7 -6
- package/dist/client/index.js +160 -3
- package/dist/client/index.js.map +6 -4
- package/dist/client/navigation.js +764 -0
- package/dist/client/navigation.js.map +10 -0
- package/dist/client/prefetch.js +33 -375
- package/dist/client/prefetch.js.map +3 -4
- package/dist/core/streamingSlotRegistrar.js +5 -2
- package/dist/core/streamingSlotRegistrar.js.map +5 -4
- package/dist/core/streamingSlotRegistry.js +5 -2
- package/dist/core/streamingSlotRegistry.js.map +5 -4
- package/dist/dev/client/cspNonce.ts +28 -0
- package/dist/dev/client/handlers/html.ts +4 -3
- package/dist/dev/client/handlers/htmx.ts +3 -2
- package/dist/dev/client/handlers/svelte.ts +15 -90
- package/dist/dev/client/syncDevtools.ts +2 -1
- package/dist/dev/serverBootstrap.js +11 -4
- package/dist/i18n/index.js +543 -0
- package/dist/i18n/index.js.map +15 -0
- package/dist/index.js +6339 -2233
- package/dist/index.js.map +89 -54
- package/dist/islands/index.js +282 -40
- package/dist/islands/index.js.map +14 -10
- package/dist/mobile/browser.js +7 -2
- package/dist/mobile/browser.js.map +5 -4
- package/dist/mobile/index.js +7 -2
- package/dist/mobile/index.js.map +5 -4
- package/dist/mobile/remoteMacAgentEntry.js +1 -1
- package/dist/react/components/browser/index.js +94 -4
- package/dist/react/components/index.js +150 -10
- package/dist/react/components/index.js.map +15 -10
- package/dist/react/hooks/index.js +479 -13
- package/dist/react/hooks/index.js.map +12 -4
- package/dist/react/index.js +769 -166
- package/dist/react/index.js.map +32 -21
- package/dist/react/router/browser.js +21 -4
- package/dist/react/router/browser.js.map +5 -4
- package/dist/react/router/index.js +21 -4
- package/dist/react/router/index.js.map +5 -4
- package/dist/react/server.js +597 -203
- package/dist/react/server.js.map +25 -15
- package/dist/src/angular/zoneRuntime.d.ts +5 -0
- package/dist/src/build/buildReactServerComponents.d.ts +22 -0
- package/dist/src/build/downlevelAsyncForZone.d.ts +1 -0
- package/dist/src/build/fileRoutes.d.ts +65 -0
- package/dist/src/build/fonts/buildFonts.d.ts +25 -0
- package/dist/src/build/fonts/fallbackMetrics.d.ts +13 -0
- package/dist/src/build/fonts/googleFonts.d.ts +18 -0
- package/dist/src/build/fonts/injectFontTags.d.ts +7 -0
- package/dist/src/build/fonts/parseFontMetrics.d.ts +4 -0
- package/dist/src/build/generateReactIndexes.d.ts +7 -1
- package/dist/src/build/htmlIncludes.d.ts +16 -0
- package/dist/src/build/inlineSourceMapComment.d.ts +1 -0
- package/dist/src/build/scanConventions.d.ts +3 -0
- package/dist/src/build/vitals.d.ts +21 -0
- package/dist/src/client/formActions.d.ts +29 -0
- package/dist/src/client/index.d.ts +2 -0
- package/dist/src/client/navigation.d.ts +16 -0
- package/dist/src/client/prefetch.d.ts +2 -30
- package/dist/src/core/build.d.ts +2 -2
- package/dist/src/core/cspNonce.d.ts +12 -0
- package/dist/src/core/fileRouteAdapter.d.ts +15 -0
- package/dist/src/core/fileRoutes.d.ts +5 -0
- package/dist/src/core/formActionFlash.d.ts +25 -0
- package/dist/src/core/formActions.d.ts +249 -0
- package/dist/src/core/index.d.ts +5 -0
- package/dist/src/core/partialPrerender.d.ts +28 -0
- package/dist/src/core/partialPrerenderServe.d.ts +24 -0
- package/dist/src/core/precompressed.d.ts +11 -1
- package/dist/src/core/prerenderNonce.d.ts +9 -0
- package/dist/src/core/productionRuntime.d.ts +4 -2
- package/dist/src/core/serverOnlyStaticFiles.d.ts +8 -0
- package/dist/src/core/staticHtmlNonce.d.ts +2 -0
- package/dist/src/core/vitals.d.ts +108 -0
- package/dist/src/dev/angular/fastHmrCompiler.d.ts +1 -1
- package/dist/src/dev/client/cspNonce.d.ts +2 -0
- package/dist/src/dev/fileRouteRefresher.d.ts +5 -0
- package/dist/src/dev/importCost/instrument.d.ts +1 -1
- package/dist/src/dev/reactServerComponentsRebuild.d.ts +3 -0
- package/dist/src/i18n/defineMessages.d.ts +5 -0
- package/dist/src/i18n/formatMessage.d.ts +26 -0
- package/dist/src/i18n/index.d.ts +6 -0
- package/dist/src/i18n/intlCache.d.ts +5 -0
- package/dist/src/i18n/routing.d.ts +28 -0
- package/dist/src/i18n/translator.d.ts +11 -0
- package/dist/src/mobile/androidRelease.d.ts +2 -2
- package/dist/src/mobile/iosRelease.d.ts +4 -4
- package/dist/src/mobile/materializedBundle.d.ts +1 -1
- package/dist/src/mobile/mobileInspect.d.ts +1 -1
- package/dist/src/mobile/releaseArtifact.d.ts +2 -2
- package/dist/src/mobile/remoteMacProtocol.d.ts +2 -2
- package/dist/src/plugins/i18n.d.ts +30 -0
- package/dist/src/plugins/index.d.ts +2 -1
- package/dist/src/plugins/secureHeaders.d.ts +48 -0
- package/dist/src/react/components/Head.d.ts +1 -1
- package/dist/src/react/components/StreamSlot.browser.d.ts +1 -0
- package/dist/src/react/components/StreamSlot.d.ts +5 -1
- package/dist/src/react/components/SuspenseSlot.browser.d.ts +2 -0
- package/dist/src/react/components/SuspenseSlot.d.ts +12 -0
- package/dist/src/react/fileRoute.d.ts +18 -0
- package/dist/src/react/hooks/index.d.ts +4 -0
- package/dist/src/react/hooks/useFormAction.d.ts +42 -0
- package/dist/src/react/hooks/useI18n.d.ts +15 -0
- package/dist/src/react/index.d.ts +2 -0
- package/dist/src/react/server.d.ts +2 -0
- package/dist/src/react/serverComponents/constants.d.ts +11 -0
- package/dist/src/react/serverComponents/flightPayload.d.ts +2 -0
- package/dist/src/react/serverComponents/pageHandler.d.ts +14 -0
- package/dist/src/svelte/browser.d.ts +1 -0
- package/dist/src/svelte/fileRoute.d.ts +15 -0
- package/dist/src/svelte/i18n.d.ts +8 -0
- package/dist/src/svelte/index.d.ts +2 -0
- package/dist/src/svelte/lowerAwaitSlotSyntax.d.ts +5 -1
- package/dist/src/svelte/renderToReadableStream.d.ts +10 -2
- package/dist/src/svelte/router/browser.d.ts +3 -1
- package/dist/src/svelte/router/goto.d.ts +13 -10
- package/dist/src/svelte/router/guards.d.ts +43 -0
- package/dist/src/svelte/router/index.d.ts +3 -1
- package/dist/src/svelte/router/lazy.d.ts +17 -0
- package/dist/src/svelte/router/lazyModule.d.ts +29 -0
- package/dist/src/svelte/router/navigation.d.ts +55 -0
- package/dist/src/svelte/router/pushState.d.ts +4 -2
- package/dist/src/svelte/router/scroll.d.ts +34 -0
- package/dist/src/svelte/routerSsr.d.ts +9 -0
- package/dist/src/svelte/server.d.ts +1 -0
- package/dist/src/utils/cspNonceRef.d.ts +8 -0
- package/dist/src/utils/fontAssets.d.ts +17 -0
- package/dist/src/utils/formActionProtocol.d.ts +10 -0
- package/dist/src/utils/generateHeadElement.d.ts +1 -1
- package/dist/src/utils/index.d.ts +1 -0
- package/dist/src/utils/inlinePageCss.d.ts +18 -0
- package/dist/src/utils/loadConfig.d.ts +5 -0
- package/dist/src/utils/localeRef.d.ts +10 -0
- package/dist/src/utils/resolveConvention.d.ts +6 -1
- package/dist/src/utils/streamingSlots.d.ts +5 -0
- package/dist/src/vue/browser.d.ts +2 -0
- package/dist/src/vue/components/Image.d.ts +2 -2
- package/dist/src/vue/index.d.ts +2 -0
- package/dist/src/vue/serverDataPayload.d.ts +32 -0
- package/dist/src/vue/serverDataState.d.ts +9 -0
- package/dist/src/vue/useServerData.browser.d.ts +6 -0
- package/dist/src/vue/useServerData.d.ts +24 -0
- package/dist/svelte/browser.js +330 -3
- package/dist/svelte/browser.js.map +8 -4
- package/dist/svelte/components/AwaitSlot.svelte +5 -0
- package/dist/svelte/components/Head.svelte +50 -0
- package/dist/svelte/components/JsonLd.svelte +9 -1
- package/dist/svelte/components/StreamSlot.svelte +5 -0
- package/dist/svelte/index.js +1017 -117
- package/dist/svelte/index.js.map +38 -24
- package/dist/svelte/router/Link.svelte +40 -8
- package/dist/svelte/router/Route.svelte +157 -12
- package/dist/svelte/router/Route.svelte.d.ts +39 -5
- package/dist/svelte/router/Router.svelte +140 -25
- package/dist/svelte/router/Router.svelte.d.ts +5 -1
- package/dist/svelte/router/browser.ts +10 -0
- package/dist/svelte/router/goto.ts +15 -86
- package/dist/svelte/router/guards.ts +112 -0
- package/dist/svelte/router/index.ts +10 -0
- package/dist/svelte/router/lazy.ts +82 -0
- package/dist/svelte/router/lazyModule.ts +74 -0
- package/dist/svelte/router/navigation.ts +412 -0
- package/dist/svelte/router/pushState.ts +7 -4
- package/dist/svelte/router/scroll.ts +286 -0
- package/dist/svelte/server.js +747 -252
- package/dist/svelte/server.js.map +30 -20
- package/dist/types/angular.d.ts +2 -0
- package/dist/types/build.d.ts +37 -0
- package/dist/types/conventions.d.ts +3 -0
- package/dist/types/fileRoutes.d.ts +72 -0
- package/dist/types/fonts.d.ts +86 -0
- package/dist/types/formAction.d.ts +54 -0
- package/dist/types/globals.d.ts +10 -0
- package/dist/types/i18n.d.ts +185 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/metadata.d.ts +11 -0
- package/dist/types/navigation.d.ts +37 -0
- package/dist/types/prefetch.d.ts +10 -0
- package/dist/types/sitemap.d.ts +4 -0
- package/dist/types/svelteRouter.d.ts +89 -2
- package/dist/types/svelteRouter.ts +112 -2
- package/dist/types/vue.d.ts +46 -1
- package/dist/utils/iconVersion.ts +34 -0
- package/dist/vue/browser.js +107 -11
- package/dist/vue/browser.js.map +7 -4
- package/dist/vue/components/index.js +5 -2
- package/dist/vue/components/index.js.map +5 -4
- package/dist/vue/index.js +712 -158
- package/dist/vue/index.js.map +32 -23
- package/dist/vue/server.js +310 -79
- package/dist/vue/server.js.map +20 -15
- package/package.json +9 -1
- package/dist/cli/prerender-mfnwsvyt.js +0 -7
- package/dist/src/plugins/pageRouter.d.ts +0 -1
- /package/dist/cli/{index-j7m8pq48.js → index-rervww4p.js} +0 -0
package/dist/react/server.js
CHANGED
|
@@ -72,6 +72,194 @@ var __esm = (fn, res, err) => () => {
|
|
|
72
72
|
};
|
|
73
73
|
var __require = import.meta.require;
|
|
74
74
|
|
|
75
|
+
// src/utils/runtimeMode.ts
|
|
76
|
+
var ENV_VAR = "NODE_ENV", getNodeEnv = () => process.env[ENV_VAR], isDevelopmentRuntime = () => process.env[ENV_VAR] === "development", isProductionRuntime = () => process.env[ENV_VAR] === "production";
|
|
77
|
+
|
|
78
|
+
// src/utils/cspNonceRef.ts
|
|
79
|
+
var GETTER_KEY, nonceAttr = (nonce = readCspNonce()) => nonce ? ` nonce="${nonce}"` : "", nonceSvelteHeadStyles = (head, nonce = readCspNonce()) => nonce ? head.replace(/<style(?=\s+id="svelte-[^"]*")(?![^>]*\snonce=)/g, `<style nonce="${nonce}"`) : head, readCspNonce = () => {
|
|
80
|
+
const getter = Reflect.get(globalThis, GETTER_KEY);
|
|
81
|
+
if (typeof getter !== "function")
|
|
82
|
+
return;
|
|
83
|
+
const nonce = getter();
|
|
84
|
+
return typeof nonce === "string" ? nonce : undefined;
|
|
85
|
+
}, registerCspNonceGetter = (getter) => {
|
|
86
|
+
Reflect.set(globalThis, GETTER_KEY, getter);
|
|
87
|
+
};
|
|
88
|
+
var init_cspNonceRef = __esm(() => {
|
|
89
|
+
GETTER_KEY = Symbol.for("absolutejs.cspNonceGetter");
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// src/utils/ssrErrorPage.ts
|
|
93
|
+
var errorPageHtml = ({
|
|
94
|
+
framework,
|
|
95
|
+
hint,
|
|
96
|
+
kind,
|
|
97
|
+
message,
|
|
98
|
+
script = ""
|
|
99
|
+
}) => {
|
|
100
|
+
const frameworkColors = {
|
|
101
|
+
angular: "#dd0031",
|
|
102
|
+
html: "#e34c26",
|
|
103
|
+
htmx: "#1a365d",
|
|
104
|
+
react: "#61dafb",
|
|
105
|
+
svelte: "#ff3e00",
|
|
106
|
+
vue: "#42b883"
|
|
107
|
+
};
|
|
108
|
+
const accent = frameworkColors[framework] ?? "#94a3b8";
|
|
109
|
+
const label = framework.charAt(0).toUpperCase() + framework.slice(1);
|
|
110
|
+
return `<!DOCTYPE html>
|
|
111
|
+
<html>
|
|
112
|
+
<head>
|
|
113
|
+
<meta charset="utf-8">
|
|
114
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
115
|
+
<title>SSR Error - AbsoluteJS</title>
|
|
116
|
+
<style${nonceAttr()}>
|
|
117
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
118
|
+
body{min-height:100vh;background:linear-gradient(135deg,rgba(15,23,42,0.98) 0%,rgba(30,41,59,0.98) 100%);color:#e2e8f0;font-family:"JetBrains Mono","Fira Code",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:14px;line-height:1.6;display:flex;align-items:flex-start;justify-content:center;padding:32px}
|
|
119
|
+
.card{max-width:720px;width:100%;background:rgba(30,41,59,0.6);border:1px solid rgba(71,85,105,0.5);border-radius:16px;box-shadow:0 25px 50px -12px rgba(0,0,0,0.5),0 0 0 1px rgba(255,255,255,0.05);overflow:hidden}
|
|
120
|
+
.header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:20px 24px;background:rgba(15,23,42,0.5);border-bottom:1px solid rgba(71,85,105,0.4)}
|
|
121
|
+
.brand{font-weight:700;font-size:20px;color:#fff;letter-spacing:-0.02em}
|
|
122
|
+
.badge{padding:5px 10px;border-radius:8px;font-size:12px;font-weight:600;background:${accent};color:#fff;opacity:0.95;box-shadow:0 2px 4px rgba(0,0,0,0.2)}
|
|
123
|
+
.kind{color:#94a3b8;font-size:13px;font-weight:500}
|
|
124
|
+
.content{padding:24px}
|
|
125
|
+
.label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.08em;color:#94a3b8;margin-bottom:8px}
|
|
126
|
+
.message{margin:0;padding:16px 20px;background:rgba(239,68,68,0.12);border:1px solid rgba(239,68,68,0.25);border-radius:10px;overflow-x:auto;white-space:pre-wrap;word-break:break-word;color:#fca5a5;font-size:13px;line-height:1.5}
|
|
127
|
+
.hint{margin-top:20px;padding:12px 20px;background:rgba(71,85,105,0.3);border-radius:10px;border:1px solid rgba(71,85,105,0.4);color:#cbd5e1;font-size:13px}
|
|
128
|
+
</style>
|
|
129
|
+
</head>
|
|
130
|
+
<body>
|
|
131
|
+
<div class="card">
|
|
132
|
+
<div class="header">
|
|
133
|
+
<div style="display:flex;align-items:center;gap:12px">
|
|
134
|
+
<span class="brand">AbsoluteJS</span>
|
|
135
|
+
<span class="badge">${label}</span>
|
|
136
|
+
</div>
|
|
137
|
+
<span class="kind">${kind}</span>
|
|
138
|
+
</div>
|
|
139
|
+
<div class="content">
|
|
140
|
+
<div class="label">What went wrong</div>
|
|
141
|
+
<pre class="message">${message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</pre>
|
|
142
|
+
<div class="hint">${hint}</div>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
${script}
|
|
146
|
+
</body>
|
|
147
|
+
</html>`;
|
|
148
|
+
}, reloadOnRebuild = () => `<script${nonceAttr()}>(()=>{const url=(location.protocol==='https:'?'wss://':'ws://')+location.host+'/hmr';let seen=false;const connect=()=>{const socket=new WebSocket(url);socket.onopen=()=>{if(seen)location.reload();seen=true;};socket.onmessage=(event)=>{try{const message=JSON.parse(event.data);const type=message&&typeof message.type==='string'?message.type:'';if(type==='rebuild-complete'||type==='server-entry-reloaded'||type.endsWith('-update'))location.reload();}catch{}};socket.onclose=()=>setTimeout(connect,500);};connect();})();</script>`, buildErrorPage = (framework, pageName, error) => errorPageHtml({
|
|
149
|
+
framework,
|
|
150
|
+
hint: "Fix the file and save. This page reloads by itself when the build succeeds.",
|
|
151
|
+
kind: "Build Error",
|
|
152
|
+
message: `${pageName || "This page"} could not be built.
|
|
153
|
+
|
|
154
|
+
${error ?? "The dev-server terminal has the build output."}`,
|
|
155
|
+
script: reloadOnRebuild()
|
|
156
|
+
}), ssrErrorPage = (framework, error) => errorPageHtml({
|
|
157
|
+
framework,
|
|
158
|
+
hint: "A component threw during server-side rendering. Check the terminal for the full stack trace.",
|
|
159
|
+
kind: "Server Render Error",
|
|
160
|
+
message: error instanceof Error ? error.message : String(error)
|
|
161
|
+
});
|
|
162
|
+
var init_ssrErrorPage = __esm(() => {
|
|
163
|
+
init_cspNonceRef();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// src/core/requestContext.ts
|
|
167
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
168
|
+
import { Elysia } from "elysia";
|
|
169
|
+
var REQUEST_STORAGE_KEY, PAGE_WARMER_KEY, isAbsoluteRequestStorage = (value) => typeof value === "object" && value !== null && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function", getRequestStorage = () => {
|
|
170
|
+
const value = Reflect.get(globalThis, REQUEST_STORAGE_KEY);
|
|
171
|
+
return isAbsoluteRequestStorage(value) ? value : undefined;
|
|
172
|
+
}, ensureRequestStorage = () => {
|
|
173
|
+
const existing = getRequestStorage();
|
|
174
|
+
if (existing)
|
|
175
|
+
return existing;
|
|
176
|
+
const storage = new AsyncLocalStorage;
|
|
177
|
+
Reflect.set(globalThis, REQUEST_STORAGE_KEY, storage);
|
|
178
|
+
return storage;
|
|
179
|
+
}, absoluteRequestContext, getCurrentAbsoluteRequest = () => getRequestStorage()?.getStore()?.request, runWithAbsoluteRequest = (request, callback) => ensureRequestStorage().run({ request }, callback), CSS_KEY_RE, isDevPageWarmer = (value) => typeof value === "object" && value !== null && ("describe" in value) && typeof value.describe === "function" && ("warm" in value) && typeof value.warm === "function" && ("lookup" in value) && typeof value.lookup === "function", devBuildErrorResponse = (framework, assets) => {
|
|
180
|
+
if (!assets?.failed)
|
|
181
|
+
return null;
|
|
182
|
+
return new Response(buildErrorPage(framework, assets.name, assets.error), {
|
|
183
|
+
headers: {
|
|
184
|
+
"cache-control": "no-store",
|
|
185
|
+
"content-type": "text/html; charset=utf-8"
|
|
186
|
+
},
|
|
187
|
+
status: 500
|
|
188
|
+
});
|
|
189
|
+
}, getDevPageWarmer = () => {
|
|
190
|
+
const value = Reflect.get(globalThis, PAGE_WARMER_KEY);
|
|
191
|
+
return isDevPageWarmer(value) ? value : undefined;
|
|
192
|
+
}, getMissingAssets = () => {
|
|
193
|
+
const missing = getRequestStorage()?.getStore()?.missingAssets;
|
|
194
|
+
return missing ? [...missing] : [];
|
|
195
|
+
}, recordMissingAsset = (name) => {
|
|
196
|
+
const store = getRequestStorage()?.getStore();
|
|
197
|
+
if (!store)
|
|
198
|
+
return;
|
|
199
|
+
store.missingAssets ??= [];
|
|
200
|
+
store.missingAssets.push(name);
|
|
201
|
+
}, resolveDeferredPageAssets = async () => {
|
|
202
|
+
const warmer = getDevPageWarmer();
|
|
203
|
+
if (!warmer)
|
|
204
|
+
return null;
|
|
205
|
+
const missing = getMissingAssets();
|
|
206
|
+
const pageKey = missing.find((key) => warmer.describe(key));
|
|
207
|
+
if (pageKey === undefined)
|
|
208
|
+
return null;
|
|
209
|
+
const described = warmer.describe(pageKey);
|
|
210
|
+
if (!described)
|
|
211
|
+
return null;
|
|
212
|
+
const status = await warmer.warm(pageKey);
|
|
213
|
+
const failed = status === "failed" || status === "unknown";
|
|
214
|
+
const lookup = (key) => failed ? "" : warmer.lookup(key) ?? "";
|
|
215
|
+
const cssKeys = missing.filter((key) => CSS_KEY_RE.test(key));
|
|
216
|
+
const cssHrefs = () => cssKeys.map(lookup).filter((href) => href.length > 0 && href.startsWith("/"));
|
|
217
|
+
const assets = {
|
|
218
|
+
cssHrefs,
|
|
219
|
+
error: failed ? warmer.lastError?.() : undefined,
|
|
220
|
+
failed,
|
|
221
|
+
lookup,
|
|
222
|
+
name: described.name
|
|
223
|
+
};
|
|
224
|
+
return assets;
|
|
225
|
+
}, setDevPageWarmer = (warmer) => {
|
|
226
|
+
Reflect.set(globalThis, PAGE_WARMER_KEY, warmer);
|
|
227
|
+
}, withDeferredStylesheets = (head, assets) => {
|
|
228
|
+
const hrefs = assets?.cssHrefs() ?? [];
|
|
229
|
+
if (hrefs.length === 0)
|
|
230
|
+
return head;
|
|
231
|
+
const links = hrefs.filter((href) => !head.includes(href)).map((href) => `<link rel="stylesheet" href="${href}">`).join("");
|
|
232
|
+
if (links.length === 0)
|
|
233
|
+
return head;
|
|
234
|
+
const headClose = /<\/head\s*>/i.exec(head);
|
|
235
|
+
return headClose ? head.slice(0, headClose.index) + links + head.slice(headClose.index) : head + links;
|
|
236
|
+
};
|
|
237
|
+
var init_requestContext = __esm(() => {
|
|
238
|
+
init_ssrErrorPage();
|
|
239
|
+
REQUEST_STORAGE_KEY = Symbol.for("absolutejs.requestAsyncLocalStorage");
|
|
240
|
+
PAGE_WARMER_KEY = Symbol.for("absolutejs.devPageWarmer");
|
|
241
|
+
absoluteRequestContext = new Elysia({
|
|
242
|
+
name: "absolutejs-request-context"
|
|
243
|
+
}).onRequest(({ request }) => {
|
|
244
|
+
ensureRequestStorage().enterWith({ request });
|
|
245
|
+
}).as("global");
|
|
246
|
+
CSS_KEY_RE = /(?:CSS|Css)$/;
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// src/utils/escapeScriptContent.ts
|
|
250
|
+
var ESCAPE_LOOKUP, ESCAPE_REGEX, escapeScriptContent = (content) => content.replace(ESCAPE_REGEX, (char) => {
|
|
251
|
+
const escaped = ESCAPE_LOOKUP[char];
|
|
252
|
+
return escaped !== undefined ? escaped : char;
|
|
253
|
+
});
|
|
254
|
+
var init_escapeScriptContent = __esm(() => {
|
|
255
|
+
ESCAPE_LOOKUP = {
|
|
256
|
+
"\u2028": "\\u2028",
|
|
257
|
+
"\u2029": "\\u2029",
|
|
258
|
+
"<": "\\u003C"
|
|
259
|
+
};
|
|
260
|
+
ESCAPE_REGEX = /[<\u2028\u2029]/g;
|
|
261
|
+
});
|
|
262
|
+
|
|
75
263
|
// src/constants.ts
|
|
76
264
|
var ANGULAR_INIT_TIMEOUT_MS = 500, ANSI_ESCAPE_CODE = 27, ANSI_ESCAPE_LENGTH = 3, ASCII_SPACE = 32, BASE_36_RADIX = 36, BUN_BUILD_WARNING_SUPPRESSION = "wildcard sideEffects are not supported yet", TAILWIND_BUN_CSS_WARNING_PATTERN, BODY_SLICE_LENGTH = 2000, BYTES_PER_KILOBYTE = 1024, CLI_ARGS_OFFSET = 3, CSS_ERROR_RESOLVE_DELAY_MS = 50, CSS_MAX_CHECK_ATTEMPTS = 10, CSS_MAX_PARSE_TIMEOUT_MS = 500, CSS_RELOAD_BACKOFF_BASE_MS = 1000, CSS_RELOAD_BACKOFF_MAX_MS = 60000, CSS_SHEET_READY_TIMEOUT_MS = 100, DEFAULT_CHUNK_SIZE = 16384, DEFAULT_DEBOUNCE_MS = 15, DEFAULT_PORT = 3000, DEV_SERVER_RESTART_DEBOUNCE_MS = 100, DOM_UPDATE_DELAY_MS = 50, FILE_PROTOCOL_PREFIX_LENGTH = 7, FOCUS_ID_PREFIX_LENGTH = 3, FOCUS_IDX_PREFIX_LENGTH = 4, FOCUS_NAME_PREFIX_LENGTH = 5, ESLINT_STUDIO_DEFAULT_HOST = "eslint.absolute.localhost", ESLINT_STUDIO_DEFAULT_PORT = 4099, CONFIG_DEFAULT_HOST = "config.absolute.localhost", CONFIG_DEFAULT_PORT = 4099, HMR_UPDATE_TIMEOUT_MS = 2000, HOOK_SIGNATURE_LENGTH = 12, EXCLUDE_LAST_OFFSET = -1, HTTP_STATUS_OK = 200, HTTP_STATUS_BAD_REQUEST = 400, HTTP_STATUS_NOT_FOUND = 404, HTTP_STATUS_GONE = 410, HOURS_IN_DAY = 24, HOURS_IN_HALF_DAY = 12, IMAGE_DEFAULT_DEVICE_SIZES, IMAGE_DEFAULT_IMAGE_SIZES, IMAGE_DEFAULT_QUALITY = 75, IMAGE_GLOB_SUFFIX_LENGTH = 2, INSTANCE_PROBE_TIMEOUT_MS = 250, MAX_ERROR_LENGTH = 200, MAX_RECONNECT_ATTEMPTS = 60, MILLISECONDS_IN_A_SECOND = 1000, MINUTES_IN_AN_HOUR = 60, SECONDS_IN_A_MINUTE = 60, MILLISECONDS_IN_A_MINUTE, MILLISECONDS_IN_A_DAY, OVERLAY_FADE_DURATION_MS = 150, PING_INTERVAL_MS = 30000, LIST_LOG_TAIL_MAX_BYTES = 65536, LIST_TUI_COLUMN_GAP = 2, LIST_TUI_DEFAULT_HEIGHT = 28, LIST_TUI_DEFAULT_WIDTH = 100, LIST_TUI_ESCAPE_SEQUENCE_TIMEOUT_MS = 30, LIST_TUI_FOOTER_LINE_COUNT = 2, LIST_TUI_MARKER_WIDTH = 2, LIST_TUI_MIN_LOG_HEIGHT = 3, LIST_TUI_MIN_URL_WIDTH = 16, LIST_TUI_RENDER_DEBOUNCE_MS = 16, LIST_TUI_STATUS_MESSAGE_TIMEOUT_MS = 4000, LIST_WATCH_REFRESH_MS = 1000, RAF_BATCH_COUNT = 3, RANDOM_ID_END_INDEX = 11, REBUILD_BATCH_DELAY_MS = 10, REBUILD_RELOAD_DELAY_MS = 200, RECONNECT_INITIAL_DELAY_MS = 500, RECONNECT_POLL_INTERVAL_MS = 300, REACT_STREAM_SLOT_FAST_DELAY_MS = 5, REACT_STREAM_SLOT_SLOW_DELAY_MS = 20, SIGINT_EXIT_CODE = 130, SIGTERM_EXIT_CODE = 143, SVELTE_CSS_LOAD_TIMEOUT_MS = 500, TIME_PRECISION = 2, TWO_THIRDS, UNFOUND_INDEX = -1, WEBSOCKET_NORMAL_CLOSURE = 1000, DEFAULT_WEBSOCKET_IDLE_TIMEOUT_SECONDS = 240, DEFAULT_HTTP_IDLE_TIMEOUT_SECONDS = 240, MAX_HTTP_IDLE_TIMEOUT_SECONDS = 255, WORKSPACE_COMMAND_ARGS_OFFSET = 3, WORKSPACE_FAILURE_LOG_PRINT_LIMIT = 30, WORKSPACE_FAILURE_RECENT_LOG_LIMIT = 60, WORKSPACE_READY_ATTEMPT_TIMEOUT_MS = 5000, WORKSPACE_READY_PROBE_INTERVAL_MS = 250, WORKSPACE_READY_TIMEOUT_MS = 30000, WORKSPACE_SHUTDOWN_TIMEOUT_MS = 1e4, WORKSPACE_TUI_DEFAULT_HEIGHT = 28, WORKSPACE_TUI_DEFAULT_WIDTH = 100, WORKSPACE_TUI_ESCAPE_SEQUENCE_TIMEOUT_MS = 30, WORKSPACE_TUI_FOOTER_LINE_COUNT = 3, WORKSPACE_TUI_MIN_LOG_HEIGHT = 3, WORKSPACE_TUI_MIN_SERVICE_NAME_WIDTH = 7, WORKSPACE_TUI_MIN_TARGET_WIDTH = 8, WORKSPACE_TUI_MIN_WRAP_WIDTH = 12, WORKSPACE_TUI_PROMPT_CURSOR_OFFSET = 3, WORKSPACE_TUI_RECENT_LOG_LIMIT = 40, WORKSPACE_TUI_RENDER_DEBOUNCE_MS = 16, WORKSPACE_TUI_STATUS_WIDTH = 10, WORKSPACE_TUI_TARGET_PADDING_WIDTH = 6, WORKSPACE_TUI_VISIBILITY_WIDTH = 8;
|
|
77
265
|
var init_constants = __esm(() => {
|
|
@@ -288,15 +476,15 @@ var ISLAND_BOOTSTRAP_MANIFEST_KEY = "AbsoluteIslandBootstrap", LEGACY_ISLAND_BOO
|
|
|
288
476
|
var ISLAND_MARKER = 'data-island="true"', MANIFEST_MARKER = "__ABSOLUTE_MANIFEST__", ISLAND_STATE_MARKER = "__ABS_ISLAND_STATE__", CLOSING_HEAD_TAG = "</head>", warnedMissingBootstrap = false, warnIfBootstrapMissing = (manifest) => {
|
|
289
477
|
if (warnedMissingBootstrap || getIslandBootstrapPath(manifest))
|
|
290
478
|
return;
|
|
291
|
-
if (
|
|
292
|
-
;
|
|
479
|
+
if (isProductionRuntime())
|
|
480
|
+
return;
|
|
293
481
|
warnedMissingBootstrap = true;
|
|
294
482
|
logWarn("A page contains islands, but the build manifest has no islands bootstrap, so they will render without hydrating. Set `islands.registry` in absolute.config.ts (a default bootstrap is generated from it) or point `islands.bootstrap` at a file that calls startIslands().");
|
|
295
483
|
}, buildIslandsHeadMarkup = (manifest) => {
|
|
296
|
-
const manifestScript = `<script>window.__ABSOLUTE_MANIFEST__ = ${JSON.stringify(manifest)}</script>`;
|
|
297
|
-
const islandStateScript = `<script>window.__ABS_ISLAND_STATE__ = ${JSON.stringify(globalThis.__ABS_ISLAND_STATE__ ?? {})}</script>`;
|
|
484
|
+
const manifestScript = `<script${nonceAttr()}>window.__ABSOLUTE_MANIFEST__ = ${escapeScriptContent(JSON.stringify(manifest))}</script>`;
|
|
485
|
+
const islandStateScript = `<script${nonceAttr()}>window.__ABS_ISLAND_STATE__ = ${escapeScriptContent(JSON.stringify(globalThis.__ABS_ISLAND_STATE__ ?? {}))}</script>`;
|
|
298
486
|
const bootstrapPath = getIslandBootstrapPath(manifest);
|
|
299
|
-
const bootstrapScript = bootstrapPath ? `<script type="module" src="${bootstrapPath}"></script>` : "";
|
|
487
|
+
const bootstrapScript = bootstrapPath ? `<script${nonceAttr()} type="module" src="${bootstrapPath}"></script>` : "";
|
|
300
488
|
return `${manifestScript}${islandStateScript}${bootstrapScript}`;
|
|
301
489
|
}, injectHeadMarkup = (html, markup) => {
|
|
302
490
|
const closingHeadIndex = html.indexOf("</head>");
|
|
@@ -497,12 +685,14 @@ var ISLAND_MARKER = 'data-island="true"', MANIFEST_MARKER = "__ABSOLUTE_MANIFEST
|
|
|
497
685
|
globalThis.__absoluteManifest = manifest;
|
|
498
686
|
};
|
|
499
687
|
var init_islandPageContext = __esm(() => {
|
|
688
|
+
init_escapeScriptContent();
|
|
689
|
+
init_cspNonceRef();
|
|
500
690
|
init_logger();
|
|
501
691
|
});
|
|
502
692
|
|
|
503
693
|
// src/core/devRouteRegistrationCallsite.ts
|
|
504
|
-
import { AsyncLocalStorage } from "async_hooks";
|
|
505
|
-
import { Elysia } from "elysia";
|
|
694
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
695
|
+
import { Elysia as Elysia2 } from "elysia";
|
|
506
696
|
var ROUTE_CALLSITE_STORAGE_KEY, ROUTE_CALLSITE_PATCHED_KEY, NODE_ENV_KEY = "NODE_ENV", ROUTE_METHOD_NAMES, PAGE_HANDLER_NAMES, pageHandlerWrappers, isPageHandlerFunction = (value) => typeof value === "function", handlerSourceMentionsPageHelper = (handler) => {
|
|
507
697
|
const source = handler.toString();
|
|
508
698
|
return PAGE_HANDLER_NAMES.some((name) => source.includes(name));
|
|
@@ -528,7 +718,7 @@ var ROUTE_CALLSITE_STORAGE_KEY, ROUTE_CALLSITE_PATCHED_KEY, NODE_ENV_KEY = "NODE
|
|
|
528
718
|
if (existing) {
|
|
529
719
|
return existing;
|
|
530
720
|
}
|
|
531
|
-
const storage = new
|
|
721
|
+
const storage = new AsyncLocalStorage2;
|
|
532
722
|
Reflect.set(globalThis, ROUTE_CALLSITE_STORAGE_KEY, storage);
|
|
533
723
|
return storage;
|
|
534
724
|
}, normalizeCallsitePath = (value) => value.replace(`${process.cwd()}/`, "").replace(process.cwd(), "").replace(/^\.\/+/, ""), shouldIgnoreRouteCallsiteFrame = (frame) => frame.includes("/node_modules/") || frame.includes("/dist/") || frame.includes("/src/core/devRouteRegistrationCallsite."), getRouteCallsiteLocation = (frame) => frame.match(/\((\/[^)]+:\d+:\d+)\)$/)?.[1] ?? frame.match(/at (\/[^ ]+:\d+:\d+)$/)?.[1], extractRouteRegistrationCallsite = (stack) => {
|
|
@@ -569,7 +759,7 @@ var ROUTE_CALLSITE_STORAGE_KEY, ROUTE_CALLSITE_PATCHED_KEY, NODE_ENV_KEY = "NODE
|
|
|
569
759
|
if (Reflect.get(globalThis, ROUTE_CALLSITE_PATCHED_KEY) === true) {
|
|
570
760
|
return;
|
|
571
761
|
}
|
|
572
|
-
const { prototype } =
|
|
762
|
+
const { prototype } = Elysia2;
|
|
573
763
|
ROUTE_METHOD_NAMES.forEach((methodName) => {
|
|
574
764
|
const originalMethod = Reflect.get(prototype, methodName);
|
|
575
765
|
if (!isRouteMethod(originalMethod))
|
|
@@ -602,159 +792,6 @@ var init_devRouteRegistrationCallsite = __esm(() => {
|
|
|
602
792
|
pageHandlerWrappers = new WeakMap;
|
|
603
793
|
});
|
|
604
794
|
|
|
605
|
-
// src/utils/ssrErrorPage.ts
|
|
606
|
-
var errorPageHtml = ({
|
|
607
|
-
framework,
|
|
608
|
-
hint,
|
|
609
|
-
kind,
|
|
610
|
-
message,
|
|
611
|
-
script = ""
|
|
612
|
-
}) => {
|
|
613
|
-
const frameworkColors = {
|
|
614
|
-
angular: "#dd0031",
|
|
615
|
-
html: "#e34c26",
|
|
616
|
-
htmx: "#1a365d",
|
|
617
|
-
react: "#61dafb",
|
|
618
|
-
svelte: "#ff3e00",
|
|
619
|
-
vue: "#42b883"
|
|
620
|
-
};
|
|
621
|
-
const accent = frameworkColors[framework] ?? "#94a3b8";
|
|
622
|
-
const label = framework.charAt(0).toUpperCase() + framework.slice(1);
|
|
623
|
-
return `<!DOCTYPE html>
|
|
624
|
-
<html>
|
|
625
|
-
<head>
|
|
626
|
-
<meta charset="utf-8">
|
|
627
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
628
|
-
<title>SSR Error - AbsoluteJS</title>
|
|
629
|
-
<style>
|
|
630
|
-
*{margin:0;padding:0;box-sizing:border-box}
|
|
631
|
-
body{min-height:100vh;background:linear-gradient(135deg,rgba(15,23,42,0.98) 0%,rgba(30,41,59,0.98) 100%);color:#e2e8f0;font-family:"JetBrains Mono","Fira Code",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:14px;line-height:1.6;display:flex;align-items:flex-start;justify-content:center;padding:32px}
|
|
632
|
-
.card{max-width:720px;width:100%;background:rgba(30,41,59,0.6);border:1px solid rgba(71,85,105,0.5);border-radius:16px;box-shadow:0 25px 50px -12px rgba(0,0,0,0.5),0 0 0 1px rgba(255,255,255,0.05);overflow:hidden}
|
|
633
|
-
.header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:20px 24px;background:rgba(15,23,42,0.5);border-bottom:1px solid rgba(71,85,105,0.4)}
|
|
634
|
-
.brand{font-weight:700;font-size:20px;color:#fff;letter-spacing:-0.02em}
|
|
635
|
-
.badge{padding:5px 10px;border-radius:8px;font-size:12px;font-weight:600;background:${accent};color:#fff;opacity:0.95;box-shadow:0 2px 4px rgba(0,0,0,0.2)}
|
|
636
|
-
.kind{color:#94a3b8;font-size:13px;font-weight:500}
|
|
637
|
-
.content{padding:24px}
|
|
638
|
-
.label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.08em;color:#94a3b8;margin-bottom:8px}
|
|
639
|
-
.message{margin:0;padding:16px 20px;background:rgba(239,68,68,0.12);border:1px solid rgba(239,68,68,0.25);border-radius:10px;overflow-x:auto;white-space:pre-wrap;word-break:break-word;color:#fca5a5;font-size:13px;line-height:1.5}
|
|
640
|
-
.hint{margin-top:20px;padding:12px 20px;background:rgba(71,85,105,0.3);border-radius:10px;border:1px solid rgba(71,85,105,0.4);color:#cbd5e1;font-size:13px}
|
|
641
|
-
</style>
|
|
642
|
-
</head>
|
|
643
|
-
<body>
|
|
644
|
-
<div class="card">
|
|
645
|
-
<div class="header">
|
|
646
|
-
<div style="display:flex;align-items:center;gap:12px">
|
|
647
|
-
<span class="brand">AbsoluteJS</span>
|
|
648
|
-
<span class="badge">${label}</span>
|
|
649
|
-
</div>
|
|
650
|
-
<span class="kind">${kind}</span>
|
|
651
|
-
</div>
|
|
652
|
-
<div class="content">
|
|
653
|
-
<div class="label">What went wrong</div>
|
|
654
|
-
<pre class="message">${message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</pre>
|
|
655
|
-
<div class="hint">${hint}</div>
|
|
656
|
-
</div>
|
|
657
|
-
</div>
|
|
658
|
-
${script}
|
|
659
|
-
</body>
|
|
660
|
-
</html>`;
|
|
661
|
-
}, RELOAD_ON_REBUILD = `<script>(()=>{const url=(location.protocol==='https:'?'wss://':'ws://')+location.host+'/hmr';let seen=false;const connect=()=>{const socket=new WebSocket(url);socket.onopen=()=>{if(seen)location.reload();seen=true;};socket.onmessage=(event)=>{try{const message=JSON.parse(event.data);const type=message&&typeof message.type==='string'?message.type:'';if(type==='rebuild-complete'||type==='server-entry-reloaded'||type.endsWith('-update'))location.reload();}catch{}};socket.onclose=()=>setTimeout(connect,500);};connect();})();</script>`, buildErrorPage = (framework, pageName, error) => errorPageHtml({
|
|
662
|
-
framework,
|
|
663
|
-
hint: "Fix the file and save. This page reloads by itself when the build succeeds.",
|
|
664
|
-
kind: "Build Error",
|
|
665
|
-
message: `${pageName || "This page"} could not be built.
|
|
666
|
-
|
|
667
|
-
${error ?? "The dev-server terminal has the build output."}`,
|
|
668
|
-
script: RELOAD_ON_REBUILD
|
|
669
|
-
}), ssrErrorPage = (framework, error) => errorPageHtml({
|
|
670
|
-
framework,
|
|
671
|
-
hint: "A component threw during server-side rendering. Check the terminal for the full stack trace.",
|
|
672
|
-
kind: "Server Render Error",
|
|
673
|
-
message: error instanceof Error ? error.message : String(error)
|
|
674
|
-
});
|
|
675
|
-
|
|
676
|
-
// src/core/requestContext.ts
|
|
677
|
-
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
678
|
-
import { Elysia as Elysia2 } from "elysia";
|
|
679
|
-
var REQUEST_STORAGE_KEY, PAGE_WARMER_KEY, isAbsoluteRequestStorage = (value) => typeof value === "object" && value !== null && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function", getRequestStorage = () => {
|
|
680
|
-
const value = Reflect.get(globalThis, REQUEST_STORAGE_KEY);
|
|
681
|
-
return isAbsoluteRequestStorage(value) ? value : undefined;
|
|
682
|
-
}, ensureRequestStorage = () => {
|
|
683
|
-
const existing = getRequestStorage();
|
|
684
|
-
if (existing)
|
|
685
|
-
return existing;
|
|
686
|
-
const storage = new AsyncLocalStorage2;
|
|
687
|
-
Reflect.set(globalThis, REQUEST_STORAGE_KEY, storage);
|
|
688
|
-
return storage;
|
|
689
|
-
}, absoluteRequestContext, getCurrentAbsoluteRequest = () => getRequestStorage()?.getStore()?.request, runWithAbsoluteRequest = (request, callback) => ensureRequestStorage().run({ request }, callback), CSS_KEY_RE, isDevPageWarmer = (value) => typeof value === "object" && value !== null && ("describe" in value) && typeof value.describe === "function" && ("warm" in value) && typeof value.warm === "function" && ("lookup" in value) && typeof value.lookup === "function", devBuildErrorResponse = (framework, assets) => {
|
|
690
|
-
if (!assets?.failed)
|
|
691
|
-
return null;
|
|
692
|
-
return new Response(buildErrorPage(framework, assets.name, assets.error), {
|
|
693
|
-
headers: {
|
|
694
|
-
"cache-control": "no-store",
|
|
695
|
-
"content-type": "text/html; charset=utf-8"
|
|
696
|
-
},
|
|
697
|
-
status: 500
|
|
698
|
-
});
|
|
699
|
-
}, getDevPageWarmer = () => {
|
|
700
|
-
const value = Reflect.get(globalThis, PAGE_WARMER_KEY);
|
|
701
|
-
return isDevPageWarmer(value) ? value : undefined;
|
|
702
|
-
}, getMissingAssets = () => {
|
|
703
|
-
const missing = getRequestStorage()?.getStore()?.missingAssets;
|
|
704
|
-
return missing ? [...missing] : [];
|
|
705
|
-
}, recordMissingAsset = (name) => {
|
|
706
|
-
const store = getRequestStorage()?.getStore();
|
|
707
|
-
if (!store)
|
|
708
|
-
return;
|
|
709
|
-
store.missingAssets ??= [];
|
|
710
|
-
store.missingAssets.push(name);
|
|
711
|
-
}, resolveDeferredPageAssets = async () => {
|
|
712
|
-
const warmer = getDevPageWarmer();
|
|
713
|
-
if (!warmer)
|
|
714
|
-
return null;
|
|
715
|
-
const missing = getMissingAssets();
|
|
716
|
-
const pageKey = missing.find((key) => warmer.describe(key));
|
|
717
|
-
if (pageKey === undefined)
|
|
718
|
-
return null;
|
|
719
|
-
const described = warmer.describe(pageKey);
|
|
720
|
-
if (!described)
|
|
721
|
-
return null;
|
|
722
|
-
const status = await warmer.warm(pageKey);
|
|
723
|
-
const failed = status === "failed" || status === "unknown";
|
|
724
|
-
const lookup = (key) => failed ? "" : warmer.lookup(key) ?? "";
|
|
725
|
-
const cssKeys = missing.filter((key) => CSS_KEY_RE.test(key));
|
|
726
|
-
const cssHrefs = () => cssKeys.map(lookup).filter((href) => href.length > 0 && href.startsWith("/"));
|
|
727
|
-
const assets = {
|
|
728
|
-
cssHrefs,
|
|
729
|
-
error: failed ? warmer.lastError?.() : undefined,
|
|
730
|
-
failed,
|
|
731
|
-
lookup,
|
|
732
|
-
name: described.name
|
|
733
|
-
};
|
|
734
|
-
return assets;
|
|
735
|
-
}, setDevPageWarmer = (warmer) => {
|
|
736
|
-
Reflect.set(globalThis, PAGE_WARMER_KEY, warmer);
|
|
737
|
-
}, withDeferredStylesheets = (head, assets) => {
|
|
738
|
-
const hrefs = assets?.cssHrefs() ?? [];
|
|
739
|
-
if (hrefs.length === 0)
|
|
740
|
-
return head;
|
|
741
|
-
const links = hrefs.filter((href) => !head.includes(href)).map((href) => `<link rel="stylesheet" href="${href}">`).join("");
|
|
742
|
-
if (links.length === 0)
|
|
743
|
-
return head;
|
|
744
|
-
const headClose = /<\/head\s*>/i.exec(head);
|
|
745
|
-
return headClose ? head.slice(0, headClose.index) + links + head.slice(headClose.index) : head + links;
|
|
746
|
-
};
|
|
747
|
-
var init_requestContext = __esm(() => {
|
|
748
|
-
REQUEST_STORAGE_KEY = Symbol.for("absolutejs.requestAsyncLocalStorage");
|
|
749
|
-
PAGE_WARMER_KEY = Symbol.for("absolutejs.devPageWarmer");
|
|
750
|
-
absoluteRequestContext = new Elysia2({
|
|
751
|
-
name: "absolutejs-request-context"
|
|
752
|
-
}).onRequest(({ request }) => {
|
|
753
|
-
ensureRequestStorage().enterWith({ request });
|
|
754
|
-
}).as("global");
|
|
755
|
-
CSS_KEY_RE = /(?:CSS|Css)$/;
|
|
756
|
-
});
|
|
757
|
-
|
|
758
795
|
// src/mobile/producerContextState.ts
|
|
759
796
|
var ABSOLUTE_MOBILE_PRODUCER_STORAGE_KEY, frameworks, isCompatibilityPage = (value) => typeof value === "object" && value !== null && ("bundleHash" in value) && typeof value.bundleHash === "string" && ("contract" in value) && typeof value.contract === "string" && ("framework" in value) && typeof value.framework === "string" && frameworks.has(value.framework) && ("pageId" in value) && typeof value.pageId === "string" && ("propsSchemaHash" in value) && typeof value.propsSchemaHash === "string", getCurrentAbsoluteMobileProducerContext = () => {
|
|
760
797
|
const value = Reflect.get(globalThis, ABSOLUTE_MOBILE_PRODUCER_STORAGE_KEY);
|
|
@@ -908,7 +945,9 @@ var ABSOLUTE_MOBILE_PAGE_MEDIA_TYPE = "application/vnd.absolute.page+json", ABSO
|
|
|
908
945
|
return createAbsoluteMobilePageErrorResponse(page.pageId);
|
|
909
946
|
}
|
|
910
947
|
}, finalizeAbsoluteNativeRouteDevelopmentPage = (input) => {
|
|
911
|
-
if (
|
|
948
|
+
if (!isDevelopmentRuntime()) {
|
|
949
|
+
return createAbsoluteMobileInvalidRequestResponse("The native-route development representation is disabled outside development.");
|
|
950
|
+
}
|
|
912
951
|
if (input.request?.method !== "GET") {
|
|
913
952
|
return createAbsoluteMobileInvalidRequestResponse("Native-route data requests must use GET.");
|
|
914
953
|
}
|
|
@@ -1250,22 +1289,15 @@ var streamSwapRuntime = () => {
|
|
|
1250
1289
|
return value.slice(start + 1, end);
|
|
1251
1290
|
}, getStreamSwapRuntimeScript = () => `(function(){${stripFunctionWrapper(streamSwapRuntime.toString())}})();`;
|
|
1252
1291
|
|
|
1253
|
-
// src/utils/escapeScriptContent.ts
|
|
1254
|
-
var ESCAPE_LOOKUP, ESCAPE_REGEX, escapeScriptContent = (content) => content.replace(ESCAPE_REGEX, (char) => {
|
|
1255
|
-
const escaped = ESCAPE_LOOKUP[char];
|
|
1256
|
-
return escaped !== undefined ? escaped : char;
|
|
1257
|
-
});
|
|
1258
|
-
var init_escapeScriptContent = __esm(() => {
|
|
1259
|
-
ESCAPE_LOOKUP = {
|
|
1260
|
-
"\u2028": "\\u2028",
|
|
1261
|
-
"\u2029": "\\u2029",
|
|
1262
|
-
"<": "\\u003C"
|
|
1263
|
-
};
|
|
1264
|
-
ESCAPE_REGEX = /[<\u2028\u2029]/g;
|
|
1265
|
-
});
|
|
1266
|
-
|
|
1267
1292
|
// src/utils/streamingSlots.ts
|
|
1268
|
-
var SLOT_ID_PREFIX = "abs-slot-", CLOSING_BODY_TAG = "</body>", CLOSING_HEAD_TAG2 = "</head>", CLOSING_BODY_TAG_LENGTH, CLOSING_HEAD_TAG_LENGTH, CLOSING_PAGE_TAG_REGEX, STREAMING_RUNTIME_GLOBAL = "__ABS_SLOT_ENQUEUE__", STREAMING_PENDING_GLOBAL = "__ABS_SLOT_PENDING__", STREAM_TAIL_LOOKBEHIND = 128, STREAMING_SLOT_TIMEOUT_MS = 5000,
|
|
1293
|
+
var SLOT_ID_PREFIX = "abs-slot-", CLOSING_BODY_TAG = "</body>", CLOSING_HEAD_TAG2 = "</head>", CLOSING_BODY_TAG_LENGTH, CLOSING_HEAD_TAG_LENGTH, CLOSING_PAGE_TAG_REGEX, STREAMING_RUNTIME_GLOBAL = "__ABS_SLOT_ENQUEUE__", STREAMING_PENDING_GLOBAL = "__ABS_SLOT_PENDING__", STREAM_TAIL_LOOKBEHIND = 128, STREAMING_SLOT_TIMEOUT_MS = 5000, findSafeFlushIndex = (text, cut) => {
|
|
1294
|
+
const head = text.slice(0, cut);
|
|
1295
|
+
const openScript = head.lastIndexOf("<script");
|
|
1296
|
+
const scriptCut = openScript > head.lastIndexOf("</script>") ? openScript : cut;
|
|
1297
|
+
const beforeScript = text.slice(0, scriptCut);
|
|
1298
|
+
const openTag = beforeScript.lastIndexOf("<");
|
|
1299
|
+
return openTag > beforeScript.lastIndexOf(">") ? openTag : scriptCut;
|
|
1300
|
+
}, STREAMING_SLOT_MAX_PER_RESPONSE = 128, STREAMING_SLOT_MAX_HTML_BYTES = 64000, createSlotPatchStatement = (id, payload) => `(window.${STREAMING_RUNTIME_GLOBAL}||function(i,p){window.${STREAMING_PENDING_GLOBAL}=window.${STREAMING_PENDING_GLOBAL}||{};window.${STREAMING_PENDING_GLOBAL}[i]=p;})(${JSON.stringify(id)},${JSON.stringify(payload)});`, createNonceAttr = (nonce) => nonceAttr(nonce), createStreamingSlotId = () => `${SLOT_ID_PREFIX}${Math.random().toString(BASE_36_RADIX).slice(2, RANDOM_ID_END_INDEX)}`, getStreamingSlotsRuntimeScript = () => getStreamSwapRuntimeScript(), injectHtmlIntoBody = (html, injection) => {
|
|
1269
1301
|
const closingBodyIndex = html.indexOf(CLOSING_BODY_TAG);
|
|
1270
1302
|
if (closingBodyIndex >= 0) {
|
|
1271
1303
|
return `${html.slice(0, closingBodyIndex)}${injection}${html.slice(closingBodyIndex)}`;
|
|
@@ -1345,6 +1377,7 @@ var SLOT_ID_PREFIX = "abs-slot-", CLOSING_BODY_TAG = "</body>", CLOSING_HEAD_TAG
|
|
|
1345
1377
|
const error = Object.assign(new Error(`Streaming slot "${slot.id}" timed out after ${timeoutMs}ms`), { __absTimeout: true });
|
|
1346
1378
|
return error;
|
|
1347
1379
|
}, isSlotPatchPayloadObject = (value) => isRecord2(value) && ("html" in value), isTimeoutError = (error) => isRecord2(error) && error.__absTimeout === true, toStreamingSlot = (slot, policy) => ({
|
|
1380
|
+
dynamic: slot.dynamic,
|
|
1348
1381
|
errorHtml: slot.errorHtml === undefined ? policy.errorHtml : slot.errorHtml,
|
|
1349
1382
|
fallbackHtml: normalizeSlotText(slot.fallbackHtml, policy.fallbackHtml),
|
|
1350
1383
|
id: slot.id ?? createStreamingSlotId(),
|
|
@@ -1569,9 +1602,10 @@ var SLOT_ID_PREFIX = "abs-slot-", CLOSING_BODY_TAG = "</body>", CLOSING_HEAD_TAG
|
|
|
1569
1602
|
if (tail.length <= STREAM_TAIL_LOOKBEHIND) {
|
|
1570
1603
|
return tail;
|
|
1571
1604
|
}
|
|
1572
|
-
const
|
|
1573
|
-
|
|
1574
|
-
|
|
1605
|
+
const cut = findSafeFlushIndex(tail, tail.length - STREAM_TAIL_LOOKBEHIND);
|
|
1606
|
+
if (cut > 0)
|
|
1607
|
+
controller.enqueue(encoder.encode(tail.slice(0, cut)));
|
|
1608
|
+
return tail.slice(cut);
|
|
1575
1609
|
};
|
|
1576
1610
|
const finalizeCompletedBaseWinner = (controller, decodedTail, baseRead) => {
|
|
1577
1611
|
const footerStart = decodedTail.search(CLOSING_PAGE_TAG_REGEX);
|
|
@@ -1804,6 +1838,7 @@ var SLOT_ID_PREFIX = "abs-slot-", CLOSING_BODY_TAG = "</body>", CLOSING_HEAD_TAG
|
|
|
1804
1838
|
});
|
|
1805
1839
|
};
|
|
1806
1840
|
var init_streamingSlots = __esm(() => {
|
|
1841
|
+
init_cspNonceRef();
|
|
1807
1842
|
init_constants();
|
|
1808
1843
|
init_escapeScriptContent();
|
|
1809
1844
|
CLOSING_BODY_TAG_LENGTH = CLOSING_BODY_TAG.length;
|
|
@@ -1818,6 +1853,42 @@ var init_streamingSlots = __esm(() => {
|
|
|
1818
1853
|
};
|
|
1819
1854
|
});
|
|
1820
1855
|
|
|
1856
|
+
// src/core/partialPrerender.ts
|
|
1857
|
+
import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
|
|
1858
|
+
import { existsSync, readFileSync } from "fs";
|
|
1859
|
+
import { rm } from "fs/promises";
|
|
1860
|
+
var PARTIAL_HOLES_HEADER = "X-Absolute-Partial-Holes", PARTIAL_SHELL_HEADER = "X-Absolute-Partial-Shell", SINK_STORAGE_KEY, isSinkStorage = (value) => value instanceof AsyncLocalStorage3, getSinkStorage = () => {
|
|
1861
|
+
const existing = Reflect.get(globalThis, SINK_STORAGE_KEY);
|
|
1862
|
+
if (isSinkStorage(existing))
|
|
1863
|
+
return existing;
|
|
1864
|
+
const created = new AsyncLocalStorage3;
|
|
1865
|
+
Reflect.set(globalThis, SINK_STORAGE_KEY, created);
|
|
1866
|
+
return created;
|
|
1867
|
+
}, activePartialHolesSink = () => getSinkStorage().getStore(), collectPartialHoles = async (render) => {
|
|
1868
|
+
const sink = { slots: undefined };
|
|
1869
|
+
const response = await getSinkStorage().run(sink, render);
|
|
1870
|
+
return { response, slots: sink.slots };
|
|
1871
|
+
}, decodePartialHoles = (value) => value ? value.split(",").filter(Boolean).map((id) => decodeURIComponent(id)) : [], encodePartialHoles = (ids) => ids.map((id) => encodeURIComponent(id)).join(","), isDynamicStreamingSlot = (slot) => slot.dynamic === true, isPartialShellCapture = (request) => request?.headers.get(PARTIAL_SHELL_HEADER) === "1", holesPath = (htmlPath) => htmlPath.replace(/\.html$/, ".holes"), readPartialHoles = (htmlPath) => {
|
|
1872
|
+
const path = holesPath(htmlPath);
|
|
1873
|
+
if (!existsSync(path))
|
|
1874
|
+
return [];
|
|
1875
|
+
return decodePartialHoles(readFileSync(path, "utf-8").trim().split(`
|
|
1876
|
+
`).join(","));
|
|
1877
|
+
}, writePartialHoles = async (htmlPath, response) => {
|
|
1878
|
+
const ids = decodePartialHoles(response.headers.get(PARTIAL_HOLES_HEADER));
|
|
1879
|
+
if (ids.length > 0) {
|
|
1880
|
+
await Bun.write(holesPath(htmlPath), `${encodePartialHoles(ids).split(",").join(`
|
|
1881
|
+
`)}
|
|
1882
|
+
`);
|
|
1883
|
+
} else {
|
|
1884
|
+
await rm(holesPath(htmlPath), { force: true });
|
|
1885
|
+
}
|
|
1886
|
+
return ids;
|
|
1887
|
+
};
|
|
1888
|
+
var init_partialPrerender = __esm(() => {
|
|
1889
|
+
SINK_STORAGE_KEY = Symbol.for("absolutejs.partialPrerenderHolesSink");
|
|
1890
|
+
});
|
|
1891
|
+
|
|
1821
1892
|
// src/utils/stringModifiers.ts
|
|
1822
1893
|
var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9\-_]+/g, "").replace(/[-_]{2,}/g, "-"), toKebab = (str) => normalizeSlug(str).replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), toPascal = (str) => {
|
|
1823
1894
|
if (!str.includes("-") && !str.includes("_")) {
|
|
@@ -1826,6 +1897,45 @@ var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-
|
|
|
1826
1897
|
return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
|
|
1827
1898
|
};
|
|
1828
1899
|
|
|
1900
|
+
// src/core/staticHtmlNonce.ts
|
|
1901
|
+
var nonceStaticHtml = async (html, nonce = readCspNonce()) => {
|
|
1902
|
+
if (!nonce)
|
|
1903
|
+
return html;
|
|
1904
|
+
const stamp = {
|
|
1905
|
+
element: (element) => {
|
|
1906
|
+
if (!element.hasAttribute("nonce"))
|
|
1907
|
+
element.setAttribute("nonce", nonce);
|
|
1908
|
+
}
|
|
1909
|
+
};
|
|
1910
|
+
return new HTMLRewriter().on("script", stamp).on("style", stamp).transform(new Response(html)).text();
|
|
1911
|
+
}, isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), parseHtmxConfig = (content) => {
|
|
1912
|
+
try {
|
|
1913
|
+
const parsed = JSON.parse(content ?? "{}");
|
|
1914
|
+
return isRecord3(parsed) ? parsed : {};
|
|
1915
|
+
} catch {
|
|
1916
|
+
return {};
|
|
1917
|
+
}
|
|
1918
|
+
}, withHtmxStyleNonce = async (html, nonce = readCspNonce()) => {
|
|
1919
|
+
if (!nonce)
|
|
1920
|
+
return html;
|
|
1921
|
+
let found = false;
|
|
1922
|
+
const merged = await new HTMLRewriter().on('meta[name="htmx-config"]', {
|
|
1923
|
+
element: (element) => {
|
|
1924
|
+
found = true;
|
|
1925
|
+
const config = parseHtmxConfig(element.getAttribute("content"));
|
|
1926
|
+
element.setAttribute("content", JSON.stringify({ ...config, inlineStyleNonce: nonce }));
|
|
1927
|
+
}
|
|
1928
|
+
}).transform(new Response(html)).text();
|
|
1929
|
+
if (found)
|
|
1930
|
+
return merged;
|
|
1931
|
+
const meta = `<meta name="htmx-config" content='${JSON.stringify({ inlineStyleNonce: nonce })}'>`;
|
|
1932
|
+
const headClose = merged.search(/<\/head>/i);
|
|
1933
|
+
return headClose >= 0 ? `${merged.slice(0, headClose)}${meta}${merged.slice(headClose)}` : `${meta}${merged}`;
|
|
1934
|
+
};
|
|
1935
|
+
var init_staticHtmlNonce = __esm(() => {
|
|
1936
|
+
init_cspNonceRef();
|
|
1937
|
+
});
|
|
1938
|
+
|
|
1829
1939
|
// src/utils/resolveConvention.ts
|
|
1830
1940
|
import { basename } from "path";
|
|
1831
1941
|
var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boolean(value) && typeof value === "object", getMap = () => {
|
|
@@ -1862,7 +1972,7 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
|
|
|
1862
1972
|
return conventions.defaults?.error;
|
|
1863
1973
|
}, resolveNotFoundConventionPath = (framework) => getMap()[framework]?.defaults?.notFound, setConventions = (map) => {
|
|
1864
1974
|
Reflect.set(globalThis, CONVENTIONS_KEY, map);
|
|
1865
|
-
}, isDev = () =>
|
|
1975
|
+
}, isDev = () => isDevelopmentRuntime(), buildErrorProps = (error) => {
|
|
1866
1976
|
if (error instanceof Error) {
|
|
1867
1977
|
return {
|
|
1868
1978
|
message: error.message,
|
|
@@ -1879,7 +1989,9 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
|
|
|
1879
1989
|
if (typeof ErrorComponent !== "function")
|
|
1880
1990
|
return null;
|
|
1881
1991
|
const element = createElement(ErrorComponent, errorProps);
|
|
1882
|
-
const stream = await renderToReadableStream(element
|
|
1992
|
+
const stream = await renderToReadableStream(element, {
|
|
1993
|
+
nonce: readCspNonce()
|
|
1994
|
+
});
|
|
1883
1995
|
return new Response(stream, {
|
|
1884
1996
|
headers: { "Content-Type": "text/html" },
|
|
1885
1997
|
status: 500
|
|
@@ -1890,10 +2002,12 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
|
|
|
1890
2002
|
const ErrorComponent = mod.default;
|
|
1891
2003
|
if (!ErrorComponent)
|
|
1892
2004
|
return null;
|
|
2005
|
+
const nonce = readCspNonce();
|
|
1893
2006
|
const { head, body } = render(ErrorComponent, {
|
|
1894
|
-
props: errorProps
|
|
2007
|
+
props: errorProps,
|
|
2008
|
+
...nonce ? { csp: { nonce } } : {}
|
|
1895
2009
|
});
|
|
1896
|
-
const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
|
|
2010
|
+
const html = `<!DOCTYPE html><html><head>${nonceSvelteHeadStyles(head)}</head><body>${body}</body></html>`;
|
|
1897
2011
|
return new Response(html, {
|
|
1898
2012
|
headers: { "Content-Type": "text/html" },
|
|
1899
2013
|
status: 500
|
|
@@ -1901,7 +2015,7 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
|
|
|
1901
2015
|
}, unescapeVueStyles = (ssrBody) => {
|
|
1902
2016
|
let styles = "";
|
|
1903
2017
|
const body = ssrBody.replace(/<style>([\s\S]*?)<\/style>/g, (_, css) => {
|
|
1904
|
-
styles += `<style>${css.replace(/"/g, '"').replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</style>`;
|
|
2018
|
+
styles += `<style${nonceAttr()}>${css.replace(/"/g, '"').replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</style>`;
|
|
1905
2019
|
return "";
|
|
1906
2020
|
});
|
|
1907
2021
|
return { body, styles };
|
|
@@ -1933,7 +2047,7 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
|
|
|
1933
2047
|
status: 500
|
|
1934
2048
|
});
|
|
1935
2049
|
}, escapeHtml = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"), replaceErrorTokens = (template, errorProps) => template.replace(/\{\{\s*name\s*\}\}/g, escapeHtml(errorProps.name)).replace(/\{\{\s*message\s*\}\}/g, escapeHtml(errorProps.message)).replace(/\{\{\s*stack\s*\}\}/g, errorProps.stack ? escapeHtml(errorProps.stack) : ""), renderHtmlError = async (conventionPath, errorProps) => {
|
|
1936
|
-
const template = await Bun.file(conventionPath).text();
|
|
2050
|
+
const template = await nonceStaticHtml(await Bun.file(conventionPath).text());
|
|
1937
2051
|
const html = replaceErrorTokens(template, errorProps);
|
|
1938
2052
|
return new Response(html, {
|
|
1939
2053
|
headers: { "Content-Type": "text/html" },
|
|
@@ -1988,7 +2102,9 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
|
|
|
1988
2102
|
if (typeof NotFoundComponent !== "function")
|
|
1989
2103
|
return null;
|
|
1990
2104
|
const element = createElement(NotFoundComponent);
|
|
1991
|
-
const stream = await renderToReadableStream(element
|
|
2105
|
+
const stream = await renderToReadableStream(element, {
|
|
2106
|
+
nonce: readCspNonce()
|
|
2107
|
+
});
|
|
1992
2108
|
return new Response(stream, {
|
|
1993
2109
|
headers: { "Content-Type": "text/html" },
|
|
1994
2110
|
status: 404
|
|
@@ -1999,8 +2115,9 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
|
|
|
1999
2115
|
const NotFoundComponent = mod.default;
|
|
2000
2116
|
if (!NotFoundComponent)
|
|
2001
2117
|
return null;
|
|
2002
|
-
const
|
|
2003
|
-
const
|
|
2118
|
+
const nonce = readCspNonce();
|
|
2119
|
+
const { head, body } = render(NotFoundComponent, nonce ? { csp: { nonce } } : {});
|
|
2120
|
+
const html = `<!DOCTYPE html><html><head>${nonceSvelteHeadStyles(head)}</head><body>${body}</body></html>`;
|
|
2004
2121
|
return new Response(html, {
|
|
2005
2122
|
headers: { "Content-Type": "text/html" },
|
|
2006
2123
|
status: 404
|
|
@@ -2033,7 +2150,7 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
|
|
|
2033
2150
|
status: 404
|
|
2034
2151
|
});
|
|
2035
2152
|
}, renderHtmlNotFound = async (conventionPath) => {
|
|
2036
|
-
const html = await Bun.file(conventionPath).text();
|
|
2153
|
+
const html = await nonceStaticHtml(await Bun.file(conventionPath).text());
|
|
2037
2154
|
return new Response(html, {
|
|
2038
2155
|
headers: { "Content-Type": "text/html" },
|
|
2039
2156
|
status: 404
|
|
@@ -2051,7 +2168,7 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
|
|
|
2051
2168
|
logConventionRenderError(framework, "not-found", renderError);
|
|
2052
2169
|
}
|
|
2053
2170
|
return null;
|
|
2054
|
-
}, NOT_FOUND_PRIORITY, renderFirstNotFound = async () => {
|
|
2171
|
+
}, NOT_FOUND_PRIORITY, renderFirstNotFound = async (options = {}) => {
|
|
2055
2172
|
const renderNext = async (frameworks) => {
|
|
2056
2173
|
const [framework, ...remaining] = frameworks;
|
|
2057
2174
|
if (!framework) {
|
|
@@ -2066,13 +2183,16 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
|
|
|
2066
2183
|
}
|
|
2067
2184
|
return renderNext(remaining);
|
|
2068
2185
|
};
|
|
2069
|
-
return renderNext(NOT_FOUND_PRIORITY);
|
|
2186
|
+
return renderNext(options.preferHtmx ? ["htmx", ...NOT_FOUND_PRIORITY.filter((key) => key !== "htmx")] : NOT_FOUND_PRIORITY);
|
|
2070
2187
|
};
|
|
2071
2188
|
var init_resolveConvention = __esm(() => {
|
|
2189
|
+
init_cspNonceRef();
|
|
2190
|
+
init_staticHtmlNonce();
|
|
2072
2191
|
ERROR_RENDERERS = {
|
|
2073
2192
|
angular: renderAngularError,
|
|
2074
2193
|
ember: renderEmberError,
|
|
2075
2194
|
html: renderHtmlError,
|
|
2195
|
+
htmx: renderHtmlError,
|
|
2076
2196
|
react: renderReactError,
|
|
2077
2197
|
svelte: renderSvelteError,
|
|
2078
2198
|
vue: renderVueError
|
|
@@ -2081,6 +2201,7 @@ var init_resolveConvention = __esm(() => {
|
|
|
2081
2201
|
angular: renderAngularNotFound,
|
|
2082
2202
|
ember: renderEmberNotFound,
|
|
2083
2203
|
html: renderHtmlNotFound,
|
|
2204
|
+
htmx: renderHtmlNotFound,
|
|
2084
2205
|
react: renderReactNotFound,
|
|
2085
2206
|
svelte: renderSvelteNotFound,
|
|
2086
2207
|
vue: renderVueNotFound
|
|
@@ -2090,7 +2211,8 @@ var init_resolveConvention = __esm(() => {
|
|
|
2090
2211
|
"svelte",
|
|
2091
2212
|
"vue",
|
|
2092
2213
|
"angular",
|
|
2093
|
-
"html"
|
|
2214
|
+
"html",
|
|
2215
|
+
"htmx"
|
|
2094
2216
|
];
|
|
2095
2217
|
});
|
|
2096
2218
|
|
|
@@ -2175,7 +2297,7 @@ var init_browserTranslationAttributes = __esm(() => {
|
|
|
2175
2297
|
});
|
|
2176
2298
|
|
|
2177
2299
|
// src/core/browserTranslation.ts
|
|
2178
|
-
var BASELINE_MARKER = "__ABSOLUTE_SSR_TEXT_BASELINES__", BROWSER_TRANSLATION_BASELINE_SCRIPT, browserTranslationBaselineTag = () => `<script>${BROWSER_TRANSLATION_BASELINE_SCRIPT}</script>`, injectBrowserTranslationBaseline = (html) => {
|
|
2300
|
+
var BASELINE_MARKER = "__ABSOLUTE_SSR_TEXT_BASELINES__", BROWSER_TRANSLATION_BASELINE_SCRIPT, browserTranslationBaselineTag = () => `<script${nonceAttr()}>${BROWSER_TRANSLATION_BASELINE_SCRIPT}</script>`, injectBrowserTranslationBaseline = (html) => {
|
|
2179
2301
|
if (html.includes(BASELINE_MARKER))
|
|
2180
2302
|
return html;
|
|
2181
2303
|
const script = browserTranslationBaselineTag();
|
|
@@ -2185,11 +2307,69 @@ var BASELINE_MARKER = "__ABSOLUTE_SSR_TEXT_BASELINES__", BROWSER_TRANSLATION_BAS
|
|
|
2185
2307
|
return `${html.slice(0, closingBodyIndex)}${script}${html.slice(closingBodyIndex)}`;
|
|
2186
2308
|
};
|
|
2187
2309
|
var init_browserTranslation = __esm(() => {
|
|
2310
|
+
init_cspNonceRef();
|
|
2188
2311
|
init_browserTranslationAttributes();
|
|
2189
2312
|
BROWSER_TRANSLATION_BASELINE_SCRIPT = "window.__ABSOLUTE_SSR_TEXT_BASELINES__=new WeakMap();" + "window.__ABSOLUTE_SSR_ATTRIBUTE_BASELINES__=new WeakMap();" + "{const r=document.body,b=window.__ABSOLUTE_SSR_TEXT_BASELINES__," + "a=window.__ABSOLUTE_SSR_ATTRIBUTE_BASELINES__;" + 'if(r)for(const e of [r,...r.querySelectorAll("*")]){' + "const t=new Map();for(const [i,n]of[...e.childNodes].entries())" + 'if(n.nodeType===3)t.set(i,n.nodeValue??"");if(t.size)b.set(e,t);' + `const v=new Map();for(const k of ${JSON.stringify(TRANSLATABLE_ATTRIBUTES)}){` + "const s=e.getAttribute(k);if(s!==null)v.set(k,s);}if(v.size)a.set(e,v);}}";
|
|
2190
2313
|
});
|
|
2191
2314
|
|
|
2315
|
+
// src/react/serverComponents/constants.ts
|
|
2316
|
+
var REACT_SERVER_CLIENT_MANIFEST_KEY = "ReactServerClient", REACT_SERVER_PAGE_MANIFEST_SUFFIX = "RSC", REACT_SERVER_PAYLOAD_GLOBAL = "__absoluteReactServerPayload", REACT_SERVER_RENDERER_MANIFEST_KEY = "ReactServerRenderer", REACT_SERVER_RUNTIME_FILE = "react-server-runtime.json";
|
|
2317
|
+
|
|
2318
|
+
// src/core/fileRouteAdapter.ts
|
|
2319
|
+
var PARAM_NAME_RE = /:([A-Za-z_$][\w$]*)/g;
|
|
2320
|
+
var paramNamesOf = (path) => [...path.matchAll(PARAM_NAME_RE)].map((match) => match[1]).filter((name) => name !== undefined);
|
|
2321
|
+
var hasRouteParams = (context, names) => names.every((name) => typeof context.params[name] === "string");
|
|
2322
|
+
var serverHooksOf = ({
|
|
2323
|
+
path,
|
|
2324
|
+
server
|
|
2325
|
+
}) => {
|
|
2326
|
+
if (!server)
|
|
2327
|
+
return {};
|
|
2328
|
+
const names = paramNamesOf(path);
|
|
2329
|
+
const withParams = async (context, run) => {
|
|
2330
|
+
const module = await server();
|
|
2331
|
+
if (!module || !hasRouteParams(context, names))
|
|
2332
|
+
return;
|
|
2333
|
+
return run(module, context);
|
|
2334
|
+
};
|
|
2335
|
+
const hooks = {
|
|
2336
|
+
beforeHandle: (context) => withParams(context, (module, typed) => module.beforeHandle?.(typed)),
|
|
2337
|
+
load: (context) => withParams(context, (module, typed) => module.load?.(typed))
|
|
2338
|
+
};
|
|
2339
|
+
return hooks;
|
|
2340
|
+
};
|
|
2341
|
+
var defineFileRouteWith = (framework, route, render) => {
|
|
2342
|
+
const definition = {
|
|
2343
|
+
framework,
|
|
2344
|
+
name: route.name,
|
|
2345
|
+
path: route.path,
|
|
2346
|
+
render,
|
|
2347
|
+
source: route.source,
|
|
2348
|
+
...serverHooksOf(route)
|
|
2349
|
+
};
|
|
2350
|
+
return definition;
|
|
2351
|
+
};
|
|
2352
|
+
|
|
2353
|
+
// src/core/lookup.ts
|
|
2354
|
+
init_requestContext();
|
|
2355
|
+
var asset = (source, name) => {
|
|
2356
|
+
const assetPath = source[name];
|
|
2357
|
+
if (assetPath === undefined) {
|
|
2358
|
+
if (isProductionRuntime()) {
|
|
2359
|
+
throw new Error(`Asset "${name}" not found in manifest.`);
|
|
2360
|
+
}
|
|
2361
|
+
recordMissingAsset(name);
|
|
2362
|
+
const page = getDevPageWarmer()?.describe(name);
|
|
2363
|
+
if (page !== undefined && !page.built)
|
|
2364
|
+
return "";
|
|
2365
|
+
console.warn(`[asset] key "${name}" not found in manifest (dev mode \u2014 skipping)`);
|
|
2366
|
+
return "";
|
|
2367
|
+
}
|
|
2368
|
+
return assetPath;
|
|
2369
|
+
};
|
|
2370
|
+
|
|
2192
2371
|
// src/react/pageHandler.ts
|
|
2372
|
+
init_cspNonceRef();
|
|
2193
2373
|
init_islandPageContext();
|
|
2194
2374
|
init_devRouteRegistrationCallsite();
|
|
2195
2375
|
init_requestContext();
|
|
@@ -2199,6 +2379,8 @@ init_pageResponseCache();
|
|
|
2199
2379
|
// src/core/responseEnhancers.ts
|
|
2200
2380
|
init_streamingSlots();
|
|
2201
2381
|
init_pageResponseCache();
|
|
2382
|
+
init_partialPrerender();
|
|
2383
|
+
init_requestContext();
|
|
2202
2384
|
|
|
2203
2385
|
// src/core/streamingSlotRegistrar.ts
|
|
2204
2386
|
var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
|
|
@@ -2241,7 +2423,7 @@ var setStreamingSlotWarningController = (controller) => {
|
|
|
2241
2423
|
Reflect.set(globalThis, STREAMING_SLOT_WARNING_STORAGE_KEY, controller);
|
|
2242
2424
|
};
|
|
2243
2425
|
var warnMissingStreamingSlotCollector = (primitiveName) => {
|
|
2244
|
-
if (isStreamingSlotCollectionActive()) {
|
|
2426
|
+
if (isProductionRuntime() || isStreamingSlotCollectionActive()) {
|
|
2245
2427
|
return;
|
|
2246
2428
|
}
|
|
2247
2429
|
getWarningController()?.maybeWarn(primitiveName);
|
|
@@ -2349,18 +2531,51 @@ var mergeStreamingSlots = (registered, explicit) => {
|
|
|
2349
2531
|
merged.set(slot.id, slot);
|
|
2350
2532
|
return [...merged.values()];
|
|
2351
2533
|
};
|
|
2534
|
+
var captureStaticShell = async (responseLike, slots, options) => {
|
|
2535
|
+
const holes = slots.filter(isDynamicStreamingSlot);
|
|
2536
|
+
const staticSlots = slots.filter((slot) => !isDynamicStreamingSlot(slot));
|
|
2537
|
+
const response = await withStreamingSlots(responseLike, {
|
|
2538
|
+
...options,
|
|
2539
|
+
streamingSlots: staticSlots
|
|
2540
|
+
});
|
|
2541
|
+
if (holes.length === 0 || !response.body)
|
|
2542
|
+
return response;
|
|
2543
|
+
const headers = cloneHeaders(response);
|
|
2544
|
+
headers.set(PARTIAL_HOLES_HEADER, encodePartialHoles(holes.map((slot) => slot.id)));
|
|
2545
|
+
const body = staticSlots.length > 0 ? response.body : injectStreamingRuntimeIntoStream(response.body, options.nonce, options.runtimePlacement, options.runtimePreludeScript);
|
|
2546
|
+
return new Response(body, {
|
|
2547
|
+
headers,
|
|
2548
|
+
status: response.status,
|
|
2549
|
+
statusText: response.statusText
|
|
2550
|
+
});
|
|
2551
|
+
};
|
|
2552
|
+
var handOverHoles = async (responseLike, slots, sink) => {
|
|
2553
|
+
sink.slots = slots.filter(isDynamicStreamingSlot);
|
|
2554
|
+
const response = await toResponse(responseLike);
|
|
2555
|
+
await response.body?.cancel().catch(() => {
|
|
2556
|
+
return;
|
|
2557
|
+
});
|
|
2558
|
+
return new Response(null, { status: 204 });
|
|
2559
|
+
};
|
|
2352
2560
|
var withRegisteredStreamingSlots = async (renderResponse, options = {}) => {
|
|
2353
2561
|
const { result, slots } = await runWithStreamingSlotRegistry(renderResponse);
|
|
2354
2562
|
const explicit = options.streamingSlots ?? [];
|
|
2563
|
+
const streamingSlots = mergeStreamingSlots(slots, explicit);
|
|
2564
|
+
const holesSink = activePartialHolesSink();
|
|
2565
|
+
if (holesSink)
|
|
2566
|
+
return handOverHoles(result, streamingSlots, holesSink);
|
|
2567
|
+
if (isPartialShellCapture(getCurrentAbsoluteRequest())) {
|
|
2568
|
+
return captureStaticShell(result, streamingSlots, options);
|
|
2569
|
+
}
|
|
2355
2570
|
return withStreamingSlots(result, {
|
|
2356
2571
|
...options,
|
|
2357
|
-
streamingSlots
|
|
2572
|
+
streamingSlots
|
|
2358
2573
|
});
|
|
2359
2574
|
};
|
|
2360
2575
|
|
|
2361
2576
|
// src/core/streamingSlotWarningScope.ts
|
|
2362
2577
|
init_logger();
|
|
2363
|
-
import { AsyncLocalStorage as
|
|
2578
|
+
import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
|
|
2364
2579
|
var STREAMING_SLOT_WARNING_STORAGE_KEY2 = Symbol.for("absolutejs.streamingSlotWarningAsyncLocalStorage");
|
|
2365
2580
|
var isObjectRecord4 = (value) => Boolean(value) && typeof value === "object";
|
|
2366
2581
|
var isAsyncLocalStorage3 = (value) => isObjectRecord4(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
|
|
@@ -2376,7 +2591,7 @@ var ensureWarningStorage = () => {
|
|
|
2376
2591
|
if (existing) {
|
|
2377
2592
|
return existing;
|
|
2378
2593
|
}
|
|
2379
|
-
const storage = new
|
|
2594
|
+
const storage = new AsyncLocalStorage4;
|
|
2380
2595
|
Reflect.set(globalThis, STREAMING_SLOT_WARNING_STORAGE_KEY2, storage);
|
|
2381
2596
|
return storage;
|
|
2382
2597
|
};
|
|
@@ -2407,7 +2622,9 @@ setStreamingSlotWarningController({
|
|
|
2407
2622
|
}
|
|
2408
2623
|
});
|
|
2409
2624
|
var captureStreamingSlotWarningCallsite = () => {
|
|
2410
|
-
if (
|
|
2625
|
+
if (isProductionRuntime()) {
|
|
2626
|
+
return;
|
|
2627
|
+
}
|
|
2411
2628
|
const { stack } = new Error;
|
|
2412
2629
|
if (!stack) {
|
|
2413
2630
|
return;
|
|
@@ -2417,6 +2634,7 @@ var captureStreamingSlotWarningCallsite = () => {
|
|
|
2417
2634
|
var runWithStreamingSlotWarningScope = (task, metadata) => ensureWarningStorage().run({ handlerCallsite: metadata?.handlerCallsite, hasWarned: false }, task);
|
|
2418
2635
|
|
|
2419
2636
|
// src/react/pageHandler.ts
|
|
2637
|
+
init_ssrErrorPage();
|
|
2420
2638
|
init_spaRouteManifest();
|
|
2421
2639
|
init_resolveConvention();
|
|
2422
2640
|
init_browserTranslation();
|
|
@@ -2432,7 +2650,9 @@ var resolveRequestPathname = (request) => {
|
|
|
2432
2650
|
}
|
|
2433
2651
|
};
|
|
2434
2652
|
var buildRefreshSetup = () => {
|
|
2435
|
-
if (
|
|
2653
|
+
if (isProductionRuntime()) {
|
|
2654
|
+
return "";
|
|
2655
|
+
}
|
|
2436
2656
|
return "window.__REFRESH_BUFFER__=[];" + "window.$RefreshReg$=function(t,i){window.__REFRESH_BUFFER__.push([t,i])};" + "window.$RefreshSig$=function(){return function(t){return t}};";
|
|
2437
2657
|
};
|
|
2438
2658
|
var handleReactPageRequest = async (input) => {
|
|
@@ -2487,6 +2707,7 @@ var handleReactPageRequest = async (input) => {
|
|
|
2487
2707
|
const stream = await renderToReadableStream(element, {
|
|
2488
2708
|
bootstrapModules: [resolvedIndex],
|
|
2489
2709
|
bootstrapScriptContent: BROWSER_TRANSLATION_BASELINE_SCRIPT + propsScript + refreshSetup,
|
|
2710
|
+
nonce: readCspNonce(),
|
|
2490
2711
|
onError(error) {
|
|
2491
2712
|
console.error("[SSR] React streaming error:", error);
|
|
2492
2713
|
}
|
|
@@ -2518,9 +2739,182 @@ var handleReactPageRequest = async (input) => {
|
|
|
2518
2739
|
}), request);
|
|
2519
2740
|
}
|
|
2520
2741
|
};
|
|
2742
|
+
|
|
2743
|
+
// src/react/fileRoute.ts
|
|
2744
|
+
var isReactComponent = (value) => typeof value === "function" || typeof value === "object" && value !== null && ("$$typeof" in value);
|
|
2745
|
+
var reactFileRoute = (route) => defineFileRouteWith("react", route, async ({ manifest, props, request }) => {
|
|
2746
|
+
const { default: Page } = await route.page();
|
|
2747
|
+
if (!isReactComponent(Page)) {
|
|
2748
|
+
throw new Error(`File route ${route.source} has no default-exported React component.`);
|
|
2749
|
+
}
|
|
2750
|
+
return handleReactPageRequest({
|
|
2751
|
+
index: asset(manifest, `${route.name}Index`),
|
|
2752
|
+
Page,
|
|
2753
|
+
props,
|
|
2754
|
+
request
|
|
2755
|
+
});
|
|
2756
|
+
});
|
|
2757
|
+
// src/react/serverComponents/pageHandler.ts
|
|
2758
|
+
init_cspNonceRef();
|
|
2759
|
+
init_requestContext();
|
|
2760
|
+
init_pageResponseCache();
|
|
2761
|
+
import { readFile } from "fs/promises";
|
|
2762
|
+
import { dirname, join } from "path";
|
|
2763
|
+
init_devRouteRegistrationCallsite();
|
|
2764
|
+
init_ssrErrorPage();
|
|
2765
|
+
init_browserTranslation();
|
|
2766
|
+
|
|
2767
|
+
// src/react/serverComponents/flightPayload.ts
|
|
2768
|
+
init_cspNonceRef();
|
|
2769
|
+
var BODY_OPEN = /<body[\s>]/i;
|
|
2770
|
+
var BODY_CLOSE = "</body>";
|
|
2771
|
+
var escapePayloadChunk = (chunk) => JSON.stringify(chunk).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
2772
|
+
var flightPayloadScript = (chunk, nonce) => `<script${nonceAttr(nonce)}>(self.${REACT_SERVER_PAYLOAD_GLOBAL}??=[]).push(${escapePayloadChunk(chunk)})</script>`;
|
|
2773
|
+
var readText = async (stream, onText) => {
|
|
2774
|
+
const reader = stream.getReader();
|
|
2775
|
+
const decoder = new TextDecoder;
|
|
2776
|
+
const step = async () => {
|
|
2777
|
+
const { done, value } = await reader.read();
|
|
2778
|
+
if (done) {
|
|
2779
|
+
onText(decoder.decode());
|
|
2780
|
+
return;
|
|
2781
|
+
}
|
|
2782
|
+
onText(decoder.decode(value, { stream: true }));
|
|
2783
|
+
await step();
|
|
2784
|
+
};
|
|
2785
|
+
await step();
|
|
2786
|
+
};
|
|
2787
|
+
var takeAll = (pending) => pending.splice(0).join("");
|
|
2788
|
+
var injectFlightPayload = (html, flight, nonce) => {
|
|
2789
|
+
const encoder = new TextEncoder;
|
|
2790
|
+
const pending = [];
|
|
2791
|
+
const flightDone = readText(flight, (text) => {
|
|
2792
|
+
if (text)
|
|
2793
|
+
pending.push(flightPayloadScript(text, nonce));
|
|
2794
|
+
});
|
|
2795
|
+
flightDone.catch(() => {
|
|
2796
|
+
return;
|
|
2797
|
+
});
|
|
2798
|
+
let bodyOpen = false;
|
|
2799
|
+
let tail = "";
|
|
2800
|
+
const handleHtml = (controller, text) => {
|
|
2801
|
+
if (!text)
|
|
2802
|
+
return;
|
|
2803
|
+
if (tail) {
|
|
2804
|
+
tail += text;
|
|
2805
|
+
return;
|
|
2806
|
+
}
|
|
2807
|
+
const closeIndex = text.indexOf(BODY_CLOSE);
|
|
2808
|
+
if (closeIndex >= 0) {
|
|
2809
|
+
tail = text.slice(closeIndex);
|
|
2810
|
+
controller.enqueue(encoder.encode(text.slice(0, closeIndex) + takeAll(pending)));
|
|
2811
|
+
return;
|
|
2812
|
+
}
|
|
2813
|
+
bodyOpen = bodyOpen || BODY_OPEN.test(text);
|
|
2814
|
+
controller.enqueue(encoder.encode(bodyOpen ? text + takeAll(pending) : text));
|
|
2815
|
+
};
|
|
2816
|
+
const pump = async (controller) => {
|
|
2817
|
+
try {
|
|
2818
|
+
await readText(html, (text) => handleHtml(controller, text));
|
|
2819
|
+
await flightDone;
|
|
2820
|
+
controller.enqueue(encoder.encode(takeAll(pending) + tail));
|
|
2821
|
+
controller.close();
|
|
2822
|
+
} catch (error) {
|
|
2823
|
+
controller.error(error);
|
|
2824
|
+
}
|
|
2825
|
+
};
|
|
2826
|
+
return new ReadableStream({
|
|
2827
|
+
start(controller) {
|
|
2828
|
+
pump(controller);
|
|
2829
|
+
}
|
|
2830
|
+
});
|
|
2831
|
+
};
|
|
2832
|
+
|
|
2833
|
+
// src/react/serverComponents/pageHandler.ts
|
|
2834
|
+
var isRecord4 = (value) => typeof value === "object" && value !== null;
|
|
2835
|
+
var isPageModule = (value) => isRecord4(value) && typeof value.Page === "function" && isRecord4(value.clientManifest) && typeof value.createElement === "function" && typeof value.renderToReadableStream === "function";
|
|
2836
|
+
var isRendererModule = (value) => isRecord4(value) && typeof value.renderHtml === "function";
|
|
2837
|
+
var isRuntime = (value) => isRecord4(value) && typeof value.client === "string" && typeof value.ssr === "string";
|
|
2838
|
+
var runtimeCache = new Map;
|
|
2839
|
+
var loadRuntime = async (pagePath) => {
|
|
2840
|
+
const runtimeDir = dirname(pagePath);
|
|
2841
|
+
const parsed = JSON.parse(await readFile(join(runtimeDir, REACT_SERVER_RUNTIME_FILE), "utf8"));
|
|
2842
|
+
if (!isRuntime(parsed)) {
|
|
2843
|
+
throw new Error(`Invalid ${REACT_SERVER_RUNTIME_FILE} in ${runtimeDir}`);
|
|
2844
|
+
}
|
|
2845
|
+
return { client: parsed.client, ssr: join(runtimeDir, parsed.ssr) };
|
|
2846
|
+
};
|
|
2847
|
+
var readRuntime = (pagePath) => {
|
|
2848
|
+
if (!isProductionRuntime())
|
|
2849
|
+
return loadRuntime(pagePath);
|
|
2850
|
+
const cached = runtimeCache.get(pagePath);
|
|
2851
|
+
if (cached)
|
|
2852
|
+
return cached;
|
|
2853
|
+
const loading = loadRuntime(pagePath);
|
|
2854
|
+
runtimeCache.set(pagePath, loading);
|
|
2855
|
+
loading.catch(() => runtimeCache.delete(pagePath));
|
|
2856
|
+
return loading;
|
|
2857
|
+
};
|
|
2858
|
+
var loadPageModule = async (pagePath) => {
|
|
2859
|
+
const loaded = await import(pagePath);
|
|
2860
|
+
if (!isPageModule(loaded)) {
|
|
2861
|
+
throw new Error(`${pagePath} is not a React Server Components page bundle. Pass asset(manifest, "<Page>RSC") and give the page a default export.`);
|
|
2862
|
+
}
|
|
2863
|
+
return loaded;
|
|
2864
|
+
};
|
|
2865
|
+
var loadRenderer = async (rendererPath) => {
|
|
2866
|
+
const loaded = await import(rendererPath);
|
|
2867
|
+
if (!isRendererModule(loaded)) {
|
|
2868
|
+
throw new Error(`${rendererPath} is not a React Server Components renderer.`);
|
|
2869
|
+
}
|
|
2870
|
+
return loaded;
|
|
2871
|
+
};
|
|
2872
|
+
var logRenderError = (error) => {
|
|
2873
|
+
console.error("[SSR] React Server Components error:", error);
|
|
2874
|
+
};
|
|
2875
|
+
var handleReactServerPageRequest = async (input) => {
|
|
2876
|
+
const request = input.request ?? getCurrentAbsoluteRequest();
|
|
2877
|
+
if (input.page === "") {
|
|
2878
|
+
throw new Error("React Server Components page bundle not found in manifest. Is reactServerComponentsDirectory set in absolute.config.ts?");
|
|
2879
|
+
}
|
|
2880
|
+
try {
|
|
2881
|
+
const handlerCallsite = input.collectStreamingSlots === true ? undefined : getCurrentRouteRegistrationCallsite() ?? captureStreamingSlotWarningCallsite();
|
|
2882
|
+
const renderPageResponse = async () => {
|
|
2883
|
+
const [pageModule, runtime] = await Promise.all([
|
|
2884
|
+
loadPageModule(input.page),
|
|
2885
|
+
readRuntime(input.page)
|
|
2886
|
+
]);
|
|
2887
|
+
const renderer = await loadRenderer(runtime.ssr);
|
|
2888
|
+
const nonce = readCspNonce();
|
|
2889
|
+
const flight = pageModule.renderToReadableStream(pageModule.createElement(pageModule.Page, input.props ?? {}), pageModule.clientManifest, { onError: logRenderError });
|
|
2890
|
+
const [forHtml, forPayload] = flight.tee();
|
|
2891
|
+
const html = await renderer.renderHtml(forHtml, {
|
|
2892
|
+
bootstrapModules: [runtime.client],
|
|
2893
|
+
bootstrapScriptContent: BROWSER_TRANSLATION_BASELINE_SCRIPT,
|
|
2894
|
+
nonce,
|
|
2895
|
+
onError: logRenderError
|
|
2896
|
+
});
|
|
2897
|
+
return new Response(injectFlightPayload(html, forPayload, nonce), {
|
|
2898
|
+
headers: streamingPageHeaders()
|
|
2899
|
+
});
|
|
2900
|
+
};
|
|
2901
|
+
const pageResponse = await runWithStreamingSlotWarningScope(() => input.collectStreamingSlots === true ? withRegisteredStreamingSlots(renderPageResponse, input) : renderPageResponse(), { handlerCallsite });
|
|
2902
|
+
return withPageCacheHeaders(pageResponse, request, {
|
|
2903
|
+
bufferStreamForEtag: input.bufferStreamForEtag
|
|
2904
|
+
});
|
|
2905
|
+
} catch (error) {
|
|
2906
|
+
logRenderError(error);
|
|
2907
|
+
return withPageCacheHeaders(new Response(ssrErrorPage("react", error), {
|
|
2908
|
+
headers: { "Content-Type": "text/html" },
|
|
2909
|
+
status: 500
|
|
2910
|
+
}), request);
|
|
2911
|
+
}
|
|
2912
|
+
};
|
|
2521
2913
|
export {
|
|
2522
|
-
handleReactPageRequest
|
|
2914
|
+
handleReactPageRequest,
|
|
2915
|
+
handleReactServerPageRequest,
|
|
2916
|
+
reactFileRoute
|
|
2523
2917
|
};
|
|
2524
2918
|
|
|
2525
|
-
//# debugId=
|
|
2919
|
+
//# debugId=E1D3F509BEBDEF2C64756E2164756E21
|
|
2526
2920
|
//# sourceMappingURL=server.js.map
|