@timber-js/app 0.2.0-alpha.211 → 0.2.0-alpha.213

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 (183) hide show
  1. package/agent-skill.md +10 -5
  2. package/dist/_chunks/{actions-Rjk4htmA.js → actions-CEootpB1.js} +49 -12
  3. package/dist/_chunks/actions-CEootpB1.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-DGX9zmg9.js → chains-BfoPFraI.js} +2 -2
  9. package/dist/_chunks/{chains-DGX9zmg9.js.map → chains-BfoPFraI.js.map} +1 -1
  10. package/dist/_chunks/{classify-QwG5rxKI.js → classify-BT66U83D.js} +2 -2
  11. package/dist/_chunks/{classify-QwG5rxKI.js.map → classify-BT66U83D.js.map} +1 -1
  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-2HCF09no.js → client-dep-entries-CQwpb8dI.js} +2 -2
  17. package/dist/_chunks/{client-dep-entries-2HCF09no.js.map → client-dep-entries-CQwpb8dI.js.map} +1 -1
  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-TFpEwm3H.js → dev-server-FKxptbnI.js} +2 -2
  21. package/dist/_chunks/{dev-server-TFpEwm3H.js.map → dev-server-FKxptbnI.js.map} +1 -1
  22. package/dist/_chunks/{error-boundary-DsNScGRM.js → error-boundary-9g_Lb2na.js} +3 -3
  23. package/dist/_chunks/{error-boundary-DsNScGRM.js.map → error-boundary-9g_Lb2na.js.map} +1 -1
  24. package/dist/_chunks/{json-lossy-check-CVuRs2hG.js → json-lossy-check-C8zBY2uZ.js} +2 -2
  25. package/dist/_chunks/{json-lossy-check-CVuRs2hG.js.map → json-lossy-check-C8zBY2uZ.js.map} +1 -1
  26. package/dist/_chunks/{live-graph-cNuWMYQI.js → live-graph-C_4v-fHv.js} +4 -4
  27. package/dist/_chunks/{live-graph-cNuWMYQI.js.map → live-graph-C_4v-fHv.js.map} +1 -1
  28. package/dist/_chunks/{logger-BP0LN6vP.js → logger-CbLdcy-W.js} +2 -2
  29. package/dist/_chunks/{logger-BP0LN6vP.js.map → logger-CbLdcy-W.js.map} +1 -1
  30. package/dist/_chunks/{poison-scan-CfQ3unZR.js → poison-scan-C92liMAr.js} +2 -2
  31. package/dist/_chunks/{poison-scan-CfQ3unZR.js.map → poison-scan-C92liMAr.js.map} +1 -1
  32. package/dist/_chunks/{scanner-DmqdxzbW.js → scanner-CQt12vE2.js} +2 -2
  33. package/dist/_chunks/{scanner-DmqdxzbW.js.map → scanner-CQt12vE2.js.map} +1 -1
  34. package/dist/_chunks/{sizeof-BM1409x2.js → sizeof-QPE5nd3u.js} +2 -2
  35. package/dist/_chunks/{sizeof-BM1409x2.js.map → sizeof-QPE5nd3u.js.map} +1 -1
  36. package/dist/_chunks/{walkers-Czu2jXFq.js → walkers-DAT4avhZ.js} +3 -3
  37. package/dist/_chunks/{walkers-Czu2jXFq.js.map → walkers-DAT4avhZ.js.map} +1 -1
  38. package/dist/adapters/cloudflare-kv-cache.js +1 -1
  39. package/dist/analyze/crawl-entry.js +3 -3
  40. package/dist/analyze/graph-command.js +2 -2
  41. package/dist/cache/index.js +2 -2
  42. package/dist/cache/stores/memory.js +1 -1
  43. package/dist/cdn/workers-cache-purge.js +1 -1
  44. package/dist/cli.js +3 -3
  45. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
  46. package/dist/client/browser-entry/action-queue.d.ts +1 -0
  47. package/dist/client/browser-entry/action-queue.d.ts.map +1 -1
  48. package/dist/client/browser-entry/form-state.d.ts +22 -0
  49. package/dist/client/browser-entry/form-state.d.ts.map +1 -0
  50. package/dist/client/browser-entry/hydrate.d.ts +9 -1
  51. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  52. package/dist/client/browser-entry/index.d.ts +2 -0
  53. package/dist/client/browser-entry/index.d.ts.map +1 -1
  54. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  55. package/dist/client/error-boundary.js +1 -1
  56. package/dist/client/form.d.ts +17 -64
  57. package/dist/client/form.d.ts.map +1 -1
  58. package/dist/client/index.d.ts +3 -2
  59. package/dist/client/index.d.ts.map +1 -1
  60. package/dist/client/index.js +111 -51
  61. package/dist/client/index.js.map +1 -1
  62. package/dist/client/internal.js +33 -32
  63. package/dist/client/internal.js.map +1 -1
  64. package/dist/client/navigation-api.d.ts +25 -63
  65. package/dist/client/navigation-api.d.ts.map +1 -1
  66. package/dist/client/navigation-transition.d.ts +11 -2
  67. package/dist/client/navigation-transition.d.ts.map +1 -1
  68. package/dist/client/router-effects.d.ts +7 -3
  69. package/dist/client/router-effects.d.ts.map +1 -1
  70. package/dist/client/router-lifecycle.d.ts +17 -11
  71. package/dist/client/router-lifecycle.d.ts.map +1 -1
  72. package/dist/client/router-pipeline.d.ts +3 -2
  73. package/dist/client/router-pipeline.d.ts.map +1 -1
  74. package/dist/client/router-types.d.ts +24 -44
  75. package/dist/client/router-types.d.ts.map +1 -1
  76. package/dist/client/router.d.ts.map +1 -1
  77. package/dist/client/use-form-field.d.ts +39 -0
  78. package/dist/client/use-form-field.d.ts.map +1 -0
  79. package/dist/config-types.d.ts +2 -1
  80. package/dist/config-types.d.ts.map +1 -1
  81. package/dist/index.js +6 -7
  82. package/dist/index.js.map +1 -1
  83. package/dist/plugins/shims.d.ts.map +1 -1
  84. package/dist/routing/index.js +2 -2
  85. package/dist/rsc-runtime/rsc.d.ts +1 -1
  86. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  87. package/dist/server/action-client.d.ts +20 -7
  88. package/dist/server/action-client.d.ts.map +1 -1
  89. package/dist/server/action-handler.d.ts +27 -8
  90. package/dist/server/action-handler.d.ts.map +1 -1
  91. package/dist/server/als-registry.d.ts +22 -2
  92. package/dist/server/als-registry.d.ts.map +1 -1
  93. package/dist/server/client-error-message.d.ts +12 -0
  94. package/dist/server/client-error-message.d.ts.map +1 -0
  95. package/dist/server/flight-scripts.d.ts +9 -0
  96. package/dist/server/flight-scripts.d.ts.map +1 -1
  97. package/dist/server/form-data.d.ts +13 -4
  98. package/dist/server/form-data.d.ts.map +1 -1
  99. package/dist/server/form-state-flight.d.ts +32 -0
  100. package/dist/server/form-state-flight.d.ts.map +1 -0
  101. package/dist/server/index.d.ts +0 -2
  102. package/dist/server/index.d.ts.map +1 -1
  103. package/dist/server/index.js +41 -60
  104. package/dist/server/index.js.map +1 -1
  105. package/dist/server/internal.js +10 -6
  106. package/dist/server/internal.js.map +1 -1
  107. package/dist/server/logger.d.ts +1 -0
  108. package/dist/server/logger.d.ts.map +1 -1
  109. package/dist/server/pipeline.d.ts +20 -6
  110. package/dist/server/pipeline.d.ts.map +1 -1
  111. package/dist/server/request-context.d.ts +27 -2
  112. package/dist/server/request-context.d.ts.map +1 -1
  113. package/dist/server/route-element-builder.d.ts.map +1 -1
  114. package/dist/server/rsc-entry/action-dispatcher.d.ts +6 -5
  115. package/dist/server/rsc-entry/action-dispatcher.d.ts.map +1 -1
  116. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  117. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  118. package/dist/server/rsc-entry/render-route.d.ts +2 -0
  119. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  120. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  121. package/dist/server/rsc-entry/ssr-renderer.d.ts +6 -0
  122. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  123. package/dist/server/ssr-bridge-types.d.ts +10 -0
  124. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  125. package/dist/server/ssr-entry.d.ts.map +1 -1
  126. package/dist/server/ssr-form-state.d.ts +30 -0
  127. package/dist/server/ssr-form-state.d.ts.map +1 -0
  128. package/dist/server/ssr-render.d.ts +3 -0
  129. package/dist/server/ssr-render.d.ts.map +1 -1
  130. package/dist/shared/form-state-flight.d.ts +36 -0
  131. package/dist/shared/form-state-flight.d.ts.map +1 -0
  132. package/docs/api/31-api-client.mdx +31 -3
  133. package/docs/api/34-api-config.mdx +1 -1
  134. package/docs/learn/08-forms-and-actions.mdx +116 -36
  135. package/package.json +1 -1
  136. package/src/client/browser-entry/action-dispatch.ts +104 -24
  137. package/src/client/browser-entry/action-queue.ts +1 -1
  138. package/src/client/browser-entry/form-state.ts +48 -0
  139. package/src/client/browser-entry/hydrate.ts +10 -1
  140. package/src/client/browser-entry/index.ts +25 -7
  141. package/src/client/browser-entry/router-init.ts +7 -20
  142. package/src/client/form.tsx +33 -98
  143. package/src/client/index.ts +3 -2
  144. package/src/client/navigation-api.ts +47 -173
  145. package/src/client/navigation-transition.ts +15 -4
  146. package/src/client/router-effects.ts +8 -4
  147. package/src/client/router-lifecycle.ts +40 -20
  148. package/src/client/router-pipeline.ts +10 -12
  149. package/src/client/router-types.ts +24 -48
  150. package/src/client/router.ts +49 -56
  151. package/src/client/use-form-field.ts +132 -0
  152. package/src/config-types.ts +2 -1
  153. package/src/plugins/shims.ts +0 -2
  154. package/src/rsc-runtime/rsc.ts +3 -0
  155. package/src/rsc-runtime/vendor-types.d.ts +14 -0
  156. package/src/server/action-client.ts +77 -64
  157. package/src/server/action-handler.ts +133 -95
  158. package/src/server/als-registry.ts +23 -9
  159. package/src/server/client-error-message.ts +18 -0
  160. package/src/server/flight-scripts.ts +13 -0
  161. package/src/server/form-data.ts +62 -10
  162. package/src/server/form-state-flight.ts +67 -0
  163. package/src/server/index.ts +0 -4
  164. package/src/server/logger.ts +6 -1
  165. package/src/server/pipeline.ts +27 -8
  166. package/src/server/request-context.ts +39 -2
  167. package/src/server/route-element-builder.ts +12 -1
  168. package/src/server/rsc-entry/action-dispatcher.ts +40 -34
  169. package/src/server/rsc-entry/error-renderer.ts +2 -1
  170. package/src/server/rsc-entry/index.ts +1 -0
  171. package/src/server/rsc-entry/render-route.ts +16 -0
  172. package/src/server/rsc-entry/rsc-stream.ts +20 -11
  173. package/src/server/rsc-entry/ssr-renderer.ts +11 -0
  174. package/src/server/ssr-bridge-types.ts +10 -0
  175. package/src/server/ssr-entry.ts +16 -2
  176. package/src/server/ssr-form-state.ts +58 -0
  177. package/src/server/ssr-render.ts +5 -0
  178. package/src/shared/form-state-flight.ts +74 -0
  179. package/dist/_chunks/actions-Rjk4htmA.js.map +0 -1
  180. package/dist/_chunks/als-registry-DaxkVjt5.js.map +0 -1
  181. package/dist/server/form-flash.d.ts +0 -78
  182. package/dist/server/form-flash.d.ts.map +0 -1
  183. package/src/server/form-flash.ts +0 -89
