Introduction
A complete, type-safe CRUD abstraction for Drizzle ORM in NestJS — configure the connection once, extend one base class per entity, and inherit full CRUD.
What it is
nestjs-drizzle-crud is a thin abstraction over Drizzle ORM that gives every NestJS service a complete, type-safe CRUD surface — find, findOne, findAll, create, update, delete, softDelete, restore, massCreate, massUpdate, massDelete, fullTextSearch, plus filtering, pagination, relations, hooks and transactions — by extending a single generic base class.
It works with both PostgreSQL and MySQL and handles the dialect differences (PostgreSQL's RETURNING vs MySQL's insertId) for you, so your service code is identical across databases.
The two-step mental model
The whole library is built on two steps:
Configure the database connection once
In your AppModule, call DrizzleCrudModule.forRoot(...) with the dialect, connection (either a connection string or a pre-built Drizzle instance), and the schema. The module creates and owns the connection, exposes it globally, and closes it on shutdown.
Per entity: extend the base, bind the table
For each entity, create an empty service class that extends SqlBaseCrudService<Entity>, then register it in a feature module with DrizzleCrudModule.forFeature([{ service, table }]). The service gets every CRUD method automatically, fully typed against your entity.
That's the entire library surface. Everything else — soft delete, bulk ops, full-text search, hooks, transactions, relations — is enabled through configuration, not new APIs to learn.
When to use it
Use nestjs-drizzle-crud when you want:
- A standard REST/JSON CRUD surface over a relational schema.
- To stop writing the same
findAll/create/updateboilerplate in every service. - Type-safe query and result types inferred from your Drizzle schema.
- Soft delete, audit timestamps, and filtering/sorting out of the box.
- Bulk operations that roll back atomically when one row fails.
- A library that doesn't hide Drizzle — you can drop down to raw
db.select()whenever you need to.
When not to use it
- Complex aggregate queries. If most of your endpoints are joins, window functions, or domain-specific reads, hand-written Drizzle will be clearer.
- Has-many / many-to-many relations. Only many-to-one / belongs-to relations are supported. Model those with custom service methods over
this.config.db. - Non-CRUD write patterns. If your writes are mostly multi-step domain operations (workflows, sagas), use a hand-rolled service and only pull in
nestjs-drizzle-crudfor the simple entities. - GraphQL. The library returns plain objects shaped for REST. Use it with REST controllers; for GraphQL you'll write resolvers against the service methods directly.
Quick taste
import { Module } from '@nestjs/common';
import { DrizzleCrudModule } from 'nestjs-drizzle-crud';
import { schema } from './db/schema';
import { UsersModule } from './users/users.module';
@Module({
imports: [
DrizzleCrudModule.forRoot({
dialect: 'postgresql',
connectionString: process.env.DATABASE_URL,
schema,
}),
UsersModule,
],
})
export class AppModule {}That's it — your UsersService already exposes find, findOne, findAll, create, update, delete, softDelete, restore, massCreate, massUpdate, count, exists, executeSqlTransaction, and fullTextSearch (Postgres), all typed against User.
Ready to wire it up? Head to the Quick start for a complete 5-minute walkthrough, or read Installation for the full peer-dependency matrix.