@timber-js/app 0.2.0-alpha.210 → 0.2.0-alpha.212

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 (158) hide show
  1. package/agent-skill.md +10 -5
  2. package/dist/_chunks/{actions-Rjk4htmA.js → actions-CCdnVtWm.js} +8 -6
  3. package/dist/_chunks/actions-CCdnVtWm.js.map +1 -0
  4. package/dist/_chunks/{als-registry-DaxkVjt5.js → als-registry-BZqHCtq-.js} +2 -4
  5. package/dist/_chunks/als-registry-BZqHCtq-.js.map +1 -0
  6. package/dist/_chunks/{cache-api-DGdYfNJn.js → cache-api-LA3sBpUS.js} +5 -5
  7. package/dist/_chunks/{cache-api-DGdYfNJn.js.map → cache-api-LA3sBpUS.js.map} +1 -1
  8. package/dist/_chunks/{chains-BoO51joc.js → chains-BfoPFraI.js} +5 -146
  9. package/dist/_chunks/chains-BfoPFraI.js.map +1 -0
  10. package/dist/_chunks/classify-BT66U83D.js +147 -0
  11. package/dist/_chunks/classify-BT66U83D.js.map +1 -0
  12. package/dist/_chunks/{cli-check-ajNY3B2e.js → cli-check-BfQ54-UJ.js} +3 -3
  13. package/dist/_chunks/{cli-check-ajNY3B2e.js.map → cli-check-BfQ54-UJ.js.map} +1 -1
  14. package/dist/_chunks/{cli-schema-sync-D2eI8jEg.js → cli-schema-sync-czh2dsLs.js} +2 -2
  15. package/dist/_chunks/{cli-schema-sync-D2eI8jEg.js.map → cli-schema-sync-czh2dsLs.js.map} +1 -1
  16. package/dist/_chunks/client-dep-entries-CQwpb8dI.js +66 -0
  17. package/dist/_chunks/client-dep-entries-CQwpb8dI.js.map +1 -0
  18. package/dist/_chunks/{convention-lint-DLmhGsRS.js → convention-lint-BEVW4EID.js} +3 -3
  19. package/dist/_chunks/{convention-lint-DLmhGsRS.js.map → convention-lint-BEVW4EID.js.map} +1 -1
  20. package/dist/_chunks/{dev-server-v97rQH4b.js → dev-server-FKxptbnI.js} +2 -2
  21. package/dist/_chunks/{dev-server-v97rQH4b.js.map → dev-server-FKxptbnI.js.map} +1 -1
  22. package/dist/_chunks/{json-lossy-check-CVuRs2hG.js → json-lossy-check-C8zBY2uZ.js} +2 -2
  23. package/dist/_chunks/{json-lossy-check-CVuRs2hG.js.map → json-lossy-check-C8zBY2uZ.js.map} +1 -1
  24. package/dist/_chunks/{live-graph-9cSnn_h9.js → live-graph-C_4v-fHv.js} +4 -3
  25. package/dist/_chunks/{live-graph-9cSnn_h9.js.map → live-graph-C_4v-fHv.js.map} +1 -1
  26. package/dist/_chunks/{logger-BP0LN6vP.js → logger-CbLdcy-W.js} +2 -2
  27. package/dist/_chunks/{logger-BP0LN6vP.js.map → logger-CbLdcy-W.js.map} +1 -1
  28. package/dist/_chunks/{poison-scan-vGV7Re0B.js → poison-scan-C92liMAr.js} +2 -4
  29. package/dist/_chunks/poison-scan-C92liMAr.js.map +1 -0
  30. package/dist/_chunks/{scanner-DmqdxzbW.js → scanner-CQt12vE2.js} +2 -2
  31. package/dist/_chunks/{scanner-DmqdxzbW.js.map → scanner-CQt12vE2.js.map} +1 -1
  32. package/dist/_chunks/{sizeof-BM1409x2.js → sizeof-QPE5nd3u.js} +2 -2
  33. package/dist/_chunks/{sizeof-BM1409x2.js.map → sizeof-QPE5nd3u.js.map} +1 -1
  34. package/dist/_chunks/{walkers-Czu2jXFq.js → walkers-DAT4avhZ.js} +3 -3
  35. package/dist/_chunks/{walkers-Czu2jXFq.js.map → walkers-DAT4avhZ.js.map} +1 -1
  36. package/dist/adapters/cloudflare-kv-cache.js +1 -1
  37. package/dist/analyze/classify.d.ts +2 -0
  38. package/dist/analyze/classify.d.ts.map +1 -1
  39. package/dist/analyze/crawl-entry.js +3 -2
  40. package/dist/analyze/crawl-entry.js.map +1 -1
  41. package/dist/analyze/graph-command.js +2 -2
  42. package/dist/analyze/poison-scan.d.ts.map +1 -1
  43. package/dist/cache/index.js +2 -2
  44. package/dist/cache/stores/memory.js +1 -1
  45. package/dist/cdn/workers-cache-purge.js +1 -1
  46. package/dist/cli.js +3 -3
  47. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
  48. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  49. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  50. package/dist/client/form.d.ts +17 -64
  51. package/dist/client/form.d.ts.map +1 -1
  52. package/dist/client/index.d.ts +2 -2
  53. package/dist/client/index.d.ts.map +1 -1
  54. package/dist/client/index.js +23 -51
  55. package/dist/client/index.js.map +1 -1
  56. package/dist/client/internal.js +25 -25
  57. package/dist/client/internal.js.map +1 -1
  58. package/dist/client/navigation-api.d.ts +25 -63
  59. package/dist/client/navigation-api.d.ts.map +1 -1
  60. package/dist/client/router-lifecycle.d.ts +17 -11
  61. package/dist/client/router-lifecycle.d.ts.map +1 -1
  62. package/dist/client/router-pipeline.d.ts +0 -1
  63. package/dist/client/router-pipeline.d.ts.map +1 -1
  64. package/dist/client/router-types.d.ts +14 -45
  65. package/dist/client/router-types.d.ts.map +1 -1
  66. package/dist/client/router.d.ts.map +1 -1
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +44 -7
  69. package/dist/index.js.map +1 -1
  70. package/dist/plugins/client-dep-entries.d.ts +44 -0
  71. package/dist/plugins/client-dep-entries.d.ts.map +1 -0
  72. package/dist/plugins/content.d.ts.map +1 -1
  73. package/dist/plugins/entries.d.ts +6 -0
  74. package/dist/plugins/entries.d.ts.map +1 -1
  75. package/dist/plugins/shims.d.ts.map +1 -1
  76. package/dist/routing/index.js +2 -2
  77. package/dist/rsc-runtime/rsc.d.ts +1 -1
  78. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  79. package/dist/server/action-client.d.ts +9 -5
  80. package/dist/server/action-client.d.ts.map +1 -1
  81. package/dist/server/action-handler.d.ts +27 -8
  82. package/dist/server/action-handler.d.ts.map +1 -1
  83. package/dist/server/als-registry.d.ts +22 -2
  84. package/dist/server/als-registry.d.ts.map +1 -1
  85. package/dist/server/client-error-message.d.ts +12 -0
  86. package/dist/server/client-error-message.d.ts.map +1 -0
  87. package/dist/server/form-state-embed.d.ts +32 -0
  88. package/dist/server/form-state-embed.d.ts.map +1 -0
  89. package/dist/server/index.d.ts +0 -2
  90. package/dist/server/index.d.ts.map +1 -1
  91. package/dist/server/index.js +7 -40
  92. package/dist/server/index.js.map +1 -1
  93. package/dist/server/internal.js +10 -6
  94. package/dist/server/internal.js.map +1 -1
  95. package/dist/server/logger.d.ts +1 -0
  96. package/dist/server/logger.d.ts.map +1 -1
  97. package/dist/server/pipeline.d.ts +20 -6
  98. package/dist/server/pipeline.d.ts.map +1 -1
  99. package/dist/server/request-context.d.ts +27 -2
  100. package/dist/server/request-context.d.ts.map +1 -1
  101. package/dist/server/route-element-builder.d.ts.map +1 -1
  102. package/dist/server/rsc-entry/action-dispatcher.d.ts +6 -5
  103. package/dist/server/rsc-entry/action-dispatcher.d.ts.map +1 -1
  104. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  105. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  106. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  107. package/dist/server/ssr-bridge-types.d.ts +8 -0
  108. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  109. package/dist/server/ssr-entry.d.ts.map +1 -1
  110. package/dist/server/ssr-render.d.ts +3 -0
  111. package/dist/server/ssr-render.d.ts.map +1 -1
  112. package/docs/api/31-api-client.mdx +9 -3
  113. package/docs/learn/08-forms-and-actions.mdx +21 -28
  114. package/package.json +1 -1
  115. package/src/analyze/classify.ts +1 -1
  116. package/src/analyze/poison-scan.ts +1 -4
  117. package/src/client/browser-entry/action-dispatch.ts +74 -18
  118. package/src/client/browser-entry/hydrate.ts +18 -0
  119. package/src/client/browser-entry/router-init.ts +4 -18
  120. package/src/client/form.tsx +33 -98
  121. package/src/client/index.ts +2 -2
  122. package/src/client/navigation-api.ts +47 -173
  123. package/src/client/navigation-transition.ts +2 -2
  124. package/src/client/router-lifecycle.ts +40 -20
  125. package/src/client/router-pipeline.ts +3 -9
  126. package/src/client/router-types.ts +14 -49
  127. package/src/client/router.ts +38 -58
  128. package/src/index.ts +21 -2
  129. package/src/plugins/client-dep-entries.ts +78 -0
  130. package/src/plugins/content.ts +26 -1
  131. package/src/plugins/entries.ts +7 -0
  132. package/src/plugins/shims.ts +0 -2
  133. package/src/rsc-runtime/rsc.ts +3 -0
  134. package/src/rsc-runtime/vendor-types.d.ts +14 -0
  135. package/src/server/action-client.ts +18 -20
  136. package/src/server/action-handler.ts +133 -95
  137. package/src/server/als-registry.ts +23 -9
  138. package/src/server/client-error-message.ts +18 -0
  139. package/src/server/form-state-embed.ts +63 -0
  140. package/src/server/index.ts +0 -4
  141. package/src/server/logger.ts +6 -1
  142. package/src/server/pipeline.ts +27 -8
  143. package/src/server/request-context.ts +39 -2
  144. package/src/server/route-element-builder.ts +12 -1
  145. package/src/server/rsc-entry/action-dispatcher.ts +37 -34
  146. package/src/server/rsc-entry/error-renderer.ts +2 -1
  147. package/src/server/rsc-entry/rsc-stream.ts +20 -11
  148. package/src/server/rsc-entry/ssr-renderer.ts +14 -1
  149. package/src/server/ssr-bridge-types.ts +9 -0
  150. package/src/server/ssr-entry.ts +1 -0
  151. package/src/server/ssr-render.ts +5 -0
  152. package/dist/_chunks/actions-Rjk4htmA.js.map +0 -1
  153. package/dist/_chunks/als-registry-DaxkVjt5.js.map +0 -1
  154. package/dist/_chunks/chains-BoO51joc.js.map +0 -1
  155. package/dist/_chunks/poison-scan-vGV7Re0B.js.map +0 -1
  156. package/dist/server/form-flash.d.ts +0 -78
  157. package/dist/server/form-flash.d.ts.map +0 -1
  158. package/src/server/form-flash.ts +0 -89
