Proven patterns, as classes
Aggregates, value objects, domain events, repositories, command handlers. Your classes extend them, and say what they are.
Domain-Driven Design building blocks and architecture checks for TypeScript, for teams and their agents.
Aggregates, value objects, domain events, repositories, command handlers. Your classes extend them, and say what they are.
alveolus arch check reports code that breaks the architecture, whoever wrote it, and says what is allowed instead.
Bounded contexts, layers, a folder per kind of building block. Anyone opening the code knows where a concept lives.
Contexts meet through an open host service and an anti-corruption layer, never by importing each other's model.
Business failures are returned in a typed Result, never thrown, so every caller sees what can go wrong.
No bus, no container, no ORM, no decorator. Core has no runtime dependency and fits NestJS, Express, Fastify, Hono or plain Node.js.
Deadlines, new teammates, shortcuts taken once and copied ten times: the structure a project started with erodes. Coding agents speed this up. They solve the task in front of them and forget the decisions behind the code around it.
Alveolus turns those decisions into code. The patterns of Domain-Driven Design become classes you extend, a shared layout tells everyone where things go, and a check run in continuous integration reports what breaks them. It works the same for a developer who knows DDD and for an agent that has never heard of it.
export class Order extends AggregateRoot<OrderId, OrderPlaced, OrderSnapshot> {
place(total: number, eventId: string, now: Date): Result<void, InvalidTotal> {
if (total <= 0) {
return err(new InvalidTotal({ total }));
}
this.placedTotal = total;
this.record(new OrderPlaced({ aggregateId: this.id, id: eventId, occurredAt: now, payload: { total } }));
return ok();
}
}$ npx alveolus arch check
src/ordering/domain/aggregates/order.aggregate.ts:1
domain-purity: The domain imports @nestjs/common: add it
to domainDependencies if the domain really needs it.
src/ordering/application/commands/place-order.command.ts:3
layer-direction: The application layer imports
src/ordering/driven/pg/adapters/pg-orders.adapter.ts
(ordering driven): it may only import domain,
application, published-language.
2 violationspnpm add @alveolus/core
pnpm add -D @alveolus/archnpm install @alveolus/core
npm install -D @alveolus/archyarn add @alveolus/core
yarn add -D @alveolus/archbun add @alveolus/core
bun add -d @alveolus/archThen describe your bounded contexts in alveolus.config.ts and run npx alveolus arch check: Getting started walks through it.