Prisma 2+ generator to emit Joi schemas from your Prisma schema
45
stars
74
commits
TypeScript
primary language
Jul 28, 2026
updated
🎯 Zero-config • 🛡️ Type-safe • ⚡ Fast • 🔧 Customizable
Automatically generates Joi schemas for all Prisma operations with full TypeScript support
If this tool accelerates your development, consider supporting its growth
✨ Your sponsorship drives innovation and keeps this project thriving ✨
|
|
| 🎉 Production Ready on Prisma 6 and Prisma 7! |
🆙 Prisma 6 and Prisma 7 Compatibility:
prisma-client, prisma-client-js, or neither🔧 Enhanced Development Experience - Modern tooling and CI/CD pipeline:
| 🚀 Feature | 📦 Version | 🎯 Benefit |
|---|---|---|
| New Prisma Client | 6.12.0+ | 🆕 ESM-compatible generator support |
| Prisma | 6.12.0+ and 7.x | 🏃♂️ Latest features & performance |
| Joi | 17.13.3+ | 🛡️ Enhanced validation & type safety |
| TypeScript | 5.8+ | ⚡ Cutting-edge language features |
| Testing | Vitest 3 | 🧪 Comprehensive coverage |
| Tooling | ESLint 9 | 🔧 Modern dev experience |
| Multi-DB | All Providers | 🗄️ PostgreSQL, MySQL, MongoDB, SQLite+ |
# 🚀 Install the latest release
npm install prisma-joi-generator
Requirements:
Update your dependencies and re-run npx prisma generate. Coming from 1.1.0 or earlier, read
how the generated schemas reference each other
first: the emitted output changed shape, because the shape it had could not be imported from an
ES module.
npm update prisma-joi-generator
npx prisma generate
|
Works instantly Sensible defaults included |
Always in sync Updates with schema changes |
100% TypeScript Catch errors at compile time |
Full CRUD coverage All Prisma operations included |
|
Highly customizable Adapt to your needs |
Minimal footprint Fast generation & runtime |
All databases PostgreSQL, MySQL, MongoDB+ |
Your way Custom paths & options |
# NPM
npm install prisma-joi-generator
# Yarn
yarn add prisma-joi-generator
# PNPM
pnpm add prisma-joi-generator
Star this repo 😉
Add the generator to your Prisma schema.
prisma generate refuses to run on a schema with no datasource block, so here is a
complete one that works as written. No client generator is required: add one if you want a
Prisma Client, leave it out if you only want Joi schemas.
Prisma 7 removed url from the datasource block. The connection URL goes in
prisma.config.ts instead:
generator joi {
provider = "prisma-joi-generator"
output = "./generated/schemas"
}
datasource db {
provider = "sqlite"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}
Prisma 6 and below keep the url on the datasource:
generator joi {
provider = "prisma-joi-generator"
output = "./generated/schemas"
}
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}
npx prisma generate
This generator reads the schema Prisma has already parsed, so it works next to any client generator, or next to none at all. It never imports or extends the Prisma Client.
Any of these work:
generator client {
provider = "prisma-client-js"
}
generator joi {
provider = "prisma-joi-generator"
output = "./generated/schemas"
}
generator client {
provider = "prisma-client"
output = "./src/generated/client"
runtime = "nodejs"
moduleFormat = "esm"
generatedFileExtension = "ts"
importFileExtension = "ts"
}
generator joi {
provider = "prisma-joi-generator"
output = "./generated/schemas"
}
generator joi {
provider = "prisma-joi-generator"
output = "./generated/schemas"
}
node_modulesExisting Projects: No changes needed - continue using prisma-client-js
New Projects: Consider using the new prisma-client generator for modern features
Gradual Migration: Both generators are supported simultaneously during the transition
Prisma 7 needs a release newer than 1.1.0. Up to and including 1.1.0 this package declared
@prisma/internalsas a dependency and re-parsed your schema with the copy of Prisma 6 that came with it. On a Prisma 7 schema that parse fails withP1012: Argument "url" is missing in data source block, reported under aPrisma CLI Version : 6.19.3banner from a project that has no Prisma 6 in it, and adding theurlback to satisfy it makes Prisma 7 itself reject the schema. There was no schema that both parsers accepted. Newer releases use the DMMF Prisma hands to every generator and carry no Prisma of their own.
For the following schema:
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String
content String?
published Boolean @default(false)
viewCount Int @default(0)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
likes BigInt
}
The generator creates different directory structures based on your configuration:
📁 generated/schemas/
├── 📁 enums/ // Enum validation schemas
│ ├── 📄 PostScalarFieldEnum.schema.ts
│ └── 📄 UserScalarFieldEnum.schema.ts
├── 📁 objects/ // Input type schemas
│ ├── 📄 UserCreateInput.schema.ts
│ ├── 📄 UserWhereInput.schema.ts
│ └── 📄 PostCreateInput.schema.ts
├── 📄 findManyUser.schema.ts
├── 📄 findUniqueUser.schema.ts
├── 📄 createOneUser.schema.ts
├── 📄 updateOneUser.schema.ts
├── 📄 deleteOneUser.schema.ts
├── 📄 findManyPost.schema.ts
├── 📄 createOnePost.schema.ts
└── 📄 index.ts // Barrel exports
📁 generated/schemas/
├── 📁 enums/ // Shared enums
├── 📁 models/
│ ├── 📁 user/
│ │ ├── 📄 findManyUser.schema.ts
│ │ ├── 📄 createOneUser.schema.ts
│ │ ├── 📁 objects/
│ │ │ ├── 📄 UserCreateInput.schema.ts
│ │ │ └── 📄 UserWhereInput.schema.ts
│ │ └── 📄 index.ts
│ └── 📁 post/
│ ├── 📄 findManyPost.schema.ts
│ ├── 📄 createOnePost.schema.ts
│ ├── 📁 objects/
│ └── 📄 index.ts
└── 📄 index.ts
📁 generated/schemas/
├── 📄 findManyUser.schema.ts
├── 📄 createOneUser.schema.ts
├── 📄 UserCreateInput.schema.ts
├── 📄 UserWhereInput.schema.ts
├── 📄 PostScalarFieldEnum.schema.ts
├── 📄 findManyPost.schema.ts
├── 📄 createOnePost.schema.ts
└── 📄 index.ts
Prisma's input types are cyclic: UserWhereInput reaches PostListRelationFilter, which
reaches PostWhereInput, which reaches back to UserWhereInput. TypeScript modules cannot
express that by importing each other, so the emitted object schemas do not. Each one refers to
the others with Joi.link('#TypeName'), and schemas/objects/index.ts exports an
objectSchemas registry that every link resolves against.
The generated root schemas already carry it, so most of the time this is invisible:
import { UserFindManySchema } from './generated/schemas';
// emitted as: objectSchemas.concat(Joi.object().keys({ ... }))
UserFindManySchema.validate({ where: { posts: { some: { title: { equals: 'hello' } } } } });
If you compose a schema out of the exported ...SchemaObject key bags yourself, concatenate
the registry onto it, otherwise Joi has nowhere to resolve the links and throws
AssertError: ... contains link reference ... which is outside of schema boundaries:
import Joi from 'joi';
import { objectSchemas, UserWhereInputSchemaObject } from './generated/schemas/objects';
const myFilter = objectSchemas.concat(Joi.object().keys(UserWhereInputSchemaObject));
Upgrading from 1.1.0 or earlier. Before this, object schemas embedded each other directly. That output could not be imported from an ES module at all, failing with
ReferenceError: Cannot access 'UserWhereInputSchemaObject' before initialization, and when compiled to CommonJS every reference across a cycle silently resolved toundefined, so each relation filter accepted absolutely anything. If you were relying on that, values nested under a relation filter are now validated, and a self-referentialwhere.ANDno longer throws.
| Version | Prisma | Joi | TypeScript | Node.js | Status |
|---|---|---|---|---|---|
| Latest | 6.12.0+ and 7.x | 17.13.3+ | 5.8+ | 18+ | ✅ Stable - verified against Prisma 6.19 and 7.9 on Node 22 and 24 |
| 1.1.0 and earlier | 6.12.0 - 6.x | 17.13.3+ | 5.8+ | 18+ | ⛔ Prisma 6 only - fails on Prisma 7, see the note above |
| Legacy | 4.0.0+ | 17.0+ | 4.7+ | 16+ | 📦 Deprecated - Limited Support |
Recommendation: Use
npm install prisma-joi-generatorfor the latest stable release with full features and modern tooling.
The Prisma Joi Generator offers powerful configuration options to customize file generation, organization, and filtering according to your project needs.
| Option | Description | Type | Default |
|---|---|---|---|
output | Output directory for generated files | string | "./generated" |
Control which types of validation schemas are generated:
| File Type | Description | Default |
|---|---|---|
create | Create operation schemas (createOne, createMany) | true |
update | Update operation schemas (updateOne, updateMany) | true |
upsert | Upsert operation schemas | true |
find | Find operation schemas (findUnique, findFirst, findMany) | true |
delete | Delete operation schemas (deleteOne, deleteMany) | true |
aggregate | Aggregate operation schemas | true |
groupBy | GroupBy operation schemas | true |
objects | Input object schemas (WhereInput, CreateInput, etc.) | true |
enums | Enum validation schemas | true |
filter | Filter and where input schemas | true |
orderBy | OrderBy input schemas | true |
unchecked | Unchecked input schemas (without relations) | true |
Configure how generated files are organized:
| Strategy | Description | Structure |
|---|---|---|
grouped | Organize by file type (default) | schemas/, schemas/objects/, schemas/enums/ |
flat | All files in single directory | schemas/ |
by-model | Organize by model name | schemas/models/User/, schemas/models/Post/ |
generator joi {
provider = "prisma-joi-generator"
output = "./src/schemas"
}
generator joi {
provider = "prisma-joi-generator"
output = "./generated/validation"
// Only generate create and find operations
create = "true"
find = "true"
update = "false"
delete = "false"
objects = "true"
enums = "true"
}
generator joi {
provider = "prisma-joi-generator"
output = "./schemas"
directoryStrategy = "flat"
}
Perfect for REST APIs that only need create and read operations:
generator joi {
provider = "prisma-joi-generator"
output = "./src/validation/schemas"
// Only essential operations
create = "true"
find = "true"
update = "false"
delete = "false"
upsert = "false"
aggregate = "false"
groupBy = "false"
// Required supporting schemas
objects = "true"
enums = "true"
}
Complete validation for complex applications:
generator joi {
provider = "prisma-joi-generator"
output = "./schemas"
directoryStrategy = "by-model"
// All operations enabled (default behavior)
create = "true"
update = "true"
upsert = "true"
find = "true"
delete = "true"
aggregate = "true"
groupBy = "true"
objects = "true"
enums = "true"
filter = "true"
orderBy = "true"
unchecked = "true"
}
For analytics dashboards or reporting systems:
generator joi {
provider = "prisma-joi-generator"
output = "./generated/read-schemas"
// Only read operations
create = "false"
update = "false"
delete = "false"
upsert = "false"
find = "true"
aggregate = "true"
groupBy = "true"
// Supporting schemas for filtering and sorting
objects = "true"
enums = "true"
filter = "true"
orderBy = "true"
}
Optimized for GraphQL resolvers with custom directory structure:
generator joi {
provider = "prisma-joi-generator"
output = "./src/graphql/validation"
directoryStrategy = "grouped"
// GraphQL typically needs input validation
create = "true"
update = "true"
find = "true"
delete = "true"
objects = "true"
enums = "true"
filter = "true"
// GraphQL handles its own aggregation
aggregate = "false"
groupBy = "false"
}
generator joi {
provider = "prisma-joi-generator"
// Strategy 1: Selective (default) - Use individual flags
create = "true"
find = "false"
// Strategy 2: Whitelist - Only generate specified types
filterStrategy = "whitelist"
includeTypes = "create,find,objects,enums"
// Strategy 3: Blacklist - Generate all except specified
filterStrategy = "blacklist"
excludeTypes = "aggregate,groupBy,unchecked"
}
generator joi {
provider = "prisma-joi-generator"
output = "./validation"
// Directory structure
directoryStrategy = "grouped"
// Custom directory names
baseDirectory = "schemas"
objectsDirectory = "inputs"
enumsDirectory = "constants"
modelsDirectory = "entities"
}
generator joi {
provider = "prisma-joi-generator"
// Customize file naming patterns
schemaFilePattern = "{operation}.validation"
objectFilePattern = "{name}.input"
enumFilePattern = "{name}.enum"
}
Before (v0.1.x):
generator joi {
provider = "prisma-joi-generator"
output = "./schemas"
}
After (v0.2.x+):
generator joi {
provider = "prisma-joi-generator"
output = "./schemas"
// Explicitly enable only needed types for better performance
create = "true"
find = "true"
update = "true"
delete = "false" // Skip if not needed
aggregate = "false" // Skip if not needed
objects = "true"
enums = "true"
}
Hide specific models from generation:
/// @@Gen.model(hide: true)
model InternalLog {
id Int @id @default(autoincrement())
message String
createdAt DateTime @default(now())
}
The generator supports all Prisma database providers:
import express from 'express';
import { PostCreateOneSchema, UserFindManySchema } from './generated/schemas';
const app = express();
// Create post with validation
app.post('/posts', async (req, res) => {
try {
const { error, value } = PostCreateOneSchema.validate(req.body);
if (error) {
return res.status(400).json({ errors: error.details });
}
const post = await prisma.post.create(value);
res.json(post);
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
// Query with validation
app.get('/users', async (req, res) => {
const { error, value } = UserFindManySchema.validate(req.query);
if (error) {
return res.status(400).json({ errors: error.details });
}
const users = await prisma.user.findMany(value);
res.json(users);
});
// pages/api/users.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { UserCreateOneSchema } from '../../generated/schemas';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
const { error, value } = UserCreateOneSchema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.message });
}
try {
const user = await prisma.user.create(value);
res.status(201).json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
}
import Fastify from 'fastify';
import { PostCreateOneSchema, PostFindManySchema } from './generated/schemas';
const fastify = Fastify();
fastify.post('/posts', {
preHandler: async (request, reply) => {
const { error } = PostCreateOneSchema.validate(request.body);
if (error) {
reply.code(400).send({ error: error.message });
return;
}
}
}, async (request, reply) => {
const post = await prisma.post.create({ data: request.body });
return post;
});
The generator creates the following types of schemas:
ModelCreateOneSchema, ModelCreateManySchemaModelFindManySchema, ModelFindUniqueSchema, ModelFindFirstSchemaModelUpdateOneSchema, ModelUpdateManySchema, ModelUpsertSchemaModelDeleteOneSchema, ModelDeleteManySchemaModelAggregateSchema, ModelGroupBySchemaModelCreateInputObjectSchema, ModelCreateNestedInputObjectSchemaModelUpdateInputObjectSchema, ModelUpdateNestedInputObjectSchemaModelWhereInputObjectSchema, ModelWhereUniqueInputObjectSchemaModelOrderByInputObjectSchemaAll generated schemas follow a consistent naming pattern:
{ModelName}{Operation}{Type}Schema
Examples:
UserCreateOneSchema - Schema for creating a single userPostFindManyArgsSchema - Schema for finding multiple posts with argumentsUserWhereInputObjectSchema - Schema for user where conditionsPrisma Compatibility
prisma-client-js, next to prisma-client, or with no client generatorCurrent Requirements
Upgrading to Latest Version
npx prisma generate after upgradingGenerator compatibility errors
prisma-client-js, prisma-client and a schema with
neither all workdatasource block, because prisma generate will not run without oneError: Cannot find module './generated/schemas'
npx prisma generate after adding the generatorTypeScript errors in generated schemas
Generated schemas not updating
npx prisma generate after modifying your schemaschema.prismaJoi validation errors
Generator fails to run
schema.prisma syntax is validNo files generated with selective filtering
create = "true")objects = "true" and enums = "true" are enabled for supporting schemas"true" not true)Missing operation schemas (createOne, findMany, etc.)
create = "true" for createOne schemas)objects and enums)Directory structure not as expected
directoryStrategy is set correctly ("grouped", "flat", or "by-model")Configuration parsing errors
create = "true" not create = trueincludeTypes = "create,find,objects"Filter strategy not working
// ❌ Wrong: Mixed strategies
generator joi {
provider = "prisma-joi-generator"
filterStrategy = "whitelist"
create = "true" // Don't mix individual flags with strategies
}
// ✅ Correct: Consistent strategy
generator joi {
provider = "prisma-joi-generator"
filterStrategy = "whitelist"
includeTypes = "create,find,objects,enums"
}
Performance issues with large schemas
directoryStrategy = "flat" for smaller projectsTypeScript import errors with filtered schemas
generateIndex = "true")To debug configuration issues, you can temporarily enable all types and gradually disable:
generator joi {
provider = "prisma-joi-generator"
output = "./debug-schemas"
// Enable everything first
create = "true"
update = "true"
find = "true"
delete = "true"
objects = "true"
enums = "true"
// Then gradually disable what you don't need
// aggregate = "false"
// groupBy = "false"
}
Contributions are welcome! Here's how you can help:
git clone https://github.com/your-username/prisma-joi-generator.git
cd prisma-joi-generator
npm install
npm run gen-example
npm test
We have comprehensive tests covering:
Run specific test suites:
npx vitest run // Every test file, which is what CI runs
npm run test:basic // Basic functionality
npm run test:coverage // Coverage reports
The test suite imports this repo's src/, so it cannot tell you whether the package it
produces works. Two more checks cover that gap, and CI runs both:
npm run gen-example // Build, then generate from the example schema
npm run check:emitted // Run the emitted schemas under Node's own loader
npm run package // Assemble the directory that gets published
We use ESLint and Prettier for consistent code formatting:
npm run lint // Check and fix linting issues
npm run format // Format code with Prettier
This project uses semantic versioning and automated releases:
This project is licensed under the MIT License.
72 commits
2 commits
TypeScript
98.4%
Prisma 2+ generator to emit Joi schemas from your Prisma schema
45
stars
74
commits
TypeScript
primary language
Jul 28, 2026
updated
🎯 Zero-config • 🛡️ Type-safe • ⚡ Fast • 🔧 Customizable
Automatically generates Joi schemas for all Prisma operations with full TypeScript support
If this tool accelerates your development, consider supporting its growth
✨ Your sponsorship drives innovation and keeps this project thriving ✨
|
|
| 🎉 Production Ready on Prisma 6 and Prisma 7! |
🆙 Prisma 6 and Prisma 7 Compatibility:
prisma-client, prisma-client-js, or neither🔧 Enhanced Development Experience - Modern tooling and CI/CD pipeline:
| 🚀 Feature | 📦 Version | 🎯 Benefit |
|---|---|---|
| New Prisma Client | 6.12.0+ | 🆕 ESM-compatible generator support |
| Prisma | 6.12.0+ and 7.x | 🏃♂️ Latest features & performance |
| Joi | 17.13.3+ | 🛡️ Enhanced validation & type safety |
| TypeScript | 5.8+ | ⚡ Cutting-edge language features |
| Testing | Vitest 3 | 🧪 Comprehensive coverage |
| Tooling | ESLint 9 | 🔧 Modern dev experience |
| Multi-DB | All Providers | 🗄️ PostgreSQL, MySQL, MongoDB, SQLite+ |
# 🚀 Install the latest release
npm install prisma-joi-generator
Requirements:
Update your dependencies and re-run npx prisma generate. Coming from 1.1.0 or earlier, read
how the generated schemas reference each other
first: the emitted output changed shape, because the shape it had could not be imported from an
ES module.
npm update prisma-joi-generator
npx prisma generate
|
Works instantly Sensible defaults included |
Always in sync Updates with schema changes |
100% TypeScript Catch errors at compile time |
Full CRUD coverage All Prisma operations included |
|
Highly customizable Adapt to your needs |
Minimal footprint Fast generation & runtime |
All databases PostgreSQL, MySQL, MongoDB+ |
Your way Custom paths & options |
# NPM
npm install prisma-joi-generator
# Yarn
yarn add prisma-joi-generator
# PNPM
pnpm add prisma-joi-generator
Star this repo 😉
Add the generator to your Prisma schema.
prisma generate refuses to run on a schema with no datasource block, so here is a
complete one that works as written. No client generator is required: add one if you want a
Prisma Client, leave it out if you only want Joi schemas.
Prisma 7 removed url from the datasource block. The connection URL goes in
prisma.config.ts instead:
generator joi {
provider = "prisma-joi-generator"
output = "./generated/schemas"
}
datasource db {
provider = "sqlite"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}
Prisma 6 and below keep the url on the datasource:
generator joi {
provider = "prisma-joi-generator"
output = "./generated/schemas"
}
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}
npx prisma generate
This generator reads the schema Prisma has already parsed, so it works next to any client generator, or next to none at all. It never imports or extends the Prisma Client.
Any of these work:
generator client {
provider = "prisma-client-js"
}
generator joi {
provider = "prisma-joi-generator"
output = "./generated/schemas"
}
generator client {
provider = "prisma-client"
output = "./src/generated/client"
runtime = "nodejs"
moduleFormat = "esm"
generatedFileExtension = "ts"
importFileExtension = "ts"
}
generator joi {
provider = "prisma-joi-generator"
output = "./generated/schemas"
}
generator joi {
provider = "prisma-joi-generator"
output = "./generated/schemas"
}
node_modulesExisting Projects: No changes needed - continue using prisma-client-js
New Projects: Consider using the new prisma-client generator for modern features
Gradual Migration: Both generators are supported simultaneously during the transition
Prisma 7 needs a release newer than 1.1.0. Up to and including 1.1.0 this package declared
@prisma/internalsas a dependency and re-parsed your schema with the copy of Prisma 6 that came with it. On a Prisma 7 schema that parse fails withP1012: Argument "url" is missing in data source block, reported under aPrisma CLI Version : 6.19.3banner from a project that has no Prisma 6 in it, and adding theurlback to satisfy it makes Prisma 7 itself reject the schema. There was no schema that both parsers accepted. Newer releases use the DMMF Prisma hands to every generator and carry no Prisma of their own.
For the following schema:
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String
content String?
published Boolean @default(false)
viewCount Int @default(0)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
likes BigInt
}
The generator creates different directory structures based on your configuration:
📁 generated/schemas/
├── 📁 enums/ // Enum validation schemas
│ ├── 📄 PostScalarFieldEnum.schema.ts
│ └── 📄 UserScalarFieldEnum.schema.ts
├── 📁 objects/ // Input type schemas
│ ├── 📄 UserCreateInput.schema.ts
│ ├── 📄 UserWhereInput.schema.ts
│ └── 📄 PostCreateInput.schema.ts
├── 📄 findManyUser.schema.ts
├── 📄 findUniqueUser.schema.ts
├── 📄 createOneUser.schema.ts
├── 📄 updateOneUser.schema.ts
├── 📄 deleteOneUser.schema.ts
├── 📄 findManyPost.schema.ts
├── 📄 createOnePost.schema.ts
└── 📄 index.ts // Barrel exports
📁 generated/schemas/
├── 📁 enums/ // Shared enums
├── 📁 models/
│ ├── 📁 user/
│ │ ├── 📄 findManyUser.schema.ts
│ │ ├── 📄 createOneUser.schema.ts
│ │ ├── 📁 objects/
│ │ │ ├── 📄 UserCreateInput.schema.ts
│ │ │ └── 📄 UserWhereInput.schema.ts
│ │ └── 📄 index.ts
│ └── 📁 post/
│ ├── 📄 findManyPost.schema.ts
│ ├── 📄 createOnePost.schema.ts
│ ├── 📁 objects/
│ └── 📄 index.ts
└── 📄 index.ts
📁 generated/schemas/
├── 📄 findManyUser.schema.ts
├── 📄 createOneUser.schema.ts
├── 📄 UserCreateInput.schema.ts
├── 📄 UserWhereInput.schema.ts
├── 📄 PostScalarFieldEnum.schema.ts
├── 📄 findManyPost.schema.ts
├── 📄 createOnePost.schema.ts
└── 📄 index.ts
Prisma's input types are cyclic: UserWhereInput reaches PostListRelationFilter, which
reaches PostWhereInput, which reaches back to UserWhereInput. TypeScript modules cannot
express that by importing each other, so the emitted object schemas do not. Each one refers to
the others with Joi.link('#TypeName'), and schemas/objects/index.ts exports an
objectSchemas registry that every link resolves against.
The generated root schemas already carry it, so most of the time this is invisible:
import { UserFindManySchema } from './generated/schemas';
// emitted as: objectSchemas.concat(Joi.object().keys({ ... }))
UserFindManySchema.validate({ where: { posts: { some: { title: { equals: 'hello' } } } } });
If you compose a schema out of the exported ...SchemaObject key bags yourself, concatenate
the registry onto it, otherwise Joi has nowhere to resolve the links and throws
AssertError: ... contains link reference ... which is outside of schema boundaries:
import Joi from 'joi';
import { objectSchemas, UserWhereInputSchemaObject } from './generated/schemas/objects';
const myFilter = objectSchemas.concat(Joi.object().keys(UserWhereInputSchemaObject));
Upgrading from 1.1.0 or earlier. Before this, object schemas embedded each other directly. That output could not be imported from an ES module at all, failing with
ReferenceError: Cannot access 'UserWhereInputSchemaObject' before initialization, and when compiled to CommonJS every reference across a cycle silently resolved toundefined, so each relation filter accepted absolutely anything. If you were relying on that, values nested under a relation filter are now validated, and a self-referentialwhere.ANDno longer throws.
| Version | Prisma | Joi | TypeScript | Node.js | Status |
|---|---|---|---|---|---|
| Latest | 6.12.0+ and 7.x | 17.13.3+ | 5.8+ | 18+ | ✅ Stable - verified against Prisma 6.19 and 7.9 on Node 22 and 24 |
| 1.1.0 and earlier | 6.12.0 - 6.x | 17.13.3+ | 5.8+ | 18+ | ⛔ Prisma 6 only - fails on Prisma 7, see the note above |
| Legacy | 4.0.0+ | 17.0+ | 4.7+ | 16+ | 📦 Deprecated - Limited Support |
Recommendation: Use
npm install prisma-joi-generatorfor the latest stable release with full features and modern tooling.
The Prisma Joi Generator offers powerful configuration options to customize file generation, organization, and filtering according to your project needs.
| Option | Description | Type | Default |
|---|---|---|---|
output | Output directory for generated files | string | "./generated" |
Control which types of validation schemas are generated:
| File Type | Description | Default |
|---|---|---|
create | Create operation schemas (createOne, createMany) | true |
update | Update operation schemas (updateOne, updateMany) | true |
upsert | Upsert operation schemas | true |
find | Find operation schemas (findUnique, findFirst, findMany) | true |
delete | Delete operation schemas (deleteOne, deleteMany) | true |
aggregate | Aggregate operation schemas | true |
groupBy | GroupBy operation schemas | true |
objects | Input object schemas (WhereInput, CreateInput, etc.) | true |
enums | Enum validation schemas | true |
filter | Filter and where input schemas | true |
orderBy | OrderBy input schemas | true |
unchecked | Unchecked input schemas (without relations) | true |
Configure how generated files are organized:
| Strategy | Description | Structure |
|---|---|---|
grouped | Organize by file type (default) | schemas/, schemas/objects/, schemas/enums/ |
flat | All files in single directory | schemas/ |
by-model | Organize by model name | schemas/models/User/, schemas/models/Post/ |
generator joi {
provider = "prisma-joi-generator"
output = "./src/schemas"
}
generator joi {
provider = "prisma-joi-generator"
output = "./generated/validation"
// Only generate create and find operations
create = "true"
find = "true"
update = "false"
delete = "false"
objects = "true"
enums = "true"
}
generator joi {
provider = "prisma-joi-generator"
output = "./schemas"
directoryStrategy = "flat"
}
Perfect for REST APIs that only need create and read operations:
generator joi {
provider = "prisma-joi-generator"
output = "./src/validation/schemas"
// Only essential operations
create = "true"
find = "true"
update = "false"
delete = "false"
upsert = "false"
aggregate = "false"
groupBy = "false"
// Required supporting schemas
objects = "true"
enums = "true"
}
Complete validation for complex applications:
generator joi {
provider = "prisma-joi-generator"
output = "./schemas"
directoryStrategy = "by-model"
// All operations enabled (default behavior)
create = "true"
update = "true"
upsert = "true"
find = "true"
delete = "true"
aggregate = "true"
groupBy = "true"
objects = "true"
enums = "true"
filter = "true"
orderBy = "true"
unchecked = "true"
}
For analytics dashboards or reporting systems:
generator joi {
provider = "prisma-joi-generator"
output = "./generated/read-schemas"
// Only read operations
create = "false"
update = "false"
delete = "false"
upsert = "false"
find = "true"
aggregate = "true"
groupBy = "true"
// Supporting schemas for filtering and sorting
objects = "true"
enums = "true"
filter = "true"
orderBy = "true"
}
Optimized for GraphQL resolvers with custom directory structure:
generator joi {
provider = "prisma-joi-generator"
output = "./src/graphql/validation"
directoryStrategy = "grouped"
// GraphQL typically needs input validation
create = "true"
update = "true"
find = "true"
delete = "true"
objects = "true"
enums = "true"
filter = "true"
// GraphQL handles its own aggregation
aggregate = "false"
groupBy = "false"
}
generator joi {
provider = "prisma-joi-generator"
// Strategy 1: Selective (default) - Use individual flags
create = "true"
find = "false"
// Strategy 2: Whitelist - Only generate specified types
filterStrategy = "whitelist"
includeTypes = "create,find,objects,enums"
// Strategy 3: Blacklist - Generate all except specified
filterStrategy = "blacklist"
excludeTypes = "aggregate,groupBy,unchecked"
}
generator joi {
provider = "prisma-joi-generator"
output = "./validation"
// Directory structure
directoryStrategy = "grouped"
// Custom directory names
baseDirectory = "schemas"
objectsDirectory = "inputs"
enumsDirectory = "constants"
modelsDirectory = "entities"
}
generator joi {
provider = "prisma-joi-generator"
// Customize file naming patterns
schemaFilePattern = "{operation}.validation"
objectFilePattern = "{name}.input"
enumFilePattern = "{name}.enum"
}
Before (v0.1.x):
generator joi {
provider = "prisma-joi-generator"
output = "./schemas"
}
After (v0.2.x+):
generator joi {
provider = "prisma-joi-generator"
output = "./schemas"
// Explicitly enable only needed types for better performance
create = "true"
find = "true"
update = "true"
delete = "false" // Skip if not needed
aggregate = "false" // Skip if not needed
objects = "true"
enums = "true"
}
Hide specific models from generation:
/// @@Gen.model(hide: true)
model InternalLog {
id Int @id @default(autoincrement())
message String
createdAt DateTime @default(now())
}
The generator supports all Prisma database providers:
import express from 'express';
import { PostCreateOneSchema, UserFindManySchema } from './generated/schemas';
const app = express();
// Create post with validation
app.post('/posts', async (req, res) => {
try {
const { error, value } = PostCreateOneSchema.validate(req.body);
if (error) {
return res.status(400).json({ errors: error.details });
}
const post = await prisma.post.create(value);
res.json(post);
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
});
// Query with validation
app.get('/users', async (req, res) => {
const { error, value } = UserFindManySchema.validate(req.query);
if (error) {
return res.status(400).json({ errors: error.details });
}
const users = await prisma.user.findMany(value);
res.json(users);
});
// pages/api/users.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { UserCreateOneSchema } from '../../generated/schemas';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
const { error, value } = UserCreateOneSchema.validate(req.body);
if (error) {
return res.status(400).json({ error: error.message });
}
try {
const user = await prisma.user.create(value);
res.status(201).json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
}
import Fastify from 'fastify';
import { PostCreateOneSchema, PostFindManySchema } from './generated/schemas';
const fastify = Fastify();
fastify.post('/posts', {
preHandler: async (request, reply) => {
const { error } = PostCreateOneSchema.validate(request.body);
if (error) {
reply.code(400).send({ error: error.message });
return;
}
}
}, async (request, reply) => {
const post = await prisma.post.create({ data: request.body });
return post;
});
The generator creates the following types of schemas:
ModelCreateOneSchema, ModelCreateManySchemaModelFindManySchema, ModelFindUniqueSchema, ModelFindFirstSchemaModelUpdateOneSchema, ModelUpdateManySchema, ModelUpsertSchemaModelDeleteOneSchema, ModelDeleteManySchemaModelAggregateSchema, ModelGroupBySchemaModelCreateInputObjectSchema, ModelCreateNestedInputObjectSchemaModelUpdateInputObjectSchema, ModelUpdateNestedInputObjectSchemaModelWhereInputObjectSchema, ModelWhereUniqueInputObjectSchemaModelOrderByInputObjectSchemaAll generated schemas follow a consistent naming pattern:
{ModelName}{Operation}{Type}Schema
Examples:
UserCreateOneSchema - Schema for creating a single userPostFindManyArgsSchema - Schema for finding multiple posts with argumentsUserWhereInputObjectSchema - Schema for user where conditionsPrisma Compatibility
prisma-client-js, next to prisma-client, or with no client generatorCurrent Requirements
Upgrading to Latest Version
npx prisma generate after upgradingGenerator compatibility errors
prisma-client-js, prisma-client and a schema with
neither all workdatasource block, because prisma generate will not run without oneError: Cannot find module './generated/schemas'
npx prisma generate after adding the generatorTypeScript errors in generated schemas
Generated schemas not updating
npx prisma generate after modifying your schemaschema.prismaJoi validation errors
Generator fails to run
schema.prisma syntax is validNo files generated with selective filtering
create = "true")objects = "true" and enums = "true" are enabled for supporting schemas"true" not true)Missing operation schemas (createOne, findMany, etc.)
create = "true" for createOne schemas)objects and enums)Directory structure not as expected
directoryStrategy is set correctly ("grouped", "flat", or "by-model")Configuration parsing errors
create = "true" not create = trueincludeTypes = "create,find,objects"Filter strategy not working
// ❌ Wrong: Mixed strategies
generator joi {
provider = "prisma-joi-generator"
filterStrategy = "whitelist"
create = "true" // Don't mix individual flags with strategies
}
// ✅ Correct: Consistent strategy
generator joi {
provider = "prisma-joi-generator"
filterStrategy = "whitelist"
includeTypes = "create,find,objects,enums"
}
Performance issues with large schemas
directoryStrategy = "flat" for smaller projectsTypeScript import errors with filtered schemas
generateIndex = "true")To debug configuration issues, you can temporarily enable all types and gradually disable:
generator joi {
provider = "prisma-joi-generator"
output = "./debug-schemas"
// Enable everything first
create = "true"
update = "true"
find = "true"
delete = "true"
objects = "true"
enums = "true"
// Then gradually disable what you don't need
// aggregate = "false"
// groupBy = "false"
}
Contributions are welcome! Here's how you can help:
git clone https://github.com/your-username/prisma-joi-generator.git
cd prisma-joi-generator
npm install
npm run gen-example
npm test
We have comprehensive tests covering:
Run specific test suites:
npx vitest run // Every test file, which is what CI runs
npm run test:basic // Basic functionality
npm run test:coverage // Coverage reports
The test suite imports this repo's src/, so it cannot tell you whether the package it
produces works. Two more checks cover that gap, and CI runs both:
npm run gen-example // Build, then generate from the example schema
npm run check:emitted // Run the emitted schemas under Node's own loader
npm run package // Assemble the directory that gets published
We use ESLint and Prettier for consistent code formatting:
npm run lint // Check and fix linting issues
npm run format // Format code with Prettier
This project uses semantic versioning and automated releases:
This project is licensed under the MIT License.
72 commits
2 commits
TypeScript
98.4%