Get started

Why OKModel

What one schema gives you, what it will not do, and the plain facts that back it.

You describe each table once, in one schema() call, and get typed queries and reviewed migration SQL from it. Calls that would read a whole table or change every row by accident are refused: a bare find() is refused until you set limits in connect, and an update or delete with no where is refused unless you call .all(reason). Tenancy, keeping each customer's rows apart in one database, is declared on the schema too. The package has no runtime dependencies.

What you get

You getWhere it is shown
One schema for types, queries, and migrationsHow it works, First schema
Typed calls on each table (find, one, insert, …)Queries
Reviewed migration SQL generated from the schema, and okm check to report drift, a live database that no longer matches the schemaFirst migration, Drift
A bare find() refused until you pass limit or .all(reason), or set limits in connectQuery limits
An update or delete with no where refused unless you call .all(reason)First schema
Tenant isolation declared on the schemaTenant isolation
No runtime dependencies; each driver is an optional peerInstallation

With no limits in connect, this read is refused before any SQL is sent:

find-needs-limit.ts
import { connect } from "okmodel/pg/postgresjs";
import { schema, table, t } from "okmodel/pg";

const notes = table("notes", {
  id: t.identity().primaryKey(),
  title: t.text(),
});
const app = schema({ tables: [notes] });

export async function read(url: string) {
  await using db = connect(url, { schema: app });
  // Without limits on connect, this throws OKM1101.
  await db.notes.find({ where: { id: "1" } });
}
find-needs-limit.err
OkmError: find() needs a limit.

What it will not do

It will notWhy, and what you do instead
Support a database other than PostgreSQLThe schema and the runtime use PostgreSQL features directly, such as row-level security, distinct on, and transaction settings, and every release is tested on PostgreSQL 15 to 18. A dialect, the SQL one database speaks, is written only for PostgreSQL. (Compatibility)
Run on DenoThe test suites run on Node.js and Bun only, so no claim is made for Deno. Use Node.js 22.18+ or Bun 1.4+. (Installation)
Set a default read limit by itselfWithout limits, a find with no limit is refused. Pass limits to connect to choose the defaults. (Query limits)
Ship a driver inside the packageThe package has no runtime dependencies, so installing it adds nothing besides the driver you choose. Install the peer your runtime already uses. (Drivers)

Plain facts

FactDetail
PostgreSQLMajors 15, 16, 17, and 18 (Minimum Postgres)
RuntimesNode.js 22.18 or newer; Bun 1.4 or newer (CLI, Drivers)
Drivers in the conformance tablepostgres.js, node-postgres, Bun.sql, and PGlite (Compatibility)
NeonSupported as okmodel/pg/neon; not a column in that table (Drivers)
DenoUnsupported (Installation)

The conformance table lists the drivers that pass the shared driver test suites: the same queries, errors, and transactions checked against each driver. okm driver test <driver> runs those suites (driver test).