Overview
@woltz/rich-domain-prisma provides seamless integration between rich-domain and Prisma ORM. It leverages Prisma’s nested writes and transaction support to align perfectly with rich-domain’s change tracking and Unit of Work patterns.
Unit of Work
Request-isolated transactions with AsyncLocalStorage
Repository Base Class
PrismaRepository with built-in Criteria support
Change Tracking
PrismaToPersistence with automatic change detection
Batch Operations
PrismaBatchExecutor for efficient bulk writes
Transactional Outbox
Optional
outboxStore on the repository for guaranteed event deliveryFor a complete working example, see the fastify-with-prisma example in the repository.
Quick Start
1. Setup
2. Create Repository
3. Use It
PrismaUnitOfWork
Manages transactions with per-request isolation usingAsyncLocalStorage.
Transaction Execution
Request Isolation
Each HTTP request gets its own transaction context, preventing cross-request interference:API Reference
| Method | Description |
|---|---|
transaction(work) | Execute work function in a transaction |
isInTransaction() | Check if currently in a transaction |
getCurrentContext() | Get current transaction context or null |
@Transactional Decorator
Decorator that automatically wraps a method in a transaction.With Explicit UoW Parameter
You can pass the UoW instance directly to the decorator instead of relying on constructor injection:UoW Resolution Order
The decorator looks for the UoW instance in this order:- Decorator parameter -
@Transactional(myUow) - Instance property -
this.uow - Private property -
this._uow - Any property - Any property that is a
PrismaUnitOfWorkinstance
Behavior
| Scenario | Behavior |
|---|---|
| Direct call | Creates new transaction |
| Already in transaction | Reuses existing one |
| Error thrown | Automatic rollback |
PrismaRepository
Base class for repositories with full Criteria support.Complete Implementation
Context Awareness
The repository automatically uses the transaction context when available:Transactional Outbox
Pass an optionaloutboxStore as the fifth argument to PrismaRepository’s constructor. When set, save() automatically persists uncommitted domain events to the outbox table in the same database transaction as the aggregate write.
| Property | Type | Required | Description |
|---|---|---|---|
outboxStore | PrismaOutboxStore | No | Enables auto-save of domain events on save() |
PrismaOutboxStore from @woltz/rich-domain-prisma. For the full setup (table migration, event bus decorator, background publisher), see Transactional Outbox.
EntitySchemaRegistry
Maps domain entities to database tables, handles field mapping, and configures relationships.See the complete Schema Registry documentation for all features.
Basic Registration
Collection Configuration (N:N Relations)
For N:N relationships, configure collections withtype: "reference":
Collection Types
| Type | Relationship | Batch Behavior |
|---|---|---|
owned | 1:N | createMany / deleteMany |
reference | N:N | connect / disconnect |
PrismaBatchExecutor automatically uses the correct Prisma operations based on collection type:
PrismaToPersistence
Base mapper class with change tracking integration.Complete Example
changes.without() to persist one entity manually and pass the remaining changes to super.onUpdate().
PrismaBatchExecutor
Executes batch operations fromAggregateChanges with proper ordering and relationship handling.
Execution Order
The executor respects referential integrity:-
Deletes - Leaf → Root (depth DESC)
owned: UsesdeleteManyreference: Usesdisconnect
-
Creates - Root → Leaf (depth ASC)
owned: UsescreateManyreference: Usesconnect
- Updates - Any order
registry.getPrimaryKeyField() and registry.buildWhereById(). Configure primaryKey when a table does not use an id column (e.g. factoryProfile.factoryId). Remember: primaryKey names the database column; the value always comes from entity.id, not from a domain property with the same name.
Convenience Function
Complete Example
Domain Model
Schema Registry
Mappers
Repository
Use Case
Error Handling
The adapter provides specific error types:Complete Example
See the fastify-with-prisma example for a complete working application demonstrating:- User aggregate with Posts (1:N owned)
- Post with Tags (N:N reference via junction table)
- Case-insensitive search
- Transaction management
- CRUD operations
- Domain events with BullMQ
API Reference
Exports
PrismaRepositoryConfig
prisma, uow, and optional outboxStore.
PrismaUnitOfWork Methods
| Method | Returns | Description |
|---|---|---|
transaction(work) | Promise<T> | Execute work in transaction |
isInTransaction() | boolean | Check if in transaction |
getCurrentContext() | PrismaTransactionContext | null | Get current context |
PrismaRepository Methods
| Method | Returns | Description |
|---|---|---|
find(criteria) | Promise<PaginatedResult<T>> | Find with criteria |
findById(id) | Promise<T | null> | Find by ID |
findManyByIds(ids) | Promise<T[]> | Find multiple by IDs |
count(criteria?) | Promise<number> | Count entities |
exists(id) | Promise<boolean> | Check if exists |
save(entity) | Promise<void> | Create or update |
delete(entity) | Promise<void> | Delete entity |
deleteById(id) | Promise<void> | Delete by ID |
transaction(work) | Promise<T> | Execute in transaction |