Domain
The @contract-kit/domain package provides small helpers for domain-driven design: entities, value objects, and domain events.
bun add @contract-kit/domain
Value objects
Immutable, validated types that represent a concept with no identity (e.g. an email address, a currency amount):
import { valueObject } from "@contract-kit/domain";
import { z } from "zod";
const Email = valueObject("Email")
.schema(z.string().email())
.brand();
const email = Email.create("user@example.com"); // branded string
Email.isValid("not-an-email"); // false
Entities
Domain objects with identity and behavior. Entities are immutable — methods return new instances:
import { entity } from "@contract-kit/domain";
import { z } from "zod";
const Todo = entity("Todo")
.props(z.object({
id: z.string(),
title: z.string(),
completed: z.boolean(),
}))
.methods((self) => ({
complete: () => self.with({ completed: true }),
rename: (title: string) => self.with({ title }),
}))
.build();
const todo = Todo.create({ id: "1", title: "Buy milk", completed: false });
const done = todo.complete(); // new instance with completed: true
Every entity gets a .with() method for partial updates, returning a new instance.
Domain events
Typed event declarations for use with the application package:
import { domainEvent } from "@contract-kit/domain";
import { z } from "zod";
const todoCreated = domainEvent(
"todo.created",
z.object({ id: z.string(), title: z.string() }),
);
const todoCompleted = domainEvent(
"todo.completed",
z.object({ id: z.string() }),
);
Domain events are declarations — they describe the shape of something that happened. Use cases declare which events they emit via .emits(), and an event bus port delivers them to subscribers.
const createTodo = define
.command("createTodo")
.input(z.object({ title: z.string() }))
.output(z.object({ id: z.string(), title: z.string() }))
.emits([todoCreated])
.run(async ({ input, ctx }) => {
const todo = await ctx.ports.db.todos.create(input);
await ctx.ports.eventBus.publish(todoCreated, {
id: todo.id,
title: todo.title,
});
return todo;
});
Schema libraries
All three helpers work with any Standard Schema library — Zod, Valibot, ArkType, etc.