@@ -1 +1 @@
1
- {"version":3,"file":"shims.d.ts","sourceRoot":"","sources":["../../src/plugins/shims.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAGnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAsB1D;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAsBlD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EA6BhD,CAAC;AA2CF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAoOvD"}
1
+ {"version":3,"file":"shims.d.ts","sourceRoot":"","sources":["../../src/plugins/shims.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAGnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAsB1D;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAsBlD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EA2BhD,CAAC;AA2CF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAoOvD"}
@@ -1,5 +1,5 @@
1
1
  import { a as INTERCEPTION_MARKERS, i as DEFAULT_PAGE_EXTENSIONS, n as classifyUrlSegment, t as classifySegment } from "../_chunks/segment-classify-C539Pa2O.js";
2
- import { d as collectInterceptionRewrites, n as scanRoutes } from "../_chunks/scanner-DmqdxzbW.js";
2
+ import { d as collectInterceptionRewrites, n as scanRoutes } from "../_chunks/scanner-CQt12vE2.js";
3
3
  import { t as generateRouteMap } from "../_chunks/codegen-Bps1sLKJ.js";
4
- import { n as collectDynamicSegmentsFromTree, r as validateSchemaAgainstRoutes, t as collectLeafRoutes } from "../_chunks/walkers-Czu2jXFq.js";
4
+ import { n as collectDynamicSegmentsFromTree, r as validateSchemaAgainstRoutes, t as collectLeafRoutes } from "../_chunks/walkers-DAT4avhZ.js";
5
5
  export { DEFAULT_PAGE_EXTENSIONS, INTERCEPTION_MARKERS, classifySegment, classifyUrlSegment, collectDynamicSegmentsFromTree, collectInterceptionRewrites, collectLeafRoutes, generateRouteMap, scanRoutes, validateSchemaAgainstRoutes };
@@ -10,5 +10,5 @@
10
10
  * Keep this as thin pass-through re-exports — the value is the single choke
11
11
  * point, not abstraction.
12
12
  */
13
- export { renderToReadableStream, loadServerAction, decodeReply, decodeAction, encryptActionBoundArgs, decryptActionBoundArgs, createFromReadableStream, } from '@vitejs/plugin-rsc/rsc';
13
+ export { renderToReadableStream, loadServerAction, decodeReply, decodeAction, decodeFormState, encryptActionBoundArgs, decryptActionBoundArgs, createFromReadableStream, } from '@vitejs/plugin-rsc/rsc';
14
14
  //# sourceMappingURL=rsc.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rsc.d.ts","sourceRoot":"","sources":["../../src/rsc-runtime/rsc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,sBAAsB,EACtB,sBAAsB,EAOtB,wBAAwB,GACzB,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"rsc.d.ts","sourceRoot":"","sources":["../../src/rsc-runtime/rsc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,WAAW,EACX,YAAY,EAGZ,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EAOtB,wBAAwB,GACzB,MAAM,wBAAwB,CAAC"}
@@ -105,7 +105,11 @@ export type ActionResult<TData = unknown> = {
105
105
  code: string;
106
106
  data?: Record<string, unknown>;
107
107
  };
108
- submittedValues?: never;
108
+ /**
109
+ * The submitted form, when the input was FormData — for repopulating
110
+ * form fields, which React resets after the action (TIM-1573).
111
+ */
112
+ submittedValues?: Record<string, unknown>;
109
113
  };
110
114
  /** Context passed to the action body. */
111
115
  export interface ActionContext<TCtx, TInput> {
@@ -139,7 +143,8 @@ export interface ActionBuilderWithSchema<TCtx, TInput> {
139
143
  /**
140
144
  * The final action function. Callable three ways:
141
145
  * - Direct: action(input) → Promise<ActionResult<TData>>
142
- * - React useActionState: action(prevState, formData) → Promise<ActionResult<TData>>
146
+ * - React useActionState: action(prevState, payload) → Promise<ActionResult<TData>>,
147
+ * where payload is the submitted FormData or the value dispatch was called with
143
148
  * - React <form action={fn}>: action(formData) → void (return value ignored by React)
144
149
  *
145
150
  * The third overload exists purely for type compatibility with React's
@@ -169,18 +174,26 @@ export type ActionFn<TData = unknown, TInput = unknown> = {
169
174
  (formData: FormData): void;
170
175
  /** Direct call: action(input) — optional when TInput is undefined/unknown (no-schema actions). */
171
176
  (...args: undefined extends TInput ? [input?: TInput] : [input: TInput]): Promise<ActionResult<TData>>;
172
- /** React useActionState: action(prevState, formData) */
173
- (prevState: ActionResult<TData> | null, formData: FormData): Promise<ActionResult<TData>>;
177
+ /**
178
+ * React useActionState: action(prevState, payload). The payload is the
179
+ * submitted FormData, or whatever the hook's dispatch was called with.
180
+ */
181
+ (prevState: ActionResult<TData> | null, payload: TInput | FormData): Promise<ActionResult<TData>>;
174
182
  };
175
183
  import { type SensitiveFieldsOption } from './sensitive-fields.ts';
176
184
  /**
177
185
  * Wrap unexpected errors into a safe server error result.
178
186
  * ActionError → typed result. Other errors → INTERNAL_ERROR (no leak).
179
187
  *
180
- * Exported for use by action-handler.ts to catch errors from raw 'use server'
181
- * functions that don't use createActionClient.
188
+ * `createActionClient` actions only. A raw `'use server'` function that
189
+ * throws is rejected on the client instead (action-handler.ts).
182
190
  */
183
- export declare function handleActionError(error: unknown): ActionResult<never>;
191
+ export declare function handleActionError(error: unknown): {
192
+ serverError: {
193
+ code: string;
194
+ data?: Record<string, unknown>;
195
+ };
196
+ };
184
197
  /**
185
198
  * Create a typed action client with middleware and schema validation.
186
199
  *
@@ -1 +1 @@
1
- {"version":3,"file":"action-client.d.ts","sourceRoot":"","sources":["../../src/server/action-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"action-client.d.ts","sourceRoot":"","sources":["../../src/server/action-client.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,8 @@
8
8
  * 1. Detect action request (POST with `x-rsc-action` header or form action fields)
9
9
  * 2. CSRF validation
10
10
  * 3. Load and execute the server action
11
- * 4. Return RSC stream (with-JS) or 302 redirect (no-JS)
11
+ * 4. Return RSC stream (with-JS), or on the no-JS path a redirect, a page
12
+ * rerender carrying React's form state, or the error page
12
13
  *
13
14
  * See design/08-forms-and-actions.md
14
15
  */
@@ -16,7 +17,7 @@ import { type CsrfConfig } from './csrf.ts';
16
17
  import { type RevalidateRenderer } from './actions.ts';
17
18
  import { type BodyLimitsConfig } from './body-limits.ts';
18
19
  import { type SensitiveFieldsOption } from './sensitive-fields.ts';
19
- import type { FormFlashData } from './form-flash.ts';
20
+ import type { ReactFormState } from 'react-dom/client';
20
21
  /** Configuration for the action handler. */
21
22
  export interface ActionDispatchConfig {
22
23
  /** CSRF configuration. */
@@ -48,7 +49,18 @@ export interface ActionDispatchConfig {
48
49
  */
49
50
  export declare function isActionRequest(req: Request): boolean;
50
51
  /**
51
- * Signal from handleFormAction to re-render the page with flash data instead of redirecting.
52
+ * How a no-JS action that did not redirect is answered. The dispatcher
53
+ * (`rsc-entry/action-dispatcher.ts`) turns it into the response:
54
+ *
55
+ * - `rerender`: the action returned. The page is rendered again as a GET,
56
+ * with `formState` — React's `decodeFormState` of the result, present
57
+ * only when the submitted form used `useActionState` — handed to SSR
58
+ * and hydration, where React gives it to the hook that submitted.
59
+ * - `error`: the action threw. The page is rendered again with the error
60
+ * in place of the page component, so the route's nearest error page
61
+ * answers, with the
62
+ * status the pipeline gives any unhandled error. The JS path rejects
63
+ * the action for the same throw, so both reach an error boundary.
52
64
  *
53
65
  * Carries two cookie-related snapshots taken before the action's ALS scope
54
66
  * exits, so the rerender pipeline (which establishes its own fresh cookie
@@ -68,16 +80,23 @@ export declare function isActionRequest(req: Request): boolean;
68
80
  * previous `cookieHeader: string` shape carried — see
69
81
  * ONGOING_SECURITY.md H-3 (TIM-868) and TIM-837.
70
82
  */
71
- export interface FormRerender {
72
- rerender: FormFlashData;
83
+ export type FormActionOutcome = {
84
+ kind: 'rerender';
85
+ formState: ReactFormState | undefined;
73
86
  setCookieHeaders: string[];
74
87
  cookies: Map<string, string>;
75
- }
88
+ } | {
89
+ kind: 'error';
90
+ error: unknown;
91
+ errorId: string;
92
+ setCookieHeaders: string[];
93
+ cookies: Map<string, string>;
94
+ };
76
95
  /**
77
96
  * Handle a server action request.
78
97
  *
79
- * Returns a Response, a FormRerender signal (for no-JS validation failure re-render),
98
+ * Returns a Response, a FormActionOutcome (no-JS action that did not redirect),
80
99
  * or null if this isn't actually an action request (e.g., a regular form POST to an API route).
81
100
  */
82
- export declare function handleActionRequest(req: Request, config: ActionDispatchConfig): Promise<Response | FormRerender | null>;
101
+ export declare function handleActionRequest(req: Request, config: ActionDispatchConfig): Promise<Response | FormActionOutcome | null>;
83
102
  //# sourceMappingURL=action-handler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"action-handler.d.ts","sourceRoot":"","sources":["../../src/server/action-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,OAAO,EAAuC,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAEjF,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAKtE,OAAO,EAAwC,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAE/F,OAAO,EAIL,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAUrD,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,0BAA0B;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,gDAAgD;IAChD,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,qBAAqB,CAAC;CACzC;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAarD;AAID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,aAAa,CAAC;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,QAAQ,GAAG,YAAY,GAAG,IAAI,CAAC,CAuFzC"}
1
+ {"version":3,"file":"action-handler.d.ts","sourceRoot":"","sources":["../../src/server/action-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAUH,OAAO,EAAuC,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAEjF,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAKtE,OAAO,EAAwC,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAKL,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAYvD,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,0BAA0B;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,gDAAgD;IAChD,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,qBAAqB,CAAC;CACzC;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAarD;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,MAAM,iBAAiB,GACzB;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,cAAc,GAAG,SAAS,CAAC;IACtC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B,CAAC;AAON;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,QAAQ,GAAG,iBAAiB,GAAG,IAAI,CAAC,CAoF9C"}
@@ -34,8 +34,14 @@ import '#server-only-guard';
34
34
  import type { CoercedParams } from '../shared/param-value.ts';
35
35
  import type { SlotParamsRecord } from '../shared/slot-params.ts';
36
36
  import { AsyncLocalStorage } from 'node:async_hooks';
37
+ import type { ReactFormState } from 'react-dom/client';
37
38
  /** @internal — import via request-context.ts public API */
38
39
  export declare const requestContextAls: AsyncLocalStorage<RequestContextStore>;
40
+ /** A no-JS action's thrown error, and the correlation ID it was logged with. */
41
+ export interface ActionErrorForRender {
42
+ error: unknown;
43
+ errorId: string;
44
+ }
39
45
  export interface RequestContextStore {
40
46
  /**
41
47
  * The request this context was opened for, or `null` in the build-time
@@ -105,6 +111,22 @@ export interface RequestContextStore {
105
111
  flushed: boolean;
106
112
  /** Whether the current context allows cookie mutation. */
107
113
  mutableContext: boolean;
114
+ /**
115
+ * The form state a no-JS action produced (`decodeFormState`), set only on
116
+ * the page render that answers it. Read once, by the SSR renderer, which
117
+ * hands it to Fizz and embeds it for `hydrateRoot`; no user-facing API
118
+ * reads it, because a server component cannot see an action's result on
119
+ * the JS path either (design/08 §"No-JS Result Round-Trip").
120
+ */
121
+ formState?: ReactFormState;
122
+ /**
123
+ * The error a no-JS action threw, set only on the page render that answers
124
+ * it. The route renders it where its page would be, so the nearest error
125
+ * page answers, as the nearest error boundary does with JS. Read by the
126
+ * route element builder and the Flight `onError`; no user-facing API reads
127
+ * it (design/08 §"The Basic Wire-Up").
128
+ */
129
+ actionError?: ActionErrorForRender;
108
130
  /**
109
131
  * Set by AccessGate or PageDenyBoundary when a DenySignal is caught
110
132
  * server-side (inside the React tree, before React Flight sees it).
@@ -187,8 +209,6 @@ export interface RevalidationState {
187
209
  }
188
210
  /** @internal — import via actions.ts public API */
189
211
  export declare const revalidationAls: AsyncLocalStorage<RevalidationState>;
190
- /** @internal — import via form-flash.ts public API */
191
- export declare const formFlashAls: AsyncLocalStorage<import("./form-flash.ts").FormFlashData>;
192
212
  /** Function that sends Link header values as a 103 Early Hints response. */
193
213
  export type EarlyHintsSenderFn = (links: string[]) => void;
194
214
  /** @internal — import via early-hints-sender.ts public API */
@@ -1 +1 @@
1
- {"version":3,"file":"als-registry.d.ts","sourceRoot":"","sources":["../../src/server/als-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"als-registry.d.ts","sourceRoot":"","sources":["../../src/server/als-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The message an unexpected server error shows the client: its own message
3
+ * in dev, a fixed one in production (design/13-security.md §"Errors don't
4
+ * leak"). One definition for every place an error crosses to the client —
5
+ * a Flight error row's digest, a rejected action, an error page's error.
6
+ *
7
+ * Uses isDevMode(), not isDebug(): the text reaches the browser, and
8
+ * TIMBER_DEBUG must never make it leak.
9
+ */
10
+ export declare const PRODUCTION_ERROR_MESSAGE = "An unexpected error occurred.";
11
+ export declare function clientErrorMessage(error: unknown): string;
12
+ //# sourceMappingURL=client-error-message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-error-message.d.ts","sourceRoot":"","sources":["../../src/server/client-error-message.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,eAAO,MAAM,wBAAwB,kCAAkC,CAAC;AAExE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGzD"}
@@ -42,4 +42,13 @@ export declare function flightInitScript(nonce?: string): string;
42
42
  * push if needed, preventing a TypeError. See TIM-559.
43
43
  */
44
44
  export declare function flightChunkScript(data: string, nonce?: string): string;
45
+ /**
46
+ * Generate the script that embeds a no-JS action's form state for
47
+ * hydration: its Flight bytes (server/form-state-flight.ts), as base64. Only
48
+ * a page answering a no-JS action has one. Base64 carries Flight's binary
49
+ * rows, which a text chunk would corrupt, and has no character that can end
50
+ * the script element or the string. See design/08-forms-and-actions.md
51
+ * §"No-JS Result Round-Trip".
52
+ */
53
+ export declare function formStateScript(bytes: Uint8Array, nonce?: string): string;
45
54
  //# sourceMappingURL=flight-scripts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"flight-scripts.d.ts","sourceRoot":"","sources":["../../src/server/flight-scripts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMxD;AAOD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAGtE"}
1
+ {"version":3,"file":"flight-scripts.d.ts","sourceRoot":"","sources":["../../src/server/flight-scripts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMxD;AAOD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAGtE;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzE"}
@@ -15,16 +15,24 @@
15
15
  * Handles:
16
16
  * - **Duplicate keys → arrays**: `tags=js&tags=ts` → `{ tags: ["js", "ts"] }`
17
17
  * - **Nested dot-paths**: `user.name=Alice` → `{ user: { name: "Alice" } }`
18
- * - **Empty strings → undefined**: Enables `.optional()` semantics in schemas
18
+ * - **Indexed lists → arrays**: `rows.0.name=A&rows.1.name=B` →
19
+ * `{ rows: [{ name: "A" }, { name: "B" }] }`, when the indexes are exactly
20
+ * `0..n-1`. A list with a gap stays an object keyed by index.
21
+ * - **Empty strings stay `""`**: a blank text input is `""`, so
22
+ * `z.string().min(1, 'Required')` reports its own message. Use
23
+ * `coerce.text` to make a blank optional field `undefined`
19
24
  * - **Empty Files → undefined**: File inputs with no selection become `undefined`
20
25
  * - **Strips `$ACTION_*` fields**: React's internal hidden fields are excluded
26
+ * - **Drops `__proto__` paths and names deeper than 32 segments**
21
27
  */
22
28
  export declare function parseFormData(formData: FormData): Record<string, unknown>;
23
29
  /**
24
30
  * Schema-agnostic coercion primitives for common FormData patterns.
25
31
  *
26
32
  * These are plain transform functions — they compose with any schema library's
27
- * `transform`/`preprocess` pipeline:
33
+ * `transform`/`preprocess` pipeline. In Zod, use `z.preprocess`: it runs on an
34
+ * absent key (an unchecked checkbox), where `z.unknown().transform()` fails
35
+ * with "expected nonoptional" before the transform runs.
28
36
  *
29
37
  * ```ts
30
38
  * // Zod
@@ -39,8 +47,9 @@ export declare const coerce: {
39
47
  * Use with `.optional()` schemas where an empty input means "not provided".
40
48
  *
41
49
  * ```ts
42
- * // Zod
43
- * z.unknown().transform(coerce.text).pipe(z.string().optional())
50
+ * // Zod — preprocess, not `z.unknown().transform(…)`: Zod 4 rejects an
51
+ * // absent key before a transform runs ("expected nonoptional")
52
+ * z.preprocess(coerce.text, z.string().optional())
44
53
  * // Valibot
45
54
  * v.pipe(v.unknown(), v.transform(coerce.text), v.optional(v.string()))
46
55
  * ```
@@ -1 +1 @@
1
- {"version":3,"file":"form-data.d.ts","sourceRoot":"","sources":["../../src/server/form-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA2BzE;AAqFD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,MAAM;IACjB;;;;;;;;;;OAUG;IACH,IAAI,QAAQ,OAAO,GAAG,MAAM,GAAG,SAAS;IAMxC;;;;;;OAMG;IACH,MAAM,QAAQ,OAAO,GAAG,MAAM,GAAG,SAAS;IAS1C;;;;;OAKG;IACH,QAAQ,QAAQ,OAAO,GAAG,OAAO;IAOjC;;;;;OAKG;IACH,IAAI,QAAQ,OAAO,GAAG,OAAO;IAU7B;;;;;;;;OAQG;IACH,IAAI,QAAQ,OAAO,GAAG,IAAI,GAAG,SAAS;IAgCtC;;;;;;;;;;;;;;OAcG;IACH,IAAI,WAAW;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,SAAS;CAmB9F,CAAC"}
1
+ {"version":3,"file":"form-data.d.ts","sourceRoot":"","sources":["../../src/server/form-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA2BzE;AAgID;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,MAAM;IACjB;;;;;;;;;;;OAWG;IACH,IAAI,QAAQ,OAAO,GAAG,MAAM,GAAG,SAAS;IAMxC;;;;;;OAMG;IACH,MAAM,QAAQ,OAAO,GAAG,MAAM,GAAG,SAAS;IAS1C;;;;;OAKG;IACH,QAAQ,QAAQ,OAAO,GAAG,OAAO;IAOjC;;;;;OAKG;IACH,IAAI,QAAQ,OAAO,GAAG,OAAO;IAU7B;;;;;;;;OAQG;IACH,IAAI,QAAQ,OAAO,GAAG,IAAI,GAAG,SAAS;IAgCtC;;;;;;;;;;;;;;OAcG;IACH,IAAI,WAAW;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,SAAS;CAmB9F,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The no-JS action form state a page render hands React (TIM-1570), encoded
3
+ * with Flight (TIM-1572).
4
+ *
5
+ * Fizz renders the `useActionState` hook that submitted with the action's
6
+ * result, and the browser must hydrate with the same value, or the hook
7
+ * resets. Both get it from the Flight bytes encoded here: SSR decodes them
8
+ * for Fizz (`NavContext.formState`) and, once they decode, embeds them for
9
+ * `hydrateRoot` (server/ssr-form-state.ts; decoded by
10
+ * client/browser-entry/form-state.ts). Flight is what carries a
11
+ * `useActionState` result with JS, so a result has the same types with and
12
+ * without JS. See shared/form-state-flight.ts for the decode.
13
+ *
14
+ * A state Flight cannot encode must not turn the page into a 500 after the
15
+ * action's mutation committed, so it is dropped from both renders: the page
16
+ * renders with no result, as for a form without `useActionState`. That is a
17
+ * value Flight cannot serialize (a plain function, a class instance), which
18
+ * fails the action with JS too, or a nested promise that rejects or does not
19
+ * settle in time, which with JS reaches the hook as that rejected or pending
20
+ * promise. The no-JS page cannot carry a pending promise, and does not embed
21
+ * an error row.
22
+ *
23
+ * See design/08-forms-and-actions.md §"No-JS Result Round-Trip".
24
+ */
25
+ import type { ReactFormState } from 'react-dom/client';
26
+ /**
27
+ * Serialize the form state with Flight, or return `null` when it cannot be,
28
+ * with a warning. The whole payload is read under one `timeoutMs` deadline,
29
+ * and the render stops when `signal` (the request's) aborts.
30
+ */
31
+ export declare function encodeFormState(formState: ReactFormState, timeoutMs: number, signal?: AbortSignal): Promise<Uint8Array | null>;
32
+ //# sourceMappingURL=form-state-flight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-state-flight.d.ts","sourceRoot":"","sources":["../../src/server/form-state-flight.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAKvD;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA2B5B"}
@@ -10,8 +10,6 @@ export { deny, redirect, redirectExternal, RedirectType, waitUntil, type DenyOpt
10
10
  export { createActionClient, ActionError, validated } from './action-client.ts';
11
11
  export type { ActionResult, ActionFn, ActionBuilder, ActionBuilderWithSchema, ActionContext, ActionMiddleware, ActionSchema, ValidationErrors, } from './action-client.ts';
12
12
  export { coerce, parseFormData } from './form-data.ts';
13
- export { getFormFlash } from './form-flash.ts';
14
- export type { FormFlashData } from './form-flash.ts';
15
13
  export { revalidatePath, revalidateTag } from './actions.ts';
16
14
  export { getTraceId, getSpanId, withSpan, addSpanEvent } from './tracing.ts';
17
15
  export type { CoercedParamValue, CoercedParams } from '../shared/param-value.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAMA,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAK3F,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACpE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAI5D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG3F,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,SAAS,EACT,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,iBAAiB,CAAC;AAKzB,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAChF,YAAY,EACV,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,uBAAuB,EACvB,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAI7E,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAMA,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAK3F,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACpE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAI5D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG3F,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,SAAS,EACT,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,iBAAiB,CAAC;AAKzB,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAChF,YAAY,EACV,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,uBAAuB,EACvB,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGvD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAI7E,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC"}
@@ -1,7 +1,6 @@
1
- import { n as formFlashAls } from "../_chunks/als-registry-DaxkVjt5.js";
2
- import { A as getSpanId, C as isRedirectSignal, E as addSpanEvent, F as withSpan, S as isDenySignal, T as isDevMode, j as getTraceId, w as isDebug } from "../_chunks/logger-BP0LN6vP.js";
1
+ import { A as getSpanId, C as isRedirectSignal, E as addSpanEvent, F as withSpan, S as isDenySignal, T as isDevMode, j as getTraceId, w as isDebug } from "../_chunks/logger-CbLdcy-W.js";
3
2
  import { t as formatSize } from "../_chunks/format-BKclgVbk.js";
4
- import { _ as getHeaders, a as parseFormData, c as deny, d as waitUntil, i as coerce, l as redirect, n as revalidatePath, p as getCookieJar, r as revalidateTag, u as redirectExternal, y as getSegmentParams } from "../_chunks/actions-Rjk4htmA.js";
3
+ import { _ as getHeaders, a as parseFormData, c as deny, d as waitUntil, i as coerce, l as redirect, n as revalidatePath, p as getCookieJar, r as revalidateTag, u as redirectExternal, y as getSegmentParams } from "../_chunks/actions-CEootpB1.js";
5
4
  //#region src/shared/redirect-type.ts
6
5
  /**
7
6
  * Next.js redirect type discriminator.
@@ -253,8 +252,8 @@ function extractStandardSchemaErrors(issues) {
253
252
  * Wrap unexpected errors into a safe server error result.
254
253
  * ActionError → typed result. Other errors → INTERNAL_ERROR (no leak).
255
254
  *
256
- * Exported for use by action-handler.ts to catch errors from raw 'use server'
257
- * functions that don't use createActionClient.
255
+ * `createActionClient` actions only. A raw `'use server'` function that
256
+ * throws is rejected on the client instead (action-handler.ts).
258
257
  */
259
258
  function handleActionError(error) {
260
259
  if (error instanceof ActionError) return { serverError: {
@@ -289,20 +288,21 @@ function handleActionError(error) {
289
288
  function createActionClient(config = {}) {
290
289
  function buildAction(schema, fn) {
291
290
  async function actionHandler(...args) {
291
+ const last = args.at(-1);
292
+ const form = last instanceof FormData ? parseFormData(last) : void 0;
293
+ const sensitivePredicate = resolveSensitivePredicate(config.stripSensitiveFields, void 0);
294
+ const echo = (value) => {
295
+ const withoutFiles = stripFiles(value);
296
+ if (withoutFiles === void 0) return void 0;
297
+ return stripSensitiveFields(withoutFiles, sensitivePredicate);
298
+ };
292
299
  try {
293
300
  const ctx = await runActionMiddleware(config.middleware);
294
- let rawInput;
295
- if (args.length === 2 && args[1] instanceof FormData) rawInput = schema ? parseFormData(args[1]) : args[1];
296
- else if (args.length === 1 && args[0] instanceof FormData) rawInput = schema ? parseFormData(args[0]) : args[0];
297
- else rawInput = args[0];
298
- const sensitivePredicate = resolveSensitivePredicate(config.stripSensitiveFields, void 0);
299
- const buildSubmittedValues = () => {
300
- const withoutFiles = stripFiles(rawInput);
301
- if (withoutFiles === void 0) return void 0;
302
- return stripSensitiveFields(withoutFiles, sensitivePredicate);
303
- };
304
- if (config.fileSizeLimit !== void 0 && rawInput && typeof rawInput === "object") {
305
- const fileSizeErrors = validateFileSizes(rawInput, config.fileSizeLimit);
301
+ const rawInput = schema && form ? form : last;
302
+ const submitted = form ?? rawInput;
303
+ const buildSubmittedValues = () => echo(submitted);
304
+ if (config.fileSizeLimit !== void 0 && submitted && typeof submitted === "object") {
305
+ const fileSizeErrors = validateFileSizes(submitted, config.fileSizeLimit);
306
306
  if (fileSizeErrors) return {
307
307
  validationErrors: fileSizeErrors,
308
308
  submittedValues: buildSubmittedValues()
@@ -351,7 +351,12 @@ function createActionClient(config = {}) {
351
351
  }) };
352
352
  } catch (error) {
353
353
  if (isRedirectSignal(error) || isDenySignal(error)) throw error;
354
- return handleActionError(error);
354
+ const result = handleActionError(error);
355
+ const submittedValues = form && echo(form);
356
+ return submittedValues ? {
357
+ ...result,
358
+ submittedValues
359
+ } : result;
355
360
  }
356
361
  }
357
362
  return actionHandler;
@@ -400,6 +405,8 @@ function logValidationFailure(errors) {
400
405
  /**
401
406
  * Validate that all File objects in the input are within the size limit.
402
407
  * Returns validation errors keyed by field name, or null if all files are ok.
408
+ * Keys are dot paths (`rows.0.file`), the form a field name and a Standard
409
+ * Schema error use, so `getFieldError` finds a file in a list.
403
410
  */
404
411
  function validateFileSizes(input, limit) {
405
412
  const limitKb = Math.round(limit / 1024);
@@ -411,7 +418,7 @@ function validateFileSizes(input, limit) {
411
418
  if (value instanceof File && value.size > limit) errors[path] = [`File "${value.name}" (${formatSize(value.size)}) exceeds the ${limitLabel} limit`];
412
419
  else if (Array.isArray(value)) for (let i = 0; i < value.length; i++) {
413
420
  const item = value[i];
414
- const itemPath = `${path}[${i}]`;
421
+ const itemPath = `${path}.${i}`;
415
422
  if (item instanceof File && item.size > limit) (errors[itemPath] ??= []).push(`File "${item.name}" (${formatSize(item.size)}) exceeds the ${limitLabel} limit`);
416
423
  else if (typeof item === "object" && item !== null && !(item instanceof File)) walk(item, itemPath);
417
424
  }
@@ -422,52 +429,26 @@ function validateFileSizes(input, limit) {
422
429
  return Object.keys(errors).length > 0 ? errors : null;
423
430
  }
424
431
  /**
425
- * Strip File objects from a value, returning a plain object safe for
426
- * serialization. File objects can't be serialized and shouldn't be echoed back.
432
+ * Strip File objects from a value, returning a copy safe for serialization.
433
+ * File objects can't be serialized and shouldn't be echoed back.
434
+ *
435
+ * Mirrors `parseFormData`'s output: objects and arrays at any depth, arrays
436
+ * of arrays included. A File in an array becomes `undefined` rather than
437
+ * being removed, so `rows.2` still names the third element (TIM-1573).
427
438
  */
428
439
  function stripFiles(value) {
429
- if (value === null || value === void 0) return void 0;
430
- if (typeof value !== "object") return void 0;
440
+ if (value === null || typeof value !== "object" || value instanceof File) return void 0;
441
+ return stripFilesFrom(value);
442
+ }
443
+ function stripFilesFrom(value) {
444
+ if (value instanceof File) return void 0;
445
+ if (Array.isArray(value)) return value.map(stripFilesFrom);
446
+ if (typeof value !== "object" || value === null) return value;
431
447
  const result = {};
432
- for (const [k, v] of Object.entries(value)) {
433
- if (v instanceof File) continue;
434
- if (Array.isArray(v)) result[k] = v.filter((item) => !(item instanceof File)).map((item) => typeof item === "object" && item !== null && !(item instanceof File) ? stripFiles(item) ?? {} : item);
435
- else if (typeof v === "object" && v !== null && !(v instanceof File)) result[k] = stripFiles(v) ?? {};
436
- else result[k] = v;
437
- }
448
+ for (const [k, v] of Object.entries(value)) if (!(v instanceof File)) result[k] = stripFilesFrom(v);
438
449
  return result;
439
450
  }
440
451
  //#endregion
441
- //#region src/server/form-flash.ts
442
- /**
443
- * Read the form flash data for the current request.
444
- *
445
- * Returns `null` if no flash data is present (i.e., this is a normal page
446
- * render, not a re-render after a no-JS form submission).
447
- *
448
- * Pass the flash as the initial state to `useActionState` so the form
449
- * component has a single source of truth for both with-JS and no-JS paths:
450
- *
451
- * ```tsx
452
- * // app/contact/page.tsx (server component)
453
- * import { getFormFlash } from '@timber-js/app/server'
454
- *
455
- * export default function ContactPage() {
456
- * const flash = getFormFlash()
457
- * return <ContactForm flash={flash} />
458
- * }
459
- *
460
- * // app/contact/form.tsx (client component)
461
- * export function ContactForm({ flash }) {
462
- * const [result, action, isPending] = useActionState(submitContact, flash)
463
- * // result is the single source of truth — flash seeds it on no-JS
464
- * }
465
- * ```
466
- */
467
- function getFormFlash() {
468
- return formFlashAls.getStore() ?? null;
469
- }
470
- //#endregion
471
- export { ActionError, RedirectType, addSpanEvent, coerce, createActionClient, deny, getCookieJar, getFormFlash, getHeaders, getSegmentParams, getSpanId, getTraceId, parseFormData, redirect, redirectExternal, revalidatePath, revalidateTag, validated, waitUntil, withSpan };
452
+ export { ActionError, RedirectType, addSpanEvent, coerce, createActionClient, deny, getCookieJar, getHeaders, getSegmentParams, getSpanId, getTraceId, parseFormData, redirect, redirectExternal, revalidatePath, revalidateTag, validated, waitUntil, withSpan };
472
453
 
473
454
  //# sourceMappingURL=index.js.map