npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

prisma-orpc-generator

v1.2.0

Published

Prisma generator that creates fully-featured oRPC routers

Readme

TL;DR — Add the generator to your Prisma schema and run Prisma generate. That’s it.

generator client {
  provider = "prisma-client-js"
}

generator orpc {
  provider = "prisma-orpc-generator"
  output   = "./src/generated/orpc"

  // Optional config (booleans are strings)
  schemaLibrary = "zod"
  generateInputValidation  = "true"
  generateOutputValidation = "true"

  // Shield authorization (optional)
  generateShield = "true"
  defaultReadRule = "allow"
  defaultWriteRule = "auth"
}

Create prisma.config.ts to hold your datasource connection (replace the URL for your database or driver adapter):

import { defineConfig } from '@prisma/config';

export default defineConfig({
  schema: './schema.prisma',
  datasource: {
    url: 'file:./dev.db',
  },
});
# generate
npx prisma generate --config prisma.config.ts

📋 Table of Contents


⚡ Quickstart

Prerequisites

  • Node: 20.19.0+, 22.12.0+, or 24.0.0+ (per Prisma 7 engine support)
  • Prisma CLI (v7+) in your project
  • TypeScript ≥ 5.4.0 recommended

Install

# npm
npm install -D prisma-orpc-generator zod prisma @prisma/client

# pnpm
pnpm add -D prisma-orpc-generator zod prisma @prisma/client

# yarn
yarn add -D prisma-orpc-generator zod prisma @prisma/client

Add the generator (minimal)

generator client {
  provider = "prisma-client-js"
}

generator orpc {
  provider = "prisma-orpc-generator"
  output   = "./src/generated/orpc"
}

Generate

npx prisma generate --config prisma.config.ts

🧩 Compatibility


🏗️ What Gets Generated

src/generated/orpc/
├─ routers/
│  ├─ models/           # per-model routers
│  └─ helpers/          # common utilities
├─ tests/               # generated tests
├─ zod-schemas/         # zod (if enabled)
└─ documentation/       # docs (if enabled)

Explore the example outputs:


🛠️ Usage

Tip: Browse the example’s generated root for real structure: examples/basic/src/generated/orpc.


⚙️ Configuration

Validated against src/config/schema.ts. Below are the most commonly used options.

Core options | Option | Type | Default | Values | Description | |---|---|---|---|---| | output | string | ./src/generated/orpc | — | Directory for generated oRPC artifacts | | schemaLibrary | enum | "zod" | zod | Schema validation library | | generateInputValidation | boolean (string) | "true" | "true", "false" | Emit Zod validation for inputs | | generateOutputValidation | boolean (string) | "true" | "true", "false" | Emit Zod validation for outputs | | strictValidation | boolean (string) | "true" | "true", "false" | Stricter Zod shapes for safety | | zodSchemasOutputPath | string | ./zod-schemas | — | Relative path (under output) for Zod files | | externalZodImportPath | string | ./zod-schemas | — | Module/path used when importing Zod schemas | | zodDateTimeStrategy | enum | "coerce" | "date", "coerce", "isoString" | How DateTime fields are modeled in Zod | | zodConfigPath | string | — | — | Path to custom zod.config.json file (relative to schema or absolute) |

Operational options | Option | Type | Default | Values | Description | |---|---|---|---|---| | generateModelActions | string list | all | see note | Comma-separated actions to emit (see note below) | | showModelNameInProcedure | boolean (string) | "true" | "true", "false" | Prefix procedures with model name | | enableSoftDeletes | boolean (string) | "false" | "true", "false" | Add soft-delete semantics where applicable | | generateRelationResolvers | boolean (string) | "true" | "true", "false" | Emit helpers to resolve relations | | wrapResponses | boolean (string) | "false" | "true", "false" | Wrap handler results in an envelope |

DX and formatting | Option | Type | Default | Values | Description | |---|---|---|---|---| | useBarrelExports | boolean (string) | "true" | "true", "false" | Generate index.ts barrel exports | | codeStyle | enum | "prettier" | "prettier", "none" | Format generated code with Prettier | | generateDocumentation | boolean (string) | "false" | "true", "false" | Generate API documentation | | generateTests | boolean (string) | "false" | "true", "false" | Generate test files | | enableDebugLogging | boolean (string) | "false" | "true", "false" | Extra logs during generation |

