@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
package/changelog.json CHANGED
@@ -2,6 +2,234 @@
2
2
  "contract": 1,
3
3
  "name": "@absolutejs/absolute",
4
4
  "releases": [
5
+ {
6
+ "changes": [
7
+ {
8
+ "detail": "The surgical Angular HMR path compiled `styleUrl` files synchronously, which Less and Stylus don't support. Editing a component whose `styleUrl` was a `.less` or `.styl` file showed \"Style file not found\" for a file that existed, and the update stalled behind the error overlay. The fast path now compiles Less and Stylus with their async compilers. A style that exists but fails to compile reports the compiler's error instead of \"not found\". The production build and the dev rebuild path already handled Less and Stylus.",
9
+ "kind": "fixed",
10
+ "summary": "Angular HMR applies edits to components whose `styleUrl` is Less or Stylus, and reports style compile errors accurately"
11
+ },
12
+ {
13
+ "detail": "Angular pages ran zoneless only, so apps and libraries that rely on zone.js (NgZone, change detection after timers or manually added event listeners) didn't update. Set `angular: { changeDetection: 'zone' }` in absolute.config.ts and add zone.js to your app (`bun add zone.js`). Server rendering then waits for the timers and requests a page starts, the browser loads zone.js before Angular boots, and hydration and HMR keep working. Async functions in your Angular code are compiled to generators in this mode, because zone.js can't follow native `await`. Elysia routes keep working with zone.js loaded on the server. The default stays zoneless. Angular islands still render zoneless in zone mode.",
14
+ "kind": "added",
15
+ "summary": "Angular pages can opt into zone.js change detection"
16
+ },
17
+ {
18
+ "detail": "`absolute add <framework>` failed with \"Could not find defineConfig\" on the config create-absolutejs writes (`import { defineConfig } …` followed by `export default defineConfig({…})`). The config walker passed `pending.push(child)` straight to TypeScript's `forEachChild`, which stops at the first truthy callback result, so only a file's first statement (the import) was ever searched. The auth config readers behind `absolute config` had the same bug and are fixed too. `absolute generate page --framework angular` now writes a self-contained page with its nav baked in, like the static pages, instead of importing `../../shared/navData` from outside the Angular directory.",
19
+ "kind": "fixed",
20
+ "summary": "`absolute add` edits scaffolded configs, and generated Angular pages no longer import shared files"
21
+ },
22
+ {
23
+ "detail": "Call `enableNavigation()` from `@absolutejs/absolute/client/navigation` on your pages and a link from a page in one framework to a page in another (a React page to a Svelte page, say) no longer reloads the browser. The target page's HTML is fetched, its stylesheets load first, the current page is torn down, the head and body are swapped (in a View Transition where the browser supports one), and the target page hydrates. Island stores made with `createIslandStore` keep their values, back and forward work across the two pages with their scroll positions, and the new page's title is announced to screen readers. Links inside a framework's own router still navigate through that router. Under `secureHeaders()` the swapped-in page's scripts and styles run with the current page's nonce, but only those that carried their own response's nonce. Add `data-absolute-navigation=\"off\"` to a link (or a parent) to get a normal page load; any failure also falls back to one. The Svelte router's `<Link>` now leaves a URL that no mounted `<Router>` matches to this navigation when it is enabled. This release is tested with React and Svelte pages. Vue and Angular pages have the same teardown hook but are not tested yet. HTML and HTMX pages have none, so leaving one is still a normal page load.",
24
+ "kind": "added",
25
+ "summary": "Links between pages built with different frameworks can navigate without a full page reload"
26
+ },
27
+ {
28
+ "detail": "Vue and Ember wrote a page's initial props into an inline script with a plain `JSON.stringify`, so a prop value containing `</script>` ended the script and the rest of the value was parsed as HTML: an XSS hole for any page that passes user-provided data as props. The same applied to Angular's `requestContext`, the island state and manifest scripts, and JSON-LD (`generateHeadElement`, the React and Svelte `JsonLd` components). All of these now escape `<`, U+2028 and U+2029, as React and Svelte page props already did. The data is unchanged once parsed.",
29
+ "kind": "security",
30
+ "summary": "Initial props, request context, island state and JSON-LD can no longer break out of their inline <script>"
31
+ },
32
+ {
33
+ "detail": "Opt-in file routes for React and Svelte pages. With `fileRoutes: true` in absolute.config.ts, each file under `<reactDirectory>/routes/` or `<svelteDirectory>/routes/` becomes a GET route: `index.tsx` serves `/`, `blog/index.tsx` serves `/blog`, and `blog/[slug].tsx` serves `/blog/:slug`. Files and folders starting with `_` are private, so components can live next to routes. A sibling `blog/[slug].server.ts` can export `load`, whose result becomes the page's props, and `beforeHandle`, which can answer the request first (for example with a redirect). The build writes a route module (`src/routes.gen.ts` by default, `fileRoutes.output` to change it); pass its `routeTree` to `fileRoutes(routeTree, manifest)` after `prepare()`. The route module checks types: `load` must take the route's params and return the page's props, so a renamed param or a missing prop is a type error. Explicit routes stay the default and win over a file route for the same path. In `absolute dev`, adding, renaming or removing a route file updates the routes without a restart. Catch-all, optional and group segments, Vue, Angular and HTML routes, and per-folder conventions are planned. See docs/FILE_ROUTER_PLAN.md.",
34
+ "kind": "added",
35
+ "summary": "Opt-in file routes for React and Svelte pages, with typed `load` functions",
36
+ "symbols": [
37
+ "fileRoutes",
38
+ "reactFileRoute",
39
+ "svelteFileRoute",
40
+ "FileRouteContext"
41
+ ]
42
+ },
43
+ {
44
+ "detail": "`defineAction(path, { body, handler })` defines a form action: a POST route that checks the form against an Elysia `t.Object` schema and works with or without JavaScript. Without JavaScript a plain `<form method=\"post\">` posts, the browser is sent back to the page (or to `redirect`) and the page shows the result: React and other SSR pages read it with `getActionState(action)` and pass it as a prop, and static HTML and HTMX pages get the errors, the success message and what the user typed written into `<form data-absolute-action>` by the server. With JavaScript, React's `useFormAction` hook (from `@absolutejs/absolute/react/hooks`) and `enhanceForms()` for plain pages (from `@absolutejs/absolute/client`) submit without a reload and expose pending, the typed result and one error message per field. HTMX `hx-post` forms get the action's `htmx` fragment, or behave like a plain post. Cross-site posts are refused (403), bodies over `maxBodySize` (default 10 MiB) are refused before they are read (413), and JSON clients such as Eden get JSON.",
45
+ "kind": "added",
46
+ "summary": "Form actions: one handler for forms that work without JavaScript and update in place with it, on React, static HTML and HTMX pages"
47
+ },
48
+ {
49
+ "detail": "HTML and HTMX pages can share markup with `<abs-include src=\"../partials/header.html\"></abs-include>`, which is replaced at build time with the file's contents. Paths are relative to the including file, and included files can include others. A layout marks where content goes with `<abs-slot>` and `<abs-slot name=\"head\">`; a page fills the slots through the include's children and `<template slot=\"head\">`. Includes are expanded before asset paths, image optimization and island rendering, so included markup gets all three. A missing file or an include cycle fails the build and shows the chain. Only the `.html` files directly in `pages/` are pages. In dev, editing a partial or layout updates every page that includes it. See docs/HTML_INCLUDES.md.",
50
+ "kind": "added",
51
+ "summary": "Layouts and partials for HTML and HTMX pages with `<abs-include>` and `<abs-slot>`"
52
+ },
53
+ {
54
+ "detail": "Apps can now be translated. `defineI18n()` takes your locales, the default locale's messages and a loader for each other locale, and `i18nPlugin()` works out each request's locale from the URL prefix (`/fr/about`), the domain, or the visitor's cookie and `Accept-Language` header. Handlers get `locale` and an `i18n` object: `i18n.t('key', params)` formats ICU messages (plurals, select, numbers, dates) with the platform's `Intl`, and `i18n.payload(['namespace'])` returns the messages a page needs to hydrate, which you pass as a page prop. React pages read them with `I18nProvider` and `useI18n()` from `@absolutejs/absolute/react/hooks`; Svelte pages with `setI18n()` and `getI18n()` from `@absolutejs/absolute/svelte`. Message keys and their parameters are type-checked against the default catalog, and a locale missing a key is a type error. `i18n.alternates()` builds hreflang links, which the `alternates` field of `Metadata` renders in `generateHeadElement` and the React and Svelte `Head` components. Setting `sitemap.i18n` lists every page once per locale with hreflang alternates. Svelte pages get the request's `lang` and `dir` on `<html>`. The browser-safe helpers (`createTranslator`, `formatMessage`, `localizePath`, `negotiateLocale`, `localeDirection`) are exported from `@absolutejs/absolute/i18n`. See docs/I18N_PLAN.md.",
55
+ "kind": "added",
56
+ "summary": "Internationalization: locale routing, typed ICU message catalogs, React and Svelte translation APIs, hreflang links and a per-locale sitemap",
57
+ "symbols": [
58
+ "defineI18n",
59
+ "i18nPlugin",
60
+ "getRequestLocale",
61
+ "I18nProvider",
62
+ "useI18n",
63
+ "setI18n",
64
+ "getI18n",
65
+ "createTranslator",
66
+ "defineMessages",
67
+ "formatMessage",
68
+ "Metadata",
69
+ "generateHeadElement",
70
+ "Head",
71
+ "SitemapConfig",
72
+ "BaseBuildConfig"
73
+ ]
74
+ },
75
+ {
76
+ "detail": "An HTML page and an HTMX page with the same file name (both `pages/Home.html`) share the manifest key `Home`. The build only warned \"Manifest key collision … overwritten\", and both routes then served whichever page was processed last. The build now fails and names both source files. In dev the error is reported like any other failed build pass. Key naming is unchanged.",
77
+ "kind": "breaking",
78
+ "migration": {
79
+ "instruction": "If the build reports \"Manifest key \\\"…\\\" belongs to two pages\", rename one of the two files (for example `htmx/pages/Home.html` to `htmx/pages/HtmxHome.html`) and update the `asset(manifest, …)` call in its route. Builds without a collision are unaffected.",
80
+ "manual": true
81
+ },
82
+ "summary": "Two pages with the same name in the HTML and HTMX directories are a build error instead of one silently replacing the other",
83
+ "symbols": [
84
+ "asset",
85
+ "build"
86
+ ]
87
+ },
88
+ {
89
+ "detail": "A pre-rendered page used to be either fully cached or fully rendered per request. Now a streaming slot marked `dynamic` (`<StreamSlot dynamic>` or `<SuspenseSlot dynamic>` in React, the `dynamic` prop or `<!-- absolute:stream dynamic -->` in Svelte) stays a hole in the pre-rendered page. On a route listed in `static.routes`, the build stores the page as a static shell: other slots are resolved into it, and dynamic slots keep their fallback. Each request gets the cached shell at once, before the route handler runs. Only the dynamic slots are then rendered, with the visitor's cookies and headers, and streamed into the page, carrying the request's CSP nonce under `secureHeaders()`. Revalidation (`static.revalidate`) re-captures the shell. Pages without a dynamic slot are pre-rendered as before. Vue and Angular support comes later.",
90
+ "kind": "added",
91
+ "summary": "Partial prerendering: pre-rendered React and Svelte pages serve a cached shell instantly and stream their `dynamic` slots per request",
92
+ "symbols": [
93
+ "StreamSlot",
94
+ "SuspenseSlot",
95
+ "StreamingSlot"
96
+ ]
97
+ },
98
+ {
99
+ "detail": "Bun's bundler replaces a literal `process.env.NODE_ENV` with its build-time value, and with nothing defined that value is \"development\". The published dist/ was built that way, so every such check was a constant: `absolute start` and compiled binaries ran development code with NODE_ENV=production. Error convention pages received `error.stack`; Vue pages with `client: 'none'` shipped the ~130 KB inline dev reload client; React pages emitted the Fast Refresh setup; Angular pages stat'ed their module on every request; and the island-bootstrap and streaming-slot dev warnings stayed on. The library build now leaves `process.env.NODE_ENV` a runtime read, the source reads it through `src/utils/runtimeMode.ts`, and a lint rule rejects a literal `process.env.NODE_ENV` in src/.",
100
+ "kind": "security",
101
+ "summary": "Production servers no longer run development code paths: error pages stop exposing stacks, and `client: 'none'` Vue pages stop shipping the dev reload client"
102
+ },
103
+ {
104
+ "detail": "The production server bundle had no source map, so errors logged by `absolute start` pointed into dist/server.js. The Svelte, Vue and Angular SSR page bundles had none either; only dev chained their maps back to the source. The server bundle now gets a linked map, and the SSR page bundles get the same inline-and-chained maps as dev. A route handler error points at its line in your server file, and a page component error at its `.svelte`/`.vue` file. Svelte frames used to name a nonexistent file next to the build output (`build/svelte/pages/Page.svelte`), because Svelte records the source by basename; they now resolve to the original file, in dev too. Neither map is served publicly. The \"Could not decode sourcemap\" warning was fixed in the previous release.",
105
+ "kind": "fixed",
106
+ "summary": "Production stack traces point at your server file and page components instead of the bundled output"
107
+ },
108
+ {
109
+ "detail": "Set `reactServerComponentsDirectory` in absolute.config.ts and put pages in its `pages` folder. Pages are server components: they can be async and read data directly, and that code never ships to the browser. Components marked `\"use client\"` are server-rendered, then hydrated in the browser. Serve a page from any Elysia route with `handleReactServerPageRequest({ page: asset(manifest, '<Page>RSC'), props })`. `<Suspense>` boundaries stream, and the inline scripts carry the CSP nonce when `secureHeaders()` is on. Install `react-server-dom-webpack` at the same version as `react` (19.2.3 or later). Existing React pages are unchanged. Server Actions, client-side navigation and HMR for these pages are not available yet; edits reload after the dev server restarts.",
110
+ "kind": "added",
111
+ "summary": "Opt-in React Server Components for React pages served from Elysia routes"
112
+ },
113
+ {
114
+ "detail": "The image optimizer created its cache directory (`<build>/.cache/images` unless `images.cacheDirectory` is set) when the server started, so a production server that could not write its build directory crashed on boot with `EACCES` or `EROFS`, even if the app never optimized an image. That is the usual container setup: the build copied in as root and the server running as a non-root user, or a read-only root filesystem. The directory is now created on the first image written to the cache. When it cannot be written, images are still optimized and served, just not cached. A prepared build now starts from a read-only directory with an empty HOME and writes nothing outside TMPDIR.",
115
+ "kind": "fixed",
116
+ "summary": "Production servers start when their build directory is read-only, such as in a container running as a non-root user"
117
+ },
118
+ {
119
+ "detail": "`pageRouterPlugin` was a placeholder that only logged \"Page Router Plugin Not Implemented Yet\" and registered nothing, so removing it changes no behavior.",
120
+ "kind": "removed",
121
+ "migration": {
122
+ "instruction": "Delete the `pageRouterPlugin` import and call; it never did anything. Register page routes with Elysia (`.get(path, () => handle…PageRequest(…))`) as before.",
123
+ "manual": true
124
+ },
125
+ "summary": "Remove the unimplemented `pageRouterPlugin` export",
126
+ "symbols": [
127
+ "pageRouterPlugin"
128
+ ]
129
+ },
130
+ {
131
+ "detail": "`secureHeaders()` is an opt-in Elysia plugin that sends a Content-Security-Policy with a per-request nonce (`'strict-dynamic'`, no `'unsafe-inline'` for scripts), plus `X-Content-Type-Options: nosniff`, `Referrer-Policy`, `frame-ancestors` and `Permissions-Policy`, each overridable. Every inline `<script>` and `<style>` AbsoluteJS writes carries the nonce: page bootstraps and initial props for every framework, island state, streaming-slot patches, inline page CSS, Svelte and Angular component styles, speculation rules, the error pages and the dev HMR client. The nonce is added where each script is written, so a script injected through `{@html}` / `v-html` / `dangerouslySetInnerHTML` stays blocked. Pre-rendered and ISR pages store the nonce they were rendered with and swap it for each request's, on scripts, styles and `<link rel=\"modulepreload\">`. A page pre-rendered without the plugin is served without a policy and logged. In development the policy also allows the HMR WebSocket and `'unsafe-eval'` (Angular's dev compiler). `getCspNonce()` and the `cspNonce` context value give your own inline scripts the nonce. See docs/SECURITY_HEADERS.md.",
132
+ "kind": "added",
133
+ "summary": "`secureHeaders()`: a strict nonce-based Content-Security-Policy and security headers for every framework",
134
+ "symbols": [
135
+ "secureHeaders",
136
+ "getCspNonce"
137
+ ]
138
+ },
139
+ {
140
+ "detail": "A new `fonts` option in `absolute.config.ts` downloads Google Fonts (or copies local font files) at build time and serves them from your own origin with content-hashed names and a one-year immutable cache. The build writes one linked stylesheet with `font-display: swap`, a size-adjusted fallback face per family so text does not shift while the font loads, and a `--font-<family>` variable and `.font-<family>` class. Pass `fontAssets(manifest)` to the `fonts` option of `Head` (React, Svelte) or `generateHeadElement`; HTML and HTMX pages get the preload and stylesheet tags automatically. Downloads are cached between builds; a failed download stops the build unless `fallbackToRemote` is set. Hashed static files served by a plain GET now also get the immutable cache header; before, only precompressed copies did.",
141
+ "kind": "added",
142
+ "summary": "Self-hosted, preloaded fonts with layout-stable fallbacks from the `fonts` config"
143
+ },
144
+ {
145
+ "detail": "`absolute start` writes the bundled server into the build directory, and that directory is also the static root, so `GET /server.js` downloaded the whole backend. The same applied to its `.br`/`.gz` copies, to the Svelte/Vue/Angular SSR page bundles under `<framework>/server/`, to the compiled convention pages, and to `absolute-runtime.json`, `conventions.json` and `spa-routes.json`. Production static serving now excludes those, plus `.map` files and native `.node` addons. The build records every file its server pass writes in `server-outputs.json`, and those are excluded by exact path, so SSR bundles are covered wherever the layout of a project puts them (a Svelte-only build writes them to `svelte/pages/`, Angular to `angular/src/…`). The precompressed handler applies the same list. The server still reads all of them from disk.",
146
+ "kind": "security",
147
+ "summary": "Production servers no longer serve their own server bundle, SSR bundles or runtime manifests as static files"
148
+ },
149
+ {
150
+ "detail": "The production server bundle has no source map, but the AbsoluteJS code inside it builds inline source map comments for Svelte and Vue output. Those were template literals starting with `\\n`, which Bun's bundler emits as a real newline, leaving a line that starts `//# sourceMappingURL=data:…${…}` in the middle of dist/server.js. Bun read that line as the bundle's own source map whenever it built a stack trace, and warned that it couldn't decode it.",
151
+ "kind": "fixed",
152
+ "summary": "`absolute start` no longer warns \"Could not decode sourcemap in dist/server.js\" on the first error"
153
+ },
154
+ {
155
+ "detail": "`handleHTMLPageRequest` and `handleHTMXPageRequest` now render the error convention when a page can't be served (its file is missing or unreadable, or it fails a static-page check). They return status 500 with `<Page>.error.html` or `error.html`, like the framework handlers, and `{{ stack }}` is empty in production. Before, the error went unhandled. HTMX pages use the HTMX pages directory's error page first. An HTMX request (`HX-Request: true`) to an unknown route gets that directory's `not-found.html` first. Having `error.html` or `not-found.html` in both the HTML and HTMX directories no longer counts as a page name collision. `loading.html` doesn't apply to static pages; see docs/STATIC_PAGE_CONVENTIONS.md.",
156
+ "kind": "fixed",
157
+ "summary": "HTML and HTMX pages render their error.html when they fail, and HTMX requests get the HTMX not-found.html",
158
+ "symbols": [
159
+ "ConventionsMap"
160
+ ]
161
+ },
162
+ {
163
+ "detail": "`SuspenseSlot` rendered its resolved content with React's `renderToStaticMarkup`, but `absolute start` strips React's legacy string renderer out of the production server bundle to save about 4,000 lines. In production every SuspenseSlot patch failed with `renderToStaticMarkup is not a function`, so the fallback stayed on the page. The slot now renders with `renderToReadableStream`, which the bundle keeps.",
164
+ "kind": "fixed",
165
+ "summary": "React `SuspenseSlot` content streams in production builds",
166
+ "symbols": [
167
+ "SuspenseSlot"
168
+ ]
169
+ },
170
+ {
171
+ "detail": "The packaged Svelte `Head` component imports a small icon helper by relative path, and the package shipped the component without that file, so any app using `Head` from `@absolutejs/absolute/svelte/components/Head.js` failed to build with \"Could not resolve ../../utils/iconVersion\". The helper now ships next to the components.",
172
+ "kind": "fixed",
173
+ "summary": "Apps using the Svelte `Head` component build again"
174
+ },
175
+ {
176
+ "detail": "On every Svelte component update the HMR client read the first number out of the page's first `<button>`, stored it in sessionStorage and remounted the page with it as an `initialCount` prop. On a page whose first button said \"Page 1\", editing any component reset a counter elsewhere on the page and injected `initialCount: 1`. The scaffold's demo only worked because its first button happened to be the counter. The client now leaves state to Svelte's own HMR and never reads it from the DOM. The dev server also stopped re-importing the components that import an edited `.svelte` file: `$.hmr` already swaps the edited component in place, and re-importing the page re-created every component under it. As in any Svelte setup, the edited component itself restarts from its props, and components elsewhere on the page keep their `$state`.",
177
+ "kind": "fixed",
178
+ "summary": "Svelte HMR keeps component state instead of remounting the page with a number read from the first button"
179
+ },
180
+ {
181
+ "detail": "Every `{#await}` with a pending branch was rewritten into a streaming slot, and any page containing one had hydration switched off. Buttons on such a page never worked; without `collectStreamingSlots: true` the pending branch showed forever; with it, a component in the `then` branch arrived as literal text; `{#if}` inside a branch failed to compile; and a shorthand `{#await x then y}` followed by a normal block failed with \"Unterminated regular expression\", because the pattern matched across both. A plain `{#await}` is now left to Svelte, which renders the pending branch on the server and resolves and hydrates it in the browser. Streaming is opt-in with `<!-- absolute:stream -->` directly before the block. A streamed block's branches are sent as HTML, so a component or logic block inside one is a build error, and only pages that stream a block skip hydration.",
182
+ "kind": "breaking",
183
+ "migration": {
184
+ "instruction": "To keep server-side streaming for an `{#await}` block, put `<!-- absolute:stream -->` directly before it and keep its branches to elements and `{expressions}`. Unmarked blocks now render the pending branch on the server and resolve in the browser.",
185
+ "manual": true
186
+ },
187
+ "summary": "Svelte `{#await}` blocks render and hydrate natively; server streaming is opt-in with `<!-- absolute:stream -->`",
188
+ "symbols": [
189
+ "handleSveltePageRequest"
190
+ ]
191
+ },
192
+ {
193
+ "detail": "Route guards: a `guard` on `<Route>` or `<Router>`, and `beforeNavigate()` for browser-only checks, runs before `<Link>` clicks, `goto()` and back/forward, and can be async. It returns nothing to allow, `false` to cancel or a URL / `redirect()` to redirect. Cancelling back/forward puts the URL back. Route and Router guards also run during the server render, where a redirect is a 302. Lazy routes: `<Route loader={() => import(\"./Page.svelte\")}>` puts the component in its own chunk, loaded when the route is first visited or when a `<Link>` to it is prefetched, with optional `pending` and `error` snippets. The server renders the real component and the browser loads its chunk before hydrating, so the page doesn't flash. Scroll restoration: while a router is mounted, new navigations start at the top or at the `#hash` target, and back/forward and reload return to where you were. `goto(url, { noScroll: true })` leaves the scroll alone. `goto()` now resolves to what happened (`\"committed\"`, `\"cancelled\"`, `\"redirected\"`, …), and `history.state` holds the router's bookkeeping next to your state, which `page.state` still returns unchanged. Smaller additions that support this: `renderToReadableStream` takes a Svelte `context`, a `settle` callback that can ask for another render pass, and a function for `bootstrapScriptContent`; `observeViewport` and `scheduleHoverPrefetch` take an `onVisible` / `onPrefetch` callback; and the `noScroll` doc on `GotoOptions` now covers `#hash` targets.",
194
+ "kind": "added",
195
+ "summary": "Svelte router: route guards with server redirects, lazy routes, and scroll restoration",
196
+ "symbols": [
197
+ "goto",
198
+ "beforeNavigate",
199
+ "redirect",
200
+ "preloadRoute",
201
+ "GotoOptions",
202
+ "renderToReadableStream",
203
+ "observeViewport"
204
+ ]
205
+ },
206
+ {
207
+ "detail": "`absolute start` bundled its own copy of Svelte into the production server, while Svelte pages load Svelte from node_modules. The two copies kept separate component context, so a page calling `getContext` or `setContext` (the Svelte router does) answered every request with a 500 `lifecycle_outside_component`. The production server now keeps Svelte external when the app has Svelte pages, so there is one copy.",
208
+ "kind": "fixed",
209
+ "summary": "Svelte pages that use `getContext` / `setContext`, including every Svelte router page, no longer fail under `absolute start`"
210
+ },
211
+ {
212
+ "detail": "The build drops the client bundle of a Vue page registered with `client: 'none'`, but it only recognised a string literal. `client: CLIENT_MODE` with `const CLIENT_MODE = 'none'` in the same file still built an unused hydration bundle. The scanner now resolves same-file `const` strings for `client` and for the `asset(manifest, …)` key, including `as const`, `satisfies` and the shorthand `{ client }`. A value it can't know at build time (an import, a `let`, a call) keeps the client bundle, which still works and just isn't trimmed.",
213
+ "kind": "fixed",
214
+ "summary": "Vue pages with `client: 'none'` set through a same-file const skip their unused client bundle"
215
+ },
216
+ {
217
+ "detail": "Vue pages could only get server data as props from the route handler. `useServerData(key, fetcher)`, exported from `@absolutejs/absolute/vue`, runs the fetcher while the page renders on the server and writes the result into the page, so hydration shows it without fetching again. A client-side route change, a page that exports `routes`, or `server: false` fetches in the browser instead. It returns `data`, `error`, `pending` and `refresh` refs, with `data` typed from the fetcher. A fetcher that throws on the server renders an error state rather than failing the page (in production the message sent to the browser is generic). Using one key twice in a request fails the page with a clear error outside production. Pages with `client: 'none'` render the data but write nothing into the page, and streaming pages are supported. Streaming-slot patches also no longer land inside the page's own inline scripts.",
218
+ "kind": "added",
219
+ "summary": "Vue pages can load data on the server with `useServerData` and hydrate without a second fetch"
220
+ },
221
+ {
222
+ "detail": "Set `vitals` in absolute.config.ts (`{ endpoint?, sampleRate?, dev? }`) to report LCP, INP, CLS, FCP and TTFB from real visits. A production build bundles a small reporter (web-vitals plus a sender) that every framework's client bundle imports and that static HTML/HTMX pages load with a script tag. Each page load samples once, and a page that reports sends one batch, with its route and navigation type, when it's hidden or closed (`sendBeacon`, falling back to `fetch` keepalive). `prepare()` serves `POST /__absolute/vitals`, validated with a TypeBox schema. It stores nothing; register `onVital(handler)` to forward the metrics to your own store. With `vitals` unset nothing is built or injected, and dev reports only with `dev: true`. It works on pre-rendered pages and under `secureHeaders()`. See docs/WEB_VITALS.md.",
223
+ "kind": "added",
224
+ "summary": "Opt-in Core Web Vitals reporting with `vitals` and `onVital()`",
225
+ "symbols": [
226
+ "onVital"
227
+ ]
228
+ }
229
+ ],
230
+ "date": "2026-11-13",
231
+ "version": "0.20.0-beta.170"
232
+ },
5
233
  {
6
234
  "changes": [
7
235
  {
@@ -9088,6 +9088,9 @@ var require_cjs = __commonJS(function(exports) {
9088
9088
  } });
9089
9089
  });
9090
9090
 
9091
+ // src/utils/runtimeMode.ts
9092
+ var ENV_VAR = "NODE_ENV", getNodeEnv = () => process.env[ENV_VAR], isDevelopmentRuntime = () => process.env[ENV_VAR] === "development", isProductionRuntime = () => process.env[ENV_VAR] === "production";
9093
+
9091
9094
  // src/constants.ts
9092
9095
  var ANGULAR_INIT_TIMEOUT_MS = 500, ANSI_ESCAPE_CODE = 27, ANSI_ESCAPE_LENGTH = 3, ASCII_SPACE = 32, BASE_36_RADIX = 36, BUN_BUILD_WARNING_SUPPRESSION = "wildcard sideEffects are not supported yet", TAILWIND_BUN_CSS_WARNING_PATTERN, BODY_SLICE_LENGTH = 2000, BYTES_PER_KILOBYTE = 1024, CLI_ARGS_OFFSET = 3, CSS_ERROR_RESOLVE_DELAY_MS = 50, CSS_MAX_CHECK_ATTEMPTS = 10, CSS_MAX_PARSE_TIMEOUT_MS = 500, CSS_RELOAD_BACKOFF_BASE_MS = 1000, CSS_RELOAD_BACKOFF_MAX_MS = 60000, CSS_SHEET_READY_TIMEOUT_MS = 100, DEFAULT_CHUNK_SIZE = 16384, DEFAULT_DEBOUNCE_MS = 15, DEFAULT_PORT = 3000, DEV_SERVER_RESTART_DEBOUNCE_MS = 100, DOM_UPDATE_DELAY_MS = 50, FILE_PROTOCOL_PREFIX_LENGTH = 7, FOCUS_ID_PREFIX_LENGTH = 3, FOCUS_IDX_PREFIX_LENGTH = 4, FOCUS_NAME_PREFIX_LENGTH = 5, ESLINT_STUDIO_DEFAULT_HOST = "eslint.absolute.localhost", ESLINT_STUDIO_DEFAULT_PORT = 4099, CONFIG_DEFAULT_HOST = "config.absolute.localhost", CONFIG_DEFAULT_PORT = 4099, HMR_UPDATE_TIMEOUT_MS = 2000, HOOK_SIGNATURE_LENGTH = 12, EXCLUDE_LAST_OFFSET = -1, HTTP_STATUS_OK = 200, HTTP_STATUS_BAD_REQUEST = 400, HTTP_STATUS_NOT_FOUND = 404, HTTP_STATUS_GONE = 410, HOURS_IN_DAY = 24, HOURS_IN_HALF_DAY = 12, IMAGE_DEFAULT_DEVICE_SIZES, IMAGE_DEFAULT_IMAGE_SIZES, IMAGE_DEFAULT_QUALITY = 75, IMAGE_GLOB_SUFFIX_LENGTH = 2, INSTANCE_PROBE_TIMEOUT_MS = 250, MAX_ERROR_LENGTH = 200, MAX_RECONNECT_ATTEMPTS = 60, MILLISECONDS_IN_A_SECOND = 1000, MINUTES_IN_AN_HOUR = 60, SECONDS_IN_A_MINUTE = 60, MILLISECONDS_IN_A_MINUTE, MILLISECONDS_IN_A_DAY, OVERLAY_FADE_DURATION_MS = 150, PING_INTERVAL_MS = 30000, LIST_LOG_TAIL_MAX_BYTES = 65536, LIST_TUI_COLUMN_GAP = 2, LIST_TUI_DEFAULT_HEIGHT = 28, LIST_TUI_DEFAULT_WIDTH = 100, LIST_TUI_ESCAPE_SEQUENCE_TIMEOUT_MS = 30, LIST_TUI_FOOTER_LINE_COUNT = 2, LIST_TUI_MARKER_WIDTH = 2, LIST_TUI_MIN_LOG_HEIGHT = 3, LIST_TUI_MIN_URL_WIDTH = 16, LIST_TUI_RENDER_DEBOUNCE_MS = 16, LIST_TUI_STATUS_MESSAGE_TIMEOUT_MS = 4000, LIST_WATCH_REFRESH_MS = 1000, RAF_BATCH_COUNT = 3, RANDOM_ID_END_INDEX = 11, REBUILD_BATCH_DELAY_MS = 10, REBUILD_RELOAD_DELAY_MS = 200, RECONNECT_INITIAL_DELAY_MS = 500, RECONNECT_POLL_INTERVAL_MS = 300, REACT_STREAM_SLOT_FAST_DELAY_MS = 5, REACT_STREAM_SLOT_SLOW_DELAY_MS = 20, SIGINT_EXIT_CODE = 130, SIGTERM_EXIT_CODE = 143, SVELTE_CSS_LOAD_TIMEOUT_MS = 500, TIME_PRECISION = 2, TWO_THIRDS, UNFOUND_INDEX = -1, WEBSOCKET_NORMAL_CLOSURE = 1000, DEFAULT_WEBSOCKET_IDLE_TIMEOUT_SECONDS = 240, DEFAULT_HTTP_IDLE_TIMEOUT_SECONDS = 240, MAX_HTTP_IDLE_TIMEOUT_SECONDS = 255, WORKSPACE_COMMAND_ARGS_OFFSET = 3, WORKSPACE_FAILURE_LOG_PRINT_LIMIT = 30, WORKSPACE_FAILURE_RECENT_LOG_LIMIT = 60, WORKSPACE_READY_ATTEMPT_TIMEOUT_MS = 5000, WORKSPACE_READY_PROBE_INTERVAL_MS = 250, WORKSPACE_READY_TIMEOUT_MS = 30000, WORKSPACE_SHUTDOWN_TIMEOUT_MS = 1e4, WORKSPACE_TUI_DEFAULT_HEIGHT = 28, WORKSPACE_TUI_DEFAULT_WIDTH = 100, WORKSPACE_TUI_ESCAPE_SEQUENCE_TIMEOUT_MS = 30, WORKSPACE_TUI_FOOTER_LINE_COUNT = 3, WORKSPACE_TUI_MIN_LOG_HEIGHT = 3, WORKSPACE_TUI_MIN_SERVICE_NAME_WIDTH = 7, WORKSPACE_TUI_MIN_TARGET_WIDTH = 8, WORKSPACE_TUI_MIN_WRAP_WIDTH = 12, WORKSPACE_TUI_PROMPT_CURSOR_OFFSET = 3, WORKSPACE_TUI_RECENT_LOG_LIMIT = 40, WORKSPACE_TUI_RENDER_DEBOUNCE_MS = 16, WORKSPACE_TUI_STATUS_WIDTH = 10, WORKSPACE_TUI_TARGET_PADDING_WIDTH = 6, WORKSPACE_TUI_VISIBILITY_WIDTH = 8;
9093
9096
  var init_constants = __esm(() => {
@@ -9166,12 +9169,7 @@ var DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, DEFAULT_QUALITY, OPTIMIZATION_END
9166
9169
  const device = config?.deviceSizes ?? DEFAULT_DEVICE_SIZES;
9167
9170
  const image = config?.imageSizes ?? DEFAULT_IMAGE_SIZES;
9168
9171
  return [...device, ...image].sort((left, right) => left - right);
9169
- }, getCacheDir = (buildDir, cacheDirectory) => {
9170
- const dir = cacheDirectory ? resolve(cacheDirectory) : join(buildDir, ".cache", "images");
9171
- if (!existsSync(dir))
9172
- mkdirSync(dir, { recursive: true });
9173
- return dir;
9174
- }, getCacheKey = (url, width, quality, format) => {
9172
+ }, getCacheDir = (buildDir, cacheDirectory) => cacheDirectory ? resolve(cacheDirectory) : join(buildDir, ".cache", "images"), getCacheKey = (url, width, quality, format) => {
9175
9173
  const hasher = new Bun.CryptoHasher("sha256");
9176
9174
  hasher.update(`${url}|${width}|${quality}|${format}`);
9177
9175
  return hasher.digest("hex");
@@ -9288,6 +9286,7 @@ var DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, DEFAULT_QUALITY, OPTIMIZATION_END
9288
9286
  }, writeToCache = (cacheDir, cacheKey, buffer, meta) => {
9289
9287
  const metaPath = join(cacheDir, `${cacheKey}.meta`);
9290
9288
  const dataPath = join(cacheDir, `${cacheKey}.data`);
9289
+ mkdirSync(cacheDir, { recursive: true });
9291
9290
  writeFileSync(dataPath, buffer);
9292
9291
  writeFileSync(metaPath, JSON.stringify(meta));
9293
9292
  };
@@ -9878,7 +9877,7 @@ var setStreamingSlotWarningController = (controller) => {
9878
9877
  Reflect.set(globalThis, STREAMING_SLOT_WARNING_STORAGE_KEY, controller);
9879
9878
  };
9880
9879
  var warnMissingStreamingSlotCollector = (primitiveName) => {
9881
- if (isStreamingSlotCollectionActive()) {
9880
+ if (isProductionRuntime() || isStreamingSlotCollectionActive()) {
9882
9881
  return;
9883
9882
  }
9884
9883
  getWarningController()?.maybeWarn(primitiveName);
@@ -10358,5 +10357,5 @@ export {
10358
10357
  withPendingTask
10359
10358
  };
10360
10359
 
10361
- //# debugId=43DEF2DFD2D62F7064756E2164756E21
10360
+ //# debugId=9E0C82D99D386E9864756E2164756E21
10362
10361
  //# sourceMappingURL=browser.js.map