Errors
unthrown
unthrownExplicit errors as values — with a separate defect channel for the unexpected. Only a true defect ever throws, and only at unwrap.
- Errors as values, typed in E
- A separate defect channel
- Zero runtime dependencies
An expressive, robust TypeScript backend.
A small stack of type-safe building blocks for Node, built on two convictions: a signature should be enough to understand a system, and the fastest error is the best one. Declare the contract once — types, validation and feedback flow everywhere.
Errors, domain, wiring, messaging and workflows — five focused packages that compose into one coherent backend.
Errors
unthrownExplicit errors as values — with a separate defect channel for the unexpected. Only a true defect ever throws, and only at unwrap.
Domain
@btravstack/entityDomain entities declared once. One field map gives you a type, four request/response schemas, behaviour, and a class that is itself a zod schema — so entities nest inside each other without losing what makes them entities.
Wiring
@btravstack/diA module-based container. Ports are the vocabulary your application defines, providers bind them at one edge, and modules declare what they import and export — so internals stay private in a graph that is one flat map at runtime.
Messaging
@amqp-contract/contractType-safe contracts for AMQP & RabbitMQ. Define your exchanges, queues and messages once — get types and runtime validation on both ends.
Workflows
@temporal-contract/contractType-safe contracts for Temporal.io. End-to-end types and automatic validation across workflows, activities and clients.
Each package is small, focused and does one thing well — but they share a worldview: expressive code you can understand from its signature alone, and robust code that fails fast enough to learn from.
A contract or a function signature should be enough to understand a system. Declare the interface once and read everything from it — no digging into implementations.
The sooner the error, the better the code. Anticipated failures are values in the type, malformed data stops at the boundary, missing wiring is a compile error.
Contracts pin down how the pieces fit — publisher and consumer, workflow and client, module and dependency can't drift apart while implementations change underneath.
None of this was invented for AI — AI just raised the stakes. When an agent writes the code, expressiveness and fail-fast stop being a matter of taste and become infrastructure.
An agent is only as good as the signal it gets back. Fail-fast code turns a wrong guess into a precise error in seconds — and fast errors are what make iteration converge.
Typechecking has no opinions. The contract holds or it doesn't — a reproducible, binary measure of generated code, before a single test runs.
Expressive contracts carry the intent. You review interfaces while the AI churns through implementations — the types guarantee the whole still fits together.
BtravStack borrows its instincts from the libraries that made TypeScript feel this way in the first place.
Star the projects, open an issue, or just read the docs. Everything is MIT-licensed and built in the open.
View on GitHub