react-f0rm 1.4.0 → 1.5.0

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 (84) hide show
  1. package/README.md +17 -4
  2. package/dist/array-Bu7W8BSz.d.ts +54 -0
  3. package/dist/devtools/index.cjs.js +1 -1
  4. package/dist/devtools/index.cjs.js.map +1 -1
  5. package/dist/devtools/index.d.cts +8 -18
  6. package/dist/devtools/index.d.mts +8 -18
  7. package/dist/devtools/index.d.ts +8 -18
  8. package/dist/devtools/index.mjs +1 -1
  9. package/dist/devtools/index.mjs.map +1 -1
  10. package/dist/errors-DA4ReEd9.mjs +2 -0
  11. package/dist/errors-DA4ReEd9.mjs.map +1 -0
  12. package/dist/errors-TzyWwBfw.cjs.js +2 -0
  13. package/dist/errors-TzyWwBfw.cjs.js.map +1 -0
  14. package/dist/index.cjs.js +1 -1
  15. package/dist/index.cjs.js.map +1 -1
  16. package/dist/index.d.cts +347 -927
  17. package/dist/index.d.mts +347 -927
  18. package/dist/index.d.ts +347 -927
  19. package/dist/index.mjs +1 -1
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/index.umd.js +538 -451
  22. package/dist/index.umd.js.map +1 -1
  23. package/dist/index.umd.min.js +2 -2
  24. package/dist/index.umd.min.js.map +1 -1
  25. package/dist/persist.cjs.js +1 -1
  26. package/dist/persist.cjs.js.map +1 -1
  27. package/dist/persist.d.cts +9 -30
  28. package/dist/persist.d.mts +9 -30
  29. package/dist/persist.d.ts +9 -30
  30. package/dist/persist.mjs +1 -1
  31. package/dist/persist.mjs.map +1 -1
  32. package/dist/resolvers/standard-schema.cjs.js +1 -1
  33. package/dist/resolvers/standard-schema.d.cts +1 -1
  34. package/dist/resolvers/standard-schema.d.mts +1 -1
  35. package/dist/resolvers/standard-schema.d.ts +1 -1
  36. package/dist/resolvers/standard-schema.mjs +1 -1
  37. package/dist/resolvers/yup.cjs.js +1 -1
  38. package/dist/resolvers/yup.mjs +1 -1
  39. package/dist/resolvers/zod.cjs.js +1 -1
  40. package/dist/resolvers/zod.cjs.js.map +1 -1
  41. package/dist/resolvers/zod.d.cts +30 -2
  42. package/dist/resolvers/zod.d.mts +30 -2
  43. package/dist/resolvers/zod.d.ts +30 -2
  44. package/dist/resolvers/zod.mjs +1 -1
  45. package/dist/resolvers/zod.mjs.map +1 -1
  46. package/dist/server/index.cjs.js +1 -1
  47. package/dist/server/index.cjs.js.map +1 -1
  48. package/dist/server/index.d.cts +24 -92
  49. package/dist/server/index.d.mts +24 -92
  50. package/dist/server/index.d.ts +24 -92
  51. package/dist/server/index.mjs +1 -1
  52. package/dist/server/index.mjs.map +1 -1
  53. package/dist/standard-schema-BAaTmAHh.d.ts +682 -0
  54. package/dist/standardSchema-5WezjHlp.mjs +2 -0
  55. package/dist/standardSchema-5WezjHlp.mjs.map +1 -0
  56. package/dist/standardSchema-DINHlsYR.cjs.js +2 -0
  57. package/dist/standardSchema-DINHlsYR.cjs.js.map +1 -0
  58. package/dist/validate-2pX-N1O6.cjs.js +2 -0
  59. package/dist/validate-2pX-N1O6.cjs.js.map +1 -0
  60. package/dist/validate-C0HOsP9v.mjs +2 -0
  61. package/dist/validate-C0HOsP9v.mjs.map +1 -0
  62. package/dist/values-BbPnLByD.cjs.js +2 -0
  63. package/dist/values-BbPnLByD.cjs.js.map +1 -0
  64. package/dist/values-CHsmcZk4.mjs +2 -0
  65. package/dist/values-CHsmcZk4.mjs.map +1 -0
  66. package/package.json +6 -4
  67. package/dist/array-3hAjl6Bz.d.ts +0 -160
  68. package/dist/errors-8oPux7GR.cjs.js +0 -2
  69. package/dist/errors-8oPux7GR.cjs.js.map +0 -1
  70. package/dist/errors-ClH3eV1R.mjs +0 -2
  71. package/dist/errors-ClH3eV1R.mjs.map +0 -1
  72. package/dist/standard-schema-CYbnugL7.d.ts +0 -1184
  73. package/dist/standardSchema-BpZvg0tZ.mjs +0 -2
  74. package/dist/standardSchema-BpZvg0tZ.mjs.map +0 -1
  75. package/dist/standardSchema-CxV_DhBO.cjs.js +0 -2
  76. package/dist/standardSchema-CxV_DhBO.cjs.js.map +0 -1
  77. package/dist/validate-BEjNsNvd.mjs +0 -2
  78. package/dist/validate-BEjNsNvd.mjs.map +0 -1
  79. package/dist/validate-BvN6hiEG.cjs.js +0 -2
  80. package/dist/validate-BvN6hiEG.cjs.js.map +0 -1
  81. package/dist/values-Bod74Kzu.mjs +0 -2
  82. package/dist/values-Bod74Kzu.mjs.map +0 -1
  83. package/dist/values-DKpOCD5J.cjs.js +0 -2
  84. package/dist/values-DKpOCD5J.cjs.js.map +0 -1
@@ -1,105 +1,37 @@
1
1
  import { FieldErrorEntry, Options } from '../index.js';
2
- export { b as VALIDATION_OUTCOME, c as ValidationOutcome } from '../standard-schema-CYbnugL7.js';
3
- export { a as appendValue, i as insertValue, m as moveValue, p as prependValue, r as removeValue, b as replaceValues, s as swapValues, u as updateValue } from '../array-3hAjl6Bz.js';
2
+ export { c as VALIDATION_OUTCOME, d as ValidationOutcome } from '../standard-schema-BAaTmAHh.js';
3
+ export { a as appendValue, i as insertValue, m as moveValue, p as prependValue, r as removeValue, b as replaceValues, s as swapValues, u as updateValue } from '../array-Bu7W8BSz.js';
4
4
  import '@for-fun/event-emitter';
