Licence
MIT
Version
0.30.0
Deps
4
Size
118 kB
Vulns
0
Weekly
0
@vytches/ddd-aggregates
Aggregate root implementation with event sourcing, optimistic concurrency, and opt-in capabilities.
Installation
pnpm add @vytches/ddd-aggregates
What's included
AggregateRoot— base class for aggregate roots with identity, versioning, and domain eventsEntity— base class for non-root domain entities (identity-based equality, no event machinery)AggregateBuilder/aggregateBuilder— fluent builder for constructing aggregates with capabilities- Capabilities —
AuditCapability,EventSourcingCapability,SnapshotCapability,VersioningCapability - Utility functions — type-safe capability casting and introspection
AggregateError— error class for aggregate-specific failures
Usage
import { AggregateRoot } from '@vytches/ddd-aggregates';
import type { IAggregateConstructorParams } from '@vytches/ddd-aggregates';
import { EntityId } from '@vytches/ddd-contracts';
class Order extends AggregateRoot<string> {
private customerId = '';
private status: 'pending' | 'confirmed' = 'pending';
constructor(params: IAggregateConstructorParams<string>) {
super(params);
this.registerEventHandler<{ customerId: string }>(
'OrderCreated',
payload => {
this.customerId = payload!.customerId;
}
);
this.registerEventHandler<void>('OrderConfirmed', () => {
this.status = 'confirmed';
});
}
static create(customerId: string): Order {
const order = new Order({ id: EntityId.create(), version: 0 });
order.apply('OrderCreated', { customerId });
return order;
}
confirm(): void {
if (this.status !== 'pending') throw new Error('Order is not pending');
this.apply('OrderConfirmed', undefined);
}
getCustomerId(): string {
return this.customerId;
}
getStatus(): string {
return this.status;
}
}
// Create an order
const order = Order.create('customer-123');
order.confirm();
// Domain events are collected until committed
const events = order.getDomainEvents(); // [OrderCreated, OrderConfirmed]
order.commit(); // clears collected events
With capabilities
import {
aggregateBuilder,
AuditCapability,
SnapshotCapability,
} from '@vytches/ddd-aggregates';
const order = aggregateBuilder(Order)
.withCapability(AuditCapability)
.withCapability(SnapshotCapability)
.build({ id: EntityId.create(), version: 0 });
Utility functions
import {
asSnapshotAggregate,
tryAsSnapshotAggregate,
hasAllCapabilities,
getAggregateCapabilities,
} from '@vytches/ddd-aggregates';
import { SnapshotCapability, AuditCapability } from '@vytches/ddd-aggregates';
// Type-safe capability access
const snapshotable = asSnapshotAggregate(order); // throws if missing
const maybeSnapshot = tryAsSnapshotAggregate(order); // returns null if missing
// Introspection
const hasAll = hasAllCapabilities(order, [SnapshotCapability, AuditCapability]);
const capabilities = getAggregateCapabilities(order);
Non-root entities
import { Entity } from '@vytches/ddd-aggregates';
import { EntityId } from '@vytches/ddd-contracts';
// Use Entity for inner aggregate objects like OrderLine, Address
class OrderLine extends Entity<string> {
constructor(
id: EntityId<string>,
private sku: string,
private quantity: number
) {
super({ id });
}
getSku(): string {
return this.sku;
}
getQuantity(): number {
return this.quantity;
}
}
API Reference
Core Classes
| Export | Kind | Description |
|---|---|---|
AggregateRoot<TId> |
class | Base aggregate root; provides identity, versioning, event collection and event sourcing reconstitution |
Entity<TId> |
class | Base class for non-root domain entities; identity-based equality, no events |
AggregateBuilder |
class | Fluent builder for aggregates with capabilities |
aggregateBuilder |
function | Factory function shorthand for AggregateBuilder |
AggregateError |
class | Error thrown for aggregate-specific failures |
Capabilities
| Export | Kind | Description |
|---|---|---|
AuditCapability |
class | Records who created/modified the aggregate and when |
EventSourcingCapability |
class | Enables event sourcing reconstitution from stored events |
SnapshotCapability |
class | Enables taking and restoring state snapshots |
VersioningCapability |
class | Manages optimistic concurrency version tracking |
Capability Utilities
| Export | Kind | Description |
|---|---|---|
asSnapshotAggregate(agg) |
function | Cast to snapshot-capable aggregate; throws if missing |
tryAsSnapshotAggregate(agg) |
function | Cast to snapshot-capable aggregate; returns null if missing |
asVersioningAggregate(agg) |
function | Cast to versioning-capable aggregate; throws if missing |
tryAsVersioningAggregate(agg) |
function | Returns null if versioning capability absent |
asAuditAggregate(agg) |
function | Cast to audit-capable aggregate; throws if missing |
tryAsAuditAggregate(agg) |
function | Returns null if audit capability absent |
asEventSourcingAggregate(agg) |
function | Cast to event-sourcing aggregate; throws if missing |
tryAsEventSourcingAggregate(agg) |
function | Returns null if event sourcing capability absent |
getAggregateCapabilities(agg) |
function | Returns all capabilities attached to an aggregate |
hasAllCapabilities(agg, caps) |
function | Returns true if aggregate has all listed capabilities |
Interfaces
| Export | Kind | Description |
|---|---|---|
IAggregateRoot |
interface | Full contract for aggregate roots |
IAggregateCapability |
interface | Base capability contract |
IAggregateConstructorParams<TId> |
interface | Constructor parameter shape for aggregates |
IAggregateEventHandler |
interface | Event handler registration contract |
IAggregateBuilder |
interface | Builder contract |
Utility Types
| Export | Kind | Description |
|---|---|---|
AggregateWithSnapshotCapability |
type | Aggregate narrowed to snapshot-capable shape |
AggregateWithVersioningCapability |
type | Aggregate narrowed to versioning-capable shape |
AggregateWithAuditCapability |
type | Aggregate narrowed to audit-capable shape |
AggregateWithEventSourcingCapability |
type | Aggregate narrowed to event-sourcing shape |
Package boundaries
@vytches/ddd-aggregates depends on:
@vytches/ddd-contracts— base interfaces andEntityId@vytches/ddd-domain-primitives— error types@vytches/ddd-value-objects— enhancedEntityId@vytches/ddd-logging— internal logging
License
MIT