@uql/core 3.11.1 → 3.12.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 +39 -2
- package/README.md +34 -2
- package/dist/browser/uql-browser.min.js.map +1 -1
- package/dist/dialect/abstractSqlDialect.d.ts +34 -5
- package/dist/dialect/abstractSqlDialect.d.ts.map +1 -1
- package/dist/dialect/abstractSqlDialect.js +134 -8
- package/dist/dialect/abstractSqlDialect.js.map +1 -1
- package/dist/postgres/postgresDialect.d.ts +9 -0
- package/dist/postgres/postgresDialect.d.ts.map +1 -1
- package/dist/postgres/postgresDialect.js +5 -3
- package/dist/postgres/postgresDialect.js.map +1 -1
- package/dist/querier/abstractQuerier.d.ts.map +1 -1
- package/dist/querier/abstractQuerier.js.map +1 -1
- package/dist/sqlite/sqliteDialect.d.ts +15 -0
- package/dist/sqlite/sqliteDialect.d.ts.map +1 -1
- package/dist/sqlite/sqliteDialect.js +8 -3
- package/dist/sqlite/sqliteDialect.js.map +1 -1
- package/dist/type/entity.d.ts +10 -3
- package/dist/type/entity.d.ts.map +1 -1
- package/dist/type/query.d.ts +6 -4
- package/dist/type/query.d.ts.map +1 -1
- package/dist/type/query.js.map +1 -1
- package/dist/type/utility.d.ts +14 -0
- package/dist/type/utility.d.ts.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
# [3.12.0](https://github.com/rogerpadilla/uql/compare/@uql/core@3.11.1...@uql/core@3.12.0) (2026-03-05)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* introduce JSONB dot-notation filtering in `where` clauses and fix `raw()` expression prefixing in logical operators. ([669257d](https://github.com/rogerpadilla/uql/commit/669257d497e08729094a9f178685ca6665b8b20b))
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
|
|
@@ -17,6 +20,40 @@ All notable changes to this project will be documented in this file. Please add
|
|
|
17
20
|
|
|
18
21
|
date format is [yyyy-mm-dd]
|
|
19
22
|
|
|
23
|
+
## [3.12.0] - 2026-03-05
|
|
24
|
+
### New Features
|
|
25
|
+
- **JSONB Dot-Notation Operators**: Filter by nested JSON field paths directly in `$where` with full operator support (`$eq`, `$ne`, `$gt`, `$lt`, `$like`, `$ilike`, `$in`, `$nin`, `$regex`, etc.). Works across PostgreSQL, MySQL, and SQLite.
|
|
26
|
+
```ts
|
|
27
|
+
await querier.findMany(User, {
|
|
28
|
+
$where: { 'settings.isArchived': { $ne: true } },
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
- **Relation Filtering**: Filter by ManyToMany and OneToMany relations using automatic EXISTS subqueries. No more manual `raw()` joins.
|
|
32
|
+
```ts
|
|
33
|
+
await querier.findMany(Item, {
|
|
34
|
+
$where: { tags: { name: 'important' } },
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
- **`Json<T>` Marker Type**: Wrap JSONB field types with `Json<T>` to ensure they are classified as `FieldKey` (not `RelationKey`), enabling type-safe usage in `$where`, `$select`, and `$sort`.
|
|
38
|
+
```ts
|
|
39
|
+
@Field({ type: 'jsonb' })
|
|
40
|
+
settings?: Json<{ isArchived?: boolean }>;
|
|
41
|
+
```
|
|
42
|
+
- **`JsonFieldPaths<E>` Autocompletion**: Template literal type that derives valid dot-notation paths from `Json<T>` fields (e.g., `'kind.public' | 'kind.private'`). Provides IDE autocompletion for JSONB `$where` queries without restricting arbitrary string paths.
|
|
43
|
+
|
|
44
|
+
### Bug Fixes
|
|
45
|
+
- **raw() String Prefix Fix**: String-based `raw()` values in `$and`/`$or` are no longer incorrectly table-prefixed (e.g., `raw("kind IS NOT NULL")` previously produced `resource.kind IS NOT NULL` instead of `kind IS NOT NULL`).
|
|
46
|
+
|
|
47
|
+
### Improvements & Refactoring
|
|
48
|
+
- **DRY JSON Config**: Extracted `getBaseJsonConfig()` in each dialect — `$elemMatch` and dot-notation now compose from a single config source, eliminating ~20 lines of duplication.
|
|
49
|
+
- **Extracted `normalizeWhereValue()`**: Deduplicated the `Array→$in / object→passthrough / scalar→$eq` normalization used by both regular field and JSON path comparisons.
|
|
50
|
+
- **Cleaner Dot-Notation Detection**: Uses `indexOf`+`slice` instead of two `split('.')` calls for efficient dot-path parsing.
|
|
51
|
+
- **Relation Safety Guard**: `compareRelation()` now throws a descriptive `TypeError` if `rel.references` is missing, instead of a cryptic undefined crash.
|
|
52
|
+
- **TypeScript 6 Compatibility**: Fixed `QueryWhereMap` circular type reference and expanded `QueryWhereOptions.clause` union.
|
|
53
|
+
|
|
54
|
+
### Test Coverage
|
|
55
|
+
- **46 new tests** across 3 dialects (base, PostgreSQL, SQLite) covering all new features and edge cases. Total: **1561 tests passing**.
|
|
56
|
+
|
|
20
57
|
## [3.11.1] - 2026-02-26
|
|
21
58
|
### Improvements
|
|
22
59
|
- **Expanded ColumnType Aliases**: Added `integer`, `tinyint`, `bool`, `datetime`, and `smallserial` as first-class `ColumnType` values (aliases for `int`, `boolean`, `timestamp`, `smallserial`, and `serial` respectively). Users can now use standard SQL keywords interchangeably (e.g., `integer` or `int`, `bool` or `boolean`, `datetime` or `timestamp`).
|
package/README.md
CHANGED
|
@@ -112,7 +112,7 @@ UQL separates the **intent** of your data from its **storage**. Both properties
|
|
|
112
112
|
externalId?: string;
|
|
113
113
|
|
|
114
114
|
@Field({ type: 'json' }) // → JSONB (Postgres), JSON (MySQL), TEXT (SQLite)
|
|
115
|
-
metadata?:
|
|
115
|
+
metadata?: Json<{ theme?: string }>;
|
|
116
116
|
|
|
117
117
|
// Logical types with constraints - portable with control
|
|
118
118
|
@Field({ type: 'varchar', length: 500 })
|
|
@@ -131,7 +131,7 @@ statusCode?: number;
|
|
|
131
131
|
|
|
132
132
|
```ts
|
|
133
133
|
import { v7 as uuidv7 } from 'uuid';
|
|
134
|
-
import { Entity, Id, Field, OneToOne, OneToMany, ManyToOne, ManyToMany, type Relation } from '@uql/core';
|
|
134
|
+
import { Entity, Id, Field, OneToOne, OneToMany, ManyToOne, ManyToMany, type Relation, type Json } from '@uql/core';
|
|
135
135
|
|
|
136
136
|
@Entity()
|
|
137
137
|
export class User {
|
|
@@ -314,6 +314,38 @@ export class Item {
|
|
|
314
314
|
|
|
315
315
|
|
|
316
316
|
|
|
317
|
+
### JSONB Operators & Relation Filtering
|
|
318
|
+
|
|
319
|
+
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.
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
// Filter by nested JSONB field paths
|
|
323
|
+
const items = await querier.findMany(Company, {
|
|
324
|
+
$where: {
|
|
325
|
+
'settings.isArchived': { $ne: true },
|
|
326
|
+
'settings.priority': { $gte: 5 },
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
**PostgreSQL:** `WHERE ("settings"->>'isArchived') <> $1 AND (("settings"->>'priority'))::numeric >= $2`
|
|
332
|
+
**SQLite:** `WHERE json_extract("settings", '$.isArchived') <> ? AND CAST(json_extract("settings", '$.priority') AS REAL) >= ?`
|
|
333
|
+
|
|
334
|
+
Filter parent entities by their **ManyToMany** or **OneToMany** relations using automatic EXISTS subqueries:
|
|
335
|
+
|
|
336
|
+
```ts
|
|
337
|
+
// Find posts that have a tag named 'typescript'
|
|
338
|
+
const posts = await querier.findMany(Post, {
|
|
339
|
+
$where: { tags: { name: 'typescript' } },
|
|
340
|
+
});
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**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))`
|
|
344
|
+
|
|
345
|
+
> **Pro Tip**: Wrap JSONB field types with `Json<T>` (e.g., `settings?: Json<{ isArchived?: boolean }>`) to get IDE autocompletion for dot-notation paths.
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
|
|
317
349
|
### Thread-Safe Transactions
|
|
318
350
|
|
|
319
351
|
UQL is one of the few ORMs with a **centralized serialization engine**. Transactions are guaranteed to be race-condition free.
|