@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.
Files changed (238) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +232 -0
  3. package/changelog.json +228 -0
  4. package/dist/angular/browser.js +7 -8
  5. package/dist/angular/browser.js.map +6 -5
  6. package/dist/angular/components/core/streamingSlotRegistrar.js +6 -2
  7. package/dist/angular/components/core/streamingSlotRegistry.js +7 -3
  8. package/dist/angular/index.js +555 -156
  9. package/dist/angular/index.js.map +29 -23
  10. package/dist/angular/server.js +555 -156
  11. package/dist/angular/server.js.map +29 -23
  12. package/dist/build/buildWorker.js +14 -8
  13. package/dist/build.js +4949 -1941
  14. package/dist/build.js.map +72 -42
  15. package/dist/cli/{add-7azr0c83.js → add-6a7pjkn9.js} +11 -7
  16. package/dist/cli/{analyze-3cyek6v3.js → analyze-606fshwa.js} +1 -1
  17. package/dist/cli/{build-25rz8v25.js → build-g81xqbb9.js} +1 -1
  18. package/dist/cli/{compile-4jnfxts9.js → compile-9y1w9zpj.js} +3 -3
  19. package/dist/cli/config/server.js +10699 -1538
  20. package/dist/cli/{dev-9tk5hn2e.js → dev-hyeb89hp.js} +5 -1
  21. package/dist/cli/{doctor-4nv2c2j3.js → doctor-h55y9hj1.js} +1 -1
  22. package/dist/cli/{generate-v75p2fct.js → generate-20x1pkf7.js} +4 -4
  23. package/dist/cli/{htmx-427swtdz.js → htmx-6mz2h7k1.js} +2 -2
  24. package/dist/cli/{index-bhbs6d5z.js → index-32ge2w1f.js} +12 -4
  25. package/dist/cli/{index-a4ws2jwd.js → index-3wz3mktm.js} +1 -1
  26. package/dist/cli/{index-b7hjgknf.js → index-9sksd8c8.js} +13 -4
  27. package/dist/cli/{index-eyzwc7gz.js → index-qbrzvmh9.js} +4 -2
  28. package/dist/cli/index-qw98g1p6.js +269 -0
  29. package/dist/cli/{index-434b7j4a.js → index-vtp20gwf.js} +69 -1
  30. package/dist/cli/{index-h7qhz02e.js → index-wk0pyxrg.js} +3 -0
  31. package/dist/cli/{index-k3y8cb6c.js → index-z6f43b20.js} +1 -1
  32. package/dist/cli/index.js +16 -16
  33. package/dist/cli/{islands-8sgky9gh.js → islands-dc54e5y1.js} +1 -1
  34. package/dist/cli/{ls-4m4yqwww.js → ls-b6zz24nt.js} +1 -1
  35. package/dist/cli/{mobile-hcxjr2gf.js → mobile-ajnnvqtv.js} +3 -3
  36. package/dist/cli/prerender-fqpp0m1j.js +10 -0
  37. package/dist/cli/{remove-1ycjx85k.js → remove-t8x1mrxg.js} +4 -4
  38. package/dist/cli/{start-mbaejxhm.js → start-d6p831ny.js} +3 -3
  39. package/dist/cli/{typecheck-dr068pmh.js → typecheck-stbt0qt5.js} +6 -1
  40. package/dist/cli/{workspace-1sycp9g1.js → workspace-61hh6jq1.js} +1 -1
  41. package/dist/client/chunks/index-6b66nzyf.js +381 -0
  42. package/dist/client/chunks/index-6b66nzyf.js.map +11 -0
  43. package/dist/client/chunks/{islands-rc28k5sx.js → islands-s2ta5ajb.js} +5 -2
  44. package/dist/client/chunks/{islands-rc28k5sx.js.map → islands-s2ta5ajb.js.map} +7 -6
  45. package/dist/client/index.js +160 -3
  46. package/dist/client/index.js.map +6 -4
  47. package/dist/client/navigation.js +764 -0
  48. package/dist/client/navigation.js.map +10 -0
  49. package/dist/client/prefetch.js +33 -375
  50. package/dist/client/prefetch.js.map +3 -4
  51. package/dist/core/streamingSlotRegistrar.js +5 -2
  52. package/dist/core/streamingSlotRegistrar.js.map +5 -4
  53. package/dist/core/streamingSlotRegistry.js +5 -2
  54. package/dist/core/streamingSlotRegistry.js.map +5 -4
  55. package/dist/dev/client/cspNonce.ts +28 -0
  56. package/dist/dev/client/handlers/html.ts +4 -3
  57. package/dist/dev/client/handlers/htmx.ts +3 -2
  58. package/dist/dev/client/handlers/svelte.ts +15 -90
  59. package/dist/dev/client/syncDevtools.ts +2 -1
  60. package/dist/dev/serverBootstrap.js +11 -4
  61. package/dist/i18n/index.js +543 -0
  62. package/dist/i18n/index.js.map +15 -0
  63. package/dist/index.js +6339 -2233
  64. package/dist/index.js.map +89 -54
  65. package/dist/islands/index.js +282 -40
  66. package/dist/islands/index.js.map +14 -10
  67. package/dist/mobile/browser.js +7 -2
  68. package/dist/mobile/browser.js.map +5 -4
  69. package/dist/mobile/index.js +7 -2
  70. package/dist/mobile/index.js.map +5 -4
  71. package/dist/mobile/remoteMacAgentEntry.js +1 -1
  72. package/dist/react/components/browser/index.js +94 -4
  73. package/dist/react/components/index.js +150 -10
  74. package/dist/react/components/index.js.map +15 -10
  75. package/dist/react/hooks/index.js +479 -13
  76. package/dist/react/hooks/index.js.map +12 -4
  77. package/dist/react/index.js +769 -166
  78. package/dist/react/index.js.map +32 -21
  79. package/dist/react/router/browser.js +21 -4
  80. package/dist/react/router/browser.js.map +5 -4
  81. package/dist/react/router/index.js +21 -4
  82. package/dist/react/router/index.js.map +5 -4
  83. package/dist/react/server.js +597 -203
  84. package/dist/react/server.js.map +25 -15
  85. package/dist/src/angular/zoneRuntime.d.ts +5 -0
  86. package/dist/src/build/buildReactServerComponents.d.ts +22 -0
  87. package/dist/src/build/downlevelAsyncForZone.d.ts +1 -0
  88. package/dist/src/build/fileRoutes.d.ts +65 -0
  89. package/dist/src/build/fonts/buildFonts.d.ts +25 -0
  90. package/dist/src/build/fonts/fallbackMetrics.d.ts +13 -0
  91. package/dist/src/build/fonts/googleFonts.d.ts +18 -0
  92. package/dist/src/build/fonts/injectFontTags.d.ts +7 -0
  93. package/dist/src/build/fonts/parseFontMetrics.d.ts +4 -0
  94. package/dist/src/build/generateReactIndexes.d.ts +7 -1
  95. package/dist/src/build/htmlIncludes.d.ts +16 -0
  96. package/dist/src/build/inlineSourceMapComment.d.ts +1 -0
  97. package/dist/src/build/scanConventions.d.ts +3 -0
  98. package/dist/src/build/vitals.d.ts +21 -0
  99. package/dist/src/client/formActions.d.ts +29 -0
  100. package/dist/src/client/index.d.ts +2 -0
  101. package/dist/src/client/navigation.d.ts +16 -0
  102. package/dist/src/client/prefetch.d.ts +2 -30
  103. package/dist/src/core/build.d.ts +2 -2
  104. package/dist/src/core/cspNonce.d.ts +12 -0
  105. package/dist/src/core/fileRouteAdapter.d.ts +15 -0
  106. package/dist/src/core/fileRoutes.d.ts +5 -0
  107. package/dist/src/core/formActionFlash.d.ts +25 -0
  108. package/dist/src/core/formActions.d.ts +249 -0
  109. package/dist/src/core/index.d.ts +5 -0
  110. package/dist/src/core/partialPrerender.d.ts +28 -0
  111. package/dist/src/core/partialPrerenderServe.d.ts +24 -0
  112. package/dist/src/core/precompressed.d.ts +11 -1
  113. package/dist/src/core/prerenderNonce.d.ts +9 -0
  114. package/dist/src/core/productionRuntime.d.ts +4 -2
  115. package/dist/src/core/serverOnlyStaticFiles.d.ts +8 -0
  116. package/dist/src/core/staticHtmlNonce.d.ts +2 -0
  117. package/dist/src/core/vitals.d.ts +108 -0
  118. package/dist/src/dev/angular/fastHmrCompiler.d.ts +1 -1
  119. package/dist/src/dev/client/cspNonce.d.ts +2 -0
  120. package/dist/src/dev/fileRouteRefresher.d.ts +5 -0
  121. package/dist/src/dev/importCost/instrument.d.ts +1 -1
  122. package/dist/src/dev/reactServerComponentsRebuild.d.ts +3 -0
  123. package/dist/src/i18n/defineMessages.d.ts +5 -0
  124. package/dist/src/i18n/formatMessage.d.ts +26 -0
  125. package/dist/src/i18n/index.d.ts +6 -0
  126. package/dist/src/i18n/intlCache.d.ts +5 -0
  127. package/dist/src/i18n/routing.d.ts +28 -0
  128. package/dist/src/i18n/translator.d.ts +11 -0
  129. package/dist/src/mobile/androidRelease.d.ts +2 -2
  130. package/dist/src/mobile/iosRelease.d.ts +4 -4
  131. package/dist/src/mobile/materializedBundle.d.ts +1 -1
  132. package/dist/src/mobile/mobileInspect.d.ts +1 -1
  133. package/dist/src/mobile/releaseArtifact.d.ts +2 -2
  134. package/dist/src/mobile/remoteMacProtocol.d.ts +2 -2
  135. package/dist/src/plugins/i18n.d.ts +30 -0
  136. package/dist/src/plugins/index.d.ts +2 -1
  137. package/dist/src/plugins/secureHeaders.d.ts +48 -0
  138. package/dist/src/react/components/Head.d.ts +1 -1
  139. package/dist/src/react/components/StreamSlot.browser.d.ts +1 -0
  140. package/dist/src/react/components/StreamSlot.d.ts +5 -1
  141. package/dist/src/react/components/SuspenseSlot.browser.d.ts +2 -0
  142. package/dist/src/react/components/SuspenseSlot.d.ts +12 -0
  143. package/dist/src/react/fileRoute.d.ts +18 -0
  144. package/dist/src/react/hooks/index.d.ts +4 -0
  145. package/dist/src/react/hooks/useFormAction.d.ts +42 -0
  146. package/dist/src/react/hooks/useI18n.d.ts +15 -0
  147. package/dist/src/react/index.d.ts +2 -0
  148. package/dist/src/react/server.d.ts +2 -0
  149. package/dist/src/react/serverComponents/constants.d.ts +11 -0
  150. package/dist/src/react/serverComponents/flightPayload.d.ts +2 -0
  151. package/dist/src/react/serverComponents/pageHandler.d.ts +14 -0
  152. package/dist/src/svelte/browser.d.ts +1 -0
  153. package/dist/src/svelte/fileRoute.d.ts +15 -0
  154. package/dist/src/svelte/i18n.d.ts +8 -0
  155. package/dist/src/svelte/index.d.ts +2 -0
  156. package/dist/src/svelte/lowerAwaitSlotSyntax.d.ts +5 -1
  157. package/dist/src/svelte/renderToReadableStream.d.ts +10 -2
  158. package/dist/src/svelte/router/browser.d.ts +3 -1
  159. package/dist/src/svelte/router/goto.d.ts +13 -10
  160. package/dist/src/svelte/router/guards.d.ts +43 -0
  161. package/dist/src/svelte/router/index.d.ts +3 -1
  162. package/dist/src/svelte/router/lazy.d.ts +17 -0
  163. package/dist/src/svelte/router/lazyModule.d.ts +29 -0
  164. package/dist/src/svelte/router/navigation.d.ts +55 -0
  165. package/dist/src/svelte/router/pushState.d.ts +4 -2
  166. package/dist/src/svelte/router/scroll.d.ts +34 -0
  167. package/dist/src/svelte/routerSsr.d.ts +9 -0
  168. package/dist/src/svelte/server.d.ts +1 -0
  169. package/dist/src/utils/cspNonceRef.d.ts +8 -0
  170. package/dist/src/utils/fontAssets.d.ts +17 -0
  171. package/dist/src/utils/formActionProtocol.d.ts +10 -0
  172. package/dist/src/utils/generateHeadElement.d.ts +1 -1
  173. package/dist/src/utils/index.d.ts +1 -0
  174. package/dist/src/utils/inlinePageCss.d.ts +18 -0
  175. package/dist/src/utils/loadConfig.d.ts +5 -0
  176. package/dist/src/utils/localeRef.d.ts +10 -0
  177. package/dist/src/utils/resolveConvention.d.ts +6 -1
  178. package/dist/src/utils/streamingSlots.d.ts +5 -0
  179. package/dist/src/vue/browser.d.ts +2 -0
  180. package/dist/src/vue/components/Image.d.ts +2 -2
  181. package/dist/src/vue/index.d.ts +2 -0
  182. package/dist/src/vue/serverDataPayload.d.ts +32 -0
  183. package/dist/src/vue/serverDataState.d.ts +9 -0
  184. package/dist/src/vue/useServerData.browser.d.ts +6 -0
  185. package/dist/src/vue/useServerData.d.ts +24 -0
  186. package/dist/svelte/browser.js +330 -3
  187. package/dist/svelte/browser.js.map +8 -4
  188. package/dist/svelte/components/AwaitSlot.svelte +5 -0
  189. package/dist/svelte/components/Head.svelte +50 -0
  190. package/dist/svelte/components/JsonLd.svelte +9 -1
  191. package/dist/svelte/components/StreamSlot.svelte +5 -0
  192. package/dist/svelte/index.js +1017 -117
  193. package/dist/svelte/index.js.map +38 -24
  194. package/dist/svelte/router/Link.svelte +40 -8
  195. package/dist/svelte/router/Route.svelte +157 -12
  196. package/dist/svelte/router/Route.svelte.d.ts +39 -5
  197. package/dist/svelte/router/Router.svelte +140 -25
  198. package/dist/svelte/router/Router.svelte.d.ts +5 -1
  199. package/dist/svelte/router/browser.ts +10 -0
  200. package/dist/svelte/router/goto.ts +15 -86
  201. package/dist/svelte/router/guards.ts +112 -0
  202. package/dist/svelte/router/index.ts +10 -0
  203. package/dist/svelte/router/lazy.ts +82 -0
  204. package/dist/svelte/router/lazyModule.ts +74 -0
  205. package/dist/svelte/router/navigation.ts +412 -0
  206. package/dist/svelte/router/pushState.ts +7 -4
  207. package/dist/svelte/router/scroll.ts +286 -0
  208. package/dist/svelte/server.js +747 -252
  209. package/dist/svelte/server.js.map +30 -20
  210. package/dist/types/angular.d.ts +2 -0
  211. package/dist/types/build.d.ts +37 -0
  212. package/dist/types/conventions.d.ts +3 -0
  213. package/dist/types/fileRoutes.d.ts +72 -0
  214. package/dist/types/fonts.d.ts +86 -0
  215. package/dist/types/formAction.d.ts +54 -0
  216. package/dist/types/globals.d.ts +10 -0
  217. package/dist/types/i18n.d.ts +185 -0
  218. package/dist/types/index.d.ts +4 -0
  219. package/dist/types/metadata.d.ts +11 -0
  220. package/dist/types/navigation.d.ts +37 -0
  221. package/dist/types/prefetch.d.ts +10 -0
  222. package/dist/types/sitemap.d.ts +4 -0
  223. package/dist/types/svelteRouter.d.ts +89 -2
  224. package/dist/types/svelteRouter.ts +112 -2
  225. package/dist/types/vue.d.ts +46 -1
  226. package/dist/utils/iconVersion.ts +34 -0
  227. package/dist/vue/browser.js +107 -11
  228. package/dist/vue/browser.js.map +7 -4
  229. package/dist/vue/components/index.js +5 -2
  230. package/dist/vue/components/index.js.map +5 -4
  231. package/dist/vue/index.js +712 -158
  232. package/dist/vue/index.js.map +32 -23
  233. package/dist/vue/server.js +310 -79
  234. package/dist/vue/server.js.map +20 -15
  235. package/package.json +9 -1
  236. package/dist/cli/prerender-mfnwsvyt.js +0 -7
  237. package/dist/src/plugins/pageRouter.d.ts +0 -1
  238. /package/dist/cli/{index-j7m8pq48.js → index-rervww4p.js} +0 -0
