zod-form-data
Advanced tools
Comparing version 1.0.1 to 1.1.0
@@ -1,2 +0,2 @@ | ||
import { z, ZodArray, ZodEffects, ZodNumber, ZodString, ZodTypeAny } from "zod"; | ||
import { z, ZodArray, ZodEffects, ZodNumber, ZodObject, ZodString, ZodTypeAny } from "zod"; | ||
declare type InputType<DefaultType extends ZodTypeAny> = { | ||
@@ -12,5 +12,10 @@ (): ZodEffects<DefaultType>; | ||
export declare const checkbox: ({ trueValue }?: CheckboxOpts) => z.ZodUnion<[z.ZodEffects<z.ZodLiteral<string>, boolean, string>, z.ZodEffects<z.ZodLiteral<undefined>, boolean, undefined>]>; | ||
export declare const file: InputType<z.ZodType<File>>; | ||
export declare const repeatable: InputType<ZodArray<any>>; | ||
export declare const repeatableOfType: <T extends z.ZodTypeAny>(schema: T) => z.ZodEffects<z.ZodArray<T, "many">, T["_output"][], T["_input"][]>; | ||
export declare const formData: <T extends z.ZodRawShape>(shape: T) => z.ZodEffects<z.ZodObject<T, "strip", z.ZodTypeAny, { [k_1 in keyof z.objectUtil.addQuestionMarks<{ [k in keyof T]: T[k]["_output"]; }>]: z.objectUtil.addQuestionMarks<{ [k_2 in keyof T]: T[k_2]["_output"]; }>[k_1]; }, { [k_3 in keyof z.objectUtil.addQuestionMarks<{ [k_2 in keyof T]: T[k_2]["_input"]; }>]: z.objectUtil.addQuestionMarks<{ [k_2_1 in keyof T]: T[k_2_1]["_input"]; }>[k_3]; }>, { [k_1 in keyof z.objectUtil.addQuestionMarks<{ [k in keyof T]: T[k]["_output"]; }>]: z.objectUtil.addQuestionMarks<{ [k_2 in keyof T]: T[k_2]["_output"]; }>[k_1]; }, { [k_3 in keyof z.objectUtil.addQuestionMarks<{ [k_2 in keyof T]: T[k_2]["_input"]; }>]: z.objectUtil.addQuestionMarks<{ [k_2_1 in keyof T]: T[k_2_1]["_input"]; }>[k_3]; }>; | ||
declare type FormDataType = { | ||
<T extends z.ZodRawShape>(shape: T): ZodEffects<ZodObject<T>>; | ||
<T extends z.ZodTypeAny>(schema: T): ZodEffects<T>; | ||
}; | ||
export declare const formData: FormDataType; | ||
export {}; |
@@ -1,2 +0,2 @@ | ||
import { z } from "zod"; | ||
import { z, ZodType, } from "zod"; | ||
const stripEmpty = z.literal("").transform(() => undefined); | ||
@@ -21,2 +21,6 @@ const preprocessIfValid = (schema) => (val) => { | ||
]); | ||
export const file = (schema = z.instanceof(File)) => z.preprocess((val) => { | ||
//Empty File object on no user input, so convert to undefined | ||
return val instanceof File && val.size === 0 ? undefined : val; | ||
}, schema); | ||
export const repeatable = (schema = z.array(text())) => { | ||
@@ -33,3 +37,3 @@ return z.preprocess((val) => { | ||
const entries = z.array(z.tuple([z.string(), z.any()])); | ||
export const formData = (shape) => z.preprocess(preprocessIfValid( | ||
export const formData = (shapeOrSchema) => z.preprocess(preprocessIfValid( | ||
// We're avoiding using `instanceof` here because different environments | ||
@@ -56,2 +60,2 @@ // won't necessarily have `FormData` or `URLSearchParams` | ||
}, {}); | ||
})), z.object(shape)); | ||
})), shapeOrSchema instanceof ZodType ? shapeOrSchema : z.object(shapeOrSchema)); |
@@ -1,2 +0,2 @@ | ||
import { z, ZodArray, ZodEffects, ZodNumber, ZodString, ZodTypeAny } from "zod"; | ||
import { z, ZodArray, ZodEffects, ZodNumber, ZodObject, ZodString, ZodTypeAny } from "zod"; | ||
declare type InputType<DefaultType extends ZodTypeAny> = { | ||
@@ -12,5 +12,10 @@ (): ZodEffects<DefaultType>; | ||
export declare const checkbox: ({ trueValue }?: CheckboxOpts) => z.ZodUnion<[z.ZodEffects<z.ZodLiteral<string>, boolean, string>, z.ZodEffects<z.ZodLiteral<undefined>, boolean, undefined>]>; | ||
export declare const file: InputType<z.ZodType<File>>; | ||
export declare const repeatable: InputType<ZodArray<any>>; | ||
export declare const repeatableOfType: <T extends z.ZodTypeAny>(schema: T) => z.ZodEffects<z.ZodArray<T, "many">, T["_output"][], T["_input"][]>; | ||
export declare const formData: <T extends z.ZodRawShape>(shape: T) => z.ZodEffects<z.ZodObject<T, "strip", z.ZodTypeAny, { [k_1 in keyof z.objectUtil.addQuestionMarks<{ [k in keyof T]: T[k]["_output"]; }>]: z.objectUtil.addQuestionMarks<{ [k_2 in keyof T]: T[k_2]["_output"]; }>[k_1]; }, { [k_3 in keyof z.objectUtil.addQuestionMarks<{ [k_2 in keyof T]: T[k_2]["_input"]; }>]: z.objectUtil.addQuestionMarks<{ [k_2_1 in keyof T]: T[k_2_1]["_input"]; }>[k_3]; }>, { [k_1 in keyof z.objectUtil.addQuestionMarks<{ [k in keyof T]: T[k]["_output"]; }>]: z.objectUtil.addQuestionMarks<{ [k_2 in keyof T]: T[k_2]["_output"]; }>[k_1]; }, { [k_3 in keyof z.objectUtil.addQuestionMarks<{ [k_2 in keyof T]: T[k_2]["_input"]; }>]: z.objectUtil.addQuestionMarks<{ [k_2_1 in keyof T]: T[k_2_1]["_input"]; }>[k_3]; }>; | ||
declare type FormDataType = { | ||
<T extends z.ZodRawShape>(shape: T): ZodEffects<ZodObject<T>>; | ||
<T extends z.ZodTypeAny>(schema: T): ZodEffects<T>; | ||
}; | ||
export declare const formData: FormDataType; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.formData = exports.repeatableOfType = exports.repeatable = exports.checkbox = exports.numeric = exports.text = void 0; | ||
exports.formData = exports.repeatableOfType = exports.repeatable = exports.file = exports.checkbox = exports.numeric = exports.text = void 0; | ||
const zod_1 = require("zod"); | ||
@@ -27,2 +27,7 @@ const stripEmpty = zod_1.z.literal("").transform(() => undefined); | ||
exports.checkbox = checkbox; | ||
const file = (schema = zod_1.z.instanceof(File)) => zod_1.z.preprocess((val) => { | ||
//Empty File object on no user input, so convert to undefined | ||
return val instanceof File && val.size === 0 ? undefined : val; | ||
}, schema); | ||
exports.file = file; | ||
const repeatable = (schema = zod_1.z.array((0, exports.text)())) => { | ||
@@ -41,3 +46,3 @@ return zod_1.z.preprocess((val) => { | ||
const entries = zod_1.z.array(zod_1.z.tuple([zod_1.z.string(), zod_1.z.any()])); | ||
const formData = (shape) => zod_1.z.preprocess(preprocessIfValid( | ||
const formData = (shapeOrSchema) => zod_1.z.preprocess(preprocessIfValid( | ||
// We're avoiding using `instanceof` here because different environments | ||
@@ -64,3 +69,3 @@ // won't necessarily have `FormData` or `URLSearchParams` | ||
}, {}); | ||
})), zod_1.z.object(shape)); | ||
})), shapeOrSchema instanceof zod_1.ZodType ? shapeOrSchema : zod_1.z.object(shapeOrSchema)); | ||
exports.formData = formData; |
{ | ||
"name": "zod-form-data", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"browser": "./browser/index.js", | ||
@@ -5,0 +5,0 @@ "main": "./build/index.js", |
@@ -51,2 +51,3 @@ # zod-form-data | ||
* [checkbox](#checkbox) | ||
* [file](#file) | ||
* [repeatable](#repeatable) | ||
@@ -82,2 +83,11 @@ * [repeatableOfType](#repeatableOfType) | ||
It's also possible to pass a zod schema to `formData`. | ||
```ts | ||
const schema = zfd.formData(z.object({ | ||
field1: zfd.text(), | ||
field2: zfd.text(), | ||
})) | ||
``` | ||
### text | ||
@@ -168,2 +178,39 @@ | ||
### file | ||
Transforms any empty File objects to `undefined` before validating. | ||
This makes it so empty files will fail required checks, | ||
allowing you to use `optional` for optional fields. | ||
If you call `zfd.file` with no arguments, it will assume the field is a required file by default. | ||
#### Usage | ||
```ts | ||
const schema = zfd.formData({ | ||
requiredFile: zfd.file(), | ||
optional: zfd.file(z.instanceof(File).optional()), | ||
}) | ||
``` | ||
There is a unique case in Remix when using a CustomUploadHandler, | ||
the field will be a `File` on the client side, but an ID string (or URL) after uploading on the server. | ||
In this case you will need the schema to switch to string on the server: | ||
```ts | ||
const baseSchema = z.object({ | ||
someOtherField: zfd.text(), | ||
}); | ||
const clientSchema = z.formData(baseSchema.and({ | ||
file: zfd.file() | ||
})) | ||
const serverSchema = z.formData(baseSchema.and({ | ||
file: z.string() | ||
})) | ||
``` | ||
*Note: This will return `File | string` for the type. TODO: Example of type safety for this* | ||
### repeatable | ||
@@ -200,2 +247,2 @@ | ||
}) | ||
``` | ||
``` |
@@ -1,2 +0,11 @@ | ||
import { z, ZodArray, ZodEffects, ZodNumber, ZodString, ZodTypeAny } from "zod"; | ||
import { | ||
z, | ||
ZodArray, | ||
ZodEffects, | ||
ZodNumber, | ||
ZodObject, | ||
ZodString, | ||
ZodType, | ||
ZodTypeAny, | ||
} from "zod"; | ||
@@ -45,2 +54,8 @@ type InputType<DefaultType extends ZodTypeAny> = { | ||
export const file: InputType<z.ZodType<File>> = (schema = z.instanceof(File)) => | ||
z.preprocess((val) => { | ||
//Empty File object on no user input, so convert to undefined | ||
return val instanceof File && val.size === 0 ? undefined : val; | ||
}, schema); | ||
export const repeatable: InputType<ZodArray<any>> = ( | ||
@@ -62,3 +77,10 @@ schema = z.array(text()) | ||
export const formData = <T extends z.ZodRawShape>(shape: T) => | ||
type FormDataType = { | ||
<T extends z.ZodRawShape>(shape: T): ZodEffects<ZodObject<T>>; | ||
<T extends z.ZodTypeAny>(schema: T): ZodEffects<T>; | ||
}; | ||
export const formData: FormDataType = <T extends z.ZodRawShape | z.ZodTypeAny>( | ||
shapeOrSchema: T | ||
) => | ||
z.preprocess( | ||
@@ -92,3 +114,3 @@ preprocessIfValid( | ||
), | ||
z.object(shape) | ||
shapeOrSchema instanceof ZodType ? shapeOrSchema : z.object(shapeOrSchema) | ||
); |
Sorry, the diff of this file is not supported yet
20576
329
245