@rshono/core 1.0.0-rc.0 → 1.0.0-rc.10

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 (143) hide show
  1. package/README.md +202 -159
  2. package/dist/builder/page-files.d.ts.map +1 -1
  3. package/dist/builder/page-files.js +7 -3
  4. package/dist/builder/page-files.js.map +1 -1
  5. package/dist/builder/public-env.d.ts +6 -0
  6. package/dist/builder/public-env.d.ts.map +1 -1
  7. package/dist/builder/public-env.js +6 -0
  8. package/dist/builder/public-env.js.map +1 -1
  9. package/dist/builder/rspack-config.d.ts +3 -3
  10. package/dist/builder/rspack-config.d.ts.map +1 -1
  11. package/dist/builder/rspack-config.js +62 -16
  12. package/dist/builder/rspack-config.js.map +1 -1
  13. package/dist/cli/build.d.ts +2 -2
  14. package/dist/cli/build.js.map +1 -1
  15. package/dist/cli/dev.d.ts +2 -2
  16. package/dist/cli/dev.d.ts.map +1 -1
  17. package/dist/cli/dev.js +63 -35
  18. package/dist/cli/dev.js.map +1 -1
  19. package/dist/cli/index.js +10 -10
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/config.d.ts +58 -70
  22. package/dist/config.d.ts.map +1 -1
  23. package/dist/config.js +17 -1
  24. package/dist/config.js.map +1 -1
  25. package/dist/deploy/cloudflare/build.js +1 -1
  26. package/dist/deploy/cloudflare/build.js.map +1 -1
  27. package/dist/deploy/cloudflare/runtime.d.ts.map +1 -1
  28. package/dist/deploy/cloudflare/runtime.js +7 -37
  29. package/dist/deploy/cloudflare/runtime.js.map +1 -1
  30. package/dist/deploy/contract.d.ts +22 -16
  31. package/dist/deploy/contract.d.ts.map +1 -1
  32. package/dist/deploy/contract.js.map +1 -1
  33. package/dist/deploy/filesystem.d.ts +1 -1
  34. package/dist/deploy/filesystem.d.ts.map +1 -1
  35. package/dist/deploy/filesystem.js +7 -10
  36. package/dist/deploy/filesystem.js.map +1 -1
  37. package/dist/deploy/node/runtime.d.ts +4 -0
  38. package/dist/deploy/node/runtime.d.ts.map +1 -1
  39. package/dist/deploy/node/runtime.js +24 -3
  40. package/dist/deploy/node/runtime.js.map +1 -1
  41. package/dist/deploy/presets.d.ts +3 -3
  42. package/dist/deploy/presets.d.ts.map +1 -1
  43. package/dist/deploy/presets.js +13 -30
  44. package/dist/deploy/presets.js.map +1 -1
  45. package/dist/deploy/vercel/runtime.d.ts.map +1 -1
  46. package/dist/deploy/vercel/runtime.js +0 -3
  47. package/dist/deploy/vercel/runtime.js.map +1 -1
  48. package/dist/index.d.ts +6 -9
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +8 -3
  51. package/dist/index.js.map +1 -1
  52. package/dist/router.d.ts +85 -48
  53. package/dist/router.d.ts.map +1 -1
  54. package/dist/router.js +4 -6
  55. package/dist/router.js.map +1 -1
  56. package/dist/runtime/boundaries.d.ts +39 -25
  57. package/dist/runtime/boundaries.d.ts.map +1 -1
  58. package/dist/runtime/boundaries.js +22 -17
  59. package/dist/runtime/boundaries.js.map +1 -1
  60. package/dist/runtime/client.d.ts +9 -8
  61. package/dist/runtime/client.d.ts.map +1 -1
  62. package/dist/runtime/client.js +9 -8
  63. package/dist/runtime/client.js.map +1 -1
  64. package/dist/runtime/context.d.ts +216 -70
  65. package/dist/runtime/context.d.ts.map +1 -1
  66. package/dist/runtime/context.js +299 -93
  67. package/dist/runtime/context.js.map +1 -1
  68. package/dist/runtime/control.d.ts.map +1 -1
  69. package/dist/runtime/control.js +7 -0
  70. package/dist/runtime/control.js.map +1 -1
  71. package/dist/runtime/dev-protocol.d.ts.map +1 -1
  72. package/dist/runtime/dev-protocol.js.map +1 -1
  73. package/dist/runtime/entry.client.d.ts +4 -0
  74. package/dist/runtime/entry.client.d.ts.map +1 -1
  75. package/dist/runtime/entry.client.js +190 -154
  76. package/dist/runtime/entry.client.js.map +1 -1
  77. package/dist/runtime/entry.rsc.d.ts.map +1 -1
  78. package/dist/runtime/entry.rsc.js +145 -159
  79. package/dist/runtime/entry.rsc.js.map +1 -1
  80. package/dist/runtime/entry.ssr.d.ts +9 -1
  81. package/dist/runtime/entry.ssr.d.ts.map +1 -1
  82. package/dist/runtime/entry.ssr.js +36 -18
  83. package/dist/runtime/entry.ssr.js.map +1 -1
  84. package/dist/runtime/flight-inject.d.ts +31 -0
  85. package/dist/runtime/flight-inject.d.ts.map +1 -0
  86. package/dist/runtime/flight-inject.js +221 -0
  87. package/dist/runtime/flight-inject.js.map +1 -0
  88. package/dist/runtime/navigation.d.ts +20 -38
  89. package/dist/runtime/navigation.d.ts.map +1 -1
  90. package/dist/runtime/navigation.js +10 -53
  91. package/dist/runtime/navigation.js.map +1 -1
  92. package/dist/runtime/request.d.ts +6 -0
  93. package/dist/runtime/request.d.ts.map +1 -1
  94. package/dist/runtime/request.js +8 -0
  95. package/dist/runtime/request.js.map +1 -1
  96. package/dist/runtime/server.d.ts +7 -12
  97. package/dist/runtime/server.d.ts.map +1 -1
  98. package/dist/runtime/server.js +15 -12
  99. package/dist/runtime/server.js.map +1 -1
  100. package/dist/server/headers.d.ts +9 -9
  101. package/dist/server/headers.js +9 -9
  102. package/dist/server/headers.js.map +1 -1
  103. package/dist/server/load-config.d.ts +2 -2
  104. package/dist/server/load-config.d.ts.map +1 -1
  105. package/dist/server/load-config.js +22 -11
  106. package/dist/server/load-config.js.map +1 -1
  107. package/dist/server/prerendered.d.ts +43 -15
  108. package/dist/server/prerendered.d.ts.map +1 -1
  109. package/dist/server/prerendered.js +47 -0
  110. package/dist/server/prerendered.js.map +1 -1
  111. package/dist/server/server-config.d.ts +13 -39
  112. package/dist/server/server-config.d.ts.map +1 -1
  113. package/dist/server/server-config.js +5 -74
  114. package/dist/server/server-config.js.map +1 -1
  115. package/dist/server/ssg.d.ts +2 -2
  116. package/dist/server/ssg.d.ts.map +1 -1
  117. package/dist/server/ssg.js +21 -34
  118. package/dist/server/ssg.js.map +1 -1
  119. package/package.json +13 -16
  120. package/dist/deploy/bun/runtime.d.ts +0 -11
  121. package/dist/deploy/bun/runtime.d.ts.map +0 -1
  122. package/dist/deploy/bun/runtime.js +0 -22
  123. package/dist/deploy/bun/runtime.js.map +0 -1
  124. package/dist/deploy/deno/runtime.d.ts +0 -11
  125. package/dist/deploy/deno/runtime.d.ts.map +0 -1
  126. package/dist/deploy/deno/runtime.js +0 -16
  127. package/dist/deploy/deno/runtime.js.map +0 -1
  128. package/dist/deploy/listen.d.ts +0 -20
  129. package/dist/deploy/listen.d.ts.map +0 -1
  130. package/dist/deploy/listen.js +0 -24
  131. package/dist/deploy/listen.js.map +0 -1
  132. package/dist/deploy/netlify/build.d.ts +0 -8
  133. package/dist/deploy/netlify/build.d.ts.map +0 -1
  134. package/dist/deploy/netlify/build.js +0 -52
  135. package/dist/deploy/netlify/build.js.map +0 -1
  136. package/dist/deploy/netlify/runtime.d.ts +0 -13
  137. package/dist/deploy/netlify/runtime.d.ts.map +0 -1
  138. package/dist/deploy/netlify/runtime.js +0 -24
  139. package/dist/deploy/netlify/runtime.js.map +0 -1
  140. package/dist/server/compress.d.ts +0 -15
  141. package/dist/server/compress.d.ts.map +0 -1
  142. package/dist/server/compress.js +0 -76
  143. package/dist/server/compress.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"boundaries.js","sourceRoot":"","sources":["../../src/runtime/boundaries.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;;GAKG;AACH,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,eAAe,CAAE,KAAqC,EAAE,MAAM,CAAC,CAAC;AACzE,CAAC;AAmCD,SAAS,WAAW,CAAC,CAAqB,EAAE,CAAqB;IAC/D,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,OAAO,aAAc,SAAQ,SAAiD;IAClF,KAAK,GAAuB,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAE5C,MAAM,CAAC,wBAAwB,CAAC,KAAY;QAC1C,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,iBAAiB,CAAC,KAAY;QAC5B,IAAI,cAAc,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,sCAAsC;QACzE,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,kBAAkB,CAAC,IAAwB;QACzC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QACjC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,IAAI,SAAS,IAAI,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;YAC9F,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,GAAG,GAAS,EAAE;QACjB,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACjC,CAAC,CAAC;IAEF,MAAM;QACJ,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QAC7B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,IAAI,cAAc,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC,CAAC,sDAAsD;YAC9F,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;YAChC,IAAI,QAAQ,KAAK,SAAS;gBAAE,MAAM,KAAK,CAAC,CAAC,qDAAqD;YAC9F,OAAO,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACjF,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACF;AAcD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAiB;IAC7F,OAAO,CACL,KAAC,aAAa,IAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,YACpE,KAAC,QAAQ,IAAC,QAAQ,EAAE,OAAO,YAAG,QAAQ,GAAY,GACpC,CACjB,CAAC;AACJ,CAAC","sourcesContent":["'use client';\n\nimport { Component, Suspense, type ReactNode } from 'react';\nimport { isControlDigest } from './control.js';\n\n/**\n * `redirect()` and `notFound()` reach the browser as a thrown error carrying a control digest.\n * They are navigation, not failure, so no boundary may absorb one — otherwise a `redirect()` from\n * a component inside a `<Boundary>` would render \"something went wrong\" instead of navigating.\n * They're re-thrown to the root, where the runtime turns the digest into a real navigation.\n */\nfunction isControlError(error: unknown): boolean {\n return isControlDigest((error as { digest?: unknown } | null)?.digest);\n}\n\n/**\n * What an {@link ErrorBoundary} / {@link Boundary} renders once a child throws.\n * Either a static node, or a render function that also gets a `reset` callback\n * to clear the error and re-render the children (e.g. a \"Try again\" button).\n *\n * The render-function form only works when the boundary is used from a `'use\n * client'` component — functions can't cross the server→client boundary. From a\n * server component, pass a `ReactNode`.\n */\nexport type ErrorFallback = ReactNode | ((error: Error, reset: () => void) => ReactNode);\n\nexport interface ErrorBoundaryProps {\n /**\n * Rendered in place of the children after one of them throws. Omit it to\n * report the error via `onError` and re-throw to the next boundary out (or\n * the global error page) instead of handling it here.\n */\n fallback?: ErrorFallback;\n /** Called with the caught error (for logging / reporting). */\n onError?: (error: Error) => void;\n /**\n * When any value in this array changes while the boundary is showing its\n * fallback, the error is cleared automatically. Pass the current pathname to\n * recover when the user navigates away: `resetKeys={[useNavigation().url.pathname]}`.\n */\n resetKeys?: readonly unknown[];\n children: ReactNode;\n}\n\ninterface ErrorBoundaryState {\n error: Error | null;\n}\n\nfunction keysChanged(a: readonly unknown[], b: readonly unknown[]): boolean {\n return a.length !== b.length || a.some((value, i) => !Object.is(value, b[i]));\n}\n\n/**\n * A general-purpose error boundary. Catches errors thrown while rendering its\n * children — a client island that blew up, or a server component that rejected\n * on a soft navigation — and renders `fallback` in their place instead of\n * tearing down the whole page.\n *\n * It's a `'use client'` component (React error boundaries must be), so drop it\n * anywhere in the tree from a server or client component. Use {@link Boundary}\n * when you also want a Suspense loading fallback in the same wrapper.\n *\n * @example\n * ```tsx\n * import { ErrorBoundary } from '@rshono/core/client';\n *\n * <ErrorBoundary fallback={(error, reset) => (\n * <div role=\"alert\">\n * <p>{error.message}</p>\n * <button onClick={reset}>Try again</button>\n * </div>\n * )}>\n * <RiskyWidget />\n * </ErrorBoundary>\n * ```\n */\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n state: ErrorBoundaryState = { error: null };\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { error };\n }\n\n componentDidCatch(error: Error): void {\n if (isControlError(error)) return; // a redirect isn't an error to report\n this.props.onError?.(error);\n }\n\n componentDidUpdate(prev: ErrorBoundaryProps): void {\n const { resetKeys } = this.props;\n if (this.state.error && prev.resetKeys && resetKeys && keysChanged(prev.resetKeys, resetKeys)) {\n this.reset();\n }\n }\n\n reset = (): void => {\n this.setState({ error: null });\n };\n\n render(): ReactNode {\n const { error } = this.state;\n if (error !== null) {\n if (isControlError(error)) throw error; // navigation in flight — never show a fallback for it\n const { fallback } = this.props;\n if (fallback === undefined) throw error; // no local fallback → propagate to an outer boundary\n return typeof fallback === 'function' ? fallback(error, this.reset) : fallback;\n }\n return this.props.children;\n }\n}\n\nexport interface BoundaryProps {\n /** Suspense fallback, shown while the children (or their data) are still loading. */\n loading?: ReactNode;\n /** Error fallback, shown if a child throws. See {@link ErrorFallback}. */\n error?: ErrorFallback;\n /** Called with the caught error. */\n onError?: (error: Error) => void;\n /** Clears the error fallback when any value changes — see {@link ErrorBoundaryProps.resetKeys}. */\n resetKeys?: readonly unknown[];\n children: ReactNode;\n}\n\n/**\n * A loading + error boundary in one wrapper — the common case for an async\n * section of a page. It always renders the same shape:\n *\n * ```tsx\n * <ErrorBoundary fallback={error}>\n * <Suspense fallback={loading}>{children}</Suspense>\n * </ErrorBoundary>\n * ```\n *\n * so `error` catches anything the children throw (including while suspended) and\n * `loading` shows until they resolve. Both fallbacks are optional: omit\n * `loading` and nothing shows while loading; omit `error` and thrown errors\n * propagate to the next boundary out (or the global error page) rather than\n * being caught here.\n *\n * @example\n * ```tsx\n * import { Boundary } from '@rshono/core/client';\n *\n * <Boundary loading={<Spinner />} error={(e, reset) => <Retry onClick={reset} />}>\n * <SlowServerComponent />\n * </Boundary>\n * ```\n */\nexport function Boundary({ loading = null, error, onError, resetKeys, children }: BoundaryProps): ReactNode {\n return (\n <ErrorBoundary fallback={error} onError={onError} resetKeys={resetKeys}>\n <Suspense fallback={loading}>{children}</Suspense>\n </ErrorBoundary>\n );\n}\n"]}