@@ -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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")}</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 (false)
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 AsyncLocalStorage;
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 } = Elysia;
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")}</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 (false) {}
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, 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) => nonce ? ` nonce="${nonce}"` : "", createStreamingSlotId = () => `${SLOT_ID_PREFIX}${Math.random().toString(BASE_36_RADIX).slice(2, RANDOM_ID_END_INDEX)}`, getStreamingSlotsRuntimeScript = () => getStreamSwapRuntimeScript(), injectHtmlIntoBody = (html, injection) => {
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 content = tail.slice(0, tail.length - STREAM_TAIL_LOOKBEHIND);
1573
- controller.enqueue(encoder.encode(content));
1574
- return tail.slice(-STREAM_TAIL_LOOKBEHIND);
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 = () => true, buildErrorProps = (error) => {
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(/&quot;/g, '"').replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">")}</style>`;
2018
+ styles += `<style${nonceAttr()}>${css.replace(/&quot;/g, '"').replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;"), 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 { head, body } = render(NotFoundComponent);
2003
- const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
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: mergeStreamingSlots(slots, explicit)
2572
+ streamingSlots
2358
2573
  });
2359
2574
  };
2360
2575
 
2361
2576
  // src/core/streamingSlotWarningScope.ts
2362
2577
  init_logger();
2363
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
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 AsyncLocalStorage3;
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 (false) {}
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 (false) {}
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=D81C9C0FCE9C30E864756E2164756E21
2919
+ //# debugId=E1D3F509BEBDEF2C64756E2164756E21
2526
2920
  //# sourceMappingURL=server.js.map