Runtime and integration | Option | Type | Default | Values | Description | |---|---|---|---|---| | prismaClientPath | string | @prisma/client | — | Import path for PrismaClient | | contextPath | string | "" | — | Optional path to your app's Context module | | serverPort | number (string) | 3000 | — | Port used by optional docs/server helpers | | apiPrefix | string | "" | — | Prefix used by optional docs/server helpers | | apiTitle | string | Generated API | — | API title for documentation | | apiDescription | string | Auto-generated API from Prisma schema | — | API description for documentation | | apiVersion | string | 1.0.0 | — | API version for documentation |

Shield / Authorization | Option | Type | Default | Values | Description | |---|---|---|---|---| | generateShield | boolean (string) | "true" | "true", "false" | Enable shield generation | | shieldPath | string | — | — | Path to custom shield file (absolute, relative to project root, relative to output dir, or module specifier) | | defaultReadRule | enum | "allow" | "allow", "deny", "auth" | Default rule for read operations | | defaultWriteRule | enum | "auth" | "auth", "deny", "allow" | Default rule for write operations | | denyErrorCode | string | "FORBIDDEN" | — | Error code for denied access | | debug | boolean (string) | "false" | "true", "false" | Enable debug logging | | allowExternalErrors | boolean (string) | "false" | "true", "false" | Allow detailed error messages from shields | Notes

  • generateModelActions supports: create, createMany, findFirst, findFirstOrThrow, findMany, findUnique, findUniqueOrThrow, update, updateMany, upsert, delete, deleteMany, aggregate, groupBy, count, findRaw, aggregateRaw.
  • Booleans are strings in Prisma generator config: use "true" or "false".
  • The full, authoritative shape lives in src/config/schema.ts.
generator orpc {
  provider = "prisma-orpc-generator"
  output   = "./src/generated/orpc"

  schemaLibrary             = "zod"
  zodDateTimeStrategy       = "coerce"
  generateInputValidation   = "true"
  generateOutputValidation  = "true"
  generateDocumentation     = "true"
  useBarrelExports          = "true"
  codeStyle                 = "prettier"
}

🔧 Zod Schemas Generation

This generator leverages prisma-zod-generator to create Zod schemas from your Prisma models. Here's how the process works:

Generation Process

  1. Automatic Integration: When schemaLibrary = "zod" is set, the generator automatically calls prisma-zod-generator
  2. Configuration Management: Creates a zod.config.json file with optimized settings for oRPC usage
  3. Schema Output: Generates Zod schemas in the zod-schemas/ subdirectory of your output path
  4. Import Integration: Generated oRPC routers automatically import and use these schemas for validation

Configuration File

The generator creates a minimal zod.config.json file:

{
  "mode": "full",
  "output": "./zod-schemas"
}

Additional settings are only added when they differ from defaults:

{
  "mode": "full", 
  "output": "./zod-schemas",
  "dateTimeStrategy": "date"
}

DateTime Handling Strategy

The zodDateTimeStrategy option controls how Prisma DateTime fields are modeled in Zod schemas:

| Strategy | Zod Schema | Description | prisma-zod-generator equivalent | |---|---|---|---| | "coerce" (default) | z.coerce.date() | Automatically converts strings/numbers to Date objects | dateTimeStrategy: "coerce" | | "date" | z.date() | Requires actual Date objects, no conversion | dateTimeStrategy: "date" | | "isoString" | z.string().regex(ISO).transform() | Validates ISO string format, transforms to Date | dateTimeStrategy: "isoString" |

Custom Zod Configuration

For advanced use cases, you can provide your own zod.config.json:

generator orpc {
  provider = "prisma-orpc-generator"
  output   = "./src/generated/orpc"
  
  zodConfigPath = "./custom-zod.config.json"  // Path to your config file
}

When zodConfigPath is specified:

  • The generator uses your existing configuration
  • oRPC-specific settings are passed as generator options instead of modifying the config file
  • Your custom configuration takes precedence

File Structure

Generated Zod schemas follow this structure:

src/generated/orpc/
├─ zod-schemas/
│  ├─ index.ts           # Barrel exports
│  ├─ objects/           # Model schemas
│  │  ├─ UserSchema.ts
│  │  └─ PostSchema.ts
│  └─ inputTypeSchemas/  # Input validation schemas
│     ├─ UserCreateInput.ts
│     └─ UserUpdateInput.ts
└─ routers/              # oRPC routers (import from ../zod-schemas)

