Checkout persistence
examples/checkout-persistence — the persistence half: a repository built on @unthrown/prisma, storing and reading the cart from Checkout domain against a real (in-memory) database.
pnpm turbo run test --filter=@unthrown/example-checkout-persistenceA read infers E = never
findCart: (cartId: string): AsyncResult<Cart, CartNotFound> =>
db.cart
.tryFindUnique({ where: { id: cartId }, include: { lines: true } })
.flatMap((row) =>
row === null ? Err(new CartNotFound({ cartId })) : Ok(/* … */),
);tryFindUnique itself is AsyncResult<Row | null, never> — a database that will not answer at all is a Defect, not a domain outcome, so there is no error case to name for the query. Absence is null. CartNotFound is not something Prisma raises; it is something this repository introduces by turning that null into the modeled error findCart promises its caller (matching CheckoutDeps["findCart"] from the domain package). The test pins the distinction:
await expect(repo.findCart("nope")).toBeErrTagged("CartNotFound", {
cartId: "nope",
});A write carries only the P-codes you would branch on
saveOrder: (order: { id: string; total: number; cartId: string }) =>
db.order.tryCreate({ data: order });saveOrder's error channel is exactly UniqueConstraintViolation | ForeignKeyViolation | RecordNotFound — the P-codes a create can actually raise. The schema's Order.cartId @unique makes "one order per cart" a real constraint, so a second saveOrder for the same cart comes back as a modeled Err, not a thrown driver exception:
await expect(repo.saveOrder({ id: "o1", total: 100, cartId: "c1" })).toBeOk();
await expect(
repo.saveOrder({ id: "o2", total: 100, cartId: "c1" }),
).toBeErrTagged("UniqueConstraintViolation");Everything infrastructural — a dropped connection, a pool timeout, a deadlock — is deliberately not in either channel. Nobody writes domain logic for those; they are a Defect, folded once at the edge. See the Prisma guide for the full per-operation error table.
Where to go next
- The modelling half: Checkout domain.
- Serve it: Checkout API.