5
5
 
6
- /** The outcome of {@link validateValues}: the error-free flag, the values
7
- * once the round has landed (schema-coerced where the validator produced
8
- * parsed values), and every error the round wrote as flat entries. */
6
+ /** The outcome of {@link validateValues}: `valid`, the (schema-coerced)
7
+ * values, and the round's flat error entries. */
9
8
  type ValidateValuesResult<T extends Record<string, any> = any> = {
10
- /** Whether the round landed no errors `trigger`'s boolean. An invalid
11
- * payload is a normal outcome, never a rejection: unlike
12
- * `ensureValidate`, server callers learn validity from data instead of
13
- * catching, because both branches are interesting on the server
14
- * (persist vs. bounce back to the client). */
9
+ /** Whether the round landed no errors. An invalid payload is data, not
10
+ * a rejection both branches are interesting server-side. */
15
11
  valid: boolean;
16
- /** The values after the round. When the validator returned a branded
17
- * {@link ValidationOutcome} with `values`, those parsed values are the
18
- * baseline `getValues` layers over the input — schema coerce/transform
19
- * output included — so this is the tree to persist or feed onward, not
20
- * necessarily the object passed in. Deep-equals the input otherwise. */
12
+ /** The values after the round: parsed output when the validator
13
+ * returned a branded outcome, the input otherwise. */
21
14
  values: T;
22
- /** Every error the round landed, flattened to `{path, type, message}`
23
- * entries the same list {@link getErrors} hands out on the client.
24
- * Feed it to `setServerErrors` to land a failed round back on the
25
- * client form (the Server Actions bridge; see the docs' Server Actions
26
- * guide). */
15
+ /** Every error flattened to {path, type, message}; feed to
16
+ * `setServerErrors` to land it back on the client form. */
27
17
  errors: FieldErrorEntry[];
28
18
  };
29
- /**
30
- * Convert a values object into FormData the transport shape React 19
31
- * Server Actions and multipart handlers expect. Built to pair with the
32
- * `<Form action>` prop and `validateValues`: the validated (schema-coerced)
33
- * values tree lands in the server action as FormData, files included.
34
- *
35
- * Array values become multiple entries under the same key (FormData's
36
- * native multi-value convention); File values keep their name; Dates
37
- * become ISO strings; plain objects JSON.stringify; null/undefined are
38
- * skipped.
39
- */
19
+ /** Convert values into FormData (Server Actions/multipart shape). Arrays
20
+ * become multiple entries per key; Files keep names; Dates ISO; objects
21
+ * JSON.stringify; null/undefined skipped. */
40
22
  declare function formDataFromValues(values: Record<string, any>): FormData;
41
- /**
42
- * Convert FormData back into a values object — the inverse of
43
- * {@link formDataFromValues}, covering both the shapes that function
44
- * produces and native form submits.
45
- *
46
- * Multiple entries under one key collect into an array (FormData's
47
- * multi-value convention, which {@link formDataFromValues} uses for
48
- * arrays); a single entry stays scalar. String values that look like JSON
49
- * (`{…}`, `[…]`) parse back into objects/arrays — the shape plain objects
50
- * take through {@link formDataFromValues} — while everything else stays a
51
- * string, exactly like a native form submit: scalar types round-trip
52
- * through String() (numbers, booleans, ISO dates), so let a schema coerce
53
- * them back (`z.coerce.number()` style). File values pass through
54
- * unchanged; keys missing from the FormData are omitted, matching the
55
- * null/undefined skipping {@link formDataFromValues} does.
56
- *
57
- * Pairs with {@link validateValues} to close the Server Action loop
58
- * without hand-rolled `.get()` calls:
59
- *
60
- * export async function register(formData: FormData) {
61
- * const result = await validateValues(valuesFromFormData(formData), {
62
- * validate: standardSchemaFormValidator(schema)
63
- * });
64
- * if (!result.valid) return {errors: result.errors};
65
- * await db.insert(result.values);
66
- * }
67
- */
23
+ /** Convert FormData back into a values object — the inverse of
24
+ * {@link formDataFromValues}. Multiple entries under a key collect into
25
+ * an array, JSON-looking strings parse back, Files pass through, and
26
+ * missing keys are omitted. */
68
27
  declare function valuesFromFormData(formData: FormData): Record<string, any>;
69
- /**
70
- * Validate a payload of values on the server no form instance, no
71
- * React.
72
- *
73
- * Spins up a throwaway form from `options` (with `initialValues` forced
74
- * to `values`), runs one whole-form `trigger`, and reads the outcome
75
- * back. `trigger` never rejects and waits out async validators and any
76
- * `validateDebounce` window, so a single `await` drains the whole round —
77
- * the returned `valid`/`errors` are final, not a snapshot mid-flight.
78
- *
79
- * Validation comes from `options.validate` — the form-level validator.
80
- * Field validators register through mounted fields (`useField`), and
81
- * nothing is mounted on the server, so they cannot participate by
82
- * construction; pass a schema-backed form validator
83
- * (`standardSchemaFormValidator(schema)` from
84
- * `react-f0rm/resolvers/standard-schema`) or a hand-written `validate`
85
- * instead. `mode`/`reValidateMode` are equally inert here — there are no
86
- * field events to gate — and may be omitted.
87
- *
88
- * When the validator returns a branded {@link ValidationOutcome} whose
89
- * `values` carry the schema's output, those parsed values become the
90
- * form's parsedValues baseline, so `result.values` flows coercion and
91
- * transforms forward (`z.coerce.number()` turning `'42'` into `42`, and
92
- * friends). Persist that tree; on the client the same schema round runs
93
- * again on submit, keeping one validation source across the boundary.
94
- *
95
- * Safe to call from Node, Server Actions and RSC — the module graph is
96
- * this file plus the pure core, zero React.
97
- *
98
- * @param values the payload to validate; becomes the form's initialValues
99
- * @param options form options; `validate` is where the rules come from
100
- * @return the settled round: `valid`, the (possibly parsed) values, and
101
- * the flat error entries
102
- */
28
+ /** Validate a payload server-side — no form instance, no React. Spins up
29
+ * a throwaway form from `options` (initialValues forced to `values`),
30
+ * runs one whole-form `trigger`, and reads the settled round back (a
31
+ * single await drains async validators and debounce windows). Field
32
+ * validators can't participate (nothing is mounted); pass a form-level
33
+ * schema validator. A branded outcome's parsed values become the baseline
34
+ * `getValues` layers over. Safe in Node, Server Actions and RSC. */
103
35
  declare function validateValues<T extends Record<string, any> = any>(values: T, options?: Options<T>): Promise<ValidateValuesResult<T>>;