@@ -110,6 +110,7 @@ export declare function logActionError(data: {
110
110
  method: string;
111
111
  path: string;
112
112
  error: unknown;
113
+ errorId?: string;
113
114
  }): void;
114
115
  /** Log unhandled error in route handler. Level: error. */
115
116
  export declare function logRouteError(data: {
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/server/logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/server/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAIlD,6FAA6F;AAC7F,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC1D;AAQD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAEpD;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,YAAY,CAExC;AAsBD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAC/D,IAAI,CAIN;AAED,4CAA4C;AAC5C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,IAAI,CAEP;AAED,0CAA0C;AAC1C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAE/E;AAED,+CAA+C;AAC/C,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,IAAI,CAEP;AAED,kDAAkD;AAClD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CAEP;AAED,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAG/F;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAG/F;AAED,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,CAGP;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,IAAI,CAEP;AAED,iDAAiD;AACjD,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAE5D;AAED,0DAA0D;AAC1D,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,CAGP;AAED,0DAA0D;AAC1D,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAG1F;AAED,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAEhE;AAED,sEAAsE;AACtE,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED,sDAAsD;AACtD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAEnE;AAED,6DAA6D;AAC7D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAEpF;AAED,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAQlF;AAED,oCAAoC;AACpC,wBAAgB,YAAY,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAE7D;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,GAAG,IAAI,CAO/F"}
@@ -20,6 +20,8 @@ import type { MiddlewareFn } from './middleware-runner.ts';
20
20
  import { DenySignal } from './primitives.ts';
21
21
  import type { ManifestSegmentNode } from './route-matcher.ts';
22
22
  import type { CsrfConfig } from './csrf.ts';
23
+ import type { ReactFormState } from 'react-dom/client';
24
+ import type { ActionErrorForRender } from './als-registry.ts';
23
25
  /**
24
26
  * Result of matching a canonical pathname against the route tree.
25
27
  *
@@ -201,17 +203,29 @@ export interface PipelineConfig {
201
203
  * from `req.url` (which re-encodes).
202
204
  *
203
205
  * The `reenter` parameter is the full pipeline function (including proxy,
204
- * ALS, tracing) for the no-JS validation rerender path — the synthetic
205
- * GET flows through the complete pipeline. Its `cookies` argument becomes
206
- * that request's parsed cookies (`runWithRequestContext`'s `cookies`
207
- * option), so the rerender reads the action's post-mutation state without
208
- * the pipeline needing the same `Request` object to reach it.
206
+ * ALS, tracing) for the no-JS action rerender path — the synthetic GET
207
+ * flows through the complete pipeline. Its `cookies` become that request's
208
+ * parsed cookies and its `formState` the action's form state for SSR
209
+ * (`runWithRequestContext`'s options), so the rerender reads both without
210
+ * the pipeline needing the same `Request` object to reach them.
209
211
  *
210
212
  * Moved into the pipeline (TIM-1213) so proxy.ts runs on action POSTs,
211
213
  * matching the design doc contract: "proxy.ts runs on every request,
212
214
  * no exclusions."
213
215
  */
214
- dispatchAction?: (req: Request, canonicalPath: string, reenter: (req: Request, cookies: Map<string, string>) => Promise<Response>) => Promise<Response | null>;
216
+ dispatchAction?: (req: Request, canonicalPath: string, reenter: (req: Request, reentry: PipelineReentry) => Promise<Response>) => Promise<Response | null>;
217
+ }
218
+ /**
219
+ * What the no-JS action rerender hands the pipeline when it re-enters it:
220
+ * the action's post-mutation cookies and, when its form used
221
+ * `useActionState`, the form state React decoded from the submission — or,
222
+ * when the action threw, the error to render in place of the page.
223
+ */
224
+ export interface PipelineReentry {
225
+ cookies: Map<string, string>;
226
+ formState?: ReactFormState;
227
+ /** The error a no-JS action threw, rendered where the page would be. */
228
+ actionError?: ActionErrorForRender;
215
229
  }
216
230
  /**
217
231
  * Create the request handler from a pipeline configuration.
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/server/pipeline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/server/pipeline.ts"],"names":[],"mappings":"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"}
@@ -14,9 +14,10 @@
14
14
  * and design/11-platform.md §"AsyncLocalStorage".
15
15
  */
16
16
  import type { CoercedParams } from '../shared/param-value.ts';
17
- import { requestContextAls } from './als-registry.ts';
17
+ import { requestContextAls, type ActionErrorForRender } from './als-registry.ts';
18
18
  import { type SlotParamsRecord } from '../shared/slot-params.ts';
19
19
  import { type ReactCacheScope } from './react-cache-scope.ts';
20
+ import type { ReactFormState } from 'react-dom/client';
20
21
  export { requestContextAls };
21
22
  /**
22
23
  * Returns a read-only view of the current request's headers.
@@ -154,6 +155,16 @@ export interface RequestContextOptions {
154
155
  * (TIM-868).
155
156
  */
156
157
  cookies?: Map<string, string>;
158
+ /**
159
+ * The form state of the no-JS action this render answers. Only the
160
+ * action dispatcher's re-entry passes it; see `RequestContextStore.formState`.
161
+ */
162
+ formState?: ReactFormState;
163
+ /**
164
+ * The error of the no-JS action this render answers. Only the action
165
+ * dispatcher's re-entry passes it; see `RequestContextStore.actionError`.
166
+ */
167
+ actionError?: ActionErrorForRender;
157
168
  }
