doba

Quick Start

Build your first schema registry with doba in under 5 minutes.

Quick Start

Create a registry that transforms user data between database, frontend, and AI representations.

Define your schemas

Each schema represents a different view of the same data:

schemas.ts
import { z } from 'zod'

const databaseUser = z.object({
  id: z.string(),
  email: z.string(),
  passwordHash: z.string(),
  createdAt: z.string(),
  role: z.enum(['admin', 'user']),
})

const frontendUser = z.object({
  id: z.string(),
  email: z.string(),
  createdAt: z.string(),
  role: z.enum(['admin', 'user']),
})

const aiUser = z.object({
  id: z.string(),
  email: z.string(),
  isAdmin: z.boolean(),
})

Create the registry

Register schemas and define migrations between them:

registry.ts
import { createRegistry } from 'dobajs'

const userRegistry = createRegistry({
  schemas: {
    database: databaseUser,
    frontend: frontendUser,
    ai: aiUser,
  },
  migrations: {
    'database->frontend': (user) => ({
      id: user.id,
      email: user.email,
      createdAt: user.createdAt,
      role: user.role,
      // passwordHash is stripped!
    }),
    'database->ai': (user) => ({
      id: user.id,
      email: user.email,
      isAdmin: user.role === 'admin',
    }),
    'frontend->ai': (user) => ({
      id: user.id,
      email: user.email,
      isAdmin: user.role === 'admin',
    }),
  },
})

This creates the following migration graph:

database
frontend
ai

Transform data

transform.ts
const dbUser = {
  id: 'user-123',
  email: 'alice@example.com',
  passwordHash: 'hashed_xyz',
  createdAt: '2024-01-15T10:30:00Z',
  role: 'admin' as const,
}

const result = await userRegistry.transform(dbUser, 'database', 'frontend')

if (result.ok) {
  console.log(result.value)
  // { id: "user-123", email: "alice@example.com", createdAt: "...", role: "admin" }

  console.log(result.meta.path)
  // ["database", "frontend"]
}
ok: true
value: { id: "user-123", email: "alice@example.com", role: "admin" }
meta: {
path: ["database", "frontend"]
steps: 1
}

Handle errors

doba returns errors as values. No try/catch:

errors.ts
const result = await userRegistry.transform(invalidData, 'database', 'frontend')

if (!result.ok) {
  for (const issue of result.issues) {
    console.log(issue.message)
    // Typed validation errors
  }
}
ok: false
issues:
- Expected string, received number at "id"
- Required at "email"

What's next?

On this page