@beignet/react-hook-form 0.0.58 → 0.0.59

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @beignet/react-hook-form
2
2
 
3
+ ## 0.0.59
4
+
5
+ ### Patch Changes
6
+
7
+ - 8a497ae: Require patched Zod releases for application schemas and generated apps, and update browser-test and UI tooling dependencies.
8
+ - 4a59715: Preserve supplied HTTP request inputs during client validation. React Hook Form
9
+ submissions return parsed values by default, with explicit raw mode and accurate
10
+ disabled/custom resolver types, including optional settings and forwarded React
11
+ Hook Form options that may be undefined. Preserve optional returned properties
12
+ and infer outputs across conditional custom and generated resolver configurations.
13
+ Keep returned form options compatible with native React Hook Form options when
14
+ TypeScript's exact optional property checking is enabled.
15
+ Bind a separate form schema whose parsed output matches the contract input when
16
+ UI values need conversion. Capture data getters
17
+ once while preserving opaque schema input instances and their private state.
18
+ Preserve inherited and non-enumerable path values when capturing URL parameters.
19
+ Require all URL placeholders in client argument types, including defaulted schema
20
+ fields, and capture query getters once with input validation enabled or disabled.
21
+
3
22
  ## 0.0.58
4
23
 
5
24
  ## 0.0.57
package/README.md CHANGED
@@ -8,8 +8,9 @@
8
8
  > Beignet is experimental alpha software. The `0.0.x` package line is for early
9
9
  > evaluation, and APIs may change between releases while the framework settles.
10
10
 
11
- This package provides automatic form validation using a contract body schema
12
- whose input is object-shaped. It works with any
11
+ This package provides automatic form validation and parsed submissions using a
12
+ contract body schema, or a separate form schema that produces contract input.
13
+ The selected form schema must have object-shaped input. It works with any
13
14
  [Standard Schema](https://github.com/standard-schema/standard-schema) library
14
15
  (Zod, Valibot, ArkType, etc.).
15
16
 
@@ -56,7 +57,7 @@ function CreateTodoForm() {
56
57
  });
57
58
 
58
59
  const onSubmit = form.handleSubmit((values) => {
59
- // values is the parsed schema output: { title: string }
60
+ // values is parsed schema output: { title: string }
60
61
  console.log("Creating todo:", values);
61
62
  });
62
63
 
@@ -175,12 +176,13 @@ Creates a React Hook Form adapter factory.
175
176
  const rhf = createReactHookForm();
176
177
  ```
177
178
 
178
- ### `rhf(contract)`
179
+ ### `rhf(contract, options?)`
179
180
 
180
- Creates a React Hook Form adapter for a contract whose body schema input is an
181
- object. TypeScript rejects contracts with scalar or array body inputs because
182
- they do not define named form fields. The schema output may still transform to
183
- any submit value.
181
+ Creates an adapter using the contract body schema by default. Pass `{ schema }`
182
+ to bind a separate form schema whose output is assignable to the contract body
183
+ input. The selected schema input must be an object with named fields. Scalar
184
+ and array bodies require an explicit object-input form schema that produces
185
+ the request shape. Contracts without a body are rejected.
184
186
 
185
187
  ```ts
186
188
  const adapter = rhf(createTodo);
@@ -188,13 +190,14 @@ const adapter = rhf(createTodo);
188
190
 
189
191
  ### `adapter.useForm(props?)`
190
192
 
191
- Returns a React Hook Form `useForm` result with the contract's body schema as resolver.
193
+ Returns a React Hook Form `useForm` result with the selected schema as resolver.
192
194
 
193
195
  ```ts
194
196
  const form = adapter.useForm({
195
- defaultValues?: { ... },
196
- resolverEnabled?: boolean, // default: true
197
- // ...other React Hook Form options
197
+ defaultValues: { title: "" },
198
+ resolverEnabled: true, // default
199
+ submitValues: "parsed", // default; use "raw" for original input
200
+ mode: "onBlur",
198
201
  });
199
202
  ```
200
203
 
