prisma-zod-generator 1.9.0 β†’ 1.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,1733 +1,107 @@
1
1
  <div align="center">
2
-
3
- # ⚑ Prisma Zod Generator
4
-
5
- ### πŸš€ **Automatically generate Zod schemas from your Prisma schema**
6
-
7
- <p>
8
- <a href="https://www.npmjs.com/package/prisma-zod-generator">
9
- <img src="https://img.shields.io/npm/v/prisma-zod-generator/latest.svg?style=for-the-badge&logo=npm&color=blue" alt="Latest Version">
10
- </a>
11
- </p>
12
-
13
- <p>
14
- <a href="https://www.npmjs.com/package/prisma-zod-generator">
15
- <img src="https://img.shields.io/npm/dt/prisma-zod-generator.svg?style=for-the-badge&logo=npm&color=green" alt="Downloads">
16
- </a>
17
- <a href="https://github.com/omar-dulaimi/prisma-zod-generator/actions">
18
- <img src="https://img.shields.io/github/actions/workflow/status/omar-dulaimi/prisma-zod-generator/ci.yml?style=for-the-badge&logo=github" alt="CI Status">
19
- </a>
20
- <a href="https://omar-dulaimi.github.io/prisma-zod-generator/">
21
- <img src="https://img.shields.io/badge/docs-website-blue?style=for-the-badge&logo=readthedocs" alt="Docs">
22
- </a>
23
- <a href="LICENSE">
24
- <img src="https://img.shields.io/npm/l/prisma-zod-generator.svg?style=for-the-badge&color=purple" alt="License">
25
- </a>
26
- </p>
27
-
28
- <p>
29
- <strong>:dart: Zero-config β€’ :shield: Type-safe β€’ :zap: Fast β€’ :wrench: Customizable</strong>
30
- </p>
31
-
32
- </div>
33
-
34
- ---
35
-
36
- <div align="center">
37
- <h3>:bulb: Transform your Prisma schema into type-safe validation schemas</h3>
38
- <p><em>Automatically generates Zod schemas for all Prisma operations with full TypeScript support</em></p>
39
- </div>
40
-
41
- <div align="center">
42
-
43
- <a id="sponsor"></a>
44
- ## :sparkling_heart: Sponsor to Keep This Project Active
45
-
46
- <p><strong>:rotating_light: Active maintenance depends on your sponsorship. If this generator saves you time, please consider sponsoring.</strong></p>
47
-
48
- <a href="https://github.com/sponsors/omar-dulaimi">
49
- <img src="https://img.shields.io/badge/πŸ’_Sponsor_on_GitHub-ea4aaa?style=for-the-badge&logo=github&logoColor=white" alt="GitHub Sponsors" height="45">
50
- </a>
51
-
52
- <p><em>Your support funds maintenance, issue triage, new features, documentation, and community help.</em></p>
53
-
2
+ <h1>Prisma Zod Generator</h1>
3
+ <p><strong>Prisma β†’ Zod in one generate. Ship validated data everywhere.</strong></p>
4
+ <p>
5
+ <a href="https://www.npmjs.com/package/prisma-zod-generator"><img alt="npm version" src="https://img.shields.io/npm/v/prisma-zod-generator.svg?color=16C464&label=version"></a>
6
+ <a href="https://www.npmjs.com/package/prisma-zod-generator"><img alt="weekly downloads" src="https://img.shields.io/npm/dw/prisma-zod-generator.svg?color=8B5CF6&label=downloads"></a>
7
+ <a href="https://github.com/omar-dulaimi/prisma-zod-generator/actions"><img alt="CI status" src="https://img.shields.io/github/actions/workflow/status/omar-dulaimi/prisma-zod-generator/ci.yml?branch=master&label=CI"></a>
8
+ <a href="https://github.com/omar-dulaimi/prisma-zod-generator/blob/master/LICENSE"><img alt="MIT license" src="https://img.shields.io/badge/license-MIT-0a0a0a.svg"></a>
9
+ <img alt="TypeScript" src="https://img.shields.io/badge/types-TypeScript-informational.svg">
10
+ <img alt="Module formats" src="https://img.shields.io/badge/modules-esm%20%2B%20cjs-444.svg">
11
+ <a href="https://omar-dulaimi.github.io/prisma-zod-generator/"><img alt="Docs" src="https://img.shields.io/badge/docs-website-blue.svg"></a>
12
+ </p>
13
+ <sub><code>input</code> Β· <code>result</code> Β· <code>pure</code> variants β€’ comment rules β€’ minimal mode β€’ targeted filtering</sub>
54
14
  </div>
55
15
 
56
16
  ---
57
17
 
18
+ > πŸ“˜ Docs: https://omar-dulaimi.github.io/prisma-zod-generator/
58
19
 
20
+ ## Prerequisites
59
21
 
60
- ## :clipboard: **Table of Contents**
61
-
62
- <table>
63
- <tr>
64
- <td><a href="#sponsor">:sparkling_heart: Sponsor</a></td>
65
- <td><a href="#-quick-start">:rocket: Quick Start</a></td>
66
- <td><a href="#-generated-output">:clipboard: Generated Output</a></td>
67
- <td><a href="#-version-compatibility">:package: Compatibility</a></td>
68
- <td><a href="#-core-examples">:books: Core Examples</a></td>
69
- </tr>
70
- <tr>
71
- <td><a href="#-advanced-features">:wrench: Advanced Features</a></td>
72
- <td><a href="#-configuration">:gear: Configuration</a></td>
73
- <td><a href="#-api-reference">:book: API Reference</a></td>
74
- <td><a href="#-framework-examples">:globe_with_meridians: Framework Examples</a></td>
75
- </tr>
76
- <td><a href="#-testing--development">:test_tube: Testing & Development</a></td>
77
- <td><a href="#-troubleshooting">:mag: Troubleshooting</a></td>
78
- <td><a href="#-contributing">:handshake: Contributing</a></td>
79
- <td></td>
80
- </tr>
81
- </table>
82
-
83
- ---
84
-
85
- ## :rocket: Quick Start
22
+ - Node.js 18+ (or Bun / Deno with Prisma compatibility layer)
23
+ - Prisma (installed & `npx prisma init` done)
24
+ - Zod (runtime dependency for the generated schemas)
25
+ - TypeScript recommended (strict mode ideal)
86
26
 
87
- ### Installation
27
+ ## Quick Start ⚑
88
28
 
29
+ **1. Install (pick one)**
89
30
  ```bash
90
- # NPM
91
- npm install prisma-zod-generator
92
-
93
- # Yarn
94
- yarn add prisma-zod-generator
95
-
96
- # PNPM
97
- pnpm add prisma-zod-generator
98
- ```
99
-
100
- ### 2. Add generator block to your Prisma schema
101
-
102
- Add the Prisma Zod Generator to your `schema.prisma` with inline options. You can also supply a JSON config via `config` for advanced/nested settings.
103
-
104
- ```prisma
105
- generator zod {
106
- provider = "prisma-zod-generator" // required: package id
107
- output = "./generated" // required: where to write output
108
-
109
- // File output mode
110
- useMultipleFiles = true // true: multi-file (default), false: single-file bundle
111
- singleFileName = "schemas.ts" // only when useMultipleFiles=false
112
- placeSingleFileAtRoot = true // single-file at output root (true) or under schemas/ (false)
113
-
114
- // Legacy select/include flags (override JSON config if both provided)
115
- isGenerateSelect = false
116
- isGenerateInclude = false
117
-
118
- // Optional: external JSON config for nested options (models, variants, exclusions, etc.)
119
- // When both sources specify the same simple option, this generator block wins.
120
- config = "./zod-generator.config.json"
121
- }
122
- ```
123
-
124
- Note on precedence: simple options declared in the Prisma generator block (like useMultipleFiles, singleFileName, placeSingleFileAtRoot, legacy isGenerateSelect/isGenerateInclude) override the same options from the JSON file. See the Precedence section for details.
125
-
126
- ### 3. Configure TypeScript (required)
127
-
128
- ```json
129
- {
130
- "compilerOptions": {
131
- "strict": true
132
- }
133
- }
31
+ # npm
32
+ npm i -D prisma-zod-generator zod
134
33
  ```
135
-
136
- ### 4. Generate schemas
137
-
138
34
  ```bash
139
- npx prisma generate
140
- ```
141
-
142
- ### πŸ’‘ Inline Custom Schema Override (@zod.custom.use)
143
-
144
- Replace a field's generated schema directly via a doc comment:
145
-
146
- ```prisma
147
- model AiChat {
148
- id String @id @default(cuid())
149
- /// @zod.custom.use(z.array(z.object({ role: z.enum(['user','assistant','system']), parts: z.array(z.object({ type: z.enum(['text','image']), text: z.string() })) })))
150
- messages Json @default("[]")
151
- }
152
- ```
153
-
154
- Output excerpt:
155
- ```ts
156
- messages: z.array(z.object({ role: z.enum(['user','assistant','system']), parts: z.array(z.object({ type: z.enum(['text','image']), text: z.string() })) })).default("[]")
157
- ```
158
-
159
- Add the internal depth refinement if desired:
160
- ```ts
161
- import { jsonMaxDepthRefinement } from 'prisma-zod-generator';
162
- const ChatMessagesSchema = z.array(MessageSchema)${'${jsonMaxDepthRefinement(10)}'};
163
- ```
164
-
165
- The override short‑circuits further inline annotations for that field.
166
-
167
- ### πŸ’‘ Inline Custom Schema Override (@zod.custom.use)
168
-
169
- You can replace a field's generated schema directly via a doc comment:
170
-
171
- ```prisma
172
- model AiChat {
173
- id String @id @default(cuid())
174
- /// @zod.custom.use(z.array(z.object({ role: z.enum(['user','assistant','system']), parts: z.array(z.object({ type: z.enum(['text','image']), text: z.string() })) })))
175
- messages Json @default("[]")
176
- }
35
+ # pnpm
36
+ pnpm add -D prisma-zod-generator zod
177
37
  ```