104
36
 
105
37
  export { formDataFromValues, validateValues, valuesFromFormData };
@@ -1,105 +1,37 @@
1
1
  import { FieldErrorEntry, Options } from '../index.js';
2
- export { b as VALIDATION_OUTCOME, c as ValidationOutcome } from '../standard-schema-CYbnugL7.js';
3
- export { a as appendValue, i as insertValue, m as moveValue, p as prependValue, r as removeValue, b as replaceValues, s as swapValues, u as updateValue } from '../array-3hAjl6Bz.js';
2
+ export { c as VALIDATION_OUTCOME, d as ValidationOutcome } from '../standard-schema-BAaTmAHh.js';
3
+ export { a as appendValue, i as insertValue, m as moveValue, p as prependValue, r as removeValue, b as replaceValues, s as swapValues, u as updateValue } from '../array-Bu7W8BSz.js';
4
4
  import '@for-fun/event-emitter';
5
5
 
6
- /** The outcome of {@link validateValues}: the error-free flag, the values
7
- * once the round has landed (schema-coerced where the validator produced
8
- * parsed values), and every error the round wrote as flat entries. */
6
+ /** The outcome of {@link validateValues}: `valid`, the (schema-coerced)
7
+ * values, and the round's flat error entries. */
9
8
  type ValidateValuesResult<T extends Record<string, any> = any> = {
10
- /** Whether the round landed no errors `trigger`'s boolean. An invalid
11
- * payload is a normal outcome, never a rejection: unlike
12
- * `ensureValidate`, server callers learn validity from data instead of
13
- * catching, because both branches are interesting on the server
14
- * (persist vs. bounce back to the client). */
9
+ /** Whether the round landed no errors. An invalid payload is data, not
10
+ * a rejection both branches are interesting server-side. */
15
11
  valid: boolean;
16
- /** The values after the round. When the validator returned a branded
17
- * {@link ValidationOutcome} with `values`, those parsed values are the
18
- * baseline `getValues` layers over the input — schema coerce/transform
19
- * output included — so this is the tree to persist or feed onward, not
20
- * necessarily the object passed in. Deep-equals the input otherwise. */
12
+ /** The values after the round: parsed output when the validator
13
+ * returned a branded outcome, the input otherwise. */
21
14
  values: T;
22
- /** Every error the round landed, flattened to `{path, type, message}`
23
- * entries the same list {@link getErrors} hands out on the client.
24
- * Feed it to `setServerErrors` to land a failed round back on the
25
- * client form (the Server Actions bridge; see the docs' Server Actions
26
- * guide). */
15
+ /** Every error flattened to {path, type, message}; feed to
16
+ * `setServerErrors` to land it back on the client form. */
27
17
  errors: FieldErrorEntry[];
28
18
  };
29
- /**
30
- * Convert a values object into FormData the transport shape React 19
31
- * Server Actions and multipart handlers expect. Built to pair with the
32
- * `<Form action>` prop and `validateValues`: the validated (schema-coerced)
33
- * values tree lands in the server action as FormData, files included.
34
- *
35
- * Array values become multiple entries under the same key (FormData's
36
- * native multi-value convention); File values keep their name; Dates
37
- * become ISO strings; plain objects JSON.stringify; null/undefined are
38
- * skipped.
39
- */
19
+ /** Convert values into FormData (Server Actions/multipart shape). Arrays
20
+ * become multiple entries per key; Files keep names; Dates ISO; objects
21
+ * JSON.stringify; null/undefined skipped. */
40
22
  declare function formDataFromValues(values: Record<string, any>): FormData;
41
- /**
42
- * Convert FormData back into a values object — the inverse of
43
- * {@link formDataFromValues}, covering both the shapes that function
44
- * produces and native form submits.
45
- *
46
- * Multiple entries under one key collect into an array (FormData's
47
- * multi-value convention, which {@link formDataFromValues} uses for
48
- * arrays); a single entry stays scalar. String values that look like JSON
49
- * (`{…}`, `[…]`) parse back into objects/arrays — the shape plain objects
50
- * take through {@link formDataFromValues} — while everything else stays a
51
- * string, exactly like a native form submit: scalar types round-trip
52
- * through String() (numbers, booleans, ISO dates), so let a schema coerce
53
- * them back (`z.coerce.number()` style). File values pass through
54
- * unchanged; keys missing from the FormData are omitted, matching the
55
- * null/undefined skipping {@link formDataFromValues} does.
56
- *
57
- * Pairs with {@link validateValues} to close the Server Action loop
58
- * without hand-rolled `.get()` calls:
59
- *
60
- * export async function register(formData: FormData) {
61
- * const result = await validateValues(valuesFromFormData(formData), {
62
- * validate: standardSchemaFormValidator(schema)
63
- * });
64
- * if (!result.valid) return {errors: result.errors};
65
- * await db.insert(result.values);
66
- * }
67
- */
23
+ /** Convert FormData back into a values object — the inverse of
24
+ * {@link formDataFromValues}. Multiple entries under a key collect into
25
+ * an array, JSON-looking strings parse back, Files pass through, and
26
+ * missing keys are omitted. */
68
27
  declare function valuesFromFormData(formData: FormData): Record<string, any>;
