Codegen + migrate CLI
vb-types, vb-flags, vb-migrate — generate typed schemas + sync collections across environments.
The SDK ships three CLIs:
| CLI | What it does |
|---|---|
vb-types | Pull the live admin’s collection schema → emit Schema for typed Vaultbase usage |
vb-flags | Pull the live admin’s flag definitions → emit a typed-keys module |
vb-migrate | Sync collection schemas across environments (dev → staging → prod) |
All three take --url <baseUrl> and --admin-token <admin-jwt>; vb-types and
vb-migrate can read a snapshot file with --schema <file> instead.
vb-types — Schema codegen
Section titled “vb-types — Schema codegen”bunx vb-types \ --url https://admin.example.com \ --admin-token $ADMIN_TOKEN \ --out src/vaultbase.gen.tsOutput:
// AUTO-GENERATED by `vb-types`. Do not edit.// Regenerate via: vb-types --url https://admin.example.com --admin-token $ADMIN_TOKEN --out src/vaultbase.gen.ts
export interface PostsRecord { id: string; created: number; updated: number; title: string; body?: string | null; author: string; // relation → users published_at?: number | null;}
export interface PostsCreate { title: string; body?: string | null; author: string; published_at?: string | number | null;}
export type PostsUpdate = Partial<PostsCreate>;
export interface UsersRecord { id: string; created: number; updated: number; email: string; email_verified: number; totp_enabled: number; is_anonymous: number; name?: string | null;}
export type Schema = { posts: { record: PostsRecord; create: PostsCreate; update: PostsUpdate }; users: { record: UsersRecord; create: UsersCreate; update: UsersUpdate }; // …};Each collection gets <Name>Record, <Name>Create and <Name>Update, named
after the collection in PascalCase. The header repeats the command that made the
file, with the admin token shown as $ADMIN_TOKEN.
An auth collection’s record carries the fields the server returns for a user:
email, and email_verified, totp_enabled and is_anonymous as numbers
(0 or 1). Its Create type takes email and password. (SDK 0.7.3; earlier
releases typed a verified: boolean the server never sends.)
Field types:
| Field | Read | Write |
|---|---|---|
text, email, url, editor, relation, color | string | string |
number | number | number |
bool | boolean | boolean |
date | number (Unix seconds) | string | number (ISO string or Unix seconds) |
autodate | number | not writable |
vector | number[] | number[] |
geoPoint | { lat: number; lng: number } | same |
select | its values as a union (an array when multiple) | same |
file | string (string[] when multiple) | same |
json | unknown | unknown |
A field that isn’t required is optional and T | null: the server returns an
unset field as null, and writing null clears it.
Use it:
import { Vaultbase } from "@vaultbase/sdk";import type { Schema } from "./vaultbase.gen";
const vb = new Vaultbase<Schema>({ baseUrl: "..." });
await vb.collection("posts").create({ title: "hi", // ✓ fakeField: 1, // ✗ TS error});
const list = await vb.collection("posts").list();list.data[0]?.title; // ← string, inferredA singleton collection’s entry carries singleton: true (SDK 0.7.0), which is
what vb.singleton() accepts:
settings: { record: SettingsRecord; create: never; update: SettingsUpdate; singleton: true };Its record’s fields are all optional and T | null, required or not, since the
record starts empty.
const s = await vb.singleton("settings").get(); // typed as SettingsRecordRe-run the CLI after every schema change. Wire it into your build:
{ "scripts": { "codegen:vb": "vb-types --url $VB_URL --admin-token $VB_TOKEN --out src/vaultbase.gen.ts", "build": "bun codegen:vb && bun build src/index.ts" }}vb-flags — typed flag keys
Section titled “vb-flags — typed flag keys”bunx vb-flags \ --url https://admin.example.com \ --admin-token $ADMIN_TOKEN \ --out src/flags.gen.tsGenerates a TS module that augments @vaultbase/sdk so flag reads are
typed by key + variation:
import "./flags.gen";
vb.flags.isEnabled("new-checkout"); // ✓vb.flags.getString("homepage-variant", "A"); // ↑ "A" | "B" | "C" inferredvb.flags.isEnabled("typo"); // ✗ TS errorSee Feature flags for usage.
vb-migrate — schema sync
Section titled “vb-migrate — schema sync”Move schema (collections + fields + rules) between environments without hand-editing JSON.
# 1. Pull a snapshot from prodbunx vb-migrate pull \ --url https://prod.example.com \ --admin-token $PROD_TOKEN \ --out prod-snapshot.json
# 2. Diff against staging — what would change?bunx vb-migrate diff \ --url https://staging.example.com \ --admin-token $STAGING_TOKEN \ --schema prod-snapshot.json# → collections to create (+), to update (~), and only on staging (-)
# 3. Apply (additive: only creates missing collections and fields)bunx vb-migrate apply \ --url https://staging.example.com \ --admin-token $STAGING_TOKEN \ --schema prod-snapshot.json \ --mode additive --yes
# 4. Or sync: also updates existing collections to match. Nothing is deleted;# collections only on staging are listed with "-" and left alone.bunx vb-migrate apply --mode sync --yes --schema prod-snapshot.json --url ...Programmatic API
Section titled “Programmatic API”The same operations are available as functions:
import { pullSnapshot, diffSnapshot, applySnapshot,} from "@vaultbase/sdk/migrate";
const snap = await pullSnapshot({ url: "https://prod.example.com", adminToken: process.env.PROD_TOKEN!,});
const diff = await diffSnapshot(snap, { url: "https://staging.example.com", adminToken: process.env.STAGING_TOKEN!,});
// diff has an entry per collection, "unchanged" ones includedif (diff.some((d) => d.kind !== "unchanged")) { await applySnapshot(snap, { url: "https://staging.example.com", adminToken: process.env.STAGING_TOKEN!, mode: "additive", });}Use this in CI to fail builds when staging drifts from prod.
Snapshot file shape
Section titled “Snapshot file shape”prod-snapshot.json:
{ "version": 1, "generated_at": "2026-10-19T18:08:33.510Z", "collections": [ { "name": "posts", "type": "base", "fields": [ … ], "list_rule": null, "view_rule": "@request.auth.id != ''", "create_rule": "", "update_rule": "owner = @request.auth.id", "delete_rule": "owner = @request.auth.id" }, … ]}Versioned on disk so future SDK upgrades can read older snapshots.
Pulled snapshots carry all five rules; null is public. A rule left out of a
hand-written snapshot is admin-only ("") when it creates a collection, and
left as it is when sync applies it to an existing one. See
Schema migrations.
CI recipe
Section titled “CI recipe”- name: Pull prod snapshot run: bunx vb-migrate pull --url $PROD_URL --admin-token $PROD_TOKEN --out snap.json
- name: Verify staging matches prod run: | DIFF=$(bunx vb-migrate diff --schema snap.json --url $STAGING_URL --admin-token $STAGING_TOKEN) echo "$DIFF" # Drift = anything to create or update, or a collection only on staging. if echo "$DIFF" | grep -qE '^ [+~-] '; then echo "Staging drift detected" exit 1 fi