Skip to content

rogerpadilla/uql

Repository files navigation

uql

tests Coverage Status license npm version

UQL is the perfectionist ORM: serializable queries, no codegen, and one API across PostgreSQL, MySQL, SQLite, MariaDB, and MongoDB. Define entities once, query everywhere.

await querier.findMany(User, {
  $select: { id: true, email: true },
  $where: { email: { $endsWith: '@uql-orm.dev' } },
  $limit: 10,
});

Full docs: uql-orm.dev


Why UQL?

  • Queries are data, not method chains. A UQL query is a plain JSON object. Build them dynamically, store them, or send them from client to server without a DSL.
  • No codegen, no build step. Entities are TypeScript classes, so your code is the schema. No .prisma files or generated clients to keep in sync.
  • One API everywhere. The same syntax runs on PostgreSQL, MySQL, MariaDB, SQLite, LibSQL, Neon, Cloudflare D1, MongoDB, and Bun's native SQL.
  • Fast by design. Fastest in all 8 categories of our open benchmark: on average ~2.1× faster than the runner-up, reaching over 3.9M ops/s on SELECTs.

Features

Feature Docs
Unified API across SQL + MongoDB Install
Type-safe queries with autocomplete Querying
Entity-first migrations & autoSync Migrations
Soft-delete, lifecycle hooks, relations Entities
Query filters, multi-tenancy & row-level security Filters · Multi-tenancy
Aggregate queries, grouping, HAVING Aggregate
Batch inserts with reliable IDs on every database Insert IDs
Semantic search & vector similarity Semantic Search
Parallel reads & raw SQL on the pool Parallel reads · Raw SQL
Streaming, transactions Streaming · Transactions
REST API from your entities (any framework) HTTP
Typed browser client, NestJS module Browser · NestJS

Install

npm install uql-orm pg   # or mysql2, mariadb, better-sqlite3, mongodb, @libsql/client

Supports PostgreSQL, MySQL, MariaDB, SQLite, CockroachDB, LibSQL/Turso, Neon, MongoDB, Cloudflare D1, and Bun SQL.

Define Entities

Declare your classes with decorators. UQL uses this metadata for type-safe querying and DDL generation.

import { v7 as uuidv7 } from 'uuid';
import { Entity, Id, Field, OneToOne, OneToMany, type Relation } from 'uql-orm';

@Entity()
export class User {
  @Id({ type: 'uuid', onInsert: () => uuidv7() })
  id?: string;

  @Field({ index: true, unique: true })
  email?: string;

  @OneToOne({ entity: () => Profile, mappedBy: (p) => p.user, cascade: true })
  profile?: Relation<Profile>;

  @OneToMany({ entity: () => Post, mappedBy: (p) => p.author })
  posts?: Relation<Post>[];
}

Imperative API: defineEntity(User, { fields: { id: { type: 'uuid', isId: true } }, ... }). No decorators needed. See Imperative Definition.

Querying

await querier.findMany(User, {
  $select: { id: true, name: true },
  $where: { email: { $endsWith: '@uql-orm.dev' } },
  $limit: 10,
});

25+ comparison operators ($eq, $in, $between, $like, $elemMatch), logical operators ($and, $or, $not, $nor), and type-safe JSON/JSONB dot-notation queries.

Independent reads run directly on the pool - each call gets its own connection, so Promise.all fans out in parallel:

const [users, total] = await Promise.all([
  pool.findMany(User, { $where: { status: 'active' } }),
  pool.count(User, {}),
]);

Querying · Parallel reads · Operators · JSON

Transactions

Functional pool.transaction() or @Transactional() decorator with centralized serialization:

const userId = await pool.transaction(async (q) => {
  const id = await q.insertOne(User, { email: 'a@b.com' });
  await q.insertOne(Profile, { userId: id, bio: '...' });
  return id;
});

Migrations

Entity-first migrations: modify TypeScript classes, UQL auto-generates DDL by diffing code against the live database:

npx uql-migrate generate:entities add_user_nickname   # generate from entities
npx uql-migrate up                                      # apply
npx uql-migrate drift:check                             # detect drift

Safe autoSync() mode adds new tables/columns and blocks destructive changes in development.

Migrations


Made with UQL

AI meeting recorder and video summarizer for Zoom, Meet, Teams, and more. Generates instant summaries with action items in 45+ languages.

Made with UQL

Sponsor this project

  •  

Packages

 
 
 

Contributors

Languages