woltz-rich-domain
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese@woltz/rich-domain
@woltz/rich-domain
TypeScript library for Domain-Driven Design with automatic change tracking and Standard Schema validation.
这是一个用于领域驱动设计(DDD)的TypeScript库,具备自动变更追踪和标准Schema验证功能。
Requirements
环境要求
- Node.js >= 22.12
- TypeScript >= 5.4
- Node.js >= 22.12
- TypeScript >= 5.4
Ecosystem
生态系统
| Package | Purpose |
|---|---|
| Core DDD building blocks |
| Prisma ORM adapter |
| TypeORM adapter |
| Zod schemas for Criteria API |
| Multi-format data export |
| 包名称 | 用途 |
|---|---|
| 核心DDD构建模块 |
| Prisma ORM适配器 |
| TypeORM适配器 |
| Criteria API的Zod Schema支持 |
| 多格式数据导出 |
Quick Start
快速开始
1. Define a Value Object
1. 定义值对象
typescript
import { ValueObject } from "@woltz/rich-domain";
import { z } from "zod";
class Email extends ValueObject<string> {
protected static validation = {
schema: z.string().email(),
};
getDomain(): string {
return this.value.split("@")[1];
}
}typescript
import { ValueObject } from "@woltz/rich-domain";
import { z } from "zod";
class Email extends ValueObject<string> {
protected static validation = {
schema: z.string().email(),
};
getDomain(): string {
return this.value.split("@")[1];
}
}2. Define an Entity
2. 定义实体
typescript
import { Entity, Id } from "@woltz/rich-domain";
const PostSchema = z.object({
id: z.custom<Id>(),
title: z.string().min(1),
content: z.string(),
published: z.boolean(),
});
class Post extends Entity<z.infer<typeof PostSchema>> {
protected static validation = { schema: PostSchema };
publish(): void {
this.props.published = true;
}
get title() {
return this.props.title;
}
}typescript
import { Entity, Id } from "@woltz/rich-domain";
const PostSchema = z.object({
id: z.custom<Id>(),
title: z.string().min(1),
content: z.string(),
published: z.boolean(),
});
class Post extends Entity<z.infer<typeof PostSchema>> {
protected static validation = { schema: PostSchema };
publish(): void {
this.props.published = true;
}
get title() {
return this.props.title;
}
}3. Define an Aggregate
3. 定义聚合根
typescript
import { Aggregate, Id, EntityHooks } from "@woltz/rich-domain";
import { UserCreatedEvent } from "./events";
import { Email } from "./email";
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(),
});
export type UserProps = z.infer<typeof UserSchema>;
class User extends Aggregate<UserProps, "createdAt"> {
protected static validation = { schema: UserSchema };
protected static hooks: EntityHooks<UserProps, User> = {
onBeforeCreate: (props) => {
if (!props.createdAt) props.createdAt = new Date();
},
onCreate: (entity) => {
if (entity.isNew()) {
entity.addDomainEvent(new UserCreatedEvent({ id: entity.id.value }));
}
},
};
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;
}
}typescript
import { Aggregate, Id, EntityHooks } from "@woltz/rich-domain";
import { UserCreatedEvent } from "./events";
import { Email } from "./email";
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(),
});
export type UserProps = z.infer<typeof UserSchema>;
class User extends Aggregate<UserProps, "createdAt"> {
protected static validation = { schema: UserSchema };
protected static hooks: EntityHooks<UserProps, User> = {
onBeforeCreate: (props) => {
if (!props.createdAt) props.createdAt = new Date();
},
onCreate: (entity) => {
if (entity.isNew()) {
entity.addDomainEvent(new UserCreatedEvent({ id: entity.id.value }));
}
},
};
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;
}
}4. Use Change Tracking
4. 使用变更追踪
typescript
const user = await userRepository.findById(userId);
// Make changes
user.addPost("New Post", "Content");
user.posts[0].publish();
// Get changes automatically
// We strongly recommend using this `getTypedChanges` helper pattern for better DX
const changes = user.getTypedChanges();
// { creates: [...], updates: [...], deletes: [...] }
// After saving
user.markAsClean();typescript
const user = await userRepository.findById(userId);
// 进行变更操作
user.addPost("New Post", "Content");
user.posts[0].publish();
// 自动获取变更记录
// 我们强烈推荐使用`getTypedChanges`辅助方法以提升开发体验(DX)
const changes = user.getTypedChanges();
// { creates: [...], updates: [...], deletes: [...] }
// 保存后
user.markAsClean();5. Query with Criteria
5. 使用Criteria进行查询
typescript
import { Criteria } from "@woltz/rich-domain";
// fully type-safe, fields inferred from schema
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);typescript
import { Criteria } from "@woltz/rich-domain";
// 完全类型安全,字段从Schema自动推导
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);Core Principles
核心原则
- Aggregates define consistency boundaries - Modify entities through their aggregate root
- Value Objects are immutable - Use to create modified copies
clone() - Id tracks new vs existing - for INSERT,
new Id()for UPDATEId.from(value) - Change tracking is automatic - Use and
getChanges()markAsClean() - Repositories abstract persistence - Domain layer doesn't know about database
- 聚合根定义一致性边界 - 通过聚合根修改实体
- 值对象不可变 - 使用创建修改后的副本
clone() - Id追踪新/已有状态 - 新建用,更新用
new Id()Id.from(value) - 变更追踪自动化 - 使用和
getChanges()markAsClean() - 仓库抽象持久化 - 领域层无需感知数据库细节
References
参考文档
For detailed documentation on specific topics:
- Core Concepts - Entities, Aggregates, Value Objects, Lifecycle Hooks
- Domain Events - Event-driven architecture with example using BullMQ
- Criteria API - Type-safe query building with filters, ordering, pagination
- Criteria Zod - Zod schemas for API query validation
- Schema Registry - EntitySchemaRegistry for field mapping and relationships
- Prisma Adapter - PrismaRepository, UnitOfWork, Transactions
- TypeORM Adapter - TypeORMRepository, change tracking
- Export - CSV, JSON export with streaming support
DO NOT read all files at once. Load based on context.
如需特定主题的详细文档,请查看:
- 核心概念 - 实体、聚合根、值对象、生命周期钩子
- 领域事件 - 事件驱动架构,含BullMQ使用示例
- Criteria API - 类型安全的查询构建,支持过滤、排序、分页
- Criteria Zod - 用于API查询验证的Zod Schema
- Schema注册中心 - EntitySchemaRegistry字段映射与关系管理
- Prisma适配器 - PrismaRepository、工作单元、事务
- TypeORM适配器 - TypeORMRepository、变更追踪
- 导出功能 - 支持CSV、JSON格式及流式导出
请勿一次性阅读所有文档,请根据实际场景按需查阅。