zmdbzero-maintenance data layer
Docs Benchmarks Anti-patterns OpenAPI
Docs / Start

IntroductionSupported

zmdb is a TypeScript data layer that eliminates schema-drift maintenance. You declare your table as a type and every derived artifact — entity types, create/update DTOs, runtime validation, JSON serialization, OpenAPI, DDL, and repository CRUD — is produced from that single source of truth, at compile time.

Start with the product quick start, then follow the SQLite HTTP application journey: one @zmdb/core install, one configuration, generated migrations, AOT validation and typed persistence behind an HTTP controller. Granular package choices belong in the advanced package reference.

The core idea#

Other tools make you write your types more than once: a TypeScript type, plus a schema, plus decorators, plus DTOs. Every one of those is a place for drift. zmdb removes the schema object entirely — the interface is the schema, and the build step reads it.

import type { HasDefault, Pattern, PrimaryKey, Serial, Sql, Table } from '@zmdb/core/tags';

export interface User extends Table<'users'> {
  id: number & Sql<'integer'> & Serial & PrimaryKey;
  email: string & Sql<'text'> & Pattern<'^[^@]+@[^@]+\\.[^@]+$'>;
  role: ('admin' | 'user' | 'guest') & HasDefault;
  createdAt: Date & Sql<'timestamp'> & HasDefault;
}

That is the whole declaration. There is no runtime object, no import that survives to the bundle, and nothing to construct — the tags are phantom symbol slots that erase, and role is a plain union because TypeScript already has a way to say "one of these". Where the database needs to know something TypeScript cannot say, like integer versus numeric, a tag says it; everywhere else the type is the answer. See Schema Declaration and the Tag Reference.

What makes it different#

Why fetched rows are inert.

Where to go next#