Skip to main content
Version: 3.x

Zod

Available since v3.4.0

The @zenstackhq/zod package generates Zod validation schemas from your ZModel definitions. It provides type-safe schemas for models, embedded types, and enums, with full support for validation attributes and custom validation rules.

Installation​

npm install @zenstackhq/zod zod

Zod 4.0 or above is required.

API​

The package exports a createSchemaFactory function that takes a ZenStack schema as input and returns a factory for creating Zod schemas.

import schema from './zenstack/schema';
import { createSchemaFactory } from '@zenstackhq/zod';

const factory = createSchemaFactory(schema);

The factory exposes the following methods:

  • makeModelSchema

    Creates a schema for the full shape of a model, including relation fields (as optional fields).

  • makeModelCreateSchema

    Creates a schema for creating new records, with fields that have defaults being optional. The result schema excludes relation fields.

  • makeModelUpdateSchema

    Creates a schema for updating records, with all fields being optional. The result schema excludes relation fields.

  • makeTypeSchema

    Creates a schema for a Custom Type.

  • makeEnumSchema

    Creates a schema for an enum type.

Schema Features​

The created Zod schemas have the following features:

  1. They are strongly typed.
  2. They verify the basic shapes of input args (object fields and types).
  3. They respect the additional validation attributes like @email, @length, etc., as described in Input Validation.
  4. If a ZModel declaration has a @@meta or @meta attribute with "description" key, the meta value will be used as the Zod schema's metadata.

Samples​

Open in StackBlitz
zenstack/schema.zmodel
// This is a sample model to get you started.

datasource db {
provider = 'sqlite'
}

/// User role
enum Role {
USER
ADMIN
}

/// Profile type definition
type Profile {
bio String?
website String? @url
}

/// User model
model User {
id Int @id @default(autoincrement())
email String @unique @email @meta('description', 'The unique email address of the user')
role Role @default(USER)
profile Profile? @json
posts Post[]
@@meta('description', 'A registered user of the application')
}

/// Post model
model Post {
id Int @id @default(autoincrement())
title String
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
main.ts
import { createSchemaFactory } from '@zenstackhq/zod';
import { schema } from './zenstack/schema';

const factory = createSchemaFactory(schema);

// enum
const roleSchema = factory.makeEnumSchema('Role');
console.log('"STAFF" is a valid Role?', roleSchema.safeParse('STAFF').success);

// type
const profileSchema = factory.makeTypeSchema('Profile');
console.log(
'Profile allows invalid website?',
profileSchema.safeParse({ website: 'not-a-url' }).success,
);

// User model's create schema
const userCreateSchema = factory.makeModelCreateSchema('User');
console.log(
'User create schema allows omitting "role"?',
userCreateSchema.safeParse({ email: 'alice@example.com' }).success,
);

// User model full schema
const userSchema = factory.makeModelSchema('User');
console.log(
'User full model allows relations?',
userSchema.safeParse({
id: 1,
email: 'user@example.com',
role: 'ADMIN',
profile: { bio: 'A developer', website: 'https://example.com' },
posts: [{ id: 1, title: 'Post1' }],
}).success,
);

// `@@meta` and `@meta` handling
console.log(
'User schema has description meta:',
userSchema.meta()?.description,
);
console.log(
'User.email field has description:',
userCreateSchema.shape.email.meta()?.description,
);
Comments
Feel free to ask questions, give feedback, or report issues.

Don't Spam


You can edit/delete your comments by going directly to the discussion, clicking on the 'comments' link below