Quick Start
UQL is type-safe to the leaf with nothing to generate: entities are plain classes, and every query is serializable (portable JSON) that runs unchanged on the server, in the browser, or over the network.

1. Install
Section titled “1. Install”Install the core and your preferred driver:
npm install uql-orm pg # or mysql2, better-sqlite3, mongodb, etc.bun add uql-orm # Bun has native SQL drivers built-in via `bun:sql`, no external drivers requiredpnpm add uql-orm pg # or mysql2, better-sqlite3, mongodb, etc.Requirements
Section titled “Requirements”Node 24+, Bun, Deno, or an edge runtime like Cloudflare Workers, plus TypeScript 5.2 or newer. UQL is
ESM only: there is no require() path, so a CommonJS project cannot consume it.
{ "compilerOptions": { // `nodenext` or `preserve`: the resolver has to read `exports` to find `uql-orm/postgres` "module": "nodenext", // any dated target works (es2022+), never `esnext`: it leaves decorator syntax untransformed "target": "es2025", // `await using` needs `AsyncDisposable`, which no dated target's default lib carries "lib": ["esnext"] }}Behind a bundler, "module": "preserve" (TypeScript 5.4+) or "moduleResolution": "bundler" does the
same job. Next.js needs no changes at all; Vite’s template pins lib to ES2022, so add
esnext there. Node also needs "type": "module" in package.json to run the compiled output, which
Bun, Deno and bundler-driven frameworks do not.
2. Complete Example
Section titled “2. Complete Example”An entity, a pool, and a query:
import { v7 as uuidv7 } from 'uuid';import { Entity, Id, Field } from 'uql-orm';
@Entity()export class User { @Id({ type: 'uuid', onInsert: uuidv7 }) id?: string;
@Field({ type: String, unique: true }) email?: string;
@Field({ type: String }) name?: string;}
// uql.config.tsimport type { Config } from 'uql-orm';import { PgQuerierPool } from 'uql-orm/postgres';import { User } from './entities.js';
const pool = new PgQuerierPool({ host: 'localhost', user: 'postgres', password: 'password', database: 'uql_app',});
export default { pool, entities: [User] } satisfies Config;export { pool };
// app.tsimport { pool } from './uql.config.js';import { User } from './entities.js';
// A single operation goes straight on the pool: it acquires a connection, runs, and releases it.await pool.insertMany(User, [ { email: 'ada@uql-orm.dev', name: 'Ada' }, { email: 'alan@uql-orm.dev', name: 'Alan' }, { email: 'grace@example.com', name: 'Grace' },]);
// Same for reads.const users = await pool.findMany(User, { $select: { id: true, name: true }, $where: { email: { $endsWith: '@uql-orm.dev' } }, $limit: 10,});
console.log(users); // -> Ada and Alan; Grace's email doesn't matchThe User table has to exist before that insert runs; step 3 generates it from the entity class.
Build the pool once per process and import it everywhere; nothing connects until the first query. Which driver, how big, and when to close it are on Pool.
Every operation lives on both the pool and the querier. A pool call is one unit of work on its own connection; pool.withQuerier (or pool.transaction when it must be all-or-nothing) pins one connection across several. See pool vs. querier.
3. Create the tables
Section titled “3. Create the tables”An entity class and a table are two views of one schema, and UQL generates either from the other. You just wrote the entity, so generate the table - on an empty database, one command is enough:
npx uql-migrate syncThat reads the entities in your uql.config.ts, diffs them against the database, and creates what is
missing. Add --dry-run to read the DDL before it runs. Keep sync for development; once the data
matters, generate:entities writes the same diff
to a file you review in the pull request and can roll back.
Starting from tables that already exist runs the other direction:
generate:from-db writes the entity classes for you.
Next Steps
Section titled “Next Steps”- Define Entities: Explore all decorators and type abstractions.
- Define Relations: One-to-one, one-to-many, and many-to-many mappings.
- Querying: Deep selection, filtering, and sorting.
- Transactions: Automatic and manual transaction patterns.
- Migrations: Schema evolution with the CLI and Drift Detection.