🛡️ Shield Authorization

The generator can automatically generate orpc-shield configurations for type-safe authorization. Shield provides declarative rules, composable operators, and path-based permissions.

Shield Configuration

Add shield options to your generator config:

generator orpc {
  provider = "prisma-orpc-generator"
  output   = "./src/generated/orpc"

  // Enable shield generation
  generateShield = "true"

  // Option 1: Auto-generate shield rules
  defaultReadRule  = "allow"  // "allow", "deny", "auth"
  defaultWriteRule = "auth"   // "auth", "deny"

  // Option 2: Use custom shield file (relative to output dir)
  // shieldPath = "../auth/my-custom-shield"

  // Error handling
  denyErrorCode = "FORBIDDEN"
  debug = "false"
}

What Gets Generated

Shield generation creates:

src/generated/orpc/
├─ shield.ts              # Shield rules and permissions (auto-generated)
├─ routers/
│  ├─ index.ts           # App router with shield exports
│  └─ helpers/
│     └─ createRouter.ts # Base router with shield middleware integration

When shieldPath is provided: The generator skips auto-generation and dynamically integrates your custom shield file into the generated middleware chain.

Dynamic Shield Path Resolution ✨

The generator now features smart dynamic path resolution for shield files. When you specify a shieldPath, the generator automatically:

  • Resolves relative paths from your project structure
  • Handles different output directory layouts
  • Integrates shield middleware using the proper oRPC pattern
  • Generates correct import paths regardless of nesting depth
  • Applies middleware to all generated procedures through inheritance

Example Generated Integration:

// In src/generated/orpc/routers/helpers/createRouter.ts
import { permissions } from '../../../../custom-shield';
export const or = os.$context<Context>().use(permissions);

Using Custom Shield Files

For advanced use cases, you can provide your own shield file instead of auto-generation:

generator orpc {
  provider = "prisma-orpc-generator"
  output   = "./src/generated/orpc"

  generateShield = "true"
  shieldPath = "../../src/custom-shield"  // Dynamically resolved!
}

Supported Path Formats:

  • Relative paths: "../../src/auth/shield"
  • Project root relative: "src/auth/shield"
  • Absolute paths: "/absolute/path/to/shield"

Your custom shield file should export a permissions object:

// src/custom-shield.ts
import { rule, allow, deny, shield, or } from 'orpc-shield';
import type { Context } from '../generated/orpc/routers/helpers/createRouter';

const isAuthenticated = rule<Context>()(({ ctx }) => !!ctx.user);
const isAdmin = rule<Context>()(({ ctx }) => ctx.user?.role === 'admin');
const isOwner = rule<Context>()(({ ctx, input }) => {
  return ctx.user?.id === (input as any)?.userId;
});

export const permissions = shield<Context>({
  user: {
    userFindMany: allow,           // Match generated procedure names
    userCreate: isAuthenticated,   
    userUpdate: isAuthenticated,
    userDelete: or(isAdmin, isOwner),
    userDeleteMany: deny,          // Explicitly deny dangerous operations
  },
  post: {
    postFindMany: allow,
    postCreate: isAuthenticated,
    postUpdate: isAuthenticated,
    postDelete: isAuthenticated,
  },
}, {
  denyErrorCode: 'FORBIDDEN',      // Maps to HTTP 403
  debug: true,                     // Enable debug logging
  allowExternalErrors: true,       // Allow detailed error messages
});

Important: Shield procedure names should match your generated router names (e.g., userCreate, postFindMany).

Note: When using shieldPath, the generator will skip auto-generation and use your custom shield file instead.

Generated Shield Rules

The generator creates rules based on your Prisma models:

// Built-in rules (generated automatically)
const isAuthenticated = rule<Context>()(({ ctx }) => !!ctx.user);

// Example custom rules (user-defined)
const isAdmin = rule<Context>()(({ ctx }) => ctx.user?.role === 'admin');

// Model-specific rules (generated based on config)
const canReadUser = allow;           // Read operations: allow
const canWriteUser = isAuthenticated; // Write operations: require auth