178
-
179
- Output excerpt:
180
- ```ts
181
- messages: z.array(z.object({ role: z.enum(['user','assistant','system']), parts: z.array(z.object({ type: z.enum(['text','image']), text: z.string() })) })).default("[]")
182
- ```
183
-
184
- Add the internal depth refinement if desired:
185
- ```ts
186
- import { jsonMaxDepthRefinement } from 'prisma-zod-generator';
187
- const ChatMessagesSchema = z.array(MessageSchema)${'${jsonMaxDepthRefinement(10)}'};
188
- ```
189
-
190
- The override short‑circuits further inline annotations for that field.
191
-
192
- ---
193
-
194
- ## 🐞 Logging and warnings
195
-
196
- <details>
197
- <summary><strong>Click to expand logging & warning details</strong></summary>
198
-
199
- By default the generator prints minimal output. Critical warnings are surfaced as tagged info lines so you won’t miss important context, while detailed diagnostics stay hidden unless you opt in.
200
-
201
- What you’ll see by default:
202
-
203
- - [prisma-zod-generator] ⚠️ File layout conflicts detected. The Prisma generator block takes precedence over JSON config.
204
- - When generator block and JSON disagree on useMultipleFiles/singleFileName/placeSingleFileAtRoot, this header appears so you know why you got a bundle vs many files (or vice versa). Details are available in debug logs.
205
- - [prisma-zod-generator] ⚠️ Minimal mode active: Select/Include schemas will be disabled even if enabled by legacy flags or config.
206
- - Minimal mode forces these helpers off to keep output lean. If you explicitly requested them, we’ll tell you they’re being ignored.
207
- - [prisma-zod-generator] ⚠️ Configuration loading failed, using defaults: …
208
- - If a config file can’t be loaded, we fall back to safe defaults and tell you why.
209
-
210
- Enable detailed debug output:
211
-
212
- - One-off run (Linux/macOS):
213
- - `DEBUG_PRISMA_ZOD=1 npx prisma generate`
214
- - or use a namespace: `DEBUG=prisma-zod npx prisma generate`
215
- - Via npm script in this repo: `npm run gen-example:debug`
216
-
217
- Unset the env var to return to quiet mode.
218
-
219
- </details>
220
-
221
- ---
222
-
223
- ## ✨ Why Choose Prisma Zod Generator?
224
-
225
- <table>
226
- <tr>
227
- <td align="center" width="25%">
228
- <img src="https://img.shields.io/badge/πŸš€-Zero_Config-blue?style=for-the-badge" alt="Zero Config"><br>
229
- <strong>Works instantly</strong><br><em>Sensible defaults included</em>
230
- </td>
231
- <td align="center" width="25%">
232
- <img src="https://img.shields.io/badge/πŸ”„-Auto_Generated-green?style=for-the-badge" alt="Auto Generated"><br>
233
- <strong>Always in sync</strong><br><em>Updates with schema changes</em>
234
- </td>
235
- <td align="center" width="25%">
236
- <img src="https://img.shields.io/badge/πŸ›‘οΈ-Type_Safe-purple?style=for-the-badge" alt="Type Safe"><br>
237
- <strong>100% TypeScript</strong><br><em>Catch errors at compile time</em>
238
- </td>
239
- <td align="center" width="25%">
240
- <img src="https://img.shields.io/badge/🎯-Comprehensive-orange?style=for-the-badge" alt="Comprehensive"><br>
241
- <strong>Full CRUD coverage</strong><br><em>All Prisma operations included</em>
242
- </td>
243
- </tr>
244
- <tr>
245
- <td align="center">
246
- <img src="https://img.shields.io/badge/βš™οΈ-Configurable-red?style=for-the-badge" alt="Configurable"><br>
247
- <strong>Highly customizable</strong><br><em>Adapt to your needs</em>
248
- </td>
249
- <td align="center">
250
- <img src="https://img.shields.io/badge/πŸ“¦-Lightweight-yellow?style=for-the-badge" alt="Lightweight"><br>
251
- <strong>Minimal footprint</strong><br><em>Fast generation & runtime</em>
252
- </td>
253
- <td align="center">
254
- <img src="https://img.shields.io/badge/πŸ—„οΈ-Multi_DB-cyan?style=for-the-badge" alt="Multi Database"><br>
255
- <strong>All databases</strong><br><em>PostgreSQL, MySQL, MongoDB+</em>
256
- </td>
257
- <td align="center">
258
- <img src="https://img.shields.io/badge/🎨-Flexible-pink?style=for-the-badge" alt="Flexible"><br>
259
- <strong>Your way</strong><br><em>Custom paths & options</em>
260
- </td>
261
- </tr>
262
- </table>
263
-
264
- ### πŸ”„ Upgrading
265
-
266
- The latest stable version maintains full API compatibility. Requirements:
267
- - Node.js 18+
268
- - Prisma 6.12.0+
269
- - Zod 4.0.5+
270
-
271
- Update and regenerate:
272
-
273
38
  ```bash
274
- npm update prisma-zod-generator
275
- npx prisma generate
276
- ```
277
-
278
- ## πŸ“‹ Generated Output
279
-
280
- <details>
281
- <summary><strong>πŸ“ File Structure Overview</strong></summary>
282
-
283
- For this Prisma schema:
284
-
285
- ```prisma
286
- model User {
287
- id Int @id @default(autoincrement())
288
- email String @unique
289
- name String?
290
- posts Post[]
291
- }
292
-
293
- model Post {
294
- id Int @id @default(autoincrement())
295
- title String
296
- content String?
297
- author User? @relation(fields: [authorId], references: [id])
298
- authorId Int?
299
- }
300
- ```
301
-
302
- The generator creates:
303
-
304
- ```
305
- πŸ“ generated/schemas/
306
- β”œβ”€β”€ πŸ“ enums/ # Enum validation schemas
307
- β”œβ”€β”€ πŸ“ objects/ # Input type schemas
308
- β”œβ”€β”€ πŸ“„ findManyUser.schema.ts
309
- β”œβ”€β”€ πŸ“„ findUniqueUser.schema.ts
310
- β”œβ”€β”€ πŸ“„ createOneUser.schema.ts
311
- β”œβ”€β”€ πŸ“„ updateOneUser.schema.ts
312
- β”œβ”€β”€ πŸ“„ deleteOneUser.schema.ts
313
- β”œβ”€β”€ πŸ“„ findManyPost.schema.ts
314
- β”œβ”€β”€ πŸ“„ createOnePost.schema.ts
315
- └── πŸ“„ index.ts # Barrel exports
316
- ```
317
-
318
- </details>
319
-
320
- ---
321
-
322
- ## :rocket: Dual Schema Export Strategy - Breakthrough Feature!
323
-
324
- ### 🎯 Solving the Type Safety vs Method Availability Trade-off
325
-
326
- This generator implements a dual export strategy that gives you both perfect Prisma typing and full Zod method support.
327
-
328
- #### The Problem
329
- With Zod schemas, you traditionally face a choice:
330
- - Type-safe: `z.ZodType<Prisma.Type>` gives perfect inference but restricts Zod method chaining
331
- - Method-friendly: Pure Zod schemas support all methods but lose perfect type binding
332
-
333
- #### Our Solution: Export Both Versions
334
-
335
- ```ts
336
- // Perfect type safety (no Zod method chaining)
337
- export const PostFindManySchema: z.ZodType<Prisma.PostFindManyArgs> = schema;
338
-
339
- // Full method availability (great inference)
340
- export const PostFindManyZodSchema = schema;
341
- ```
342
-
343
- Type-safe version (perfect Prisma integration):
344
-
345
- ```ts
346
- import { PostFindManySchema } from './generated/schemas/findManyPost.schema';
347
-
348
- type FindManyArgs = z.infer<typeof PostFindManySchema>; // Prisma.PostFindManyArgs
349
-
350
- const validatedInput = PostFindManySchema.parse(queryParams);
351
- const posts = await prisma.post.findMany(validatedInput);
352
- ```
353
-
354
- Method-friendly version (full Zod capabilities):
355
-
356
- ```ts
357
- import { PostFindManyZodSchema } from './generated/schemas/findManyPost.schema';
358
-
359
- const customSchema = PostFindManyZodSchema
360
- .extend({ customField: z.string() })
361
- .omit({ take: true })
362
- .merge(otherSchema);
363
-
364
- const partialSchema = PostFindManyZodSchema.partial();
365
- ```
366
-
367
- #### Configuration Options
368
-
369
- ```prisma
370
- generator zod {
371
- provider = "prisma-zod-generator"
372
- output = "./generated/schemas"
373
- exportTypedSchemas = true // Export z.ZodType<Prisma.Type> versions
374
- exportZodSchemas = true // Export pure Zod versions
375
- typedSchemaSuffix = "Schema" // Suffix for typed versions
376
- zodSchemaSuffix = "ZodSchema" // Suffix for method-friendly versions
377
- }
378
- ```
379
-
380
- #### Configuration Scenarios
381
-
382
- Type-safe only:
383
-
384
- ```prisma
385
- generator zod {
386
- provider = "prisma-zod-generator"
387
- exportTypedSchemas = true
388
- exportZodSchemas = false
389
- }
390
- ```
391
-
392
- Method-friendly only:
393
-
394
- ```prisma
395
- generator zod {
396
- provider = "prisma-zod-generator"
397
- exportTypedSchemas = false
398
- exportZodSchemas = true
399
- }
400
- ```
401
-
402
- Both versions:
403
-
404
- ```prisma
405
- generator zod {
406
- provider = "prisma-zod-generator"
407
- exportTypedSchemas = true
408
- exportZodSchemas = true
409
- }
410
- ```
411
-
412
- Custom naming:
413
-
414
- ```prisma
415
- generator zod {
416
- provider = "prisma-zod-generator"
417
- exportTypedSchemas = true
418
- exportZodSchemas = true
419
- typedSchemaSuffix = "Args"
420
- zodSchemaSuffix = "Validator"
421
- }
422
- ```
423
-
424
- Pro tips:
425
-
426
- - Smaller bundles: use a single export mode
427
- - Team consistency: choose one naming convention and stick with it
428
- - Gradual adoption: start with type-safe schemas, add method-friendly as needed
429
- - IDE performance: fewer exports -> faster IntelliSense in huge projects
430
-
431
- ---
432
-
433
- ## :package: Version Compatibility
434
-
435
- <details>
436
- <summary><strong>πŸ”„ Supported Versions & Migration Guide</strong></summary>
437
-
438
- ### Current Requirements
439
- | **Prisma** | 6.12.0+ | βœ… Recommended |
440
- | **Zod** | 4.0.5+ | βœ… Required |
441
- | **TypeScript** | 5.8+ | βœ… Recommended |
442
- ### Prisma Client Generator Support
443
-
444
- Both legacy and new ESM-compatible generators are supported:
445
-
446
- #### Legacy Generator (Existing Projects)
447
- ```prisma
448
- ```
449
-
450
- #### New ESM Generator (Prisma 6.12.0+)
451
- ```prisma
452
- generator client {
453
- provider = "prisma-client"
454
- output = "./src/generated/client"
455
- runtime = "nodejs"
456
- moduleFormat = "esm"
457
- generatedFileExtension = "ts"
458
- importFileExtension = "ts"
459
- }
460
- ```
461
-
462
- ### Migration Guide
463
-
464
- **Existing Projects**: No changes needed - continue using `prisma-client-js`
465
-
466
- **New Projects**: Consider the new `prisma-client` generator for ESM support
467
-
468
- </details>
469
-
470
- ---
471
-
472
- ## πŸ“š Core Examples
473
-
474
- <details>
475
- <summary><strong>🎯 Essential Usage Patterns</strong></summary>
476
-
477
- ### API Validation
478
-
479
- ```typescript
480
- // Validate input data
481
- const createUser = UserCreateInputObjectSchema.parse(requestData);
482
-
483
- // Validate query parameters
484
- const findUsers = UserFindManySchema.parse(queryParams);
485
-
486
- // Validate update operations
487
- const updateUser = UserUpdateOneSchema.parse(updateData);
488
- ```
489
-
490
- ### Form Validation with React Hook Form
491
-
492
- ```typescript
493
- import { useForm } from 'react-hook-form';
494
- import { zodResolver } from '@hookform/resolvers/zod';
495
- import { UserCreateInputObjectSchema } from './generated/schemas';
496
-
497
- function CreateUserForm() {
498
- const { register, handleSubmit, formState: { errors } } = useForm({
499
- resolver: zodResolver(UserCreateInputObjectSchema)
500
- });
501
-
502
- return (
503
- <form onSubmit={handleSubmit(onSubmit)}>
504
- <input {...register('email')} type="email" />
505
- {errors.email && <span>{errors.email.message}</span>}
506
- <button type="submit">Create User</button>
507
- </form>
508
- );
509
- }
510
- ```
511
-
512
- ### Database Operations
513
-
514
- ```typescript
515
- // Safe database queries with validation
516
- const searchUsers = async (params: unknown) => {
517
- const validatedParams = UserFindManySchema.parse(params);
518
- return await prisma.user.findMany(validatedParams);
519
- };
520
-
521
- // Validated mutations
522
- const createPost = async (data: unknown) => {
523
- const validatedData = PostCreateOneSchema.parse(data);
524
- return await prisma.post.create(validatedData);
525
- };
526
- ```
527
-
528
- </details>
529
-
530
- ---
531
-
532
- ## πŸ”§ Advanced Features
533
-
534
- <details>
535
- <summary><strong>🎯 Configuration System</strong></summary>
536
-
537
- Looking for ready-made configs? See the new Recipes catalog in `recipes/` for common setups (single file, models-only, minimal CRUD, tRPC, API result schemas, hide fields, and more).
538
-
539
- ### JSON-Based Configuration
540
-
541
- Create `zod-generator.config.json`:
542
-
543
- ```json
544
- {
545
- "mode": "custom",
546
- "output": "./src/generated/zod",
547
- "globalExclusions": {
548
- "input": ["id", "createdAt", "updatedAt"],
549
- "result": [],
550
- "pure": ["password", "hashedPassword"]
551
- },
552
- "variants": {
553
- "pure": {
554
- "enabled": true,
555
- "suffix": ".model",
556
- "excludeFields": []
557
- },
558
- "input": {
559
- "enabled": true,
560
- "suffix": ".input",
561
- "excludeFields": ["id"]
562
- },
563
- "result": {
564
- "enabled": true,
565
- "suffix": ".result",
566
- "excludeFields": ["password"]
567
- }
568
- },
569
- "models": {
570
- "User": {
571
- "enabled": true,
572
- "operations": ["findMany", "findUnique", "create", "update"],
573
- "variants": {
574
- "input": {
575
- "excludeFields": ["role", "permissions"]
576
- }
577
- }
578
- }
579
- }
580
- }
581
- ```
582
-
583
- ### Configuration Modes
584
-
585
- ```typescript
586
- // Minimal mode - essential operations only
587
- const minimalConfig = {
588
- mode: "minimal",
589
- operations: ["findMany", "findUnique", "create", "update"]
590
- };
591
-
592
- // Full mode - all operations and features
593
- const fullConfig = {
594
- mode: "full",
595
- includeAggregations: true,
596
- includeGroupBy: true
597
- };
598
- ```
599
-
600
- </details>
601
-
602
- <details>
603
- <summary><strong>🎨 Schema Variants</strong></summary>
604
-
605
- ### Multiple Schema Types
606
-
607
- Generate different schema variants for various use cases:
608
-
609
- ```typescript
610
- // Pure model schemas - exact Prisma model structure
611
- import { UserSchema } from './schemas/models/User.schema';
612
-
613
- // Input schemas - for API endpoints and forms
614
- import { UserInputSchema } from './schemas/User.input';
615
-
616
- // Result schemas - for API responses
617
- import { UserResultSchema } from './schemas/User.result';
618
-
619
- // Usage examples
620
- const createUser = UserInputSchema.parse(formData);
621
- const userResponse = UserResultSchema.parse(dbResult);
622
- const pureUser = UserSchema.parse(prismaModel);
623
- ```
624
-
625
- ### Variant Configuration
626
-
627
- ```json
628
- {
629
- "variants": [
630
- {
631
- "name": "input",
632
- "suffix": "Input",
633
- "exclude": ["id", "createdAt", "updatedAt"]
634
- },
635
- {
636
- "name": "result",
637
- "suffix": "Result",
638
- "exclude": ["password"]
639
- },
640
- {
641
- "name": "public",
642
- "suffix": "Public",
643
- "exclude": ["password", "email", "internalId"]
644
- }
645
- ]
646
- }
647
- ```
648
-
649
- </details>
650
-
651
- <details>
652
- <summary><strong>πŸ” Field Exclusion System</strong></summary>
653
-
654
- ### Global and Model-Specific Exclusions
655
-
656
- ```typescript
657
- // Configuration-based exclusion
658
- const config = {
659
- globalExclusions: {
660
- input: ["id", "createdAt", "updatedAt"],
661
- result: ["password", "hashedPassword"],
662
- pure: []
663
- },
664
- models: {
665
- User: {
666
- variants: {
667
- input: { excludeFields: ["role", "permissions"] },
668
- result: { excludeFields: ["password", "sessionToken"] }
669
- }
670
- }
671
- }
672
- };
673
- ```
674
-
675
- ### Prisma Schema Exclusions
676
-
677
- ```prisma
678
- model User {
679
- id Int @id @default(autoincrement())
680
- email String @unique
681
- password String // Excluded from result schemas
682
- role String // Excluded from input schemas
683
- /// @@Gen.model(hide: true) // Hide entire model
684
- posts Post[]
685
- }
686
- ```
687
-
688
- </details>
689
-
690
- <details>
691
- <summary><strong>🧭 Create input strictness</strong></summary>
692
-
693
- Control how Create-like inputs respect field exclusions.
694
-
695
- - strictCreateInputs (boolean, default: true)
696
- - true: Create-like inputs (CreateInput, UncheckedCreateInput, CreateMany*, CreateWithout*, CreateOrConnectWithout*, CreateNested*Without*) match Prisma exactly; exclusions do not apply.
697
- - false: Apply exclusions to these Create-like inputs as well.
698
- - preserveRequiredScalarsOnCreate (boolean, default: true)
699
- - When strictCreateInputs is false, keep truly required scalar fields even if excluded. Set to false to omit them too (advanced use only).
700
-
701
- Type parity with filtered Create inputs:
702
- - When exclusions apply to Create-like inputs, the typed export binds to Omit<Prisma.Type, 'excluded' | ...> so TypeScript matches the Zod shape.
703
-
704
- JSON config example:
705
-
706
- ```json
707
- {
708
- "globalExclusions": { "input": ["password", "internalId"] },
709
- "strictCreateInputs": false,
710
- "preserveRequiredScalarsOnCreate": true
711
- }
712
- ```
713
-
714
- </details>
715
-
716
- <details>
717
- <summary><strong>πŸ“ @zod Comment Annotations</strong></summary>
718
-
719
- ### Inline Validation Rules
720
-
721
- Add validation directly in your Prisma schema:
722
-
723
- ```prisma
724
- model User {
725
- id Int @id @default(autoincrement())
726
- email String @unique /// @zod.email()
727
- name String? /// @zod.min(2).max(50)
728
- age Int? /// @zod.min(0).max(120)
729
- username String @unique /// @zod.regex(/^[a-zA-Z0-9_]+$/)
730
- website String? /// @zod.url().optional()
731
- }
732
- ```
733
-
734
- Generated schema with validations:
735
-
736
- ```typescript
737
- export const UserCreateInputSchema = z.object({
738
- email: z.string().email(),
739
- name: z.string().min(2).max(50).optional(),
740
- age: z.number().int().min(0).max(120).optional(),
741
- username: z.string().regex(/^[a-zA-Z0-9_]+$/),
742
- website: z.string().url().optional()
743
- });
744
- ```
745
-
746
- ### Supported @zod Annotations
747
-
748
- ```prisma
749
- // String validations
750
- field String /// @zod.email()
751
- field String /// @zod.url()
752
- field String /// @zod.regex(/pattern/)
753
- field String /// @zod.min(2).max(50)
754
-
755
- // Number validations
756
- field Int /// @zod.min(0).max(100)
757
- field Float /// @zod.positive()
758
-
759
- // Custom validations
760
- field String /// @zod.custom(z.string().transform(s => s.toLowerCase()))
39
+ # yarn
40
+ yarn add -D prisma-zod-generator zod
761
41
  ```
