@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,180 @@ 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
+
75
249
  // src/build/resolvePackageImport.ts
76
250
  import { resolve, join } from "path";
77
251
  import { existsSync, readFileSync } from "fs";
@@ -220,47 +394,140 @@ var init_lowerIslandSyntax = __esm(() => {
220
394
  });
221
395
 
222
396
  // src/svelte/lowerAwaitSlotSyntax.ts
223
- var AWAIT_BLOCK_RE, escapeTemplateLiteral = (value) => value.replaceAll("\\", "\\\\").replaceAll("`", "\\`").replaceAll("${", "\\${"), markupToTemplateLiteral = (markup) => {
224
- const escaped = escapeTemplateLiteral(markup.trim());
225
- const withExpressions = escaped.replace(/\{([^{}]+)\}/g, (_, expression) => `\${${String(expression).trim()}}`);
226
- return `\`${withExpressions}\``;
227
- }, lowerSvelteAwaitSlotSyntax = (source) => {
228
- if (!source.includes("{#await")) {
397
+ var AWAIT_STREAM_DIRECTIVE = "<!-- absolute:stream -->", DIRECTIVE_RE, BRANCH_TAG_RE, SVELTE_ONLY_MARKUP_RE, QUOTES, scanCharacter = (scan, char) => {
398
+ if (scan.escaped) {
399
+ scan.escaped = false;
400
+ return;
401
+ }
402
+ if (scan.quote) {
403
+ scan.escaped = char === "\\";
404
+ if (char === scan.quote)
405
+ scan.quote = null;
406
+ return;
407
+ }
408
+ if (QUOTES.has(char))
409
+ scan.quote = char;
410
+ if (char === "{")
411
+ scan.depth += 1;
412
+ if (char === "}")
413
+ scan.depth -= 1;
414
+ }, findTagEnd = (source, start) => {
415
+ const scan = { depth: 0, escaped: false, quote: null };
416
+ for (let index = start;index < source.length; index += 1) {
417
+ scanCharacter(scan, source[index] ?? "");
418
+ if (scan.depth === 0)
419
+ return index + 1;
420
+ }
421
+ return -1;
422
+ }, topLevelTags = (markup) => {
423
+ const tags = [];
424
+ let index = markup.indexOf("{");
425
+ while (index !== -1) {
426
+ const end = findTagEnd(markup, index);
427
+ if (end === -1)
428
+ break;
429
+ tags.push({ end, start: index, text: markup.slice(index, end) });
430
+ index = markup.indexOf("{", end);
431
+ }
432
+ return tags;
433
+ }, escapeTemplateLiteral = (value) => value.replaceAll("\\", "\\\\").replaceAll("`", "\\`").replaceAll("${", "\\${"), markupToTemplateLiteral = (markup) => {
434
+ const parts = topLevelTags(markup.trim());
435
+ const trimmed = markup.trim();
436
+ let cursor = 0;
437
+ let literal = "";
438
+ for (const { end, start, text } of parts) {
439
+ literal += escapeTemplateLiteral(trimmed.slice(cursor, start));
440
+ literal += `\${${text.slice(1, -1).trim()}}`;
441
+ cursor = end;
442
+ }
443
+ literal += escapeTemplateLiteral(trimmed.slice(cursor));
444
+ return `\`${literal}\``;
445
+ }, fail = (filePath, message) => {
446
+ throw new Error(`${filePath ? `${filePath}: ` : ""}${message} (${AWAIT_STREAM_DIRECTIVE} streams plain HTML; remove the directive to let Svelte render the block and hydrate it)`);
447
+ }, assertPlainHtml = (markup, branch, filePath) => {
448
+ const withoutExpressions = topLevelTags(markup).reduceRight((text, { end, start }) => text.slice(0, start) + text.slice(end), markup);
449
+ const nestedTag = topLevelTags(markup).find(({ text }) => /^\{[#:/@]/.test(text));
450
+ if (nestedTag || SVELTE_ONLY_MARKUP_RE.test(withoutExpressions)) {
451
+ fail(filePath, `the ${branch} branch of a streamed {#await} holds Svelte markup (${nestedTag?.text ?? withoutExpressions.match(SVELTE_ONLY_MARKUP_RE)?.[0]}\u2026)`);
452
+ }
453
+ }, parseStreamedAwait = (source, start, filePath) => {
454
+ if (!source.startsWith("{#await", start)) {
455
+ fail(filePath, `${AWAIT_STREAM_DIRECTIVE} must come directly before an {#await} block`);
456
+ }
457
+ const headerEnd = findTagEnd(source, start);
458
+ if (headerEnd === -1)
459
+ fail(filePath, "unterminated {#await} tag");
460
+ const expression = source.slice(start + "{#await".length, headerEnd - 1).trim();
461
+ if (!expression)
462
+ fail(filePath, "{#await} without an expression");
463
+ if (/\s(?:then|catch)\b/.test(` ${expression}`)) {
464
+ fail(filePath, "a streamed {#await} needs a pending branch; the shorthand {#await \u2026 then \u2026} has none");
465
+ }
466
+ const close = source.indexOf("{/await}", headerEnd);
467
+ if (close === -1)
468
+ fail(filePath, "{#await} without a matching {/await}");
469
+ const body = source.slice(headerEnd, close);
470
+ const branchTags = topLevelTags(body).filter(({ text }) => /^\{:/.test(text));
471
+ const [thenTag, catchTag, extra] = branchTags;
472
+ const thenMatch = thenTag?.text.match(BRANCH_TAG_RE);
473
+ const catchMatch = catchTag?.text.match(BRANCH_TAG_RE);
474
+ if (!thenTag || thenMatch?.[1] !== "then" || catchTag && catchMatch?.[1] !== "catch" || extra) {
475
+ fail(filePath, "a streamed {#await} takes exactly one {:then} and at most one {:catch}, in that order");
476
+ }
477
+ const pendingMarkup = body.slice(0, thenTag?.start);
478
+ const thenMarkup = body.slice(thenTag?.end, catchTag?.start);
479
+ const catchMarkup = catchTag ? body.slice(catchTag.end) : undefined;
480
+ assertPlainHtml(pendingMarkup, "pending", filePath);
481
+ assertPlainHtml(thenMarkup, "then", filePath);
482
+ if (catchMarkup !== undefined)
483
+ assertPlainHtml(catchMarkup, "catch", filePath);
484
+ return {
485
+ catchIdentifier: catchMatch?.[2],
486
+ catchMarkup,
487
+ end: close + "{/await}".length,
488
+ expression,
489
+ pendingMarkup,
490
+ thenIdentifier: thenMatch?.[2],
491
+ thenMarkup
492
+ };
493
+ }, renderSlot = (block, slotId, dynamic) => {
494
+ const thenValueIdentifier = block.thenIdentifier ?? "__awaitValue";
495
+ const catchValueIdentifier = block.catchIdentifier ?? "__awaitError";
496
+ const catchBranch = block.catchMarkup === undefined ? "catch (_absoluteAwaitError) { throw _absoluteAwaitError; }" : `catch (${catchValueIdentifier}) { return ${markupToTemplateLiteral(block.catchMarkup)}; }`;
497
+ return `<AbsoluteAwaitSlot id="${slotId}"${dynamic ? " dynamic" : ""} fallbackHtml={${markupToTemplateLiteral(block.pendingMarkup)}} resolve={async () => { try { const ${thenValueIdentifier} = await (${block.expression}); return ${markupToTemplateLiteral(block.thenMarkup)}; } ${catchBranch} }} />`;
498
+ }, IMPORT_LINE = 'import AbsoluteAwaitSlot from "@absolutejs/absolute/svelte/components/AwaitSlot.svelte";', lowerSvelteAwaitSlotSyntax = (source, filePath) => {
499
+ if (!source.includes("absolute:stream")) {
229
500
  return { code: source, transformed: false };
230
501
  }
502
+ let lowered = "";
503
+ let cursor = 0;
231
504
  let awaitIndex = 0;
232
- let transformed = false;
233
- const lowered = source.replace(AWAIT_BLOCK_RE, (fullMatch, awaitExpression, pendingMarkup, thenIdentifier, thenMarkup, catchIdentifier, catchMarkup) => {
234
- const trimmedAwaitExpression = awaitExpression.trim();
235
- if (!trimmedAwaitExpression) {
236
- return fullMatch;
237
- }
505
+ for (const directive of source.matchAll(DIRECTIVE_RE)) {
506
+ const awaitStart = directive.index + directive[0].length;
507
+ if (awaitStart < cursor)
508
+ continue;
509
+ const block = parseStreamedAwait(source, awaitStart, filePath);
238
510
  const slotId = `absolute-svelte-await-${awaitIndex.toString(BASE_36_RADIX)}`;
239
511
  awaitIndex += 1;
240
- transformed = true;
241
- const thenValueIdentifier = thenIdentifier?.trim() || "__awaitValue";
242
- const catchValueIdentifier = catchIdentifier?.trim() || "__awaitError";
243
- const fallbackHtml = markupToTemplateLiteral(pendingMarkup);
244
- const resolvedHtml = markupToTemplateLiteral(thenMarkup);
245
- const rejectedHtml = typeof catchMarkup === "string" ? markupToTemplateLiteral(catchMarkup) : null;
246
- const catchBranch = rejectedHtml ? `catch (${catchValueIdentifier}) { return ${rejectedHtml}; }` : "catch (_absoluteAwaitError) { throw _absoluteAwaitError; }";
247
- return `<AbsoluteAwaitSlot id="${slotId}" fallbackHtml={${fallbackHtml}} resolve={async () => { try { const ${thenValueIdentifier} = await (${trimmedAwaitExpression}); return ${resolvedHtml}; } ${catchBranch} }} />`;
248
- });
249
- if (!transformed) {
512
+ lowered += source.slice(cursor, directive.index);
513
+ lowered += renderSlot(block, slotId, directive[1] !== undefined);
514
+ cursor = block.end;
515
+ }
516
+ if (awaitIndex === 0) {
250
517
  return { code: source, transformed: false };
251
518
  }
252
- const importLine = 'import AbsoluteAwaitSlot from "@absolutejs/absolute/svelte/components/AwaitSlot.svelte";';
519
+ lowered += source.slice(cursor);
253
520
  if (lowered.includes("<script")) {
254
521
  return {
255
522
  code: lowered.replace(/<script(\s[^>]*)?>/, (match) => `${match}
256
- ${importLine}
523
+ ${IMPORT_LINE}
257
524
  `),
258
525
  transformed: true
259
526
  };
260
527
  }
261
528
  return {
262
529
  code: `<script lang="ts">
263
- ${importLine}
530
+ ${IMPORT_LINE}
264
531
  </script>
265
532
  ${lowered}`,
266
533
  transformed: true
@@ -268,7 +535,10 @@ ${lowered}`,
268
535
  };
269
536
  var init_lowerAwaitSlotSyntax = __esm(() => {
270
537
  init_constants();
271
- AWAIT_BLOCK_RE = /\{#await\s+([^}]+)\}([\s\S]*?)\{:then(?:\s+([A-Za-z_$][\w$]*))?\}([\s\S]*?)(?:\{:catch(?:\s+([A-Za-z_$][\w$]*))?\}([\s\S]*?))?\{\/await\}/g;
538
+ DIRECTIVE_RE = /<!--\s*absolute:stream(\s+dynamic)?\s*-->\s*/g;
539
+ BRANCH_TAG_RE = /^\{:(then|catch)(?:\s+([A-Za-z_$][\w$]*))?\s*\}$/;
540
+ SVELTE_ONLY_MARKUP_RE = /\{[#:/@]|<[A-Z]|<svelte:/;
541
+ QUOTES = new Set(['"', "'", "`"]);
272
542
  });
273
543
 
274
544
  // src/build/stylePreprocessor.ts
@@ -460,7 +730,7 @@ ${contents}` : contents, normalizePostcssModule = (mod) => {
460
730
  const config = normalizePostcssModule(loaded);
461
731
  const value = typeof config === "function" ? await config({
462
732
  cwd: process.cwd(),
463
- env: "development"
733
+ env: getNodeEnv()
464
734
  }) : config;
465
735
  return normalizePostcssModule(value) ?? {};
466
736
  }, normalizePostcssPlugins = (plugins) => {
@@ -826,10 +1096,10 @@ ${contents}` : contents, normalizePostcssModule = (mod) => {
826
1096
  return resolveCssImportsSync(result.css, dirname(filePath), new Set([filePath]));
827
1097
  }
828
1098
  if (language === "less") {
829
- throw new Error(`Unable to compile ${filePath}: Less styleUrl preprocessing is async-only. Import the Less file from a bundled entrypoint or use SCSS/CSS for Angular styleUrl.`);
1099
+ throw new Error(`Unable to compile ${filePath} synchronously: Less only has an async compiler. Compile it with compileStyleFileIfNeeded() instead.`);
830
1100
  }
831
1101
  if (language === "stylus") {
832
- throw new Error(`Unable to compile ${filePath}: Stylus styleUrl preprocessing is async-only. Import the Stylus file from a bundled entrypoint or use SCSS/CSS for Angular styleUrl.`);
1102
+ throw new Error(`Unable to compile ${filePath} synchronously: Stylus only has an async compiler. Compile it with compileStyleFileIfNeeded() instead.`);
833
1103
  }
834
1104
  return resolveCssImportsSync(rawContents, dirname(filePath), new Set([filePath]));
835
1105
  };
@@ -847,6 +1117,32 @@ var init_stylePreprocessor = __esm(() => {
847
1117
  CSS_IMPORT_PATTERN = /@import\s+["']([^"']+)["']\s*;?/g;
848
1118
  });
849
1119
 
1120
+ // src/svelte/router/lazyModule.ts
1121
+ var LAZY_RESOLVED_KEY, LAZY_SOURCE_EXPORT = "__ABSOLUTE_SVELTE_SOURCE__", isRecord = (value) => typeof value === "object" && value !== null, isComponent = (value) => typeof value === "function", toLazyComponent = (value) => {
1122
+ if (isComponent(value))
1123
+ return value;
1124
+ if (!isRecord(value))
1125
+ return;
1126
+ const fallback = value.default;
1127
+ return isComponent(fallback) ? fallback : undefined;
1128
+ }, readSourceFrom = (value) => {
1129
+ if (!isRecord(value) && !isComponent(value))
1130
+ return;
1131
+ const source = Reflect.get(value, LAZY_SOURCE_EXPORT);
1132
+ return typeof source === "string" ? source : undefined;
1133
+ }, lazyModuleRegistration = (sourceId, specifier) => `
1134
+ ;(globalThis[Symbol.for("absolutejs.svelte.lazy-modules")] ??= new Map()).set(${JSON.stringify(sourceId)}, () => import(${JSON.stringify(specifier)}));`, readLazySource = (value) => {
1135
+ const fromValue = readSourceFrom(value);
1136
+ if (fromValue !== undefined)
1137
+ return fromValue;
1138
+ if (!isRecord(value))
1139
+ return;
1140
+ return readSourceFrom(value.default);
1141
+ };
1142
+ var init_lazyModule = __esm(() => {
1143
+ LAZY_RESOLVED_KEY = Symbol.for("absolutejs.svelte.lazy-resolved");
1144
+ });
1145
+
850
1146
  // src/core/svelteServerModule.ts
851
1147
  import { mkdir, readdir } from "fs/promises";
852
1148
  import { basename, dirname as dirname2, extname as extname2, join as join3, relative as relative2, resolve as resolve3 } from "path";
@@ -956,11 +1252,11 @@ var serverCacheRoot, compiledModuleCache, originalSourcePathCache, transpiler, e
956
1252
  const resolutionSourcePath = await resolveOriginalSourcePath(sourcePath);
957
1253
  const source = await Bun.file(sourcePath).text();
958
1254
  const { compile, preprocess } = await import("svelte/compiler");
959
- const loweredAwaitSource = lowerSvelteAwaitSlotSyntax(source);
1255
+ const loweredAwaitSource = lowerSvelteAwaitSlotSyntax(source, sourcePath);
960
1256
  const loweredSource = lowerSvelteIslandSyntax(loweredAwaitSource.code, "server");
961
1257
  const preprocessed = await preprocess(loweredSource.code, createSvelteStylePreprocessor());
962
1258
  let transpiled = sourcePath.endsWith(".ts") || sourcePath.endsWith(".svelte.ts") ? transpiler.transformSync(preprocessed.code) : preprocessed.code;
963
- const childImportSpecs = Array.from(transpiled.matchAll(/from\s+['"]([^'"]+)['"]/g)).map((match) => match[1]).filter((value) => value !== undefined);
1259
+ const childImportSpecs = Array.from(new Set(Array.from(transpiled.matchAll(/(?:from\s+|\bimport\s*\(\s*)['"]([^'"]+)['"]/g)).map((match) => match[1]).filter((value) => value !== undefined)));
964
1260
  const resolvedChildModules = await Promise.all(childImportSpecs.map((spec) => resolveSvelteImport(spec, resolutionSourcePath)));
965
1261
  const resolvedModuleImports = await Promise.all(childImportSpecs.map((spec) => resolveRelativeModule(spec, resolutionSourcePath)));
966
1262
  const childModulePaths = new Map;
@@ -1007,6 +1303,14 @@ var serverCacheRoot, compiledModuleCache, originalSourcePathCache, transpiler, e
1007
1303
  for (const [spec, resolvedModuleImport] of rewrittenModulePaths) {
1008
1304
  compiledCode = compiledCode.replaceAll(spec, resolvedModuleImport);
1009
1305
  }
1306
+ const sourceId = JSON.stringify(relative2(process.cwd(), resolutionSourcePath).replace(/\\/g, "/"));
1307
+ const componentName = /export default function ([\w$]+)\s*\(/.exec(compiledCode)?.[1];
1308
+ compiledCode += `
1309
+ export const ${LAZY_SOURCE_EXPORT} = ${sourceId};`;
1310
+ if (componentName) {
1311
+ compiledCode += `
1312
+ ${componentName}.${LAZY_SOURCE_EXPORT} = ${sourceId};`;
1313
+ }
1010
1314
  const compiledModulePath = getCachedModulePath(sourcePath);
1011
1315
  await mkdir(dirname2(compiledModulePath), { recursive: true });
1012
1316
  await writeIfChanged(compiledModulePath, compiledCode);
@@ -1018,6 +1322,7 @@ var init_svelteServerModule = __esm(() => {
1018
1322
  init_lowerIslandSyntax();
1019
1323
  init_lowerAwaitSlotSyntax();
1020
1324
  init_stylePreprocessor();
1325
+ init_lazyModule();
1021
1326
  serverCacheRoot = join3(process.cwd(), ".absolutejs", "islands", "svelte");
1022
1327
  compiledModuleCache = new Map;
1023
1328
  originalSourcePathCache = new Map;
@@ -1027,6 +1332,20 @@ var init_svelteServerModule = __esm(() => {
1027
1332
  });
1028
1333
  });
1029
1334
 
1335
+ // src/utils/escapeScriptContent.ts
1336
+ var ESCAPE_LOOKUP, ESCAPE_REGEX, escapeScriptContent = (content) => content.replace(ESCAPE_REGEX, (char) => {
1337
+ const escaped = ESCAPE_LOOKUP[char];
1338
+ return escaped !== undefined ? escaped : char;
1339
+ });
1340
+ var init_escapeScriptContent = __esm(() => {
1341
+ ESCAPE_LOOKUP = {
1342
+ "\u2028": "\\u2028",
1343
+ "\u2029": "\\u2029",
1344
+ "<": "\\u003C"
1345
+ };
1346
+ ESCAPE_REGEX = /[<\u2028\u2029]/g;
1347
+ });
1348
+
1030
1349
  // src/utils/getDurationString.ts
1031
1350
  var getDurationString = (duration) => {
1032
1351
  let durationString;
@@ -1223,15 +1542,15 @@ var ISLAND_BOOTSTRAP_MANIFEST_KEY = "AbsoluteIslandBootstrap", LEGACY_ISLAND_BOO
1223
1542
  var ISLAND_MARKER = 'data-island="true"', MANIFEST_MARKER = "__ABSOLUTE_MANIFEST__", ISLAND_STATE_MARKER = "__ABS_ISLAND_STATE__", CLOSING_HEAD_TAG = "</head>", warnedMissingBootstrap = false, warnIfBootstrapMissing = (manifest) => {
1224
1543
  if (warnedMissingBootstrap || getIslandBootstrapPath(manifest))
1225
1544
  return;
1226
- if (false)
1227
- ;
1545
+ if (isProductionRuntime())
1546
+ return;
1228
1547
  warnedMissingBootstrap = true;
1229
1548
  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().");
1230
1549
  }, buildIslandsHeadMarkup = (manifest) => {
1231
- const manifestScript = `<script>window.__ABSOLUTE_MANIFEST__ = ${JSON.stringify(manifest)}</script>`;
1232
- const islandStateScript = `<script>window.__ABS_ISLAND_STATE__ = ${JSON.stringify(globalThis.__ABS_ISLAND_STATE__ ?? {})}</script>`;
1550
+ const manifestScript = `<script${nonceAttr()}>window.__ABSOLUTE_MANIFEST__ = ${escapeScriptContent(JSON.stringify(manifest))}</script>`;
1551
+ const islandStateScript = `<script${nonceAttr()}>window.__ABS_ISLAND_STATE__ = ${escapeScriptContent(JSON.stringify(globalThis.__ABS_ISLAND_STATE__ ?? {}))}</script>`;
1233
1552
  const bootstrapPath = getIslandBootstrapPath(manifest);
1234
- const bootstrapScript = bootstrapPath ? `<script type="module" src="${bootstrapPath}"></script>` : "";
1553
+ const bootstrapScript = bootstrapPath ? `<script${nonceAttr()} type="module" src="${bootstrapPath}"></script>` : "";
1235
1554
  return `${manifestScript}${islandStateScript}${bootstrapScript}`;
1236
1555
  }, injectHeadMarkup = (html, markup) => {
1237
1556
  const closingHeadIndex = html.indexOf("</head>");
@@ -1432,12 +1751,14 @@ var ISLAND_MARKER = 'data-island="true"', MANIFEST_MARKER = "__ABSOLUTE_MANIFEST
1432
1751
  globalThis.__absoluteManifest = manifest;
1433
1752
  };
1434
1753
  var init_islandPageContext = __esm(() => {
1754
+ init_escapeScriptContent();
1755
+ init_cspNonceRef();
1435
1756
  init_logger();
1436
1757
  });
1437
1758
 
1438
1759
  // src/core/devRouteRegistrationCallsite.ts
1439
- import { AsyncLocalStorage } from "async_hooks";
1440
- import { Elysia } from "elysia";
1760
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
1761
+ import { Elysia as Elysia2 } from "elysia";
1441
1762
  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) => {
1442
1763
  const source = handler.toString();
1443
1764
  return PAGE_HANDLER_NAMES.some((name) => source.includes(name));
@@ -1463,7 +1784,7 @@ var ROUTE_CALLSITE_STORAGE_KEY, ROUTE_CALLSITE_PATCHED_KEY, NODE_ENV_KEY = "NODE
1463
1784
  if (existing) {
1464
1785
  return existing;
1465
1786
  }
1466
- const storage = new AsyncLocalStorage;
1787
+ const storage = new AsyncLocalStorage2;
1467
1788
  Reflect.set(globalThis, ROUTE_CALLSITE_STORAGE_KEY, storage);
1468
1789
  return storage;
1469
1790
  }, 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) => {
@@ -1504,7 +1825,7 @@ var ROUTE_CALLSITE_STORAGE_KEY, ROUTE_CALLSITE_PATCHED_KEY, NODE_ENV_KEY = "NODE
1504
1825
  if (Reflect.get(globalThis, ROUTE_CALLSITE_PATCHED_KEY) === true) {
1505
1826
  return;
1506
1827
  }
1507
- const { prototype } = Elysia;
1828
+ const { prototype } = Elysia2;
1508
1829
  ROUTE_METHOD_NAMES.forEach((methodName) => {
1509
1830
  const originalMethod = Reflect.get(prototype, methodName);
1510
1831
  if (!isRouteMethod(originalMethod))
@@ -1537,159 +1858,6 @@ var init_devRouteRegistrationCallsite = __esm(() => {
1537
1858
  pageHandlerWrappers = new WeakMap;
1538
1859
  });
1539
1860
 
1540
- // src/utils/ssrErrorPage.ts
1541
- var errorPageHtml = ({
1542
- framework,
1543
- hint,
1544
- kind,
1545
- message,
1546
- script = ""
1547
- }) => {
1548
- const frameworkColors = {
1549
- angular: "#dd0031",
1550
- html: "#e34c26",
1551
- htmx: "#1a365d",
1552
- react: "#61dafb",
1553
- svelte: "#ff3e00",
1554
- vue: "#42b883"
1555
- };
1556
- const accent = frameworkColors[framework] ?? "#94a3b8";
1557
- const label = framework.charAt(0).toUpperCase() + framework.slice(1);
1558
- return `<!DOCTYPE html>
1559
- <html>
1560
- <head>
1561
- <meta charset="utf-8">
1562
- <meta name="viewport" content="width=device-width, initial-scale=1">
1563
- <title>SSR Error - AbsoluteJS</title>
1564
- <style>
1565
- *{margin:0;padding:0;box-sizing:border-box}
1566
- 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}
1567
- .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}
1568
- .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)}
1569
- .brand{font-weight:700;font-size:20px;color:#fff;letter-spacing:-0.02em}
1570
- .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)}
1571
- .kind{color:#94a3b8;font-size:13px;font-weight:500}
1572
- .content{padding:24px}
1573
- .label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.08em;color:#94a3b8;margin-bottom:8px}
1574
- .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}
1575
- .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}
1576
- </style>
1577
- </head>
1578
- <body>
1579
- <div class="card">
1580
- <div class="header">
1581
- <div style="display:flex;align-items:center;gap:12px">
1582
- <span class="brand">AbsoluteJS</span>
1583
- <span class="badge">${label}</span>
1584
- </div>
1585
- <span class="kind">${kind}</span>
1586
- </div>
1587
- <div class="content">
1588
- <div class="label">What went wrong</div>
1589
- <pre class="message">${message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")}</pre>
1590
- <div class="hint">${hint}</div>
1591
- </div>
1592
- </div>
1593
- ${script}
1594
- </body>
1595
- </html>`;
1596
- }, 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({
1597
- framework,
1598
- hint: "Fix the file and save. This page reloads by itself when the build succeeds.",
1599
- kind: "Build Error",
1600
- message: `${pageName || "This page"} could not be built.
1601
-
1602
- ${error ?? "The dev-server terminal has the build output."}`,
1603
- script: RELOAD_ON_REBUILD
1604
- }), ssrErrorPage = (framework, error) => errorPageHtml({
1605
- framework,
1606
- hint: "A component threw during server-side rendering. Check the terminal for the full stack trace.",
1607
- kind: "Server Render Error",
1608
- message: error instanceof Error ? error.message : String(error)
1609
- });
1610
-
1611
- // src/core/requestContext.ts
1612
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
1613
- import { Elysia as Elysia2 } from "elysia";
1614
- 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 = () => {
1615
- const value = Reflect.get(globalThis, REQUEST_STORAGE_KEY);
1616
- return isAbsoluteRequestStorage(value) ? value : undefined;
1617
- }, ensureRequestStorage = () => {
1618
- const existing = getRequestStorage();
1619
- if (existing)
1620
- return existing;
1621
- const storage = new AsyncLocalStorage2;
1622
- Reflect.set(globalThis, REQUEST_STORAGE_KEY, storage);
1623
- return storage;
1624
- }, 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) => {
1625
- if (!assets?.failed)
1626
- return null;
1627
- return new Response(buildErrorPage(framework, assets.name, assets.error), {
1628
- headers: {
1629
- "cache-control": "no-store",
1630
- "content-type": "text/html; charset=utf-8"
1631
- },
1632
- status: 500
1633
- });
1634
- }, getDevPageWarmer = () => {
1635
- const value = Reflect.get(globalThis, PAGE_WARMER_KEY);
1636
- return isDevPageWarmer(value) ? value : undefined;
1637
- }, getMissingAssets = () => {
1638
- const missing = getRequestStorage()?.getStore()?.missingAssets;
1639
- return missing ? [...missing] : [];
1640
- }, recordMissingAsset = (name) => {
1641
- const store = getRequestStorage()?.getStore();
1642
- if (!store)
1643
- return;
1644
- store.missingAssets ??= [];
1645
- store.missingAssets.push(name);
1646
- }, resolveDeferredPageAssets = async () => {
1647
- const warmer = getDevPageWarmer();
1648
- if (!warmer)
1649
- return null;
1650
- const missing = getMissingAssets();
1651
- const pageKey = missing.find((key) => warmer.describe(key));
1652
- if (pageKey === undefined)
1653
- return null;
1654
- const described = warmer.describe(pageKey);
1655
- if (!described)
1656
- return null;
1657
- const status = await warmer.warm(pageKey);
1658
- const failed = status === "failed" || status === "unknown";
1659
- const lookup = (key) => failed ? "" : warmer.lookup(key) ?? "";
1660
- const cssKeys = missing.filter((key) => CSS_KEY_RE.test(key));
1661
- const cssHrefs = () => cssKeys.map(lookup).filter((href) => href.length > 0 && href.startsWith("/"));
1662
- const assets = {
1663
- cssHrefs,
1664
- error: failed ? warmer.lastError?.() : undefined,
1665
- failed,
1666
- lookup,
1667
- name: described.name
1668
- };
1669
- return assets;
1670
- }, setDevPageWarmer = (warmer) => {
1671
- Reflect.set(globalThis, PAGE_WARMER_KEY, warmer);
1672
- }, withDeferredStylesheets = (head, assets) => {
1673
- const hrefs = assets?.cssHrefs() ?? [];
1674
- if (hrefs.length === 0)
1675
- return head;
1676
- const links = hrefs.filter((href) => !head.includes(href)).map((href) => `<link rel="stylesheet" href="${href}">`).join("");
1677
- if (links.length === 0)
1678
- return head;
1679
- const headClose = /<\/head\s*>/i.exec(head);
1680
- return headClose ? head.slice(0, headClose.index) + links + head.slice(headClose.index) : head + links;
1681
- };
1682
- var init_requestContext = __esm(() => {
1683
- REQUEST_STORAGE_KEY = Symbol.for("absolutejs.requestAsyncLocalStorage");
1684
- PAGE_WARMER_KEY = Symbol.for("absolutejs.devPageWarmer");
1685
- absoluteRequestContext = new Elysia2({
1686
- name: "absolutejs-request-context"
1687
- }).onRequest(({ request }) => {
1688
- ensureRequestStorage().enterWith({ request });
1689
- }).as("global");
1690
- CSS_KEY_RE = /(?:CSS|Css)$/;
1691
- });
1692
-
1693
1861
  // src/mobile/producerContextState.ts
1694
1862
  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 = () => {
1695
1863
  const value = Reflect.get(globalThis, ABSOLUTE_MOBILE_PRODUCER_STORAGE_KEY);
@@ -1807,13 +1975,13 @@ var ABSOLUTE_MOBILE_PAGE_MEDIA_TYPE = "application/vnd.absolute.page+json", ABSO
1807
1975
  }, headerVaryValues, envelopeResponse = (response, status) => new Response(JSON.stringify({
1808
1976
  protocol: ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION,
1809
1977
  response
1810
- }), { headers: responseHeaders(), status }), isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value), normalizeJsonValue = (value) => {
1978
+ }), { headers: responseHeaders(), status }), isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), normalizeJsonValue = (value) => {
1811
1979
  const serialized = JSON.stringify(value);
1812
1980
  if (serialized === undefined) {
1813
1981
  throw new TypeError("Mobile page props must be JSON-serializable.");
1814
1982
  }
1815
1983
  const parsed = JSON.parse(serialized);
1816
- if (!isRecord(parsed)) {
1984
+ if (!isRecord2(parsed)) {
1817
1985
  throw new TypeError("Mobile page props must serialize to an object.");
1818
1986
  }
1819
1987
  return parsed;
@@ -1843,7 +2011,9 @@ var ABSOLUTE_MOBILE_PAGE_MEDIA_TYPE = "application/vnd.absolute.page+json", ABSO
1843
2011
  return createAbsoluteMobilePageErrorResponse(page.pageId);
1844
2012
  }
1845
2013
  }, finalizeAbsoluteNativeRouteDevelopmentPage = (input) => {
1846
- if (false) {}
2014
+ if (!isDevelopmentRuntime()) {
2015
+ return createAbsoluteMobileInvalidRequestResponse("The native-route development representation is disabled outside development.");
2016
+ }
1847
2017
  if (input.request?.method !== "GET") {
1848
2018
  return createAbsoluteMobileInvalidRequestResponse("Native-route data requests must use GET.");
1849
2019
  }
@@ -2185,22 +2355,15 @@ var streamSwapRuntime = () => {
2185
2355
  return value.slice(start + 1, end);
2186
2356
  }, getStreamSwapRuntimeScript = () => `(function(){${stripFunctionWrapper(streamSwapRuntime.toString())}})();`;
2187
2357
 
2188
- // src/utils/escapeScriptContent.ts
2189
- var ESCAPE_LOOKUP, ESCAPE_REGEX, escapeScriptContent = (content) => content.replace(ESCAPE_REGEX, (char) => {
2190
- const escaped = ESCAPE_LOOKUP[char];
2191
- return escaped !== undefined ? escaped : char;
2192
- });
2193
- var init_escapeScriptContent = __esm(() => {
2194
- ESCAPE_LOOKUP = {
2195
- "\u2028": "\\u2028",
2196
- "\u2029": "\\u2029",
2197
- "<": "\\u003C"
2198
- };
2199
- ESCAPE_REGEX = /[<\u2028\u2029]/g;
2200
- });
2201
-
2202
2358
  // src/utils/streamingSlots.ts
2203
- 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) => {
2359
+ 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) => {
2360
+ const head = text.slice(0, cut);
2361
+ const openScript = head.lastIndexOf("<script");
2362
+ const scriptCut = openScript > head.lastIndexOf("</script>") ? openScript : cut;
2363
+ const beforeScript = text.slice(0, scriptCut);
2364
+ const openTag = beforeScript.lastIndexOf("<");
2365
+ return openTag > beforeScript.lastIndexOf(">") ? openTag : scriptCut;
2366
+ }, 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) => {
2204
2367
  const closingBodyIndex = html.indexOf(CLOSING_BODY_TAG);
2205
2368
  if (closingBodyIndex >= 0) {
2206
2369
  return `${html.slice(0, closingBodyIndex)}${injection}${html.slice(closingBodyIndex)}`;
@@ -2218,7 +2381,7 @@ var SLOT_ID_PREFIX = "abs-slot-", CLOSING_BODY_TAG = "</body>", CLOSING_HEAD_TAG
2218
2381
  getStreamingSlotsRuntimeScript()
2219
2382
  ].filter(Boolean).join(";");
2220
2383
  return `<script${createNonceAttr(nonce)}>${escapeScriptContent(runtimeBody)}</script>`;
2221
- }, toUint8 = (value, encoder) => encoder.encode(value), isRecord2 = (value) => Boolean(value) && typeof value === "object", isSafeHtmlLike = (value) => isRecord2(value) && typeof value.changingThisBreaksApplicationSecurity === "string", normalizeSafeHtml = (value) => {
2384
+ }, toUint8 = (value, encoder) => encoder.encode(value), isRecord3 = (value) => Boolean(value) && typeof value === "object", isSafeHtmlLike = (value) => isRecord3(value) && typeof value.changingThisBreaksApplicationSecurity === "string", normalizeSafeHtml = (value) => {
2222
2385
  if (isSafeHtmlLike(value)) {
2223
2386
  return value.changingThisBreaksApplicationSecurity;
2224
2387
  }
@@ -2279,7 +2442,8 @@ var SLOT_ID_PREFIX = "abs-slot-", CLOSING_BODY_TAG = "</body>", CLOSING_HEAD_TAG
2279
2442
  }, createTimeoutError = (slot, timeoutMs) => {
2280
2443
  const error = Object.assign(new Error(`Streaming slot "${slot.id}" timed out after ${timeoutMs}ms`), { __absTimeout: true });
2281
2444
  return error;
2282
- }, isSlotPatchPayloadObject = (value) => isRecord2(value) && ("html" in value), isTimeoutError = (error) => isRecord2(error) && error.__absTimeout === true, toStreamingSlot = (slot, policy) => ({
2445
+ }, isSlotPatchPayloadObject = (value) => isRecord3(value) && ("html" in value), isTimeoutError = (error) => isRecord3(error) && error.__absTimeout === true, toStreamingSlot = (slot, policy) => ({
2446
+ dynamic: slot.dynamic,
2283
2447
  errorHtml: slot.errorHtml === undefined ? policy.errorHtml : slot.errorHtml,
2284
2448
  fallbackHtml: normalizeSlotText(slot.fallbackHtml, policy.fallbackHtml),
2285
2449
  id: slot.id ?? createStreamingSlotId(),
@@ -2504,9 +2668,10 @@ var SLOT_ID_PREFIX = "abs-slot-", CLOSING_BODY_TAG = "</body>", CLOSING_HEAD_TAG
2504
2668
  if (tail.length <= STREAM_TAIL_LOOKBEHIND) {
2505
2669
  return tail;
2506
2670
  }
2507
- const content = tail.slice(0, tail.length - STREAM_TAIL_LOOKBEHIND);
2508
- controller.enqueue(encoder.encode(content));
2509
- return tail.slice(-STREAM_TAIL_LOOKBEHIND);
2671
+ const cut = findSafeFlushIndex(tail, tail.length - STREAM_TAIL_LOOKBEHIND);
2672
+ if (cut > 0)
2673
+ controller.enqueue(encoder.encode(tail.slice(0, cut)));
2674
+ return tail.slice(cut);
2510
2675
  };
2511
2676
  const finalizeCompletedBaseWinner = (controller, decodedTail, baseRead) => {
2512
2677
  const footerStart = decodedTail.search(CLOSING_PAGE_TAG_REGEX);
@@ -2739,6 +2904,7 @@ var SLOT_ID_PREFIX = "abs-slot-", CLOSING_BODY_TAG = "</body>", CLOSING_HEAD_TAG
2739
2904
  });
2740
2905
  };
2741
2906
  var init_streamingSlots = __esm(() => {
2907
+ init_cspNonceRef();
2742
2908
  init_constants();
2743
2909
  init_escapeScriptContent();
2744
2910
  CLOSING_BODY_TAG_LENGTH = CLOSING_BODY_TAG.length;
@@ -2753,6 +2919,42 @@ var init_streamingSlots = __esm(() => {
2753
2919
  };
2754
2920
  });
2755
2921
 
2922
+ // src/core/partialPrerender.ts
2923
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
2924
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
2925
+ import { rm } from "fs/promises";
2926
+ var PARTIAL_HOLES_HEADER = "X-Absolute-Partial-Holes", PARTIAL_SHELL_HEADER = "X-Absolute-Partial-Shell", SINK_STORAGE_KEY, isSinkStorage = (value) => value instanceof AsyncLocalStorage3, getSinkStorage = () => {
2927
+ const existing = Reflect.get(globalThis, SINK_STORAGE_KEY);
2928
+ if (isSinkStorage(existing))
2929
+ return existing;
2930
+ const created = new AsyncLocalStorage3;
2931
+ Reflect.set(globalThis, SINK_STORAGE_KEY, created);
2932
+ return created;
2933
+ }, activePartialHolesSink = () => getSinkStorage().getStore(), collectPartialHoles = async (render) => {
2934
+ const sink = { slots: undefined };
2935
+ const response = await getSinkStorage().run(sink, render);
2936
+ return { response, slots: sink.slots };
2937
+ }, 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) => {
2938
+ const path = holesPath(htmlPath);
2939
+ if (!existsSync3(path))
2940
+ return [];
2941
+ return decodePartialHoles(readFileSync3(path, "utf-8").trim().split(`
2942
+ `).join(","));
2943
+ }, writePartialHoles = async (htmlPath, response) => {
2944
+ const ids = decodePartialHoles(response.headers.get(PARTIAL_HOLES_HEADER));
2945
+ if (ids.length > 0) {
2946
+ await Bun.write(holesPath(htmlPath), `${encodePartialHoles(ids).split(",").join(`
2947
+ `)}
2948
+ `);
2949
+ } else {
2950
+ await rm(holesPath(htmlPath), { force: true });
2951
+ }
2952
+ return ids;
2953
+ };
2954
+ var init_partialPrerender = __esm(() => {
2955
+ SINK_STORAGE_KEY = Symbol.for("absolutejs.partialPrerenderHolesSink");
2956
+ });
2957
+
2756
2958
  // src/core/routeAssets.ts
2757
2959
  var LINK_TAG_RE, REL_STYLESHEET_RE, HREF_RE, TITLE_RE, ENTITIES, ENTITY_RE, decodeEntities = (value) => value.replace(ENTITY_RE, (match) => ENTITIES[match] ?? match), readHeadStylesheets = (head) => {
2758
2960
  if (!head)
@@ -2796,7 +2998,7 @@ var siblingCssCache, clearSiblingCssCache = () => {
2796
2998
  }, injectInlineCss = (headTag, css) => {
2797
2999
  if (!css)
2798
3000
  return headTag;
2799
- const styleBlock = `<style data-absolute-page-css>${css}</style>`;
3001
+ const styleBlock = `<style data-absolute-page-css${nonceAttr()}>${css}</style>`;
2800
3002
  return headTag.replace("</head>", `${styleBlock}</head>`);
2801
3003
  }, readSiblingCss = async (siblingJsPath) => {
2802
3004
  if (!siblingJsPath)
@@ -2818,6 +3020,7 @@ var siblingCssCache, clearSiblingCssCache = () => {
2818
3020
  }
2819
3021
  };
2820
3022
  var init_inlinePageCss = __esm(() => {
3023
+ init_cspNonceRef();
2821
3024
  siblingCssCache = new Map;
2822
3025
  });
2823
3026
 
@@ -2829,6 +3032,45 @@ var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-
2829
3032
  return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
2830
3033
  };
2831
3034
 
3035
+ // src/core/staticHtmlNonce.ts
3036
+ var nonceStaticHtml = async (html, nonce = readCspNonce()) => {
3037
+ if (!nonce)
3038
+ return html;
3039
+ const stamp = {
3040
+ element: (element) => {
3041
+ if (!element.hasAttribute("nonce"))
3042
+ element.setAttribute("nonce", nonce);
3043
+ }
3044
+ };
3045
+ return new HTMLRewriter().on("script", stamp).on("style", stamp).transform(new Response(html)).text();
3046
+ }, isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), parseHtmxConfig = (content) => {
3047
+ try {
3048
+ const parsed = JSON.parse(content ?? "{}");
3049
+ return isRecord4(parsed) ? parsed : {};
3050
+ } catch {
3051
+ return {};
3052
+ }
3053
+ }, withHtmxStyleNonce = async (html, nonce = readCspNonce()) => {
3054
+ if (!nonce)
3055
+ return html;
3056
+ let found = false;
3057
+ const merged = await new HTMLRewriter().on('meta[name="htmx-config"]', {
3058
+ element: (element) => {
3059
+ found = true;
3060
+ const config = parseHtmxConfig(element.getAttribute("content"));
3061
+ element.setAttribute("content", JSON.stringify({ ...config, inlineStyleNonce: nonce }));
3062
+ }
3063
+ }).transform(new Response(html)).text();
3064
+ if (found)
3065
+ return merged;
3066
+ const meta = `<meta name="htmx-config" content='${JSON.stringify({ inlineStyleNonce: nonce })}'>`;
3067
+ const headClose = merged.search(/<\/head>/i);
3068
+ return headClose >= 0 ? `${merged.slice(0, headClose)}${meta}${merged.slice(headClose)}` : `${meta}${merged}`;
3069
+ };
3070
+ var init_staticHtmlNonce = __esm(() => {
3071
+ init_cspNonceRef();
3072
+ });
3073
+
2832
3074
  // src/utils/resolveConvention.ts
2833
3075
  import { basename as basename2 } from "path";
2834
3076
  var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boolean(value) && typeof value === "object", getMap = () => {
@@ -2865,7 +3107,7 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
2865
3107
  return conventions.defaults?.error;
2866
3108
  }, resolveNotFoundConventionPath = (framework) => getMap()[framework]?.defaults?.notFound, setConventions = (map) => {
2867
3109
  Reflect.set(globalThis, CONVENTIONS_KEY, map);
2868
- }, isDev = () => true, buildErrorProps = (error) => {
3110
+ }, isDev = () => isDevelopmentRuntime(), buildErrorProps = (error) => {
2869
3111
  if (error instanceof Error) {
2870
3112
  return {
2871
3113
  message: error.message,
@@ -2882,7 +3124,9 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
2882
3124
  if (typeof ErrorComponent !== "function")
2883
3125
  return null;
2884
3126
  const element = createElement(ErrorComponent, errorProps);
2885
- const stream = await renderToReadableStream(element);
3127
+ const stream = await renderToReadableStream(element, {
3128
+ nonce: readCspNonce()
3129
+ });
2886
3130
  return new Response(stream, {
2887
3131
  headers: { "Content-Type": "text/html" },
2888
3132
  status: 500
@@ -2893,10 +3137,12 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
2893
3137
  const ErrorComponent = mod.default;
2894
3138
  if (!ErrorComponent)
2895
3139
  return null;
3140
+ const nonce = readCspNonce();
2896
3141
  const { head, body } = render(ErrorComponent, {
2897
- props: errorProps
3142
+ props: errorProps,
3143
+ ...nonce ? { csp: { nonce } } : {}
2898
3144
  });
2899
- const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
3145
+ const html = `<!DOCTYPE html><html><head>${nonceSvelteHeadStyles(head)}</head><body>${body}</body></html>`;
2900
3146
  return new Response(html, {
2901
3147
  headers: { "Content-Type": "text/html" },
2902
3148
  status: 500
@@ -2904,7 +3150,7 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
2904
3150
  }, unescapeVueStyles = (ssrBody) => {
2905
3151
  let styles = "";
2906
3152
  const body = ssrBody.replace(/<style>([\s\S]*?)<\/style>/g, (_, css) => {
2907
- styles += `<style>${css.replace(/&quot;/g, '"').replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">")}</style>`;
3153
+ styles += `<style${nonceAttr()}>${css.replace(/&quot;/g, '"').replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">")}</style>`;
2908
3154
  return "";
2909
3155
  });
2910
3156
  return { body, styles };
@@ -2936,7 +3182,7 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
2936
3182
  status: 500
2937
3183
  });
2938
3184
  }, 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) => {
2939
- const template = await Bun.file(conventionPath).text();
3185
+ const template = await nonceStaticHtml(await Bun.file(conventionPath).text());
2940
3186
  const html = replaceErrorTokens(template, errorProps);
2941
3187
  return new Response(html, {
2942
3188
  headers: { "Content-Type": "text/html" },
@@ -2991,7 +3237,9 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
2991
3237
  if (typeof NotFoundComponent !== "function")
2992
3238
  return null;
2993
3239
  const element = createElement(NotFoundComponent);
2994
- const stream = await renderToReadableStream(element);
3240
+ const stream = await renderToReadableStream(element, {
3241
+ nonce: readCspNonce()
3242
+ });
2995
3243
  return new Response(stream, {
2996
3244
  headers: { "Content-Type": "text/html" },
2997
3245
  status: 404
@@ -3002,8 +3250,9 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
3002
3250
  const NotFoundComponent = mod.default;
3003
3251
  if (!NotFoundComponent)
3004
3252
  return null;
3005
- const { head, body } = render(NotFoundComponent);
3006
- const html = `<!DOCTYPE html><html><head>${head}</head><body>${body}</body></html>`;
3253
+ const nonce = readCspNonce();
3254
+ const { head, body } = render(NotFoundComponent, nonce ? { csp: { nonce } } : {});
3255
+ const html = `<!DOCTYPE html><html><head>${nonceSvelteHeadStyles(head)}</head><body>${body}</body></html>`;
3007
3256
  return new Response(html, {
3008
3257
  headers: { "Content-Type": "text/html" },
3009
3258
  status: 404
@@ -3036,7 +3285,7 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
3036
3285
  status: 404
3037
3286
  });
3038
3287
  }, renderHtmlNotFound = async (conventionPath) => {
3039
- const html = await Bun.file(conventionPath).text();
3288
+ const html = await nonceStaticHtml(await Bun.file(conventionPath).text());
3040
3289
  return new Response(html, {
3041
3290
  headers: { "Content-Type": "text/html" },
3042
3291
  status: 404
@@ -3054,7 +3303,7 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
3054
3303
  logConventionRenderError(framework, "not-found", renderError);
3055
3304
  }
3056
3305
  return null;
3057
- }, NOT_FOUND_PRIORITY, renderFirstNotFound = async () => {
3306
+ }, NOT_FOUND_PRIORITY, renderFirstNotFound = async (options = {}) => {
3058
3307
  const renderNext = async (frameworks) => {
3059
3308
  const [framework, ...remaining] = frameworks;
3060
3309
  if (!framework) {
@@ -3069,13 +3318,16 @@ var CONVENTIONS_KEY = "__absoluteConventions", isConventionsMap = (value) => Boo
3069
3318
  }
3070
3319
  return renderNext(remaining);
3071
3320
  };
3072
- return renderNext(NOT_FOUND_PRIORITY);
3321
+ return renderNext(options.preferHtmx ? ["htmx", ...NOT_FOUND_PRIORITY.filter((key) => key !== "htmx")] : NOT_FOUND_PRIORITY);
3073
3322
  };
3074
3323
  var init_resolveConvention = __esm(() => {
3324
+ init_cspNonceRef();
3325
+ init_staticHtmlNonce();
3075
3326
  ERROR_RENDERERS = {
3076
3327
  angular: renderAngularError,
3077
3328
  ember: renderEmberError,
3078
3329
  html: renderHtmlError,
3330
+ htmx: renderHtmlError,
3079
3331
  react: renderReactError,
3080
3332
  svelte: renderSvelteError,
3081
3333
  vue: renderVueError
@@ -3084,6 +3336,7 @@ var init_resolveConvention = __esm(() => {
3084
3336
  angular: renderAngularNotFound,
3085
3337
  ember: renderEmberNotFound,
3086
3338
  html: renderHtmlNotFound,
3339
+ htmx: renderHtmlNotFound,
3087
3340
  react: renderReactNotFound,
3088
3341
  svelte: renderSvelteNotFound,
3089
3342
  vue: renderVueNotFound
@@ -3093,7 +3346,8 @@ var init_resolveConvention = __esm(() => {
3093
3346
  "svelte",
3094
3347
  "vue",
3095
3348
  "angular",
3096
- "html"
3349
+ "html",
3350
+ "htmx"
3097
3351
  ];
3098
3352
  });
3099
3353
 
@@ -3178,7 +3432,7 @@ var init_browserTranslationAttributes = __esm(() => {
3178
3432
  });
3179
3433
 
3180
3434
  // src/core/browserTranslation.ts
3181
- var BASELINE_MARKER = "__ABSOLUTE_SSR_TEXT_BASELINES__", BROWSER_TRANSLATION_BASELINE_SCRIPT, browserTranslationBaselineTag = () => `<script>${BROWSER_TRANSLATION_BASELINE_SCRIPT}</script>`, injectBrowserTranslationBaseline = (html) => {
3435
+ var BASELINE_MARKER = "__ABSOLUTE_SSR_TEXT_BASELINES__", BROWSER_TRANSLATION_BASELINE_SCRIPT, browserTranslationBaselineTag = () => `<script${nonceAttr()}>${BROWSER_TRANSLATION_BASELINE_SCRIPT}</script>`, injectBrowserTranslationBaseline = (html) => {
3182
3436
  if (html.includes(BASELINE_MARKER))
3183
3437
  return html;
3184
3438
  const script = browserTranslationBaselineTag();
@@ -3188,12 +3442,40 @@ var BASELINE_MARKER = "__ABSOLUTE_SSR_TEXT_BASELINES__", BROWSER_TRANSLATION_BAS
3188
3442
  return `${html.slice(0, closingBodyIndex)}${script}${html.slice(closingBodyIndex)}`;
3189
3443
  };
3190
3444
  var init_browserTranslation = __esm(() => {
3445
+ init_cspNonceRef();
3191
3446
  init_browserTranslationAttributes();
3192
3447
  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);}}";
3193
3448
  });
3194
3449
 
3450
+ // src/utils/localeRef.ts
3451
+ var GETTER_KEY2, isRequestLocale = (value) => typeof value === "object" && value !== null && ("locale" in value) && typeof value.locale === "string" && ("dir" in value) && (value.dir === "ltr" || value.dir === "rtl"), escapeAttribute = (value) => value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;"), htmlLangAttributes = (fallback = "en") => {
3452
+ const current = readRequestLocale();
3453
+ if (!current)
3454
+ return ` lang="${escapeAttribute(fallback)}"`;
3455
+ return ` lang="${escapeAttribute(current.locale)}" dir="${current.dir}"`;
3456
+ }, readRequestLocale = () => {
3457
+ const getter = Reflect.get(globalThis, GETTER_KEY2);
3458
+ if (typeof getter !== "function")
3459
+ return;
3460
+ const value = getter();
3461
+ return isRequestLocale(value) ? value : undefined;
3462
+ }, registerRequestLocaleGetter = (getter) => {
3463
+ Reflect.set(globalThis, GETTER_KEY2, getter);
3464
+ };
3465
+ var init_localeRef = __esm(() => {
3466
+ GETTER_KEY2 = Symbol.for("absolutejs.requestLocaleGetter");
3467
+ });
3468
+
3195
3469
  // src/svelte/renderToReadableStream.ts
3196
- var SVELTE_PAGE_ROOT_ID = "__absolute_svelte_root__", renderToReadableStream = async (component, props, {
3470
+ var SVELTE_PAGE_ROOT_ID = "__absolute_svelte_root__", MAX_RENDER_PASSES = 5, renderUntilSettled = async (renderPass, settle, pass = 1) => {
3471
+ const rendered = await renderPass();
3472
+ if (!settle || pass >= MAX_RENDER_PASSES)
3473
+ return rendered;
3474
+ const again = await settle();
3475
+ if (!again)
3476
+ return rendered;
3477
+ return renderUntilSettled(renderPass, settle, pass + 1);
3478
+ }, renderToReadableStream = async (component, props, {
3197
3479
  bootstrapScriptContent,
3198
3480
  bootstrapScripts = [],
3199
3481
  bootstrapModules = [],
@@ -3202,17 +3484,28 @@ var SVELTE_PAGE_ROOT_ID = "__absolute_svelte_root__", renderToReadableStream = a
3202
3484
  progressiveChunkSize = DEFAULT_CHUNK_SIZE,
3203
3485
  signal,
3204
3486
  headContent,
3205
- bodyContent
3487
+ bodyContent,
3488
+ context,
3489
+ settle
3206
3490
  } = {}) => {
3207
3491
  try {
3208
3492
  const { render } = await import("svelte/server");
3209
3493
  const renderComponent = render;
3210
- const rendered = typeof props === "undefined" ? await renderComponent(component) : await renderComponent(component, { props });
3494
+ const resolvedNonce = nonce ?? readCspNonce();
3495
+ const svelteCsp = resolvedNonce ? { csp: { nonce: resolvedNonce } } : {};
3496
+ const renderPass = async () => {
3497
+ if (typeof props === "undefined" && !context) {
3498
+ return renderComponent(component, svelteCsp);
3499
+ }
3500
+ return renderComponent(component, { ...svelteCsp, context, props });
3501
+ };
3502
+ const rendered = await renderUntilSettled(renderPass, settle);
3211
3503
  const { head, body } = rendered;
3212
- const nonceAttr = nonce ? ` nonce="${nonce}"` : "";
3213
- const scripts = (bootstrapScriptContent ? `<script${nonceAttr}>${escapeScriptContent(bootstrapScriptContent)}</script>` : "") + bootstrapScripts.map((src) => `<script${nonceAttr} src="${src}"></script>`).join("") + bootstrapModules.map((src) => `<script${nonceAttr} type="module" src="${src}"></script>`).join("");
3504
+ const nonceAttr2 = nonceAttr(resolvedNonce);
3505
+ const inlineScript = typeof bootstrapScriptContent === "function" ? bootstrapScriptContent() : bootstrapScriptContent;
3506
+ const scripts = (inlineScript ? `<script${nonceAttr2}>${escapeScriptContent(inlineScript)}</script>` : "") + bootstrapScripts.map((src) => `<script${nonceAttr2} src="${src}"></script>`).join("") + bootstrapModules.map((src) => `<script${nonceAttr2} type="module" src="${src}"></script>`).join("");
3214
3507
  const encoder = new TextEncoder;
3215
- const full = encoder.encode(`<!DOCTYPE html><html lang="en"><head>${head}${headContent ?? ""}</head><body><div id="${SVELTE_PAGE_ROOT_ID}">${body}</div>${scripts}${bodyContent ?? ""}</body></html>`);
3508
+ const full = encoder.encode(`<!DOCTYPE html><html${htmlLangAttributes()}><head>${nonceSvelteHeadStyles(head, resolvedNonce)}${headContent ?? ""}</head><body><div id="${SVELTE_PAGE_ROOT_ID}">${body}</div>${scripts}${bodyContent ?? ""}</body></html>`);
3216
3509
  let offset = 0;
3217
3510
  return new ReadableStream({
3218
3511
  type: "bytes",
@@ -3239,11 +3532,67 @@ var SVELTE_PAGE_ROOT_ID = "__absolute_svelte_root__", renderToReadableStream = a
3239
3532
  }
3240
3533
  };
3241
3534
  var init_renderToReadableStream = __esm(() => {
3535
+ init_cspNonceRef();
3242
3536
  init_constants();
3243
3537
  init_escapeScriptContent();
3538
+ init_localeRef();
3244
3539
  });
3245
3540
 
3541
+ // src/core/fileRouteAdapter.ts
3542
+ var PARAM_NAME_RE = /:([A-Za-z_$][\w$]*)/g;
3543
+ var paramNamesOf = (path) => [...path.matchAll(PARAM_NAME_RE)].map((match) => match[1]).filter((name) => name !== undefined);
3544
+ var hasRouteParams = (context, names) => names.every((name) => typeof context.params[name] === "string");
3545
+ var serverHooksOf = ({
3546
+ path,
3547
+ server
3548
+ }) => {
3549
+ if (!server)
3550
+ return {};
3551
+ const names = paramNamesOf(path);
3552
+ const withParams = async (context, run) => {
3553
+ const module = await server();
3554
+ if (!module || !hasRouteParams(context, names))
3555
+ return;
3556
+ return run(module, context);
3557
+ };
3558
+ const hooks = {
3559
+ beforeHandle: (context) => withParams(context, (module, typed) => module.beforeHandle?.(typed)),
3560
+ load: (context) => withParams(context, (module, typed) => module.load?.(typed))
3561
+ };
3562
+ return hooks;
3563
+ };
3564
+ var defineFileRouteWith = (framework, route, render) => {
3565
+ const definition = {
3566
+ framework,
3567
+ name: route.name,
3568
+ path: route.path,
3569
+ render,
3570
+ source: route.source,
3571
+ ...serverHooksOf(route)
3572
+ };
3573
+ return definition;
3574
+ };
3575
+
3576
+ // src/core/lookup.ts
3577
+ init_requestContext();
3578
+ var asset = (source, name) => {
3579
+ const assetPath = source[name];
3580
+ if (assetPath === undefined) {
3581
+ if (isProductionRuntime()) {
3582
+ throw new Error(`Asset "${name}" not found in manifest.`);
3583
+ }
3584
+ recordMissingAsset(name);
3585
+ const page = getDevPageWarmer()?.describe(name);
3586
+ if (page !== undefined && !page.built)
3587
+ return "";
3588
+ console.warn(`[asset] key "${name}" not found in manifest (dev mode \u2014 skipping)`);
3589
+ return "";
3590
+ }
3591
+ return assetPath;
3592
+ };
3593
+
3246
3594
  // src/svelte/pageHandler.ts
3595
+ init_cspNonceRef();
3247
3596
  init_svelteServerModule();
3248
3597
  init_islandPageContext();
3249
3598
  init_devRouteRegistrationCallsite();
@@ -3254,6 +3603,8 @@ init_pageResponseCache();
3254
3603
  // src/core/responseEnhancers.ts
3255
3604
  init_streamingSlots();
3256
3605
  init_pageResponseCache();
3606
+ init_partialPrerender();
3607
+ init_requestContext();
3257
3608
 
3258
3609
  // src/core/streamingSlotRegistrar.ts
3259
3610
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
@@ -3296,7 +3647,7 @@ var setStreamingSlotWarningController = (controller) => {
3296
3647
  Reflect.set(globalThis, STREAMING_SLOT_WARNING_STORAGE_KEY, controller);
3297
3648
  };
3298
3649
  var warnMissingStreamingSlotCollector = (primitiveName) => {
3299
- if (isStreamingSlotCollectionActive()) {
3650
+ if (isProductionRuntime() || isStreamingSlotCollectionActive()) {
3300
3651
  return;
3301
3652
  }
3302
3653
  getWarningController()?.maybeWarn(primitiveName);
@@ -3404,18 +3755,51 @@ var mergeStreamingSlots = (registered, explicit) => {
3404
3755
  merged.set(slot.id, slot);
3405
3756
  return [...merged.values()];
3406
3757
  };
3758
+ var captureStaticShell = async (responseLike, slots, options) => {
3759
+ const holes = slots.filter(isDynamicStreamingSlot);
3760
+ const staticSlots = slots.filter((slot) => !isDynamicStreamingSlot(slot));
3761
+ const response = await withStreamingSlots(responseLike, {
3762
+ ...options,
3763
+ streamingSlots: staticSlots
3764
+ });
3765
+ if (holes.length === 0 || !response.body)
3766
+ return response;
3767
+ const headers = cloneHeaders(response);
3768
+ headers.set(PARTIAL_HOLES_HEADER, encodePartialHoles(holes.map((slot) => slot.id)));
3769
+ const body = staticSlots.length > 0 ? response.body : injectStreamingRuntimeIntoStream(response.body, options.nonce, options.runtimePlacement, options.runtimePreludeScript);
3770
+ return new Response(body, {
3771
+ headers,
3772
+ status: response.status,
3773
+ statusText: response.statusText
3774
+ });
3775
+ };
3776
+ var handOverHoles = async (responseLike, slots, sink) => {
3777
+ sink.slots = slots.filter(isDynamicStreamingSlot);
3778
+ const response = await toResponse(responseLike);
3779
+ await response.body?.cancel().catch(() => {
3780
+ return;
3781
+ });
3782
+ return new Response(null, { status: 204 });
3783
+ };
3407
3784
  var withRegisteredStreamingSlots = async (renderResponse, options = {}) => {
3408
3785
  const { result, slots } = await runWithStreamingSlotRegistry(renderResponse);
3409
3786
  const explicit = options.streamingSlots ?? [];
3787
+ const streamingSlots = mergeStreamingSlots(slots, explicit);
3788
+ const holesSink = activePartialHolesSink();
3789
+ if (holesSink)
3790
+ return handOverHoles(result, streamingSlots, holesSink);
3791
+ if (isPartialShellCapture(getCurrentAbsoluteRequest())) {
3792
+ return captureStaticShell(result, streamingSlots, options);
3793
+ }
3410
3794
  return withStreamingSlots(result, {
3411
3795
  ...options,
3412
- streamingSlots: mergeStreamingSlots(slots, explicit)
3796
+ streamingSlots
3413
3797
  });
3414
3798
  };
3415
3799
 
3416
3800
  // src/core/streamingSlotWarningScope.ts
3417
3801
  init_logger();
3418
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
3802
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
3419
3803
  var STREAMING_SLOT_WARNING_STORAGE_KEY2 = Symbol.for("absolutejs.streamingSlotWarningAsyncLocalStorage");
3420
3804
  var isObjectRecord4 = (value) => Boolean(value) && typeof value === "object";
3421
3805
  var isAsyncLocalStorage3 = (value) => isObjectRecord4(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
@@ -3431,7 +3815,7 @@ var ensureWarningStorage = () => {
3431
3815
  if (existing) {
3432
3816
  return existing;
3433
3817
  }
3434
- const storage = new AsyncLocalStorage3;
3818
+ const storage = new AsyncLocalStorage4;
3435
3819
  Reflect.set(globalThis, STREAMING_SLOT_WARNING_STORAGE_KEY2, storage);
3436
3820
  return storage;
3437
3821
  };
@@ -3462,7 +3846,9 @@ setStreamingSlotWarningController({
3462
3846
  }
3463
3847
  });
3464
3848
  var captureStreamingSlotWarningCallsite = () => {
3465
- if (false) {}
3849
+ if (isProductionRuntime()) {
3850
+ return;
3851
+ }
3466
3852
  const { stack } = new Error;
3467
3853
  if (!stack) {
3468
3854
  return;
@@ -3474,18 +3860,112 @@ var runWithStreamingSlotWarningScope = (task, metadata) => ensureWarningStorage(
3474
3860
  // src/svelte/pageHandler.ts
3475
3861
  init_routeAssets();
3476
3862
  init_inlinePageCss();
3863
+ init_ssrErrorPage();
3477
3864
  init_spaRouteManifest();
3478
3865
  init_resolveConvention();
3479
3866
  init_browserTranslation();
3480
- var isRecord3 = (value) => typeof value === "object" && value !== null;
3481
- var isGenericSvelteComponent = (value) => typeof value === "function" || isRecord3(value);
3867
+
3868
+ // src/svelte/routerSsr.ts
3869
+ init_lazyModule();
3870
+ var SVELTE_ROUTER_SSR_CONTEXT_KEY = Symbol.for("absolutejs.svelte-router.ssr");
3871
+ var REDIRECT_STATUS = 302;
3872
+ var FORBIDDEN_STATUS = 403;
3873
+ var runSequentially = async (tasks, index = 0) => {
3874
+ const task = tasks[index];
3875
+ if (!task)
3876
+ return;
3877
+ await task();
3878
+ await runSequentially(tasks, index + 1);
3879
+ };
3880
+ var toResolved = (value) => {
3881
+ const component = toLazyComponent(value);
3882
+ const resolved = component ? { component, source: readLazySource(value) } : {
3883
+ error: new Error('A lazy <Route> loader must resolve to a Svelte component or to a module whose default export is one, e.g. `() => import("./Page.svelte")`.')
3884
+ };
3885
+ return resolved;
3886
+ };
3887
+ var createSvelteRouterSsr = (request) => {
3888
+ const tasks = [];
3889
+ const pending = new Map;
3890
+ const resolved = new Map;
3891
+ let outcome;
3892
+ const state = {
3893
+ request,
3894
+ resolved,
3895
+ settledGuards: new Set,
3896
+ afterRender: (task) => {
3897
+ tasks.push(task);
3898
+ },
3899
+ load: (key, loader) => {
3900
+ if (resolved.has(key) || pending.has(key))
3901
+ return;
3902
+ const settle = Promise.resolve().then(loader).then((value) => {
3903
+ resolved.set(key, toResolved(value));
3904
+ }, (error) => {
3905
+ resolved.set(key, { error });
3906
+ });
3907
+ pending.set(key, settle);
3908
+ },
3909
+ outcome: () => outcome,
3910
+ setOutcome: (next) => {
3911
+ outcome ??= next;
3912
+ }
3913
+ };
3914
+ const settle = async () => {
3915
+ await runSequentially(tasks.splice(0));
3916
+ if (outcome !== undefined)
3917
+ return false;
3918
+ if (pending.size === 0)
3919
+ return false;
3920
+ const loads = Array.from(pending.values());
3921
+ pending.clear();
3922
+ await Promise.all(loads);
3923
+ return true;
3924
+ };
3925
+ const response = () => {
3926
+ if (!outcome)
3927
+ return;
3928
+ if (outcome.kind === "redirect") {
3929
+ return new Response(null, {
3930
+ headers: { Location: outcome.location },
3931
+ status: REDIRECT_STATUS
3932
+ });
3933
+ }
3934
+ return new Response("Forbidden", {
3935
+ headers: { "Content-Type": "text/plain; charset=utf-8" },
3936
+ status: FORBIDDEN_STATUS
3937
+ });
3938
+ };
3939
+ const bootstrapScript = () => {
3940
+ const sources = {};
3941
+ for (const [key, entry] of resolved) {
3942
+ if ("component" in entry && entry.source)
3943
+ sources[key] = entry.source;
3944
+ }
3945
+ if (Object.keys(sources).length === 0)
3946
+ return "";
3947
+ return `window.__ABS_SVELTE_LAZY_ROUTES__=${JSON.stringify(sources)};`;
3948
+ };
3949
+ return {
3950
+ bootstrapScript,
3951
+ context: new Map([
3952
+ [SVELTE_ROUTER_SSR_CONTEXT_KEY, state]
3953
+ ]),
3954
+ response,
3955
+ settle
3956
+ };
3957
+ };
3958
+
3959
+ // src/svelte/pageHandler.ts
3960
+ var isRecord5 = (value) => typeof value === "object" && value !== null;
3961
+ var isGenericSvelteComponent = (value) => typeof value === "function" || isRecord5(value);
3482
3962
  var readHasIslands = (value) => {
3483
- if (!isRecord3(value))
3963
+ if (!isRecord5(value))
3484
3964
  return false;
3485
3965
  const hasIslands = value["__ABSOLUTE_PAGE_HAS_ISLANDS__"];
3486
3966
  return typeof hasIslands === "boolean" ? hasIslands : false;
3487
3967
  };
3488
- var readDefaultExport = (value) => isRecord3(value) ? value.default : undefined;
3968
+ var readDefaultExport = (value) => isRecord5(value) ? value.default : undefined;
3489
3969
  var primeSvelteStream = async (stream) => {
3490
3970
  const reader = stream.getReader();
3491
3971
  const firstChunk = await reader.read();
@@ -3531,7 +4011,7 @@ var handleSveltePageRequest = async (input) => {
3531
4011
  const userProps = input.props;
3532
4012
  const request = input.request ?? getCurrentAbsoluteRequest();
3533
4013
  const requestPathname = resolveRequestPathname(request);
3534
- const resolvedProps = requestPathname !== undefined && (!isRecord3(userProps) || !("url" in userProps)) ? {
4014
+ const resolvedProps = requestPathname !== undefined && (!isRecord5(userProps) || !("url" in userProps)) ? {
3535
4015
  ...userProps ?? {},
3536
4016
  url: requestPathname
3537
4017
  } : userProps;
@@ -3597,13 +4077,19 @@ var handleSveltePageRequest = async (input) => {
3597
4077
  await Promise.resolve().then(() => init_renderToReadableStream());
3598
4078
  const resolvedPage = await resolvePageComponent();
3599
4079
  const siblingCss = await readSiblingCss(resolvedPagePath);
3600
- const cssBlock = siblingCss ? `<style data-absolute-page-css>${siblingCss}</style>` : "";
4080
+ const cssBlock = siblingCss ? `<style data-absolute-page-css${nonceAttr()}>${siblingCss}</style>` : "";
3601
4081
  const composedHeadContent = `${cssBlock}${withDeferredStylesheets(resolvedOptions?.headContent ?? "", deferredAssets)}`;
4082
+ const routerSsr = createSvelteRouterSsr(request);
3602
4083
  const stream = await renderToReadableStream(resolvedPage.component, resolvedProps, {
3603
4084
  bodyContent: resolvedOptions?.bodyContent,
3604
- bootstrapScriptContent: `${BROWSER_TRANSLATION_BASELINE_SCRIPT}window.__ABS_SLOT_HYDRATION_PENDING__=true;window.__INITIAL_PROPS__=${JSON.stringify(resolvedProps)};${resolvedIndexPath ? `import(${JSON.stringify(resolvedIndexPath)});` : ""}`,
3605
- headContent: composedHeadContent
4085
+ context: routerSsr.context,
4086
+ headContent: composedHeadContent,
4087
+ settle: routerSsr.settle,
4088
+ bootstrapScriptContent: () => `${BROWSER_TRANSLATION_BASELINE_SCRIPT}window.__ABS_SLOT_HYDRATION_PENDING__=true;${routerSsr.bootstrapScript()}window.__INITIAL_PROPS__=${JSON.stringify(resolvedProps)};${resolvedIndexPath ? `import(${JSON.stringify(resolvedIndexPath)});` : ""}`
3606
4089
  });
4090
+ const routerResponse = routerSsr.response();
4091
+ if (routerResponse)
4092
+ return routerResponse;
3607
4093
  const htmlStream = injectIslandPageContextStream(stream, {
3608
4094
  hasIslands: resolvedPage.hasIslands ? true : undefined
3609
4095
  });
@@ -3632,9 +4118,18 @@ var handleSveltePageRequest = async (input) => {
3632
4118
  }), request);
3633
4119
  }
3634
4120
  };
4121
+
4122
+ // src/svelte/fileRoute.ts
4123
+ var svelteFileRoute = (route) => defineFileRouteWith("svelte", route, async ({ manifest, props, request }) => handleSveltePageRequest({
4124
+ indexPath: asset(manifest, `${route.name}Index`),
4125
+ pagePath: asset(manifest, route.name),
4126
+ props,
4127
+ request
4128
+ }));
3635
4129
  export {
3636
- handleSveltePageRequest
4130
+ handleSveltePageRequest,
4131
+ svelteFileRoute
3637
4132
  };
3638
4133
 
3639
- //# debugId=00CAECF858B4E16264756E2164756E21
4134
+ //# debugId=E85559ACF34AD14564756E2164756E21
3640
4135
  //# sourceMappingURL=server.js.map