prisma-trpc-generator

2.1.1 • Public • Published
Prisma tRPC Generator

⚡ Prisma tRPC Generator

🚀 Automatically generate fully implemented tRPC routers from your Prisma schema

Enhanced with improved error handling and better TypeScript support

Latest Version

Downloads CI Status License

🎯 Zero-config • 🛡️ Type-safe • ⚡ Fast • 🔧 Customizable



💡 Transform your Prisma schema into production-ready tRPC APIs

Automatically generates type-safe endpoints with Zod validation, middleware support, and optional tRPC Shield integration

💖 Support This Project

If this tool accelerates your development, consider supporting its growth

GitHub Sponsors

✨ Your sponsorship drives innovation and keeps this project thriving ✨

What's New

🚀 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

🌟 Prisma Client Generator Support

✨ Starting from v2.1.0, full support for the new Prisma Client generator preview feature ✨

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):

generator client {
  provider = "prisma-client-js"
  previewFeatures = ["queryCompiler"]
}

generator trpc {
  provider = "prisma-trpc-generator"
  // ... your config
}

New Generator (Prisma 6.12.0+ projects):

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):

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+

Why Choose Prisma tRPC Generator?

Zero Config
Works instantly
Sensible defaults included
Auto Generated
Always in sync
Updates with schema changes
Type Safe
100% TypeScript
Catch errors at compile time
Comprehensive
Full CRUD coverage
All Prisma operations included
Configurable
Highly customizable
Adapt to your needs
Lightweight
Minimal footprint
Fast generation & runtime
Integrations
Ecosystem ready
Zod, Shield, middleware
Flexible
Your way
Custom paths & middleware

🚀 Quick Start

Installation

# 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:

generator trpc {
  provider          = "prisma-trpc-generator"
  withZod           = true
  withMiddleware    = false
  withShield        = false
  contextPath       = "../src/context"
  trpcOptionsPath   = "../src/trpcOptions"
}
  1. Enable strict mode in tsconfig.json (required by Zod):
{
  "compilerOptions": {
    "strict": true
  }
}
  1. Generate your tRPC routers:
npx prisma generate

📋 Generated Output

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?
}

The generator creates:

tRPC Routers

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

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:

// 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:

// 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:

// 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:

/// @@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:

// 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

// 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

// 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

// 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

🤝 Contributing

Contributions are welcome! Here's how you can help:

Development Setup

  1. Fork and clone the repository
git clone https://github.com/your-username/prisma-trpc-generator.git
cd prisma-trpc-generator
  1. Install dependencies
npm install
  1. Run the development build
npm run generate
  1. Run tests
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:

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:

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 file for details.

🔗 Related Projects

🙏 Acknowledgments

  • Prisma - Modern database toolkit
  • tRPC - End-to-end typesafe APIs
  • Zod - TypeScript-first schema validation
  • All our contributors



🌟 **Show Your Support** 🌟

GitHub Stars



Stable
v1.4.1
Latest
v2.1.0+

Made with ❤️ by Omar Dulaimi

⚡ Accelerating tRPC development, one schema at a time

Package Sidebar

Install

npm i prisma-trpc-generator

Weekly Downloads

1,683

Version

2.1.1

License

MIT

Unpacked Size

69.5 kB

Total Files

33

Last publish

Collaborators

  • omar-dulaimi