762
-
763
- </details>
764
-
765
- <details>
766
- <summary><strong>πŸ—„οΈ Multi-Database Provider Support</strong></summary>
767
-
768
- ### Database-Specific Optimizations
769
-
770
- ```typescript
771
- // PostgreSQL - Advanced types supported
772
- const pgUser = z.object({
773
- id: z.number().int(),
774
- metadata: z.record(z.unknown()), // JSON type
775
- tags: z.array(z.string()), // Array type
776
- balance: z.number() // Decimal type
777
- });
778
-
779
- // MongoDB - Document structure
780
- const mongoUser = z.object({
781
- id: z.string(), // ObjectId as string
782
- embedded: z.object({ // Embedded documents
783
- profile: z.object({
784
- bio: z.string().optional()
785
- })
786
- }).optional()
787
- });
788
-
789
- // MySQL - Optimized for relational data
790
- const mysqlUser = z.object({
791
- id: z.number().int(),
792
- createdAt: z.date(),
793
- updatedAt: z.date()
794
- });
795
- ```
796
-
797
- ### Supported Providers
798
-
799
- - **PostgreSQL** - Full advanced type support
800
- - **MySQL** - Complete compatibility
801
- - **MongoDB** - Native document schemas
802
- - **SQLite** - Development & testing optimized
803
- - **SQL Server** - Enterprise features
804
- - **CockroachDB** - Distributed database support
805
-
806
- </details>
807
-
808
- <details>
809
- <summary><strong>πŸ”§ ESM Import Handling</strong></summary>
810
-
811
- ### Modern ES Module Support
812
-
813
- Full ESM compatibility with automatic file extension handling:
814
-
815
- ```prisma
816
- generator client {
817
- provider = "prisma-client"
818
- output = "./src/generated/client"
819
- moduleFormat = "esm"
820
- importFileExtension = "js" # Auto-handled
821
- }
822
- ```
823
-
824
- Generated imports include proper extensions:
825
-
826
- ```typescript
827
- import { User } from '../client/index.js'; // Auto-generated
828
- import { z } from 'zod';
829
- ```
830
-
831
- ### Import Configuration
832
-
833
- ```json
834
- {
835
- "esm": {
836
- "enabled": true,
837
- "fileExtension": ".js",
838
- "importExtension": ".js"
839
- }
840
- }
841
- ```
842
-
843
- </details>
844
-
845
- <details>
846
- <summary><strong>⚑ Performance Optimization</strong></summary>
847
-
848
- ### Built-in Optimizations
849
-
850
- ```typescript
851
- // Lazy loading for circular references
852
- const UserSchema = z.lazy(() => z.object({
853
- id: z.number().int(),
854
- posts: z.array(PostSchema).optional()
855
- }));
856
-
857
- // Selective generation
858
- const config = {
859
- models: {
860
- AuditLog: { enabled: false }, // Skip audit tables
861
- Migration: { enabled: false }, // Skip migration tables
862
- User: {
863
- enabled: true,
864
- operations: ["findMany", "create", "update"] // Only needed operations
865
- }
866
- }
867
- };
868
- ```
869
-
870
- ### Performance Tips
871
-
872
- - Use `minimal` mode for faster generation
873
- - Exclude unused models and operations
874
- - Enable lazy loading for complex relationships
875
- - Cache generated schemas in production
876
-
877
- </details>
878
-
879
- <details>
880
- <summary><strong>πŸ” API Security & Validation Patterns</strong></summary>
881
-
882
- ### Input Sanitization
883
-
884
- ```typescript
885
- export const sanitizeUserInput = (data: unknown) => {
886
- return UserCreateInputSchema
887
- .omit({ id: true }) // Remove ID from input
888
- .extend({
889
- email: z.string().email().toLowerCase() // Normalize email
890
- })
891
- .parse(data);
892
- };
893
- ```
894
-
895
- ### Role-Based Field Filtering
896
-
897
- ```typescript
898
- export const getUserForRole = (user: User, role: 'admin' | 'user') => {
899
- const baseSchema = UserResultSchema;
900
-
901
- if (role === 'user') {
902
- return baseSchema.omit({
903
- email: true,
904
- role: true,
905
- permissions: true
906
- }).parse(user);
907
- }
908
-
909
- return baseSchema.parse(user);
910
- };
911
- ```
912
-
913
- ### Complete API Endpoint Validation
914
-
915
- ```typescript
916
- app.post('/users', async (req, res) => {
917
- try {
918
- const userData = UserCreateInputSchema.parse(req.body);
919
- const user = await prisma.user.create({ data: userData });
920
- const response = UserResultSchema.parse(user);
921
- res.json(response);
922
- } catch (error) {
923
- if (error instanceof z.ZodError) {
924
- return res.status(400).json({
925
- errors: error.errors.map(e => ({
926
- field: e.path.join('.'),
927
- message: e.message
928
- }))
929
- });
930
- }
931
- }
932
- });
933
- ```
934
-
935
- </details>
936
-
937
- ---
938
-
939
- ## βš™οΈ Configuration
940
-
941
- <details>
942
- <summary><strong>πŸ”§ Configuration Options</strong></summary>
943
-
944
- > Looking for a complete, exhaustively documented list of every flag? See **[Full Configuration Reference](./CONFIG_REFERENCE.md)**.
945
-
946
- ### Basic Configuration
947
-
948
- | Option | Description | Type | Default |
949
- |--------|-------------|------|---------|
950
- | `output` | Output directory for generated files | `string` | `"./generated"` |
951
- | `isGenerateSelect` | Generate Select-related schemas | `boolean` | `false` |
952
- | `isGenerateInclude` | Generate Include-related schemas | `boolean` | `false` |
953
- | `exportTypedSchemas` | Export z.ZodType versions (type-safe) | `boolean` | `true` |
954
- | `exportZodSchemas` | Export pure Zod versions (method-friendly) | `boolean` | `true` |
955
- | `typedSchemaSuffix` | Suffix for typed schemas | `string` | `"Schema"` |
956
- | `zodSchemaSuffix` | Suffix for Zod schemas | `string` | `"ZodSchema"` |
957
- | `useMultipleFiles` | Output multiple files (true) or single bundle (false) | `boolean` | `true` |
958
- | `singleFileName` | Name of the single-file bundle when `useMultipleFiles=false` | `string` | `"schemas.ts"` |
959
- | `placeSingleFileAtRoot` | When `useMultipleFiles=false`, place the single file at the generator output root instead of a `schemas/` subfolder | `boolean` | `true` |
960
- | `pureModels` | Emit plain model object schemas (no operation args wiring) | `boolean` | `false` (implicitly true in minimal mode) |
961
- | `pureModelsLean` | When pure models are enabled, omit JSDoc/statistics & field doc blocks for minimal output | `boolean` | `true` |
962
- | `pureModelsIncludeRelations` | When pureModels are enabled, include relation fields (lazy refs). Default excludes relations for slimmer objects | `boolean` | `false` |
963
- | `dateTimeStrategy` | Mapping for Prisma `DateTime` ("date" | "coerce" | "isoString") | `string` | `"date"` |
964
- | `emit.enums` | Explicitly emit enum schemas | `boolean` | `true` |
965
- | `emit.objects` | Emit input/object schemas (`objects/`) | `boolean` | `true` |
966
- | `emit.crud` | Emit CRUD operation arg schemas | `boolean` | `true` |
967
- | `emit.results` | Emit result schemas (`results/`) | `boolean` | heuristic (off in minimal) |
968
- | `emit.pureModels` | Emit pure model schemas (overrides heuristics) | `boolean` | mirrors `pureModels` |
969
- | `emit.variants` | Emit variant wrapper/index | `boolean` | `true` if any variant enabled |
970
- | `naming.pureModel.filePattern` | Pure model file name pattern (tokens) | `string` | `{Model}.schema.ts` |
971
- | `naming.pureModel.schemaSuffix` | Suffix for schema const | `string` | `Schema` |
972
- | `naming.pureModel.typeSuffix` | Suffix for inferred type export | `string` | `Type` |
973
- | `naming.pureModel.exportNamePattern` | Pattern for schema export variable | `string` | `{Model}{SchemaSuffix}` |
974
- | `naming.preset` | Apply preset naming (see below) | `string` | `default` |
975
-
976
- ### Advanced Configuration
977
-
978
- ```prisma
979
- generator zod {
980
- provider = "prisma-zod-generator"
981
- output = "./src/schemas"
982
- // File output mode
983
- // true -> multiple files (default)
984
- // false -> single file bundle (see singleFileName below)
985
- useMultipleFiles = true
986
- // Optional: name of the single-file bundle when useMultipleFiles = false
987
- // Defaults to "schemas.ts"
988
- singleFileName = "schemas.ts"
989
- // Optional: when useMultipleFiles = false, place the single file at the
990
- // generator output root (true) or inside a schemas/ subdir (false)
991
- placeSingleFileAtRoot = true
992
- isGenerateSelect = true
993
- isGenerateInclude = true
994
- // Pure model + DateTime handling examples
995
- pureModels = true // enable pure model schemas (can also go in JSON)
996
- pureModelsLean = true // default: lean (no doc banners)
997
- pureModelsIncludeRelations = true // opt-in to emit relation fields (default false)
998
- dateTimeStrategy = "coerce" // accept strings/numbers, coerce to Date
999
- // Explicit emission overrides:
1000
- // Example zod-generator.config.json:
1001
- // {
1002
- // "emit": {
1003
- // "enums": true,
1004
- // "objects": false,
1005
- // "crud": false,
1006
- // "results": false,
1007
- // "pureModels": true,
1008
- // "variants": true
1009
- // }
1010
- // }
1011
- // Omit any key to fall back to legacy heuristics (e.g. minimal mode pruning).
1012
- config = "./zod-config.json"
1013
- }
1014
- ```
1015
-
1016
- ### Model Customizations
1017
-
1018
- ```prisma
1019
- /// @@Gen.model(hide: true)
1020
- model InternalLog {
1021
- id Int @id @default(autoincrement())
1022
- message String
1023
- createdAt DateTime @default(now())
1024
- }
1025
- ```
1026
-
1027
- ### JSON Configuration File
1028
-
1029
- ```json
1030
- {
1031
- "mode": "custom",
1032
- "output": "./generated/schemas",
1033
- "relationModel": true,
1034
- "modelCase": "PascalCase",
1035
- "modelSuffix": "Schema",
1036
- "useMultipleFiles": true,
1037
- "placeSingleFileAtRoot": true,
1038
- "createInputTypes": true,
1039
- "addIncludeType": true,
1040
- "addSelectType": true,
1041
- "validateWhereUniqueInput": true,
1042
- "prismaClientPath": "@prisma/client"
1043
- // Explicit emission
1044
- // "emit": { "crud": false, "objects": false, "results": false, "variants": true, "enums": true }
1045
- }
1046
- ```
1047
-
1048
- ### Naming Customization
1049
-
1050
- Configure pure model naming:
1051
-
1052
- ```json
1053
- {
1054
- "pureModels": true,
1055
- "naming": {
1056
- "pureModel": {
1057
- "filePattern": "{model}.zod.ts",
1058
- "schemaSuffix": "Zod",
1059
- "typeSuffix": "Shape",
1060
- "exportNamePattern": "{Model}{SchemaSuffix}",
1061
- "legacyAliases": false
1062
- }
1063
- }
1064
- }
1065
- ```
1066
-
1067
- Tokens:
1068
- - `{Model}` PascalCase model name
1069
- - `{model}` / `{camel}` camelCase
1070
- - `{kebab}` kebab-case
1071
- - `{SchemaSuffix}` / `{TypeSuffix}` resolved suffix values
1072
-
1073
- Presets:
1074
- - `zod-prisma` β†’ keeps `ModelSchema`, adds legacy alias
1075
- - `zod-prisma-types` β†’ primary export without suffix + legacy alias
1076
- - `legacy-model-suffix` β†’ reintroduces `.model.ts` + `Model` suffix
1077
-
1078
- Override any field after applying a preset.
1079
-
1080
- Detailed preset behavior:
1081
-
1082
- | Preset | File Pattern | Primary Const Export | Inferred Type Export | Legacy Aliases Emitted | Intended Use Case |
1083
- |--------|--------------|----------------------|----------------------|------------------------|-------------------|
1084
- | default | `{Model}.schema.ts` | `UserSchema` | `UserType` | No | Current built‑in style (no config needed) |
1085
- | zod-prisma | `{Model}.schema.ts` | `UserSchema` | `UserType` | Yes (`UserModel`, `UserType`) | Migrate from prior community libs that used `ModelSchema` but also relied on `UserModel` name |
1086
- | zod-prisma-types | `{Model}.schema.ts` | `User` | `User` (no suffix) | Yes (`UserSchema`, `UserType`) | Emulate style where primary export is unsuffixed but compatibility aliases are needed |
1087
- | legacy-model-suffix | `{Model}.model.ts` | `UserModel` | `UserModelType` | No | Restore historical `.model.ts` file naming with `Model` suffix |
1088
-
1089
- Examples:
1090
-
1091
- ```jsonc
1092
- // zod-prisma
1093
- {
1094
- "pureModels": true,
1095
- "naming": { "preset": "zod-prisma" }
1096
- }
1097
-
1098
- // zod-prisma-types (empty suffix primary export + aliases)
1099
- {
1100
- "pureModels": true,
1101
- "naming": { "preset": "zod-prisma-types" }
1102
- }
1103
-
1104
- // legacy-model-suffix (.model.ts files + Model suffix, no aliases)
1105
- {
1106
- "pureModels": true,
1107
- "naming": { "preset": "legacy-model-suffix" }
1108
- }
1109
-
1110
- // Start from a preset then override just the file pattern
1111
- {
1112
- "pureModels": true,
1113
- "naming": {
1114
- "preset": "zod-prisma",
1115
- "pureModel": { "filePattern": "{Model}.validation.ts" }
1116
- }
1117
- }
1118
- ```
1119
-
1120
- Override precedence notes:
1121
- 1. A `preset` seeds base values.
1122
- 2. Keys under `naming.pureModel` override only the ones you specify (others inherit from the preset).
1123
- 3. Leaving `pureModel` empty ( `{}` ) ensures the preset is applied untouched (this is what the generator defaults to internally).
1124
-
1125
- Migration tips:
1126
- - Coming from `.model.ts` style: set `preset` to `legacy-model-suffix` (no further changes needed).
1127
- - Want to gradually adopt suffixless exports but keep old names available: use `zod-prisma-types` first; remove aliases later by disabling `legacyAliases`.
1128
- - Need a custom pattern: supply `filePattern` (must end with `.ts`) and adjust `exportNamePattern` plus suffixes.
1129
-
1130
- Validation rules:
1131
- - `filePattern` must contain `{Model}` (or another token that yields a unique name) and end with `.ts`.
1132
- - Empty `schemaSuffix` or `typeSuffix` is allowed; set explicit empty string `""` to clear the default.
1133
- - Avoid producing duplicate file names after token replacement; the generator will overwrite silently if collisions occur.
1134
-
1135
- #### DateTime Strategy Examples
1136
-
1137
- Choose how Prisma `DateTime` fields are represented at validation boundaries:
1138
-
1139
- ```jsonc
1140
- { "dateTimeStrategy": "date" } // -> z.date() (default)
1141
- { "dateTimeStrategy": "coerce" } // -> z.coerce.date() (flexible input)
1142
- { "dateTimeStrategy": "isoString" } // -> z.string().regex(ISO).transform(v => new Date(v))
1143
- ```
1144
-
1145
- #### pureModelsLean
1146
-
1147
- When `pureModels` are enabled, the default `pureModelsLean: true` suppresses large JSDoc header banners, schema statistics, and field documentation comments for ultra-small output. Set `pureModelsLean: false` to restore verbose docs:
1148
-
1149
- ```jsonc
1150
- {
1151
- "pureModels": true,
1152
- "pureModelsLean": false
1153
- }
1154
- ```
1155
-
1156
- Provides parity with popular β€œlean” generators while still allowing an opt-in to rich docs for teams that want them.
1157
-
1158
- </details>
1159
-
1160
- ---
1161
-
1162
- ## πŸ“– API Reference
1163
-
1164
- ## βš™οΈ Configuration sources, precedence, and availability
1165
-
1166
- This generator accepts configuration from two sources. When the same option is provided in multiple places, the value is resolved using a simple precedence.
1167
-
1168
- ### Sources
1169
-
1170
- - Prisma generator block (schema.prisma)
1171
- - Standard Prisma fields like `output`.
1172
- - Simple override flags/strings (e.g., `useMultipleFiles`, `singleFileName`, etc.).
1173
- - Optional `config = "./zod-generator.config.json"` to point to a JSON file.
1174
- - JSON config file (recommended for complex/nested settings)
1175
- - Full configuration surface, including nested structures like `models` and `variants`.
1176
- - Can be provided explicitly via `config = "./path.json"` or auto-discovered (e.g., `zod-generator.config.json`, `.zod-generator.json`).
1177
-
1178
- ### Precedence (highest β†’ lowest)
1179
-
1180
- 1) Prisma generator block options (direct attributes in `generator zod { ... }`)
1181
- 2) JSON config file (explicit or auto-discovered)
1182
- 3) Built-in defaults (computed based on `mode`, etc.)
1183
-
1184
- Notes and special cases:
1185
- - Output path: The Prisma generator’s `output` always decides where files go. Any `output` set in the JSON config is ignored.
1186
- - File layout: The Prisma generator’s `useMultipleFiles` and `singleFileName` override the JSON. Keep them aligned with any recipe you copy.
1187
- - Minimal mode: If `mode = "minimal"` (or legacy `minimal = true`), select/include schemas are forcibly disabled and many complex nested inputs are suppressed to speed up generation and shrink output.
1188
- - Legacy flags: `isGenerateSelect` / `isGenerateInclude` (Prisma block) override the newer `addSelectType` / `addIncludeType` (config JSON). Minimal mode will still force them off.
1189
-
1190
- Visibility of conflicts and overrides:
1191
- - Critical cases (e.g., file layout conflicts; minimal mode overriding select/include) are surfaced as tagged info lines prefixed with `[prisma-zod-generator]`.
1192
- - Detailed context and tips are printed only when debug logging is enabled.
1193
-
1194
- ### Option availability matrix
1195
-
1196
- | Option | Prisma generator block | JSON config file | Notes |
1197
- |---|---|---|---|
1198
- | `output` | Yes (authoritative) | Ignored if present | Use the Prisma generator `output` only |
1199
- | `useMultipleFiles` | Yes | Yes | `false` enables strict single-file mode |
1200
- | `singleFileName` | Yes | Yes | File name for the single bundle (default `schemas.ts`) |
1201
- | `placeSingleFileAtRoot` | Yes | Yes | Place single file at output root (true, default) or under `schemas/` (false) |
1202
- | `placeArrayVariantsAtRoot` | Yes | Yes | For array-based variants placement (root vs `variants/`) |
1203
- | `mode` (`full|minimal|custom`) | Yes | Yes | Minimal mode applies opinionated defaults |
1204
- | `pureModels` | Yes | Yes | Generates `models/` set when multi-file; N/A in single-file (content is bundled) |
1205
- | `globalExclusions` | β€” | Yes | Object keyed by variant (`input`, `result`, `pure`) |
1206
- | `variants` (object-based) | β€” | Yes | Nested structure; configure `pure/input/result` |
1207
- | `models.*` (per-model) | β€” | Yes | Nested per-model rules, operations, and variant overrides |
1208
- | `addSelectType` / `addIncludeType` | Yes (as legacy `isGenerateSelect` / `isGenerateInclude`) | Yes | Prisma block flags override the JSON values; minimal mode forces off |
1209
- | `formatGeneratedSchemas` | β€” | Yes | Formatting can be skipped for speed (default: false) |
1210
- | `config` (path to JSON) | Yes | β€” | Points to the JSON file; not a config value itself |
1211
-
1212
- Example: Prisma block overrides JSON file
1213
-
1214
- ```prisma
1215
- generator zod {
1216
- provider = "prisma-zod-generator"
1217
- output = "./generated"
1218
- // Overrides values from the JSON config below
1219
- useMultipleFiles = false
1220
- singleFileName = "bundle.ts"
1221
- placeSingleFileAtRoot = true
1222
- // Load additional (nested) settings from a JSON file
1223
- config = "./zod-generator.config.json"
1224
- }
1225
- ```
1226
-
1227
- When both sources specify the same simple option (e.g., `useMultipleFiles`), the Prisma block wins. Nested settings (like `models` and `variants`) should live in the JSON file.
1228
-
1229
- Tip when using recipes: If you want models-only (multi-file) but your generator block still has `useMultipleFiles = false` from a previous setup, you'll see extra files or a bundle you didn't expect. Open the matching recipe folder under `recipes/<name>/` and copy the generator block from its `schema.prisma`.
1230
-
1231
- ### How @zod schema comments fit into precedence
1232
-
1233
- Inline `@zod` comments in your Prisma schema are not a separate β€œconfig source,” but they do affect field-level validation and are always respected when that field is generated.
1234
-
1235
- - Scope: Applies only to the field where the comment appears, and only in schemas that include that field (subject to filtering, variants, minimal mode).
1236
- - Merge behavior: Field validation is built by combining pieces. In practice, the chain is composed of the base Zod type plus any optional/nullable handling, any config-driven validations (e.g., variant `additionalValidation`), and your `@zod` comment directives. If multiple validations of the same kind are present, they’re appended in order; the latter call wins when there’s a conflict.
1237
- - Not a global override: `@zod` comments do not override global settings like `output`, `mode`, or file layout; they only enrich the field’s Zod chain.
1238
- - Filtering/minimal mode: If a field or schema is excluded by filters/variants/minimal mode, its comments simply won’t apply because that schema isn’t emitted.
1239
-
1240
- See the β€œ@zod Comment Annotations” section for syntax and examples.
1241
-
1242
- <details>
1243
- <summary><strong>πŸ“š Generated Schema Types</strong></summary>
1244
-
1245
- ### Operation Schemas
1246
-
1247
- - **Create Operations**: `ModelCreateOneSchema`, `ModelCreateManySchema`
1248
- - **Read Operations**: `ModelFindManySchema`, `ModelFindUniqueSchema`, `ModelFindFirstSchema`
1249
- - **Update Operations**: `ModelUpdateOneSchema`, `ModelUpdateManySchema`, `ModelUpsertSchema`
1250
- - **Delete Operations**: `ModelDeleteOneSchema`, `ModelDeleteManySchema`
1251
- - **Aggregate Operations**: `ModelAggregateSchema`, `ModelGroupBySchema`
1252
-
1253
- ### Input Object Schemas
1254
-
1255
- - **Create Inputs**: `ModelCreateInputObjectSchema`, `ModelCreateNestedInputObjectSchema`
1256
- - **Update Inputs**: `ModelUpdateInputObjectSchema`, `ModelUpdateNestedInputObjectSchema`
1257
- - **Where Inputs**: `ModelWhereInputObjectSchema`, `ModelWhereUniqueInputObjectSchema`
1258
- - **Order Inputs**: `ModelOrderByInputObjectSchema`
1259
-
1260
- ### Select & Include Schemas
1261
-
1262
- When enabled with `isGenerateSelect: true` and `isGenerateInclude: true`:
1263
- - **Select Schemas**: `ModelSelectObjectSchema`
1264
- - **Include Schemas**: `ModelIncludeObjectSchema`
1265
-
1266
- ### Schema Naming Convention
1267
-
1268
- All generated schemas follow this pattern:
1269
- ```
1270
- {ModelName}{Operation}{Type}Schema
1271
- ```
1272
-
1273
- Examples:
1274
- - `UserCreateOneSchema` - Schema for creating a single user
1275
- - `PostFindManyArgsSchema` - Schema for finding multiple posts with arguments
1276
- - `UserWhereInputObjectSchema` - Schema for user where conditions
1277
-
1278
- </details>
1279
-
1280
- ---
1281
-
1282
- ## 🌐 Framework Examples
1283
-
1284
- <details>
1285
- <summary><strong>πŸš€ Next.js Integration</strong></summary>
1286
-
1287
- ### API Routes
1288
-
1289
- ```typescript
1290
- // pages/api/users.ts
1291
- import type { NextApiRequest, NextApiResponse } from 'next';
1292
- import { UserCreateOneSchema } from '../../generated/schemas';
1293
-
1294
- export default async function handler(req: NextApiRequest, res: NextApiResponse) {
1295
- if (req.method === 'POST') {
1296
- try {
1297
- const userData = UserCreateOneSchema.parse(req.body);
1298
- const user = await prisma.user.create(userData);
1299
- res.status(201).json(user);
1300
- } catch (error) {
1301
- res.status(400).json({ error: error.message });
1302
- }
1303
- }
1304
- }
1305
- ```
1306
-
1307
- ### App Router (Next.js 13+)
1308
-
1309
- ```typescript
1310
- // app/api/users/route.ts
1311
- import { NextRequest, NextResponse } from 'next/server';
1312
- import { UserCreateOneSchema } from '@/generated/schemas';
1313
-
1314
- export async function POST(request: NextRequest) {
1315
- try {
1316
- const body = await request.json();
1317
- const userData = UserCreateOneSchema.parse(body);
1318
- const user = await prisma.user.create(userData);
1319
- return NextResponse.json(user);
1320
- } catch (error) {
1321
- return NextResponse.json({ error: error.message }, { status: 400 });
1322
- }
1323
- }
1324
- ```
1325
-
1326
- </details>
1327
-
1328
- <details>
1329
- <summary><strong>⚑ tRPC Integration</strong></summary>
1330
-
1331
- ```typescript
1332
- import { z } from 'zod';
1333
- import { PostCreateOneSchema, PostFindManySchema } from './generated/schemas';
1334
-
1335
- export const postRouter = router({
1336
- create: publicProcedure
1337
- .input(PostCreateOneSchema)
1338
- .mutation(({ input }) => {
1339
- return prisma.post.create(input);
1340
- }),
1341
-
1342
- list: publicProcedure
1343
- .input(PostFindManySchema)
1344
- .query(({ input }) => {
1345
- return prisma.post.findMany(input);
1346
- }),
1347
- });
1348
- ```
1349
-
1350
- </details>
1351
-
1352
- <details>
1353
- <summary><strong>πŸ› οΈ Fastify Integration</strong></summary>
1354
-
1355
- ```typescript
1356
- import fastify from 'fastify';
1357
- import { UserCreateOneSchema } from './generated/schemas';
1358
-
1359
- const server = fastify();
1360
-
1361
- server.post('/users', {
1362
- schema: {
1363
- body: UserCreateOneSchema
1364
- }
1365
- }, async (request, reply) => {
1366
- const user = await prisma.user.create(request.body);
1367
- return user;
1368
- });
1369
- ```
1370
-
1371
- </details>
1372
-
1373
- <details>
1374
- <summary><strong>🌐 Express.js Integration</strong></summary>
1375
-
1376
- ```typescript
1377
- import express from 'express';
1378
- import { UserCreateOneSchema, UserFindManySchema } from './generated/schemas';
1379
-
1380
- const app = express();
1381
-
1382
- // Create user with validation
1383
- app.post('/users', async (req, res) => {
1384
- try {
1385
- const data = UserCreateOneSchema.parse(req.body);
1386
- const user = await prisma.user.create(data);
1387
- res.json(user);
1388
- } catch (error) {
1389
- if (error instanceof z.ZodError) {
1390
- return res.status(400).json({ errors: error.errors });
1391
- }
1392
- res.status(500).json({ error: 'Internal server error' });
1393
- }
1394
- });
1395
-
1396
- // Query with validation
1397
- app.get('/users', async (req, res) => {
1398
- const query = UserFindManySchema.parse(req.query);
1399
- const users = await prisma.user.findMany(query);
1400
- res.json(users);
1401
- });
1402
- ```
1403
-
1404
- </details>
1405
-
1406
- ---
1407
-
1408
- ## πŸ§ͺ Testing & Development
1409
-
1410
- <details>
1411
- <summary><strong>πŸ”¬ Testing Infrastructure</strong></summary>
1412
-
1413
- ### Test Suite Overview
1414
-
1415
- We maintain **enterprise-grade testing standards** with comprehensive coverage:
1416
-
1417
- #### πŸ“Š **Test Statistics**
1418
- - **πŸ“Š 80+ Tests Passing** - Comprehensive validation across all features
1419
- - **πŸ” 5,239 Schemas Validated** - Massive multi-provider testing
1420
- - **βœ… 100% TypeScript Compilation** - Zero compilation errors guaranteed
1421
- - **πŸ›‘οΈ Zero ESLint Issues** - Clean, maintainable code quality
1422
-
1423
- #### πŸ“‹ **Test Categories**
1424
-
1425
42
  ```bash
1426
- # Core infrastructure tests
1427
- npm run test:core # Configuration & integration tests
1428
- npm run test:esm # ESM import handling tests
1429
- npm run test:comprehensive # Multi-provider schema validation
1430
-
1431
- # Feature-specific tests
1432
- npm run test:config # Configuration system validation
1433
- npm run test:variants # Schema variant generation
1434
- npm run test:filtering # Model/field filtering logic
1435
- npm run test:pure-models # Pure model schema generation
1436
- npm run test:result-schemas # Result schema validation
1437
- npm run test:zod-comments # @zod comment parsing
1438
- npm run test:field-exclusion # Field exclusion system
1439
-
1440
- # Advanced testing
1441
- npm run test:integration # Full generation pipeline tests
1442
- npm run test:multi-provider # All database provider validation
1443
- npm run test:performance # Schema generation performance
1444
- npm run test:coverage # Code coverage analysis
1445
- ```
1446
-
1447
- </details>
1448
-
1449
- <details>
1450
- <summary><strong>πŸ§ͺ Testing Integration</strong></summary>
1451
-
1452
- ### Schema Testing Utilities
1453
-
1454
- ```typescript
1455
- import { SchemaTestUtils } from './test-utils';
1456
-
1457
- // Validate schema structure
1458
- SchemaTestUtils.testValidData(UserCreateInputSchema, {
1459
- email: 'test@example.com',
1460
- name: 'Test User'
1461
- });
1462
-
1463
- // Test boundary conditions
1464
- SchemaTestUtils.testBoundaryValues(UserCreateInputSchema, [
1465
- { value: { email: 'invalid-email' }, shouldPass: false },
1466
- { value: { name: 'x'.repeat(51) }, shouldPass: false },
1467
- { value: { name: 'Valid Name' }, shouldPass: true }
1468
- ]);
1469
-
1470
- // Performance testing
1471
- const performance = SchemaTestUtils.performanceTest(
1472
- UserCreateInputSchema,
1473
- validUserData,
1474
- 1000 // iterations
1475
- );
1476
- console.log(`Avg validation time: ${performance.avgTime}ms`);
43
+ # bun
44
+ bun add -d prisma-zod-generator zod
1477
45
  ```
