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.
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.
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 → "********"Start with a value. Compose your way
to the behavior of your application.
class User extends recordOf(UserProps) {}
const user = new User({ name: "Ada", email: "ada@example.com" });email: ctx.email,
name: ctx.text({ min: 2 }),Properties validate and normalize every value. Records reject undeclared keys, even in nested objects.
JSON.stringify(account);
// token: "********"Sensitive properties are masked by toJSON(), at any depth. Serialization respects the rules of your model.
error.layer; // "use-case"
error.trace; // the path to the failureEvery exception carries its layer and a trace. Follow a failure from the boundary back to the property that caused it.
The framework is the code you own and run. Compose commands and outputs, then connect the tools your application needs.