DOMAIN MODELING · BUILT ON TYPEBOX

Model the domain.
Keep the invariants.

Your domain has rules.
Give them a place to live.

A TypeScript framework for properties, entities and use cases. Validate at the boundary. Keep your model consistent. Bring your own infrastructure.

View on GitHub
Open source. MIT licensed. Yours to build with.
user.tsTypeScript
import { blueprintOf, entityOf } from "@afora/core"; class User extends entityOf(  blueprintOf((ctx) => ({    name: ctx.text,    email: ctx.email,    token: ctx.string,  })),  { unique: ["email"], sensitive: ["token"] },) {} const user = new User({  name: "Ada",  email: "  Ada@Example.com  ",  token: "keep-it-private",}); JSON.stringify(user);// email → "ada@example.com"// token → "********"
One definition. Types and runtime, in agreement.
AT HOME IN YOUR STACK
BunNode.js ≥ 22Browsers & WorkersTypeBoxStandard Schema V1
FROM THE INSIDE OUT

Small pieces. A coherent model.

Start with a value. Compose your way
to the behavior of your application.

03 / Record

Holds the value. Rejects undeclared keys at any depth.

class User extends recordOf(UserProps) {}
const user = new User({ name: "Ada", email: "ada@example.com" });
EnvironmentValidated configuration, available where your domain needs it.
RULES THAT TRAVEL WITH YOUR DATA

Make the model do the work.

01 / INVARIANTS
email: ctx.email,
name: ctx.text({ min: 2 }),

Valid by construction

Properties validate and normalize every value. Records reject undeclared keys, even in nested objects.

02 / SENSITIVE DATA
JSON.stringify(account);
// token: "********"

Private stays private

Sensitive properties are masked by toJSON(), at any depth. Serialization respects the rules of your model.

03 / LAYERED EXCEPTIONS
error.layer; // "use-case"
error.trace; // the path to the failure

Errors with a sense of place

Every exception carries its layer and a trace. Follow a failure from the boundary back to the property that caused it.

YOUR DOMAIN, YOUR INFRASTRUCTURE

Define once.
Connect where it matters.

The framework is the code you own and run. Compose commands and outputs, then connect the tools your application needs.