返回 Skill 列表
extension
分类: 开发与工程无需 API Key

zodipus-setup

安装并配置Zodipus Prisma生成器。在安装zodipus、设置生成器选项、配置输出路径、选择日期格式或与Next.js/Express/Fastify/tRPC集成时使用。

person作者: jakexiaohubgithub

Zodipus Setup

Complete guide for installing and configuring Zodipus.

When to Apply

  • User is installing zodipus for the first time
  • User asks about generator configuration options
  • User needs framework-specific setup (Next.js, Express, tRPC)
  • User wants to understand dateFormat, relationDepth, or other options
  • User is setting up a new Prisma project with Zod validation

Installation

# npm
npm install zodipus zod

# pnpm
pnpm add zodipus zod

# yarn
yarn add zodipus zod

Requirements:

  • Node.js 18+
  • Prisma 6.0+
  • Zod 3.25.0+

Basic Configuration

Add to your schema.prisma:

generator client {
  provider = "prisma-client-js"
}

generator zodipus {
  provider = "zodipus"
  output   = "./generated"
}

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String?
  role      Role     @default(USER)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  posts     Post[]
}

model Post {
  id        String   @id @default(cuid())
  title     String
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  String
}

enum Role {
  USER
  ADMIN
}

Generate Schemas

npx prisma generate

This creates:

generated/
├── enums.ts              # RoleSchema
├── models.ts             # UserSchema, PostSchema
├── custom-schemas.ts     # Placeholder for @zodSchema
├── generated-relations.ts
└── generated-index.ts

Configuration Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | provider | string | Required | Must be "zodipus" | | output | string | Required | Output directory for generated files | | relationDepth | string | "5" | Maximum depth for nested relation extraction | | dateFormat | string | "coerce" | DateTime handling: "coerce" or "string" | | passthroughEnabled | string | "false" | Allow unknown keys in objects | | debug | string | "false" | Enable verbose debug logging | | zodImport | string | "zod" | Custom Zod import path |

Date Format Options

dateFormat = "coerce" (Default)

Accepts multiple input types, converts to Date:

// All valid inputs:
UserSchema.parse({ createdAt: new Date() });           // Date object
UserSchema.parse({ createdAt: '2024-01-15T10:30:00Z' }); // ISO string
UserSchema.parse({ createdAt: 1705315800000 });        // Timestamp

Use when: Receiving data from various sources (APIs, databases, user input).

dateFormat = "string"

Requires strict ISO 8601 format:

// Only ISO strings accepted:
UserSchema.parse({ createdAt: '2024-01-15T10:30:00.000Z' }); // OK
UserSchema.parse({ createdAt: new Date() }); // Error!

Use when: Building strict APIs, need consistent date format.

Passthrough Mode

passthroughEnabled = "false" (Default)

Unknown keys are stripped:

const data = { id: '1', email: 'a@b.com', unknownField: 'ignored' };
const user = UserSchema.parse(data);
// user = { id: '1', email: 'a@b.com' } - unknownField removed

Use when: Sanitizing input, preventing data leakage.

passthroughEnabled = "true"

Unknown keys are preserved:

const data = { id: '1', email: 'a@b.com', extra: 'kept' };
const user = UserSchema.parse(data);
// user = { id: '1', email: 'a@b.com', extra: 'kept' }

Use when: Transforming data, need to preserve extra fields.

Relation Depth

Controls how deeply nested relations are extracted for the Query Engine:

generator zodipus {
  relationDepth = "10"  # Allow queries 10 levels deep
}

Default: 5 - Sufficient for most apps. Increase if you have deeply nested queries.

Common Configurations

Strict API Server

Best for REST/GraphQL APIs with strict validation:

generator zodipus {
  provider           = "zodipus"
  output             = "./src/generated/zodipus"
  passthroughEnabled = "false"
  dateFormat         = "string"
  relationDepth      = "5"
}

Flexible Data Pipeline

Best for ETL, migrations, or internal tools:

generator zodipus {
  provider           = "zodipus"
  output             = "./generated"
  passthroughEnabled = "true"
  dateFormat         = "coerce"
  relationDepth      = "8"
}

Minimal Setup

Quick start with sensible defaults:

generator zodipus {
  provider = "zodipus"
  output   = "./generated"
}

Framework Integration

Next.js App Router

// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { UserSchema } from '@/generated';
import { prisma } from '@/lib/prisma';

export async function POST(request: NextRequest) {
  const body = await request.json();

  const result = UserSchema.omit({ id: true, createdAt: true, updatedAt: true })
    .safeParse(body);

  if (!result.success) {
    return NextResponse.json({ errors: result.error.flatten() }, { status: 400 });
  }

  const user = await prisma.user.create({ data: result.data });
  return NextResponse.json(UserSchema.parse(user));
}

Express.js

// routes/users.ts
import { Router } from 'express';
import { UserSchema } from '../generated';
import { prisma } from '../lib/prisma';

const router = Router();

router.post('/', async (req, res) => {
  const CreateUserSchema = UserSchema.omit({ id: true, createdAt: true, updatedAt: true });
  const result = CreateUserSchema.safeParse(req.body);

  if (!result.success) {
    return res.status(400).json({ errors: result.error.flatten() });
  }

  const user = await prisma.user.create({ data: result.data });
  res.json(UserSchema.parse(user));
});

export default router;

tRPC

// server/routers/user.ts
import { router, publicProcedure } from '../trpc';
import { UserSchema } from '../../generated';
import { prisma } from '../../lib/prisma';

export const userRouter = router({
  create: publicProcedure
    .input(UserSchema.omit({ id: true, createdAt: true, updatedAt: true }))
    .mutation(async ({ input }) => {
      const user = await prisma.user.create({ data: input });
      return UserSchema.parse(user);
    }),

  getById: publicProcedure
    .input(z.object({ id: z.string() }))
    .query(async ({ input }) => {
      const user = await prisma.user.findUnique({ where: { id: input.id } });
      return user ? UserSchema.parse(user) : null;
    }),
});

Verification

After setup, verify everything works:

// test-setup.ts
import { UserSchema, RoleSchema } from './generated';
import { createRegistry } from 'zodipus/queryEngine';
import { models, modelRelations } from './generated/generated-index';

// Test schema parsing
const user = UserSchema.parse({
  id: 'test-id',
  email: 'test@example.com',
  name: null,
  role: 'USER',
  createdAt: new Date(),
  updatedAt: new Date(),
});
console.log('Schema validation:', user);

// Test Query Engine
const registry = createRegistry({ models, relations: modelRelations });
const userQuery = registry.createQuery('user');
console.log('Query Engine:', userQuery({ select: { id: true } }).query);

Troubleshooting Setup

"Cannot find module './generated'"

Run npx prisma generate after adding the generator.

TypeScript errors after generation

Ensure your tsconfig includes the output directory:

{
  "include": ["src/**/*", "generated/**/*"]
}

ESM/CJS conflicts

Zodipus outputs CommonJS. If using ESM, ensure your bundler handles the conversion.

For detailed options, see references/GENERATOR-OPTIONS.md.