pglite-typegen
v0.0.2
Published
Generate TypeScript types from a PGlite database via pg_catalog. Optional Kysely output.
Readme
pglite-typegen
Generates TypeScript types by introspecting a PGlite database through
pg_catalog. Plain interfaces by default; Kysely Generated<> output is
an opt-in flag, not the default.
Why this approach
PGlite is Postgres compiled to WASM, so its pg_catalog is standard
Postgres. There is no SQL parsing and nothing is executed — the tool
opens an existing PGlite data dir and asks the catalog what the schema
actually is. This captures, with zero guessing: enums (as string-literal
unions), domains (resolved to their base type via a recursive CTE),
standalone composite types, array columns, and nullability. However the
schema got into the dir — any migration tool, raw SQL, DO blocks — is
irrelevant, because the catalog reflects the final state regardless.
Usage
# Plain TypeScript interfaces (default)
pglite-typegen ./.pglite --out ./src/db.ts
# Kysely DB interface with Generated<> wrappers
pglite-typegen ./.pglite --out ./src/db.ts --kysely
# Multiple schemas, numeric/bigint as number
pglite-typegen ./.pglite --schemas public,app \
--out ./src/db.ts --numeric-as-numberWith --kysely, columns with a default / identity / generated value are
wrapped in Generated<> (so they're optional on insert) and the file
imports Generated from kysely. Without it, every column is T or
T | null and there is no kysely dependency at all.
The dir must already contain the schema (run your migrations into it beforehand, by whatever means — that's not this tool's job).
Programmatic
import { generate } from "pglite-typegen";
await generate({ dataDir: "./.pglite", outFile: "./src/db.ts" });generate() also accepts { pglite } (any object with .query),
which overrides dataDir and is how the test suite runs without a
real PGlite.
Type mapping notes
int8/numeric→stringby default (avoids 2^53 precision loss).--numeric-as-numberoverrides.json/jsonb→unknown(annotate yourself if you have a shape).- Unknown base types emit
string /* unmapped pg type: <name> */so they surface in review rather than silently becomingany. - Non-
publicschemas: interface name isSchema_TableTable,DBkey is"schema.table".
Tests
bun test — validates the model builder and emitter against synthetic
pg_catalog rows shaped exactly as the introspection queries return them
(enum, domain, composite, array, identity, generated, nullable), covering
both the plain default output and the --kysely opt-in. Bun resolves the
.ts sources directly, so no build step or loader is needed to run it.
