SkillAgentSearch skills...

Uql

The fastest TypeScript ORM

Install / Use

/learn @rogerpadilla/Uql

README

<!-- ![code](/assets/code.webp 'code') -->

<a href="https://uql-orm.dev"><img src="assets/logo.svg" alt="uql" width="80" /></a>

tests Coverage Status license npm version

UQL is the best ORM for TypeScript and modern JavaScript designed to be fast, safe, and easy to integrate into any application — especially AI and data‑heavy workloads. Built with a unified API across SQL and MongoDB.

const results = await querier.findMany(User, {
  $select: { name: true, profile: { $select: { picture: true } } },
  $where: { name: { $istartsWith: 'a' }, posts: { tags: { name: 'typescript' } } },
  $sort: { createdAt: 'desc' },
  $limit: 10,
});

Quick Start

npm install uql-orm pg
import { PgQuerierPool } from 'uql-orm/postgres';

const pool = new PgQuerierPool({ host: 'localhost', database: 'app' });
const users = await pool.withQuerier((querier) => querier.findMany(User, { $limit: 10 }));

For production setup and migrations, jump to:

Note: For explicit lifecycle control, use manual getQuerier() + release() (shown in Core Query Pattern).

Guide Map

Core path:

Advanced and operations:

Features

| Feature | Why it matters | | :--- | :--- | | Intelligent Querying | Deep auto-completion for operators and relations at any depth—no more guessing property names. | | Serializable JSON | Query objects are valid JSON, which makes them straightforward to transport over HTTP/gRPC/WebSockets. | | Unified Dialects | Write once, run anywhere. Seamlessly switch between PostgreSQL, MySQL, MariaDB, SQLite, and MongoDB. | | Naming Strategies | No more camelCase vs snake_case headaches. Map your code to your database automatically. | | Smart SQL Engine | Zero-allocation SQL generation with top-ranked results in our open benchmark. | | Thread-Safe by Design | Protect your data integrity with centralized task queues and the @Serialized() decorator. | | Declarative Transactions | Clean @Transactional() decorators that work beautifully with modern DI frameworks like NestJS. | | Lifecycle Hooks | Automate validation, timestamps, and computed logic with intuitive class-based decorators. | | Aggregate Queries | Real-time analytics with GROUP BY, HAVING, and native math operators across all dialects. | | Semantic Search | Native vector similarity search. Rank results by meaning using standard ORM operators. | | Cursor Streaming | Process millions of rows with a stable memory footprint using native driver-level cursors. | | Modern & Versatile | Pure ESM, high-res timing, built-in soft-delete, and first-class JSON/JSONB support. | | Database Migrations | Entity-First synchronization. DDL is auto-generated by diffing your code against the live DB. | | Logging & Monitoring | High-visibility debugging with slow-query detection and high-contrast terminal output. | | Fullstack Bridge | Speak to your database from the browser securely. First-party HttpQuerier removes API boilerplate. |

1. Install

Install the core package and the driver for your database:

# Core
npm install uql-orm       # or bun add / pnpm add

Supported Drivers (pick according to your database)

| Database | Command | | :--- | :--- | | PostgreSQL (incl. Neon, Cockroach, Yugabyte) | npm install pg | | MySQL (incl. TiDB, Aurora) | npm install mysql2 | | MariaDB | npm install mariadb | | SQLite | npm install better-sqlite3 | | LibSQL (incl. Turso) | npm install @libsql/client | | MongoDB | npm install mongodb | | Cloudflare D1 | Native (no driver needed) | | Bun SQL Native (Incl. Postgres, MySQL, SQLite) | Native (no driver needed) |

TypeScript Configuration

Ensure your tsconfig.json is configured to support decorators and metadata:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Note: UQL is Modern Pure ESM — ensure your project's module supports ESM imports (e.g., NodeNext, ESNext, Bundler).

2. Define your Entities

Annotate your classes with decorators. UQL's engine uses this metadata for both type-safe querying and precise DDL generation.

Core Decorators

| Decorator | Purpose | | :--- | :--- | | @Entity() | Marks a class as a database table/collection. | | @Id() | Defines the Primary Key with support for onInsert generators. | | @Field() | Standard column. Use { references: ... } for Foreign Keys. | | @Index() | Defines a composite or custom index on one or more columns. | | @OneToOne | Defines a one-to-one relationship. | | @OneToMany | Defines a one-to-many relationship. | | @ManyToOne | Defines a many-to-one relationship. | | @ManyToMany | Defines a many-to-many relationship. | | @BeforeInsert | Lifecycle hooks fired around database operations. | | @AfterLoad | Lifecycle hook fired after loading entities. |

Type Abstraction: Logical vs. Physical

UQL separates the intent of your data from its storage. Both properties are optional; if omitted, UQL performs a best-effort inference using the TypeScript types from your class.

| Property | Purpose | Values | | :--- | :--- | :--- | | type | Logical Type (Abstraction). Used for runtime behavior and automatic SQL mapping. | String, Number, Boolean, Date, BigInt, or semantic strings: 'uuid', 'json', 'vector', 'halfvec', 'sparsevec'. | | columnType | Physical Type (Implementation). Highest Priority. Bypasses UQL's inference for exact SQL control. | Raw SQL types: 'varchar(100)', 'decimal(10,2)', 'smallint', etc. |

// Automatic inference from TypeScript types
@Field() name?: string;           // → TEXT (Postgres), VARCHAR(255) (MySQL)
@Field() age?: number;            // → INTEGER
@Field() isActive?: boolean;      // → BOOLEAN
@Field() createdAt?: Date;        // → TIMESTAMP

// Semantic types - portable across all databases
@Field({ type: 'uuid' })          // → UUID (Postgres), CHAR(36) (MySQL), TEXT (SQLite)
externalId?: string;

@Field({ type: 'json' })          // → JSONB (Postgres), JSON (MySQL), TEXT (SQLite)
metadata?: Json<{ theme?: string }>;

// Logical types with constraints - portable with control
@Field({ type: 'varchar', length: 500 })
bio?: string;

@Field({ type: 'decimal', precision: 10, scale: 2 })
price?: number;

// Exact SQL type - when you need dialect-specific control
@Field({ columnType: 'smallint' })
statusCode?: number;
import { v7 as uuidv7 } from 'uuid';
import { Entity, Id, Field, OneToOne, OneToMany, ManyToOne, ManyToMany, type Relation, type Json } from 'uql-orm';

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

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

  @Field({
    unique: true,
    comment: 'User login email',
  })
  email?: string;

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

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

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

  @Field()
  bio?: string;

  @Field({ references: () => User, foreignKey: 'fk_profile_user' })
  userId?: string;

  @OneToOne({ entity: () => User })
  user?: User;
}

@Entity()
export class Post {
  @Id()
  id?: number;

  @Field()
  title?: string;

  @Field({ references: () => User })
  authorId?: string;

  @ManyToOne({ entity: () => User })
  author?: User;

  @ManyToMany({
    entity: () => Tag,
    through: () => PostTag,
  })
  tags?: Tag[];
}

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

  @Field()
  name?: string;
}

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

  @Field({ references: () => Post })
  postId?: number;

  @Field({ references: () => Tag })
  tagId?: string;
}

Note: Use the Relation<T> utility type for relationship properties. It prevents TypeScript circular dependency errors while maintaining full type-safety throughout your app.

3.

View on GitHub
GitHub Stars102
CategoryData
Updated7h ago
Forks2

Languages

TypeScript

Security Score

100/100

Audited on Mar 26, 2026

No findings