1478
46
 
1479
- ### Development Setup
1480
-
1481
- ```bash
1482
- # Clone and setup
1483
- git clone https://github.com/your-username/prisma-zod-generator.git
1484
- cd prisma-zod-generator
1485
- npm install
1486
-
1487
- # Development build
1488
- npm run gen-example
1489
-
1490
- # Run tests
1491
- npm test
1492
-
1493
- # Code quality
1494
- npm run lint # Check and fix linting issues
1495
- npm run format # Format code with Prettier
1496
- ```
1497
-
1498
- </details>
1499
-
1500
- <details>
1501
- <summary><strong>πŸ“ˆ Multi-Database Provider Validation</strong></summary>
1502
-
1503
- Our test suite validates schemas across **6 database providers**:
1504
-
1505
- | Provider | Schemas Validated | Status |
1506
- |----------|------------------|---------|
1507
- | **PostgreSQL** | 1,020 schemas | βœ… |
1508
- | **MySQL** | 1,326 schemas | βœ… |
1509
- | **MongoDB** | 855 schemas | βœ… |
1510
- | **SQLite** | 1,409 schemas | βœ… |
1511
- | **SQL Server** | 622 schemas | βœ… |
1512
- | **Default** | Additional schemas | βœ… |
1513
-
1514
- </details>
1515
-
1516
- ---
1517
-
1518
- ## πŸ” Troubleshooting
1519
-
1520
- <details>
1521
- <summary><strong>🚨 Common Issues & Solutions</strong></summary>
1522
-
1523
- ### Generator Compatibility Errors
1524
-
1525
- **Issue**: Cannot find compatible Prisma generator
1526
- ```bash
1527
- Error: No compatible Prisma client generator found
1528
- ```
1529
-
1530
- **Solution**: Ensure you have a supported generator in your schema:
47
+ **2. Add to schema.prisma**
1531
48
  ```prisma
1532
- generator client {
1533
- provider = "prisma-client-js" // or "prisma-client"
1534
- }
1535
-
1536
49
  generator zod {
1537
- provider = "prisma-zod-generator"
1538
- output = "./generated/schemas"
1539
- }
1540
- ```
1541
-
1542
- ### Module Resolution Errors
1543
-
1544
- **Issue**: `Cannot find module './generated/schemas'`
1545
-
1546
- **Solutions**:
1547
- 1. Run `npx prisma generate` after adding the generator
1548
- 2. Check that your output path is correct
1549
- 3. Verify the generator completed successfully
1550
-
1551
- ### TypeScript Compilation Errors
1552
-
1553
- **Issue**: Generated schemas have TypeScript errors
1554
-
1555
- **Solutions**:
1556
- 1. Enable strict mode in `tsconfig.json`:
1557
- ```json
1558
- {
1559
- "compilerOptions": {
1560
- "strict": true,
1561
- }
1562
- }
1563
- ```
1564
- 2. Update dependencies: `npm update prisma-zod-generator prisma zod`
1565
- 3. Clear build cache and regenerate
1566
-
1567
- ### Generation Performance Issues
1568
-
1569
- **Issue**: Slow generation for large schemas
1570
-
1571
- **Solutions**:
1572
- 1. Use minimal mode:
1573
- ```json
1574
- {
1575
- "mode": "minimal",
1576
- "models": {
1577
- "AuditLog": { "enabled": false },
1578
- "Migration": { "enabled": false }
1579
- }
50
+ provider = "prisma-zod-generator"
1580
51
  }
1581
52
  ```
