stable

Schema

The always-on typing scaffold: attach any Standard Schema v1 validator to a collection. Input is validated before encryption, output after decryption.

Always-on. Lightweight typing scaffold. Source of truth: packages/hub/src/kernel/schema.ts

noy-db stores typed records in collections inside an encrypted vault. Schema is the always-on core feature that keeps those records well-shaped: attach any Standard Schema v1 validator (Zod, Valibot, ArkType, Effect Schema, …) to a collection via collection(name, { schema }). Input is validated on put() before encryption; output is validated after decryption on read.

For typed relationships between collections — foreign keys, integrity, joins — see Foreign refs.

Schema validation

Pass a Standard Schema validator when creating the collection:

import { z } from 'zod'
import { createNoydb } from '@noy-db/hub'

const InvoiceSchema = z.object({
  id:     z.string(),
  amount: z.number().positive(),
  status: z.enum(['draft', 'open', 'paid', 'overdue']),
  date:   z.string().datetime(),
})

const db = await createNoydb({ user: 'alice', secret: '…' })
const vault = await db.openVault('acme')

const invoices = vault.collection<z.infer<typeof InvoiceSchema>>('invoices', {
  schema: InvoiceSchema,
})

await invoices.put('inv-1', { id: 'inv-1', amount: 120, status: 'open', date: '2026-07-01T00:00:00Z' })
// → stored (encrypted) — the validated value is what gets persisted

await invoices.put('inv-2', { id: 'inv-2', amount: -5, status: 'open', date: '2026-07-01T00:00:00Z' })
// → throws SchemaValidationError: "Schema validation failed on put(inv-2): amount: …"
  • Input validation runs in put() before encryption. A rejected record throws SchemaValidationError with direction: 'input' and the validator's full structured issues list — useful for rendering field-level messages in a UI.
  • Output validation runs on records coming out of get() / list() / query() after decryption. If stored data has drifted from the current schema, it throws with direction: 'output' instead of silently returning garbage.
  • Validators may transform the input (coerce strings to numbers, strip unknown fields); the transformed value is what gets encrypted and stored.

The T parameter on Collection<T> is the validator's output type — whatever it produces after coercion and transforms. The InferOutput<typeof schema> helper type (exported from @noy-db/hub) derives it from a schema instance.

Edge cases

  • Schema validation is opt-in per collection; a vault can mix validated and unvalidated collections.
  • When a collection also declares i18nText fields (see i18n), the schema validates first; the i18n required-translation check runs after it, on the schema-validated record.

See also