@sidhxntt/prismify-express
v2.0.0
Published
CLI that generates a complete Express REST API from a Prisma schema, with validation, pagination and safe defaults.
Maintainers
Readme
@sidhxntt/prismify-express
A CLI tool that generates a complete Express REST API from your Prisma schema. Transform your database schema into ready-to-extend API endpoints with full CRUD operations, validation and pagination.
Features
- 🚀 Zero configuration — generate an API directly from a
schema.prisma - 🧠 Real Prisma parsing — uses
@prisma/internals(getDMMF), so composite@@id,@@map,viewblocks, block comments andJson @default("{}")all parse correctly - 📝 Full CRUD — GET / POST / PATCH / DELETE per model
- 🔍 Safe pagination —
page/limitcoerced withNumber.parseInt,limitclamped to 100,orderBychecked against a per-model allowlist - ✅ Real validation — ISO-8601 parsing for
DateTime, membership checks for enums, array/null guards forJson, precision-preservingBigInt/Decimalhandling - 🔐 Secrets excluded by default —
password,passwordHash,resetToken,apiKey, … are never returned (opt out with--include-sensitive) - 🗣️ Correct pluralization —
Category→/api/categories,Person→/api/people - 🔌 One shared PrismaClient — a single connection pool plus graceful
SIGINT/SIGTERMshutdown - 🛡️ Hardened defaults —
helmet, a 1 MB body cap and a closed-by-default CORS origin - 📦 Complete setup — generates
package.json,README.md,.env.example(matched to your datasource provider) and.gitignore
Prerequisites
- Node.js 20.0.0 or higher (required by
commander@14) - A Prisma schema file (
schema.prisma)
Installation
Install globally via npm:
npm install -g @sidhxntt/prismify-expressOr use npx to run without installing:
npx @sidhxntt/prismify-express generate schema.prismaUsage
Basic generation
prismify-express generate prisma/schema.prismaCustom output directory
prismify-express generate prisma/schema.prisma --output ./my-apiOverwriting an existing output directory
Generation refuses to clobber existing files and lists exactly what it would overwrite. Re-run with --force once you are happy to lose local edits:
prismify-express generate prisma/schema.prisma --forcePreview mode
prismify-express generate prisma/schema.prisma --dry-run--dry-run also marks which files already exist and would be overwritten.
Inspect a schema
prismify-express inspect prisma/schema.prismaLists models, fields, defaults, composite keys, @@map names, enums and the route each model will be mounted at. Exits non-zero if the schema fails to parse or contains no models.
Generated API structure
generated-api/
├── prisma/
│ └── schema.prisma # Copy of your original schema
├── src/
│ ├── routes/
│ │ ├── user.js # Routes for User model
│ │ └── category.js # Routes for Category model
│ ├── prisma.js # The single shared PrismaClient
│ ├── validators.js # Shared request validation helpers
│ ├── app.js # Express app configuration
│ └── server.js # Server entry point + graceful shutdown
├── .env.example # Environment variables template
├── .gitignore
├── README.md # Docs for the generated API
└── package.jsonGenerated API endpoints
Model names are pluralized properly, so Category becomes /api/categories (not /api/categorys) and Person becomes /api/people.
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /api/{models} | List records with pagination |
| GET | /api/{models}/:id | Get single record by id |
| POST | /api/{models} | Create a record |
| PATCH | /api/{models}/:id | Update a record |
| DELETE | /api/{models}/:id | Delete a record |
Models with a composite @@id([a, b]) get list/create routes only, with a comment explaining why. view blocks get read routes only.
Example API calls
# List users with pagination (limit is clamped to 100; orderBy is allowlisted)
GET /api/users?page=1&limit=10&orderBy=createdAt&order=desc
# Get specific user
GET /api/users/123
# Create new user — fields with @default() are optional but ARE honoured when sent
POST /api/posts
{
"title": "Hello",
"userId": 1,
"published": true # published Boolean @default(false) → stored as true
}
# Update user
PATCH /api/users/123
{ "username": "jane" }
# Delete user
DELETE /api/users/123Behaviour worth knowing
Fields with @default(...)
A defaulted field is optional on create but still writable. Sending {"published": true} for published Boolean @default(false) stores true; omitting it falls back to the database default. Only genuinely non-writable columns are rejected: an @id backed by @default(autoincrement()/uuid()/cuid()/…) and any @updatedAt.
Sensitive fields
These field names are matched case-insensitively and omitted from every generated select:
password, passwordHash, hashedPassword, salt, resetToken, refreshToken, accessToken, secret, apiKey, otp, mfaSecret, twoFactorSecret
Each generated route file carries a comment listing what was excluded and how to re-enable it (add the field back to that file's select). --include-sensitive disables the exclusion entirely.
Query parameters
orderBy is validated against ORDERABLE_FIELDS, a per-model allowlist emitted at the top of each route file, and order must be asc or desc; anything else returns 400 instead of reaching Prisma. page and limit are parsed with Number.parseInt and guarded with Number.isFinite, defaulting to 1 and 20, with limit clamped to 100.
⚠ The generated API has no authentication
Every generated endpoint is public. The generator deliberately does not invent an auth scheme — add authentication, per-route authorization and rate limiting before exposing the API beyond localhost. This is restated in the generated project's own README.md.
Configuration
After generation:
- Copy
.env.exampleto.env(theDATABASE_URLtemplate matches your schema'sdatasource provider):
cp .env.example .env- Install dependencies:
npm install- Generate the Prisma client:
npx prisma generate- Run migrations:
npx prisma migrate dev- Start the server:
npm startExample Prisma schema
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
password String // excluded from every response
role Role @default(USER)
posts Post[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum Role {
USER
ADMIN
}CLI reference
prismify-express generate <schema> [options]
Arguments:
schema Path to Prisma schema file
Options:
-o, --output <dir> Output directory (default: "./generated-api")
--no-package Skip generating package.json
--dry-run Preview output without writing files
--force Overwrite existing files in the output directory
--include-sensitive Include password/token-like fields in the generated select
-h, --help Display help for command
prismify-express inspect <schema>Project structure
src/parser.js— parses a Prisma schema with@prisma/internalsand adapts the DMMF into{ models, enums, types, datasourceProvider }src/generator.js— generates the route files, shared client, validators and project scaffoldingsrc/index.js— CLI interface and orchestrationtest/—node:testsuite (npm test)
Development
npm install
npm testContributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