1
+ {"version":3,"file":"boundaries.js","sourceRoot":"","sources":["../../src/runtime/boundaries.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;;GAKG;AACH,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,eAAe,CAAE,KAAqC,EAAE,MAAM,CAAC,CAAC;AACzE,CAAC;AAqCD,SAAS,WAAW,CAAC,CAAqB,EAAE,CAAqB;IAC/D,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,OAAO,aAAc,SAAQ,SAAiD;IAClF,KAAK,GAAuB,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAE5C,MAAM,CAAC,wBAAwB,CAAC,KAAY;QAC1C,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,iBAAiB,CAAC,KAAY;QAC5B,IAAI,cAAc,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,sCAAsC;QACzE,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,kBAAkB,CAAC,IAAwB;QACzC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QACjC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,IAAI,SAAS,IAAI,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;YAC9F,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,GAAG,GAAS,EAAE;QACjB,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACjC,CAAC,CAAC;IAEF,MAAM;QACJ,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QAC7B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,IAAI,cAAc,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC,CAAC,sDAAsD;YAC9F,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;YAChC,IAAI,QAAQ,KAAK,SAAS;gBAAE,MAAM,KAAK,CAAC,CAAC,qDAAqD;YAC9F,OAAO,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACjF,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACF;AAqBD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAsB;IAChG,OAAO,CACL,KAAC,aAAa,IAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,YACpE,KAAC,QAAQ,IAAC,QAAQ,EAAE,OAAO,YAAG,QAAQ,GAAY,GACpC,CACjB,CAAC;AACJ,CAAC","sourcesContent":["'use client';\n\nimport { Component, Suspense, type ReactNode } from 'react';\nimport { isControlDigest } from './control.js';\n\n/**\n * `redirect()` and `notFound()` reach the browser as a thrown error carrying a control digest.\n * They are navigation, not failure, so no boundary may absorb one — otherwise a `redirect()` from\n * a component inside a `<CatchBoundary>` would render \"something went wrong\" instead of navigating.\n * They're re-thrown to the root, where the runtime turns the digest into a real navigation.\n */\nfunction isControlError(error: unknown): boolean {\n return isControlDigest((error as { digest?: unknown } | null)?.digest);\n}\n\n/**\n * What a {@link CatchBoundary} / {@link AsyncBoundary} renders once a child throws.\n * Either a static node, or a render function that also gets a `reset` callback\n * to clear the error and re-render the children (e.g. a \"Try again\" button).\n *\n * The render-function form only works when the boundary is used from a `'use\n * client'` component — functions can't cross the server→client boundary. From a\n * server component, pass a `ReactNode`.\n */\nexport type ErrorFallback = ReactNode | ((error: Error, reset: () => void) => ReactNode);\n\n/** Props for {@link CatchBoundary}. */\nexport interface CatchBoundaryProps {\n /**\n * Rendered in place of the children after one of them throws. Omit it to\n * report the error via `onError` and re-throw to the next boundary out (or\n * the global error page) instead of handling it here.\n */\n fallback?: ErrorFallback;\n /** Called with the caught error (for logging / reporting). */\n onError?: (error: Error) => void;\n /**\n * When any value in this array changes while the boundary is showing its\n * fallback, the error is cleared automatically. Pass the current pathname to\n * recover when the user navigates away: `resetKeys={[useNavigation().url.pathname]}`.\n */\n resetKeys?: readonly unknown[];\n /** The subtree this boundary protects. */\n children: ReactNode;\n}\n\ninterface CatchBoundaryState {\n error: Error | null;\n}\n\nfunction keysChanged(a: readonly unknown[], b: readonly unknown[]): boolean {\n return a.length !== b.length || a.some((value, i) => !Object.is(value, b[i]));\n}\n\n/**\n * A general-purpose error boundary. Catches errors thrown while rendering its\n * children — a client island that blew up, or a server component that rejected\n * on a soft navigation — and renders `fallback` in their place instead of\n * tearing down the whole page.\n *\n * It's a `'use client'` component (React error boundaries must be), so drop it\n * anywhere in the tree from a server or client component. Use {@link AsyncBoundary}\n * when you also want a Suspense loading fallback in the same wrapper.\n *\n * @example\n * ```tsx\n * import { CatchBoundary } from '@rshono/core/client';\n *\n * <CatchBoundary fallback={(error, reset) => (\n * <div role=\"alert\">\n * <p>{error.message}</p>\n * <button onClick={reset}>Try again</button>\n * </div>\n * )}>\n * <RiskyWidget />\n * </CatchBoundary>\n * ```\n *\n * @see {@link https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary | React — error boundaries}\n * @see {@link https://www.rshono.com/docs/api#rshonocoreclient | Docs — `@rshono/core/client`}\n */\nexport class CatchBoundary extends Component<CatchBoundaryProps, CatchBoundaryState> {\n state: CatchBoundaryState = { error: null };\n\n static getDerivedStateFromError(error: Error): CatchBoundaryState {\n return { error };\n }\n\n componentDidCatch(error: Error): void {\n if (isControlError(error)) return; // a redirect isn't an error to report\n this.props.onError?.(error);\n }\n\n componentDidUpdate(prev: CatchBoundaryProps): void {\n const { resetKeys } = this.props;\n if (this.state.error && prev.resetKeys && resetKeys && keysChanged(prev.resetKeys, resetKeys)) {\n this.reset();\n }\n }\n\n reset = (): void => {\n this.setState({ error: null });\n };\n\n render(): ReactNode {\n const { error } = this.state;\n if (error !== null) {\n if (isControlError(error)) throw error; // navigation in flight — never show a fallback for it\n const { fallback } = this.props;\n if (fallback === undefined) throw error; // no local fallback → propagate to an outer boundary\n return typeof fallback === 'function' ? fallback(error, this.reset) : fallback;\n }\n return this.props.children;\n }\n}\n\n/** Props for {@link AsyncBoundary}. */\nexport interface AsyncBoundaryProps {\n /**\n * Suspense fallback, shown while the children (or their data) are still\n * loading. Required — a loading state is the reason to reach for this over\n * {@link CatchBoundary}, so showing nothing is an explicit `loading={null}`\n * rather than something you get by leaving the prop off.\n */\n loading: ReactNode;\n /** Error fallback, shown if a child throws. See {@link ErrorFallback}. */\n error?: ErrorFallback;\n /** Called with the caught error. */\n onError?: (error: Error) => void;\n /** Clears the error fallback when any value changes — see {@link CatchBoundaryProps.resetKeys}. */\n resetKeys?: readonly unknown[];\n /** The subtree this boundary suspends on and protects. */\n children: ReactNode;\n}\n\n/**\n * A loading + error boundary in one wrapper — the common case for an async\n * section of a page. It always renders the same shape:\n *\n * ```tsx\n * <CatchBoundary fallback={error}>\n * <Suspense fallback={loading}>{children}</Suspense>\n * </CatchBoundary>\n * ```\n *\n * so `error` catches anything the children throw (including while suspended) and\n * `loading` shows until they resolve. `error` is optional: omit it and thrown\n * errors propagate to the next boundary out (or the global error page) rather\n * than being caught here.\n *\n * @example\n * ```tsx\n * import { AsyncBoundary } from '@rshono/core/client';\n *\n * <AsyncBoundary loading={<Spinner />} error={(e, reset) => <Retry onClick={reset} />}>\n * <SlowServerComponent />\n * </AsyncBoundary>\n * ```\n *\n * @see {@link https://react.dev/reference/react/Suspense | React — `<Suspense>`}\n * @see {@link https://www.rshono.com/docs/api#rshonocoreclient | Docs — `@rshono/core/client`}\n */\nexport function AsyncBoundary({ loading, error, onError, resetKeys, children }: AsyncBoundaryProps): ReactNode {\n return (\n <CatchBoundary fallback={error} onError={onError} resetKeys={resetKeys}>\n <Suspense fallback={loading}>{children}</Suspense>\n </CatchBoundary>\n );\n}\n"]}
@@ -1,16 +1,17 @@
1
1
  /**
2
2
  * `@rshono/core/client` — the browser-side surface, for use from `'use client'`
3
- * modules: {@link useNavigation} for the current URL and soft navigation, and
4
- * {@link Boundary} / {@link ErrorBoundary} / {@link NavigationProgress} as
5
- * components.
3
+ * modules: `useNavigation()` for the current URL and soft navigation, and
4
+ * `<AsyncBoundary>` / `<CatchBoundary>` as components.
6
5
  *
7
6
  * Every export is itself a `'use client'` module, so a server component can
8
- * render {@link Boundary} or {@link NavigationProgress} directly — but the hook
9
- * needs a client component. In a server component, read the same request data
10
- * from `getContext()` in `@rshono/core/server`.
7
+ * render `<AsyncBoundary>` directly — but the hook needs a client component. In a
8
+ * server component, read the same request data from `getRequestContext()` in
9
+ * `@rshono/core/server`.
10
+ *
11
+ * @see {@link https://www.rshono.com/docs/api#rshonocoreclient | Docs — `@rshono/core/client`}
11
12
  *
12
13
  * @packageDocumentation
13
14
  */
14
- export { NavigationProgress, useNavigation, type Navigation, type NavigationProgressProps, type Router } from './navigation.js';
15
- export { Boundary, ErrorBoundary, type BoundaryProps, type ErrorBoundaryProps, type ErrorFallback } from './boundaries.js';
15
+ export { useNavigation, type NavigationRouter, type NavigationState } from './navigation.js';
16
+ export { AsyncBoundary, CatchBoundary, type AsyncBoundaryProps, type CatchBoundaryProps, type ErrorFallback } from './boundaries.js';
16
17
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/runtime/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,uBAAuB,EAAE,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAChI,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/runtime/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC7F,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,16 +1,17 @@
1
1
  /**
2
2
  * `@rshono/core/client` — the browser-side surface, for use from `'use client'`
3
- * modules: {@link useNavigation} for the current URL and soft navigation, and
4
- * {@link Boundary} / {@link ErrorBoundary} / {@link NavigationProgress} as
5
- * components.
3
+ * modules: `useNavigation()` for the current URL and soft navigation, and
4
+ * `<AsyncBoundary>` / `<CatchBoundary>` as components.
6
5
  *
7
6
  * Every export is itself a `'use client'` module, so a server component can
8
- * render {@link Boundary} or {@link NavigationProgress} directly — but the hook
9
- * needs a client component. In a server component, read the same request data
10
- * from `getContext()` in `@rshono/core/server`.
7
+ * render `<AsyncBoundary>` directly — but the hook needs a client component. In a
8
+ * server component, read the same request data from `getRequestContext()` in
9
+ * `@rshono/core/server`.
10
+ *
11
+ * @see {@link https://www.rshono.com/docs/api#rshonocoreclient | Docs — `@rshono/core/client`}
11
12
  *
12
13
  * @packageDocumentation
13
14
  */
14
- export { NavigationProgress, useNavigation } from './navigation.js';
15
- export { Boundary, ErrorBoundary } from './boundaries.js';
15
+ export { useNavigation } from './navigation.js';
16
+ export { AsyncBoundary, CatchBoundary } from './boundaries.js';
16
17
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/runtime/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAA8D,MAAM,iBAAiB,CAAC;AAChI,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAmE,MAAM,iBAAiB,CAAC","sourcesContent":["/**\n * `@rshono/core/client` — the browser-side surface, for use from `'use client'`\n * modules: {@link useNavigation} for the current URL and soft navigation, and\n * {@link Boundary} / {@link ErrorBoundary} / {@link NavigationProgress} as\n * components.\n *\n * Every export is itself a `'use client'` module, so a server component can\n * render {@link Boundary} or {@link NavigationProgress} directly — but the hook\n * needs a client component. In a server component, read the same request data\n * from `getContext()` in `@rshono/core/server`.\n *\n * @packageDocumentation\n */\n\nexport { NavigationProgress, useNavigation, type Navigation, type NavigationProgressProps, type Router } from './navigation.js';\nexport { Boundary, ErrorBoundary, type BoundaryProps, type ErrorBoundaryProps, type ErrorFallback } from './boundaries.js';\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/runtime/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,aAAa,EAA+C,MAAM,iBAAiB,CAAC;AAC7F,OAAO,EAAE,aAAa,EAAE,aAAa,EAAwE,MAAM,iBAAiB,CAAC","sourcesContent":["/**\n * `@rshono/core/client` — the browser-side surface, for use from `'use client'`\n * modules: `useNavigation()` for the current URL and soft navigation, and\n * `<AsyncBoundary>` / `<CatchBoundary>` as components.\n *\n * Every export is itself a `'use client'` module, so a server component can\n * render `<AsyncBoundary>` directly — but the hook needs a client component. In a\n * server component, read the same request data from `getRequestContext()` in\n * `@rshono/core/server`.\n *\n * @see {@link https://www.rshono.com/docs/api#rshonocoreclient | Docs — `@rshono/core/client`}\n *\n * @packageDocumentation\n */\n\nexport { useNavigation, type NavigationRouter, type NavigationState } from './navigation.js';\nexport { AsyncBoundary, CatchBoundary, type AsyncBoundaryProps, type CatchBoundaryProps, type ErrorFallback } from './boundaries.js';\n"]}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The request context: {@link getContext} and the {@link Ctx} wrapper it returns,
2
+ * The request context: {@link getRequestContext} and the {@link RequestContext} wrapper it returns,
3
3
  * the {@link redirect} / {@link notFound} control-flow helpers, and the
4
4
  * {@link onServerError} reporting funnel — plus the `@internal` plumbing that binds
5
5
  * a request to the async context in the first place.
@@ -9,7 +9,7 @@
9
9
  * here is safe in a `'use client'` module — those run in the browser, with no bound
10
10
  * request context.
11
11
  */
12
- import type { Context, Env, HonoRequest } from 'hono';
12
+ import type { Context, Env } from 'hono';
13
13
  import type { CookieOptions } from 'hono/utils/cookie';
14
14
  /**
15
15
  * HTTP status codes accepted by {@link redirect}.
@@ -18,153 +18,293 @@ import type { CookieOptions } from 'hono/utils/cookie';
18
18
  * - `302` Found, `307` Temporary Redirect — temporary.
19
19
  * - `303` See Other — the default; forces a `GET` on the target, which is what
20
20
  * you almost always want after a form action (post/redirect/get).
21
+ *
22
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status#redirection_messages | MDN — redirection status codes}
21
23
  */
22
24
  export type RedirectStatus = 301 | 302 | 303 | 307 | 308;
25
+ /**
26
+ * Marks the request as having entered its page render, which is what makes
27
+ * {@link RequestContext.setHeader} and `ctx.cookies.set()` start throwing.
28
+ *
29
+ * Framework internal — `renderComponent` calls this immediately before handing the page to React.
30
+ * Everything that legitimately writes to the response (middleware, a `'use server'` action, an
31
+ * endpoint route) has already run by then, so none of them are affected.
32
+ *
33
+ * @internal
34
+ */
35
+ export declare function beginPageRender(c: Context): void;
23
36
  /**
24
37
  * Runs `fn` with the given Hono {@link Context} bound as the ambient request
25
- * context, so that {@link getContext} resolves to it anywhere in the call tree.
38
+ * context, so that {@link getRequestContext} resolves to it anywhere in the call tree.
26
39
  *
27
40
  * Framework internal — the request handler wraps every render and action in
28
- * this. Application code should reach for {@link getContext} instead.
41
+ * this. Application code should reach for {@link getRequestContext} instead.
29
42
  *
30
43
  * @internal
31
44
  */
32
45
  export declare function runWithContext<T>(c: Context, fn: () => T): T;
33
46
  /**
34
- * Reads the matched route params, returning an empty object when there is no
35
- * active route match (rather than throwing). Shared by {@link Ctx.params} and the
36
- * request renderer so the fallback behaviour stays in one place.
47
+ * The matched route params, or an empty object when there is no active match.
37
48
  *
38
- * Framework internal — read params from {@link Ctx.params} or a page's
39
- * `PageProps` instead.
49
+ * Framework internal — the request renderer calls this to build a page's `params` prop, and
50
+ * {@link RequestContext.params} caches it. Read them from that prop, or from `ctx.params`.
40
51
  *
41
52
  * @internal
42
53
  */
43
54
  export declare function readParams(c: Context): Record<string, string>;
44
55
  /**
45
- * Resolves the browser-facing {@link URL} for a request.
56
+ * Resolves the browser-facing {@link URL} for a request, from a Hono {@link Context}.
46
57
  *
47
- * `c.req.url` reflects the internal address the server was reached on, which is wrong behind a
48
- * proxy or load balancer. `X-Forwarded-Host` / `X-Forwarded-Proto` fix that up — **but only when
49
- * `trustProxy` is enabled in `rshono.config.ts`** (always the case under `rshono dev`). Those
50
- * headers are client-supplied: honouring them unconditionally lets anyone who can reach the server
51
- * dictate the origin of every absolute URL the app builds — canonical tags, emails, redirects — and
52
- * poison a shared cache with them. So the default is to ignore them entirely.
58
+ * `c.req.url` reflects the internal address the server was reached on, which is wrong behind a proxy.
59
+ * `X-Forwarded-Host` / `X-Forwarded-Proto` fix that up — **but only when `trustProxy` is enabled in
60
+ * `rshono.config.ts`** (always so under `rshono dev`). They are client-supplied, so honouring them
61
+ * unconditionally would let anyone who can reach the server dictate the origin of every absolute URL
62
+ * the app builds, and poison a shared cache with it.
53
63
  *
54
- * Framework internal — prefer {@link Ctx.url}, which caches the result per request.
64
+ * This is the form for **middleware**, which is handed `c` and runs outside the request context. In
65
+ * a server component or a `'use server'` action prefer {@link RequestContext.url}, which is this same
66
+ * value cached per request.
55
67
  *
56
- * @internal
68
+ * Its main use is giving Hono's own middleware the origin the browser actually used, since they all
69
+ * read `c.req.url` on their own and so see the internal one:
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * // src/server.ts — a CSRF check that still works behind a proxy that rewrites Host
74
+ * import { publicUrl } from '@rshono/core/server';
75
+ * import { csrf } from 'hono/csrf';
76
+ *
77
+ * server.use(csrf({ origin: (origin, c) => origin === publicUrl(c).origin }));
78
+ * ```
79
+ *
80
+ * A fresh instance per call, so mutating it disturbs nothing else.
81
+ *
82
+ * @param c - The Hono {@link Context} for the request.
83
+ * @returns The browser-facing URL — proxy-corrected under `trustProxy`, `c.req.url` otherwise.
84
+ *
85
+ * @see {@link https://www.rshono.com/docs/configuration#proxy-headers | Docs — proxy headers}
57
86
  */
58
87
  export declare function publicUrl(c: Context): URL;
59
88
  /**
60
89
  * The environment available to a request: Cloudflare/Workers `Bindings` merged
61
90
  * with process env vars. Values not declared in `Bindings` are typed as
62
- * `string | undefined`. See {@link Ctx.env}.
91
+ * `string | undefined`. See {@link RequestContext.env}.
92
+ *
93
+ * @see {@link https://hono.dev/docs/getting-started/cloudflare-workers#bindings | Hono — bindings}
63
94
  */
64
95
  export type EnvVars<E extends Env> = E['Bindings'] & Record<string, string | undefined>;
65
96
  /**
66
97
  * Ergonomic, read-mostly wrapper around Hono's {@link Context} for use inside
67
98
  * server components and server actions.
68
99
  *
69
- * Obtain one with {@link getContext}, or — in a page component — take it straight
100
+ * Obtain one with {@link getRequestContext}, or — in a page component — take it straight
70
101
  * off the `ctx` prop, which is this same object. Never construct it yourself. One
71
102
  * instance is reused for the lifetime of a request, so its lazy getters
72
- * ({@link Ctx.url}, {@link Ctx.env}) are computed at most once.
103
+ * ({@link RequestContext.url}, {@link RequestContext.env}) are computed at most once.
73
104
  *
74
105
  * @typeParam E - The Hono {@link Env} describing this app's `Bindings` and
75
- * `Variables`, so {@link Ctx.var} and {@link Ctx.env} stay typed.
106
+ * `Variables`, so {@link RequestContext.var} and {@link RequestContext.env} stay typed.
76
107
  *
77
108
  * @example
78
109
  * ```tsx
79
- * import { getContext } from '@rshono/core/server';
110
+ * import { getRequestContext } from '@rshono/core/server';
80
111
  *
81
112
  * export default async function Whoami() {
82
- * const ctx = getContext();
113
+ * const ctx = getRequestContext();
83
114
  * const session = ctx.cookies.get('session');
84
115
  * return <p>{ctx.url.pathname} — {session ?? 'anonymous'}</p>;
85
116
  * }
86
117
  * ```
118
+ *
119
+ * @see {@link https://www.rshono.com/docs/api#rshonocoreserver | Docs — `@rshono/core/server`}
120
+ * @see {@link https://hono.dev/docs/api/context | Hono — Context}, reachable in full via {@link RequestContext.hono}
87
121
  */
88
- export declare class Ctx<E extends Env = Env> {
122
+ export declare class RequestContext<E extends Env = Env> {
89
123
  #private;
124
+ /**
125
+ * Framework internal — one instance is created per request and handed to you by
126
+ * {@link getRequestContext} or the `ctx` page prop. Application code never calls this.
127
+ *
128
+ * @internal
129
+ */
90
130
  constructor(c: Context<E>);
91
131
  /**
92
- * The underlying Hono {@link Context}. Escape hatch for anything this wrapper does not expose.
132
+ * The underlying Hono {@link Context} — the escape hatch for what this wrapper does not expose,
133
+ * such as `executionCtx.waitUntil()` on Workers.
134
+ *
135
+ * Its response builders (`redirect`, `notFound`, `json`, `body`, `status`, …) still do nothing from
136
+ * inside a page, for the reason the stubs on this class explain: reaching them through here
137
+ * bypasses the error, it does not make them work.
138
+ *
139
+ * @example
140
+ * ```ts
141
+ * getRequestContext().hono.executionCtx.waitUntil(logAsync()); // Workers
142
+ * ```
93
143
  *
94
- * A getter over a private field rather than a plain property, so it is not an *own enumerable*
95
- * one — which matters more than it looks. React's diagnostic for a value that cannot be sent to a
96
- * client component (`describeObjectForErrorMessage`) walks `Object.keys` recursively with no depth
97
- * limit and no cycle guard, and the Hono context graph reaches the socket and the whole server
98
- * through `req.raw` and `env`. While this was a plain property, passing a `Ctx` to a `'use client'`
99
- * component blew the stack *inside that message builder* — so React's actual, accurate "you cannot
100
- * pass this" error never got printed. Hidden from `Object.keys`, the walk stops here.
144
+ * @see {@link https://hono.dev/docs/api/context | Hono — Context}
101
145
  */
102
- get raw(): Context<E>;
103
- /** The parsed Hono request (`c.req`) — headers, body parsing, param access, etc. */
104
- get req(): HonoRequest;
146
+ get hono(): Context<E>;
105
147
  /**
106
- * The browser-facing request URL, proxy-header aware (see {@link publicUrl}) —
107
- * read `url.pathname`, `url.searchParams` and the rest off it. Parsed once and
108
- * cached, so the same instance comes back on every read within a request; treat
109
- * it as read-only for that reason.
148
+ * The parsed request — method, headers, path params, query and the body readers. Hono's
149
+ * {@link Context.req}, unwrapped, so `ctx.req.header('authorization')` rather than
150
+ * `ctx.hono.req.header(…)`.
151
+ *
152
+ * Reads only. Setting a *response* header is {@link RequestContext.setHeader}, deliberately in a
153
+ * different place — Hono's `c.header()` writing the response while `c.req.header()` reads the
154
+ * request is a well-worn source of confusion.
155
+ *
156
+ * @example
157
+ * ```ts
158
+ * const ctx = getRequestContext();
159
+ * ctx.req.method; // 'GET'
160
+ * ctx.req.header('authorization'); // string | undefined
161
+ * ctx.req.query('tab'); // string | undefined
162
+ * ```
163
+ *
164
+ * @see {@link https://hono.dev/docs/api/request | Hono — HonoRequest}
110
165
  */
111
- get url(): URL;
112
- /** The HTTP method of the request, e.g. `GET` or `POST`. */
113
- get method(): string;
166
+ get req(): Context<E>['req'];
114
167
  /**
115
- * Matched route params, e.g. `{ id }` for a `/users/[id]` route. Returns an
116
- * empty object when there is no active route match (rather than throwing).
168
+ * Matched route params for this request, e.g. `{ id: '42' }` for `/profile/:id`. Empty when there
169
+ * is no active route match.
170
+ *
171
+ * A **page** is handed the same record as its `params` prop, typed key-by-key from its route path,
172
+ * and that is the better read where it is available. This is for everywhere else — a nested server
173
+ * component, or a `'use server'` action — which get no props from the framework.
117
174
  */
118
175
  get params(): Record<string, string>;
176
+ /**
177
+ * The browser-facing request URL — read `url.pathname`, `url.searchParams` and the
178
+ * rest off it. Parsed once and cached, so the same instance comes back on every
179
+ * read within a request; treat it as read-only for that reason.
180
+ *
181
+ * `X-Forwarded-Host` / `-Proto` are honoured only when `trustProxy` is enabled in
182
+ * `rshono.config.ts`, since any client can send them.
183
+ *
184
+ * @see {@link https://www.rshono.com/docs/configuration#proxy-headers | Docs — proxy headers}
185
+ */
186
+ get url(): URL;
119
187
  /**
120
188
  * Typed variables set by middleware via `c.set('user', …)`, read here as
121
189
  * `ctx.var.user`. Type them by parameterising this class's {@link Env}.
190
+ *
191
+ * @example
192
+ * ```ts
193
+ * type AppEnv = { Variables: { user: { id: string } } };
194
+ * const { user } = getRequestContext<AppEnv>().var; // typed, set by your middleware
195
+ * ```
196
+ *
197
+ * @see {@link https://hono.dev/docs/api/context#var | Hono — c.var}
198
+ * @see {@link https://www.rshono.com/docs/hono#typing-the-context | Docs — typing the context}
122
199
  */
123
200
  get var(): Readonly<E['Variables']>;
124
201
  /**
125
202
  * Environment for the request: process env vars merged with runtime bindings
126
203
  * (bindings win on conflict). Computed once and cached.
127
204
  *
128
- * @example `const key = getContext().env.STRIPE_SECRET_KEY;`
205
+ * @example `const key = getRequestContext().env.STRIPE_SECRET_KEY;`
206
+ *
207
+ * @see {@link https://hono.dev/docs/api/context#env | Hono — c.env}
208
+ * @see {@link https://www.rshono.com/docs/configuration#environment-and-secrets | Docs — environment and secrets}
129
209
  */
130
210
  get env(): EnvVars<E>;
131
- /** Sets a response header. Thin pass-through to `c.header(name, value)`. */
132
- header(name: string, value: string): void;
133
211
  /**
134
212
  * Read and write request/response cookies.
135
213
  *
136
214
  * @example
137
215
  * ```ts
138
- * const ctx = getContext();
216
+ * const ctx = getRequestContext();
139
217
  * ctx.cookies.get('session'); // string | undefined
140
218
  * ctx.cookies.set('session', id, { httpOnly: true, sameSite: 'Lax', path: '/' });
141
219
  * ctx.cookies.delete('session', { path: '/' });
142
220
  * ```
221
+ *
222
+ * @see {@link https://hono.dev/docs/helpers/cookie | Hono — cookie helper}, which this wraps
143
223
  */
144
224
  cookies: {
145
- /** Reads a single cookie by name, or `undefined` if absent. */
225
+ /** Reads a single cookie by name, or `undefined` if absent. Safe anywhere, a page included. */
146
226
  get: (name: string) => string | undefined;
147
- /** Reads every cookie as a `{ name: value }` record. */
227
+ /** Reads every cookie as a `{ name: value }` record. Safe anywhere, a page included. */
148
228
  all: () => Record<string, string>;
149
- /** Sets a cookie on the response. See Hono's {@link CookieOptions} for `path`, `httpOnly`, `maxAge`, etc. */
229
+ /**
230
+ * Sets a cookie on the response. See Hono's {@link CookieOptions} for `path`, `httpOnly`,
231
+ * `maxAge`, etc.
232
+ *
233
+ * **Throws inside a page render** — see {@link RequestContext.setHeader}, of which a `Set-Cookie`
234
+ * is a special case. Set cookies from a `'use server'` action, or with Hono's `setCookie(c, …)`
235
+ * in middleware and endpoint routes.
236
+ *
237
+ * @throws If called while a page is rendering, where it could not reach the browser reliably.
238
+ *
239
+ * @see {@link https://hono.dev/docs/helpers/cookie#options | Hono — cookie options}
240
+ */
150
241
  set: (name: string, value: string, options?: CookieOptions) => void;
151
- /** Clears a cookie. Pass the same `path`/`domain` it was set with so the browser matches it. */
242
+ /**
243
+ * Clears a cookie. Pass the same `path`/`domain` it was set with so the browser matches it.
244
+ * Throws inside a page render, exactly as `set` does.
245
+ *
246
+ * @throws If called while a page is rendering.
247
+ */
152
248
  delete: (name: string, options?: CookieOptions) => void;
153
249
  };
250
+ /**
251
+ * Sets a header on the response — from a `'use server'` action, which is the one place a request
252
+ * context exists *and* the response is still open.
253
+ *
254
+ * From inside a page it throws: a page streams, so by then the response head is committed. Hono's
255
+ * `c.header()` fails there silently and inconsistently — landing on a full page load, vanishing on
256
+ * a soft navigation — so this refuses rather than doing it half the time.
257
+ *
258
+ * Middleware and `{ type: 'endpoint' }` routes run outside the request context but are handed
259
+ * Hono's `c` directly, so they use `c.header(…)`. That is also where a header belonging to the
260
+ * *page* rather than to one action goes — `Cache-Control`, `X-Robots-Tag` — since middleware runs
261
+ * before the render.
262
+ *
263
+ * @param name - Header name, case-insensitive.
264
+ * @param value - Header value.
265
+ * @param options - `{ append: true }` to add another value rather than replace.
266
+ * @throws If called while a page is rendering, where it could not reach the browser reliably.
267
+ *
268
+ * @example
269
+ * ```ts
270
+ * 'use server';
271
+ * export async function logout() {
272
+ * const ctx = getRequestContext();
273
+ * ctx.cookies.delete('session', { path: '/' });
274
+ * ctx.setHeader('clear-site-data', '"cache", "storage"');
275
+ * redirect('/');
276
+ * }
277
+ * ```
278
+ */
279
+ setHeader(name: string, value: string, options?: {
280
+ append?: boolean;
281
+ }): void;
282
+ /** @deprecated Not available on a page's context — use `redirect()` from `@rshono/core/server`. */
283
+ redirect(...args: unknown[]): never;
284
+ /** @deprecated Not available on a page's context — use `notFound()` from `@rshono/core/server`. */
285
+ notFound(...args: unknown[]): never;
286
+ /** @deprecated A page renders JSX. For a JSON response, use an `{ type: 'endpoint' }` route. */
287
+ json(...args: unknown[]): never;
288
+ /** @deprecated A page renders JSX. For a text response, use an `{ type: 'endpoint' }` route. */
289
+ text(...args: unknown[]): never;
290
+ /** @deprecated A page renders JSX, which the framework turns into HTML for you. */
291
+ html(...args: unknown[]): never;
292
+ /** @deprecated Not available on a page's context. To read the request body, use `ctx.req`. */
293
+ body(...args: unknown[]): never;
294
+ /** @deprecated A page's status is set by the framework — use `notFound()`, or an endpoint route. */
295
+ status(...args: unknown[]): never;
296
+ /** @deprecated Renamed — use `ctx.setHeader(name, value)`, which is valid from a `'use server'` action. */
297
+ header(...args: unknown[]): never;
154
298
  }
155
299
  /**
156
- * Returns the {@link Ctx} for the current request.
157
- *
158
- * This is the primary entry point for reading request data from a server
159
- * component or server action — the URL, cookies, params, env, and middleware
160
- * variables. The returned wrapper is memoised per request, so repeated calls in
161
- * the same request are cheap and return the same instance.
300
+ * Returns the {@link RequestContext} for the current request — the URL, cookies, params, env and
301
+ * middleware variables, read from a server component or a server action. Memoised per request, so
302
+ * repeated calls return the same instance.
162
303
  *
163
- * A **page** component is handed the very same object as its `ctx` prop, so this
164
- * import is for everywhere else: a nested server component, or a `'use server'`
165
- * action module — neither of which receives props from the framework.
304
+ * A **page** component is handed that same object as its `ctx` prop, so this import is for everywhere
305
+ * else: a nested server component, or a `'use server'` action module.
166
306
  *
167
- * @typeParam E - The app's Hono {@link Env}, to type {@link Ctx.var} and {@link Ctx.env}.
307
+ * @typeParam E - The app's Hono {@link Env}, to type {@link RequestContext.var} and {@link RequestContext.env}.
168
308
  * @throws If called at module load, where there is no ambient context to resolve.
169
309
  * @throws If called while prerendering a `render: 'static'` route, which has no
170
310
  * per-request context at build time — mark the route `render: 'dynamic'` instead.
@@ -172,15 +312,17 @@ export declare class Ctx<E extends Env = Env> {
172
312
  * @example
173
313
  * ```ts
174
314
  * 'use server';
175
- * import { getContext, redirect } from '@rshono/core/server';
315
+ * import { getRequestContext, redirect } from '@rshono/core/server';
176
316
  *
177
317
  * export async function login(form: FormData) {
178
- * getContext().cookies.set('session', String(form.get('email')), { httpOnly: true });
318
+ * getRequestContext().cookies.set('session', String(form.get('email')), { httpOnly: true });
179
319
  * redirect('/dashboard');
180
320
  * }
181
321
  * ```
322
+ *
323
+ * @see {@link https://www.rshono.com/docs/api#rshonocoreserver | Docs — `@rshono/core/server`}
182
324
  */
183
- export declare function getContext<E extends Env = Env>(): Ctx<E>;
325
+ export declare function getRequestContext<E extends Env = Env>(): RequestContext<E>;
184
326
  /**
185
327
  * Redirects the request to `location` by throwing a control signal that the
186
328
  * framework catches and turns into an HTTP redirect response.
@@ -195,7 +337,7 @@ export declare function getContext<E extends Env = Env>(): Ctx<E>;
195
337
  *
196
338
  * @example
197
339
  * ```ts
198
- * const session = getContext().cookies.get('session');
340
+ * const session = getRequestContext().cookies.get('session');
199
341
  * if (!session) redirect('/login');
200
342
  * // session is defined below this line
201
343
  * ```
@@ -209,9 +351,11 @@ export declare function redirect(location: string, status?: RedirectStatus): nev
209
351
  *
210
352
  * @example
211
353
  * ```tsx
212
- * const user = await db.user.find(getContext().params.id);
213
- * if (!user) notFound();
214
- * return <Profile user={user} />; // user is non-null here
354
+ * export default async function Page({ params }: PageProps<'/users/:id'>) {
355
+ * const user = await db.user.find(params.id);
356
+ * if (!user) notFound();
357
+ * return <Profile user={user} />; // user is non-null here
358
+ * }
215
359
  * ```
216
360
  */
217
361
  export declare function notFound(): never;
@@ -255,6 +399,8 @@ export type ServerErrorHandler = (error: unknown, context: ServerErrorContext) =
255
399
  * Sentry.captureException(error, { tags: { source }, extra: { url: request.url } });
256
400
  * });
