@uql/core 3.13.0 → 3.14.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.
Files changed (72) hide show
  1. package/CHANGELOG.md +45 -2
  2. package/README.md +23 -2
  3. package/dist/browser/type/clientQuerier.d.ts +11 -2
  4. package/dist/browser/type/clientQuerier.d.ts.map +1 -1
  5. package/dist/dialect/abstractSqlDialect.d.ts +13 -5
  6. package/dist/dialect/abstractSqlDialect.d.ts.map +1 -1
  7. package/dist/dialect/abstractSqlDialect.js +70 -90
  8. package/dist/dialect/abstractSqlDialect.js.map +1 -1
  9. package/dist/express/querierMiddleware.d.ts.map +1 -1
  10. package/dist/express/querierMiddleware.js +9 -24
  11. package/dist/express/querierMiddleware.js.map +1 -1
  12. package/dist/maria/mariadbQuerier.d.ts +1 -5
  13. package/dist/maria/mariadbQuerier.d.ts.map +1 -1
  14. package/dist/maria/mariadbQuerier.js +2 -2
  15. package/dist/maria/mariadbQuerier.js.map +1 -1
  16. package/dist/migrate/cli.d.ts +4 -4
  17. package/dist/migrate/cli.d.ts.map +1 -1
  18. package/dist/migrate/cli.js.map +1 -1
  19. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +2 -2
  20. package/dist/migrate/generator/mongoSchemaGenerator.d.ts.map +1 -1
  21. package/dist/migrate/generator/mongoSchemaGenerator.js.map +1 -1
  22. package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +7 -7
  23. package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts.map +1 -1
  24. package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js.map +1 -1
  25. package/dist/migrate/introspection/mongoIntrospector.js +1 -1
  26. package/dist/migrate/introspection/mongoIntrospector.js.map +1 -1
  27. package/dist/migrate/introspection/postgresIntrospector.d.ts +2 -2
  28. package/dist/migrate/introspection/postgresIntrospector.d.ts.map +1 -1
  29. package/dist/migrate/introspection/postgresIntrospector.js +0 -1
  30. package/dist/migrate/introspection/postgresIntrospector.js.map +1 -1
  31. package/dist/migrate/storage/databaseStorage.js.map +1 -1
  32. package/dist/mongo/mongoDialect.d.ts +2 -2
  33. package/dist/mongo/mongoDialect.d.ts.map +1 -1
  34. package/dist/mongo/mongoDialect.js +2 -8
  35. package/dist/mongo/mongoDialect.js.map +1 -1
  36. package/dist/mysql/mysql2Querier.d.ts +1 -1
  37. package/dist/mysql/mysql2Querier.d.ts.map +1 -1
  38. package/dist/mysql/mysql2Querier.js +6 -5
  39. package/dist/mysql/mysql2Querier.js.map +1 -1
  40. package/dist/neon/neonQuerier.d.ts +1 -5
  41. package/dist/neon/neonQuerier.d.ts.map +1 -1
  42. package/dist/neon/neonQuerier.js +2 -3
  43. package/dist/neon/neonQuerier.js.map +1 -1
  44. package/dist/postgres/pgQuerier.d.ts +3 -7
  45. package/dist/postgres/pgQuerier.d.ts.map +1 -1
  46. package/dist/postgres/pgQuerier.js +3 -3
  47. package/dist/postgres/pgQuerier.js.map +1 -1
  48. package/dist/querier/abstractQuerier.d.ts +2 -2
  49. package/dist/querier/abstractQuerier.d.ts.map +1 -1
  50. package/dist/querier/abstractQuerier.js +2 -7
  51. package/dist/querier/abstractQuerier.js.map +1 -1
  52. package/dist/querier/abstractSqlQuerier.d.ts.map +1 -1
  53. package/dist/querier/abstractSqlQuerier.js +1 -1
  54. package/dist/querier/abstractSqlQuerier.js.map +1 -1
  55. package/dist/type/entity.d.ts +1 -2
  56. package/dist/type/entity.d.ts.map +1 -1
  57. package/dist/type/query.d.ts +20 -34
  58. package/dist/type/query.d.ts.map +1 -1
  59. package/dist/type/query.js.map +1 -1
  60. package/dist/type/universalQuerier.d.ts +16 -16
  61. package/dist/type/universalQuerier.d.ts.map +1 -1
  62. package/dist/type/utility.d.ts +8 -1
  63. package/dist/type/utility.d.ts.map +1 -1
  64. package/dist/util/dialect.util.d.ts +1 -1
  65. package/dist/util/dialect.util.d.ts.map +1 -1
  66. package/dist/util/dialect.util.js +3 -6
  67. package/dist/util/dialect.util.js.map +1 -1
  68. package/dist/util/sql.util.d.ts +9 -1
  69. package/dist/util/sql.util.d.ts.map +1 -1
  70. package/dist/util/sql.util.js +10 -0
  71. package/dist/util/sql.util.js.map +1 -1
  72. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -3,12 +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
