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-json-server-generator

v0.3.1

Published

Prisma 2+ generator to emit a JSON file that can be run with json-server

Readme

🚀 Prisma JSON Server Generator

Transform your Prisma schema into a fully functional REST API in seconds


🎯 Why Choose This Generator?

| 🔴 Before (Manual Setup) | 🟢 After (This Generator) | |:-----|:-----| | 📝 Create mock data manually | 🚀 npx prisma generate | | ✍️ Write JSON files by hand | ⚡ json-server prisma/generated/db.json | | 🔧 Set up json-server manually | | | 🔄 Maintain data consistency | | | 📋 Update when schema changes | | | | | | ❌ Time consuming | ✅ 2 commands to full REST API | | ❌ Error prone | ✅ Realistic data with faker.js | | ❌ Hard to maintain | ✅ Auto-sync with schema changes | | ❌ Inconsistent data | ✅ Customizable data patterns |


🚀 Quick Start

Get a fully functional REST API running in under 2 minutes:

1️⃣ Install

npm install prisma-json-server-generator --save-dev
npm install -g json-server

2️⃣ Add to your Prisma schema

prisma generate refuses to run on a schema without a datasource block, so a complete minimal prisma/schema.prisma looks like this. Nothing here ever connects to a database: the generator only reads your models.

Prisma 7:

generator json_server {
  provider = "prisma-json-server-generator"
}

datasource db {
  provider = "sqlite"
}

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  posts Post[]
}

model Post {
  id       Int    @id @default(autoincrement())
  title    String
  author   User?  @relation(fields: [authorId], references: [id])
  authorId Int?
}

Prisma 6 and below need a url on the datasource, which Prisma 7 removed:

datasource db {
  provider = "sqlite"
  url      = "file:./dev.db"
}

You do not need a client generator block. If your schema already has one (prisma-client on Prisma 7, prisma-client-js on Prisma 6), leave it: this generator runs happily next to either.

3️⃣ Generate & Launch

npx prisma generate                                  # Generate data
json-server prisma/generated/db.json --port 3001     # Launch API

The generator's default output directory is ./generated, resolved relative to your schema file, so the data lands in prisma/generated/db.json. Set output on the generator block to put it somewhere else.

4️⃣ Start Building! 🎉

Your REST API is now live at http://localhost:3001

  • GET /users - List all users
  • GET /posts - List all posts
  • POST /users - Create user
  • Full CRUD operations available!

🆕 New in v0.3.0

🎭 Custom Faker Patterns • 🎯 Data Volume Control • 🌱 Seed Data Support

🎭 Custom Patterns

{
  "customPatterns": {
    "User.email": "{{internet.email}}",
    "Product.price": "{{commerce.price}}"
  }
}

Generate realistic data with 50+ faker patterns

🎯 Volume Control

{
  "recordCounts": {
    "User": 100,
    "Product": 500,
    "Order": 1000
  }
}

Control exactly how much data you need

🌱 Seed Data

// seeds/admins.json
[{
  "id": 1,
  "role": "admin",
  "email": "[email protected]"
}]

Load real data then generate additional records


✨ Supported Prisma Versions

| Prisma Version | Generator Version | Status | |----------------|-------------------|--------| | 7.x (Latest) | next release | ✅ Fully Supported | | 6.x | 0.3.0+ | ✅ Fully Supported | | 5.x | 0.2.5+ | ✅ Compatible | | 4.x | 0.2.0 - 0.2.4 | ⚠️ Legacy | | 2.x/3.x | 0.1.2 and lower | ❌ Deprecated |

Prisma 7 needs a release newer than 0.3.0. Up to and including 0.3.0 this generator parsed your schema a second time using its own bundled copy of Prisma 6. On a Prisma 7 schema that parse fails with P1012: Argument "url" is missing in data source block, because Prisma 7 removed url from the datasource block. Those versions also declared requiresGenerators: ['prisma-client-js'] and so refused to run at all next to Prisma 7's prisma-client provider.


🚧 Known Limitations

This generator produces throwaway mock data for a local json-server. The following are real gaps, not bugs to be reported. Two escape hatches cover most of them: a custom faker pattern replaces the default value for one field, and seed data supplies whole records verbatim.