158
169
  /**
159
170
  * Run a callback within a request context. Used by the pipeline to establish
@@ -171,7 +182,7 @@ export interface RequestContextOptions {
171
182
  * @param req - The incoming Request object.
172
183
  * @param fn - The function to run within the request context.
173
184
  */
174
- export declare function runWithRequestContext<T>(req: Request, fn: () => T, { reactCacheScope, cookies }?: RequestContextOptions): T;
185
+ export declare function runWithRequestContext<T>(req: Request, fn: () => T, { reactCacheScope, cookies, formState, actionError }?: RequestContextOptions): T;
175
186
  /**
176
187
  * Enable cookie mutation for the current context. Called by the framework
177
188
  * when entering middleware.ts, server actions, or route.ts handlers.
@@ -199,4 +210,18 @@ export declare function markResponseFlushed(): void;
199
210
  * See design/07-routing.md §"Request Header Injection"
200
211
  */
201
212
  export declare function applyRequestHeaderOverlay(overlay: Headers): void;
213
+ /**
214
+ * The form state of the no-JS action this render answers, or `null`. Read by
215
+ * the SSR renderer only (`rsc-entry/ssr-renderer.ts`), which passes it to
216
+ * Fizz and embeds it for `hydrateRoot`. Framework-internal: not exported
217
+ * from `@timber-js/app/server`.
218
+ */
219
+ export declare function getFormStateForSsr(): ReactFormState | null;
220
+ /**
221
+ * The error of the no-JS action this render answers, or `null`. Read by the
222
+ * route element builder, which renders it in place of the page, and by the
223
+ * Flight `onError`, which gives it the ID the action logged it with.
224
+ * Framework-internal: not exported from `@timber-js/app/server`.
225
+ */
226
+ export declare function getActionErrorForRender(): ActionErrorForRender | null;
202
227
  //# sourceMappingURL=request-context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/server/request-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAA4B,MAAM,mBAAmB,CAAC;AAGhF,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGtF,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAI7B;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,eAAe,CAU5C;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG1D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,eAAe,CAUjD;AAaD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,aAAa,CA2CpE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAM5D;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAK9E;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,UAAU,EAAE,aAAa,EACzB,EAAE,EAAE,MAAM,CAAC,GACV,CAAC,CAcH;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,IAAI,aAAa,CAEzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,GAAG,SAAS,CAIrE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAI/D;AAkBD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAG/C;AAID;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,OAAO,EACP,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,MAAM,CAAC,QAAQ,CACnF,CAAC;AAIF,6CAA6C;AAC7C,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,GAAG,EAAE,OAAO,EACZ,EAAE,EAAE,MAAM,CAAC,EACX,EAAE,eAAe,EAAE,OAAO,EAAE,GAAE,qBAA0B,GACvD,CAAC,CAyBH;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAK9D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAK1C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmBhE"}
