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

生态系统

PackagePurpose
@woltz/rich-domain
Core DDD building blocks
@woltz/rich-domain-prisma
Prisma ORM adapter
@woltz/rich-domain-typeorm
TypeORM adapter
@woltz/rich-domain-criteria-zod
Zod schemas for Criteria API
@woltz/rich-domain-export
Multi-format data export
包名称用途
@woltz/rich-domain
核心DDD构建模块
@woltz/rich-domain-prisma
Prisma ORM适配器
@woltz/rich-domain-typeorm
TypeORM适配器
@woltz/rich-domain-criteria-zod
Criteria API的Zod Schema支持
@woltz/rich-domain-export
多格式数据导出

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

核心原则

  1. Aggregates define consistency boundaries - Modify entities through their aggregate root
  2. Value Objects are immutable - Use
    clone()
    to create modified copies
  3. Id tracks new vs existing -
    new Id()
    for INSERT,
    Id.from(value)
    for UPDATE
  4. Change tracking is automatic - Use
    getChanges()
    and
    markAsClean()
  5. Repositories abstract persistence - Domain layer doesn't know about database
  1. 聚合根定义一致性边界 - 通过聚合根修改实体
  2. 值对象不可变 - 使用
    clone()
    创建修改后的副本
  3. Id追踪新/已有状态 - 新建用
    new Id()
    ,更新用
    Id.from(value)
  4. 变更追踪自动化 - 使用
    getChanges()
    markAsClean()
  5. 仓库抽象持久化 - 领域层无需感知数据库细节

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格式及流式导出
请勿一次性阅读所有文档,请根据实际场景按需查阅。

Resources

相关资源