I built an npm package that auto-generates a REST API from your Prisma schema
Every time I started a new backend project with Prisma, I found myself writing the same thing over and over.
A controller for users. A controller for posts. Pagination logic. Error handling. The same response shape copy-pasted across every endpoint. It's tedious, repetitive, and honestly — it's not real work. It's just boilerplate.
So I built apiform to solve this once and for all.
What is apiform?
apiform is an npm package that sits on top of your existing Prisma setup and automatically generates a fully structured REST API from your models. No controllers. No route handlers. No boilerplate.
Your Prisma Schema → apiform → Fully structured REST API
Quick demo
Here's all the code you need to get a full API running:
import { PrismaClient } from "@prisma/client";
import { PrismaLibSql } from "@prisma/adapter-libsql";
import { ApiForm } from "apiform";
const adapter = new PrismaLibSql({ url: "file:./prisma/dev.db" });
const prisma = new PrismaClient({ adapter });
const app = new ApiForm(prisma, {
globalPrefix: "/api",
models: {
user: true,
post: true,
},
});
app.start(3000);
That's it. You instantly get these routes for every model:
| Method | Route | Action |
|---|---|---|
| GET | /api/users |
Find all (paginated) |
| GET | /api/users/:id |
Find by ID |
| POST | /api/users |
Create |
| PATCH | /api/users/:id |
Update |
| DELETE | /api/users/:id |
Delete |
Consistent response shape
Every single endpoint returns the same predictable structure:
{
"success": true,
"message": "USERS_RETRIEVED_SUCCESSFULLY",
"data": [],
"meta": {
"total": 100,
"page": 1,
"limit": 10,
"totalPages": 10,
"hasNext": true,
"hasPrev": false
},
"error": null
}
No more inconsistent responses across your API. Every endpoint behaves the same way.
Built-in pagination, search and filtering
All list endpoints support query parameters out of the box:
GET /api/users?page=2&limit=5&searchBy=name&searchValue=john&sortBy=createdAt&sortOrder=desc
No extra code needed.
Soft delete
Add deletedAt DateTime? to your Prisma model and soft delete is automatically enabled. Records are never permanently deleted — just marked with a timestamp.
model User {
id Int @id @default(autoincrement())
name String
email String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?
}
apiform automatically generates three extra routes:
-
DELETE /api/users/:id— soft deletes the record -
GET /api/users/deleted— retrieves all soft deleted records -
PATCH /api/users/:id/restore— restores a soft deleted record
Soft deleted records are automatically excluded from all normal queries.
Nested relations
Include related models in your queries with a simple query parameter:
GET /api/posts?include=author
GET /api/users/1?include=posts,comments
Fully customizable
apiform is convention over configuration — everything works out of the box. But you can customize anything:
const app = new ApiForm(prisma, {
models: {
user: {
delete: { enabled: false },
findAll: { middleware: [authMiddleware] },
prefix: "/members",
},
},
});
Custom routes
Need something apiform doesn't generate? Add your own routes on top:
app.addRoutes((fastify) => {
fastify.get("/api/users/count", async (request, reply) => {
const count = await prisma.user.count();
reply.send({
success: true,
data: { count },
message: "USERS_COUNTED_SUCCESSFULLY",
meta: null,
error: null,
});
});
});
app.start(3000);
TypeScript generics
All operations are fully typed:
import type { User } from "@prisma/client";
const result = await crud.findById<User>("user", 1);
result.data.email // ✅ fully typed
Why Fastify?
I chose Fastify over Express because it's significantly faster, has first-class TypeScript support, and schema-based validation built in. The performance difference is real — especially for high-traffic APIs.
What's next?
This is v0.2.0 — the package is functional and published but there's a lot more planned:
- Support for other ORMs (Sequelize, TypeORM)
- More advanced filtering options
- Auto-generated OpenAPI/Swagger docs
Try it
npm install apiform
# or
bun add apiform
I'd genuinely love feedback — especially from developers who work with Prisma daily. What would make this actually useful in your projects? What's missing? What would you change?
Top comments (1)
Great package! Working with Prisma daily, the boilerplate fatigue is incredibly real. To answer your question about what would make it useful: an easy, standardized way to handle Role-Based Access Control (RBAC) on specific auto-generated routes would be a game changer. Also, love the zero-boilerplate approach to soft deletes. Starred the repo!