// Shield configuration
export const permissions = shield<Context>({
  user: {
    list: canReadUser,
    findById: canReadUser,
    create: canWriteUser,
    update: canWriteUser,
    delete: canWriteUser,
  },
  post: {
    list: allow,
    create: isAuthenticated,
    update: isAuthenticated,
  },
});

Using Shield in Your Server

Import and use the generated shield:

import { appRouter, permissions } from './generated/orpc/routers';

// Apply shield at server level
const server = createServer(appRouter, {
  // Shield is applied via middleware
  middleware: [permissions]
});

// Or use with oRPC handlers
import { OpenAPIHandler } from '@orpc/openapi';

const handler = new OpenAPIHandler(appRouter, {
  // Shield permissions are automatically applied
  interceptors: [/* your interceptors */]
});

Context Requirements

Shield rules expect a Context with user information:

interface Context {
  prisma: PrismaClient;
  user?: {
    id: string;
    email?: string;
    name?: string;
    roles?: string[];
    permissions?: string[];
  };
}

Customization

Override default rules by modifying the generated shield.ts:

// Custom rule for post ownership
const isPostOwner = rule<Context>()(({ ctx, input }) => {
  return ctx.user?.id === (input as any)?.authorId;
});

// Use in shield config
const permissions = shield<Context>({
  post: {
    update: and(isAuthenticated, isPostOwner), // Auth + ownership
    delete: or(isAdmin, isPostOwner),          // Admin or owner
  },
});

Shield Options

| Option | Type | Default | Values | Description | |---|---|---|---|---| | generateShield | boolean (string) | "true" | "true", "false" | Enable shield generation | | shieldPath | string | — | — | Path to custom shield file (absolute, relative to project root, relative to output dir, or module specifier) | | defaultReadRule | enum | "allow" | "allow", "deny", "auth" | Default rule for read operations | | defaultWriteRule | enum | "auth" | "auth", "deny", "allow" | Default rule for write operations | | denyErrorCode | string | "FORBIDDEN" | — | Error code for denied access | | debug | boolean (string) | "false" | "true", "false" | Enable debug logging | | allowExternalErrors | boolean (string) | "false" | "true", "false" | Allow detailed error messages from shields |


🧪 Examples

What it does

  • Builds the generator
  • Generates Prisma artifacts
  • Seeds a local DB
  • Starts a small server using the generated routers/schemas

Notable files


❓ FAQ / Troubleshooting

Node version or ESM issues

  • Symptom: runtime errors about module type or syntax
  • Action: use Node 20.19.0+, 22.12.0+, or 24.0.0+; align package type with your build, then rebuild npm run build

Generated path is unexpected

Schema/config validation failures

  • Symptom: errors referencing invalid options
  • Action: check inputs against src/config/schema.ts; fix paths/booleans; re-run generation

Docs not emitted

Shield path resolution errors

  • Symptom: "Cannot find module" errors for shield imports
  • Action: verify shieldPath points to correct file; check file exports permissions object; ensure path is relative to project root or absolute
  • Note: generator now handles dynamic path resolution automatically for common directory structures

🧑‍💻 Development (Contributing)

Local dev loop

npm run dev         # watch build
npm run build       # one-off build
npm run lint        # lint
npm run lint:fix    # lint + fix
npm run format      # prettier
npm run typecheck   # types only

Local development (monorepo) provider example

generator orpc {
  provider = "../../lib/bin.js" // relative path to built generator
  output   = "./src/generated/orpc"
}

Testing

npm test               # unit/integration
npm run test:watch     # watch
npm run test:e2e       # Prisma-backed CRUD
npm run test:coverage  # coverage

Conventions

  • Conventional Commits
  • Ensure npm run build and npm run typecheck pass before PR
  • Update README.md if flags/outputs change

🗺️ Roadmap

  • Integration with oRPC Shield - Built-in authorization with dynamic path resolution
  • Schema-based Auth Configuration - Define authorization rules directly in Prisma schema, JSON, or TypeScript config files
  • Plugin hooks for custom emitters
  • Config discovery and overrides

📄 License

  • License: MIT — see the LICENSE file.
  • Copyright © 2025 Omar Dulaimi.

🙏 Acknowledgements

  • Prisma and its ecosystem
  • oRPC community and patterns
  • Zod for runtime validation
  • TypeScript tooling
  • Vitest and contributors

📝 Changelog

See CHANGELOG.md


Made with ❤️ by Omar Dulaimi