Introduction
Schema registry with flexible transformations. Type-safe migrations between any schemas, errors as values.
Introduction
doba is a TypeScript schema registry that lets you define multiple representations of the same data and transform between them with full type safety.
Standard Schema
doba works with any Standard Schema compliant library: Zod, Valibot, ArkType, and more. No lock-in.
Why doba?
Most applications deal with the same data in multiple shapes:
- Database: full record with sensitive fields
- Frontend: stripped for the client
- AI/LLM: flattened for context windows
- Export: formatted for data portability
- Legacy: old versions that still need support
doba lets you put all these variants in one registry with migrations between them. It finds the shortest path automatically, validates at each step, and returns typed results with metadata.
Key features
Type-safe migrations
Full TypeScript inference. Migrations are type-checked at compile time. Input matches source, output matches target.
Automatic path finding
BFS-powered graph traversal finds the shortest path between any two schemas. No manual chaining.
Errors as values
No try/catch. Every operation returns a discriminated Result type you can check with .ok.
Migration helpers
Type-safe pipe builder for field renaming, mapping, adding, and dropping. No assertions needed.
Fast
~2ns lookups, ~467ns transforms, 2.6M items/sec batch processing. References, not copies.
Quick example
import { createRegistry } from 'dobajs'
import { z } from 'zod'
const registry = createRegistry({
schemas: {
database: z.object({ id: z.string(), email: z.string(), passwordHash: z.string() }),
frontend: z.object({ id: z.string(), email: z.string() }),
},
migrations: {
'database->frontend': (user) => ({ id: user.id, email: user.email }),
},
})import { createRegistry } from 'dobajs'
import * as v from 'valibot'
const registry = createRegistry({
schemas: {
database: v.object({ id: v.string(), email: v.string(), passwordHash: v.string() }),
frontend: v.object({ id: v.string(), email: v.string() }),
},
migrations: {
'database->frontend': (user) => ({ id: user.id, email: user.email }),
},
})import { createRegistry } from 'dobajs'
import { type } from 'arktype'
const registry = createRegistry({
schemas: {
database: type({ id: 'string', email: 'string', passwordHash: 'string' }),
frontend: type({ id: 'string', email: 'string' }),
},
migrations: {
'database->frontend': (user) => ({ id: user.id, email: user.email }),
},
})