prisma-extension-autozod 1.0.3 → 1.0.5
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 +87 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,14 +7,26 @@
|
|
|
7
7
|
> Contract-aware compile-time linting and runtime Zod validation for the new Prisma ORM (@prisma/orm-postgres).
|
|
8
8
|
|
|
9
9
|
`prisma-extension-autozod` connects **Zod 4** and **Prisma ORM 8**. It provides two layers of safety:
|
|
10
|
+
|
|
10
11
|
1. **Compile-time Linting**: TypeScript flags any field in your Zod schema that does not exist in your Prisma data contract.
|
|
11
12
|
2. **Runtime Middleware**: Automatically intercepts write operations (`create`, `update`, `insert`) via Prisma 8's `beforeCompile` hook, validates payloads, normalizes column naming conventions, and blocks invalid mutations before SQL reaches your database.
|
|
12
13
|
|
|
13
14
|
---
|
|
14
15
|
|
|
16
|
+
## Why prisma-extension-autozod?
|
|
17
|
+
|
|
18
|
+
| Feature | Manual Controller Validation | Schema Generators (zod-prisma) | prisma-extension-autozod |
|
|
19
|
+
| :--- | :--- | :--- | :--- |
|
|
20
|
+
| **Zero Controller Boilerplate** | No (Manual `.parse()`) | No (Manual `.parse()`) | Yes (Auto-intercepted) |
|
|
21
|
+
| **Prisma 8 Native Architecture** | No | No | Yes (`beforeCompile` / Contract) |
|
|
22
|
+
| **Compile-Time Typo Linter** | No | No | Yes (Immediate IDE feedback) |
|
|
23
|
+
| **Casing Normalization** | No | No | Yes (`first_name` <-> `firstName`) |
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
15
27
|
## Requirements
|
|
16
28
|
|
|
17
|
-
- **Node.js**: `>=
|
|
29
|
+
- **Node.js**: `>= 22.0.0`
|
|
18
30
|
- **Prisma ORM**: `@prisma/orm-postgres >= 8.0.0`
|
|
19
31
|
- **Zod**: `^4.0.0`
|
|
20
32
|
|
|
@@ -64,18 +76,30 @@ export const userValidator = defineModel(
|
|
|
64
76
|
"User",
|
|
65
77
|
z.object({
|
|
66
78
|
email: z.string().email("Invalid email address"),
|
|
67
|
-
username: z
|
|
68
|
-
|
|
69
|
-
|
|
79
|
+
username: z
|
|
80
|
+
.string()
|
|
81
|
+
.min(2, "Username must be at least 2 characters")
|
|
82
|
+
.nullable()
|
|
83
|
+
.optional(),
|
|
84
|
+
name: z
|
|
85
|
+
.string()
|
|
86
|
+
.min(2, "Name must be at least 2 characters")
|
|
87
|
+
.nullable()
|
|
88
|
+
.optional(),
|
|
89
|
+
}),
|
|
70
90
|
);
|
|
71
91
|
```
|
|
72
92
|
|
|
73
93
|
> **Compile-Time Safety in Action:**
|
|
74
94
|
> If you add a field that does not exist in the contract:
|
|
95
|
+
>
|
|
75
96
|
> ```typescript
|
|
76
|
-
> defineModel(
|
|
77
|
-
>
|
|
78
|
-
>
|
|
97
|
+
> defineModel(
|
|
98
|
+
> "User",
|
|
99
|
+
> z.object({
|
|
100
|
+
> nonExistentColumn: z.string(), // Error: Field 'nonExistentColumn' does not exist in table contract
|
|
101
|
+
> }),
|
|
102
|
+
> );
|
|
79
103
|
> ```
|
|
80
104
|
|
|
81
105
|
---
|
|
@@ -128,11 +152,43 @@ await db.orm.public.User.create({
|
|
|
128
152
|
});
|
|
129
153
|
|
|
130
154
|
// Update: Only supplied fields are validated
|
|
131
|
-
await db.orm.public.User
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
155
|
+
await db.orm.public.User.where({ email: "alice@prisma.io" }).update({
|
|
156
|
+
name: "Alice Wonder", // Valid; other fields are not required on updates
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
### 4. Column Normalization in Action
|
|
163
|
+
|
|
164
|
+
Incoming payloads from frontend forms or REST APIs often use `snake_case`. The middleware automatically remaps them to match your contract columns:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
// Incoming frontend payload uses snake_case:
|
|
168
|
+
await db.orm.public.User.create({
|
|
169
|
+
first_name: "Alice", // Automatically remapped to `firstName` in Postgres
|
|
170
|
+
email: "alice@prisma.io",
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### 5. Error Handling DX
|
|
177
|
+
|
|
178
|
+
Because validation throws standard `ZodError` instances, you can easily catch and format errors for HTTP responses in Express, NestJS, Fastify, or Hono:
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
import { ZodError } from "zod";
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
await db.orm.public.User.create(req.body);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
if (error instanceof ZodError) {
|
|
187
|
+
// Clean flattened validation errors directly back to the client
|
|
188
|
+
return res.status(400).json({ errors: error.flatten().fieldErrors });
|
|
189
|
+
}
|
|
190
|
+
throw error;
|
|
191
|
+
}
|
|
136
192
|
```
|
|
137
193
|
|
|
138
194
|
---
|
|
@@ -140,28 +196,36 @@ await db.orm.public.User
|
|
|
140
196
|
## API Reference
|
|
141
197
|
|
|
142
198
|
### `createZodRegistry<TModels>()`
|
|
199
|
+
|
|
143
200
|
Creates a model validator factory bound to your contract models. Validates that all fields in the schema exist in the contract table, allowing omission of auto-generated or optional fields.
|
|
201
|
+
|
|
144
202
|
```typescript
|
|
145
203
|
const defineModel = createZodRegistry<typeof models.public>();
|
|
146
204
|
const userValidator = defineModel("User", zodSchema);
|
|
147
205
|
```
|
|
148
206
|
|
|
149
207
|
### `createStrictZodRegistry<TModels>()`
|
|
208
|
+
|
|
150
209
|
Creates a strict validator factory that requires all columns in the contract table to be declared in the schema, while also rejecting unknown fields.
|
|
210
|
+
|
|
151
211
|
```typescript
|
|
152
212
|
const defineStrict = createStrictZodRegistry<typeof models.public>();
|
|
153
213
|
const userValidator = defineStrict("User", zodSchema);
|
|
154
214
|
```
|
|
155
215
|
|
|
156
216
|
### `autoZodPrisma8(options)` (alias: `autoZod`)
|
|
217
|
+
|
|
157
218
|
Prisma ORM 8 middleware factory:
|
|
219
|
+
|
|
158
220
|
- `options.contract`: The raw `contract.json` object.
|
|
159
221
|
- `options.validators`: Array of validator entries returned by `createZodRegistry` or `createStrictZodRegistry`.
|
|
160
222
|
|
|
161
223
|
### `extractColumns(contractJson)`
|
|
224
|
+
|
|
162
225
|
Helper function that inspects storage namespaces inside `contract.json` and returns a normalized dictionary of table column names.
|
|
163
226
|
|
|
164
227
|
### `normalizeKey(key: string)`
|
|
228
|
+
|
|
165
229
|
Normalizes strings to lowercase alphanumeric format for reliable case- and separator-insensitive mapping.
|
|
166
230
|
|
|
167
231
|
---
|
|
@@ -184,6 +248,17 @@ pnpm run build
|
|
|
184
248
|
|
|
185
249
|
---
|
|
186
250
|
|
|
251
|
+
## Contributing
|
|
252
|
+
|
|
253
|
+
Contributions, bug reports, and feature requests are welcome!
|
|
254
|
+
Feel free to check the [issues page](https://github.com/abzr0o/prisma-extension-autozod/issues).
|
|
255
|
+
|
|
256
|
+
## Support
|
|
257
|
+
|
|
258
|
+
If this library saves you time or prevents schema bugs in production, consider giving it a star on [GitHub](https://github.com/abzr0o/prisma-extension-autozod)!
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
187
262
|
## License
|
|
188
263
|
|
|
189
264
|
[MIT](LICENSE) (c) [Mohammed Thamer](https://github.com/abzr0o)
|
package/package.json
CHANGED