@@ -217,87 +220,102 @@ form.setError(
217
220
 
218
221
  ## Type inference
219
222
 
220
- Form types come from the contract's body schema and follow React Hook Form's
221
- input/output split:
222
-
223
- - Live field values — `register`, `watch`, `setValue`, `getValues`, and
224
- `defaultValues` — use the schema **input**: what the user edits before
225
- validation runs.
226
- - `handleSubmit` callbacks receive the schema **output**: the parsed values
227
- after coercion, transforms, and defaults run.
228
-
229
- The schema input must be object-shaped. Keep lists and scalar values inside
230
- named fields rather than making the request body itself an array or scalar:
223
+ - Live fields (`register`, `watch`, `setValue`, `getValues`, `defaultValues`)
224
+ use the selected schema's **input**.
225
+ - `handleSubmit` receives parsed schema **output** by default, including
226
+ transforms, defaults, and removal of unknown keys. Live field state is unchanged.
227
+ - `submitValues: "raw"` validates but returns the original submitted snapshot.
228
+ - `resolverEnabled: false` returns unparsed input. Explicit parsed mode requires
229
+ the generated resolver. A dynamic or optional enable flag returns an input/output union.
230
+ - A custom `resolver` owns its output type, even when generation is disabled.
231
+ It cannot be combined with `submitValues`.
232
+ - Both adapter methods accept forwarded `UseFormProps` and optional resolvers.
233
+ An absent override falls back to the generated resolver, or unparsed input
234
+ when generation is disabled. Submit types include every possible output.
235
+ An `undefined` options object uses generated validation and parsed output.
236
+ - Conditional configurations may choose a custom resolver or a generated mode;
237
+ submit types include each branch's output. A single configuration cannot set
238
+ both `resolver` and `submitValues`. If the whole options object may be absent,
239
+ returned properties such as `defaultValues` and `mode` are optional too.
240
+
241
+ ### Reuse the contract schema
242
+
243
+ For a number-valued API, use `z.number()` in the contract and configure the
244
+ numeric field with `register("amount", { valueAsNumber: true })`. Submit parsed
245
+ callback values to the typed client; the client sends supplied input unchanged
246
+ and the server independently validates it.
247
+
248
+ Use `z.coerce.number()` in a shared contract when the API intentionally accepts
249
+ numeric strings too. Reusing transforming schemas is appropriate only when
250
+ parsed values remain valid request inputs and parsing again preserves their
251
+ meaning. `z.string().transform(Number)` cannot parse its numeric output; even
252
+ same-type transforms can change a value again. Use a separate form schema for
253
+ such UI conversions, or raw mode to submit original contract input.
254
+
255
+ ### Bind a separate form schema
231
256
 
232
257
  ```ts
233
- const replaceTags = todos
234
- .put("/api/todos/:id/tags")
235
- .body(z.object({ tags: z.array(z.string()) }))
236
- .responses({ 200: TodoSchema });
258
+ import { defineContract } from "@beignet/core/contracts";
259
+ import { createReactHookForm } from "@beignet/react-hook-form";
260
+ import { z } from "zod";
237
261
 
238
- const form = rhf(replaceTags).useForm({
239
- defaultValues: { tags: [] },
262
+ const paymentBody = z.object({
263
+ amount: z.number().int().positive(),
264
+ currency: z.string().default("USD"),
265
+ });
266
+ const createPayment = defineContract({ method: "POST", path: "/api/payments" })
267
+ .body(paymentBody)
268
+ .responses({ 201: z.object({ id: z.string() }) });
269
+ const paymentFormSchema = paymentBody.extend({
270
+ amount: z.string().trim().regex(/^\d+$/)
271
+ .transform(Number)
272
+ .pipe(paymentBody.shape.amount),
240
273
  });
241
- ```
242
274
 
243
- ```ts
244
- // Contract definition
245
- const createTodo = todos
246
- .post("/api/todos")
247
- .body(z.object({
248
- title: z.string().min(1),
249
- description: z.string().optional(),
250
- completed: z.boolean().optional(),
251
- }))
252
- .responses({ 201: TodoSchema });
253
-
254
- // Form values are inferred
255
275
  const rhf = createReactHookForm();
256
- const form = rhf(createTodo).useForm();
257
- form.register("title"); // ✓ Valid
258
- form.register("description"); // ✓ Valid
259
- form.register("invalid"); // ✗ Type error
260
- ```
261
-
262
- For plain schemas like the one above, input and output are identical. For
263
- coercing or transforming schemas they differ:
276
+ const paymentForm = rhf(createPayment, { schema: paymentFormSchema });
277
+ const form = paymentForm.useForm({ defaultValues: { amount: "" } });
264
278
 
265
- ```ts
266
- const createPayment = payments
267
- .post("/api/payments")
268
- .body(z.object({
269
- amount: z.string().transform(Number),
270
- note: z.string().optional(),
271
- }))
272
- .responses({ 201: PaymentSchema });
273
-
274
- const form = rhf(createPayment).useForm({
275
- defaultValues: { amount: "" }, // input: string
279
+ form.watch("amount"); // string
280
+ form.handleSubmit((body) => {
281
+ body.amount; // number, matching the request body input
282
+ body.currency; // string, including the schema default
276
283
  });
284
+ ```
277
285
 
278
- form.watch("amount"); // string (input)
286
+ The form schema owns form validation; the adapter does not additionally run the
287
+ contract schema. Derive it from shared validators to keep runtime constraints
288
+ aligned. TypeScript rejects incompatible output shapes but cannot check every
289
+ runtime rule. Raw or disabled submissions use the form schema's input and may
290
+ need mapping before posting to the contract.
279
291
 
280
- form.handleSubmit((values) => {
281
- values.amount; // number (output)
282
- });
283
- ```
292
+ Use `defaultValues` for defaults the UI should display. Generated resolvers
293
+ copy plain objects, arrays, and dates before asynchronous validation, capturing
294
+ own getters once. Class instances, files, functions, and other opaque values
295
+ retain their identity; keep them immutable during validation and submission.
296
+ Custom resolvers own their validation and snapshot behavior.
284
297
 
285
- ### Submitting transforming schemas
298
+ ### Options for React Hook Form wrappers
286
299
 
287
- The typed client posts the schema input — the server validates and transforms
288
- the body when it receives the request. Parsed output from `handleSubmit` is
289
- still valid input for plain, defaulted, and coerced schemas, so
290
- `mutation.mutate({ body: values })` keeps working for those. When a transform
291
- changes a field's type, the parsed output no longer matches the contract body
292
- and TypeScript rejects it. Send the raw field values instead — validation has
293
- already passed by the time the submit handler runs:
300
+ `formOptions(...)` returns options compatible with native `UseFormProps`,
301
+ `useForm`, and `createFormControl`, including with `exactOptionalPropertyTypes`
302
+ enabled. Input/output types match the adapter's `useForm`. Partial
303
+ `defaultValues` can narrow React Hook Form's own inference, so supply all three
304
+ generics in that case:
294
305
 
295
- ```tsx
296
- const onSubmit = form.handleSubmit(() => {
297
- mutation.mutate({ body: form.getValues() });
298
- });
306
+ ```ts
307
+ import { useForm } from "react-hook-form";
308
+
309
+ const form = useForm<
310
+ z.input<typeof paymentFormSchema>,
311
+ unknown,
312
+ z.output<typeof paymentFormSchema>
313
+ >(paymentForm.formOptions({ defaultValues: { amount: "" } }));
299
314
  ```
300
315
 
316
+ The adapter's `useForm` infers these automatically. Submit the callback's values
317
+ instead of rereading mutable field state through `getValues()`.
318
+
301
319
  ## Standard Schema support
302
320
 
303
321
  This package uses the `@hookform/resolvers/standard-schema` resolver, which works with any Standard Schema compatible library:
package/dist/index.d.ts CHANGED
@@ -1,77 +1,135 @@
1
1
  import { type ErrorMessageOverrides } from "@beignet/core/client";
2
2
  import { type ContractLike, type HttpContractConfig, type InferInput, type InferOutput, type ResolveContract, type StandardSchemaV1 } from "@beignet/core/contracts";
3
- import { type FieldValues, type UseFormProps, type UseFormReturn } from "react-hook-form";
3
+ import { type FieldValues, type Resolver, type UseFormProps, type UseFormReturn } from "react-hook-form";
4
4
  /**
5
5
  * Keep only object-shaped React Hook Form field values. Arrays are objects in
6
6
  * JavaScript, but they do not define the named field-value record expected by
7
7
  * this adapter.
8
8
  */
9
9
  type ObjectFieldValues<T> = [T] extends [FieldValues] ? Extract<T, readonly unknown[]> extends never ? T : never : never;
10
- /**
11
- * Live form field values inferred from the contract body schema input.
12
- *
13
- * React Hook Form field values (`register`, `watch`, `setValue`,
14
- * `defaultValues`) hold pre-validation input, so coercing or transforming body
15
- * schemas type fields as what the user edits, not what the schema produces.
16
- */
17
- type FormInput<TContract extends HttpContractConfig> = TContract["body"] extends StandardSchemaV1 ? ObjectFieldValues<InferInput<TContract["body"]>> : never;
18
- /**
19
- * Validated submit values inferred from the contract body schema output.
20
- *
21
- * `handleSubmit` callbacks receive the resolver-parsed output.
22
- */
23
- type FormOutput<TContract extends HttpContractConfig> = TContract["body"] extends StandardSchemaV1 ? InferOutput<TContract["body"]> : never;
24
- /**
25
- * Contract input accepted by the React Hook Form adapter.
26
- */
27
- type ReactHookFormContract<TContractLike extends ContractLike> = [
28
- FormInput<ResolveContract<TContractLike>>
29
- ] extends [never] ? never : TContractLike;
30
- /**
31
- * React Hook Form options accepted by the Beignet adapter.
32
- */
33
- type RhfFormOptions<TContract extends HttpContractConfig> = Omit<UseFormProps<FormInput<TContract>, unknown, FormOutput<TContract>>, "resolver"> & {
34
- /**
35
- * Optional override for the resolver. If supplied, this is used instead of
36
- * the default contract-based resolver.
37
- */
38
- resolver?: UseFormProps<FormInput<TContract>, unknown, FormOutput<TContract>>["resolver"];
39
- /**
40
- * Enables or disables automatic resolver generation from the contract body schema.
41
- * Defaults to true.
42
- */
10
+ /** Live fields and defaults use the selected schema's input. */
11
+ type FormInput<S extends StandardSchemaV1> = ObjectFieldValues<InferInput<S>>;
12
+ /** Parsed submissions use the selected schema's output. */
13
+ type FormOutput<S extends StandardSchemaV1> = InferOutput<S>;
14
+ type BodySchema<C extends HttpContractConfig> = Extract<C["body"], StandardSchemaV1>;
15
+ type ReactHookFormContract<T extends ContractLike> = [
16
+ FormInput<BodySchema<ResolveContract<T>>>
17
+ ] extends [never] ? never : T;
18
+ /** A form-specific schema produces the request input accepted by the contract. */
19
+ type CompatibleFormSchema<C extends HttpContractConfig, S extends StandardSchemaV1> = [BodySchema<C>] extends [never] ? never : [FormInput<S>] extends [never] ? never : [FormOutput<S>] extends [InferInput<BodySchema<C>>] ? S : never;
20
+ type RhfFormOptions<S extends StandardSchemaV1, Output> = Omit<UseFormProps<FormInput<S>, unknown, Output>, "resolver">;
21
+ type ParsedFormOptions<S extends StandardSchemaV1> = RhfFormOptions<S, FormOutput<S>> & {
22
+ /** Submit parsed schema output. Default: parsed. Requires the generated resolver. */
23
+ submitValues?: "parsed";
24
+ resolver?: undefined;
25
+ /** Generate the schema resolver. Default: true. */
26
+ resolverEnabled?: true;
27
+ };
28
+ type RawFormOptions<S extends StandardSchemaV1> = RhfFormOptions<S, FormInput<S>> & {
29
+ /** Validate with the selected schema and submit original input. */
30
+ submitValues: "raw";
31
+ resolver?: undefined;
43
32
  resolverEnabled?: boolean;
44
33
  };
45
- /**
46
- * React Hook Form adapter methods for one compatible contract.
47
- */
48
- type ReactHookFormContractAdapterShape<TContract extends HttpContractConfig> = {
49
- /**
50
- * Generate `UseFormProps` for any React Hook Form usage.
51
- */
52
- formOptions: (props?: RhfFormOptions<TContract>) => UseFormProps<FormInput<TContract>, unknown, FormOutput<TContract>>;
53
- /**
54
- * Convenience wrapper around `useForm(formOptions(props))`.
55
- */
56
- useForm: (props?: RhfFormOptions<TContract>) => UseFormReturn<FormInput<TContract>, unknown, FormOutput<TContract>>;
34
+ type DisabledFormOptions<S extends StandardSchemaV1> = RhfFormOptions<S, FormInput<S>> & {
35
+ resolverEnabled: false;
36
+ resolver?: undefined;
37
+ submitValues?: "raw";
38
+ };
39
+ type VariableFormOptions<S extends StandardSchemaV1> = RhfFormOptions<S, FormInput<S> | FormOutput<S>> & {
40
+ resolver?: undefined;
41
+ } & ({
42
+ submitValues?: "raw" | "parsed" | undefined;
43
+ resolverEnabled?: true;
44
+ } | {
45
+ submitValues?: "raw";
46
+ resolverEnabled?: boolean | undefined;
47
+ });
48
+ type CustomFormOptions<S extends StandardSchemaV1, Output> = RhfFormOptions<S, Output> & {
49
+ /** A custom resolver owns its submit output, independently of the schema. */
50
+ resolver: Resolver<FormInput<S>, unknown, Output>;
51
+ resolverEnabled?: boolean;
52
+ submitValues?: never;
53
+ };
54
+ type OptionalResolverFormOptions<S extends StandardSchemaV1, Output> = RhfFormOptions<S, Output> & {
55
+ resolver?: Resolver<FormInput<S>, unknown, Output> | undefined;
56
+ resolverEnabled?: boolean | undefined;
57
+ submitValues?: never;
58
+ };
59
+ type SuppliedResolverFormOptions<S extends StandardSchemaV1, Output> = OptionalResolverFormOptions<S, Output> & {
60
+ resolver: Resolver<FormInput<S>, unknown, Output> | undefined;
61
+ };
62
+ /** An absent override falls back to schema parsing unless generation is disabled. */
63
+ type ResolverFallbackOutput<S extends StandardSchemaV1, Props> = Props extends {
64
+ resolverEnabled: false;
65
+ } ? FormInput<S> : Props extends {
66
+ resolverEnabled?: infer Enabled;
67
+ } ? false extends Enabled ? FormInput<S> | FormOutput<S> : FormOutput<S> : FormOutput<S>;
68
+ type ResolverSubmitOutput<S extends StandardSchemaV1, Output, Props> = Props extends {
69
+ resolver: undefined;
70
+ } ? ResolverFallbackOutput<S, Props> : Props extends {
71
+ resolver: Resolver<FormInput<S>, unknown, Output>;
72
+ } ? Output : Output | ResolverFallbackOutput<S, Props>;
73
+ type ConditionalFormOptions<S extends StandardSchemaV1> = ParsedFormOptions<S> | RawFormOptions<S> | DisabledFormOptions<S> | VariableFormOptions<S> | OptionalResolverFormOptions<S, unknown>;
74
+ type GeneratedSubmitOutput<S extends StandardSchemaV1, Props> = Props extends {
75
+ submitValues: "raw";
76
+ } | {
77
+ resolverEnabled: false;
78
+ } ? FormInput<S> : Props extends {
79
+ submitValues?: infer Mode;
80
+ } ? "raw" extends Mode ? FormInput<S> | ResolverFallbackOutput<S, Props> : ResolverFallbackOutput<S, Props> : ResolverFallbackOutput<S, Props>;
81
+ type CustomSubmitOutput<S extends StandardSchemaV1, R> = R extends Resolver<FormInput<S>, unknown, infer Output> ? Output : never;
82
+ /** Distribute over configurations so each branch contributes only its own output. */
83
+ type ConditionalSubmitOutput<S extends StandardSchemaV1, Props> = Props extends undefined ? FormOutput<S> : Props extends {
84
+ resolver: infer R;
85
+ } ? undefined extends R ? CustomSubmitOutput<S, R> | GeneratedSubmitOutput<S, Props> : CustomSubmitOutput<S, R> : Props extends {
86
+ resolver?: infer R;
87
+ } ? CustomSubmitOutput<S, R> | GeneratedSubmitOutput<S, Props> : GeneratedSubmitOutput<S, Props>;
88
+ type SuppliedFormProps<Props> = undefined extends Props ? Partial<Exclude<Props, undefined>> : Props;
89
+ type FormOptions<Input extends FieldValues, Output, Props> = Omit<Props, "resolver" | "resolverEnabled" | "submitValues"> & Pick<UseFormProps<Input, unknown, Output>, "resolver">;
90
+ /** React Hook Form methods for the selected form schema. */
91
+ type ReactHookFormContractAdapterShape<S extends StandardSchemaV1> = {
92
+ /** Generate options for React Hook Form or a wrapper. */
93
+ formOptions: {
94
+ (props?: undefined): FormOptions<FormInput<S>, FormOutput<S>, Record<never, never>>;
95
+ <Output, Props extends SuppliedResolverFormOptions<S, Output>>(props: SuppliedResolverFormOptions<S, Output> & Props): FormOptions<FormInput<S>, ResolverSubmitOutput<S, Output, Props>, Props>;
96
+ <Props extends RawFormOptions<S> | DisabledFormOptions<S>>(props: Props): FormOptions<FormInput<S>, FormInput<S>, Props>;
97
+ <Props extends ParsedFormOptions<S>>(props: Props): FormOptions<FormInput<S>, FormOutput<S>, Props>;
98
+ <Props extends VariableFormOptions<S>>(props: Props): FormOptions<FormInput<S>, FormInput<S> | FormOutput<S>, Props>;
99
+ <Output, Props extends OptionalResolverFormOptions<S, Output>>(props: OptionalResolverFormOptions<S, Output> & Props): FormOptions<FormInput<S>, Output | ResolverFallbackOutput<S, Props>, Props>;
100
+ <Props extends ParsedFormOptions<S>>(props?: Props): FormOptions<FormInput<S>, FormOutput<S>, Partial<Props>>;
101
+ <Props extends VariableFormOptions<S>>(props: Props | undefined): FormOptions<FormInput<S>, FormInput<S> | FormOutput<S>, Partial<Props>>;
102
+ <Output, Props extends OptionalResolverFormOptions<S, Output>>(props: (OptionalResolverFormOptions<S, Output> & Props) | undefined): FormOptions<FormInput<S>, ResolverSubmitOutput<S, Output, Props> | FormOutput<S>, Partial<Props>>;
103
+ <Props extends ConditionalFormOptions<S> | undefined>(props: Props): FormOptions<FormInput<S>, ConditionalSubmitOutput<S, Props>, SuppliedFormProps<Props>>;
104
+ };
105
+ /** Convenience wrapper around useForm(formOptions(props)). */
106
+ useForm: {
107
+ <Output>(props: CustomFormOptions<S, Output>): UseFormReturn<FormInput<S>, unknown, Output>;
108
+ (props: RawFormOptions<S> | DisabledFormOptions<S>): UseFormReturn<FormInput<S>, unknown, FormInput<S>>;
109
+ (props?: ParsedFormOptions<S>): UseFormReturn<FormInput<S>, unknown, FormOutput<S>>;
110
+ (props?: VariableFormOptions<S>): UseFormReturn<FormInput<S>, unknown, FormInput<S> | FormOutput<S>>;
111
+ <Output, Props extends OptionalResolverFormOptions<S, Output>>(props: OptionalResolverFormOptions<S, Output> & Props): UseFormReturn<FormInput<S>, unknown, Output | ResolverFallbackOutput<S, Props>>;
112
+ <Output, Props extends OptionalResolverFormOptions<S, Output>>(props: (OptionalResolverFormOptions<S, Output> & Props) | undefined): UseFormReturn<FormInput<S>, unknown, ResolverSubmitOutput<S, Output, Props> | FormOutput<S>>;
113
+ <Props extends ConditionalFormOptions<S> | undefined>(props: Props): UseFormReturn<FormInput<S>, unknown, ConditionalSubmitOutput<S, Props>>;
114
+ };
57
115
  };
58
116
  /**
59
- * React Hook Form adapter for one contract whose body schema input is
60
- * object-shaped.
117
+ * Adapter for a contract body, optionally using a separate form schema.
118
+ * The selected schema must have object-shaped input for named form fields.
61
119
  */
62
- export type ReactHookFormContractAdapter<TContract extends HttpContractConfig> = [
63
- FormInput<TContract>
64
- ] extends [never] ? never : ReactHookFormContractAdapterShape<TContract>;
120
+ export type ReactHookFormContractAdapter<TContract extends HttpContractConfig, TSchema extends StandardSchemaV1 = BodySchema<TContract>> = [BodySchema<TContract>] extends [never] ? never : [FormInput<TSchema>] extends [never] ? never : ReactHookFormContractAdapterShape<TSchema>;
65
121
  /**
66
- * Create a React Hook Form adapter factory.
67
- *
68
- * Mirrors the React integration pattern used by `createReactQuery()` and `createNuqs()`:
69
- * create the adapter once, then bind individual contracts with `rhf(contract)`.
70
- * Contracts must declare a body schema whose input is object-shaped. After
71
- * binding, callers may override or disable the generated resolver through
72
- * `formOptions(...)` or `useForm(...)`.
122
+ * Create a React Hook Form adapter factory. Bind a contract with rhf(contract),
123
+ * or pass { schema } when the form's input differs from the request body.
124
+ * A separate schema must have object-shaped input and output assignable to the
125
+ * contract body input. Parsed submissions are the default; raw mode is opt-in.
73
126
  */
74
- export declare function createReactHookForm(): <TContractLike extends ContractLike>(contract: ReactHookFormContract<TContractLike>) => ReactHookFormContractAdapter<ResolveContract<TContractLike>>;
127
+ export declare function createReactHookForm(): {
128
+ <TContractLike extends ContractLike>(contract: ReactHookFormContract<TContractLike>): ReactHookFormContractAdapter<ResolveContract<TContractLike>>;
129
+ <TContractLike extends ContractLike, TSchema extends StandardSchemaV1>(contract: TContractLike, options: {
130
+ schema: CompatibleFormSchema<ResolveContract<TContractLike>, TSchema>;
131
+ }): ReactHookFormContractAdapter<ResolveContract<TContractLike>, TSchema>;
132
+ };
75
133
  /**
76
134
  * Root-level form error for `form.setError("root", ...)`.
77
135
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -3,22 +3,42 @@ import { contractErrorMessage, } from "@beignet/core/client";
3
3
  import { resolveContract, } from "@beignet/core/contracts";
4
4
  import { standardSchemaResolver } from "@hookform/resolvers/standard-schema";
5
5
  import { useForm as rhfUseForm, } from "react-hook-form";
6
- function createReactHookFormAdapter(contract) {
6
+ import { snapshotInput } from "./input-snapshot.js";
7
+ function createReactHookFormAdapter(contract, schema) {
7
8
  const resolvedContract = resolveContract(contract);
8
9
  if (!resolvedContract.body) {
9
10
  throw new Error(`rhf(${resolvedContract.name}): Contract has no body schema. ` +
10
11
  "React Hook Form requires a body schema to generate form fields and validation. " +
11
12
  "Use .body(schema) on the contract builder to define the request body shape.");
12
13
  }
14
+ const formSchema = (schema ?? resolvedContract.body);
13
15
  function formOptions(props) {
14
- const bodySchema = resolvedContract.body;
15
- const { resolverEnabled = true, resolver: resolverOverride, ...rest } = props ?? {};
16
- const resolver = resolverOverride ??
17
- (resolverEnabled
18
- ? standardSchemaResolver(bodySchema)
19
- : undefined);
16
+ const { resolverEnabled = true, resolver: resolverOverride, submitValues = "parsed", ...rest } = props ?? {};
17
+ if (resolverOverride && props?.submitValues !== undefined) {
18
+ throw new Error(`rhf(${resolvedContract.name}): A custom resolver owns its submit values; omit submitValues.`);
19
+ }
20
+ if (props?.submitValues === "parsed" &&
21
+ !resolverEnabled &&
22
+ !resolverOverride) {
23
+ throw new Error(`rhf(${resolvedContract.name}): Parsed submit values require the generated resolver.`);
24
+ }
25
+ let resolver = resolverOverride;
26
+ if (!resolver && resolverEnabled) {
27
+ const generated = submitValues === "parsed"
28
+ ? standardSchemaResolver(formSchema)
29
+ : standardSchemaResolver(formSchema, undefined, { raw: true });
30
+ resolver = async (values, context, options) => {
31
+ // Capture data containers before asynchronous validation.
32
+ const snapshot = snapshotInput(values);
33
+ const result = await generated(submitValues === "raw" ? snapshotInput(snapshot) : snapshot, context, options);
34
+ return submitValues === "raw" && Object.keys(result.errors).length === 0
35
+ ? { errors: {}, values: snapshot }
36
+ : result;
37
+ };
38
+ }
20
39
  return {
21
40
  ...rest,
41
+ // RHF merges options on rerender; an explicit undefined clears an old resolver.
22
42
  resolver,
23
43
  };
24
44
  }
@@ -29,18 +49,16 @@ function createReactHookFormAdapter(contract) {
29
49
  return { formOptions, useForm };
30
50
  }
31
51
  /**
32
- * Create a React Hook Form adapter factory.
33
- *
34
- * Mirrors the React integration pattern used by `createReactQuery()` and `createNuqs()`:
35
- * create the adapter once, then bind individual contracts with `rhf(contract)`.
36
- * Contracts must declare a body schema whose input is object-shaped. After
37
- * binding, callers may override or disable the generated resolver through
38
- * `formOptions(...)` or `useForm(...)`.
52
+ * Create a React Hook Form adapter factory. Bind a contract with rhf(contract),
53
+ * or pass { schema } when the form's input differs from the request body.
54
+ * A separate schema must have object-shaped input and output assignable to the
55
+ * contract body input. Parsed submissions are the default; raw mode is opt-in.
39
56
  */
40
57
  export function createReactHookForm() {
41
- return function rhf(contract) {
42
- return createReactHookFormAdapter(contract);
43
- };
58
+ function rhf(contract, options) {
59
+ return createReactHookFormAdapter(contract, options?.schema);
60
+ }
61
+ return rhf;
44
62
  }
45
63
  /**
46
64
  * Map a failed endpoint call or mutation error to a root-level form error.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EACL,oBAAoB,GAErB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAML,eAAe,GAEhB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAEL,OAAO,IAAI,UAAU,GAGtB,MAAM,iBAAiB,CAAC;AAmGzB,SAAS,0BAA0B,CACjC,QAA8C;IAE9C,MAAM,gBAAgB,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAEnD,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,OAAO,gBAAgB,CAAC,IAAI,kCAAkC;YAC5D,iFAAiF;YACjF,6EAA6E,CAChF,CAAC;IACJ,CAAC;IAKD,SAAS,WAAW,CAClB,KAAsD;QAEtD,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAuC,CAAC;QAE5E,MAAM,EACJ,eAAe,GAAG,IAAI,EACtB,QAAQ,EAAE,gBAAgB,EAC1B,GAAG,IAAI,EACR,GAAG,KAAK,IAAI,EAAE,CAAC;QAEhB,MAAM,QAAQ,GACZ,gBAAgB;YAChB,CAAC,eAAe;gBACd,CAAC,CAAC,sBAAsB,CAAyB,UAAU,CAAC;gBAC5D,CAAC,CAAC,SAAS,CAAC,CAAC;QAEjB,OAAO;YACL,GAAI,IAA6C;YACjD,QAAQ;SACT,CAAC;IACJ,CAAC;IAED,SAAS,OAAO,CACd,KAAsD;QAEtD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QACnC,OAAO,UAAU,CAAyB,OAAO,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;AAClC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,SAAS,GAAG,CACjB,QAA8C;QAE9C,OAAO,0BAA0B,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC,CAAC;AACJ,CAAC;AAUD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAC3B,KAAc,EACd,QAAgB,EAChB,SAAiC;IAEjC,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC;KAC1D,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Snapshot data containers without manufacturing invalid copies of opaque
3
+ * instances (which may depend on private fields or native internal slots).
4
+ * Opaque instances and functions remain references and must be treated as immutable.
5
+ */
6
+ export declare function snapshotInput<T>(input: T): T;
7
+ //# sourceMappingURL=input-snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-snapshot.d.ts","sourceRoot":"","sources":["../src/input-snapshot.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAoC5C"}