1582
- 2. Exclude unnecessary operations
1583
- 3. Enable selective model generation
1584
-
1585
- </details>
1586
-
1587
- <details>
1588
- <summary><strong>πŸ’‘ Performance Optimization Tips</strong></summary>
1589
53
 
1590
- ### Large Schema Optimization
1591
-
1592
- For projects with 50+ models:
1593
- - Use selective generation with model hiding
1594
- - Split schemas into multiple files
1595
- - Implement lazy loading for schemas
1596
- - Consider minimal mode for faster builds
1597
-
1598
- ### Build Time Optimization
1599
-
1600
- ```json
1601
- {
1602
- "mode": "minimal",
1603
- "models": {
1604
- "User": {
1605
- "operations": ["findMany", "create", "update"]
1606
- }
1607
- }
1608
- }
54
+ **3. Generate**
55
+ ```bash
56
+ npx prisma generate
1609
57
  ```
1610
58
 
1611
- ### Production Deployment
1612
-
1613
- ```typescript
1614
- // Environment-specific configuration
1615
- const productionConfig = {
1616
- mode: 'minimal',
1617
- globalExclusions: {
1618
- result: ['password', 'sessionToken', 'internalNotes']
1619
- }
1620
- };
59
+ **4. Use**
60
+ ```ts
61
+ import { UserSchema } from './prisma/generated/zod';
1621
62
  ```
