Skip to content

Commit e2b0cce

Browse files
committed
Added preprocessed option to superValidate.
1 parent 11f2775 commit e2b0cce

File tree

3 files changed

+49
-15
lines changed

3 files changed

+49
-15
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ Headlines: Added, Changed, Deprecated, Removed, Fixed, Security
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Added
11+
12+
- Added `preprocessed` option to superValidate, for handling the processing of form fields manually.
13+
814
## [1.6.1] - 2023-08-22
915

1016
### Fixed

src/index.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,3 +800,21 @@ test('Passthrough validation', async () => {
800800
name: ''
801801
});
802802
});
803+
804+
test.only('Preprocessed fields', async () => {
805+
const schema = z.object({
806+
accept: z.preprocess(
807+
(val) => (val === undefined ? undefined : Boolean(val)),
808+
z.boolean().optional()
809+
)
810+
});
811+
812+
const formData = new FormData();
813+
814+
const form = await superValidate(formData, schema, {
815+
preprocessed: ['accept']
816+
});
817+
818+
assert(form.valid);
819+
expect(form.data.accept).toBeUndefined();
820+
});

src/lib/superValidate.ts

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ export function setError<T extends ZodValidation<AnyZodObject>>(
153153

154154
function formDataToValidation<T extends AnyZodObject>(
155155
data: FormData,
156-
schemaData: SchemaData<T>
156+
schemaData: SchemaData<T>,
157+
preprocessed?: string[]
157158
) {
158159
const output: Record<string, unknown> = {};
159160
const { schemaKeys, entityInfo } = schemaData;
@@ -166,8 +167,10 @@ function formDataToValidation<T extends AnyZodObject>(
166167
if (entry && typeof entry !== 'string') {
167168
// File object, not supported
168169
return undefined;
169-
} else {
170+
} else if (!preprocessed || !preprocessed.includes(key)) {
170171
return parseFormDataEntry(key, entry, typeInfo);
172+
} else {
173+
return entry;
171174
}
172175
}
173176

@@ -307,7 +310,8 @@ function dataToValidate<T extends AnyZodObject>(
307310

308311
function parseFormData<T extends AnyZodObject>(
309312
formData: FormData,
310-
schemaData: SchemaData<T>
313+
schemaData: SchemaData<T>,
314+
options?: SuperValidateOptions
311315
): ParsedData {
312316
function tryParseSuperJson() {
313317
if (formData.has('__superform_json')) {
@@ -332,14 +336,19 @@ function parseFormData<T extends AnyZodObject>(
332336
? { id, data, posted: true }
333337
: {
334338
id,
335-
data: formDataToValidation(formData, schemaData),
339+
data: formDataToValidation(
340+
formData,
341+
schemaData,
342+
options?.preprocessed
343+
),
336344
posted: true
337345
};
338346
}
339347

340348
function parseSearchParams<T extends AnyZodObject>(
341349
data: URL | URLSearchParams,
342-
schemaData: SchemaData<T>
350+
schemaData: SchemaData<T>,
351+
options?: SuperValidateOptions
343352
): ParsedData {
344353
if (data instanceof URL) data = data.searchParams;
345354

@@ -349,7 +358,7 @@ function parseSearchParams<T extends AnyZodObject>(
349358
}
350359

351360
// Only FormData can be posted.
352-
const output = parseFormData(convert, schemaData);
361+
const output = parseFormData(convert, schemaData, options);
353362
output.posted = false;
354363
return output;
355364
}
@@ -489,14 +498,15 @@ function getSchemaData<T extends AnyZodObject>(
489498

490499
/////////////////////////////////////////////////////////////////////
491500

492-
export type SuperValidateOptions = {
493-
errors?: boolean;
494-
id?: string;
495-
warnings?: {
501+
export type SuperValidateOptions = Partial<{
502+
errors: boolean;
503+
id: string;
504+
warnings: {
496505
multipleRegexps?: boolean;
497506
multipleSteps?: boolean;
498507
};
499-
};
508+
preprocessed: string[];
509+
}>;
500510

501511
export async function superValidate<
502512
T extends ZodValidation<AnyZodObject>,
@@ -563,16 +573,16 @@ export async function superValidate<
563573
// No data found, return an empty form
564574
return { id: undefined, data: undefined, posted: false };
565575
}
566-
return parseFormData(formData, schemaData);
576+
return parseFormData(formData, schemaData, options);
567577
}
568578

569579
async function parseRequest() {
570580
let parsed: ParsedData;
571581

572582
if (data instanceof FormData) {
573-
parsed = parseFormData(data, schemaData);
583+
parsed = parseFormData(data, schemaData, options);
574584
} else if (data instanceof URL || data instanceof URLSearchParams) {
575-
parsed = parseSearchParams(data, schemaData);
585+
parsed = parseSearchParams(data, schemaData, options);
576586
} else if (data instanceof Request) {
577587
parsed = await tryParseFormData(data);
578588
} else if (
@@ -656,7 +666,7 @@ export function superValidateSync<
656666

657667
const parsed =
658668
data instanceof FormData
659-
? parseFormData(data, schemaData)
669+
? parseFormData(data, schemaData, options)
660670
: data instanceof URL || data instanceof URLSearchParams
661671
? parseSearchParams(data, schemaData)
662672
: {

0 commit comments

Comments
 (0)