69
- /**
70
- * Validate a payload of values on the server no form instance, no
71
- * React.
72
- *
73
- * Spins up a throwaway form from `options` (with `initialValues` forced
74
- * to `values`), runs one whole-form `trigger`, and reads the outcome
75
- * back. `trigger` never rejects and waits out async validators and any
76
- * `validateDebounce` window, so a single `await` drains the whole round —
77
- * the returned `valid`/`errors` are final, not a snapshot mid-flight.
78
- *
79
- * Validation comes from `options.validate` — the form-level validator.
80
- * Field validators register through mounted fields (`useField`), and
81
- * nothing is mounted on the server, so they cannot participate by
82
- * construction; pass a schema-backed form validator
83
- * (`standardSchemaFormValidator(schema)` from
84
- * `react-f0rm/resolvers/standard-schema`) or a hand-written `validate`
85
- * instead. `mode`/`reValidateMode` are equally inert here — there are no
86
- * field events to gate — and may be omitted.
87
- *
88
- * When the validator returns a branded {@link ValidationOutcome} whose
89
- * `values` carry the schema's output, those parsed values become the
90
- * form's parsedValues baseline, so `result.values` flows coercion and
91
- * transforms forward (`z.coerce.number()` turning `'42'` into `42`, and
92
- * friends). Persist that tree; on the client the same schema round runs
93
- * again on submit, keeping one validation source across the boundary.
94
- *
95
- * Safe to call from Node, Server Actions and RSC — the module graph is
96
- * this file plus the pure core, zero React.
97
- *
98
- * @param values the payload to validate; becomes the form's initialValues
99
- * @param options form options; `validate` is where the rules come from
100
- * @return the settled round: `valid`, the (possibly parsed) values, and
101
- * the flat error entries
102
- */
28
+ /** Validate a payload server-side — no form instance, no React. Spins up
29
+ * a throwaway form from `options` (initialValues forced to `values`),
30
+ * runs one whole-form `trigger`, and reads the settled round back (a
31
+ * single await drains async validators and debounce windows). Field
32
+ * validators can't participate (nothing is mounted); pass a form-level
33
+ * schema validator. A branded outcome's parsed values become the baseline
34
+ * `getValues` layers over. Safe in Node, Server Actions and RSC. */
103
35
  declare function validateValues<T extends Record<string, any> = any>(values: T, options?: Options<T>): Promise<ValidateValuesResult<T>>;
104
36
 
105
37
  export { formDataFromValues, validateValues, valuesFromFormData };
@@ -1,105 +1,37 @@
1
1
  import { FieldErrorEntry, Options } from '../index.js';
2
- export { b as VALIDATION_OUTCOME, c as ValidationOutcome } from '../standard-schema-CYbnugL7.js';
3
- export { a as appendValue, i as insertValue, m as moveValue, p as prependValue, r as removeValue, b as replaceValues, s as swapValues, u as updateValue } from '../array-3hAjl6Bz.js';
2
+ export { c as VALIDATION_OUTCOME, d as ValidationOutcome } from '../standard-schema-BAaTmAHh.js';
3
+ export { a as appendValue, i as insertValue, m as moveValue, p as prependValue, r as removeValue, b as replaceValues, s as swapValues, u as updateValue } from '../array-Bu7W8BSz.js';
4
4
  import '@for-fun/event-emitter';
5
5
 
6
- /** The outcome of {@link validateValues}: the error-free flag, the values
7
- * once the round has landed (schema-coerced where the validator produced
8
- * parsed values), and every error the round wrote as flat entries. */
6
+ /** The outcome of {@link validateValues}: `valid`, the (schema-coerced)
7
+ * values, and the round's flat error entries. */
9
8
  type ValidateValuesResult<T extends Record<string, any> = any> = {
10
- /** Whether the round landed no errors `trigger`'s boolean. An invalid
11
- * payload is a normal outcome, never a rejection: unlike
12
- * `ensureValidate`, server callers learn validity from data instead of
13
- * catching, because both branches are interesting on the server
14
- * (persist vs. bounce back to the client). */
9
+ /** Whether the round landed no errors. An invalid payload is data, not
10
+ * a rejection both branches are interesting server-side. */
15
11
  valid: boolean;
16
- /** The values after the round. When the validator returned a branded
17
- * {@link ValidationOutcome} with `values`, those parsed values are the
18
- * baseline `getValues` layers over the input — schema coerce/transform
19
- * output included — so this is the tree to persist or feed onward, not
20
- * necessarily the object passed in. Deep-equals the input otherwise. */
12
+ /** The values after the round: parsed output when the validator
13
+ * returned a branded outcome, the input otherwise. */
21
14
  values: T;
22
- /** Every error the round landed, flattened to `{path, type, message}`
23
- * entries the same list {@link getErrors} hands out on the client.
24
- * Feed it to `setServerErrors` to land a failed round back on the
25
- * client form (the Server Actions bridge; see the docs' Server Actions
26
- * guide). */
15
+ /** Every error flattened to {path, type, message}; feed to
16
+ * `setServerErrors` to land it back on the client form. */
27
17
  errors: FieldErrorEntry[];
28
18
  };
29
- /**
30
- * Convert a values object into FormData the transport shape React 19
31
- * Server Actions and multipart handlers expect. Built to pair with the
32
- * `<Form action>` prop and `validateValues`: the validated (schema-coerced)
33
- * values tree lands in the server action as FormData, files included.
34
- *
35
- * Array values become multiple entries under the same key (FormData's
36
- * native multi-value convention); File values keep their name; Dates
37
- * become ISO strings; plain objects JSON.stringify; null/undefined are
38
- * skipped.
39
- */
19
+ /** Convert values into FormData (Server Actions/multipart shape). Arrays
20
+ * become multiple entries per key; Files keep names; Dates ISO; objects
21
+ * JSON.stringify; null/undefined skipped. */
40
22
  declare function formDataFromValues(values: Record<string, any>): FormData;