1622
63
 
1623
- </details>
64
+ Optional config: add `prisma/zod-generator.config.json` only if you need tweaks.
1624
65
 
1625
- <details>
1626
- <summary><strong>❓ Frequently Asked Questions</strong></summary>
1627
66
 
1628
- **Q: Can I customize the generated validation rules?**
1629
- A: Modify your Prisma schema with `@zod` comments or use configuration options to customize validation.
67
+ ## ❀️ Sponsor
1630
68
 
1631
- **Q: Does this work with Prisma Edge Runtime?**
1632
- A: Yes, generated schemas are compatible with Prisma Edge Runtime.
69
+ If this generator saves you engineering hours or reduces production risk, sponsoring keeps it fast, stable, and evolving.
1633
70
 
1634
- **Q: How do I handle circular references?**
1635
- A: The generator automatically uses lazy loading for circular relationships.
71
+ Your support helps:
1636
72
 
1637
- **Q: Can I exclude certain fields from validation?**
1638
- A: Yes, use the `globalExclusions` or model-specific `excludeFields` configuration.
73
+ - Prioritized issue triage & regression fixes
74
+ - New variant / edge‑case coverage (providers, previews)
75
+ - Performance & DX improvements (leaner outputs, smarter filtering)
76
+ - Continued compatibility as Prisma & Zod evolve
1639
77
 
