@shirudo/ddd-kit
v2.0.0
Published
Composable TypeScript toolkit for tactical DDD
Downloads
1,695
Readme
@shirudo/ddd-kit
Composable TypeScript toolkit for tactical Domain-Driven Design. Ships the canonical building blocks (Value Objects, Entities, Aggregate Roots, Domain Events, Repositories, and CQRS handlers) without a framework or runtime lock-in. ESM-only; runs on Node 18+, Cloudflare Workers, Vercel Edge, Deno, and Bun.
Stable: 1.0
The public API is stable and follows Semantic Versioning. Breaking changes bump the major and ship with a migration path in the CHANGELOG.
Features
- Value Objects: deep-frozen, by-attribute equality (
vo,ValueObject,voEquals). - Entities: identity + lifecycle, with collection helpers branded by
Id<Tag>. - Aggregate Roots: state-stored (
AggregateRoot) and event-sourced (EventSourcedAggregate), with optimistic-concurrency versioning. - Domain Events: typed, deeply frozen, carry metadata for traceability and schema evolution.
- Repositories: technology-agnostic persistence ports with an Identity-Map contract and OCC.
- CQRS: zero-config in-memory
CommandBus/QueryBus, plusCommandHandler/QueryHandlertypes for external brokers. - Unit of Work: opt-in
UnitOfWorkfacade with tx-bound repositories, repository-side enrollment, a per-operation Identity Map, and aggregate-level dirty tracking (changedKeys/hasChanges) for partial writes. Honestly speaking: a transaction coordinator with registration and Identity Map; writes stay explicit by design (no auto-flush). - Outbox:
withCommitharvests pending events inside the transaction, stamps them with the aggregate's commit version, and publishes them atomically. - Repository contract tests:
@shirudo/ddd-kit/testingships the suite every adapter must pass: OCC is a testable contract, not a documented pattern. - Result-first boundary: a typed error hierarchy on
@shirudo/base-errorandResultfrom@shirudo/result;voValidatedcollects field violations and renders RFC 9457 via the opt-in@shirudo/ddd-kit/httpentry.
Installation
pnpm add @shirudo/ddd-kit @shirudo/result @shirudo/base-error@shirudo/result and @shirudo/base-error are peer dependencies; install them once in the consuming app.
Quick start
import { vo, type VO } from "@shirudo/ddd-kit";
type EmailAddress = VO<{ value: string }>;
function createEmail(value: string): EmailAddress {
if (!value.includes("@")) throw new Error("Invalid email address");
return vo({ value }); // deeply frozen, immutable
}
const email = createEmail("[email protected]");For a complete walkthrough (a minimal Order aggregate with typed events, commit(), and the App-Service boundary), see Getting Started.
Core concepts
Each building block has a dedicated guide. Start with Design Decisions for the non-obvious calls (Result at the App boundary, no Specification pattern, the TransactionScope/Unit-of-Work layering, class-based aggregates).
| Concept | Guide |
|---|---|
| Value Objects (vo, ValueObject, voWithValidation, voValidated) | Value Objects |
| Entities and identity | Entities |
| Aggregate Roots, factories, reconstitution | Aggregate Roots |
| Event sourcing (apply, replay, snapshots) | Event Sourcing |
| Domain Events (createDomainEvent, metadata) | Domain Events |
| Errors: throw vs Result, ValidationError, RFC 9457 | Result vs Throw |
| Commands, queries, buses | CQRS & Buses |
| Repositories, Identity Map, OCC | Repository |
| Unit of Work, enrollment, contract test suite | Unit of Work |
| Outbox, withCommit, transactions | Outbox & Transactions |
| Read-side projections | Projections |
| Concurrency & operation-scoped aggregates | Concurrency |
| Edge runtimes (Workers, Deno, Bun) | Edge Runtimes |
Documentation
- LLM.md: hand-curated, high-signal guide for LLM coding tools and a fast human skim of the whole surface.
- Common Mistakes: the footgun catalogue; read it before writing consumer code.
- API reference: full type definitions ship with the package (
node_modules/@shirudo/ddd-kit/dist/index.d.ts); the@shirudo/ddd-kit/httpsubpath exports the RFC 9457 presenter. - CHANGELOG: release history with a migration path for every breaking change.
TypeScript support
Requires TypeScript 5.9+. The kit leans on branded, conditional, and mapped types for a type-safe DDD experience; all APIs are fully typed.
Contributing
Contributions are welcome. For bugs and feature requests, use the issue tracker; open a pull request against main.
License
MIT.
