@rshono/core 1.0.0-rc.16 → 1.0.0-rc.18

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 (73) hide show
  1. package/README.md +29 -5
  2. package/dist/builder/env-shadow-loader.cjs +58 -2
  3. package/dist/builder/rspack-config.d.ts.map +1 -1
  4. package/dist/builder/rspack-config.js +46 -6
  5. package/dist/builder/rspack-config.js.map +1 -1
  6. package/dist/cli/build.d.ts.map +1 -1
  7. package/dist/cli/build.js +24 -1
  8. package/dist/cli/build.js.map +1 -1
  9. package/dist/cli/dev.d.ts.map +1 -1
  10. package/dist/cli/dev.js +4 -0
  11. package/dist/cli/dev.js.map +1 -1
  12. package/dist/cli/index.js +14 -8
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/config.d.ts +10 -0
  15. package/dist/config.d.ts.map +1 -1
  16. package/dist/config.js.map +1 -1
  17. package/dist/deploy/cloudflare/runtime.d.ts.map +1 -1
  18. package/dist/deploy/cloudflare/runtime.js +31 -5
  19. package/dist/deploy/cloudflare/runtime.js.map +1 -1
  20. package/dist/deploy/contract.d.ts +6 -2
  21. package/dist/deploy/contract.d.ts.map +1 -1
  22. package/dist/deploy/contract.js.map +1 -1
  23. package/dist/deploy/filesystem.d.ts.map +1 -1
  24. package/dist/deploy/filesystem.js +2 -1
  25. package/dist/deploy/filesystem.js.map +1 -1
  26. package/dist/deploy/node/runtime.d.ts.map +1 -1
  27. package/dist/deploy/node/runtime.js +3 -4
  28. package/dist/deploy/node/runtime.js.map +1 -1
  29. package/dist/index.d.ts +3 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +3 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/router.d.ts +60 -7
  34. package/dist/router.d.ts.map +1 -1
  35. package/dist/router.js.map +1 -1
  36. package/dist/runtime/context.d.ts +51 -7
  37. package/dist/runtime/context.d.ts.map +1 -1
  38. package/dist/runtime/context.js +49 -5
  39. package/dist/runtime/context.js.map +1 -1
  40. package/dist/runtime/entry.client.js +230 -277
  41. package/dist/runtime/entry.client.js.map +1 -1
  42. package/dist/runtime/entry.rsc.d.ts.map +1 -1
  43. package/dist/runtime/entry.rsc.js +187 -39
  44. package/dist/runtime/entry.rsc.js.map +1 -1
  45. package/dist/runtime/flight-inject.d.ts +1 -1
  46. package/dist/runtime/flight-inject.d.ts.map +1 -1
  47. package/dist/runtime/flight-inject.js +207 -40
  48. package/dist/runtime/flight-inject.js.map +1 -1
  49. package/dist/runtime/navigation.d.ts +4 -0
  50. package/dist/runtime/navigation.d.ts.map +1 -1
  51. package/dist/runtime/navigation.js.map +1 -1
  52. package/dist/runtime/request.d.ts.map +1 -1
  53. package/dist/runtime/request.js +10 -0
  54. package/dist/runtime/request.js.map +1 -1
  55. package/dist/runtime/validate-entries.d.ts +33 -0
  56. package/dist/runtime/validate-entries.d.ts.map +1 -0
  57. package/dist/runtime/validate-entries.js +185 -0
  58. package/dist/runtime/validate-entries.js.map +1 -0
  59. package/dist/server/prerendered.d.ts +30 -6
  60. package/dist/server/prerendered.d.ts.map +1 -1
  61. package/dist/server/prerendered.js +71 -13
  62. package/dist/server/prerendered.js.map +1 -1
  63. package/dist/server/server-config.d.ts +12 -0
  64. package/dist/server/server-config.d.ts.map +1 -1
  65. package/dist/server/server-config.js +25 -0
  66. package/dist/server/server-config.js.map +1 -1
  67. package/dist/server/ssg.d.ts.map +1 -1
  68. package/dist/server/ssg.js +151 -25
  69. package/dist/server/ssg.js.map +1 -1
  70. package/dist/server/static.d.ts.map +1 -1
  71. package/dist/server/static.js +3 -1
  72. package/dist/server/static.js.map +1 -1
  73. package/package.json +7 -6
