uql-orm 0.5.3 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +77 -58
- package/dist/browser/uql-browser.min.js.map +1 -1
- package/dist/dialect/abstractSqlDialect.d.ts +13 -8
- package/dist/dialect/abstractSqlDialect.d.ts.map +1 -1
- package/dist/dialect/abstractSqlDialect.js +40 -21
- package/dist/dialect/abstractSqlDialect.js.map +1 -1
- package/dist/dialect/index.d.ts +1 -0
- package/dist/dialect/index.d.ts.map +1 -1
- package/dist/dialect/index.js +1 -0
- package/dist/dialect/index.js.map +1 -1
- package/dist/dialect/jsonArrayElemMatchUtils.d.ts +10 -0
- package/dist/dialect/jsonArrayElemMatchUtils.d.ts.map +1 -0
- package/dist/dialect/jsonArrayElemMatchUtils.js +24 -0
- package/dist/dialect/jsonArrayElemMatchUtils.js.map +1 -0
- package/dist/dialect/mysqlLikeSqlDialect.d.ts +26 -0
- package/dist/dialect/mysqlLikeSqlDialect.d.ts.map +1 -0
- package/dist/dialect/mysqlLikeSqlDialect.js +94 -0
- package/dist/dialect/mysqlLikeSqlDialect.js.map +1 -0
- package/dist/maria/mariaDialect.d.ts +3 -4
- package/dist/maria/mariaDialect.d.ts.map +1 -1
- package/dist/maria/mariaDialect.js +11 -13
- package/dist/maria/mariaDialect.js.map +1 -1
- package/dist/mysql/mysqlDialect.d.ts +3 -16
- package/dist/mysql/mysqlDialect.d.ts.map +1 -1
- package/dist/mysql/mysqlDialect.js +2 -93
- package/dist/mysql/mysqlDialect.js.map +1 -1
- package/dist/postgres/postgresDialect.d.ts +2 -2
- package/dist/postgres/postgresDialect.d.ts.map +1 -1
- package/dist/postgres/postgresDialect.js +10 -1
- package/dist/postgres/postgresDialect.js.map +1 -1
- package/dist/sqlite/sqliteDialect.d.ts +3 -13
- package/dist/sqlite/sqliteDialect.d.ts.map +1 -1
- package/dist/sqlite/sqliteDialect.js +25 -20
- package/dist/sqlite/sqliteDialect.js.map +1 -1
- package/dist/type/entity.d.ts +18 -8
- package/dist/type/entity.d.ts.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file. Please add
|
|
|
4
4
|
|
|
5
5
|
date format is [yyyy-mm-dd]
|
|
6
6
|
|
|
7
|
+
## [0.6.0] - 2026-03-18
|
|
8
|
+
### Features
|
|
9
|
+
- **JSON update operators expanded**: Added `$push` for atomic JSON array append in update payloads across SQL dialects.
|
|
10
|
+
- **Unified JSON update API type**: Introduced `JsonUpdateOp` with type-safe `$merge`, `$unset`, and `$push` support for `Json<T>` fields.
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
- **MariaDB JSON dot-notation correctness**: Fixed JSON path extraction for MariaDB by using `JSON_VALUE(...)` instead of MySQL-style `->` / `->>` operators.
|
|
14
|
+
- **PostgreSQL operator chaining semantics**: Fixed `$merge + $push` evaluation when targeting the same key so `$push` reads from the current intermediate expression (not stale column state).
|
|
15
|
+
|
|
16
|
+
### Testing
|
|
17
|
+
- Added multi-dialect regression tests for JSON update chaining (`$merge`, `$push`, `$unset`), including same-key `$merge + $push` behavior.
|
|
18
|
+
- Added MariaDB-specific regression tests for dot-notation filtering/sorting SQL generation (`JSON_VALUE` paths).
|
|
19
|
+
|
|
7
20
|
## [0.5.2] - 2026-03-17
|
|
8
21
|
### Testing
|
|
9
22
|
- **Suite reliability**: Ensured the full test suite runs without runtime errors across all dialects with coverage thresholds still met (>97% statements, >90% branches).
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://github.com/rogerpadilla/uql) [](https://coveralls.io/github/rogerpadilla/uql?branch=main) [](https://github.com/rogerpadilla/uql/blob/main/LICENSE) [](https://www.npmjs.com/package/uql-orm)
|
|
6
6
|
|
|
7
|
-
**[UQL](https://uql-orm.dev)** is a
|
|
7
|
+
**[UQL](https://uql-orm.dev)** is a TypeScript ORM focused on portability, performance, and a consistent query model across SQL and MongoDB. In our open benchmark, SQL generation reaches [**3.9M+ ops/s**](https://github.com/rogerpadilla/ts-orm-benchmark). UQL is designed for teams that want type safety and dialect portability without introducing a proprietary query DSL.
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
10
|
const results = await querier.findMany(User, {
|
|
@@ -15,30 +15,62 @@ const results = await querier.findMany(User, {
|
|
|
15
15
|
});
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
npm install uql-orm pg
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { PgQuerierPool } from 'uql-orm/postgres';
|
|
26
|
+
|
|
27
|
+
const pool = new PgQuerierPool({ host: 'localhost', database: 'app' });
|
|
28
|
+
const users = await pool.withQuerier((querier) => querier.findMany(User, { $limit: 10 }));
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
For production setup and migrations, jump to:
|
|
32
|
+
- [Install](#1-install)
|
|
33
|
+
- [Define your Entities](#2-define-your-entities)
|
|
34
|
+
- [Migrations & Synchronization](#5-migrations--synchronization)
|
|
35
|
+
|
|
36
|
+
> **Note:** For explicit lifecycle control, use manual `getQuerier()` + `release()` (shown in [Core Query Pattern](#core-query-pattern)).
|
|
37
|
+
|
|
38
|
+
## Guide Map
|
|
39
|
+
|
|
40
|
+
Core path:
|
|
41
|
+
- [1. Install](#1-install)
|
|
42
|
+
- [2. Define your Entities](#2-define-your-entities)
|
|
43
|
+
- [3. Set up a pool](#3-set-up-a-pool)
|
|
44
|
+
- [4. Manipulate the Data](#4-manipulate-the-data)
|
|
45
|
+
- [5. Migrations & Synchronization](#5-migrations--synchronization)
|
|
46
|
+
|
|
47
|
+
Advanced and operations:
|
|
48
|
+
- [Semantic Search](#modern-indexing-semantic-search)
|
|
49
|
+
- [JSON Operators & Relation Filtering](#json-operators--relation-filtering)
|
|
50
|
+
- [Thread-Safe Transactions](#thread-safe-transactions)
|
|
51
|
+
- [6. Logging & Monitoring](#6-logging--monitoring)
|
|
52
|
+
- [Deep Dive: Tests & Technical Resources](#deep-dive-tests--technical-resources)
|
|
19
53
|
|
|
20
54
|
## Features
|
|
21
55
|
|
|
22
56
|
| Feature | Why it matters |
|
|
23
57
|
| :--- | :--- |
|
|
24
58
|
| **[Intelligent Querying](https://uql-orm.dev/querying/relations)** | Deep auto-completion for operators and relations at any depth—no more guessing property names. |
|
|
25
|
-
| **Serializable JSON** |
|
|
26
|
-
| **Unified Dialects** | Write once, run anywhere. Seamlessly switch between PostgreSQL, MySQL, SQLite, and MongoDB. |
|
|
59
|
+
| **Serializable JSON** | Query objects are valid JSON, which makes them straightforward to transport over HTTP/gRPC/WebSockets. |
|
|
60
|
+
| **Unified Dialects** | Write once, run anywhere. Seamlessly switch between PostgreSQL, MySQL, MariaDB, SQLite, and MongoDB. |
|
|
27
61
|
| **[Naming Strategies](https://uql-orm.dev/naming-strategy)** | No more `camelCase` vs `snake_case` headaches. Map your code to your database automatically. |
|
|
28
|
-
| **Smart SQL Engine** | Zero-allocation SQL generation
|
|
62
|
+
| **Smart SQL Engine** | Zero-allocation SQL generation with top-ranked results in our [open benchmark](https://github.com/rogerpadilla/ts-orm-benchmark). |
|
|
29
63
|
| **Thread-Safe by Design** | Protect your data integrity with centralized task queues and the `@Serialized()` decorator. |
|
|
30
64
|
| **[Declarative Transactions](https://uql-orm.dev/querying/transactions)** | Clean `@Transactional()` decorators that work beautifully with modern DI frameworks like NestJS. |
|
|
31
65
|
| **[Lifecycle Hooks](https://uql-orm.dev/entities/lifecycle-hooks)** | Automate validation, timestamps, and computed logic with intuitive class-based decorators. |
|
|
32
66
|
| **[Aggregate Queries](https://uql-orm.dev/querying/aggregate)** | Real-time analytics with `GROUP BY`, `HAVING`, and native math operators across all dialects. |
|
|
33
67
|
| **[Semantic Search](https://uql-orm.dev/querying/semantic-search)** | Native vector similarity search. Rank results by meaning using standard ORM operators. |
|
|
34
68
|
| **[Cursor Streaming](https://uql-orm.dev/querying/streaming)** | Process millions of rows with a stable memory footprint using native driver-level cursors. |
|
|
35
|
-
| **[Modern & Versatile](https://uql-orm.dev/entities/virtual-fields)** | Pure ESM, high-res timing, built-in soft-delete, and first-class JSONB
|
|
69
|
+
| **[Modern & Versatile](https://uql-orm.dev/entities/virtual-fields)** | Pure ESM, high-res timing, built-in soft-delete, and first-class JSON/JSONB support. |
|
|
36
70
|
| **[Database Migrations](https://www.uql-orm.dev/migrations)** | Entity-First synchronization. DDL is auto-generated by diffing your code against the live DB. |
|
|
37
71
|
| **[Logging & Monitoring](https://www.uql-orm.dev/logging)** | High-visibility debugging with slow-query detection and high-contrast terminal output. |
|
|
38
72
|
| **[Fullstack Bridge](https://www.uql-orm.dev/comparison#network-boundaries--apis)** | Speak to your database from the browser securely. First-party `HttpQuerier` removes API boilerplate. |
|
|
39
73
|
|
|
40
|
-
|
|
41
|
-
|
|
42
74
|
## 1. Install
|
|
43
75
|
|
|
44
76
|
Install the core package and the driver for your database:
|
|
@@ -58,7 +90,6 @@ npm install uql-orm # or bun add / pnpm add
|
|
|
58
90
|
| **SQLite** | `npm install better-sqlite3` |
|
|
59
91
|
| **LibSQL** (incl. Turso) | `npm install @libsql/client` |
|
|
60
92
|
| **MongoDB** | `npm install mongodb` |
|
|
61
|
-
| **CockroachDB** | `npm install pg` |
|
|
62
93
|
| **Cloudflare D1** | _Native (no driver needed)_ |
|
|
63
94
|
|
|
64
95
|
### TypeScript Configuration
|
|
@@ -74,7 +105,7 @@ Ensure your `tsconfig.json` is configured to support decorators and metadata:
|
|
|
74
105
|
}
|
|
75
106
|
```
|
|
76
107
|
|
|
77
|
-
|
|
108
|
+
> **Note:** UQL is Modern Pure ESM — ensure your project's `module` supports ESM imports (e.g., `NodeNext`, `ESNext`, `Bundler`).
|
|
78
109
|
|
|
79
110
|
## 2. Define your Entities
|
|
80
111
|
|
|
@@ -130,9 +161,6 @@ price?: number;
|
|
|
130
161
|
statusCode?: number;
|
|
131
162
|
```
|
|
132
163
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
164
|
```ts
|
|
137
165
|
import { v7 as uuidv7 } from 'uuid';
|
|
138
166
|
import { Entity, Id, Field, OneToOne, OneToMany, ManyToOne, ManyToMany, type Relation, type Json } from 'uql-orm';
|
|
@@ -225,9 +253,7 @@ export class PostTag {
|
|
|
225
253
|
}
|
|
226
254
|
```
|
|
227
255
|
|
|
228
|
-
> **
|
|
229
|
-
|
|
230
|
-
|
|
256
|
+
> **Note:** Use the `Relation<T>` utility type for relationship properties. It prevents TypeScript circular dependency errors while maintaining full type-safety throughout your app.
|
|
231
257
|
|
|
232
258
|
## 3. Set up a pool
|
|
233
259
|
|
|
@@ -242,7 +268,7 @@ export const pool = new PgQuerierPool(
|
|
|
242
268
|
{ host: 'localhost', database: 'uql_app', max: 10 },
|
|
243
269
|
{
|
|
244
270
|
logger: ['error', 'warn', 'migration'],
|
|
245
|
-
namingStrategy: new SnakeCaseNamingStrategy()
|
|
271
|
+
namingStrategy: new SnakeCaseNamingStrategy(),
|
|
246
272
|
slowQuery: { threshold: 1000 },
|
|
247
273
|
}
|
|
248
274
|
);
|
|
@@ -254,29 +280,27 @@ export default {
|
|
|
254
280
|
} satisfies Config;
|
|
255
281
|
```
|
|
256
282
|
|
|
257
|
-
> **
|
|
258
|
-
>
|
|
259
|
-
>
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
283
|
+
> **Notes:**
|
|
284
|
+
> - Reuse one pool for both app queries and migrations to keep behavior (for example naming strategy) consistent.
|
|
285
|
+
> - If your architecture spans backend + browser, `HttpQuerier` reduces custom API mapping and keeps query semantics aligned.
|
|
264
286
|
|
|
265
287
|
## 4. Manipulate the Data
|
|
266
288
|
|
|
267
289
|
UQL provides a straightforward API to interact with your data. **Always ensure queriers are released back to the pool.**
|
|
268
290
|
|
|
291
|
+
### Core Query Pattern
|
|
292
|
+
|
|
269
293
|
```ts
|
|
270
294
|
const querier = await pool.getQuerier();
|
|
271
295
|
try {
|
|
272
296
|
const results = await querier.findMany(User, {
|
|
273
297
|
$select: {
|
|
274
298
|
name: true,
|
|
275
|
-
profile: { $select: { bio: true }, $required: true } // INNER JOIN
|
|
299
|
+
profile: { $select: { bio: true }, $required: true }, // INNER JOIN
|
|
276
300
|
},
|
|
277
301
|
$where: {
|
|
278
302
|
status: 'active',
|
|
279
|
-
name: { $istartsWith: 'a' }
|
|
303
|
+
name: { $istartsWith: 'a' },
|
|
280
304
|
},
|
|
281
305
|
$limit: 10,
|
|
282
306
|
});
|
|
@@ -295,7 +319,7 @@ WHERE "User"."status" = 'active' AND "User"."name" ILIKE 'a%'
|
|
|
295
319
|
LIMIT 10 OFFSET 0
|
|
296
320
|
```
|
|
297
321
|
|
|
298
|
-
|
|
322
|
+
### Advanced Query Patterns
|
|
299
323
|
|
|
300
324
|
### Modern Indexing: Semantic Search
|
|
301
325
|
|
|
@@ -309,8 +333,6 @@ const results = await querier.findMany(Item, {
|
|
|
309
333
|
});
|
|
310
334
|
```
|
|
311
335
|
|
|
312
|
-
|
|
313
|
-
|
|
314
336
|
### Advanced: Virtual Fields & Raw SQL
|
|
315
337
|
|
|
316
338
|
Define complex logic directly in your entities using `raw` functions. These are resolved during SQL generation for peak efficiency.
|
|
@@ -331,11 +353,9 @@ export class Item {
|
|
|
331
353
|
}
|
|
332
354
|
```
|
|
333
355
|
|
|
334
|
-
&
|
|
356
|
+
### JSON Operators & Relation Filtering
|
|
335
357
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
Query nested JSON fields using **type-safe dot-notation** with full operator support. Wrap fields with `Json<T>` to get IDE autocompletion for valid paths. UQL generates the correct SQL for each dialect.
|
|
358
|
+
Query nested JSON fields using **type-safe dot-notation** with full operator support. Wrap fields with `Json<T>` to get IDE autocompletion for valid paths. UQL generates native SQL per dialect.
|
|
339
359
|
|
|
340
360
|
```ts
|
|
341
361
|
// Filter by nested JSONB field paths
|
|
@@ -347,9 +367,22 @@ const items = await querier.findMany(Company, {
|
|
|
347
367
|
});
|
|
348
368
|
```
|
|
349
369
|
|
|
350
|
-
**PostgreSQL:** `WHERE ("settings"->>'isArchived') IS DISTINCT FROM $1 AND (("settings"->>'priority'))::numeric >= $2`
|
|
370
|
+
**PostgreSQL:** `WHERE ("settings"->>'isArchived') IS DISTINCT FROM $1 AND (("settings"->>'priority'))::numeric >= $2`
|
|
371
|
+
**MySQL:** `WHERE (\`settings\`->>'isArchived') <> ? AND CAST((\`settings\`->>'priority') AS DECIMAL) >= ?`
|
|
372
|
+
**MariaDB:** `WHERE JSON_VALUE(\`settings\`, '$.isArchived') <> ? AND CAST(JSON_VALUE(\`settings\`, '$.priority') AS DECIMAL) >= ?`
|
|
351
373
|
**SQLite:** `WHERE json_extract("settings", '$.isArchived') IS NOT ? AND CAST(json_extract("settings", '$.priority') AS REAL) >= ?`
|
|
352
374
|
|
|
375
|
+
Atomic JSON updates support `$merge`, `$unset`, and `$push`:
|
|
376
|
+
|
|
377
|
+
```ts
|
|
378
|
+
await querier.updateOneById(Company, id, {
|
|
379
|
+
settings: { $merge: { theme: 'dark' }, $push: { tags: 'orm' }, $unset: ['deprecated'] },
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
> **Modern DB Baselines used by docs/examples:** PostgreSQL 16+, MySQL 8.4+ (LTS), MariaDB 12.2+, SQLite 3.45+.
|
|
384
|
+
> Full generated SQL examples: [JSON / JSONB docs](https://uql-orm.dev/querying/json).
|
|
385
|
+
|
|
353
386
|
Filter parent entities by their **ManyToMany** or **OneToMany** relations using automatic EXISTS subqueries:
|
|
354
387
|
|
|
355
388
|
```ts
|
|
@@ -361,9 +394,7 @@ const posts = await querier.findMany(Post, {
|
|
|
361
394
|
|
|
362
395
|
**PostgreSQL:** `WHERE EXISTS (SELECT 1 FROM "PostTag" WHERE "PostTag"."postId" = "Post"."id" AND "PostTag"."tagId" IN (SELECT "Tag"."id" FROM "Tag" WHERE "Tag"."name" = $1))`
|
|
363
396
|
|
|
364
|
-
> **
|
|
365
|
-
|
|
366
|
-
|
|
397
|
+
> **Note:** Wrap JSON fields with `Json<T>` to get autocompletion for valid dot-notation paths.
|
|
367
398
|
|
|
368
399
|
### Aggregate Queries
|
|
369
400
|
|
|
@@ -405,8 +436,6 @@ const names = await querier.findMany(User, {
|
|
|
405
436
|
|
|
406
437
|
> **Learn more**: See the full [Aggregate Queries guide](https://uql-orm.dev/querying/aggregate) for `$having` operators, MongoDB pipeline details, and advanced patterns.
|
|
407
438
|
|
|
408
|
-
|
|
409
|
-
|
|
410
439
|
### Cursor-Based Streaming
|
|
411
440
|
|
|
412
441
|
For large result sets, use `findManyStream()` to iterate row-by-row without loading everything into memory. Each driver uses its optimal native cursor API.
|
|
@@ -417,8 +446,6 @@ for await (const user of querier.findManyStream(User, { $where: { active: true }
|
|
|
417
446
|
}
|
|
418
447
|
```
|
|
419
448
|
|
|
420
|
-
|
|
421
|
-
|
|
422
449
|
### Thread-Safe Transactions
|
|
423
450
|
|
|
424
451
|
UQL is one of the few ORMs with a **centralized serialization engine**. Transactions are guaranteed to be race-condition free.
|
|
@@ -469,8 +496,6 @@ try {
|
|
|
469
496
|
}
|
|
470
497
|
```
|
|
471
498
|
|
|
472
|
-
|
|
473
|
-
|
|
474
499
|
## 5. Migrations & Synchronization
|
|
475
500
|
|
|
476
501
|
UQL takes an **Entity-First** approach. You modify your TypeScript classes, and UQL handles the heavy lifting—auto-generating migration files by diffing your code against the live database.
|
|
@@ -484,7 +509,7 @@ npx uql-migrate generate:entities add_user_nickname
|
|
|
484
509
|
npx uql-migrate up
|
|
485
510
|
```
|
|
486
511
|
|
|
487
|
-
> **
|
|
512
|
+
> **Note:** Keep entities as the source of truth to minimize drift between code and database schema.
|
|
488
513
|
|
|
489
514
|
### 1. Unified Configuration
|
|
490
515
|
|
|
@@ -544,7 +569,7 @@ npx uql-migrate generate seed_default_roles
|
|
|
544
569
|
|
|
545
570
|
### 3. AutoSync (Development)
|
|
546
571
|
|
|
547
|
-
Keep your schema in sync without manual migrations. It is **
|
|
572
|
+
Keep your schema in sync without manual migrations. It is **safe by default**: in safe mode (default), it adds new tables/columns and blocks destructive changes (column drops or type alterations). Blocked actions are logged so you can migrate them manually.
|
|
548
573
|
|
|
549
574
|
**New Capabilities (v3.8+):**
|
|
550
575
|
|
|
@@ -582,13 +607,13 @@ const migrator = new Migrator(pool, {
|
|
|
582
607
|
await migrator.autoSync({ logging: true });
|
|
583
608
|
```
|
|
584
609
|
|
|
585
|
-
> **
|
|
610
|
+
> **Note:** In development, `autoSync` accelerates iteration while still protecting data by blocking destructive schema changes.
|
|
586
611
|
|
|
587
|
-
|
|
612
|
+
## Operations
|
|
588
613
|
|
|
589
|
-
|
|
614
|
+
### 6. Logging & Monitoring
|
|
590
615
|
|
|
591
|
-
UQL
|
|
616
|
+
UQL includes a structured logging system for query visibility and performance monitoring.
|
|
592
617
|
|
|
593
618
|
### Log Levels
|
|
594
619
|
|
|
@@ -603,7 +628,7 @@ UQL features a professional-grade, structured logging system designed for high v
|
|
|
603
628
|
|
|
604
629
|
### Visual Feedback
|
|
605
630
|
|
|
606
|
-
The `DefaultLogger` provides high-contrast, colored output
|
|
631
|
+
The `DefaultLogger` provides high-contrast, colored output for quick debugging:
|
|
607
632
|
|
|
608
633
|
```text
|
|
609
634
|
query: SELECT * FROM "user" WHERE "id" = $1 -- [123] [2ms]
|
|
@@ -611,9 +636,7 @@ slow query: UPDATE "post" SET "title" = $1 -- ["New Title"] [1250ms]
|
|
|
611
636
|
error: Failed to connect to database: Connection timeout
|
|
612
637
|
```
|
|
613
638
|
|
|
614
|
-
> **
|
|
615
|
-
|
|
616
|
-
|
|
639
|
+
> **Note:** In production, keep logs lean with `logger: ['error', 'warn', 'slowQuery']`.
|
|
617
640
|
|
|
618
641
|
Learn more about UQL at [uql-orm.dev](https://uql-orm.dev) for details on:
|
|
619
642
|
|
|
@@ -625,9 +648,7 @@ Learn more about UQL at [uql-orm.dev](https://uql-orm.dev) for details on:
|
|
|
625
648
|
- [Soft Deletes & Auditing](https://uql-orm.dev/entities/soft-delete)
|
|
626
649
|
- [Database Migration & Syncing](https://uql-orm.dev/migrations)
|
|
627
650
|
|
|
628
|
-
&
|
|
629
|
-
|
|
630
|
-
## 🛠 Deep Dive: Tests & Technical Resources
|
|
651
|
+
### Deep Dive: Tests & Technical Resources
|
|
631
652
|
|
|
632
653
|
For those who want to see the "engine under the hood," check out these resources in the source code:
|
|
633
654
|
|
|
@@ -638,8 +659,6 @@ For those who want to see the "engine under the hood," check out these resources
|
|
|
638
659
|
- [PostgreSQL](https://github.com/rogerpadilla/uql/blob/main/packages/uql-orm/src/postgres/postgresDialect.spec.ts) \| [MySQL](https://github.com/rogerpadilla/uql/blob/main/packages/uql-orm/src/mysql/mysqlDialect.spec.ts) \| [SQLite](https://github.com/rogerpadilla/uql/blob/main/packages/uql-orm/src/sqlite/sqliteDialect.spec.ts) specs.
|
|
639
660
|
- [Querier Integration Tests](https://github.com/rogerpadilla/uql/blob/main/packages/uql-orm/src/querier/abstractSqlQuerier-spec.ts): SQL generation & connection management tests.
|
|
640
661
|
|
|
641
|
-
|
|
642
|
-
|
|
643
662
|
## Built with ❤️ and supported by
|
|
644
663
|
|
|
645
664
|
UQL is an open-source project proudly sponsored by **[Variability.ai](https://variability.ai)**.
|