nestrs-prisma
Nest-style PrismaModule / PrismaService for nestrs: configuration, optional SQLx pooling (DATABASE_URL), and helpers that stay ORM-agnostic so you can choose how models are represented in Rust.
Docs: docs.rs/nestrs-prisma · Repo: github.com/Joshyahweh/nestrs
[]
= "0.1"
= { = "0.3.4", = ["sqlx", "sqlx-sqlite"] }
= "0.3.4"
When enabling sqlx, choose exactly one backend feature in your app: sqlx-sqlite, sqlx-postgres, or sqlx-mysql. If more than one is enabled (for example through workspace --all-features), the concrete driver is selected in priority order: Postgres, then MySQL, then SQLite.
The async-trait crate must be a direct dependency of any crate that invokes prisma_model!, because the generated repository trait uses #[async_trait::async_trait].
Run the quickstart example
There are two ways to run quickstart:
A) From this repository (maintainers/contributors)
From the nestrs workspace root:
B) From your own app (crate consumers on nestrs-prisma = "0.3.4")
cargo run -p nestrs-prisma ... will not work in your app, because -p targets a package in your current workspace.
Instead:
- Add dependency:
= { = "0.3.4", = ["sqlx", "sqlx-postgres"] }
= "0.3.4"
= { = "1", = ["macros", "rt-multi-thread"] }
- Fetch quickstart source into your app as
examples/quickstart.rs(no manual copying):
Alternative (fetch from crates.io source):
- Run from your app root:
If DATABASE_URL is not set, the example defaults to sqlite:quickstart.db.
With prisma/schema.prisma present, it also generates bindings and writes src/models/prisma_generated.rs.
1. Write models in Prisma
Add a schema next to your app (convention: prisma/schema.prisma):
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String
}
Use prisma migrate, prisma db push, or your own SQL migrations to apply it to the database.
2. Map rows in Rust (SQLx path, no codegen)
Enable sqlx on nestrs-prisma. Mirror columns with sqlx::FromRow and load via PrismaService::query_all_as:
let users: = prisma
.query_all_as
.await?;
Use PrismaService::execute for DDL/DML without a row mapper (e.g. migration scripts).
3. Declarative prisma_model! (NestJS / Prisma-shaped repository)
With sqlx enabled, you can declare a table-bound model once. The macro expands to:
- A
#[derive(sqlx::FromRow)]struct for the row shape. UserWhere(per model) withAnd/Or/Not, per-fieldequals/not, and helpers under a lowercase module (e.g.user::id::equals(1)).UserUpdatewithOptionfields anduser::email::set("…")-style builders.UserCreateInput: if the first field isid: i64, it is omitted from create input (auto-increment inserts).UserOrderByanduser::id::order(SortOrder::Desc).PrismaUserRepository(async trait) implemented forModelRepository<User>with:find_unique,find_first,find_many,find_many_with_options,count,create,create_many,update,update_many,upsert,delete,delete_many.PrismaUserClientExtonArc<PrismaService>so you can writeprisma.user().find_unique(…).
Errors: PrismaError maps to nestrs::HttpException via impl From<PrismaError> for HttpException (404 for missing rows, 409 for unique violations, 503-style for pool issues).
Example:
prisma_model!;
// `PrismaUserRepository` + `PrismaUserClientExt` live in this module after the macro expands.
async
Supported field types today: i64, String, bool (extend the macro for more as needed).
Note: In-memory SQLite with SQLx Any works most reliably with a single-connection pool (pool_max(1)) so DDL and queries share one database. File-backed URLs avoid that limitation.
4. Optional: Prisma Client Rust (cargo prisma generate)
For generated model APIs, add prisma-client-rust to your app, run:
Register the generated client as an extra #[injectable] / module provider alongside PrismaService. This crate does not embed the codegen CLI; it focuses on connectivity and a PrismaService shape familiar to Nest users.
5. Generate command hint
After PrismaModule::for_root, you can surface the documented generate line with:
let hint = generate_command_hint;