cartergrimmeisen / zod-prisma Goto Github PK
View Code? Open in Web Editor NEWA custom prisma generator that creates Zod schemas from your Prisma model.
License: MIT License
A custom prisma generator that creates Zod schemas from your Prisma model.
License: MIT License
Hello there.
Whenever I use zod to validate my schema, i validate the data coming from userland. That means any HTTP/REST API, MQTT API etc. needs to get validated in order to create or update a database entry.
That means, all fields that are autogenerated (denoted by prisma with @id
) should be marked as optional
or removed from the model, as they are not needed neither in create or update mechanisms.
Fields that have a default value (denoted by @default
) should be optional. This could be solved by making the field itself optional with ?
. However, I would like to disallow explicitly setting null
, but allow implicitly accepting the default value by omitting the field.
This could be solved with /// @zod.optional()
in the schema, but could also be a sensible default.
What are your thoughts? Is it worth to introduce an option for the generator? Am I maybe understanding something wrong?
In the end it is not so urgent, because it can be fixed on my end applying the correct types.
Thanks!
Hi, I am using zod-prisma but I would love have more examples, tip and tricks about use your package. :) Can you please write article when you have time?
Hey Carter,
I came across this project and I'd love to use it. Really awesome to see that someone else already put the hard work into the project that I need. But I really need to use Prisma@3, and this project's dependencies require Prisma@2. Is there any possibility that I could help you update this project to Prisma@3?
Glad I found this, but trying to add any custom option to the generator section in my schema.prisma
file results in prisma complaining:
$ npx prisma generate
Environment variables loaded from .env
Prisma schema loaded from db/schema.prisma
Error: Get config: Schema Parsing P1012
error: Error validating: This line is not a valid definition within a generator.
--> schema.prisma:10
|
9 | provider = "zod-prisma"
10 | output = "../somewhere" // the directory where generated zod schemas will be saved
|
...
Validation Error Count: x
Looks like prisma is unaware of the options the zod-prisma
provider exposes. Can this be fixed?
Hello,
I just installed this generator to try it out, but so far nothing is working.
I attempted to run it on two separate projects, one has a small prisma and the other has a relatively large one.
Both didn't work, and remained stuck.
I can't share the schemas unfortunately. So, any ideas what could the problem be?
I also enabled strict in tsconfig, still the same.
prisma : 3.6.0
@prisma/client : 3.6.0
Current platform : debian-openssl-1.1.x
Query Engine (Node-API) : libquery-engine dc520b92b1ebb2d28dc3161f9f82e875bd35d727 (at node_modules/@prisma/engines/libquery_engine-debian-openssl-1.1.x.so.node)
Migration Engine : migration-engine-cli dc520b92b1ebb2d28dc3161f9f82e875bd35d727 (at node_modules/@prisma/engines/migration-engine-debian-openssl-1.1.x)
Introspection Engine : introspection-core dc520b92b1ebb2d28dc3161f9f82e875bd35d727 (at node_modules/@prisma/engines/introspection-engine-debian-openssl-1.1.x)
Format Binary : prisma-fmt dc520b92b1ebb2d28dc3161f9f82e875bd35d727 (at node_modules/@prisma/engines/prisma-fmt-debian-openssl-1.1.x)
Default Engines Hash : dc520b92b1ebb2d28dc3161f9f82e875bd35d727
Studio : 0.440.0
typescript": "^4.5.2"
"zod-prisma": "^0.5.4"
{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"lib": ["es2018", "esnext.asynciterable"],
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"declaration": true,
"removeComments": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"sourceMap": false,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
"strict": true
}
}
I also cloned the example in this repo, but it had no zod-prisma configured at all. So, I added this from README:
generator zod {
provider = "zod-prisma"
output = "./zod"
relationModel = true
// relationModel = "default" // Do not export model without relations.
// relationModel = false // Do not generate related model
modelCase = "PascalCase"
// modelCase = "camelCase" // Output models using camel case (ex. userModel, postModel)
modelSuffix = "Model"
// useDecimalJs = false // (default) represent the prisma Decimal type using as a JS number
useDecimalJs = true
imports = null
// https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-by-null-values
prismaJsonNullability = true
// prismaJsonNullability = false // allows null assignment to optional JSON fields
}
but it also got stuck when I ran npx prisma generate
I use node v14.19.1
I upgraded to latest prisma version:
prisma : 3.13.0
@prisma/client : 3.13.0
Current platform : debian-openssl-1.1.x
Query Engine (Node-API) : libquery-engine efdf9b1183dddfd4258cd181a72125755215ab7b (at node_modules/@prisma/engines/libquery_engine-debian-openssl-1.1.x.so.node)
Migration Engine : migration-engine-cli efdf9b1183dddfd4258cd181a72125755215ab7b (at node_modules/@prisma/engines/migration-engine-debian-openssl-1.1.x)
Introspection Engine : introspection-core efdf9b1183dddfd4258cd181a72125755215ab7b (at node_modules/@prisma/engines/introspection-engine-debian-openssl-1.1.x)
Format Binary : prisma-fmt efdf9b1183dddfd4258cd181a72125755215ab7b (at node_modules/@prisma/engines/prisma-fmt-debian-openssl-1.1.x)
Default Engines Hash : efdf9b1183dddfd4258cd181a72125755215ab7b
Studio : 0.459.0
Still same issue!
If I got the following model:
model User {
/// other fields
name String?
}
It should produce the following zod schema:
const UserSchema = z.object({
name: z.string().nullable()
})
instead of:
const UserSchema = z.object({
name: z.string().nullish()
})
I believe that string | null
union type (from Prisma exports) suits better than string | undefined | null
union type got from Zod schemas
It would be nice to have the possibility to pass arguments to the z.string()
function.
This would be useful to, for example, set the required_error
option to some better message than just the default "Required"
One way of doing that could maybe look like this:
model User {
id String @id @default(uuid())
/// @zod {required_error: "Please enter a name"}
name String
}
which would generate the following
export const UserModel = z.object({
id: z.string(),
name: z.string({ required_error: "Please enter a name" })
});
You are unable to use this generator if you define custom prisma client output because this generator uses hardcoded import { Type } from '@prisma/client'
here which only exports types from default output path node_modules/.prisma/client
.
Hi. I'm trying to get this great library to work in a (Blitzjs with) Prisma project, but don't seem to get it installed properly.
Steps:
me@computer:~/project$ npm i --save-dev zod-prisma
added 10 packages, and audited 1714 packages in 12s
Add this to schema.prisma:
generator zod {
provider = "zod-prisma"
output = "./zod"
relationModel = "default"
}
Run blitz prisma migrate dev
, which results in this error:
Environment variables loaded from .env
Prisma schema loaded from db/schema.prisma
Datasource "db": SQLite database "db.sqlite" at "file:./db.sqlite"
Already in sync, no schema change or pending migration was found.
Running generate... (Use --skip-generate to skip the generators)
Error: Generator at zod-prisma could not start:
/bin/sh: 1: zod-prisma: not found
To me I loks like zod-prisma
haven't been properly installed, and I suspect must have missed something in the documentation have yet to find exactly what. Do you have any suggestions as to how to debug this?
In the mean while I'm going for node_modules/zod-prisma/bin/cli.js
as the provider.
Hi!
Fist of all, thank you for this package :)
I'm about to upgrade from Prisma v3 to v4. Unfortunately npm cli rejects to do the upgrade because the peer deps support only Prisma version ^3.0.0
. I've noticed you've already started working on zod-prisma
v1. Do you have some rough estimate when it's going to be released please?
Thank you in advance!
The 0.5.x releases and the change from .nullable()
to .nullish()
for optional fields have revealed a potential flaw in my application logic. Allow me to elaborate (this is not an issue per-se, but it can help others in a similar situation).
Optional fields in Prisma behave differently when reading and writing.
Let's use the following example model:
model User {
id String @id @default(uuid())
name String?
}
When writing data to the database (using create
/update
/upsert
model methods), the following input types are accepted:
Value type | on create |
on update /upsert |
---|---|---|
string |
insert value | replace value |
null |
keep field empty | make field empty |
undefined |
keep field empty | no-op |
This is because the UserCreateInput
type in Prisma looks like this:
export type UserCreateInput = {
id?: string
name?: string | null
}
On the other hand, when querying data, there are only two data types returned:
string
for existing field valuesnull
otherwiseNote that there is no undefined
on queried data.
This is because the User
type in Prisma looks like this:
export type User = {
id: string
name: string | null
}
I agree that the generated schemas should represent what Prisma will accept as input, in order to do pre-write validation.
However, I use z.TypeOf<typeof aSubsetOfASchema>
to generate partial types from the schemas, and have this single source of truth be used for:
zod-to-json-schema
)Example:
// On the server:
export const userNameReply = userSchema.pick({
name: true
})
export type UserNameReply = z.TypeOf<typeof userNameReply>
fastify.get<{ Reply: UserNameReply }>(
'/user/name',
{
schema: {
reply: {
200: zodToJsonSchema(userNameReply)
}
}
},
async (req, res) => {
const user = await req.server.prisma.user.findUnique({ where: {...} })
// The JSON schema on the reply guarantees only the `name` property is returned
return user
}
)
// In the client:
const res = await axios.get('/user/name')
const userName = userNameReply.parse(res.data)
// or
const res = await axios.get<UserNameReply>('/user/name')
const userName = res.data
Because the userNameReply
schema has .nullish()
optional fields, it adds incorrect undefined
constraints to the response data type.
As I said, this is not really an issue with zod-prisma
and more with the way I use it, but I thought it could open a discussion on this duality of input/output types in Prisma queries.
Note: I know of the z.input
and z.output
type inferring helpers, but those probably won't help here as they are internal to the schema structure.
I would like to use the generated schema-files also in my frontend (and not only in the backend, where these files are generated). But there is no (easy) way to copy them to my frontend project, because enum values are imported from '@prisma/client'. If these values were not imported by prisma client, but included, these files would be "exportable" to another project without any changes.
If you also like the idea of including enum values into the generated files, I would make a pull request.
This schema:
model User {
profilePicUrl String? /// @zod.url()
}
will generate the following output:
profilePicUrl: z.string().nullable().url()
which gives the error:
Property 'url' does not exist on type 'ZodNullable<ZodString>'
Solution: append .nullable()
after all potential rich-comment modifiers.
I have a need to intentionally stop zod-prisma generation, for example when running prisma generate
on CI.
It would be useful to be able to temporarily disable it via an environment variable.
e.g. ZOD_PRISMA_DISABLE=true yarn prisma generate
.
I have a need to add documentation to the beginning of model files.
For example, if I have a model that specifies imports
but does not use custom validation, I want to add // @ts-nocheck
to the top of the file because typescript will respond to an unused import clause and display an error.
Just delete import * as imports from ". /customs"
, the error does not occur, but it comes back every time I run prisma generate
.
How about adopting these config value?
generator zod {
provider = "zod-prisma"
output = "../app/zod"
imports = "../app/zod/customs"
relationModel = true
modelCase = "PascalCase"
modelSuffix = "Model"
useDecimalJs = true
prismaJsonNullability = true
additionalDoc = "// @ts-nocheck" <--
}
When a model has a JSON field, its relationship declaration will throw a type error.
// Example schema
model User {
id Int @id @default(autoincrement())
meta Json
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
authorId Int
author User @relation(fields: [authorId], references: [id])
}
The issue comes from the Json type resolving to z.any()
, and the extended schema not mapping correctly to the extended interface due to some part being optional and some other being required.
Rather than the builtin any
, the package could include some runtime helpers to resolve JSON types. See Zod's documentation for implementation suggestions, though this may cause some issues when trying to resolve the schema types using z.typeOf<typeof modelSchema>
.
Hi.
Thanks for this great utility.
I ran it on my schema, and got a file company.ts
containing something like this:
export const _BlogPostModel = z.object({
id: z.number().int(),
createdAt: z.date(),
updatedAt: z.date(),
name: z.string(),
})
export interface CompleteBlogPost extends BlogPost {
comments: CompleteComment[]
}
export const BlogPostModel: z.ZodSchema<CompleteBlogPost> = z.lazy(() =>
_BlogPostModel.extend({
comments: CommentModel.array(),
})
)
I'm not able to use BlogPostModel to validate input for updates to blogposts. But when creating a new blog post however, I need to omit id, createdAt and updatedAt. If I make use of _BlogPostModel
, I could do something like this:
# Location: Some file in my app, where I handle database access
import { _BlogPostModel } from "db/zod/blogpost"
export const CreateBlogPostModel = _BlogPostModel.omit({
id: true,
createdAt: true,
updatedAt: true,
})
The latter example is very hacky, as the underscore-prefixed variable I assume is not supposed to be used like this. On the other hand, BlogPostModel
doesn't support the omit
operation.
What's the recommended way to generate zod schemas that omit only the three fields mentioned?
A feature request could be to have zod-prisma to export one schema containing everything (like it does today) called for example BlogPostUpdateModel
, plus a BlogPostCreateModel
which omits the mentioned fields.
I can't build expected test file. Like below.
camelmasa@camelmasanoMacBook-Pro zod-prisma % yarn run tsc ./test/functional/recursive/expected/index.ts --noEmit
yarn run v1.23.0-20210726.1745
$ /Users/camelmasa/work/zod-prisma/node_modules/.bin/tsc ./test/functional/recursive/expected/index.ts --noEmit
test/functional/recursive/expected/comment.ts:21:14 - error TS2322: Type 'ZodLazy<ZodObject<extendShape<{ id: ZodString; author: ZodString; contents: ZodString; parentId: ZodString; }, { parent: ZodType<CompleteComment, ZodTypeDef, CompleteComment>; children: ZodArray<...>; }>, "strip", ZodTypeAny, { ...; }, { ...; }>>' is not assignable to type 'ZodType<CompleteComment, ZodTypeDef, CompleteComment>'.
Types of property '_type' are incompatible.
Type '{ id?: string; children?: CompleteComment[]; parent?: CompleteComment; author?: string; contents?: string; parentId?: string; }' is not assignable to type 'CompleteComment'.
Property 'parent' is optional in type '{ id?: string; children?: CompleteComment[]; parent?: CompleteComment; author?: string; contents?: string; parentId?: string; }' but required in type 'CompleteComment'.
21 export const RelatedCommentModel: z.ZodSchema<CompleteComment> = z.lazy(() => CommentModel.extend({
~~~~~~~~~~~~~~~~~~~
Found 1 error.
error Command failed with exit code 2.
Hi there, thanks for building this!
Are non-relative paths supported for the imports
config property? I'm seeing the following:
Given the following config in schema.prisma
:
generator zod {
imports = "@my-org/custom-zod"
}
The generated typescript contains a relative import path:
import * as imports from "../../prisma/@my-org/custom-zod"
import * as imports from "@my-org/custom-zod"
Hi, currently Decimal is represented with zod.number()
. While this may be some workable default, I would like to be able to use decimal.js, which is also used by Prisma.
Decimal
constructor takes number | string | Decimal
as input and returns Decimal
object.
Now imagine that you fetch data using HTTP, then you will most likely end up with some JSON object you want to parse.
Since JSON does not support Decimal objects, the input to Decimal
could be narrowed to just number | string
, which is ok, as your decimal data could be encoded by a string or a number – I would argue that the former is better as you don't lose precision when transferring data from your API to your consumers.
Given the above, this is how we could represent a Decimal type:
import { z } from "zod";
import { Decimal } from "decimal.js";
const decimalParser = z
.union([z.string(), z.number()])
.transform(value => new Decimal(value));
decimalParser.parse(42); // ok, returns Decimal instance
decimalParser.parse("3.14159265359"); // ok, returns Decimal instance
decimalParser.parse(true); // error, input is neither number nor string
I am not sure what would be the best way to do it in this project.
Looking at the code, I would either allow specifying custom zod constructors for various prisma field types in the options to generator zod
or using some annotation in field documentation like the documentation extensions.
Furthermore, I think neither is possible before #54 is merged though, because we need a way to dynamically import from decimal.js
.
What would be the optimal way to do this?
We get a TS error due to duplicated named imports.
This schema:
enum MyEnum {
A
B
}
enum MyOtherEnum {
A
B
}
model MyModel {
id String @id
a MyEnum[]
b MyOtherEnum?
c MyEnum[]
d MyOtherEnum?
}
Generates the following which results in the TS error
import {MyEnum, MyOtherEnum, MyEnum, MyOtherEnum} from '@prisma/client'
% npm ls zod-prisma
@gaia-family/[email protected] /Users/chrispearce/Projects/monorepo
└── [email protected]
Desired:
Imported identifier should only be written once.
In one of the files generated I have:
import { Gender } from "@prisma/client"
export const _UserModel = z.object({
id: z.string(),
gender: z.nativeEnum(Gender),
})
this causes a problem when I use native ESM modules. Node.js is not able to import that as named export:
SyntaxError: Named export 'Gender' not found. The requested module '@prisma/client' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from '@prisma/client';
const { QuestionnaireScheduleType } = pkg;
it would be much better to generate the file like this:
import prisma from "@prisma/client"
export const _UserModel = z.object({
id: z.string(),
gender: z.nativeEnum(prisma.Gender),
})
this way it will work fine on commonJS and native ESM.
There is an issue in prisma repo which might explain the problem further:
prisma/prisma#4816
Hey,
Jan from Prisma Engineering here.
Quick heads up that we will soon rename our @prisma/sdk
package to @prisma/internals
with Prisma 4, which we plan to release on June 28th (soon!).
The @prisma/sdk
package was meant as an Prisma internal package only, but somehow it leaked out over time and is now used across all kinds of tools - including yours of course 😄
With the rename of the Npm package we want to make it clearer that we can not give any API guarantees for @prisma/internals
, might need to introduce breaking changes to the API from time to time and will not follow semantic versioning (breaking changes only in major upgrade) with it. We think that it is better communicated with internals
than with sdk
.
With Prisma 4, besides the package name nothing should change though.
Additionally it would be super helpful if you could help us gain an understanding where, how and why you are using @prisma/sdk
(soon @prisma/internals
, remember 😀) to achieve, what exactly. We want to cleanup that package and your feedback will be valuable to us to define a better API.
Looking forward to your feedback.
Best
Jan & your friends at Prisma
PS: Are you using Prisma.dmmf
from import { Prisma } from '@prisma/client'
in your code somewhere by chance? That will also change soon and not include the Prisma.dmmf.schema
sub property. Instead you can use getDmmf
from @prisma/internals
moving forward.
Typescript 4.7 has support for ES modules using "type": "module"
, but relative import paths require .js
extensions.
Currently these are not generated.
Generated Zod schemas for complete records (with relations) report errors, see test/functional/recursive/expected/comment.ts
:
Type 'ZodLazy<ZodObject<extendShape<{ id: ZodString; author: ZodString; contents: ZodString; parentId: ZodString; }, { parent: ZodType<CompleteComment, ZodTypeDef, CompleteComment>; children: ZodArray<...>; }>, "strip", ZodTypeAny, { ...; }, { ...; }>>' is not assignable to type 'ZodType<CompleteComment, ZodTypeDef, CompleteComment>'.
Types of property '_type' are incompatible.
Type '{ id?: string; contents?: string; author?: string; parentId?: string; parent?: CompleteComment; children?: CompleteComment[]; }' is not assignable to type 'CompleteComment'.
Property 'parent' is optional in type '{ id?: string; contents?: string; author?: string; parentId?: string; parent?: CompleteComment; children?: CompleteComment[]; }' but required in type 'CompleteComment'.ts(2322)
I'll have a closer look and open a PR if I find a fix.
The relationModel is useful for simple models only with only a few relations.
But in real world projects, every model has many relations. In ein ERP solution i would like to validate an invoice with its items (related to invoice). But i don't want to validate the related customer, or products related to the items.
So for me the relationModel ist mostly useless. I would like to have (an additional) relationModel for every model (ex. optionalRelationModel) which has all relations as optional() so i could validate only the things i want.
Thanks
if useDecimalJs = true is defined, the helper schema for Decimal fields is created but not used.
details:
creates Helper (without assignment to const)
z
.instanceof(Decimal)
.or(z.string())
.or(z.number())
.refine((value) => {
try {
return new Decimal(value)
} catch (error) {
return false
}
})
.transform((value) => new Decimal(value))
does not use it in schema (ex. property price)
export const product = z.object({
id: z.string(),
name: z.string(),
price: z.number().nullish(),
})
We really need #108 as we want to use zod-prisma generated models in our NextJS frontend. We are having some troubles using the version via a Git-URL dependency, but as it's merged into 1.0-beta maybe you can release that as a pre-release (by appending -beta.<version>
to the version) to npm?
Thank you very much!
This feature request may be a bit far-fetched, feel free to close if out of scope, though I might give it a go if you're interested.
I have some fields which I'd like to annotate with a /// @zod.regex()
constraint. The content of the regex is defined somewhere else in the app, and needs to find its way to the generated file.
Currently, I'm copying the regex to the schema file, which is brittle as it exists in two places (and god knows it's easy enough to make mistakes in one regex, trying to keep two in sync is a footgun).
One way to make constraint extensions via documentation use external code would be to use rich-comments again, to define imports in the model.
Example API:
/// ```@zod
/// import { publicKeyRegex } from 'modules/crypto/box'
/// ```
model User {
publicKey String /// @zod.regex(publicKeyRegex)
}
Generated code:
import * as z from 'zod'
import { publicKeyRegex } from 'modules/crypto/box'
export const userModel = z.object({
publicKey: z.string().regex(publicKeyRegex)
})
Hey Carter, I like the new version of the library!
I just found a bug parsing zod.custom()
:
url String? @db.VarChar(400) /// @zod.custom(z.string().min(1).refine((val) => isURL(val)))
Is producing this: z.string(.refine((val).nullish()
So there is this parsing bug, but also reading the docs I understand that we need to specify it's a string but I'm not sure whether I should also specify it's nullish
Hi! Thanks for this amazing time saver.
I have started using it and I noticed that the unknown
type is incorrectly generated due to a typo.
The issue results in the following runtime error: ReferenceError: unknown is not defined
.
You can find the typo here:
Line 8 in 1962bec
The line should most likely read:
- let zodType = 'unknown()'
+ let zodType = 'z.unknown()'
As I tend to reserve PascalCase for class definitions, and camelCase for objects and literal definitions, it would be nice to be able to configure the output names of the generated Zod schemas:
export const userModel = z.object(...)
Also, as Zod names its objects schemas, allowing to change the suffix would be nice too:
export const userSchema = z.object(...)
Suggested API (with current defaults):
generator zod {
provider = "zod-prisma"
output = "./zod"
modelCase = "PascalCase" // options: "camelCase" | "PascalCase"
modelSuffix = "Model"
}
I can open a PR if you're interested.
Related packages: https://github.com/blakeembrey/change-case
Hi,
I've tried to generate Zod schemas but I'm getting errors. I've tried to install the package with both npm
and yarn
and the result was always the same whenever I try to generate prisma schemas.
npx prisma generate
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Error: Generator at zod-prisma could not start:
node:internal/modules/cjs/loader:936
throw err;
^
Error: Cannot find module '../dist/index'
Require stack:
First off, thanks a lot for v5.0.1, the imports feature is awesome!
I initially tried to store the imports file in the output directory, and the resolved path was missing a ./
prefix, example:
generator zod {
provider = "zod-prisma"
output = "./schemas"
imports = "./schemas/_imports"
}
import * from '_imports'
// should be import * from './_imports'
Now, this is probably a stupid idea to store this file there, so I've moved it somewhere else, no rush for a fix.
I'm encountering many cases of:
Type 'number | null | undefined' is not assignable to type 'number | undefined'.
Using nullish instead for optional fields could solve this issue.
Would be great to have support for zod-definitions on model level.
example:
/// @zod.refine((val) => val.type === 'PRIVATE' || val.company !== null, { path: 'company', message: 'Required if type is company' })
model Address {
id String @id @unique @default(uuid())
type AddressType
company String? /// @zod.min(1).max(50)
address String /// @zod.min(1).max(50)
zipCode String /// @zod.min(1).max(10)
city String /// @zod.min(1).max(50)
}
enum AddressType {
PRIVATE
COMPANY
}
When I run the generator zod includes the following after zod import:
import * as z from "zod"
import * as imports from "../null"
...
Am I missing something? This is my generator zod:
generator zod {
provider = "zod-prisma"
output = "./zod"
relationModel = true
modelCase = "camelCase"
modelSuffix = "Model"
useDecimalJs = true
imports = null
prismaJsonNullability = true
}
This is a survival check.
I find this library very useful and I like it very much. However, I am very disappointed that maintenance has stopped and there is no way to fix bugs and support the latest prisma(v4).
@CarterGrimmeisen Do you intend to continue the maintenance of this library? If not, please recruit maintainers and give them proper authority.
P.S. There is another similar library, but I personally don't like it because it generates a lot of files when running genarate.
For example, a schema like this:
model Test {
id Int @id @default(autoincrement())
/// @zod.custom(z.nativeEnum(imports.State))
state Int @default(0)
}
Where State
is defined in imports
like:
export enum State {
ONE,
TWO,
THREE
}
Generates:
export const TestModel = z.object({
id: z.number().int(),
state: z.nativeEnum(imports.State).int()
})
Which is invalid because nativeEnum
is number and don't have .int()
.
I can replace with a custom refine
, but this is not the question...
Is there a way to override the type of a property?
My use case: I'm using remix which has this concept of "loaders". Whatever data you return from your loaders you have it available in your ui. However, since the loaders run on a server the data gets serialized with JSON.stringify
this basically converts Date
types to String
.
This causes my prisma and zod-prisma types to be "incorrect". Is there a way I can force the type of a property?
Hello,
When I define a composite type it is not exported in zod folder.
Do you know why ?
datasource db {
provider = "mongodb"
url = "..."
}
generator zod {
provider = "zod-prisma"
}
type Photo {
height Int
width Int
url String
}
model Place {
id String @id @default(auto()) @map("_id") @db.ObjectId
photos Photo[]
}
I have the given (simplified) schema where User
and Keychain
have a 1-1 relationship:
datasource db {
provider = "postgresql"
url = env("DATABASE_URI")
}
generator client {
provider = "prisma-client-js"
}
generator zod {
provider = "zod-prisma"
output = "./schemas"
relationModel = true
}
model User {
id String @id @default(uuid())
keychain Keychain?
}
model Keychain {
userID String @id
owner User @relation(fields: [userID], references: [id])
}
Those relationships have to be defined as nullable on one end, but the generated user schema generates a TypeScript error:
import * as z from "zod"
import { CompleteKeychain, relatedKeychainSchema } from "./index"
export const userSchema = z.object({
id: z.string()
})
export interface CompleteUser extends z.infer<typeof userSchema> {
keychain: CompleteKeychain | null
}
/**
* relatedUserSchema contains all relations on your model in addition to the scalars
*
* NOTE: Lazy required in case of potential circular dependencies within schema
*/
export const relatedUserSchema: z.ZodSchema<CompleteUser> = z.lazy(() => userSchema.extend({
keychain: relatedKeychainSchema.nullish(), // <= ts2322
}))
Removing the .nullish()
modifier for the keychain in relatedUserSchema
fixes the issue.
Edit: using .nullable()
there works too, which was what was used before.
I'm finding it useful to create types of all my Prisma models: export type UserDB = z.infer<typeof UserModel>
I'm doing this because I end up cleaning data up a bit and transforming it when I pull it from the DB, so it makes some sense to create a new type derived from the base types which I can then use to construct more accurate types for the client code. zod-prisma
could do this when it's creating the complete types etc. I just wonder if anyone else is doing this and whether it would be a useful addition to the library?
According to Prisma's docs JSON fields cannot be directly set to null. Instead one can utilize Prisma.JsonNull
or Prisma.DbNull
in order to set the field to a JSON value of null or to NULL
the db field respectively.
My current plan is to update the generated zod schemas to match this behavior but I am curious as to what others think about this.
I'm not sure if there's already a support for this, but I ran into this issue using MySQL connector.
For a model like this, I think it's redundant to use @zod
keyword when there's clearly a criteria defined in the data models itself.
I want the library to be smart enough to understand the native column types if that's possible.
model User {
id String @id @default(uuid())
name String @unique @db.VarChar(15) ///@zod.max(15)
bio String? @db.VarChar(140) ///@zod.max(140)
email String @unique @db.VarChar(254) ///@zod.max(254)
password String @db.VarChar(255) ///@zod.max(255)
@@map("user")
}
Hi Carter, I'm been playing around with trying to pass in z.prepocess
in the Prisma comments because I need to preprocess an empty string to undefined so zod plays nicely with browser formData: The function is:
export function optionalField(zodValidation: z.ZodNullable<z.ZodString>) {
return z.preprocess((val) => (val === "" ? undefined : val), zodValidation);
}
I can't pass a function in the comments so I tried the direct route:
/// @zod.preprocess((val) => (val === "" ? undefined : val), z.min(1).max(600))
but that creates:
z.string().nullable().preprocess((val) => (val === "" ? undefined : val), z.min(1).max(600)),
while we're looking for:
z.preprocess((val) => (val === "" ? undefined : val), z.string().min(1).max(600).nullable()),
What do you think, is this doable?
Hi.
My generated zod file have suddenly started getting errors like this:
Syntax error: Identifier 'RelatedCommentModel' has already been declared
Extract from the file itself:
import { CompleteComment, RelatedCommentModel } from "./index"
export const CommentModel = z.object({ ....
export interface CompleteComment extends Comment { ....
export const RelatedCommentModel: z.ZodSchema<CompleteComment> = z.lazy(() => CommentModel.extend({ ....
I may be because my model references itself, i.e. the Comment
model references other comments.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.