Only Int, String, DateTime, Boolean and enums are generated

Fields typed Float, Decimal, BigInt, Json or Bytes are silently omitted from the generated records. They do not appear as null; the key is simply absent. Given this model:

model Product {
  id        Int     @id @default(autoincrement())
  name      String
  price     Float
  cost      Decimal
  serial    BigInt
  metadata  Json
  thumbnail Bytes
  inStock   Boolean
}

you get records with only id, name and inStock. A price on a product is exactly the sort of field you would want in mock data, so set it explicitly. A custom pattern is checked before the field's type is looked at, so this brings the dropped field back:

{
  "customPatterns": {
    "Product.price": "{{commerce.price}}"
  }
}

Collection names are pluralised by appending s

The endpoint name is the lowercased model name with an s stuck on the end. There is no real pluraliser, so Category becomes /categorys, Person becomes /persons and Status becomes /statuss. Models that already end in s get a second one. Name your models so that the naive plural reads correctly, or expect the odd URL.

Seed files are matched to collections by filename, so they have to use the same naive plural: seed data for Category belongs in seeds/categorys.json. Name it categories.json and it still loads, but into a separate categories collection that no model feeds, leaving /categorys with nothing but randomly generated records.

The built-in faker patterns are crude

With no customPatterns configured, a String field is matched by case-sensitive substring, first hit wins: name, then email, then title, otherwise a lorem sentence. DateTime is matched the same way on create and update. That is the whole of it, so it misfires in both directions:

| Field | Generated value | Why | |-------|-----------------|-----| | name | "Lawson" | a person's first name, as intended | | filename | "Alexane" | also a person's first name, because it contains name | | firstName | "Contra amitto tantum minus..." | lorem, because Name is not name | | Email | "Vae antiquus vulnus certus..." | lorem, for the same reason | | title | "Supervisor" | a job type, which is not what most title fields hold | | jobTitle | "Bis spes aperte eos tondeo..." | lorem |

Relations are not made consistent either. Every Int field, foreign keys included, gets an independent random integer, so Post.authorId will not match the id of any generated User and nested lookups on the running API return nothing. Use seed data if you need relations that actually resolve.


📦 Installation

# npm
npm install prisma-json-server-generator --save-dev

# yarn
yarn add prisma-json-server-generator --dev

# pnpm
pnpm add -D prisma-json-server-generator

Don't forget json-server:

npm install -g json-server

🔧 Advanced Configuration

💪 Power User Setup

Create prisma/json-server-config.json:

{
  "outputFileName": "api-data.json",
  "recordCounts": {
    "User": 50,
    "Product": 200,
    "Category": 10,
    "Order": 300
  },
  "customPatterns": {
    "User.email": "{{internet.email}}",
    "User.firstName": "{{person.firstName}}",
    "User.lastName": "{{person.lastName}}",
    "User.avatar": "{{image.avatar}}",
    "Product.name": "{{commerce.productName}}",
    "Product.price": "{{commerce.price}}",
    "Product.description": "{{commerce.productDescription}}",
    "Category.name": "{{commerce.department}}",
    "Order.status": "{{helpers.arrayElement(['pending', 'shipped', 'delivered'])}}"
  },
  "seedData": {
    "enabled": true,
    "seedDataPath": "./seeds/",
    "generateAdditionalRecords": true
  }
}

Update your schema:

generator json_server {
  provider = "prisma-json-server-generator"
  config   = "./prisma/json-server-config.json"
}

🎨 Popular Faker Patterns

{
  "User.firstName": "{{person.firstName}}",
  "User.lastName": "{{person.lastName}}",
  "User.fullName": "{{person.fullName}}",
  "User.jobTitle": "{{person.jobTitle}}",
  "User.bio": "{{person.bio}}"
}
{
  "User.email": "{{internet.email}}",
  "User.username": "{{internet.userName}}",
  "User.website": "{{internet.url}}",
  "User.phone": "{{phone.number}}"
}
{
  "Product.name": "{{commerce.productName}}",
  "Product.price": "{{commerce.price}}",
  "Product.department": "{{commerce.department}}",
  "Product.material": "{{commerce.productMaterial}}"
}
{
  "Address.street": "{{location.streetAddress}}",
  "Address.city": "{{location.city}}",
  "Address.country": "{{location.country}}",
  "Address.zipCode": "{{location.zipCode}}"
}