1640
- **Q: How do I handle enum validation?**
1641
- A: Enums are automatically converted to Zod enum schemas in the `enums/` directory.
78
+ Monthly tiers (GitHub Sponsors) unlock:
1642
79
 
1643
- </details>
1644
-
1645
- ---
1646
-
1647
- ## 🀝 Contributing
1648
-
1649
- <details>
1650
- <summary><strong>πŸ› οΈ Development Guidelines</strong></summary>
80
+ | Tier | Intended For | Perks |
81
+ | ---- | ------------- | ----- |
82
+ | Solo | Indie devs | πŸ’– Listed in README (opt‑in) |
83
+ | Team | Startups | Priority issues + roadmap influence |
84
+ | Scale | Companies | Early feature previews + escalation channel |
1651
85
 
86
+ ➑️ Sponsor here: https://github.com/sponsors/omar-dulaimi
1652
87
 
1653
- <details>
1654
- <summary><strong>πŸš€ Release Process</strong></summary>
88
+ One‑off support also welcome (GitHub custom amount).
1655
89
 
1656
- This project uses semantic versioning and automated releases:
1657
90
 
1658
- - Patch: Bug fixes and small improvements
1659
- - Minor: New features and enhancements
1660
- - Major: Breaking changes
91
+ ## Contribute
92
+ PRs welcome. Keep diffs small; no unrelated refactors.
1661
93
 
