MongrelDB Kit

July 15, 2026 ยท View on GitHub

@visorcraft/mongreldb-kit is the application persistence layer for MongrelDB. MongrelDB is a fast storage engine with typed tables, snapshots, transactions, and SQL reads; the Kit adds the relational application layer on top:

  • a schema DSL with typed rows, inserts, and updates,
  • a synchronous query builder (CRUD, batch inserts, predicates, ordering, projections, aggregates, joins, group/having, subqueries, CTEs),
  • a migration runner with content-addressed checksums,
  • engine-side triggers and SQL-backed virtual/external table helpers,
  • Extended SQL Function helpers for date/time, JSON, aggregate, and math-style SQL calls,
  • relational constraints the engine does not enforce natively - not-null, checks, unique and composite-unique, foreign keys, and cascade / set-null / restrict deletes,
  • auto-increment ids, defaults, table rename support, and a stable error taxonomy.

The same semantics are available from TypeScript, Rust, and Python, backed by a shared Rust core and validated by a cross-language conformance suite.

The Kit deliberately does not expose MongrelDB's internal storage RowId as your primary key. Your application ids live in your own columns and are assigned by the Kit's sequences, so they stay stable and portable.

Install

npm install @visorcraft/mongreldb-kit @visorcraft/mongreldb

@visorcraft/mongreldb (the native engine binding) is a peer dependency. Node 22+ is required. In local development, build the sibling engine addon in release mode before benchmarking TypeScript paths. See the TypeScript guide for build/runtime details, and the Rust and Python guides for those ecosystems.

Quickstart

Define a schema, open a database directory, run migrations, and use typed CRUD:

import {
  Schema, table, int, text, timestamp,
  sequenceDefault, nowDefault, staticDefault, unique,
  KitDatabase, eq, desc,
} from '@visorcraft/mongreldb-kit';

const customers = table('customers', {
  columns: [
    int('id', { primaryKey: true, default: sequenceDefault('customers_id_seq') }),
    text('email', { nullable: false }),
    text('name', { nullable: false }),
    text('tier', { enumValues: ['free', 'pro'], default: staticDefault('free') }),
    timestamp('created_at', { default: nowDefault() }),
  ],
  primaryKey: 'id',
  unique: [unique(['email'])],
});

const schema = new Schema([customers]);
const migrations = [{ version: 1, name: 'init', up: () => {} }];

// A MongrelDB data *directory* (created if missing) - not a single file.
const db = KitDatabase.openSync('./data', schema);
db.migrateSync(schema, migrations);

// Insert: omit `id` and the sequence assigns a 1-based id; `tier`/`created_at` use defaults.
const ada = db.insertInto(customers).values({ email: 'ada@example.com', name: 'Ada' }).executeSync();
console.log(ada.id);   // 1n  (bigint - int64 columns are bigint in TS)
console.log(ada.tier); // 'free'

// Read back, newest first.
const recent = db.selectFrom(customers).orderBy(desc(customers.created_at)).limit(10).executeSync();

// Unique violation throws a typed error.
try {
  db.insertInto(customers).values({ email: 'ada@example.com', name: 'Ada II' }).executeSync();
} catch (err) {
  // err instanceof KitDuplicateError
}

db.close();

Everything above - schema, defaults, the 1-based id, the unique constraint, typed rows - is explained in depth in the topic guides below.

Documentation map

Start here, then dive into the topic that fits your task.

GuideWhat it covers
Schema DSLTables, columns, types, column options, indexes, and assembling a Schema.
TypesRow<T>, Insert<T>, Update<T> inference and typed CRUD.
Defaults & sequencesStatic / now / uuid / sequence / custom defaults and auto-increment ids.
Query builderSelect, insert (single and batch), update, delete, predicates, ordering, pagination, projections, aggregates, distinct, joins, group/having, subqueries, exists, CTEs, and the raw escape hatch.
ConstraintsNot-null, checks, unique / composite-unique, foreign keys, and delete actions (cascade / set-null / restrict).
Transactionsbegin/commit/rollback, the retrying transaction() helper, conflicts, and the concurrency model.
SQL cancellation and timeoutsEmbedded and remote query handles, deadlines, transport timeouts, transaction safety, capability negotiation, and CLI cancellation.
MigrationsMigration files, the runner, checksums, supported operations, idempotent column adds, table renames, and SQL views.
Stored proceduresDeclarative routines callable from embedded, remote, and CLI Kit clients.
TriggersEngine-side declarative triggers, migration helpers, remote APIs, and trigger validation errors.
Extended SQL & virtual tablesSQL function helpers, db.sqlRows, and virtual/external table module specs.
Users, roles & permissionsCatalog-stored users (Argon2id), roles, GRANT/REVOKE, and HTTP Basic + Bearer daemon auth, plus credential enforcement - require_auth, credentialed open/create, and disable_auth recovery. Documented in each language guide and the CLI user/role commands; the full model lives in the engine auth guide and the credential enforcement guide.
ErrorsThe error taxonomy, codes, and how to handle each category.
Internal tablesThe reserved __kit_* tables and what each one stores.
CLIThe mongreldb-kit command line: check, diff, generate, migrate, and more.
TestingTemp-directory fixtures and patterns for fast, isolated tests.
Production checklistWhat to verify before shipping.

Language guides

GuidePackage
TypeScript@visorcraft/mongreldb-kit
Rustmongreldb-kit
Pythonmongreldb-kit (import mongreldb_kit)

A note on examples

All examples use a generic "store" domain - customers, products, orders, and order_items - so the relationships (a customer has orders, an order has items, items reference products) exercise foreign keys, cascade deletes, joins, and aggregates. The full schema appears in Schema DSL and is reused throughout.