41
- /**
42
- * Convert FormData back into a values object — the inverse of
43
- * {@link formDataFromValues}, covering both the shapes that function
44
- * produces and native form submits.
45
- *
46
- * Multiple entries under one key collect into an array (FormData's
47
- * multi-value convention, which {@link formDataFromValues} uses for
48
- * arrays); a single entry stays scalar. String values that look like JSON
49
- * (`{…}`, `[…]`) parse back into objects/arrays — the shape plain objects
50
- * take through {@link formDataFromValues} — while everything else stays a
51
- * string, exactly like a native form submit: scalar types round-trip
52
- * through String() (numbers, booleans, ISO dates), so let a schema coerce
53
- * them back (`z.coerce.number()` style). File values pass through
54
- * unchanged; keys missing from the FormData are omitted, matching the
55
- * null/undefined skipping {@link formDataFromValues} does.
56
- *
57
- * Pairs with {@link validateValues} to close the Server Action loop
58
- * without hand-rolled `.get()` calls:
59
- *
60
- * export async function register(formData: FormData) {
61
- * const result = await validateValues(valuesFromFormData(formData), {
62
- * validate: standardSchemaFormValidator(schema)
63
- * });
64
- * if (!result.valid) return {errors: result.errors};
65
- * await db.insert(result.values);
66
- * }
67
- */
23
+ /** Convert FormData back into a values object — the inverse of
24
+ * {@link formDataFromValues}. Multiple entries under a key collect into
25
+ * an array, JSON-looking strings parse back, Files pass through, and
26
+ * missing keys are omitted. */
68
27
  declare function valuesFromFormData(formData: FormData): Record<string, any>;
69
- /**
70
- * Validate a payload of values on the server no form instance, no
71
- * React.
72
- *
73
- * Spins up a throwaway form from `options` (with `initialValues` forced
74
- * to `values`), runs one whole-form `trigger`, and reads the outcome
75
- * back. `trigger` never rejects and waits out async validators and any
76
- * `validateDebounce` window, so a single `await` drains the whole round —
77
- * the returned `valid`/`errors` are final, not a snapshot mid-flight.
78
- *
79
- * Validation comes from `options.validate` — the form-level validator.
80
- * Field validators register through mounted fields (`useField`), and
81
- * nothing is mounted on the server, so they cannot participate by
82
- * construction; pass a schema-backed form validator
83
- * (`standardSchemaFormValidator(schema)` from
84
- * `react-f0rm/resolvers/standard-schema`) or a hand-written `validate`
85
- * instead. `mode`/`reValidateMode` are equally inert here — there are no
86
- * field events to gate — and may be omitted.
87
- *
88
- * When the validator returns a branded {@link ValidationOutcome} whose
89
- * `values` carry the schema's output, those parsed values become the
90
- * form's parsedValues baseline, so `result.values` flows coercion and
91
- * transforms forward (`z.coerce.number()` turning `'42'` into `42`, and
92
- * friends). Persist that tree; on the client the same schema round runs
93
- * again on submit, keeping one validation source across the boundary.
94
- *
95
- * Safe to call from Node, Server Actions and RSC — the module graph is
96
- * this file plus the pure core, zero React.
97
- *
98
- * @param values the payload to validate; becomes the form's initialValues
99
- * @param options form options; `validate` is where the rules come from
100
- * @return the settled round: `valid`, the (possibly parsed) values, and
101
- * the flat error entries
102
- */
28
+ /** Validate a payload server-side — no form instance, no React. Spins up
29
+ * a throwaway form from `options` (initialValues forced to `values`),
30
+ * runs one whole-form `trigger`, and reads the settled round back (a
31
+ * single await drains async validators and debounce windows). Field
32
+ * validators can't participate (nothing is mounted); pass a form-level
33
+ * schema validator. A branded outcome's parsed values become the baseline
34
+ * `getValues` layers over. Safe in Node, Server Actions and RSC. */
103
35
  declare function validateValues<T extends Record<string, any> = any>(values: T, options?: Options<T>): Promise<ValidateValuesResult<T>>;
104
36
 
105
37
  export { formDataFromValues, validateValues, valuesFromFormData };