1
+ {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/server/request-context.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"route-element-builder.d.ts","sourceRoot":"","sources":["../../src/server/route-element-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAQ9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAMhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAQ5D;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,GAChB,MAAM,EAAE,CAGV;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAID,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;IAC3C,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAED,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,EAAE,cAAc,CAAC;IACxB,wDAAwD;IACxD,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,qCAAqC;IACrC,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,4DAA4D;IAC5D,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;OAIG;IACH,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,EAAE,CAAC;CACjC;AA2DD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,YAAY,CAAC,EAAE,mBAAmB,EAClC,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,EACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3C,OAAO,CAAC,kBAAkB,CAAC,CA6Z7B"}
1
+ {"version":3,"file":"route-element-builder.d.ts","sourceRoot":"","sources":["../../src/server/route-element-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAQ9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAMhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAS5D;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,UAAU,GAChB,MAAM,EAAE,CAGV;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAID,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;IAC3C,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAED,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,EAAE,cAAc,CAAC;IACxB,wDAAwD;IACxD,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,qCAAqC;IACrC,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,4DAA4D;IAC5D,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;OAIG;IACH,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,EAAE,CAAC;CACjC;AA2DD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,YAAY,CAAC,EAAE,mBAAmB,EAClC,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,EACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3C,OAAO,CAAC,kBAAkB,CAAC,CAua7B"}
@@ -8,7 +8,8 @@
8
8
  * `createPipeline` calls it after proxy.ts runs (TIM-1213), so proxy.ts
9
9
  * sees action POSTs — "proxy.ts runs on every request, no exclusions." It
10
10
  * encapsulates action detection, the route-type check, action handler
11
- * dispatch, and the no-JS validation rerender path.
11
+ * dispatch, and the answer to a no-JS action that did not redirect: the
12
+ * page rerendered with React's form state, or the error page.
12
13
  *
13
14
  * The CSRF gate is not here: it runs in `createPipeline` before proxy.ts
14
15
  * (`csrfGate` in pipeline-helpers.ts). The action handler repeats the
@@ -20,7 +21,7 @@
20
21
  */
21
22
  import type { BodyLimitsConfig } from '../body-limits.ts';
22
23
  import type { CsrfConfig } from '../csrf.ts';
23
- import type { RouteMatcher } from '../pipeline.ts';
24
+ import type { PipelineReentry, RouteMatcher } from '../pipeline.ts';
24
25
  import type { SensitiveFieldsOption } from '../sensitive-fields.ts';
25
26
  import type { RevalidateRenderer } from '../actions.ts';
26
27
  /**
@@ -57,11 +58,11 @@ export interface ActionDispatcherDeps {
57
58
  *
58
59
  * Called after proxy.ts runs (inside the pipeline) for every request.
59
60
  * Checks if the request is a server action POST, handles the route-type
60
- * check (TIM-870), dispatches to the action handler, and handles the
61
- * no-JS validation rerender path.
61
+ * check (TIM-870), dispatches to the action handler, and answers a no-JS
62
+ * action that did not redirect.
62
63
  *
63
64
  * Returns `Response` if the request was handled as an action, `null` to
64
65
  * fall through to normal routing.
65
66
  */
66
- export declare function buildActionDispatcher(deps: ActionDispatcherDeps): (req: Request, canonicalPath: string, reenter: (req: Request, cookies: Map<string, string>) => Promise<Response>) => Promise<Response | null>;
67
+ export declare function buildActionDispatcher(deps: ActionDispatcherDeps): (req: Request, canonicalPath: string, reenter: (req: Request, reentry: PipelineReentry) => Promise<Response>) => Promise<Response | null>;
67
68
  //# sourceMappingURL=action-dispatcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"action-dispatcher.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/action-dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAIxD;;;;;;;;GAQG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,kBAAkB,CAAC;AAE7E,yEAAyE;AACzE,MAAM,WAAW,oBAAoB;IACnC,6EAA6E;IAC7E,UAAU,EAAE,UAAU,CAAC;IACvB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACxC,oEAAoE;IACpE,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC,8DAA8D;IAC9D,uBAAuB,EAAE,yBAAyB,CAAC;IACnD;;;;;;OAMG;IACH,UAAU,EAAE,YAAY,CAAC;CAC1B;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,oBAAoB,GACzB,CACD,GAAG,EAAE,OAAO,EACZ,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,KACvE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA0D5B"}
1
+ {"version":3,"file":"action-dispatcher.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/action-dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAIxD;;;;;;;;GAQG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,kBAAkB,CAAC;AAE7E,yEAAyE;AACzE,MAAM,WAAW,oBAAoB;IACnC,6EAA6E;IAC7E,UAAU,EAAE,UAAU,CAAC;IACvB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACxC,oEAAoE;IACpE,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC,8DAA8D;IAC9D,uBAAuB,EAAE,yBAAyB,CAAC;IACnD;;;;;;OAMG;IACH,UAAU,EAAE,YAAY,CAAC;CAC1B;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,oBAAoB,GACzB,CACD,GAAG,EAAE,OAAO,EACZ,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,QAAQ,CAAC,KACnE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA8D5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"error-renderer.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/error-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAIjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAGlE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAcvD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AA+GD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,gBAAgB,EAAE,WAAW,EAAE,EAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,eAAe,EAAE,qBAAqB,EACtC,WAAW,CAAC,EAAE,eAAe,EAC7B,gBAAgB,SAAW,GAC1B,OAAO,CAAC,QAAQ,CAAC,CA6DnB"}
1
+ {"version":3,"file":"error-renderer.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/error-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAIjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAGlE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAevD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AA+GD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,gBAAgB,EAAE,WAAW,EAAE,EAC/B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,OAAO,EACxB,eAAe,EAAE,qBAAqB,EACtC,WAAW,CAAC,EAAE,eAAe,EAC7B,gBAAgB,SAAW,GAC1B,OAAO,CAAC,QAAQ,CAAC,CA6DnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"rsc-stream.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/rsc-stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAKnE,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAM3E,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAI/E,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACtC,OAAO,EAAE,aAAa,CAAC;CACxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,OAAO,EACZ,aAAa,CAAC,EAAE,aAAa,EAAE,GAC9B,eAAe,CAgHjB"}
1
+ {"version":3,"file":"rsc-stream.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/rsc-stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAKnE,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAQ3E,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAG/E,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACtC,OAAO,EAAE,aAAa,CAAC;CACxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,OAAO,EACZ,aAAa,CAAC,EAAE,aAAa,EAAE,GAC9B,eAAe,CAiHjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-renderer.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/ssr-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAMlE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAOzD,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA8BzD;;;;;;;;GAQG;AACH,eAAO,MAAM,gCAAgC,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAiB,CAAC;AAEhF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iCAAiC,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAqB,CAAC;AAEtF,UAAU,gBAAgB;IACxB,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACtC,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,KAAK,EAAE,UAAU,CAAC;IAClB,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,qBAAqB,CAAC;IACvC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,YAAY,CAAC,EAAE,aAAa,EAAE,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2QjF"}
1
+ {"version":3,"file":"ssr-renderer.d.ts","sourceRoot":"","sources":["../../../src/server/rsc-entry/ssr-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAMlE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AASzD,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA8BzD;;;;;;;;GAQG;AACH,eAAO,MAAM,gCAAgC,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAiB,CAAC;AAEhF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iCAAiC,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAqB,CAAC;AAEtF,UAAU,gBAAgB;IACxB,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACtC,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,KAAK,EAAE,UAAU,CAAC;IAClB,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,qBAAqB,CAAC;IACvC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,YAAY,CAAC,EAAE,aAAa,EAAE,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAsRjF"}
@@ -49,6 +49,7 @@
49
49
  * See `design/02-rendering-pipeline.md` §"RSC → SSR → Client Hydration"
50
50
  * and `CLAUDE.md` §"RSC and SSR Are Separate Vite Environments".
51
51
  */
52
+ import type { ReactFormState } from 'react-dom/client';
52
53
  /**
53
54
  * Navigation context passed from the RSC environment to SSR.
54
55
  *
@@ -102,6 +103,13 @@ export interface NavContext {
102
103
  /** Request cookies as name→value pairs. Used by useCookie() during SSR
103
104
  * to return correct cookie values before hydration. */
104
105
  cookies?: Map<string, string>;
106
+ /**
107
+ * The form state of the no-JS action this page answers (React's
108
+ * `decodeFormState`), passed to Fizz so the `useActionState` hook that
109
+ * submitted renders with the action's result. Absent on every other
110
+ * render. See design/08-forms-and-actions.md §"No-JS Result Round-Trip".
111
+ */
112
+ formState?: ReactFormState;
105
113
  /**
106
114
  * Lazy thunk that produces the `<script>self.__timber_segments=…</script>`
107
115
  * tag. Invoked by the SSR entry AFTER `renderSsrNodeStream` /
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-bridge-types.d.ts","sourceRoot":"","sources":["../../src/server/ssr-bridge-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;OAUG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,eAAe,EAAE,OAAO,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,sBAAsB,EAAE,MAAM,CAAC;IAC/B;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,SAAS,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACvC;;;0DAGsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;iFAE6E;IAC7E,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;4DACwD;IACxD,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B;;;;;;;;;;;;;;;;;OAiBG;IACH,oBAAoB,CAAC,EAAE,MAAM,MAAM,CAAC;IAEpC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,UAAU,CAAC;IACpB;;;;;;;;;;;;;;;;OAgBG;IACH,oBAAoB,EAAE,OAAO,CAAC;CAC/B"}
1
+ {"version":3,"file":"ssr-bridge-types.d.ts","sourceRoot":"","sources":["../../src/server/ssr-bridge-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;OAUG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,eAAe,EAAE,OAAO,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,sBAAsB,EAAE,MAAM,CAAC;IAC/B;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,SAAS,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACvC;;;0DAGsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;iFAE6E;IAC7E,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;4DACwD;IACxD,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B;;;;;;;;;;;;;;;;;OAiBG;IACH,oBAAoB,CAAC,EAAE,MAAM,MAAM,CAAC;IAEpC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,WAAW,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,UAAU,CAAC;IACpB;;;;;;;;;;;;;;;;OAgBG;IACH,oBAAoB,EAAE,OAAO,CAAC;CAC/B"}
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-entry.d.ts","sourceRoot":"","sources":["../../src/server/ssr-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA+BH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAiDzE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EACrC,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,eAAe,CAAC,CA2L1B;eAEc,SAAS"}
1
+ {"version":3,"file":"ssr-entry.d.ts","sourceRoot":"","sources":["../../src/server/ssr-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA+BH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAiDzE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EACrC,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,eAAe,CAAC,CA4L1B;eAEc,SAAS"}
@@ -20,11 +20,14 @@
20
20
  * 18-build-system.md §"Entry Files"
21
21
  */
22
22
  import type { ReactNode } from 'react';
23
+ import type { ReactFormState } from 'react-dom/client';
23
24
  /** Options shared by both SSR render paths (Node streams and Web Streams). */
24
25
  export interface SsrStreamOptions {
25
26
  bootstrapScriptContent?: string;
26
27
  /** Request CSP nonce — stamped by Fizz on the bootstrap and runtime scripts. */
27
28
  nonce?: string;
29
+ /** A no-JS action's form state, for the `useActionState` hook that submitted. */
30
+ formState?: ReactFormState;
28
31
  deferSuspenseFor?: number;
29
32
  signal?: AbortSignal;
30
33
  renderTimeoutMs?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-render.d.ts","sourceRoot":"","sources":["../../src/server/ssr-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAkGvC,8EAA8E;AAC9E,MAAM,WAAW,gBAAgB;IAC/B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,WAAW,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CACtD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,SAAS,EAClB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAErC;AAED,wEAAwE;AACxE,eAAO,MAAM,cAAc,SAAkB,CAAC;AAU9C;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,SAAS,EAClB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,OAAO,aAAa,EAAE,QAAQ,CAAC,CAsGzC;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,OAAO,aAAa,EAAE,QAAQ,GACvC,cAAc,CAAC,UAAU,CAAC,CAE5B;AAqGD;;;;;;;;;;;;GAYG;AACH,2CAA2C;AAC3C,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,MAAM,CAAC,EAAE,WAAW,EACpB,KAAK,CAAC,EAAE,MAAM,GACb,cAAc,CAAC,UAAU,CAAC,CA2B5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,cAAc,CAAC,UAAU,CAAC,EACtC,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,OAAO,GACvB,QAAQ,CAOV"}
1
+ {"version":3,"file":"ssr-render.d.ts","sourceRoot":"","sources":["../../src/server/ssr-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiGvD,8EAA8E;AAC9E,MAAM,WAAW,gBAAgB;IAC/B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,WAAW,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CACtD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,SAAS,EAClB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAErC;AAED,wEAAwE;AACxE,eAAO,MAAM,cAAc,SAAkB,CAAC;AAU9C;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,SAAS,EAClB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,OAAO,aAAa,EAAE,QAAQ,CAAC,CAuGzC;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,OAAO,aAAa,EAAE,QAAQ,GACvC,cAAc,CAAC,UAAU,CAAC,CAE5B;AAsGD;;;;;;;;;;;;GAYG;AACH,2CAA2C;AAC3C,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,MAAM,CAAC,EAAE,WAAW,EACpB,KAAK,CAAC,EAAE,MAAM,GACb,cAAc,CAAC,UAAU,CAAC,CA2B5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,cAAc,CAAC,UAAU,CAAC,EACtC,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,OAAO,GACvB,QAAQ,CAOV"}
@@ -123,12 +123,18 @@ const params = useSegmentParams(); // Partial<AllSegmentParams>
123
123
 
124
124
  ## Form Hooks
125
125
 
126
- ### `useActionState(action, initialState)`
126
+ Forms use React's own `useActionState`, imported from `react`. An action built with `createActionClient` passes to it directly: `result` is typed from the action, and the dispatch accepts the submitted `FormData` or the schema's input.
127
127
 
128
- Typed wrapper around React 19's `useActionState`. Returns `[result, formAction, isPending, errors]` — the 4th element auto-derives field and form-level errors from the result.
128
+ ### `parseFormErrors(result)`
129
+
130
+ Reads the errors out of an action result. `_root` validation errors are form-level; every other key is a field.
129
131
 
130
132
  ```tsx
131
- const [result, action, isPending, errors] = useActionState(createTodo, flash);
133
+ import { useActionState } from 'react';
134
+ import { parseFormErrors } from '@timber-js/app/client';
135
+
136
+ const [result, action, isPending] = useActionState(createTodo, null);
137
+ const errors = parseFormErrors(result);
132
138
 
133
139
  errors.hasErrors; // boolean
134
140
  errors.fieldErrors; // Record<string, string[]>
@@ -51,11 +51,13 @@ The `.schema()` method accepts any Standard Schema-compatible validator — Zod,
51
51
  ```tsx title="app/todos/todo-form.tsx"
52
52
  'use client';
53
53
 
54
- import { useActionState } from '@timber-js/app/client';
54
+ import { useActionState } from 'react';
55
+ import { parseFormErrors } from '@timber-js/app/client';
55
56
  import { createTodo } from './actions';
56
57
 
57
58
  export default function TodoForm() {
58
- const [state, action, pending, errors] = useActionState(createTodo, null);
59
+ const [state, action, pending] = useActionState(createTodo, null);
60
+ const errors = parseFormErrors(state);
59
61
 
60
62
  return (
61
63
  <form action={action}>
@@ -76,14 +78,15 @@ export default function TodoForm() {
76
78
  }
77
79
  ```
78
80
 
79
- Without JS, this submits as a standard form POST. With JS, `useActionState` handles pending state and error display.
81
+ `useActionState` is React's own hook. An action built with `createActionClient` passes to it directly, and `state` is typed from the action's result. Without JS, this submits as a standard form POST. With JS, `useActionState` handles pending state and error display.
80
82
 
81
83
  ### Form Errors
82
84
 
83
- `useActionState` from `@timber-js/app/client` returns a 4-tuple where the 4th element is auto-derived form errors:
85
+ `parseFormErrors` from `@timber-js/app/client` reads the errors out of the result:
84
86
 
85
87
  ```tsx
86
- const [state, action, pending, errors] = useActionState(myAction, null);
88
+ const [state, action, pending] = useActionState(myAction, null);
89
+ const errors = parseFormErrors(state);
87
90
 
88
91
  errors.fieldErrors; // Record<string, string[]>
89
92
  errors.formErrors; // string[] (form-level errors)
@@ -102,37 +105,25 @@ errors.getFieldError('title'); // string | null (first error for field)
102
105
 
103
106
  ## Forms Without JavaScript
104
107
 
105
- When JavaScript is disabled and a server action returns validation errors, timber re-renders the page instead of redirecting. The errors and submitted values are available via `getFormFlash()`:
106
-
107
- ```tsx title="app/todos/page.tsx"
108
- import { getFormFlash } from '@timber-js/app/server';
109
- import { TodoForm } from './todo-form';
110
-
111
- export default async function TodosPage() {
112
- const flash = getFormFlash();
113
- return <TodoForm flash={flash} />;
114
- }
115
- ```
108
+ The same form works with JavaScript disabled, with no extra code. When a no-JS submission's action returns instead of redirecting, timber renders the page again and React hands the result to the `useActionState` hook that submitted it. `state` holds the result on both paths, so errors and repopulated fields render the same way:
116
109
 
117
110
  ```tsx title="app/todos/todo-form.tsx"
118
111
  'use client';
119
112
 
120
- import { useActionState } from '@timber-js/app/client';
113
+ import { useActionState } from 'react';
114
+ import { parseFormErrors } from '@timber-js/app/client';
121
115
  import { createTodo } from './actions';
122
- import type { FormFlashData } from '@timber-js/app/server';
123
116
 
124
- export function TodoForm({ flash }: { flash?: FormFlashData | null }) {
125
- const [state, action, pending, errors] = useActionState(createTodo, null);
126
-
127
- const fieldError = (field: string) =>
128
- errors.getFieldError(field) ?? flash?.validationErrors?.[field]?.[0];
129
- const defaultValue = (field: string) =>
130
- (flash?.submittedValues?.[field] as string) ?? '';
117
+ export function TodoForm() {
118
+ const [state, action, pending] = useActionState(createTodo, null);
119
+ const errors = parseFormErrors(state);
131
120
 
132
121
  return (
133
122
  <form action={action}>
134
- <input name="title" defaultValue={defaultValue('title')} />
135
- {fieldError('title') && <p className="text-red-600">{fieldError('title')}</p>}
123
+ <input name="title" defaultValue={(state?.submittedValues?.title as string) ?? ''} />
124
+ {errors.getFieldError('title') && (
125
+ <p className="text-red-600">{errors.getFieldError('title')}</p>
126
+ )}
136
127
  <button type="submit" disabled={pending}>
137
128
  {pending ? 'Adding...' : 'Add Todo'}
138
129
  </button>
@@ -141,6 +132,8 @@ export function TodoForm({ flash }: { flash?: FormFlashData | null }) {
141
132
  }
142
133
  ```
143
134
 
144
- Flash data is server-side only — stored in AsyncLocalStorage for the duration of the re-render. Sensitive fields (password, apiKey, cvv, etc.) are automatically stripped from `submittedValues`.
135
+ The result goes only to the hook that submitted, so two forms on one page never see each other's results. Sensitive fields (password, apiKey, cvv, etc.) are automatically stripped from `submittedValues`.
136
+
137
+ A form that doesn't use `useActionState` gets no result back, just as with JavaScript, where React discards a plain `<form action>`'s return value. Such an action should `redirect()` to a page that shows the new state (post-redirect-get). An action that throws renders the nearest `error.tsx`: with JavaScript the action rejects to the nearest error boundary, and without it the page answers from the same `error.tsx` with a 500; return errors from `createActionClient` actions instead.
145
138
 
146
139
  For advanced topics — coercion helpers, `parseFormData`, sensitive field stripping configuration, and the full end-to-end example — see [Advanced Forms](/docs/advanced-forms).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timber-js/app",
3
- "version": "0.2.0-alpha.210",
3
+ "version": "0.2.0-alpha.212",
4
4
  "description": "Vite-native React framework built for Servers and Serverless Platforms — correct HTTP semantics, real status codes, pages that work without JavaScript",
5
5
  "keywords": [
6
6
  "cloudflare-workers",
@@ -105,7 +105,7 @@ export interface ModuleClassification {
105
105
  }
106
106
 
107
107
  /** File extensions eligible for directive detection. */
108
- const PARSEABLE_EXTENSIONS = /\.(?:ts|tsx|js|jsx|mjs|cjs|mts|cts)$/;
108
+ export const PARSEABLE_EXTENSIONS = /\.(?:ts|tsx|js|jsx|mjs|cjs|mts|cts)$/;
109
109
 
110
110
  /**
111
111
  * Parse language for a source file, from its extension. Never force
@@ -19,7 +19,7 @@
19
19
 
20
20
  import { parseAst } from 'vite';
21
21
  import { EXPLICIT_MARKERS, INFERRED_RULES } from './poison-rules.ts';
22
- import { langForFile, type ModuleKind } from './classify.ts';
22
+ import { langForFile, PARSEABLE_EXTENSIONS, type ModuleKind } from './classify.ts';
23
23
 
24
24
  /** One poisoning finding on a module, in the JSON-contract shape. */
25
25
  export interface Poisoning {
@@ -33,9 +33,6 @@ export interface Poisoning {
33
33
  description: string;
34
34
  }
35
35
 
36
- /** File extensions the specifier scan can parse. */
37
- const PARSEABLE_EXTENSIONS = /\.(?:ts|tsx|js|jsx|mjs|cjs|mts|cts)$/;
38
-
39
36
  /**
40
37
  * A NON-EMPTY specifier list where every entry is type-only. Empty or
41
38
  * absent lists return false — a bare `import 'pkg'` is a side-effect
@@ -25,20 +25,6 @@ import { RSC_CONTENT_TYPE } from '../../shared/rsc-media-type.ts';
25
25
  import { CSRF_REJECT_HEADER, CSRF_REJECT_VALUE } from '../../shared/csrf-reject.ts';
26
26
  import { createActionQueue } from './action-queue.ts';
27
27
 
28
- /**
29
- * Wait for a navigation or refresh to both settle (promise resolved) AND
30
- * commit (pushState / the navigation's commit thunk ran). The queue must
31
- * not release the next action until the URL is correct in the address bar
32
- * — same rule `<Link>` uses for `isPending` (design/19 §Per-Link Pending
33
- * State). `onCommit` fires exactly once: on commit, supersession, or
34
- * failure, so nothing awaiting this can hang (codex on #1125).
35
- */
36
- function settledAndCommitted(start: (onCommit: () => void) => Promise<void>): Promise<void> {
37
- let commitResolve!: () => void;
38
- const committed = new Promise<void>((r) => (commitResolve = r));
39
- return Promise.all([start(commitResolve).catch(() => {}), committed]).then(() => {});
40
- }
41
-
42
28
  export function setupServerActions(): void {
43
29
  const queue = createActionQueue({
44
30
  refreshWhenIdle(): void {
@@ -60,8 +46,30 @@ export function setupServerActions(): void {
60
46
  },
61
47
  });
62
48
 
49
+ // An action that redirects settles — ending `useActionState`'s pending
50
+ // state — a full round trip before the destination is on screen, and the
51
+ // page that submitted stays mounted until then with its button enabled
52
+ // again. A second submit would run the mutation again (TIM-1568). So the
53
+ // departing page may not dispatch: `departing` is set from the redirect
54
+ // response until the router is next idle, and a call made
55
+ // meanwhile is never sent. It resolves at once with `undefined` — what the
56
+ // redirecting action itself returned. It must settle: React entangles every
57
+ // transition started while an action is pending, so one left pending would
58
+ // hold the redirect's own commit forever. `pageGen` names
59
+ // the page a call was made on, so one queued behind the redirecting
60
+ // action is dropped too. The check is here rather than in the DOM
61
+ // (`inert`) because it covers every way a call is made: a click inside a
62
+ // modal dialog or a shadow root, `requestSubmit()` from a keyboard
63
+ // shortcut, an effect.
64
+ let departing = false;
65
+ let pageGen = 0;
66
+
63
67
  setServerCallback((id: string, args: unknown[]) => {
68
+ if (departing) return Promise.resolve(undefined);
69
+ const calledOn = pageGen;
64
70
  return queue.run(async ({ hold }) => {
71
+ if (calledOn !== pageGen) return undefined;
72
+
65
73
  // encodeReply inside the queue — preserves call order when two
66
74
  // calls' args serialize in different numbers of microtasks.
67
75
  const body = await encodeReply(args);
@@ -75,6 +83,9 @@ export function setupServerActions(): void {
75
83
  let hasRevalidation = false;
76
84
  let hasRedirect = false;
77
85
  let invalidated = false;
86
+ // Set once the server answered the action itself — past the version
87
+ // skew and CSRF rejections, which run nothing.
88
+ let answered = false;
78
89
 
79
90
  const actionHeaders: Record<string, string> = {
80
91
  'Accept': RSC_CONTENT_TYPE,
@@ -104,10 +115,26 @@ export function setupServerActions(): void {
104
115
  hasRevalidation = res.headers.get('X-Timber-Revalidation') === '1';
105
116
  hasRedirect = res.headers.get('X-Timber-Redirect') != null;
106
117
  invalidated = res.headers.get('X-Timber-Invalidated') === '1';
118
+ answered = true;
107
119
  return res;
108
120
  });
109
121
 
110
- const decoded = await createFromFetch(response);
122
+ let decoded: unknown;
123
+ try {
124
+ decoded = await createFromFetch(response);
125
+ } catch (error) {
126
+ // A raw server function that throws arrives as a rejected root
127
+ // (TIM-1570). It may have mutated before it threw, so no payload
128
+ // cached before it may be reused, nor the mounted shared layouts on
129
+ // the next navigation. No refresh: the rejection renders the nearest
130
+ // error boundary, and a refresh would hand that boundary new
131
+ // children, which resets it and hides the error (error-boundary.tsx).
132
+ if (answered && router) {
133
+ router.suppressSegmentReuse();
134
+ router.evictStaleCaches();
135
+ }
136
+ throw error;
137
+ }
111
138
 
112
139
  // The mutation happened server-side, and the next thing on screen is
113
140
  // not a full render of the current page: revalidatePath named only
@@ -140,10 +167,12 @@ export function setupServerActions(): void {
140
167
  // action scope settles — awaiting the commit inline would deadlock:
141
168
  // React entangles the commit lane with the action scope, so the
142
169
  // commit waits on the action while the action waits on the commit.
143
- // The navigate is fire-and-forget: unlike revalidation (where the
144
- // next action must capture the refreshed epoch), a redirect leaves
145
- // the page entirely — no subsequent action runs on this URL.
170
+ //
171
+ // Set before returning, so React never sees the action settle while
172
+ // the departing page can still dispatch (see `departing`).
146
173
  if (hasRedirect) {
174
+ departing = true;
175
+ pageGen += 1;
147
176
  const wrapper = decoded as { _redirect: string; _status: number };
148
177
  const isExternal =
149
178
  wrapper._redirect.startsWith('https://') || wrapper._redirect.startsWith('http://');
@@ -156,7 +185,34 @@ export function setupServerActions(): void {
156
185
  }
157
186
  try {
158
187
  const r = getRouter();
188
+ // The redirect's own navigation takes the next sequence number.
189
+ // A tree handed to React before it — a refresh of this very page
190
+ // still suspended — can commit afterwards, and must not release
191
+ // the latch: it is the departing page again (codex on #1211).
192
+ const redirectSeq = r.epoch().seq + 1;
159
193
  void r.navigate(wrapper._redirect);
194
+ // Released once the departing page can no longer be on screen:
195
+ // when any navigation's tree commits (a streamed destination
196
+ // commits its shell before its stream finishes, and is live from
197
+ // then), or when the router is idle with nothing committed (every
198
+ // navigation was abandoned; the user stays and may act again).
199
+ // Not on the redirect navigation's own outcome: a navigation the
200
+ // user starts meanwhile supersedes it at once, but the departing
201
+ // page stays until that successor commits (codex on #1211).
202
+ const stops: (() => void)[] = [];
203
+ const arrive = (): void => {
204
+ departing = false;
205
+ for (const stop of stops) stop();
206
+ };
207
+ stops.push(
208
+ r.onTreeCommit((seq) => {
209
+ if (seq >= redirectSeq) arrive();
210
+ }),
211
+ r.onIdle(arrive)
212
+ );
213
+ // A navigation that failed before taking the router never makes
214
+ // it busy, so no idle transition would come.
215
+ if (r.epoch().idle) arrive();
160
216
  } catch (e) {
161
217
  console.debug(
162
218
  '[timber] action redirect: router not ready, using full navigation',