Zod Schemas
You can generate Zod schemas for tables declared with @monolayer/pg with the zodSchema function before inserting or updating data to the database.
The Zod schemas will take into account:
- The data type of the column.
- The column nullability and its default value.
- Whether the column is a primary key or generated.
- Specific column data type validations that match validations at database level. For example, the range of an
integercolumn is: -2147483648 to +2147483647.
Validating Schemas
import {
enumType,
enumerated,
integer,
primaryKey,
table,
text,
timestampWithTimeZone
} from "@monolayer/pg/schema"
import { zodSchema } from "@monolayer/pg/zod"
import { sql } from "kysely";
import z from "zod";
// `users` table
const userRole = enumType("user_role", ["admin", "user"]);
const users = table({
columns: {
id: integer().generatedAlwaysAsIdentity(),
name: text(),
email: text().notNull(),
role: enumerated(userRole).notNull(),
createdAt: timestampWithTimeZone().default(sql`now()`).notNull(),
},
constraints: {
primaryKey: primaryKey(["id"]),
},
});
// Zod Schema for `users`
const schema = zodSchema(users);
// Usage
const user = schema.parse({
name: "John Smith",
email: 'john@smith.com',
role: 'admin',
});
type InputType = z.input<typeof schema>;
//{
// id: never;
// name?: string | null | undefined;
// email: string;
// role: "user" | "admin";
// createdAt?: Date | string | undefined;
//}
type OutputType = z.output<typeof schema>;
//{
// id: never;
// name?: string | null | undefined;
// email: string;
// role: "user" | "admin";
// createdAt?: Date | undefined;
// }Extending Schemas
You can use the Zod API to customize schemas.
Example
Adding an email validation to the email column in the users table from the previous example:
const schemaWithEmailValidation = zodSchema(users).extend({
email: schema.shape.email.pipe(z.string().email())
})
type InputTypeEmail = z.input<typeof schemaWithEmailValidation>;
//{
// id: never;
// name: string;
// email: string;
// role: "user" | "admin";
// createdAt?: Date | string | undefined;
//}
type OutputTypeEmail = z.output<typeof schemaWithEmailValidation>;
//{
// id: never;
// name: string;
// email: string;
// role: "user" | "admin";
// createdAt?: Date | undefined;
// }See: Zod Objects
Default input and output types
Each column data type has input and output types in the generated schema:
| Column | Input | Output |
|---|---|---|
| bigint | bigint | number | string | null | undefined | string | null | undefined |
| bigserial | bigint | number | string | string |
| bit | string | null | undefined | string | null | undefined |
| bitVarying | string | null | undefined | string | null | undefined |
| boolean | boolean | Boolish| null | undefined | boolean | null | undefined |
| bytea | Buffer | string | null | undefined | Buffer | string | null | undefined |
| characterVarying | string | null | undefined | string | null | undefined |
| character | string | null | undefined | string | null | undefined |
| cidr | string | null | undefined | string | null | undefined |
| date | Date | string | null | undefined | Date | null | undefined |
| doublePrecision | bigint | number | string | null | undefined | string | null | undefined |
| enumerated | enum values | null | undefined | enum values | null | undefined |
| inet | string | null | undefined | string | null | undefined |
| integer | number | string | null | undefined | number | null | undefined |
| json | JsonValue| null | undefined | JsonValue| null | undefined |
| jsonb | JsonValue| null | undefined | JsonValue| null | undefined |
| macaddr | string | null | undefined | string | null | undefined |
| macaddr8 | string | null | undefined | string | null | undefined |
| numeric | bigint | number | string | null | undefined | number | null | undefined |
| real | bigint | number | string | null | undefined | string | null | undefined |
| serial | number | string | number |
| smallint | number | string | null | undefined | number | null | undefined |
| time | string | null | undefined | string | null | undefined |
| timeWithTimeZone | string | null | undefined | string | null | undefined |
| timestamp | Date | string | null | undefined | Date | null | undefined |
| timestampWithTimeZone | Date | string | null | undefined | Date | null | undefined |
| tsquery | string | null | undefined | string | null | undefined |
| tsvector | string | null | undefined | string | null | undefined |
| uuid | string | null | undefined | string | null | undefined |
| xml | string | null | undefined | string | null | undefined |
Boolish and JsonValue types
type Boolish = "true" | "false" | "yes" | "no" |
1 | 0 | "1" | "0" | "on" | "off";
type JsonArray = JsonValue[];
type JsonValue = boolean | number | string |
Record<string, unknown> | JsonArray;Nullability and optionality
Depending on a column constraints (NOT NULL, primary key), the default data value, and whether it's generated, input and output types in the schema will change:
| Column | Input and output types allow null | Input and output types allow undefined |
|---|---|---|
| with default data value | N/A | yes |
with NOT NULL constraint | no | no |
with NOT NULL constraint and default data value | no | yes |
| primary key | no | no |
| generated by default as identity | no | yes |
| serial | no | yes |
| bigserial | no | yes |
Generated always by identity columns
Generated always by identity columns have never as input and output type.
Column Validations
bigint
Validations:
- Explicit
undefinedvalues are rejected. - Value must be a valid
bigint. - Value cannot be lower than -9223372036854775808.
- Value cannot be greater than 9223372036854775807.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: bigint | number | string | null | undefined;
output?: string | null | undefined;
}bigserial
- Explicit
undefinedvalues are rejected. - Value must be a valid
bigint. - Value cannot be lower than -9223372036854775808.
- Value cannot be greater than 9223372036854775807.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: bigint | number | string | undefined;
output?: string | undefined;
}bit
- Explicit
undefinedvalues are rejected. - Value must be a string of 1's and 0's.
- Value must match the
fixedLengthexactly.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}bit varying
- Explicit
undefinedvalues are rejected. - Value must be a string.
- Value can contain only 1 and 0.
- Value cannot exceed
maximumLength.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}boolean
- Explicit
undefinedvalues are rejected. - Value must be
booleanorBoolish.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: boolean | Boolish | null | undefined;
output?: boolean | null | undefined;
}bytea
- Explicit
undefinedvalues are rejected. - Value must be a
Buffer,string, ornull.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: Buffer | string | null | undefined;
output?: Buffer | string | null | undefined;
}Nullability and optionality will change according to the column's constraints, generated values, and default data values.
INFO
Since Buffer is a Node.js API, the schema will not coerce the input to Buffer for browser compatibility.
character
- Explicit
undefinedvalues are rejected. - Value must be a
stringornull. - String values cannot exceed
maximumLength.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}character varying
- Value must be a
stringornull. - Value cannot exceed
maximumLength(when specified).
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}cidr
- Explicit
undefinedvalues are rejected. - Value must be
stringornull. - String values must be a valid IPv4 or IPv6 network specification without bits set to the right of the mask.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}date
- Value must be
Date,string, ornull. - Explicit
undefinedvalues are rejected. - String values must be coercible to
Date.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: Date | string | null | undefined;
output?: Date | null | undefined;
}double precision
- Input value must be
bigint,number,string, ornull. - Explicit
undefinedvalues are rejected. - Non-null values must be either:
- Coercible to BigInt.
NaNInfinity-Infinity.
- Bigint values must be:
- Lower than -1e308.
- Greater than 1e308.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: bigint | number | string | null | undefined;
output?: string | null | undefined;
}enum types
- Explicit
undefinedvalues are rejected. - Input values must be an enum value, or
null.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
// enumType("role", ["admin", "user"]);
{
input?: "admin" | "user" | null | undefined;
output?: "admin" | "user" | null | undefined;
}inet
- Explicit
undefinedvalues are rejected. - Value must be
stringornull. - String values must be a valid IPv4 or IPv6 host address with optional subnet.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}integer
- Input value must be
number,string, ornull. - Non-null values must be:
- Coercible to
number. - Greater or equal than -2147483648.
- Less than 2147483647.
- Coercible to
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: number | string | null | undefined;
output?: number | null | undefined;
}json
- Explicit
undefinedvalues are rejected. - Input values must be
JsonValueornull. - String values must be valid JSON.
- Record values must be convertible to a JSON string.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
// type JsonArray = JsonValue[];
// type JsonValue = boolean | number | string | Record<string, any> | JsonArray;
{
input?: JsonValue | null | undefined;
output?: JsonValue | null | undefined;
}jsonb
- Explicit
undefinedvalues are rejected. - Input values must be
JsonValueornull. - String values must be valid JSON.
- Record values must be convertible to a JSON string.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
// type JsonArray = JsonValue[];
// type JsonValue = boolean | number | string | Record<string, any> | JsonArray;
{
input?: JsonValue | null | undefined;
output?: JsonValue | null | undefined;
}macaddr
- Explicit
undefinedvalues are rejected. - Input value must be
stringornull. - String values must be a valid MAC address.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}macaddr8
- Explicit
undefinedvalues are rejected. - Input value must be
stringornull. - String values must be a valid MAC address in EUI-64 format.
{
input?: string | null | undefined;
output?: string | null | undefined;
}Nullability and optionality will change according to the column's constraints, generated values, and default data values.
numeric
- Explicit
undefinedvalues are rejected. - Input value must be
bigint,number,string, ornull. - Non-null values must be either:
- Coercible to a number.
- NaN, Infinity, -Infinity
- Precision and scale are enforced when specified.
{
input?: bigint | number | string | null | undefined;
output?: string | null | undefined;
}Nullability and optionality will change according to the column's constraints, generated values, and default data values.
real
- Explicit
undefinedvalues are rejected. - Input value must be
number,string, ornull. - Non-null values must be either:
- coercible to
number. NaN,Infinity, or-Infinity.
- coercible to
numbervalues:- Cannot be lower than -1e37.
- Cannot be greater than 1e37.
{
input?: bigint | number | string | null | undefined;
output?: number | null | undefined;
}Nullability and optionality will change according to the column's constraints, generated values, and default data values.
serial
- Explicit
undefinedvalues are rejected. - Value must be a valid
number. - Value cannot be lower than -2147483648.
- Value cannot be greater than 2147483647.
{
input?: number | string | undefined;
output?: number | undefined;
}smallint
- Input value must be
number,string, ornull. - Non-null values:
- must be coercible to
number. - Cannot be lower than -32768.
- Cannot be greater than 32767.
- must be coercible to
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: number | string | null | undefined;
output?: number | null | undefined;
}text
- Explicit
undefinedvalues are rejected. - Input value must be
stringornull.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}time
- Explicit
undefinedvalues are rejected. - Input value must be
string, ornull. - Non-values must be a valid string that matches a time format.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}time with time zone
- Explicit
undefinedvalues are rejected. - Input value must be
string, ornull. - Non-values must be a valid string that matches a time format.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}timestamp
- Explicit
undefinedvalues are rejected. - Input value must be
Date,string, ornull. - Non-null values must be:
- Coercible to a
Date. - Date must be 4713 BC or later.
- Coercible to a
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: Date | string | null | undefined;
output?: Date | null | undefined;
}timestamp with timezone
- Explicit
undefinedvalues are rejected. - Input value must be
Date,string, ornull. - Non-null values must be:
- Coercible to a
Date. - Date must be 4713 BC or later.
- Coercible to a
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: Date | string | null | undefined;
output?: Date | null | undefined;
}tsquery
- Explicit
undefinedvalues are rejected. - Input value must be
stringornull.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}tsvector
- Explicit
undefinedvalues are rejected. - Input value must be
stringornull.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}uuid
- Explicit
undefinedvalues are rejected. - Input value must be
string, ornull. - String values must be a valid UUID.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}xml
- Explicit
undefinedvalues are rejected. - Input value must be
string, ornull.
Nullability and optionality will change according to the column's constraints, generated values, and default data values.
{
input?: string | null | undefined;
output?: string | null | undefined;
}