@@ -1,2 +1,2 @@
1
- import{emit as e,on as t,create as n,setMaxListeners as a}from"@for-fun/event-emitter";import{h as i,s as r}from"../standardSchema-BpZvg0tZ.mjs";import{z as o,l as s,e as u,c as l,f as c,y as d}from"../errors-ClH3eV1R.mjs";export{V as VALIDATION_OUTCOME}from"../errors-ClH3eV1R.mjs";import{c as f,d as m,h as g,e as h,a as v,f as p,i as y,s as b,g as k}from"../values-Bod74Kzu.mjs";import{r as A,a as L,b as M,c as S,t as x}from"../validate-BEjNsNvd.mjs";const w=new WeakMap;function N(e,t,n,a){w.get(e)?.get(t.key)?function(e,t,n){m(e,t,n);const a=w.get(e)?.get(t.key);a&&function(e,t,n){("onChange"===n||"all"===n||"onTouched"===n&&g(e,t)||o(e,t).length>0&&"onChange"===e.reValidateMode)&&e.validators.get(t.key)?.();L(e,t,n),"onChange"===e.validateMode&&e.validate&&A(e).catch(()=>{});M(e,t,n)}(e,t,a.mode??e.mode)}(e,t,n):m(e,t,n,a)}function q(e){return void 0!==e.required||void 0!==e.min||void 0!==e.max||void 0!==e.minLength||void 0!==e.maxLength||void 0!==e.pattern||void 0!==e.validate}function O(e,t){switch(e){case"required":return"This field is required";case"min":return`Must be at least ${t}`;case"max":return`Must be at most ${t}`;case"minLength":return`Must be at least ${t} characters`;case"maxLength":return`Must be at most ${t} characters`;case"pattern":return"Invalid format";default:return"Invalid value"}}function D(e){return(t,n)=>{if(e.required&&(""===t||null==t||Array.isArray(t)&&0===t.length))return[{type:"required",message:"string"==typeof e.required?e.required:O("required")}];const a=[],i=(t,n)=>e.messages?.[t]??O(t,n);if(void 0!==e.min){const n=Number(t);!Number.isNaN(n)&&n<e.min&&a.push({type:"min",message:i("min",e.min)})}if(void 0!==e.max){const n=Number(t);!Number.isNaN(n)&&n>e.max&&a.push({type:"max",message:i("max",e.max)})}const r="string"==typeof t||Array.isArray(t);if(void 0!==e.minLength&&r&&t.length<e.minLength&&a.push({type:"minLength",message:i("minLength",e.minLength)}),void 0!==e.maxLength&&r&&t.length>e.maxLength&&a.push({type:"maxLength",message:i("maxLength",e.maxLength)}),e.pattern&&!e.pattern.value.test(t)&&a.push({type:"pattern",message:e.messages?.pattern??e.pattern.message??O("pattern")}),void 0!==e.validate){const i="function"==typeof e.validate?{validate:e.validate}:e.validate;for(const[e,r]of Object.entries(i)){const i=r(t,n);if(void 0!==i)for(const t of Array.isArray(i)?i:[i])a.push("string"==typeof t?{type:e,message:t}:{...t,type:e})}}return a.length?a:void 0}}function j(n,a,i){const r=l(a),{mode:c,shouldUnregister:d,eventToValue:g,valueAsNumber:b,valueAsDate:k,rules:L}=i??{},M=g??(e=>{const t=e?.target;return t?"file"===t.type?t.files:"checkbox"===t.type?t.checked:b?t.valueAsNumber:k?t.valueAsDate:t.value:e});let x=null,V=null,O=null,j=null,C=null,F=null;const B=a=>{if(j&&(!function(t,n,a){const{key:i}=n;a.present?m(t,n,a.value,{shouldDirty:!1}):(t.deleted.delete(i),s(t),e(t.emitter,"change",n)),a.touched&&f(t,n),a.errors&&u(t,n,a.errors)}(n,r,j),j=null),x=a,"file"!==a.type&&void 0===v(n,r)&&(p(n,r,"checkbox"===a.type?a.checked:a.value),y(n,r)),V=function(e,t,n){let a=w.get(e);a||(a=new Map,w.set(e,a));const i=a.has(t.key),r={};return a.set(t.key,{mode:n,token:r}),{token:r,displaced:i}}(n,r,c).token,L&&q(L)){const e=void 0!==L.required?D({required:L.required}):void 0,t=void 0!==L.required?{...L,required:void 0}:L;O=S(n,r,{validate:()=>q(t)?D(t):void 0,debounce:()=>0,sync:()=>e})}C=t(n.emitter,"focusError",(e,t)=>{e===r.key&&x&&"function"==typeof x.focus&&(x.focus(),t?.shouldSelect&&"function"==typeof x.select&&x.select())}),F=t(n.emitter,"change",e=>{e||(()=>{if(!x||"file"===x.type)return;const e=v(n,r),t=null==e?"":String(e);x.value!==t&&(x.value=t)})()})},T=()=>{V&&(!function(e,t,n){const a=w.get(e),i=a?.get(t.key);a&&i&&i.token===n&&a.delete(t.key)}(n,r,V),V=null),O&&(O(),O=null),C&&(C(),C=null),F&&(F(),F=null),x=null,!1!==(d??n.shouldUnregister)&&(j=function(e,t){const{key:n}=t,a={present:e.values.has(n),value:e.values.get(n),touched:e.touched.has(n),errors:e.errors.get(n)};return h(e,t),a}(n,r))};return{name:r.key,onChange:e=>N(n,r,M(e)),onBlur:()=>function(e,t){f(e,t);const n=w.get(e)?.get(t.key);if(!n)return;const a=n.mode??e.mode;("onBlur"===a||"onTouched"===a||"all"===a||o(e,t).length>0&&"onBlur"===e.reValidateMode)&&e.validators.get(t.key)?.(),"onBlur"===e.validateMode&&e.validate&&A(e).catch(()=>{})}(n,r),ref:e=>{e?B(e):T()}}}function C(e,t){const n=v(e,t);return Array.isArray(n)?n:[]}function F(e,t,n){!function(e,t,n){const a=C(e,t);m(e,t,[...a,n])}(e,l(t),n)}function B(e,t,n){!function(e,t,n){const a=C(e,t);m(e,t,[n,...a])}(e,l(t),n)}function T(e,t,n,a){return function(e,t,n,a){const i=C(e,t);return!(n<0||n>i.length||(m(e,t,[...i.slice(0,n),a,...i.slice(n)]),0))}(e,l(t),n,a)}function I(e,t,n){return function(e,t,n){const a=C(e,t),i=new Set;for(const e of Array.isArray(n)?n:[n])e>=0&&e<a.length&&i.add(e);if(0===i.size)return[];const r=[...i].sort((e,t)=>t-e);return m(e,t,a.filter((e,t)=>!i.has(t))),r}(e,l(t),n)}function U(e,t,n,a){return function(e,t,n,a){const i=C(e,t);if(n<0||n>=i.length||a<0||a>=i.length)return!1;if(n===a)return!1;const r=[...i],[o]=r.splice(n,1);return r.splice(a,0,o),m(e,t,r),!0}(e,l(t),n,a)}function $(e,t,n,a){return function(e,t,n,a){const i=C(e,t);if(n<0||n>=i.length||a<0||a>=i.length)return!1;if(n===a)return!1;const r=[...i];return[r[n],r[a]]=[r[a],r[n]],m(e,t,r),!0}(e,l(t),n,a)}function W(e,t,n){!function(e,t,n){m(e,t,[...n])}(e,l(t),n)}function z(e,t,n,a){return function(e,t,n,a){const i=C(e,t);if(n<0||n>=i.length)return!1;const r=[...i];return r[n]=a,m(e,t,r),!0}(e,l(t),n,a)}function E(e,t,n){if(null!=n)if(Array.isArray(n))for(const a of n)E(e,t,a);else if("undefined"!=typeof FileList&&n instanceof FileList)for(let a=0;a<n.length;a++)e.append(t,n.item(a));else"undefined"!=typeof File&&n instanceof File?e.append(t,n,n.name):"undefined"!=typeof Blob&&n instanceof Blob?e.append(t,n):n instanceof Date?e.append(t,n.toISOString()):e.append(t,"object"==typeof n?JSON.stringify(n):String(n))}function J(e){const t=new FormData;for(const n of Object.keys(e))E(t,n,e[n]);return t}function P(e){const t=e.trim();if(t.length>0&&(t.startsWith("{")||t.startsWith("[")))try{return JSON.parse(t)}catch{return e}return e}function _(e){const t={};for(const n of new Set(e.keys())){const a=e.getAll(n),i=e=>"undefined"!=typeof File&&e instanceof File?e:P(e);t[n]=1===a.length?i(a[0]):a.map(i)}return t}async function G(t,o){const s=function(t){const o=n();a(o,0);let s=t?.initialValues??{};"function"==typeof s&&(s=s());const u=t?.validate,d=u&&i(u)?r(u):u,f={emitter:o,...t,validate:d,mode:t?.mode??"onSubmit",reValidateMode:t?.reValidateMode??"onChange",validateMode:t?.validateMode??"onSubmit",disabled:t?.disabled??!1,validateOnMount:t?.validateOnMount??!1,asyncAlways:t?.asyncAlways??!1,shouldUseNativeValidation:t?.shouldUseNativeValidation??!0,validateDeps:t?.validateDeps?new Set(t.validateDeps.map(e=>l(e).key)):void 0,initialValues:{},values:new Map,deleted:new Set,errors:new Map,touched:new Set,validators:new Map,validating:new Set,parsedValues:void 0,isSubmitting:!1,isSubmitted:!1,submitCount:0,isSubmitSuccessful:void 0,isLoading:!1,status:void 0,register:(e,t)=>j(f,e,t)};return c(s)?(f.isLoading=!0,e(o,"loading"),Promise.resolve(s).then(t=>{b(f,t??{}),f.isLoading=!1,e(o,"loading")},t=>{f.isLoading=!1,e(o,"loading")})):f.initialValues=s,f}({...o,initialValues:t});return{valid:await x(s),values:k(s),errors:d(s)}}export{F as appendValue,J as formDataFromValues,T as insertValue,U as moveValue,B as prependValue,I as removeValue,W as replaceValues,$ as swapValues,z as updateValue,G as validateValues,_ as valuesFromFormData};
1
+ import{emit as e,on as t,create as n,setMaxListeners as r}from"@for-fun/event-emitter";import{h as i,s as o}from"../standardSchema-5WezjHlp.mjs";import{g as a,B as s,o as u,j as l,c,f as d,A as f}from"../errors-DA4ReEd9.mjs";export{V as VALIDATION_OUTCOME}from"../errors-DA4ReEd9.mjs";import{c as m,d as p,h as g,e as v,a as y,f as h,i as b,s as k,g as A}from"../values-CHsmcZk4.mjs";import{s as S,r as M,a as w,b as L,c as q,t as N}from"../validate-C0HOsP9v.mjs";const x=new WeakMap;function O(e,t,n,r){x.get(e)?.get(t.key)?function(e,t,n){p(e,t,n);const r=x.get(e)?.get(t.key);r&&function(e,t,n){D(e,t,n,"onChange",g(e,t)),w(e,t,n),j(e,"onChange"),L(e,t,n)}(e,t,r.mode??e.mode)}(e,t,n):p(e,t,n,r)}function j(e,t){e.validateMode===t&&e.validate&&M(e).catch(()=>{})}function D(e,t,n,r,i){S(n,r,i,()=>s(e,t).length>0,e.reValidateMode)&&e.validators.get(t.key)?.()}function F(e){return void 0!==e.required||void 0!==e.min||void 0!==e.max||void 0!==e.minLength||void 0!==e.maxLength||void 0!==e.pattern||void 0!==e.validate}function B(e,t){switch(e){case"required":return"This field is required";case"min":return`Must be at least ${t}`;case"max":return`Must be at most ${t}`;case"minLength":return`Must be at least ${t} characters`;case"maxLength":return`Must be at most ${t} characters`;case"pattern":return"Invalid format";default:return"Invalid value"}}function C(e,t){return"function"==typeof e?e(t):e?.replace("{bound}",String(t))}function I(e){const t=Number(e);return Number.isNaN(t)?void 0:t}function U(e){return"string"==typeof e||Array.isArray(e)?e.length:void 0}const T=[["min",I,(e,t)=>e<t],["max",I,(e,t)=>e>t],["minLength",U,(e,t)=>e<t],["maxLength",U,(e,t)=>e>t]];function $(e,t){return(n,r)=>{if(e.required&&(""===n||null==n||Array.isArray(n)&&0===n.length))return[{type:"required",message:"string"==typeof e.required?e.required:C(t?.required)??B("required")}];const i=[],o=(n,r)=>e.messages?.[n]??C(t?.[n],r)??B(n,r);for(const[t,r,a]of T){const s=e[t];if(void 0===s)continue;const u=r(n);void 0!==u&&a(u,s)&&i.push({type:t,message:o(t,s)})}if(e.pattern&&!e.pattern.value.test(n)&&i.push({type:"pattern",message:e.messages?.pattern??e.pattern.message??C(t?.pattern)??B("pattern")}),void 0!==e.validate){const t="function"==typeof e.validate?{validate:e.validate}:e.validate;for(const[e,o]of Object.entries(t)){const t=o(n,r);if(void 0!==t)for(const n of Array.isArray(t)?t:[t])i.push("string"==typeof n?{type:e,message:n}:{...n,type:e})}}return i.length?i:void 0}}function W(n,r,i){const o=c(r),{mode:s,shouldUnregister:d,eventToValue:f,valueAsNumber:g,valueAsDate:k,rules:A}=i??{},S=f??(e=>{const t=e?.target;return t?"file"===t.type?t.files:"checkbox"===t.type?t.checked:g?t.valueAsNumber:k?t.valueAsDate:t.value:e});let M=null,w=null,L=null,V=null,N=null,B=null;const C=r=>{if(V&&(!function(t,n,r){const{key:i}=n;r.present?p(t,n,r.value,{shouldDirty:!1}):(t.deleted.delete(i),u(t),e(t.emitter,"change",n)),r.touched&&m(t,n),r.errors&&l(t,n,r.errors)}(n,o,V),V=null),M=r,"file"!==r.type&&void 0===y(n,o)&&(h(n,o,"checkbox"===r.type?r.checked:r.value),b(n,o)),w=function(e,t,n){const r=a(x,e,()=>new Map),i=r.has(t.key),o={};return r.set(t.key,{mode:n,token:o}),{token:o,displaced:i}}(n,o,s).token,A&&F(A)){const{required:e,...t}=A,r=void 0!==e?$({required:e},n.messages):void 0;L=q(n,o,{validate:()=>F(t)?$(t,n.messages):void 0,debounce:()=>0,sync:()=>r})}N=t(n.emitter,"focusError",(e,t)=>{e===o.key&&M&&"function"==typeof M.focus&&(M.focus(),t?.shouldSelect&&"function"==typeof M.select&&M.select())}),B=t(n.emitter,"change",e=>{e||(()=>{if(!M||"file"===M.type)return;const e=y(n,o),t=null==e?"":String(e);M.value!==t&&(M.value=t)})()})},I=()=>{w&&(!function(e,t,n){const r=x.get(e),i=r?.get(t.key);r&&i&&i.token===n&&r.delete(t.key)}(n,o,w),w=null),L&&(L(),L=null),N&&(N(),N=null),B&&(B(),B=null),M=null,!1!==(d??n.shouldUnregister)&&(V=function(e,t){const{key:n}=t,r={present:e.values.has(n),value:e.values.get(n),touched:e.touched.has(n),errors:e.errors.get(n)};return v(e,t),r}(n,o))};return{name:o.key,onChange:e=>O(n,o,S(e)),onBlur:()=>function(e,t){m(e,t);const n=x.get(e)?.get(t.key);n&&(D(e,t,n.mode??e.mode,"onBlur",!0),j(e,"onBlur"))}(n,o),ref:e=>{e?C(e):I()}}}function E(e,t){const n=y(e,t);return Array.isArray(n)?n:[]}function J(e,t,n){!function(e,t,n){const r=E(e,t);p(e,t,[...r,n])}(e,c(t),n)}function z(e,t,n){!function(e,t,n){const r=E(e,t);p(e,t,[n,...r])}(e,c(t),n)}function P(e,t,n,r){return function(e,t,n,r){const i=E(e,t);return!(n<0||n>i.length||(p(e,t,[...i.slice(0,n),r,...i.slice(n)]),0))}(e,c(t),n,r)}function _(e,t,n){return function(e,t,n){const r=E(e,t),i=new Set;for(const e of Array.isArray(n)?n:[n])e>=0&&e<r.length&&i.add(e);if(0===i.size)return[];const o=[...i].sort((e,t)=>t-e);return p(e,t,r.filter((e,t)=>!i.has(t))),o}(e,c(t),n)}function G(e,t,n,r){return function(e,t,n,r){const i=E(e,t);if(n<0||n>=i.length||r<0||r>=i.length)return!1;if(n===r)return!1;const o=[...i],[a]=o.splice(n,1);return o.splice(r,0,a),p(e,t,o),!0}(e,c(t),n,r)}function H(e,t,n,r){return function(e,t,n,r){const i=E(e,t);if(n<0||n>=i.length||r<0||r>=i.length)return!1;if(n===r)return!1;const o=[...i];return[o[n],o[r]]=[o[r],o[n]],p(e,t,o),!0}(e,c(t),n,r)}function K(e,t,n){!function(e,t,n){p(e,t,[...n])}(e,c(t),n)}function Q(e,t,n,r){return function(e,t,n,r){const i=E(e,t);if(n<0||n>=i.length)return!1;const o=[...i];return o[n]=r,p(e,t,o),!0}(e,c(t),n,r)}function R(t){const a=n();r(a,0);const s=t?.initialValues??{},u="function"==typeof s?s():s,l=t?.validate,f=l&&i(l)?o(l):l,m={emitter:a,...t,validate:f,mode:t?.mode??"onSubmit",reValidateMode:t?.reValidateMode??"onChange",validateMode:t?.validateMode??"onSubmit",disabled:t?.disabled??!1,validateOnMount:t?.validateOnMount??!1,asyncAlways:t?.asyncAlways??!1,shouldUseNativeValidation:t?.shouldUseNativeValidation??!0,validateDeps:t?.validateDeps?new Set(t.validateDeps.map(e=>c(e).key)):void 0,initialValues:{},values:new Map,deleted:new Set,errors:new Map,touched:new Set,validators:new Map,validating:new Set,parsedValues:void 0,isSubmitting:!1,isSubmitted:!1,submitCount:0,isSubmitSuccessful:void 0,isLoading:!1,status:void 0,register:(e,t)=>W(m,e,t)};return function(t,n,r){d(r)?(t.isLoading=!0,e(n,"loading"),Promise.resolve(r).then(r=>{k(t,r??{}),t.isLoading=!1,e(n,"loading")},r=>{t.isLoading=!1,e(n,"loading")})):t.initialValues=r}(m,a,u),m}function X(e,t,n){if(null!=n)if(Array.isArray(n))for(const r of n)X(e,t,r);else if("undefined"!=typeof FileList&&n instanceof FileList)for(let r=0;r<n.length;r++)e.append(t,n.item(r));else"undefined"!=typeof File&&n instanceof File?e.append(t,n,n.name):"undefined"!=typeof Blob&&n instanceof Blob?e.append(t,n):n instanceof Date?e.append(t,n.toISOString()):e.append(t,"object"==typeof n?JSON.stringify(n):String(n))}function Y(e){const t=new FormData;for(const n of Object.keys(e))X(t,n,e[n]);return t}function Z(e){return"undefined"!=typeof File&&e instanceof File?e:function(e){const t=e.trim();if(t.startsWith("{")||t.startsWith("["))try{return JSON.parse(t)}catch{return e}return e}(e)}function ee(e){const t={};for(const n of new Set(e.keys())){const r=e.getAll(n);t[n]=1===r.length?Z(r[0]):r.map(Z)}return t}async function te(e,t){const n=R({...t,initialValues:e});return{valid:await N(n),values:A(n),errors:f(n)}}export{J as appendValue,Y as formDataFromValues,P as insertValue,G as moveValue,z as prependValue,_ as removeValue,K as replaceValues,H as swapValues,Q as updateValue,te as validateValues,ee as valuesFromFormData};
2
2
  //# sourceMappingURL=index.mjs.map