1662
- Helpful commands:
94
+ Before starting a feature or significant refactor: **open an issue / feature request first** (or discuss in an existing one) so we can:
95
+ - Confirm scope & fit
96
+ - Avoid duplicate / misaligned work
97
+ - Point you to internal patterns or existing WIP
1663
98
 
1664
- ```bash
1665
- npm run prerelease # Build, type-check, lint
1666
- npm run release:dry # Preview the next release
1667
- ```
99
+ Okay to skip issue for: typo fixes, tiny docs tweaks, test flake isolation.
1668
100
 
1669
- </details>
1670
- ### Contribution Process
101
+ See tests for coverage expectations.
1671
102
 
1672
- 1. **Create an issue** for bugs or feature requests
1673
- 2. **Fork and clone** the repository
1674
- 3. **Follow existing code style** (ESLint + Prettier)
1675
- 4. **Add comprehensive tests** for new functionality
1676
- 5. **Update documentation** as needed
1677
- 6. **Submit a pull request** with clear description
103
+ ## License
104
+ Released under the MIT License – see [LICENSE](./LICENSE) for full text.
1678
105
 
1679
- ### Code Quality Standards
106
+ Built & maintained by [Omar Dulaimi](https://github.com/omar-dulaimi) with community contributors.
1680
107
 
1681
- ```bash
1682
- npm run lint # Check and fix linting issues
1683
- npm run format # Format code with Prettier
1684
- npm test # Run comprehensive test suite
1685
- ```
1686
-
1687
- ### Testing Requirements
1688
-
1689
- When contributing new features:
1690
- 1. **Write tests first** - TDD approach
1691
- 2. **Test all edge cases** - Comprehensive scenarios
1692
- 3. **Validate across providers** - Multi-database compatibility
1693
- 4. **Performance testing** - Ensure scalability
1694
- 5. **Integration testing** - End-to-end validation
1695
-
1696
- </details>
1697
-
1698
- ---
1699
-
1700
- ## πŸ“„ License
1701
-
1702
- This project is licensed under the [MIT License](LICENSE).
1703
-
1704
- ---
1705
-
1706
- ## πŸ”— Related Projects
1707
-
1708
- - [prisma-trpc-generator](https://github.com/omar-dulaimi/prisma-trpc-generator) - Generate tRPC routers from Prisma schema
1709
- - [Prisma](https://github.com/prisma/prisma) - Database toolkit and ORM
1710
- - [Zod](https://github.com/colinhacks/zod) - TypeScript-first schema validation
1711
-
1712
- ---
1713
-
1714
- <div align="center">
1715
-
1716
- <h3>🌟 **Show Your Support** 🌟</h3>
1717
-
1718
- <a href="https://github.com/omar-dulaimi/prisma-zod-generator">
1719
- <img src="https://img.shields.io/github/stars/omar-dulaimi/prisma-zod-generator?style=for-the-badge&logo=github&color=yellow" alt="GitHub Stars">
1720
- </a>
1721
-
1722
- <br><br>
1723
-
1724
- <p>
1725
- <strong>Made with ❀️ by</strong>
1726
- <a href="https://github.com/omar-dulaimi">
1727
- <img src="https://img.shields.io/badge/Omar_Dulaimi-100000?style=for-the-badge&logo=github&logoColor=white" alt="Omar Dulaimi">
1728
- </a>
1729
- </p>
1730
-
1731
- <p><em>⚑ Accelerating Prisma development, one schema at a time</em></p>
1732
-
1733
- </div>