prisma-trpc-generator
Version:
Prisma 2+ generator to emit fully implemented tRPC routers
798 lines (621 loc) โข 22.9 kB
Markdown
<div align="center">
<img src="https://raw.githubusercontent.com/omar-dulaimi/prisma-trpc-generator/master/logo.png" alt="Prisma tRPC Generator" width="100" height="100">
# โก Prisma tRPC Generator
### ๐ **Automatically generate fully implemented tRPC routers from your Prisma schema**
โจ **Enhanced with improved error handling and better TypeScript support**
<p>
<a href="https://www.npmjs.com/package/prisma-trpc-generator">
<img src="https://img.shields.io/npm/v/prisma-trpc-generator.svg?style=for-the-badge&logo=npm&color=blue" alt="Latest Version">
</a>
</p>
<p>
<a href="https://www.npmjs.com/package/prisma-trpc-generator">
<img src="https://img.shields.io/npm/dt/prisma-trpc-generator.svg?style=for-the-badge&logo=npm&color=green" alt="Downloads">
</a>
<a href="https://github.com/omar-dulaimi/prisma-trpc-generator/actions">
<img src="https://img.shields.io/github/actions/workflow/status/omar-dulaimi/prisma-trpc-generator/ci.yml?style=for-the-badge&logo=github" alt="CI Status">
</a>
<a href="LICENSE">
<img src="https://img.shields.io/npm/l/prisma-trpc-generator.svg?style=for-the-badge&color=purple" alt="License">
</a>
</p>
<p>
<strong>๐ฏ Zero-config โข ๐ก๏ธ Type-safe โข โก Fast โข ๐ง Customizable</strong>
</p>
</div>
---
<br>
<div align="center">
<h3>๐ก Transform your Prisma schema into production-ready tRPC APIs</h3>
<p><em>Automatically generates type-safe endpoints with Zod validation, middleware support, and optional tRPC Shield integration</em></p>
</div>
<div align="center">
## ๐ **Support This Project**
<p><em>If this tool accelerates your development, consider supporting its growth</em></p>
<a href="https://github.com/sponsors/omar-dulaimi">
<img src="https://img.shields.io/badge/๐_Sponsor_on_GitHub-ea4aaa?style=for-the-badge&logo=github&logoColor=white" alt="GitHub Sponsors" height="45">
</a>
<p><strong>โจ Your sponsorship drives innovation and keeps this project thriving โจ</strong></p>
</div>
## โจ **What's New**
<div align="center">
| ๐ **Feature** | ๐ฆ **Version** | ๐ฏ **Benefit** |
|----------------|----------------|------------------|
| **Prisma** | `6.12.0+` | ๐โโ๏ธ Improved performance & stability |
| **tRPC** | `11.4.3+` | ๐ก๏ธ Enhanced type safety & modern APIs |
| **TypeScript** | `5.8+` | โก Cutting-edge language features |
| **Zod** | `4.0+` | ๐ Advanced validation & error handling |
| **Testing** | `Vitest 3` | ๐งช 90%+ coverage with modern tooling |
| **Tooling** | `ESLint 9` | ๐ง Latest dev experience |
</div>
## ๐ Prisma Client Generator Support
<div align="center">
**โจ Starting from v2.1.0, full support for the new Prisma Client generator preview feature โจ**
</div>
This generator now supports both the legacy and new Prisma Client generators:
### Supported Generators
| Generator Type | Provider | Supported Since | Status |
|----------------|----------|-----------------|---------|
| **Legacy** | `prisma-client-js` | v1.0.0+ | โ
**Fully Supported** |
| **Preview** | `prisma-client` | **v2.1.0+** | โ
**Fully Supported** |
### Preview Features Support
The following preview features are automatically detected and supported:
| Preview Feature | Description | Status |
|-----------------|-------------|---------|
| `queryCompiler` | Improved query compilation performance | โ
Supported |
| `driverAdapters` | Enhanced database driver compatibility | โ
Supported |
| `metrics` | Query performance metrics collection | โ
Supported |
| Custom features | Any new preview features from Prisma | โ
Auto-detected |
### Usage Examples
**Legacy Generator (existing projects):**
```prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["queryCompiler"]
}
generator trpc {
provider = "prisma-trpc-generator"
// ... your config
}
```
**New Generator (Prisma 6.12.0+ projects):**
```prisma
generator client {
provider = "prisma-client"
output = "./generated/client"
previewFeatures = ["queryCompiler", "driverAdapters", "metrics"]
runtime = "nodejs"
moduleFormat = "esm"
}
generator trpc {
provider = "prisma-trpc-generator"
// ... your config
}
```
**Mixed Setup (both generators):**
```prisma
generator clientLegacy {
provider = "prisma-client-js"
}
generator clientNew {
provider = "prisma-client"
output = "./generated/client-new"
previewFeatures = ["queryCompiler", "driverAdapters"]
}
generator trpc {
provider = "prisma-trpc-generator"
// Automatically detects and uses preview features from any client generator
}
```
> **๐ Note**: Preview features are automatically detected from your Prisma client generator and applied to the generated tRPC routers. No additional configuration needed!
### ๐ Requirements
- **Node.js 18+**
- **Prisma 6.12.0+**
- **tRPC 11.4.3+**
- **TypeScript 5.8+**
<div align="center">
## ๐ **Navigation**
<table>
<tr>
<td><a href="#-features">โจ Features</a></td>
<td><a href="#-quick-start">๐ Quick Start</a></td>
<td><a href="#-generated-output">๐ Output</a></td>
<td><a href="#๏ธ-configuration-options">โ๏ธ Config</a></td>
</tr>
<tr>
<td><a href="#-advanced-usage">๐ง Advanced</a></td>
<td><a href="#-examples">๐ Examples</a></td>
<td><a href="#-troubleshooting">๐ Troubleshooting</a></td>
<td><a href="#-contributing">๐ค Contributing</a></td>
</tr>
</table>
</div>
<div align="center">
## โจ **Why Choose Prisma tRPC Generator?**
</div>
<table>
<tr>
<td align="center" width="25%">
<img src="https://img.shields.io/badge/๐-Zero_Config-blue?style=for-the-badge" alt="Zero Config">
<br><strong>Works instantly</strong><br><em>Sensible defaults included</em>
</td>
<td align="center" width="25%">
<img src="https://img.shields.io/badge/๐-Auto_Generated-green?style=for-the-badge" alt="Auto Generated">
<br><strong>Always in sync</strong><br><em>Updates with schema changes</em>
</td>
<td align="center" width="25%">
<img src="https://img.shields.io/badge/๐ก๏ธ-Type_Safe-purple?style=for-the-badge" alt="Type Safe">
<br><strong>100% TypeScript</strong><br><em>Catch errors at compile time</em>
</td>
<td align="center" width="25%">
<img src="https://img.shields.io/badge/๐ฏ-Comprehensive-orange?style=for-the-badge" alt="Comprehensive">
<br><strong>Full CRUD coverage</strong><br><em>All Prisma operations included</em>
</td>
</tr>
<tr>
<td align="center">
<img src="https://img.shields.io/badge/โ๏ธ-Configurable-red?style=for-the-badge" alt="Configurable">
<br><strong>Highly customizable</strong><br><em>Adapt to your needs</em>
</td>
<td align="center">
<img src="https://img.shields.io/badge/๐ฆ-Lightweight-yellow?style=for-the-badge" alt="Lightweight">
<br><strong>Minimal footprint</strong><br><em>Fast generation & runtime</em>
</td>
<td align="center">
<img src="https://img.shields.io/badge/๐-Integrations-cyan?style=for-the-badge" alt="Integrations">
<br><strong>Ecosystem ready</strong><br><em>Zod, Shield, middleware</em>
</td>
<td align="center">
<img src="https://img.shields.io/badge/๐จ-Flexible-pink?style=for-the-badge" alt="Flexible">
<br><strong>Your way</strong><br><em>Custom paths & middleware</em>
</td>
</tr>
</table>
## ๐ Quick Start
### Installation
```bash
# NPM
npm install prisma-trpc-generator
# Yarn
yarn add prisma-trpc-generator
# PNPM
pnpm add prisma-trpc-generator
```
### Setup
1. **Star this repo** ๐
2. **Add the generator to your Prisma schema:**
```prisma
generator trpc {
provider = "prisma-trpc-generator"
withZod = true
withMiddleware = false
withShield = false
contextPath = "../src/context"
trpcOptionsPath = "../src/trpcOptions"
}
```
3. **Enable strict mode in `tsconfig.json`** (required by Zod):
```json
{
"compilerOptions": {
"strict": true
}
}
```
4. **Generate your tRPC routers:**
```bash
npx prisma generate
```
## ๐ Generated Output
For the following schema:
```prisma
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?
}
```
The generator creates:

```
generated/
โโโ routers/
โ โโโ index.ts # Main app router that combines all model routers
โ โโโ helpers/
โ โ โโโ createRouter.ts # Base router factory with middleware/shield setup
โ โโโ User.router.ts # User CRUD operations
โ โโโ Post.router.ts # Post CRUD operations
โโโ schemas/ # Zod validation schemas (if withZod: true)
โโโ objects/ # Input type schemas
โโโ findManyUser.schema.ts
โโโ createOneUser.schema.ts
โโโ index.ts # Barrel exports
```
### Version Compatibility
| Version | Prisma | tRPC | TypeScript | Zod | Node.js | Status |
|---------|--------|------|------------|-----|---------|--------|
| **v2.1.0+** | 6.12.0+ | 11.4.3+ | 5.8+ | 4.0+ | 18+ | โ
**Stable** (+ Preview Features) |
| v2.0.2 | 6.12.0+ | 11.4.3+ | 5.8+ | 4.0+ | 18+ | โ
**Stable** |
| v1.4.1 (stable) | 4.8.0+ | 10.7.0+ | 4.9+ | 3.20+ | 16+ | โ
**Stable** |
> **Recommendation**: Use the latest stable version for all projects.
## โ๏ธ Configuration Options
| Option | Description | Type | Default |
|--------|-------------|------|---------|
| `output` | Output directory for generated files | `string` | `./generated` |
| `withZod` | Generate Zod validation schemas | `boolean` | `true` |
| `withMiddleware` | Include global middleware support | `boolean \| string` | `true` |
| `withShield` | Generate tRPC Shield permissions | `boolean \| string` | `false` |
| `contextPath` | Path to your tRPC context file | `string` | `../../../../src/context` |
| `trpcOptionsPath` | Path to tRPC instance options | `string` | `../../../../src/trpcOptions` |
| `isGenerateSelect` | Enable Select schema generation | `boolean` | `false` |
| `isGenerateInclude` | Enable Include schema generation | `boolean` | `false` |
| `showModelNameInProcedure` | Include model name in procedure names | `boolean` | `true` |
| `generateModelActions` | Specify which CRUD operations to generate | `string` | All operations |
### Example Configuration
```prisma
generator trpc {
provider = "prisma-trpc-generator"
output = "./src/server/api"
withZod = true
withMiddleware = "../middleware"
withShield = "../permissions"
contextPath = "../context"
trpcOptionsPath = "../trpcOptions"
isGenerateSelect = true
isGenerateInclude = true
showModelNameInProcedure = false
generateModelActions = "findMany,findUnique,create,update,delete"
}
```
## ๐ง Advanced Usage
### Custom Middleware
Create a middleware file to run before all procedures:
```ts
// src/middleware.ts
import { TRPCError } from '@trpc/server';
import { t } from './trpc';
export const authMiddleware = t.middleware(async ({ ctx, next }) => {
if (!ctx.user) {
throw new TRPCError({ code: 'UNAUTHORIZED' });
}
return next({
ctx: {
...ctx,
user: ctx.user,
},
});
});
export const loggingMiddleware = t.middleware(async ({ path, type, next }) => {
console.log(`tRPC ${type} ${path}`);
return next();
});
```
### Integration with tRPC Shield
Set up permissions using the generated shield:
```ts
// src/permissions.ts
import { shield, rule, and, or } from 'trpc-shield';
const isAuthenticated = rule()(async (parent, args, ctx) => {
return !!ctx.user;
});
const isOwner = rule()(async (parent, args, ctx) => {
if (!args.where?.id) return false;
const post = await ctx.prisma.post.findUnique({
where: { id: args.where.id },
select: { authorId: true }
});
return post?.authorId === ctx.user?.id;
});
export const permissions = shield({
query: {
findManyPost: true, // Public
findUniqueUser: isAuthenticated,
},
mutation: {
createOnePost: isAuthenticated,
updateOnePost: and(isAuthenticated, isOwner),
deleteOnePost: and(isAuthenticated, isOwner),
},
});
```
### Custom tRPC Options
Configure your tRPC instance with custom options:
```ts
// src/trpcOptions.ts
import { ZodError } from 'zod';
import superjson from 'superjson';
export default {
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.code === 'BAD_REQUEST' && error.cause instanceof ZodError
? error.cause.flatten()
: null,
},
};
},
};
```
## ๐จ Customizations
### Skipping Models
Hide specific models from generation:
```prisma
/// @@Gen.model(hide: true)
model InternalLog {
id Int @id @default(autoincrement())
message String
createdAt DateTime @default(now())
}
```
### Custom Context
Ensure you have a properly typed context file:
```ts
// src/context.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export interface Context {
prisma: PrismaClient;
user?: {
id: string;
email: string;
role: string;
};
}
export const createContext = async ({ req }): Promise<Context> => {
// Add your authentication logic here
const user = await getUserFromRequest(req);
return {
prisma,
user,
};
};
```
## ๐ Examples
### Basic CRUD with Authentication
```ts
// src/server/routers/posts.ts
import { z } from 'zod';
import { createTRPCRouter, protectedProcedure, publicProcedure } from '../trpc';
export const postsRouter = createTRPCRouter({
// Public read access
getAll: publicProcedure.query(({ ctx }) => {
return ctx.prisma.post.findMany({
where: { published: true },
include: { author: { select: { name: true } } },
});
}),
// Protected create
create: protectedProcedure
.input(z.object({
title: z.string().min(1),
content: z.string().optional(),
}))
.mutation(({ ctx, input }) => {
return ctx.prisma.post.create({
data: {
...input,
authorId: ctx.user.id,
},
});
}),
// Protected update (owner only)
update: protectedProcedure
.input(z.object({
id: z.number(),
title: z.string().min(1).optional(),
content: z.string().optional(),
}))
.mutation(async ({ ctx, input }) => {
const { id, ...data } = input;
// Verify ownership
const post = await ctx.prisma.post.findFirst({
where: { id, authorId: ctx.user.id },
});
if (!post) {
throw new TRPCError({ code: 'FORBIDDEN' });
}
return ctx.prisma.post.update({
where: { id },
data,
});
}),
});
```
### Integration with Next.js App Router
```ts
// src/app/api/trpc/[trpc]/route.ts
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';
import { appRouter } from '@/server/api/root';
import { createContext } from '@/server/api/context';
const handler = (req: Request) =>
fetchRequestHandler({
endpoint: '/api/trpc',
req,
router: appRouter,
createContext,
});
export { handler as GET, handler as POST };
```
### Client-side Usage
```ts
// src/lib/trpc.ts
import { createTRPCReact } from '@trpc/react-query';
import type { AppRouter } from '@/server/api/root';
export const trpc = createTRPCReact<AppRouter>();
// In your component
const PostList = () => {
const { data: posts, isLoading } = trpc.post.findMany.useQuery();
const createPost = trpc.post.createOne.useMutation();
if (isLoading) return <div>Loading...</div>;
return (
<div>
{posts?.map((post) => (
<div key={post.id}>{post.title}</div>
))}
</div>
);
};
```
## ๐ Troubleshooting
### Common Issues
**Dependency compatibility errors**
- Ensure you're using Node.js 18+
- Update Prisma to 6.12.0+ and tRPC to 11.4.3+
- Check that all peer dependencies are compatible
**Migration from v1.x to v2.x**
- Backup your project before upgrading
- Update all related dependencies (Prisma, tRPC, Zod)
- Re-run `npx prisma generate` after upgrading
- Test thoroughly in development environment
### Common Issues
**Error: Cannot find module '../context'**
- Ensure your `contextPath` is correct relative to the output directory
- Check that your context file exports a `Context` type
**TypeScript errors in generated routers**
- Make sure all dependencies are installed and up to date
- Verify your tRPC context is properly typed
- Ensure `strict: true` is enabled in `tsconfig.json`
**Generated routers not updating**
- Run `npx prisma generate` after modifying your schema
- Check that the generator is properly configured in `schema.prisma`
- Clear your build cache and regenerate
**Zod validation errors**
- Ensure you have Zod 4.0+ installed for compatibility
- Check that your input schemas match your Prisma model types
### Performance Considerations
#### Large Schemas
For projects with many models (50+), consider:
- Using selective generation with model hiding
- Splitting routers into multiple files
- Implementing lazy loading for routers
#### Build Times
To optimize build performance:
- Add generated files to `.gitignore`
- Use parallel builds where possible
- Consider caching in CI/CD pipelines
### FAQ
**Q: Can I customize the generated router validation rules?**
A: The routers are generated based on your Prisma schema constraints. Modify your Prisma model definitions to change validation rules.
**Q: Does this work with Prisma Edge Runtime?**
A: Yes, the generated routers are compatible with Prisma Edge Runtime.
**Q: Can I use this with databases other than the officially supported ones?**
A: The generator supports all Prisma-compatible databases. Custom databases should work if Prisma supports them.
**Q: How do I handle enum validation?**
A: Enums are automatically converted to Zod enum schemas and included in the generated validation.
**Q: Can I exclude certain fields from validation?**
A: Use Prisma's `@ignore` directive or model-level hiding with `@@Gen.model(hide: true)`.
### Getting Help
- ๐ **Bug Reports**: [Create a bug report](https://github.com/omar-dulaimi/prisma-trpc-generator/issues/new)
- ๐ก **Feature Requests**: [Request a feature](https://github.com/omar-dulaimi/prisma-trpc-generator/issues/new)
- ๐ฌ **Discussions**: [Join the discussion](https://github.com/omar-dulaimi/prisma-trpc-generator/discussions)
## ๐ค Contributing
Contributions are welcome! Here's how you can help:
### Development Setup
1. **Fork and clone the repository**
```bash
git clone https://github.com/your-username/prisma-trpc-generator.git
cd prisma-trpc-generator
```
2. **Install dependencies**
```bash
npm install
```
3. **Run the development build**
```bash
npm run generate
```
4. **Run tests**
```bash
npm test
```
### Testing
We have comprehensive tests covering:
- **Unit Tests**: Core transformation logic
- **Integration Tests**: End-to-end router generation
- **Multi-Provider Tests**: All database providers
- **Performance Tests**: Large schema handling
Run specific test suites:
```bash
npm run test:basic # Basic functionality
npm run test:integration # Integration testing
npm run test:coverage # Coverage reports
npm run test:comprehensive # Full test suite
```
### Contribution Guidelines
1. **Create an issue** for bugs or feature requests
2. **Follow the existing code style** (ESLint + Prettier)
3. **Add tests** for new functionality
4. **Update documentation** as needed
5. **Submit a pull request** with a clear description
### Code Style
We use ESLint and Prettier for consistent code formatting:
```bash
npm run lint # Check and fix linting issues
npm run format # Format code with Prettier
```
### Release Process
This project uses semantic versioning and automated releases:
- **Patch**: Bug fixes and small improvements
- **Minor**: New features and enhancements
- **Major**: Breaking changes
## ๐ License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## ๐ Related Projects
- [prisma-zod-generator](https://github.com/omar-dulaimi/prisma-zod-generator) - Generate Zod schemas from Prisma schema
- [prisma-trpc-shield-generator](https://github.com/omar-dulaimi/prisma-trpc-shield-generator) - Generate tRPC Shield permissions from Prisma schema
- [tRPC Shield](https://github.com/omar-dulaimi/trpc-shield) - Permission system for tRPC
- [Prisma](https://github.com/prisma/prisma) - Database toolkit and ORM
- [tRPC](https://trpc.io) - End-to-end typesafe APIs made easy
## ๐ Acknowledgments
- [Prisma](https://github.com/prisma/prisma) - Modern database toolkit
- [tRPC](https://trpc.io) - End-to-end typesafe APIs
- [Zod](https://github.com/colinhacks/zod) - TypeScript-first schema validation
- All our [contributors](https://github.com/omar-dulaimi/prisma-trpc-generator/graphs/contributors)
---
<br>
---
<div align="center">
<h3>๐ **Show Your Support** ๐</h3>
<a href="https://github.com/omar-dulaimi/prisma-trpc-generator">
<img src="https://img.shields.io/github/stars/omar-dulaimi/prisma-trpc-generator?style=for-the-badge&logo=github&color=yellow" alt="GitHub Stars">
</a>
<br><br>
<table>
<tr>
<td align="center">
<img src="https://img.shields.io/badge/๐-Latest_Stable-success?style=for-the-badge&logo=npm" alt="Stable">
<br>
<code>v1.4.1</code>
</td>
<td align="center">
<img src="https://img.shields.io/badge/๐-Latest_Version-success?style=for-the-badge&logo=rocket" alt="Latest">
<br>
<code>v2.1.0+</code>
</td>
</tr>
</table>
<br>
<p>
<strong>Made with โค๏ธ by</strong>
<a href="https://github.com/omar-dulaimi">
<img src="https://img.shields.io/badge/Omar_Dulaimi-100000?style=for-the-badge&logo=github&logoColor=white" alt="Omar Dulaimi">
</a>
</p>
<p><em>โก Accelerating tRPC development, one schema at a time</em></p>
</div>