- # [3.13.0](https://github.com/rogerpadilla/uql/compare/@uql/core@3.12.1...@uql/core@3.13.0) (2026-03-07)
6
+ # [3.14.0](https://github.com/rogerpadilla/uql/compare/@uql/core@3.13.1...@uql/core@3.14.0) (2026-03-07)
7
7
 
8
8
 
9
9
  ### Features
10
10
 
11
- * Add JSON merge/unset operations to SQL dialect update methods and enable JSON dot-notation sorting. ([9140ff7](https://github.com/rogerpadilla/uql/commit/9140ff767218e44ae9c054a0fdc431b4b14b9d15))
11
+ * Standardize the `$select` query parameter to accept an object instead of an array for field selection. ([b4dca74](https://github.com/rogerpadilla/uql/commit/b4dca74e65013c14dd508c9ccea646b44eee1f3e))
12
12
 
13
13
 
14
14
 
@@ -20,6 +20,49 @@ All notable changes to this project will be documented in this file. Please add
20
20
 
21
21
  date format is [yyyy-mm-dd]
22
22
 
23
+ ## [3.14.0] - 2026-03-07
24
+ ### Type Safety
25
+ - **Map-Only `$select`**: `$select` now only accepts the map form (e.g., `{ id: true, name: true }`), removing the less type-safe array form. Relation selections are now additive in map form.
26
+ - **Stricter `$and`/`$or`/`$not`/`$nor`**: Logical operators now only accept `QueryWhereMap | QueryRaw` elements — bare ID values (e.g., `$or: [5]`) must use the explicit form `$or: [{ id: 5 }]`. This restores TypeScript's excess property checking inside logical clauses.
27
+ - **Wider JSON Array Operators**: `$elemMatch` and `$all` now accept JSON fields without requiring `as any` casts, thanks to widened fallback types for non-array field types. Removed 6 unnecessary `as any` casts from tests.
28
+
29
+ ### Refactoring
30
+ - **Simplified Express Middleware**: `$where` ID injection in `querierMiddleware` now always uses map form, properly converting array `$where` from query strings to `{ id: { $in: [...] } }`.
31
+ - **Removed `QueryWhereSingle`**: Consolidated into a flattened `QueryWhere<E>` union. Introduced reusable `QueryWhereArray<E>` type alias.
32
+
33
+ ## [3.13.1] - 2026-03-07
34
+ ### Type Safety
35
+ - **Fully Typed Querier Returns**: Remaining querier methods now return proper types instead of `unknown`, enabling IDE autocompletion and compile-time validation on query results for all methods.
36
+ - **Semantic `RawRow` Type**: Introduced `RawRow` as a reusable semantic alias for raw database result rows, replacing scattered `Record<string, unknown>` and `any` across queriers, introspection, and SQL utilities.
37
+ - **Typed MySQL Driver**: Replaced `any` in MySQL2 querier with proper `ResultSetHeader` type from the driver.
38
+ - **Smarter `$select` Validation**: Field and relation selections are now validated simultaneously, catching invalid property names at compile time.
39
+ - **Stricter Null Comparisons**: `null` is now only accepted in `$eq` and `$ne` operators — invalid comparisons like `$gt: null` are caught at compile time.
40
+ - **Typed `defaultValue`**: Entity field defaults are now type-checked instead of accepting `any`.
41
+
42
+ ### API Surface & DX
43
+ - **Cleaner Querier Interfaces**: `ClientQuerier` and `UniversalQuerier` are now properly separated with documented contracts, preventing confusing type mismatches.
44
+ - **Reduced Public API**: Removed unused/redundant type exports (`QuerySearchOne`, `QueryConflictPathsMap`), making the API surface smaller and easier to navigate.
45
+ - **Improved JSDoc**: Added cross-references between related operators (`$not` root vs field) for better discoverability.
46
+
47
+ ### Refactoring
48
+ - **DRY Relation Iteration**: Consolidated duplicated relation iteration logic into `forEachJoinableRelation`, eliminating ~35 duplicated lines.
49
+ - **DRY `compareJsonPath`**: Simplified from 6 parameters to 3, removing redundant internal calls.
50
+ - **DRY `extractInsertResult`**: Shared utility for INSERT result ID extraction across all RETURNING-based drivers (pg, neon, maria), eliminating duplicated logic.
51
+ - **Eliminated Type Casts**: Replaced `Record<string, unknown>` casts with proper type guards across the dialect layer.
52
+ - **Typo Fix**: Renamed `buldQueryWhereAsMap` → `buildQueryWhereAsMap`.
53
+
54
+ ## [3.13.0] - 2026-03-07
55
+ ### New Features
56
+ - **`QueryRaw` Class Refactoring**: Replaced the opaque type + type-guard pattern with a proper `class` using `Symbol`-keyed properties (`RAW_VALUE`, `RAW_ALIAS`). Enables `instanceof QueryRaw` checks, eliminates autocomplete pollution, and prevents accidental structural matches.
57
+ - **JSON `$merge`/`$unset` Operators**: Restored type-safe partial update of JSONB fields via `$merge` (shallow merge) and `$unset` (key removal) in `update()` payloads. Works across PostgreSQL (`||`/`-`), MySQL (`JSON_MERGE_PATCH`/`JSON_REMOVE`), and SQLite (`json_patch`/`json_remove`).
58
+ ```ts
59
+ await querier.updateMany(Company, { $where: { id: 1 } }, {
60
+ kind: { $merge: { theme: 'dark' }, $unset: ['deprecated'] },
61
+ });
62
+ ```
63
+ - **JSON Dot-Notation Sorting**: `$sort` now supports JSONB dot-notation paths (e.g. `{ 'kind.priority': 'desc' }`), sharing the `resolveJsonDotPath` helper with `$where` for DRY consistency.
64
+
65
+
23
66
  ## [3.12.1] - 2026-03-05
24
67
  ### Bug Fixes
25
68
  - **Null-Safe JSONB `$ne`**: JSONB dot-notation `$ne` now uses null-safe operators (`IS DISTINCT FROM` on PostgreSQL, `IS NOT` on SQLite) so that absent keys (which return SQL `NULL`) are correctly included in results. Previously, `{ 'settings.isArchived': { $ne: true } }` would silently exclude rows where the key didn't exist.
package/README.md CHANGED
@@ -28,7 +28,7 @@ const users = await querier.findMany(User, {
28
28
  | **[Naming Strategies](https://uql.app/naming-strategy)** | Pluggable system to translate between TypeScript `camelCase` and database `snake_case`. |
29
29
  | **Smart SQL Engine** | Optimized sub-queries, placeholders ($1, $2), and minimal SQL generation via `QueryContext`. |
30
30
  | **Thread-Safe by Design** | Centralized task queue and `@Serialized()` decorator prevent race conditions. |
31
- | **[Declarative Transactions](https://www.uql.app/transactions-declarative)** | Standard `@Transactional()` and `@InjectQuerier()` decorators for NestJS/DI. |
31
+ | **[Declarative Transactions](https://uql.app/transactions)** | Standard `@Transactional()` and `@InjectQuerier()` decorators for NestJS/DI. |
32
32
  | **[Modern &amp; Versatile](https://uql.app/entities/virtual-fields)** | **Pure ESM**, high-res timing, [Soft-delete](https://uql.app/entities/soft-delete), and **Vector/JSONB/JSON** support. |
33
33
  | **[Database Migrations](https://www.uql.app/migrations)** | Built-in [Entity-First synchronization](https://uql.app/migrations#3-entity-first-synchronization-development) and a robust CLI for version-controlled schema evolution. |
34
34
  | **[Logging & Monitoring](https://www.uql.app/logging)** | Professional-grade monitoring with slow-query detection and colored output. |
@@ -266,7 +266,7 @@ try {
266
266
  const users = await querier.findMany(User, {
267
267
  $select: {
268
268
  name: true,
269
- profile: { $select: ['bio'], $required: true } // INNER JOIN
269
+ profile: { $select: { bio: true }, $required: true } // INNER JOIN
270
270
  },
271
271
  $where: {
272
272
  status: 'active',
@@ -375,6 +375,27 @@ export class UserService {
375
375
  }
376
376
  ```
377
377
 
378
+ #### Option C: Imperative
379
+
380
+ For granular control over the transaction lifecycle, manage `begin`, `commit`, `rollback`, and `release` yourself.
381
+
382
+ ```ts
383
+ const querier = await pool.getQuerier();
384
+ try {
385
+ await querier.beginTransaction();
386
+
387
+ const userId = await querier.insertOne(User, { name: '...' });
388
+ await querier.insertOne(Profile, { userId, picture: '...' });
389
+
390
+ await querier.commitTransaction();
391
+ } catch (error) {
392
+ await querier.rollbackTransaction();
393
+ throw error;
394
+ } finally {
395
+ await querier.release();
396
+ }
397
+ ```
398
+
378
399
  &nbsp;
379
400
 
380
401
  ## 5. Migrations & Synchronization
@@ -1,6 +1,15 @@
1
- import type { IdValue, Query, QueryOne, QueryOptions, QuerySearch, Type, UniversalQuerier, UpdatePayload } from '../../type/index.js';
1
+ import type { IdValue, Query, QueryOne, QueryOptions, QuerySearch, Type, UpdatePayload } from '../../type/index.js';
2
2
  import type { RequestOptions, RequestSuccessResponse } from './request.js';
3
- export interface ClientQuerier extends UniversalQuerier {
3
+ /**
4
+ * Client-side querier — mirrors {@link UniversalQuerier} method names and semantics but with two structural differences:
5
+ * 1. Every return type is wrapped in `RequestSuccessResponse<T>` (adds `data`/`count` envelope).
6
+ * 2. Every method accepts an extra `opts?: RequestOptions` parameter.
7
+ *
8
+ * These differences prevent clean `extends UniversalQuerier` — TypeScript does not support
9
+ * higher-kinded type wrappers, so the interfaces are kept in sync by convention.
10
+ * @see UniversalQuerier for the server-side contract with direct return types.
11
+ */
12
+ export interface ClientQuerier {
4
13
  findOneById<E>(entity: Type<E>, id: IdValue<E>, q?: QueryOne<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E | undefined>>;
5
14
  findOne<E>(entity: Type<E>, q: QueryOne<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E | undefined>>;
6
15
  findMany<E>(entity: Type<E>, q: Query<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E[]>>;
@@ -1 +1 @@
1
- {"version":3,"file":"clientQuerier.d.ts","sourceRoot":"","sources":["../../../src/browser/type/clientQuerier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,IAAI,EACJ,gBAAgB,EAChB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAE3E,MAAM,WAAW,aAAc,SAAQ,gBAAgB;IACrD,WAAW,CAAC,CAAC,EACX,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EACd,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EACf,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,sBAAsB,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAElD,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAEnH,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEvG,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE/G,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IAE9G,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9G,aAAa,CAAC,CAAC,EACb,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EACd,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EACzB,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3C,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5G,aAAa,CAAC,CAAC,EACb,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EACd,IAAI,CAAC,EAAE,YAAY,GAAG,cAAc,GACnC,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3C,UAAU,CAAC,CAAC,EACV,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,EAClB,IAAI,CAAC,EAAE,YAAY,GAAG,cAAc,GACnC,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;CAC5C"}
1
+ {"version":3,"file":"clientQuerier.d.ts","sourceRoot":"","sources":["../../../src/browser/type/clientQuerier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpH,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAE3E;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,CAAC,EACX,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EACd,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EACf,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,sBAAsB,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAElD,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAEnH,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEvG,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE/G,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IAE9G,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9G,aAAa,CAAC,CAAC,EACb,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EACd,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EACzB,IAAI,CAAC,EAAE,cAAc,GACpB,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3C,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5G,aAAa,CAAC,CAAC,EACb,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EACd,IAAI,CAAC,EAAE,YAAY,GAAG,cAAc,GACnC,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3C,UAAU,CAAC,CAAC,EACV,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EACf,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,EAClB,IAAI,CAAC,EAAE,YAAY,GAAG,cAAc,GACnC,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;CAC5C"}
@@ -12,14 +12,19 @@ export declare abstract class AbstractSqlDialect extends AbstractDialect impleme
12
12
  placeholder(_index: number): string;
13
13
  returningId<E>(entity: Type<E>): string;
14
14
  search<E>(ctx: QueryContext, entity: Type<E>, q?: Query<E>, opts?: QueryOptions): void;
15
- selectFields<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelect<E> | undefined, opts?: QuerySelectOptions): void;
16
- select<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelect<E> | undefined, opts?: QueryOptions): void;
15
+ selectFields<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelect<E> | QueryRaw[] | undefined, opts?: QuerySelectOptions): void;
16
+ select<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelect<E> | QueryRaw[] | undefined, opts?: QueryOptions): void;
17
17
  protected selectRelationFields<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelect<E> | undefined, opts?: {
18
18
  prefix?: string;
19
19
  }): void;
20
20
  protected selectRelationJoins<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelect<E> | undefined, opts?: {
21
21
  prefix?: string;
22
22
  }): void;
23
+ /**
24
+ * Iterates over joinable (11/m1) relations for a given select, resolving shared metadata.
25
+ * Used by both `selectRelationFields` and `selectRelationJoins` to avoid duplicated iteration logic.
26
+ */
27
+ private forEachJoinableRelation;
23
28
  where<E>(ctx: QueryContext, entity: Type<E>, where?: QueryWhere<E>, opts?: QueryWhereOptions): void;
24
29
  compare<E>(ctx: QueryContext, entity: Type<E>, key: string, val: unknown, opts?: QueryComparisonOptions): void;
25
30
  protected compareLogicalOperator<E>(ctx: QueryContext, entity: Type<E>, key: '$and' | '$or' | '$not' | '$nor', val: QueryWhereArray<E>, opts: QueryComparisonOptions): void;
@@ -69,16 +74,19 @@ export declare abstract class AbstractSqlDialect extends AbstractDialect impleme
69
74
  *
70
75
  * @returns resolved metadata or `undefined` if the key is not a JSON dot-notation path
71
76
  */
72
- protected resolveJsonDotPath<E>(meta: EntityMeta<E>, key: string): {
77
+ protected resolveJsonDotPath<E>(meta: EntityMeta<E>, key: string, prefix?: string): {
73
78
  root: string;
74
79
  jsonPath: string;
75
80
  config: JsonFieldConfig;
76
81
  } | undefined;
77
82
  /**
78
83
  * Compare a JSONB dot-notation path, e.g. `'settings.isArchived': { $ne: true }`.
79
- * The dialect's `getJsonFieldConfig` provides the SQL expression for accessing the nested JSON value.
84
+ * Receives a pre-resolved `resolveJsonDotPath` result to avoid redundant computation.
80
85
  */
81
- protected compareJsonPath<E>(ctx: QueryContext, entity: Type<E>, root: string, jsonPath: string, val: unknown, opts: QueryComparisonOptions): void;
86
+ protected compareJsonPath(ctx: QueryContext, resolved: {
87
+ jsonPath: string;
88
+ config: JsonFieldConfig;
89
+ }, val: unknown): void;
82
90
  /**
83
91
  * Returns a dialect-specific `JsonFieldConfig` for accessing a nested JSON path.
84
92
  * Dialects should override this to provide their specific JSON accessor syntax.
@@ -1 +1 @@
1
- {"version":3,"file":"abstractSqlDialect.d.ts","sourceRoot":"","sources":["../../src/dialect/abstractSqlDialect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"abstractSqlDialect.d.ts","sourceRoot":"","sources":["../../src/dialect/abstractSqlDialect.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { getMeta } from '../entity/index.js';
2
2
  import { QueryRaw, RAW_ALIAS, RAW_VALUE, } from '../type/index.js';
3
- import { buildSortMap, buldQueryWhereAsMap, escapeSqlId, fillOnFields, filterFieldKeys, filterRelationKeys, flatObject, getFieldCallbackValue, getFieldKeys, getKeys, hasKeys, isJsonType, isSelectingRelations, raw, } from '../util/index.js';
3
+ import { buildQueryWhereAsMap, buildSortMap, escapeSqlId, fillOnFields, filterFieldKeys, filterRelationKeys, flatObject, getFieldCallbackValue, getFieldKeys, getKeys, hasKeys, isJsonType, isSelectingRelations, raw, } from '../util/index.js';
4
4
  import { AbstractDialect } from './abstractDialect.js';
5
5
  import { SqlQueryContext } from './queryContext.js';
6
6
  export class AbstractSqlDialect extends AbstractDialect {
@@ -48,15 +48,18 @@ export class AbstractSqlDialect extends AbstractDialect {
48
48
  let selectArr;
49
49
  if (select) {
50
50
  if (Array.isArray(select)) {
51
+ // Internal-only path: raw SQL expressions passed as QueryRaw[]
51
52
  selectArr = select;
52
53
  }
53
54
  else {
54
- const selectPositive = getKeys(select).filter((it) => select[it]);
55
- selectArr = selectPositive.length
56
- ? selectPositive
57
- : getFieldKeys(meta.fields).filter((it) => !(it in select));
55
+ // Only field keys affect whitelist/exclusion mode; relation keys are additive
56
+ const fieldEntries = getKeys(select).filter((it) => it in meta.fields);
57
+ const positiveFields = fieldEntries.filter((it) => select[it]);
58
+ const negativeFields = fieldEntries.filter((it) => !select[it]);
59
+ selectArr = positiveFields.length
60
+ ? positiveFields
61
+ : getFieldKeys(meta.fields).filter((it) => !negativeFields.includes(it));
58
62
  }
59
- selectArr = selectArr.filter((it) => it instanceof QueryRaw || it in meta.fields);
60
63
  const id = meta.id;
61
64
  if (id && opts.prefix && !selectArr.includes(id)) {
62
65
  selectArr = [id, ...selectArr];
@@ -108,86 +111,30 @@ export class AbstractSqlDialect extends AbstractDialect {
108
111
  select(ctx, entity, select, opts = {}) {
109
112
  const meta = getMeta(entity);
110
113
  const tableName = this.resolveTableName(entity, meta);
111
- const prefix = (opts.prefix ?? (opts.autoPrefix || isSelectingRelations(meta, select))) ? tableName : undefined;
114
+ const mapSelect = Array.isArray(select) ? undefined : select;
115
+ const prefix = (opts.prefix ?? (opts.autoPrefix || isSelectingRelations(meta, mapSelect))) ? tableName : undefined;
112
116
  ctx.append('SELECT ');
113
117
  this.selectFields(ctx, entity, select, { prefix });
114
118
  // Add related fields BEFORE FROM clause
115
- this.selectRelationFields(ctx, entity, select, { prefix });
119
+ this.selectRelationFields(ctx, entity, mapSelect, { prefix });
116
120
  ctx.append(` FROM ${this.escapeId(tableName)}`);
117
121
  // Add JOINs AFTER FROM clause
118
- this.selectRelationJoins(ctx, entity, select, { prefix });
122
+ this.selectRelationJoins(ctx, entity, mapSelect, { prefix });
119
123
  }
120
124
  selectRelationFields(ctx, entity, select, opts = {}) {
121
- if (Array.isArray(select)) {
122
- return;
123
- }
124
- const meta = getMeta(entity);
125
- const tableName = this.resolveTableName(entity, meta);
126
- const relKeys = filterRelationKeys(meta, select);
127
- const isSelectArray = Array.isArray(select);
128
- const prefix = opts.prefix;
129
- for (const relKey of relKeys) {
130
- const relOpts = meta.relations[relKey];
131
- if (!relOpts)
132
- continue;
133
- if (relOpts.cardinality === '1m' || relOpts.cardinality === 'mm') {
134
- continue;
135
- }
136
- const isFirstLevel = prefix === tableName;
137
- const joinRelAlias = isFirstLevel ? relKey : prefix ? prefix + '.' + relKey : relKey;
138
- if (!relOpts.entity)
139
- continue;
140
- const relEntity = relOpts.entity();
141
- const relSelect = select[relKey];
142
- const relQuery = isSelectArray
143
- ? {}
144
- : Array.isArray(relSelect)
145
- ? { $select: relSelect }
146
- : (relSelect ?? {});
125
+ this.forEachJoinableRelation(entity, select, opts, (relEntity, relQuery, joinRelAlias) => {
147
126
  ctx.append(', ');
148
- this.selectFields(ctx, relEntity, relQuery.$select, {
149
- prefix: joinRelAlias,
150
- autoPrefixAlias: true,
151
- });
152
- // Recursively add nested relation fields
153
- this.selectRelationFields(ctx, relEntity, relQuery.$select, {
154
- prefix: joinRelAlias,
155
- });
156
- }
127
+ this.selectFields(ctx, relEntity, relQuery.$select, { prefix: joinRelAlias, autoPrefixAlias: true });
128
+ this.selectRelationFields(ctx, relEntity, relQuery.$select, { prefix: joinRelAlias });
129
+ });
157
130
  }
158
131
  selectRelationJoins(ctx, entity, select, opts = {}) {
159
- if (Array.isArray(select)) {
160
- return;
161
- }
162
- const meta = getMeta(entity);
163
- const tableName = this.resolveTableName(entity, meta);
164
- const relKeys = filterRelationKeys(meta, select);
165
- const isSelectArray = Array.isArray(select);
166
- const prefix = opts.prefix;
167
- for (const relKey of relKeys) {
168
- const relOpts = meta.relations[relKey];
169
- if (!relOpts)
170
- continue;
171
- if (relOpts.cardinality === '1m' || relOpts.cardinality === 'mm') {
172
- continue;
173
- }
174
- const isFirstLevel = prefix === tableName;
175
- const joinRelAlias = isFirstLevel ? relKey : prefix ? prefix + '.' + relKey : relKey;
176
- if (!relOpts.entity)
177
- continue;
178
- const relEntity = relOpts.entity();
179
- const relSelect = select[relKey];
180
- const relQuery = isSelectArray
181
- ? {}
182
- : Array.isArray(relSelect)
183
- ? { $select: relSelect }
184
- : (relSelect ?? {});
132
+ this.forEachJoinableRelation(entity, select, opts, (relEntity, relQuery, joinRelAlias, relOpts, meta, tableName, required) => {
185
133
  const relMeta = getMeta(relEntity);
186
134
  const relTableName = this.resolveTableName(relEntity, relMeta);
187
135
  const relEntityName = this.escapeId(relTableName);
188
- const relPath = prefix ? this.escapeId(prefix, true) : this.escapeId(tableName);
189
- const required = '$required';
190
- const joinType = relQuery[required] ? 'INNER' : 'LEFT';
136
+ const relPath = opts.prefix ? this.escapeId(opts.prefix, true) : this.escapeId(tableName);
137
+ const joinType = required ? 'INNER' : 'LEFT';
191
138
  const joinAlias = this.escapeId(joinRelAlias, true);
192
139
  ctx.append(` ${joinType} JOIN ${relEntityName} ${joinAlias} ON `);
193
140
  ctx.append((relOpts.references ?? [])
@@ -203,16 +150,47 @@ export class AbstractSqlDialect extends AbstractDialect {
203
150
  ctx.append(' AND ');
204
151
  this.where(ctx, relEntity, relQuery.$where, { prefix: joinRelAlias, clause: false });
205
152
  }
206
- // Recursively add nested relation JOINs
207
- this.selectRelationJoins(ctx, relEntity, relQuery.$select, {
208
- prefix: joinRelAlias,
209
- });
153
+ this.selectRelationJoins(ctx, relEntity, relQuery.$select, { prefix: joinRelAlias });
154
+ });
155
+ }
156
+ /**
157
+ * Iterates over joinable (11/m1) relations for a given select, resolving shared metadata.
158
+ * Used by both `selectRelationFields` and `selectRelationJoins` to avoid duplicated iteration logic.
159
+ */
160
+ forEachJoinableRelation(entity, select, opts, callback) {
161
+ if (!select)
162
+ return;
163
+ const meta = getMeta(entity);
164
+ const tableName = this.resolveTableName(entity, meta);
165
+ const relKeys = filterRelationKeys(meta, select);
166
+ const prefix = opts.prefix;
167
+ for (const relKey of relKeys) {
168
+ const relOpts = meta.relations[relKey];
169
+ if (!relOpts || relOpts.cardinality === '1m' || relOpts.cardinality === 'mm' || !relOpts.entity)
170
+ continue;
171
+ const isFirstLevel = prefix === tableName;
172
+ const joinRelAlias = isFirstLevel ? relKey : prefix ? `${prefix}.${relKey}` : relKey;
173
+ const relEntity = relOpts.entity();
174
+ const relSelect = select?.[relKey];
175
+ let relQuery;
176
+ let required = false;
177
+ if (isRelationSelectQuery(relSelect)) {
178
+ relQuery = relSelect;
179
+ required = relSelect.$required === true;
180
+ }
181
+ else if (Array.isArray(relSelect)) {
182
+ relQuery = { $select: relSelect };
183
+ }
184
+ else {
185
+ relQuery = {};
186
+ }
187
+ callback(relEntity, relQuery, joinRelAlias, relOpts, meta, tableName, required);
210
188
  }
211
189
  }
212
190
  where(ctx, entity, where = {}, opts = {}) {
213
191
  const meta = getMeta(entity);
214
192
  const { usePrecedence, clause = 'WHERE', softDelete } = opts;
215
- where = buldQueryWhereAsMap(meta, where);
193
+ where = buildQueryWhereAsMap(meta, where);
216
194
  if (meta.softDelete &&
217
195
  (softDelete || softDelete === undefined) &&
218
196
  !where[meta.softDelete]) {
@@ -283,9 +261,9 @@ export class AbstractSqlDialect extends AbstractDialect {
283
261
  }
284
262
  // Detect JSONB dot-notation: 'column.path' where column is a registered JSON/JSONB field
285
263
  const keyStr = key;
286
- const jsonDot = this.resolveJsonDotPath(meta, keyStr);
264
+ const jsonDot = this.resolveJsonDotPath(meta, keyStr, opts.prefix);
287
265
  if (jsonDot) {
288
- this.compareJsonPath(ctx, entity, jsonDot.root, jsonDot.jsonPath, val, opts);
266
+ this.compareJsonPath(ctx, jsonDot, val);
289
267
  return;
290
268
  }
291
269
  // Detect relation filtering: key is a known relation with 'mm' or '1m' cardinality
@@ -603,7 +581,7 @@ export class AbstractSqlDialect extends AbstractDialect {
603
581
  count(ctx, entity, q, opts) {
604
582
  const search = { ...q };
605
583
  delete search.$sort;
606
- this.select(ctx, entity, [raw('COUNT(*)', 'count')], undefined);
584
+ this.select(ctx, entity, [raw('COUNT(*)', 'count')]);
607
585
  this.search(ctx, entity, search, opts);
608
586
  }
609
587
  find(ctx, entity, q = {}, opts) {
@@ -825,7 +803,7 @@ export class AbstractSqlDialect extends AbstractDialect {
825
803
  *
826
804
  * @returns resolved metadata or `undefined` if the key is not a JSON dot-notation path
827
805
  */
828
- resolveJsonDotPath(meta, key) {
806
+ resolveJsonDotPath(meta, key, prefix) {
829
807
  const dotIndex = key.indexOf('.');
830
808
  if (dotIndex <= 0) {
831
809
  return undefined;
@@ -837,20 +815,16 @@ export class AbstractSqlDialect extends AbstractDialect {
837
815
  }
838
816
  const jsonPath = key.slice(dotIndex + 1);
839
817
  const colName = this.resolveColumnName(root, field);
840
- const escapedCol = this.escapeId(colName);
818
+ const escapedCol = (prefix ? this.escapeId(prefix, true, true) : '') + this.escapeId(colName);
841
819
  const config = this.getJsonFieldConfig(escapedCol, jsonPath);
842
820
  return { root, jsonPath, config };
843
821
  }
844
822
  /**
845
823
  * Compare a JSONB dot-notation path, e.g. `'settings.isArchived': { $ne: true }`.
846
- * The dialect's `getJsonFieldConfig` provides the SQL expression for accessing the nested JSON value.
824
+ * Receives a pre-resolved `resolveJsonDotPath` result to avoid redundant computation.
847
825
  */
848
- compareJsonPath(ctx, entity, root, jsonPath, val, opts) {
849
- const meta = getMeta(entity);
850
- const field = meta.fields[root];
851
- const columnName = this.resolveColumnName(root, field);
852
- const escapedColumn = (opts.prefix ? this.escapeId(opts.prefix, true, true) : '') + this.escapeId(columnName);
853
- const config = this.getJsonFieldConfig(escapedColumn, jsonPath);
826
+ compareJsonPath(ctx, resolved, val) {
827
+ const { jsonPath, config } = resolved;
854
828
  const value = this.normalizeWhereValue(val);
855
829
  const operators = getKeys(value);
856
830
  if (operators.length > 1) {
@@ -964,4 +938,10 @@ export class AbstractSqlDialect extends AbstractDialect {
964
938
  ctx.append(')');
965
939
  }
966
940
  }
941
+ /**
942
+ * Type guard: narrows a relation select value to a query object (with optional `$required`).
943
+ */
944
+ function isRelationSelectQuery(val) {
945
+ return val !== null && typeof val === 'object' && !Array.isArray(val);
946
+ }
967
947
  //# sourceMappingURL=abstractSqlDialect.js.map