257
401
  * ```
402
+ *
403
+ * @see {@link https://www.rshono.com/docs/hono#error-reporting | Docs — error reporting}
258
404
  */
259
405
  export declare function onServerError(handler: ServerErrorHandler): void;
260
406
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/runtime/context.ts"],"names":[],"mappings":"AACA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAEtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAkCzD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAE5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAM7D;AAaD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,GAAG,GAAG,CAmBzC;AAED;;;;GAIG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAExF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,GAAG,CAAC,CAAC,SAAS,GAAG,GAAG,GAAG;;IAKlC,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAExB;IAED;;;;;;;;;;OAUG;IACH,IAAI,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,CAEpB;IAED,oFAAoF;IACpF,IAAI,GAAG,IAAI,WAAW,CAErB;IAED;;;;;OAKG;IACH,IAAI,GAAG,IAAI,GAAG,CAEb;IAED,4DAA4D;IAC5D,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;;OAGG;IACH,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEnC;IAED;;;OAGG;IACH,IAAI,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAElC;IAED;;;;;OAKG;IACH,IAAI,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,CAKpB;IAED,4EAA4E;IAC5E,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAExC;IAED;;;;;;;;;;OAUG;IACH,OAAO;QACL,+DAA+D;QAC/D,GAAG,SAAS,MAAM,KAAG,MAAM,GAAG,SAAS;QACvC,wDAAwD;QACxD,GAAG,QAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;QAC/B,6GAA6G;QAC7G,GAAG,SAAS,MAAM,SAAS,MAAM,YAAY,aAAa,KAAG,IAAI;QACjE,gGAAgG;QAChG,MAAM,SAAS,MAAM,YAAY,aAAa,KAAG,IAAI;MAGrD;CACH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAqBxD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAE,cAAoB,GAAG,KAAK,CAE9E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,IAAI,KAAK,CAEhC;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;AAExE,0FAA0F;AAC1F,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,MAAM,EAAE,iBAAiB,CAAC;IAC1B,iEAAiE;IACjE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,8GAA8G;AAC9G,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAIvF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAE/D;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAkB,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAQtG"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/runtime/context.ts"],"names":[],"mappings":"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"}