@@ -1 +1 @@
1
- {"version":3,"file":"entry.client.js","sourceRoot":"","sources":["../../src/runtime/entry.client.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { hydrateRoot } from 'react-dom/client';\nimport {\n createFromFetch,\n createFromReadableStream,\n createTemporaryReferenceSet,\n encodeReply,\n setServerCallback,\n} from 'react-server-dom-rspack/client.browser';\nimport { isControlDigest, parseRedirectDigest } from './control.js';\nimport type { DevMessage } from './dev-protocol.js';\nimport type { RscPayload } from './entry.rsc.js';\n// Dev-only: its one caller sits behind `import.meta.webpackHot`, which a production build compiles to\n// `false` — so this module is dropped there.\nimport { walkHotUpdates } from './hot-update.js';\nimport { RouterContext, type NavigationRouter } from './navigation.js';\nimport { createRscRequest } from './request.js';\n\nconst isDev = process.env.NODE_ENV === 'development';\n\ndeclare global {\n /** The array the payload `<script>` tags `flight-inject.ts` emits push their chunks into. */\n var __FLIGHT_DATA: Array<string | Uint8Array> | undefined;\n}\n\n/** The flight payload the document carried, read back out of `__FLIGHT_DATA` — see `flight-inject.ts`. */\nfunction readFlightPayload(): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n // Assigned synchronously by `start`, which `new ReadableStream` runs before it returns.\n let controller!: ReadableStreamDefaultController<Uint8Array>;\n const stream = new ReadableStream<Uint8Array>({\n start: (c) => void (controller = c),\n });\n const enqueue = (chunk: string | Uint8Array) => controller.enqueue(typeof chunk === 'string' ? encoder.encode(chunk) : chunk);\n\n // Payload scripts interleave with the document: the ones that already ran are in the array, the rest\n // arrive through `push`.\n const data = (self.__FLIGHT_DATA ??= []);\n for (const chunk of data) enqueue(chunk);\n data.push = enqueue as typeof data.push;\n\n // The last payload script lands before parsing finishes, so that is what closes the stream.\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => controller.close(), { once: true });\n } else {\n controller.close();\n }\n return stream;\n}\n\n/** Created at module evaluation, not inside `main()`, so no chunk can be pushed before it is watching. */\nconst flightStream = readFlightPayload();\n\n/**\n * The part of the location a payload is rendered for — the document, without the fragment, which the server\n * never sees. Two URLs that differ only by `#hash` describe the same payload.\n */\nconst documentUrl = (): string => location.pathname + location.search;\n\n/** Guarantees somewhere to attach the fatal overlay: the root container is `document`, so a teardown can take `<body>` with it. */\nfunction overlayHost(): HTMLElement {\n if (!document.documentElement) document.appendChild(document.createElement('html'));\n if (!document.body) document.documentElement.appendChild(document.createElement('body'));\n return document.body;\n}\n\n/**\n * Paints the reason for an uncaught render error over the blank page it leaves behind — the full stack in\n * dev, a generic notice and a reload button in production.\n *\n * DOM calls rather than React (the renderer is what just failed), and `textContent` rather than\n * `innerHTML` (an error message is untrusted input).\n */\nfunction showFatal(error: unknown, componentStack?: string | null): void {\n // Queued: React's teardown runs after this callback returns and would remove a node appended inline.\n setTimeout(() => {\n const host = overlayHost();\n host.querySelector('[data-rshono-fatal]')?.remove();\n\n const box = document.createElement('div');\n box.setAttribute('data-rshono-fatal', '');\n box.setAttribute('role', 'alert');\n box.style.cssText =\n 'position:fixed;inset:0;z-index:2147483647;overflow:auto;padding:1.5rem;background:#18181b;color:#f4f4f5;' +\n 'font:14px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;text-align:left';\n\n const title = document.createElement('div');\n title.textContent = isDev ? 'Unhandled error' : 'Something went wrong';\n title.style.cssText = 'font-size:1.0625rem;font-weight:700;color:#f87171;margin:0 0 0.75rem';\n box.appendChild(title);\n\n if (isDev) {\n const detail = document.createElement('pre');\n detail.style.cssText = 'margin:0;white-space:pre-wrap;word-break:break-word';\n detail.textContent =\n (error instanceof Error ? (error.stack ?? `${error.name}: ${error.message}`) : String(error)) +\n (componentStack ? `\\n\\nComponent stack:${componentStack}` : '');\n box.appendChild(detail);\n } else {\n const message = document.createElement('p');\n message.textContent = 'This page hit an unexpected error and can’t continue.';\n message.style.cssText = 'margin:0 0 1rem;color:#d4d4d8';\n box.appendChild(message);\n }\n\n const reload = document.createElement('button');\n reload.textContent = 'Reload page';\n reload.style.cssText =\n 'margin-top:1.25rem;padding:0.5rem 1rem;font:inherit;color:#18181b;background:#f4f4f5;border:0;border-radius:4px;cursor:pointer';\n reload.addEventListener('click', () => window.location.reload());\n box.appendChild(reload);\n\n host.appendChild(box);\n }, 0);\n}\n\n/**\n * Asks a URL for its flight payload. Deliberately uncached — a payload can never be staler than the click\n * that wanted it, and the browser's own HTTP cache is what makes a repeat visit cheap.\n */\nfunction requestPayload(href: string, signal: AbortSignal): Promise<RscPayload> {\n return createFromFetch<RscPayload>(fetch(createRscRequest(new URL(href, location.href).href, undefined, signal)));\n}\n\nasync function main() {\n // The assertion is load-bearing under the compiler that builds this: TypeScript 7 declares `nonce` on\n // HTMLElement, 6 declares it on Element. ESLint runs the older lib — where the narrowing is redundant —\n // so it reports an assertion that `tsc` requires. Believe `typecheck`, not the rule.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n const cspMeta = document.querySelector('meta[property=\"csp-nonce\"]') as HTMLMetaElement | null;\n if (cspMeta?.nonce) __webpack_nonce__ = cspMeta.nonce;\n\n // Both are replaced by BrowserRoot's own on mount. The defaults cover the window before hydration, where\n // `setServerCallback` is already registered but there is no root to update — a reload is the honest answer.\n let setPayload: (v: RscPayload) => void = () => {\n window.location.reload();\n };\n // Runs work inside the nav transition so useNavigation().pending stays true across the round-trip.\n let startNav: (run: () => void | Promise<void>) => void = (run) => {\n void run();\n };\n\n const initialPayload = await createFromReadableStream<RscPayload>(flightStream);\n\n function push(href: string) {\n const target = new URL(href, window.location.href);\n if (target.origin !== window.location.origin) {\n window.location.assign(target.href);\n return;\n }\n window.history.pushState(null, '', target.href);\n }\n\n function replace(href: string) {\n const target = new URL(href, window.location.href);\n if (target.origin !== window.location.origin) {\n window.location.replace(target.href);\n return;\n }\n window.history.replaceState(null, '', target.href);\n }\n\n // A traversal is the browser's to perform: it moves the entry itself and fires `popstate`, which is where\n // `listenNavigation` picks the new document up — so these need no more than to ask, and inherit the same\n // fetch, scroll restoration and `pending` flag a back-button press already got.\n const back = () => window.history.back();\n const forward = () => window.history.forward();\n\n // A refresh keeps the URL, so it can't ride the history patch like push/replace and drives the re-fetch itself.\n const refresh = () =>\n startNav(async () => {\n try {\n await fetchRscPayload();\n } catch {\n window.location.reload();\n }\n });\n\n /**\n * Turns a control-signal digest — how `redirect()` / `notFound()` reach the browser — into a real\n * navigation. Returns false for anything else, so callers fall through to their own handling.\n *\n * `hard` forces a full document load, for signals that surfaced *through React*: it unmounts the root on\n * an uncaught error, leaving no live tree to soft-navigate with.\n */\n function handleControlDigest(error: unknown, { hard = false }: { hard?: boolean } = {}): boolean {\n const digest = (error as { digest?: unknown } | null)?.digest;\n if (!isControlDigest(digest)) return false;\n const redirect = parseRedirectDigest(digest);\n if (!redirect) {\n window.location.reload();\n } else if (hard) {\n window.location.assign(new URL(redirect.location, window.location.href).href);\n } else {\n push(redirect.location);\n }\n return true;\n }\n\n /**\n * The navigation whose payload the screen is allowed to show. React runs async transitions concurrently, so\n * two overlapping navigations are two live fetches with no ordering between them — without this, a slow\n * first response landing after a fast second one renders the page the user already left while the address\n * bar shows the one they asked for.\n */\n let currentNavigation = 0;\n /** The in-flight navigation's fetch, so a newer one can stop paying for it. */\n let navigationFetch: AbortController | null = null;\n\n /**\n * Fetches the payload for the current URL and applies it, unless a newer navigation started meanwhile.\n *\n * @returns `true` when this navigation is the one that settled the screen, `false` when it was superseded.\n * The distinction is what keeps a stale response from scrolling a page it is no longer rendering — and\n * why being superseded resolves rather than throws: both callers answer a rejection with a full reload,\n * so surfacing the abort would turn every fast second click into one.\n */\n async function fetchRscPayload(): Promise<boolean> {\n const navigation = ++currentNavigation;\n navigationFetch?.abort();\n const controller = (navigationFetch = new AbortController());\n const superseded = () => navigation !== currentNavigation;\n\n let payload: RscPayload;\n try {\n payload = await requestPayload(window.location.href, controller.signal);\n } catch (error) {\n // Checked before the error is read: an abort is this navigation being replaced, and the one that\n // replaced it owns the outcome.\n if (superseded()) return false;\n if (handleControlDigest(error)) return true;\n throw error;\n }\n if (superseded()) return false;\n if (payload.redirect) {\n push(payload.redirect);\n return true;\n }\n setPayload(payload);\n return true;\n }\n\n function BrowserRoot() {\n const [payload, setPayloadState] = React.useState(initialPayload);\n const [pending, startTransition] = React.useTransition();\n // The scroll a fetched navigation still owes, held until its payload is on screen.\n const pendingScroll = React.useRef<(() => void) | null>(null);\n\n React.useEffect(() => {\n setPayload = (v) => setPayloadState(v);\n startNav = (run) => startTransition(run);\n }, [startTransition]);\n\n /**\n * Scrolls where the navigation asked, once React has put its payload in the DOM — a `#hash` target does\n * not exist until the new tree does. A layout effect, so the pre-scroll position is never painted.\n */\n React.useLayoutEffect(() => {\n const scroll = pendingScroll.current;\n pendingScroll.current = null;\n scroll?.();\n }, [payload]);\n\n React.useEffect(() => {\n const stopNavigating = listenNavigation((afterRender) =>\n startNav(async () => {\n try {\n // Only the navigation that settled the screen owes a scroll — a superseded one would move the\n // page the navigation that replaced it is about to render.\n if (await fetchRscPayload()) pendingScroll.current = afterRender;\n } catch {\n window.location.reload();\n }\n }),\n );\n const stopUpgradingLinks = listenLinks();\n return () => {\n stopUpgradingLinks();\n stopNavigating();\n };\n }, []);\n\n const router = React.useMemo<NavigationRouter>(() => ({ push, replace, back, forward, refresh, pending }), [pending]);\n\n return <RouterContext.Provider value={router}>{payload.root}</RouterContext.Provider>;\n }\n\n setServerCallback(async (id, args) => {\n const temporaryReferences = createTemporaryReferenceSet();\n // The document the action is being called from. Every action response carries a fresh payload for that\n // page, so if a navigation has moved on by the time it arrives the payload describes a page the user has\n // left — the return value is still theirs, but painting it is not. Compared without the fragment, which\n // the server never saw.\n const calledFrom = documentUrl();\n const request = createRscRequest(window.location.href, {\n id,\n body: await encodeReply(args, { temporaryReferences }),\n });\n let payload: RscPayload;\n try {\n payload = await createFromFetch<RscPayload>(fetch(request), { temporaryReferences });\n } catch (error) {\n if (handleControlDigest(error)) return undefined;\n throw error;\n }\n if (payload.redirect) {\n push(payload.redirect);\n return undefined;\n }\n if (documentUrl() === calledFrom) React.startTransition(() => setPayload(payload));\n if (payload.notFound) return undefined;\n const result = payload.returnValue!;\n if (!result.ok) throw result.error;\n return result.value;\n });\n\n // A `redirect()` / `notFound()` from a component below the page root reaches us through React: it rides the\n // flight payload as an error, and boundaries re-throw it so it lands here rather than in a fallback.\n //\n // Installing these hooks opts out of React's own defaults, so everything that isn't a control signal has to\n // be put back by hand — `reportError` rather than a bare log, so error-reporting tools still see it.\n hydrateRoot(document, <BrowserRoot />, {\n formState: initialPayload.formState,\n onCaughtError: (error, errorInfo) => {\n if (handleControlDigest(error, { hard: true })) return;\n // A boundary handled it and the tree is intact, so no overlay over the app's own fallback.\n console.error(error, errorInfo.componentStack ?? '');\n },\n onUncaughtError: (error, errorInfo) => {\n if (handleControlDigest(error, { hard: true })) return;\n // Nothing caught it, so React tears the root down — and the root is `document`.\n globalThis.reportError(error);\n showFatal(error, errorInfo.componentStack);\n },\n });\n\n if (import.meta.webpackHot) {\n initDevRefresh(fetchRscPayload);\n }\n}\n\ntype NavigationType = 'push' | 'replace' | 'pop';\n\n/** Runs teardown in reverse and empties the list, so a second call is a no-op. */\nfunction disposeAll(undo: Array<() => void>): void {\n for (const dispose of undo.splice(0).reverse()) dispose();\n}\n\n// An `<a>` we intercept for soft navigation: same-origin, same tab, not a download,\n// and not explicitly opted out with `data-native` (which forces a full browser navigation).\nfunction isRouterLink(link: HTMLAnchorElement): boolean {\n return (\n !!link.href &&\n (!link.target || link.target === '_self') &&\n link.origin === location.origin &&\n !link.hasAttribute('download') &&\n !link.hasAttribute('data-native')\n );\n}\n\n/**\n * Upgrades the app's anchors: a plain left-click becomes a soft navigation. It shares no state with\n * `listenNavigation` — a click only calls `history.pushState`, which is where that picks the navigation up.\n */\nfunction listenLinks(): () => void {\n const undo: Array<() => void> = [];\n\n function onClick(e: MouseEvent) {\n const link = (e.target as Element).closest('a');\n if (\n link &&\n link instanceof HTMLAnchorElement &&\n isRouterLink(link) &&\n e.button === 0 &&\n !e.metaKey &&\n !e.ctrlKey &&\n !e.altKey &&\n !e.shiftKey &&\n !e.defaultPrevented\n ) {\n if (link.hash && link.pathname === location.pathname && link.search === location.search) return;\n e.preventDefault();\n history.pushState(null, '', link.href);\n }\n }\n document.addEventListener('click', onClick);\n undo.push(() => document.removeEventListener('click', onClick));\n\n return () => disposeAll(undo);\n}\n\n/**\n * The element the current `#fragment` names, if it is on the page. A fragment is percent-encoded and an `id`\n * is not, so it is decoded first — and taken literally when a hand-written `%` makes that throw.\n */\nfunction fragmentTarget(): HTMLElement | null {\n const fragment = location.hash.slice(1);\n if (!fragment) return null;\n let id = fragment;\n try {\n id = decodeURIComponent(fragment);\n } catch {\n // Malformed escape — the literal fragment is the better guess at the id than nothing.\n }\n return document.getElementById(id);\n}\n\nfunction listenNavigation(onNavigation: (afterRender: () => void) => void): () => void {\n const undo: Array<() => void> = [];\n\n // Set explicitly as a statement of intent: the browser remembers a traversal's offset, and nothing here\n // tracks one.\n const prevRestoration = window.history.scrollRestoration;\n try {\n window.history.scrollRestoration = 'auto';\n } catch {\n // Not settable in every browser, and only a preference — the navigation still works without it.\n }\n undo.push(() => {\n try {\n window.history.scrollRestoration = prevRestoration;\n } catch {\n // As above: if it could not be set, it cannot be put back either.\n }\n });\n\n /**\n * A push is not a real navigation to the browser, so nothing resets the scroll offset. A `#hash` names\n * where to land instead; `replace` keeps its position, and a traversal is the browser's to restore.\n *\n * `scrollIntoView` is the algorithm a browser's own fragment jump uses, so `scroll-padding-top` still\n * applies. Neither call passes a `behavior`, leaving `scroll-behavior: smooth` the app's to ask for.\n */\n const afterRenderFor = (type: NavigationType) => () => {\n if (type !== 'push') return;\n const target = fragmentTarget();\n if (target) target.scrollIntoView();\n else window.scrollTo(0, 0);\n };\n\n // What the payload on screen was rendered for. See {@link documentUrl}.\n let renderedUrl = documentUrl();\n\n /**\n * A navigation that moves only the fragment leaves the document unchanged, so the payload on screen is\n * already the right one — fetching another would re-render the page out from under the jump.\n * `router.refresh()` is unaffected, and remains the way to ask for fresh data at an unchanged URL.\n */\n const notify = (type: NavigationType) => {\n const afterRender = afterRenderFor(type);\n if (documentUrl() === renderedUrl) {\n afterRender();\n return;\n }\n renderedUrl = documentUrl();\n onNavigation(afterRender);\n };\n\n const onPopState = () => notify('pop');\n window.addEventListener('popstate', onPopState);\n undo.push(() => window.removeEventListener('popstate', onPopState));\n\n // Saved unbound on purpose, and called back with `.call(this, …)` below — patching `history` is the only\n // way to see a navigation the app makes itself, and the receiver is restored at every call site.\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const oldPushState = window.history.pushState;\n window.history.pushState = function (state, unused, url) {\n const res = oldPushState.call(this, state, unused, url as string);\n notify('push');\n return res;\n };\n undo.push(() => {\n window.history.pushState = oldPushState;\n });\n\n // eslint-disable-next-line @typescript-eslint/unbound-method -- as with `pushState` above.\n const oldReplaceState = window.history.replaceState;\n window.history.replaceState = function (state, unused, url) {\n const res = oldReplaceState.call(this, state, unused, url as string);\n notify('replace');\n return res;\n };\n undo.push(() => {\n window.history.replaceState = oldReplaceState;\n });\n\n return () => disposeAll(undo);\n}\n\n/**\n * Dev-only refresh client, listening to the CLI's SSE endpoint:\n *\n * client-built → hot-apply the waiting updates; anything the page can't be patched up to reloads.\n * rsc-update → server component code changed: re-fetch the flight payload, state preserved.\n * hello → sent on (re)connect with the latest build hash; a mismatch means a missed event.\n */\n// `Promise<unknown>`: the payload fetch reports whether its navigation was superseded, which matters to a\n// click and not to a rebuild — here only settling or rejecting does.\nfunction initDevRefresh(fetchRscPayload: () => Promise<unknown>) {\n const hot = import.meta.webpackHot!;\n let connectedOnce = false;\n /** The newest build the dev server has announced — what {@link applyClientUpdate} walks towards. */\n let targetHash: string | undefined;\n\n function reload(reason: string, error?: unknown): void {\n console.warn(`[rshono] ${reason} — reloading`, ...(error === undefined ? [] : [error]));\n window.location.reload();\n }\n\n async function applyClientUpdate(): Promise<void> {\n const giveUp = await walkHotUpdates(\n hot,\n () => __webpack_hash__,\n () => targetHash,\n );\n if (giveUp) reload(giveUp.reason, giveUp.error);\n }\n\n async function handle(message: DevMessage): Promise<void> {\n switch (message.type) {\n case 'hello':\n targetHash = message.hash ?? targetHash;\n if (connectedOnce) {\n await applyClientUpdate();\n await fetchRscPayload().catch(() => window.location.reload());\n }\n connectedOnce = true;\n break;\n case 'client-built':\n targetHash = message.hash;\n await applyClientUpdate();\n break;\n case 'rsc-update':\n console.log('[rshono] server components updated');\n await fetchRscPayload().catch(() => window.location.reload());\n break;\n }\n }\n\n const source = new EventSource('/_rshono/hmr');\n // Chained rather than handled as they arrive: `hot.check` may only run from `idle`, and a burst of saves\n // puts several frames on the wire inside the time one takes. Queueing drops nothing, because `targetHash`\n // is shared — whichever handler runs next walks to the newest build.\n let queue: Promise<void> = Promise.resolve();\n source.onmessage = (event: MessageEvent<string>) => {\n const message = JSON.parse(event.data) as DevMessage;\n queue = queue.then(() => handle(message)).catch((error) => reload('the dev client failed', error));\n };\n}\n\n// A bootstrap failure — a truncated initial payload, most likely — would otherwise be an unhandled\n// rejection: nothing hydrates, nothing is reported, and the page just sits there.\nmain().catch((error) => {\n console.error('[rshono] the client runtime failed to start:', error);\n showFatal(error);\n});\n"]}
1
+ {"version":3,"file":"entry.client.js","sourceRoot":"","sources":["../../src/runtime/entry.client.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { hydrateRoot } from 'react-dom/client';\nimport {\n createFromFetch,\n createFromReadableStream,\n createTemporaryReferenceSet,\n encodeReply,\n setServerCallback,\n} from 'react-server-dom-rspack/client.browser';\nimport { isControlDigest, parseRedirectDigest } from './control.js';\nimport type { DevMessage } from './dev-protocol.js';\nimport type { RscPayload } from './entry.rsc.js';\n// Dev-only: its one caller sits behind `import.meta.webpackHot`, which a production build compiles to\n// `false` — so this module is dropped there.\nimport { walkHotUpdates } from './hot-update.js';\nimport { RouterContext, type NavigationRouter } from './navigation.js';\nimport { createRscRequest } from './request.js';\n\nconst isDev = process.env.NODE_ENV === 'development';\n\ndeclare global {\n /** The array the payload `<script>` tags `flight-inject.ts` emits push their chunks into. */\n var __FLIGHT_DATA: Array<string | Uint8Array> | undefined;\n}\n\n/** The flight payload the document carried, read back out of `__FLIGHT_DATA` — see `flight-inject.ts`. */\nfunction readFlightPayload(): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n // Assigned synchronously by `start`, which `new ReadableStream` runs before it returns.\n let controller!: ReadableStreamDefaultController<Uint8Array>;\n const stream = new ReadableStream<Uint8Array>({\n start: (c) => void (controller = c),\n });\n const enqueue = (chunk: string | Uint8Array) => controller.enqueue(typeof chunk === 'string' ? encoder.encode(chunk) : chunk);\n\n // Payload scripts interleave with the document: the ones that already ran are in the array, the rest\n // arrive through `push`.\n const data = (self.__FLIGHT_DATA ??= []);\n for (const chunk of data) enqueue(chunk);\n data.push = enqueue as typeof data.push;\n\n // The last payload script lands before parsing finishes, so that is what closes the stream.\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => controller.close(), { once: true });\n } else {\n controller.close();\n }\n return stream;\n}\n\n/** Created at module evaluation, not inside `main()`, so no chunk can be pushed before it is watching. */\nconst flightStream = readFlightPayload();\n\n/**\n * The part of the location a payload is rendered for — the document, without the fragment, which the server\n * never sees. Two URLs that differ only by `#hash` describe the same payload.\n */\nconst documentUrl = (): string => location.pathname + location.search;\n\n/** Guarantees somewhere to attach the fatal overlay: the root container is `document`, so a teardown can take `<body>` with it. */\nfunction overlayHost(): HTMLElement {\n if (!document.documentElement) document.appendChild(document.createElement('html'));\n if (!document.body) document.documentElement.appendChild(document.createElement('body'));\n return document.body;\n}\n\n/**\n * Paints the reason for an uncaught render error over the blank page it leaves behind — the full stack in\n * dev, a generic notice and a reload button in production.\n *\n * DOM calls rather than React (the renderer is what just failed), and `textContent` rather than\n * `innerHTML` (an error message is untrusted input).\n */\nfunction showFatal(error: unknown, componentStack?: string | null): void {\n // Queued: React's teardown runs after this callback returns and would remove a node appended inline.\n setTimeout(() => {\n const host = overlayHost();\n host.querySelector('[data-rshono-fatal]')?.remove();\n\n const box = document.createElement('div');\n box.setAttribute('data-rshono-fatal', '');\n box.setAttribute('role', 'alert');\n box.style.cssText =\n 'position:fixed;inset:0;z-index:2147483647;overflow:auto;padding:1.5rem;background:#18181b;color:#f4f4f5;' +\n 'font:14px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;text-align:left';\n\n const title = document.createElement('div');\n title.textContent = isDev ? 'Unhandled error' : 'Something went wrong';\n title.style.cssText = 'font-size:1.0625rem;font-weight:700;color:#f87171;margin:0 0 0.75rem';\n box.appendChild(title);\n\n if (isDev) {\n const detail = document.createElement('pre');\n detail.style.cssText = 'margin:0;white-space:pre-wrap;word-break:break-word';\n detail.textContent =\n (error instanceof Error ? (error.stack ?? `${error.name}: ${error.message}`) : String(error)) +\n (componentStack ? `\\n\\nComponent stack:${componentStack}` : '');\n box.appendChild(detail);\n } else {\n const message = document.createElement('p');\n message.textContent = 'This page hit an unexpected error and can’t continue.';\n message.style.cssText = 'margin:0 0 1rem;color:#d4d4d8';\n box.appendChild(message);\n }\n\n const reload = document.createElement('button');\n reload.textContent = 'Reload page';\n reload.style.cssText =\n 'margin-top:1.25rem;padding:0.5rem 1rem;font:inherit;color:#18181b;background:#f4f4f5;border:0;border-radius:4px;cursor:pointer';\n reload.addEventListener('click', () => window.location.reload());\n box.appendChild(reload);\n\n host.appendChild(box);\n }, 0);\n}\n\n/** What every flight response is typed as. The charset and any other parameters follow it. */\nconst FLIGHT_CONTENT_TYPE = 'text/x-component';\n\n/**\n * Fetches a payload, refusing a response that is not one.\n *\n * The status cannot be the gate: a payload legitimately arrives as a 404 from the `notFound` page and as a\n * 500 from an action that threw, and both carry a real payload the caller has to see. The content type is.\n *\n * What this catches is the response that is not a payload at all — a `bodyLimit()` 413, a proxy's error page,\n * a 502 mid-deploy. Handed to the flight parser those all surface as `Error: Connection closed.`, with the\n * status and the body nowhere in sight; here they become an error that says what arrived.\n */\nasync function payloadResponse(request: Request): Promise<Response> {\n const response = await fetch(request);\n const contentType = response.headers.get('content-type');\n if (contentType?.startsWith(FLIGHT_CONTENT_TYPE)) return response;\n // Read for the message: a plain-text refusal says what it refused only in its body, and HTTP/2 has no\n // `statusText` at all. Bounded, because this is an error path and the body is not ours to trust.\n const body = await response.text().then(\n (text) => text.trim().slice(0, 200),\n () => '',\n );\n const status = `${response.status}${response.statusText ? ` ${response.statusText}` : ''}`;\n throw new Error(`[rshono] the server answered ${status} (${contentType ?? 'no content type'}) instead of a payload${body ? `: ${body}` : ''}`);\n}\n\n/**\n * Asks a URL for its flight payload. Deliberately uncached — a payload can never be staler than the click\n * that wanted it, and the browser's own HTTP cache is what makes a repeat visit cheap.\n */\nfunction requestPayload(href: string, signal?: AbortSignal): Promise<RscPayload> {\n return createFromFetch<RscPayload>(payloadResponse(createRscRequest(new URL(href, location.href).href, undefined, signal)));\n}\n\n/**\n * Whether the browser hands us its navigations. Gated on `sourceElement` rather than on `navigation` itself:\n * Chrome shipped the event in 102 and that property only in 135, and without it a `data-native` link cannot\n * be told from any other — so the older window would soft-navigate the very links that asked not to be.\n *\n * Where this is false there is no interception at all and every navigation is a real browser load, which a\n * server-rendered app answers correctly on its own. Only the soft part is missing.\n *\n * Both globals are tested, and neither is touched before: this runs at module scope, where a ReferenceError\n * would take the whole client runtime down with it rather than degrading anything.\n */\nconst canSoftNavigate = typeof navigation !== 'undefined' && typeof NavigateEvent !== 'undefined' && 'sourceElement' in NavigateEvent.prototype;\n\n/**\n * Drops a navigation's result promises. Both reject when a navigation is superseded or cancelled — routine\n * here, since a second click is meant to abandon the first — and unhandled they would be reported as faults.\n */\nfunction settle(result: NavigationResult): void {\n const ignore = () => {};\n void result.committed?.catch(ignore);\n void result.finished?.catch(ignore);\n}\n\n// The imperative actions behind `useNavigation().router`. Each one only *asks*: the browser turns it into a\n// `navigate` event, which is where `listenNavigation` answers it — so a `router.push` and a link click reach\n// the same code by the same route, and inherit the same fetch, scroll and `pending` flag.\nfunction push(href: string): void {\n if (canSoftNavigate) settle(navigation.navigate(href, { history: 'push' }));\n else window.location.assign(href);\n}\n\nfunction replace(href: string): void {\n if (canSoftNavigate) settle(navigation.navigate(href, { history: 'replace' }));\n else window.location.replace(href);\n}\n\n// A traversal is the browser's to perform either way — `navigation` only hands it back as an interceptable\n// event first. Nothing to go back to is a rejection there and a no-op here; both amount to the same thing.\nfunction back(): void {\n if (canSoftNavigate) settle(navigation.back());\n else window.history.back();\n}\n\nfunction forward(): void {\n if (canSoftNavigate) settle(navigation.forward());\n else window.history.forward();\n}\n\n// A refresh keeps the URL, and is still a navigation: it arrives as `navigationType: 'reload'`, which is what\n// tells the listener to leave scroll and focus where the user left them.\nfunction refresh(): void {\n if (canSoftNavigate) settle(navigation.reload());\n else window.location.reload();\n}\n\n/**\n * Turns a control-signal digest — how `redirect()` / `notFound()` reach the browser — into a real\n * navigation. Returns false for anything else, so callers fall through to their own handling.\n *\n * `hard` forces a full document load, for signals that surfaced *through React*: it unmounts the root on\n * an uncaught error, leaving no live tree to soft-navigate with.\n */\nfunction handleControlDigest(error: unknown, { hard = false }: { hard?: boolean } = {}): boolean {\n const digest = (error as { digest?: unknown } | null)?.digest;\n if (!isControlDigest(digest)) return false;\n const redirect = parseRedirectDigest(digest);\n if (!redirect) {\n window.location.reload();\n } else if (hard) {\n window.location.assign(new URL(redirect.location, window.location.href).href);\n } else {\n push(redirect.location);\n }\n return true;\n}\n\n/**\n * Puts a payload on screen, resolving once React has committed it. Replaced by `BrowserRoot`'s own on mount;\n * the default covers the window before hydration, where `setServerCallback` is already registered but there\n * is no root to update — a reload is the honest answer, and nothing after it needs to run.\n */\nlet setPayload: (payload: RscPayload) => Promise<void> = () => {\n window.location.reload();\n return new Promise<void>(() => {});\n};\n\n/** Runs work inside the nav transition so `useNavigation().pending` stays true across the round-trip. */\nlet startNav: (run: () => void | Promise<void>) => void = (run) => {\n void run();\n};\n\n/**\n * Fetches the payload for `url` and puts it on screen.\n *\n * Resolves once React has **committed** it rather than when the fetch lands: an intercepted navigation\n * scrolls and moves focus when this promise settles, and a `#hash` target does not exist until the new tree\n * does. Rejects only on a genuine failure — being superseded is not one, and resolves quietly, because the\n * navigation that replaced this one owns the screen from then on.\n */\nfunction loadPayload(url: string, signal?: AbortSignal): Promise<void> {\n // Deliberately not awaited inside the transition: the scope ends once the payload is handed to React, and\n // React holds `pending` until the update it scheduled commits. Awaiting the commit *inside* the scope would\n // work too, but only because React happens not to gate a commit on its async scope settling — an internal\n // this has no reason to depend on across the whole `^19.1.0` peer range.\n let committed: Promise<void> | undefined;\n\n const run = async () => {\n const payload = await requestPayload(url, signal);\n // The browser aborts a navigation the moment a newer one starts. Checked again after the await because\n // the fetch may already have resolved by then, and applying it would repaint a page the user has left.\n if (signal?.aborted) return;\n if (payload.redirect) {\n push(payload.redirect);\n return;\n }\n committed = setPayload(payload);\n };\n\n // `startTransition` runs the work but hands nothing back, so the promise carrying a failure is caught here\n // instead. Assigned synchronously: React invokes the callback before `startNav` returns.\n let work!: Promise<void>;\n startNav(() => (work = run()));\n\n return work.then(\n // Undefined whenever nothing was applied — an abort, or a redirect — and there is then nothing to wait for.\n () => committed,\n (error: unknown) => {\n // Checked before the error is read: an abort is this navigation being replaced, and the one that\n // replaced it owns the outcome.\n if (signal?.aborted || handleControlDigest(error)) return;\n throw error;\n },\n );\n}\n\n/**\n * Navigations the browser can hand over but shouldn't:\n *\n * - a fragment jump, which is same-document already and needs no payload — the browser's own jump is the one\n * that honours `scroll-padding-top`, and re-rendering would pull the target out from under it;\n * - a download, which is not a navigation of this page at all;\n * - a `POST` form, which is a submission and the server's to answer (a `GET` form carries its fields in the\n * URL, has no `formData`, and soft-navigates like any other link);\n * - a link marked `data-native`, the documented opt-out.\n */\nfunction leaveToBrowser(event: NavigateEvent): boolean {\n return event.hashChange || event.downloadRequest !== null || event.formData !== null || event.sourceElement?.hasAttribute('data-native') === true;\n}\n\n/**\n * The whole router, in one listener.\n *\n * Every navigation the page can make arrives as a `navigate` event — a link click, a `GET` form, a\n * `history.pushState`, the back button, `navigation.reload()` — already filtered by the browser: it does not\n * fire for a middle-click, a modified click or a new tab, and reports `canIntercept: false` for anything\n * cross-origin, or for a traversal that leaves the app. Those need no handling here; they are left alone, and\n * the browser performs them as it always would.\n */\nfunction listenNavigation(): () => void {\n if (!canSoftNavigate) return () => {};\n\n const onNavigate = (event: NavigateEvent) => {\n if (!event.canIntercept || leaveToBrowser(event)) return;\n\n // A push or a traversal lands on a new page, so the browser resets the scroll offset — or restores the\n // one it remembers — and moves focus, which is what makes a soft navigation announce itself to a screen\n // reader. A replace or a refresh stays where it is, so neither should move. Both wait on the handler,\n // which is the point of resolving it at commit rather than at fetch.\n const inPlace = event.navigationType === 'replace' || event.navigationType === 'reload';\n\n event.intercept({\n scroll: inPlace ? 'manual' : 'after-transition',\n focusReset: inPlace ? 'manual' : 'after-transition',\n // The URL commits before the handler runs, so a failure leaves the address bar describing a page the\n // document is not showing. A real load is the only way back to agreement.\n handler: () => loadPayload(event.destination.url, event.signal).catch(() => window.location.reload()),\n });\n };\n\n navigation.addEventListener('navigate', onNavigate);\n return () => navigation.removeEventListener('navigate', onNavigate);\n}\n\nasync function main() {\n // The assertion is load-bearing under the compiler that builds this: TypeScript 7 declares `nonce` on\n // HTMLElement, 6 declares it on Element. ESLint runs the older lib — where the narrowing is redundant —\n // so it reports an assertion that `tsc` requires. Believe `typecheck`, not the rule.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n const cspMeta = document.querySelector('meta[property=\"csp-nonce\"]') as HTMLMetaElement | null;\n if (cspMeta?.nonce) __webpack_nonce__ = cspMeta.nonce;\n\n const initialPayload = await createFromReadableStream<RscPayload>(flightStream);\n\n function BrowserRoot() {\n const [payload, setPayloadState] = React.useState(initialPayload);\n const [pending, startTransition] = React.useTransition();\n // The resolver the payload on screen still owes — see {@link loadPayload}.\n const pendingCommit = React.useRef<(() => void) | null>(null);\n\n React.useEffect(() => {\n setPayload = (next) =>\n new Promise<void>((resolve) => {\n // A payload replaced before it ever painted still has a navigation waiting on it. React commits\n // only the newest, so the effect below never runs for the one it skipped: release it here.\n pendingCommit.current?.();\n pendingCommit.current = resolve;\n setPayloadState(next);\n });\n startNav = (run) => startTransition(run);\n }, [startTransition]);\n\n /**\n * Releases the navigation waiting on this payload, which is what lets the browser scroll and move focus\n * now that their target exists. A layout effect, so the pre-scroll position is never painted.\n */\n React.useLayoutEffect(() => {\n const commit = pendingCommit.current;\n pendingCommit.current = null;\n commit?.();\n }, [payload]);\n\n React.useEffect(() => listenNavigation(), []);\n\n const router = React.useMemo<NavigationRouter>(() => ({ push, replace, back, forward, refresh, pending }), [pending]);\n\n return <RouterContext.Provider value={router}>{payload.root}</RouterContext.Provider>;\n }\n\n setServerCallback(async (id, args) => {\n const temporaryReferences = createTemporaryReferenceSet();\n // The document the action is being called from. Every action response carries a fresh payload for that\n // page, so if a navigation has moved on by the time it arrives the payload describes a page the user has\n // left — the return value is still theirs, but painting it is not. Compared without the fragment, which\n // the server never saw.\n const calledFrom = documentUrl();\n const request = createRscRequest(window.location.href, {\n id,\n body: await encodeReply(args, { temporaryReferences }),\n });\n let payload: RscPayload;\n try {\n payload = await createFromFetch<RscPayload>(payloadResponse(request), { temporaryReferences });\n } catch (error) {\n if (handleControlDigest(error)) return undefined;\n throw error;\n }\n if (payload.redirect) {\n push(payload.redirect);\n return undefined;\n }\n if (documentUrl() === calledFrom) React.startTransition(() => void setPayload(payload));\n if (payload.notFound) return undefined;\n const result = payload.returnValue;\n if (!result) {\n // A payload that is not this action's own reply: the server rendered a page in its place. An action\n // that had already run has its result carried across (see `actionResults` in entry.rsc.tsx), so\n // reaching here means the request failed before it ran at all — an undecodable body, most likely.\n // Reading `.ok` off it used to hand the caller `Cannot read properties of undefined`.\n throw new Error('[rshono] the server action produced no result — the request failed around it and the server answered with a page instead. Its log has the error.');\n }\n if (!result.ok) throw result.error;\n return result.value;\n });\n\n // A `redirect()` / `notFound()` from a component below the page root reaches us through React: it rides the\n // flight payload as an error, and boundaries re-throw it so it lands here rather than in a fallback.\n //\n // Installing these hooks opts out of React's own defaults, so everything that isn't a control signal has to\n // be put back by hand — `reportError` rather than a bare log, so error-reporting tools still see it.\n hydrateRoot(document, <BrowserRoot />, {\n formState: initialPayload.formState,\n onCaughtError: (error, errorInfo) => {\n if (handleControlDigest(error, { hard: true })) return;\n // A boundary handled it and the tree is intact, so no overlay over the app's own fallback.\n console.error(error, errorInfo.componentStack ?? '');\n },\n onUncaughtError: (error, errorInfo) => {\n if (handleControlDigest(error, { hard: true })) return;\n // Nothing caught it, so React tears the root down — and the root is `document`.\n globalThis.reportError(error);\n showFatal(error, errorInfo.componentStack);\n },\n });\n\n if (import.meta.webpackHot) {\n initDevRefresh();\n }\n}\n\n/**\n * Dev-only refresh client, listening to the CLI's SSE endpoint:\n *\n * client-built → hot-apply the waiting updates; anything the page can't be patched up to reloads.\n * rsc-update → server component code changed: re-fetch the flight payload, state preserved.\n * hello → sent on (re)connect with the latest build hash; a mismatch means a missed event.\n */\nfunction initDevRefresh() {\n const hot = import.meta.webpackHot!;\n let connectedOnce = false;\n /** The newest build the dev server has announced — what {@link applyClientUpdate} walks towards. */\n let targetHash: string | undefined;\n\n function reload(reason: string, error?: unknown): void {\n console.warn(`[rshono] ${reason} — reloading`, ...(error === undefined ? [] : [error]));\n window.location.reload();\n }\n\n async function applyClientUpdate(): Promise<void> {\n const giveUp = await walkHotUpdates(\n hot,\n () => __webpack_hash__,\n () => targetHash,\n );\n if (giveUp) reload(giveUp.reason, giveUp.error);\n }\n\n async function handle(message: DevMessage): Promise<void> {\n switch (message.type) {\n case 'hello':\n targetHash = message.hash ?? targetHash;\n if (connectedOnce) {\n await applyClientUpdate();\n await loadPayload(window.location.href).catch(() => window.location.reload());\n }\n connectedOnce = true;\n break;\n case 'client-built':\n targetHash = message.hash;\n await applyClientUpdate();\n break;\n case 'rsc-update':\n console.log('[rshono] server components updated');\n await loadPayload(window.location.href).catch(() => window.location.reload());\n break;\n }\n }\n\n const source = new EventSource('/_rshono/hmr');\n // Chained rather than handled as they arrive: `hot.check` may only run from `idle`, and a burst of saves\n // puts several frames on the wire inside the time one takes. Queueing drops nothing, because `targetHash`\n // is shared — whichever handler runs next walks to the newest build.\n let queue: Promise<void> = Promise.resolve();\n source.onmessage = (event: MessageEvent<string>) => {\n const message = JSON.parse(event.data) as DevMessage;\n queue = queue.then(() => handle(message)).catch((error) => reload('the dev client failed', error));\n };\n}\n\n// A bootstrap failure — a truncated initial payload, most likely — would otherwise be an unhandled\n// rejection: nothing hydrates, nothing is reported, and the page just sits there.\nmain().catch((error) => {\n console.error('[rshono] the client runtime failed to start:', error);\n showFatal(error);\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"entry.rsc.d.ts","sourceRoot":"","sources":["../../src/runtime/entry.rsc.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAsBvD,OAAO,EAA0F,KAAK,KAAK,EAAoB,MAAM,cAAc,CAAC;AAwBpJ,eAAO,MAAM,MAAM,EAAE,SAAS,KAAK,EAAuB,CAAC;AAE3D,kGAAkG;AAClG,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAExF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAycF,eAAO,MAAM,GAAG,4EAAa,CAAC;AAE9B;;;;;;GAMG"}
1
+ {"version":3,"file":"entry.rsc.d.ts","sourceRoot":"","sources":["../../src/runtime/entry.rsc.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAsBvD,OAAO,EAA0F,KAAK,KAAK,EAAE,MAAM,cAAc,CAAC;AAmDlI,eAAO,MAAM,MAAM,EAAE,SAAS,KAAK,EAAuB,CAAC;AAE3D,kGAAkG;AAClG,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAExF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AA+kBF,eAAO,MAAM,GAAG,4EAAa,CAAC;AAE9B;;;;;;GAMG"}
@@ -20,16 +20,55 @@ import { isControlSignal, RedirectSignal } from './control.js';
20
20
  import { renderHTML } from './entry.ssr.js';
21
21
  import { RouterProvider } from './navigation.js';
22
22
  import { asksForRsc, isActionRequest, parseRenderRequest, requestWantsRsc, RSC_VARY_HEADER, wantsRsc } from './request.js';
23
- const serverApp = (serverAppModule.default ?? null);
23
+ import { validateRoutesModule, validateServerApp } from './validate-entries.js';
24
+ const serverApp = validateServerApp(serverAppModule);
24
25
  // Compiled into the bundle from rshono.config.ts by DefinePlugin; there is no runtime env-var interface.
25
26
  const { isDev } = __RSHONO_CONFIG__;
26
- /** How long a prerendered page may be reused before revalidating. Also what `public/` files get. */
27
+ /**
28
+ * How long a prerendered page may be reused before revalidating. Also what `public/` files get.
29
+ *
30
+ * Not a config field, deliberately: it is a per-response header, and `rshono.config.ts` is compiled into the
31
+ * bundle — a cache policy you cannot change without a rebuild is the wrong shape. An app that wants a longer
32
+ * `max-age`, or a `stale-while-revalidate`, sets it from middleware **after `await next()`**:
33
+ *
34
+ * ```ts
35
+ * server.use('/docs/*', async (c, next) => {
36
+ * await next();
37
+ * c.res.headers.set('cache-control', 'public, max-age=86400, stale-while-revalidate=604800');
38
+ * });
39
+ * ```
40
+ *
41
+ * After, because the response below is built with `cache-control` in the bag it hands `c.body(...)`, and
42
+ * that replaces a header prepared with `c.header(...)` before the handler ran. The `ETag` is untouched
43
+ * either way, so revalidation still costs a 304 rather than the page.
44
+ */
27
45
  const SSG_CACHE_CONTROL = 'public, max-age=300';
46
+ /**
47
+ * What a page response gets when nothing else set one: without it a shared cache is free to store a logged-in
48
+ * user's page and hand it to someone else. `private, no-cache` forbids that without blocking bfcache, which
49
+ * `no-store` would.
50
+ */
51
+ const PAGE_CACHE_CONTROL = 'private, no-cache';
28
52
  /** The two content types a page can be served as, from the same URL — which is what makes `Vary` non-optional. */
29
53
  const PAGE_CONTENT_TYPE = /^(?:text\/html|text\/x-component)\b/;
30
54
  runtime.loadEnv();
31
- const routeConfig = userRoutes;
55
+ // Checked rather than cast: these two modules are the app's, and a mistake in either used to surface as a
56
+ // `TypeError` from somewhere else entirely — or, for a duplicated path, as nothing at all.
57
+ const routeConfig = validateRoutesModule(userRoutes);
32
58
  export const routes = routeConfig.routes;
59
+ /**
60
+ * The result of an action that has already run, for the request whose *render* then failed.
61
+ *
62
+ * The action and the page it answers with are one response: an action returns its value through the payload
63
+ * of the page rendered after it. So when that render throws — a page module that will not load, most
64
+ * plausibly a chunk that went away mid-deploy — `onError` renders the `error` page in its place, and without
65
+ * this the reply carries no `returnValue` at all. The caller of an action that ran, and may well have
66
+ * written something, would be told only that a field was missing.
67
+ *
68
+ * Keyed on the Hono context the way `beginPageRender` keys its own marker, and weakly, so nothing outlives
69
+ * the request it belongs to.
70
+ */
71
+ const actionResults = new WeakMap();
33
72
  /**
34
73
  * The per-request CSP nonce, if the app asked for one.
35
74
  *
@@ -56,23 +95,31 @@ function cspNonce(c) {
56
95
  *
57
96
  * Both halves are required, because either alone refuses something real:
58
97
  *
59
- * - `Sec-Fetch-Site: cross-site` is the browser's own statement of provenance, and every browser that can post
60
- * a form to a server action sends it. An absent header means a non-browser client, which cannot be a CSRF
61
- * victim; `same-site` is left alone too, since a subdomain policy is `csrf()`'s to express.
62
- * - An `Origin` that is the app's own contradicts that label — a browser calls a post from the app's own pages
98
+ * - `Sec-Fetch-Site` is the browser's own statement of provenance, unforgeable by page script, and every
99
+ * browser that can post a form to a server action sends it. `cross-site` and `same-site` are the two labels
100
+ * that mean "not from this origin" — `same-site` is what a *sibling subdomain* gets, which is a user-content
101
+ * host, a stale CNAME or a subdomain takeover, so leaving it to `csrf()` meant an app without one could have
102
+ * any `'use server'` export driven from next door. An absent header means a non-browser client, which cannot
103
+ * be a CSRF victim. `same-origin` and `none` settle it on their own, and are what a genuine post carries
104
+ * however many proxies rewrote `Host` on the way in.
105
+ * - An `Origin` that is the app's own contradicts either label — a browser calls a post from the app's own pages
63
106
  * `same-origin` — so the pair is a shape no browser produces, and refusing it would only catch a proxy or a
64
- * test client setting the label by hand while posting from the app itself.
107
+ * test client setting the label by hand while posting from the app itself. Nothing else clears the label:
108
+ * an `Origin` of `null` (a sandboxed iframe, a `data:` URL, `Referrer-Policy: no-referrer`) and no `Origin`
109
+ * at all are both refused. A browser attaches one to every non-GET request, so neither is a shape it
110
+ * produces — but a security predicate that says "not proven foreign" rather than "proven local" fails open
111
+ * the day something does produce it.
65
112
  *
66
113
  * `publicUrl(c)` rather than `c.req.url`, so it honours `trustProxy` and compares against the origin the
67
114
  * browser actually used — which behind a proxy, `rshono dev`'s included, is not the one the server was reached
68
- * on. The cost is that an app deliberately accepting cross-site *form* posts to an action cannot; that is what
69
- * an `{ type: 'endpoint' }` route is for.
115
+ * on. The cost is that an app deliberately accepting *form* posts to an action from another origin of its own
116
+ * cannot, `csrf()`'s allowlist included; that is what an `{ type: 'endpoint' }` route is for.
70
117
  */
71
118
  function refusesCrossSiteForm(c) {
72
- if (c.req.header('sec-fetch-site') !== 'cross-site')
119
+ const site = c.req.header('sec-fetch-site');
120
+ if (site !== 'cross-site' && site !== 'same-site')
73
121
  return false;
74
- const origin = c.req.header('origin');
75
- return origin !== undefined && origin !== publicUrl(c).origin;
122
+ return c.req.header('origin') !== publicUrl(c).origin;
76
123
  }
77
124
  async function loadPageModule(load, label) {
78
125
  const mod = await load();
@@ -97,7 +144,11 @@ function acceptsHtml(c) {
97
144
  * payload. It carries the `Vary` too: this is one of the answers a page URL gives depending on the `RSC` request header.
98
145
  */
99
146
  function plainNotFound(c) {
100
- return c.text('Not Found', 404, { vary: RSC_VARY_HEADER });
147
+ // `cache-control` explicitly, because the default above is applied to page *content types* and this is
148
+ // `text/plain`. A 404 is heuristically cacheable under RFC 9111, so without it a shared cache may store
149
+ // this one — while the rendered HTML 404 next to it, the same answer to the same request from a client
150
+ // that asked for HTML, is correctly private.
151
+ return c.text('Not Found', 404, { vary: RSC_VARY_HEADER, 'cache-control': PAGE_CACHE_CONTROL });
101
152
  }
102
153
  /** A lazy once-cell: runs `load` at most once, but clears a rejection so a later call can retry. */
103
154
  function once(load) {
@@ -126,6 +177,32 @@ function releaseWhenDone(stream, done) {
126
177
  cancel: done,
127
178
  }));
128
179
  }
180
+ /**
181
+ * A macrotask boundary: `setImmediate` where there is one — the current turn's check phase rather than a
182
+ * timer — and `setTimeout` as the portable fallback, for a runtime without it. `flight-inject.ts` has the
183
+ * same two lines and the same reason; they are not shared because that module belongs to the SSR layer, and
184
+ * importing it here would give the RSC layer its own instance of it.
185
+ */
186
+ const deferTask = typeof setImmediate === 'function'
187
+ ? setImmediate
188
+ : (run) => {
189
+ setTimeout(run, 0);
190
+ };
191
+ /**
192
+ * Dev-only: says that a control signal arrived too late to be one.
193
+ *
194
+ * The root fix is in app code, so authoring time is where this has to be said, and a docs paragraph is not
195
+ * where anyone reads it. `isDev` is the baked build flag, so a production server pays one boolean check on a
196
+ * path that has already gone wrong — and says nothing.
197
+ */
198
+ function warnLateControlSignal(c, signal) {
199
+ const isRedirect = signal instanceof RedirectSignal;
200
+ console.warn(`[rshono] ${isRedirect ? `redirect(${JSON.stringify(signal.location)})` : 'notFound()'} was called from a boundary that ` +
201
+ `resolved after the page shell had already been sent (${c.req.method} ${c.req.path}), so it cannot become a real ` +
202
+ `${isRedirect ? '3xx' : '404'}: the response is committed as 200 text/html. A browser with JavaScript follows the ` +
203
+ `digest that rides the payload; one without stays on the Suspense fallback, and a crawler indexes the 200.${isRedirect ? '' : ' A JavaScript client recovers by reloading, which renders this same page again.'}` +
204
+ ' Decide before the render starts streaming — in Hono middleware, or in the page component body above the boundary.');
205
+ }
129
206
  /**
130
207
  * Builds the props a page component is called with.
131
208
  *
@@ -171,16 +248,37 @@ async function renderComponent(c, Page, opts) {
171
248
  // starts throwing — while the action `renderPage` just ran, and the middleware around it, legitimately wrote.
172
249
  beginPageRender(c);
173
250
  let controlSignal;
251
+ /** Set once `renderHTML` has returned, which is where the response head stops being changeable. */
252
+ let shellFlushed = false;
174
253
  const rscStream = renderToReadableStream(rscPayload, {
175
254
  temporaryReferences: opts.temporaryReferences,
176
255
  signal,
177
256
  onError(error) {
178
257
  if (isControlSignal(error)) {
179
258
  controlSignal = error;
259
+ if (shellFlushed) {
260
+ if (isDev)
261
+ warnLateControlSignal(c, error);
262
+ // Past the shell the status line, the headers and the first bytes are on the wire, so the digest
263
+ // React writes into the payload is the only path left — and everything still rendering is for a
264
+ // page the browser is about to navigate away from. Winding it down stops those boundaries, runs
265
+ // `flight-inject`'s cancel/flush, and fires the `release()` above now rather than whenever the
266
+ // doomed render happens to finish.
267
+ //
268
+ // One macrotask later rather than from inside `onError`, where React is still handling the error
269
+ // that produced the digest — the row carrying it is the only recovery the client has, and an abort
270
+ // that re-entered React there could cut the render off before it is written. Measured to survive
271
+ // either way on react-server-dom-rspack 0.1.0; deferred anyway, because that ordering is an
272
+ // internal the `^19.1.0` peer range does not promise, and the cost is one macrotask on a render
273
+ // that is already doomed. The reason is the signal itself, so every boundary the abort errors
274
+ // carries the digest rather than a bare AbortError the client would paint as a fault.
275
+ if (!signal.aborted)
276
+ deferTask(() => renderAbort.abort(error));
277
+ }
180
278
  return error.digest;
181
279
  }
182
280
  if (!signal.aborted)
183
- reportServerError(error, { source: 'render', request: c.req.raw, message: '[rshono] render error:' });
281
+ reportServerError(error, { source: 'render', hono: c, message: '[rshono] render error:' });
184
282
  },
185
283
  });
186
284
  if (opts.isRsc) {
@@ -196,8 +294,8 @@ async function renderComponent(c, Page, opts) {
196
294
  signal,
197
295
  nonce,
198
296
  onDone: release,
199
- onShellError: (error) => reportServerError(error, { source: 'ssr', request: c.req.raw, message: '[rshono] SSR shell error:' }),
200
- onError: (error) => reportServerError(error, { source: 'ssr', request: c.req.raw, message: '[rshono] SSR error:' }),
297
+ onShellError: (error) => reportServerError(error, { source: 'ssr', hono: c, message: '[rshono] SSR shell error:' }),
298
+ onError: (error) => reportServerError(error, { source: 'ssr', hono: c, message: '[rshono] SSR error:' }),
201
299
  });
202
300
  }
203
301
  catch (error) {
@@ -206,6 +304,10 @@ async function renderComponent(c, Page, opts) {
206
304
  throw controlSignal;
207
305
  throw error;
208
306
  }
307
+ // `renderHTML` returns at *shell ready*, so from here the response is the one that ships. Set before the
308
+ // check below rather than after it, so nothing lands in the window between the two: a signal that arrives
309
+ // in it is handled there *and* schedules an abort, and aborting an aborted controller is a no-op.
310
+ shellFlushed = true;
209
311
  if (controlSignal) {
210
312
  // The shell resolved, so this response is live: React is being pumped into the payload-injecting
211
313
  // transform, and a `redirect()` that surfaced from a boundary settling just before the shell was ready
@@ -253,10 +355,13 @@ async function renderPage(c, loadPage) {
253
355
  throw error;
254
356
  // In production React sends a thrown action error to the client as an opaque marker, so this is
255
357
  // the only place the real one is visible.
256
- reportServerError(error, { source: 'action', request, message: '[rshono] server action error:' });
358
+ reportServerError(error, { source: 'action', hono: c, message: '[rshono] server action error:' });
257
359
  returnValue = { ok: false, error };
258
360
  actionStatus = 500;
259
361
  }
362
+ // The action is done and its result is the caller's, whatever becomes of the render below. See
363
+ // {@link actionResults}.
364
+ actionResults.set(c, returnValue);
260
365
  }
261
366
  else {
262
367
  // A `<form action={serverAction}>` post, which is the path that runs before hydration and with
@@ -280,7 +385,7 @@ async function renderPage(c, loadPage) {
280
385
  // because this path has no client boundary and no `useActionState` to hand the error to, so the
281
386
  // app's `error` page is the honest answer. `reportServerError` de-duplicates, so the re-throw
282
387
  // reaching `onError` does not report it a second time.
283
- reportServerError(error, { source: 'action', request, message: '[rshono] server action error:' });
388
+ reportServerError(error, { source: 'action', hono: c, message: '[rshono] server action error:' });
284
389
  throw error;
285
390
  }
286
391
  formState = (await decodeFormState(result, formData, __rspack_rsc_manifest__.serverManifest)) ?? undefined;
@@ -300,8 +405,7 @@ function buildApp() {
300
405
  const app = new Hono();
301
406
  // A floor, not a policy: an app wanting the full set registers `secureHeaders()` in src/server.ts, and
302
407
  // because this is registered first it unwinds last, so the "only if unset" checks stand aside for it.
303
- // Owned by the framework because it also has to cover `mountStaticAssets` — a terminal handler the
304
- // app's own middleware never sees.
408
+ // Owned by the framework so that an app with no src/server.ts at all still gets it.
305
409
  app.use(async (c, next) => {
306
410
  await next();
307
411
  const headers = c.res.headers;
@@ -323,17 +427,20 @@ function buildApp() {
323
427
  if (!PAGE_CONTENT_TYPE.test(headers.get('content-type') ?? ''))
324
428
  return;
325
429
  appendVary(headers, RSC_VARY_HEADER);
326
- // Without a default a shared cache is free to store a logged-in user's page and hand it to someone
327
- // else. `private, no-cache` forbids that without blocking bfcache, which `no-store` would.
328
430
  if (!headers.has('cache-control'))
329
- headers.set('cache-control', 'private, no-cache');
431
+ headers.set('cache-control', PAGE_CACHE_CONTROL);
330
432
  });
331
- runtime.mountStaticAssets(app);
332
- // Ahead of the page routes, so the app's own middleware (`csrf()`, `bodyLimit()`, auth, logging) wraps
333
- // page requests too. The flip side: a *terminal* handler in src/server.ts shadows a page at the same path.
433
+ // First, so the app's own middleware (`csrf()`, `bodyLimit()`, auth, logging) wraps everything registered
434
+ // below: the page routes, and the asset handlers too. Assets used to be mounted ahead of this, which left
435
+ // `/_static/*` answered by a terminal handler nothing of the app's ever saw — no `secureHeaders()`, and so
436
+ // no HSTS on exactly the requests a downgrade attack lands on. The flip side is the same one it always had,
437
+ // one path wider: a *terminal* handler in src/server.ts shadows a page at the same path, and unscoped
438
+ // middleware now also runs for `/_static`, which is a reserved prefix an app should not be matching on
439
+ // purpose anyway.
334
440
  if (serverApp) {
335
441
  app.route('/', serverApp);
336
442
  }
443
+ runtime.mountStaticAssets(app);
337
444
  const memoizePage = (page, label) => once(() => loadPageModule(page.component, label));
338
445
  const loadNotFoundPage = routeConfig.notFound ? memoizePage(routeConfig.notFound, 'the notFound page') : null;
339
446
  /** Turns a thrown `redirect()` / `notFound()` into the response it stands for. */
@@ -349,7 +456,23 @@ function buildApp() {
349
456
  return c.redirect(signal.location, signal.status);
350
457
  }
351
458
  if (loadNotFoundPage) {
352
- return renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc, notFound: true });
459
+ try {
460
+ return await renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc, notFound: true });
461
+ }
462
+ catch (error) {
463
+ // The `notFound` page is already the answer to a request that went wrong, so a failure here has
464
+ // nowhere to escalate to: this runs from `onError` as well as from the page handler, and Hono calls
465
+ // `onError` inside its own catch — a throw from there rejects `app.fetch`, which
466
+ // `@hono/node-server` turns into a bodiless 500 with nothing in the log. So it is answered here, the
467
+ // way a failing `error` page is answered below.
468
+ //
469
+ // A `redirect()` from the page is the exception: nothing is committed yet, the branch above cannot
470
+ // fail, and this is what the same page does when `app.notFound` renders it — so it is honoured, and
471
+ // recurses exactly once.
472
+ if (error instanceof RedirectSignal)
473
+ return respondToControlSignal(c, error);
474
+ reportServerError(error, { source: 'render', hono: c, message: '[rshono] the notFound page failed to render:' });
475
+ }
353
476
  }
354
477
  return plainNotFound(c);
355
478
  };
@@ -358,9 +481,12 @@ function buildApp() {
358
481
  // Both fixed for the life of the process, so resolved once rather than per request.
359
482
  const servesPrerendered = !isDev && route.render === 'static';
360
483
  const loadPage = once(() => loadPageModule(route.component, `"${route.path}"`));
361
- const handler = async (c) => {
484
+ /** Everything the route answers, before a HEAD has its body taken off it. */
485
+ const respond = async (c) => {
362
486
  try {
363
- if (servesPrerendered && c.req.method === 'GET') {
487
+ // A HEAD takes the GET path, prerendered bytes included: the headers it promises are the ones a
488
+ // GET would send, `etag` and `content-length` among them.
489
+ if (servesPrerendered && (c.req.method === 'GET' || c.req.method === 'HEAD')) {
364
490
  const isRsc = asksForRsc(c.req.raw);
365
491
  // One fixed set of bytes cannot carry a per-request nonce, so a document has to be rendered
366
492
  // where the app's CSP has one. Decided per request, so an app whose policy carries no `NONCE`
@@ -392,6 +518,20 @@ function buildApp() {
392
518
  throw error;
393
519
  }
394
520
  };
521
+ const handler = async (c) => {
522
+ const response = await respond(c);
523
+ // Hono dispatches a HEAD to the GET route and then rebuilds the response as `new Response(null, res)`,
524
+ // which drops the body without reading it — so for a rendered page nothing ever consumes the stream:
525
+ // `flight-inject`'s `cancel` never runs, and neither does the `release()` that detaches the abort
526
+ // forwarder from the request signal. Cancelling here is what ends the render nobody asked to read.
527
+ if (c.req.method === 'HEAD' && response.body !== null) {
528
+ void response.body.cancel().catch(() => {
529
+ // Already errored or locked, and there is nothing left to release either way.
530
+ });
531
+ return new Response(null, response);
532
+ }
533
+ return response;
534
+ };
395
535
  app.on(['GET', 'POST'], route.path, handler);
396
536
  }
397
537
  else {
@@ -403,18 +543,24 @@ function buildApp() {
403
543
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
404
544
  return endpointHandler(c, next);
405
545
  };
406
- const method = route.method ?? 'all';
407
- if (method === 'all')
546
+ // De-duplicated, because `app.on(['GET', 'GET'], …)` registers the path twice. Validation refuses
547
+ // `'all'` inside a list, so a list that reaches here is concrete methods only.
548
+ const methods = [...new Set([route.method ?? 'all'].flat())];
549
+ if (methods.includes('all'))
408
550
  app.all(route.path, handler);
409
- else
410
- app.on(method.toUpperCase(), route.path, handler);
551
+ else {
552
+ app.on(methods.map((method) => method.toUpperCase()), route.path, handler);
553
+ }
411
554
  }
412
555
  }
413
556
  runtime.mountPublicFallback(app);
414
557
  app.notFound(async (c) => {
415
558
  const isRsc = requestWantsRsc(c.req.raw);
416
559
  if (loadNotFoundPage && (isRsc || acceptsHtml(c))) {
417
- return runWithContext(c, async () => renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc }));
560
+ // `notFound: true` here as well as on the signal path: the two produce the same page for the same
561
+ // status, and a payload that says so from one route and not the other is a wire contract with a hole
562
+ // in it. The client reads it to tell "this is the 404 page" from "this is the page you asked for".
563
+ return runWithContext(c, async () => renderComponent(c, await loadNotFoundPage(), { status: 404, isRsc, notFound: true }));
418
564
  }
419
565
  return plainNotFound(c);
420
566
  });
@@ -430,7 +576,7 @@ function buildApp() {
430
576
  const res = error.getResponse();
431
577
  return c.newResponse(res.body, res);
432
578
  }
433
- reportServerError(error, { source: 'request', request: c.req.raw, message: '[rshono] request error:' });
579
+ reportServerError(error, { source: 'request', hono: c, message: '[rshono] request error:' });
434
580
  const isRsc = requestWantsRsc(c.req.raw);
435
581
  if (loadErrorPage && (isRsc || acceptsHtml(c))) {
436
582
  const errorInfo = isDev
@@ -440,14 +586,16 @@ function buildApp() {
440
586
  }
441
587
  : { message: 'Internal Server Error' };
442
588
  try {
443
- return await runWithContext(c, async () => renderComponent(c, await loadErrorPage(), { status: 500, isRsc, errorInfo }));
589
+ return await runWithContext(c, async () => renderComponent(c, await loadErrorPage(), { status: 500, isRsc, errorInfo, returnValue: actionResults.get(c) }));
444
590
  }
445
591
  catch (renderError) {
446
- reportServerError(renderError, { source: 'request', request: c.req.raw, message: '[rshono] the error page failed to render:' });
592
+ reportServerError(renderError, { source: 'request', hono: c, message: '[rshono] the error page failed to render:' });
447
593
  }
448
594
  }
449
595
  const detail = isDev ? `\n\n${error instanceof Error ? (error.stack ?? error.message) : String(error)}` : '';
450
- return c.text(`Internal Server Error${detail}`, 500, { vary: RSC_VARY_HEADER });
596
+ // Same reason as `plainNotFound`, minus the urgency: a 500 is not heuristically cacheable, so this half
597
+ // is consistency — the framework's own answers should not differ in what they promise about caching.
598
+ return c.text(`Internal Server Error${detail}`, 500, { vary: RSC_VARY_HEADER, 'cache-control': PAGE_CACHE_CONTROL });
451
599
  });
452
600
  return app;
453
601
  }