🌱 Seed Data Example

1. Create seed files:

seeds/
├── users.json        # Admin users, test accounts
├── categories.json   # Product categories  
└── settings.json     # App configuration

2. Example seed file (seeds/users.json):

[
  {
    "id": 1,
    "email": "[email protected]",
    "firstName": "Admin",
    "lastName": "User",
    "role": "ADMIN"
  },
  {
    "id": 2,
    "email": "[email protected]", 
    "firstName": "Demo",
    "lastName": "User",
    "role": "USER"
  }
]

3. Configure in your JSON config:

{
  "seedData": {
    "enabled": true,
    "seedDataPath": "./seeds/",
    "generateAdditionalRecords": true
  },
  "recordCounts": {
    "User": 25  // Will generate 23 more (25 - 2 seeds)
  }
}

🧪 Testing

This project uses Vitest for lightning-fast testing:

# Run tests in watch mode
npm test

# Run tests once  
npm run test:run

# Generate coverage report
npm run test:coverage

Test Coverage:

  • ✅ Configuration validation
  • ✅ Faker pattern evaluation
  • ✅ Seed data loading
  • ✅ Record generation logic
  • ✅ Error handling

🛠️ Generator Options

In schema.prisma:

| Option | Description | Type | Default | |--------|-------------|------|---------| | output | Output directory | string | ./generated | | config | External config file path | string | null |

generator json_server {
  provider = "prisma-json-server-generator"
  output   = "./api-data"
  config   = "./my-config.json" 
}

In external config file:

| Option | Description | Type | Default | |--------|-------------|------|---------| | outputFileName | Generated JSON filename | string | db.json | | recordCounts | Records per model | Record<string,number> | {} | | customPatterns | Faker patterns | Record<string,string> | {} | | seedData | Seed configuration | object | {} |


🎨 Real-World Examples

Schema:

model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  firstName String
  lastName  String
  orders    Order[]
}

model Product {
  id          Int      @id @default(autoincrement())
  name        String
  price       Float
  categoryId  Int
  category    Category @relation(fields: [categoryId], references: [id])
}

model Category {
  id       Int       @id @default(autoincrement())
  name     String
  products Product[]
}

model Order {
  id     Int  @id @default(autoincrement())
  userId Int
  user   User @relation(fields: [userId], references: [id])
  total  Float
}

Configuration:

{
  "recordCounts": {
    "User": 100,
    "Product": 500, 
    "Category": 12,
    "Order": 1000
  },
  "customPatterns": {
    "User.email": "{{internet.email}}",
    "User.firstName": "{{person.firstName}}",
    "User.lastName": "{{person.lastName}}",
    "Product.name": "{{commerce.productName}}",
    "Product.price": "{{commerce.price}}",
    "Category.name": "{{commerce.department}}"
  }
}

Generated API endpoints:

  • GET /users - Customer list
  • GET /products - Product catalog
  • GET /categories - Product categories
  • GET /orders - Order history
  • Full CRUD on all resources

Schema:

model User {
  id       Int    @id @default(autoincrement())
  username String @unique
  email    String @unique
  avatar   String?
  bio      String?
  posts    Post[]
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String
  imageUrl  String?
  likes     Int      @default(0)
  authorId  Int
  author    User     @relation(fields: [authorId], references: [id])
  createdAt DateTime @default(now())
}

Configuration:

{
  "recordCounts": {
    "User": 200,
    "Post": 1000
  },
  "customPatterns": {
    "User.username": "{{internet.userName}}",
    "User.email": "{{internet.email}}",
    "User.avatar": "{{image.avatar}}",
    "User.bio": "{{lorem.sentence}}",
    "Post.title": "{{lorem.sentence}}",
    "Post.content": "{{lorem.paragraphs}}",
    "Post.imageUrl": "{{image.url}}",
    "Post.likes": "{{number.int({'min': 0, 'max': 500})}}"
  }
}

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.


Made with ❤️ by Omar Dulaimi

Don't forget to star this repo if you found it useful!