原始内容
Packages
| Package | Version | Description |
|---|---|---|
@woltz/rich-domain |
Core library — Entities, Aggregates, Value Objects, Criteria, Change Tracking, Domain Events | |
@woltz/rich-domain-prisma |
Prisma adapter — Unit of Work, batch operations, @Transactional decorator |
|
@woltz/rich-domain-drizzle |
Drizzle adapter — Unit of Work, batch operations, @Transactional decorator |
|
@woltz/rich-domain-typeorm |
TypeORM adapter — repository, transactions, batch executor | |
@woltz/rich-domain-export |
Multi-format data export (CSV, JSON, JSONL) with streaming support | |
@woltz/rich-domain-criteria-zod |
Zod schemas for validating Criteria query params from HTTP requests |
Quick Start
Install
npm install @woltz/rich-domain zod
Add an ORM adapter if needed:
@woltz/rich-domain-prisma,@woltz/rich-domain-drizzle, or@woltz/rich-domain-typeorm.
Define a Value Object
import { ValueObject, VOValidation } from "@woltz/rich-domain";
import { z } from "zod";
const emailSchema = z.string().email();
class Email extends ValueObject<string> {
protected static validation<VOValidation<string>> = { schema: emailSchema };
getDomain(): string {
return this.value.split("@")[1];
}
}
const email = new Email("john@example.com");
console.log(email.value); // "john@example.com"
console.log(email.getDomain()); // "example.com"
Define an Aggregate with Validation
import {
Aggregate,
Entity,
Id,
type EntityValidation,
type EntityHooks,
} from "@woltz/rich-domain";
import { z } from "zod";
// Child Entity
const PostSchema = z.object({
id: z.custom<Id>(),
title: z.string().min(1),
content: z.string(),
published: z.boolean(),
});
type PostProps = z.infer<typeof PostSchema>;
class Post extends Entity<PostProps> {
protected static validation: EntityValidation<PostProps> = {
schema: PostSchema,
};
publish() {
this.props.published = true;
}
get title() {
return this.props.title;
}
get content() {
return this.props.content;
}
}
// Aggregate Root
const UserSchema = z.object({
id: z.custom<Id>(),
email: z.custom<Email>(),
name: z.string().min(2),
posts: z.array(z.instanceof(Post)),
createdAt: z.date(),
});
type UserProps = z.infer<typeof UserSchema>;
class User extends Aggregate<UserProps, "createdAt"> {
protected static validation: EntityValidation<UserProps> = {
schema: UserSchema,
};
protected static hooks: EntityHooks<UserProps, User> = {
onBeforeCreate: (props) => {
if (!props.createdAt) props.createdAt = new Date();
},
};
// Recommended pattern for type-safe change tracking
getTypedChanges() {
interface Entities {
Post: Post;
}
return this.getChanges<Entities>();
}
addPost(title: string, content: string): void {
this.props.posts.push(new Post({ title, content, published: false }));
}
get email() {
return this.props.email.value;
}
get posts() {
return this.props.posts;
}
}
Query with Type-Safe Criteria
import { Criteria } from "@woltz/rich-domain";
const criteria = Criteria.create<User>()
.where("status", "equals", "active")
.whereContains("email", "@company.com")
.orderBy("createdAt", "desc")
.paginate(1, 20);
const result = await userRepository.find(criteria);
Automatic Change Tracking
const user = await userRepository.findById(userId);
user.addPost("Hello", "World");
user.posts[0].publish();
const changes = user.getTypedChanges();
// changes.of("Post").creates → [Post]
// changes.of("Post").updates → [{ entity: Post, changed: { published: { from: false, to: true } } }]
await userRepository.save(user); // Only the diff hits the database
user.markAsClean();
Domain Events
Rich Domain provides the IDomainEventBus interface — you bring the implementation (in-memory, BullMQ, Kafka, etc.).
import { DomainEvent, type IDomainEventBus } from "@woltz/rich-domain";
class OrderConfirmedEvent extends DomainEvent<{
orderId: string;
total: number;
}> {}
// Inside a use case
const order = Order.create(data);
await orderRepository.save(order);
await order.dispatchAll(eventBus); // Publishes and clears events automatically
Development
Prerequisites: Node.js ≥ 22.12.0
git clone https://github.com/tarcisioandrade/rich-domain.git
cd rich-domain
npm install
npm run build
npm test
Workspace commands:
npm run build --workspace=@woltz/rich-domain # Build a single package
npm run test --workspace=@woltz/rich-domain # Test a single package
npm run check # Type-check all packages
npm run lint # Lint all packages
npm run clean # Clean all build artifacts
Releasing packages (Changesets — see CONTRIBUTING.md):
npm run changeset # Describe changes + semver bump (per PR)
npm run version:packages # Apply versions + CHANGELOGs
npm run build:packages
npm run release # Publish to npm
Documentation
Visit woltz.mintlify.app for the full documentation covering core concepts, validation, criteria queries, repository patterns, ORM integrations, React components, and CLI reference.
Contributing
Contributions are welcome. See CONTRIBUTING.md for the changeset workflow and release process.
- Fork the repository
- Create your feature branch (
git checkout -b feature/my-feature) - Commit with conventional commits (
git commit -m 'feat: add something') - Add a changeset if you changed a publishable package:
npm run changeset - Run
npm run check && npm test && npm formatbefore pushing - Open a Pull Request