uql-orm 0.19.0 → 0.20.1

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 (120) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +1 -1
  3. package/dist/browser/uql-browser.min.js +2 -2
  4. package/dist/browser/uql-browser.min.js.map +3 -3
  5. package/dist/bunSql/bunSqlCockroachDialect.d.ts +1 -1
  6. package/dist/bunSql/bunSqlCockroachDialect.js +1 -1
  7. package/dist/dialect/abstractSqlDialect.d.ts +130 -58
  8. package/dist/dialect/abstractSqlDialect.d.ts.map +1 -1
  9. package/dist/dialect/abstractSqlDialect.js +226 -178
  10. package/dist/dialect/abstractSqlDialect.js.map +1 -1
  11. package/dist/dialect/jsonArrayElemMatchUtils.d.ts +5 -6
  12. package/dist/dialect/jsonArrayElemMatchUtils.d.ts.map +1 -1
  13. package/dist/dialect/jsonArrayElemMatchUtils.js +9 -19
  14. package/dist/dialect/jsonArrayElemMatchUtils.js.map +1 -1
  15. package/dist/dialect/jsonSql.d.ts +44 -0
  16. package/dist/dialect/jsonSql.d.ts.map +1 -0
  17. package/dist/dialect/jsonSql.js +57 -0
  18. package/dist/dialect/jsonSql.js.map +1 -0
  19. package/dist/dialect/mysqlLikeSqlDialect.d.ts +42 -2
  20. package/dist/dialect/mysqlLikeSqlDialect.d.ts.map +1 -1
  21. package/dist/dialect/mysqlLikeSqlDialect.js +73 -22
  22. package/dist/dialect/mysqlLikeSqlDialect.js.map +1 -1
  23. package/dist/dialect/pgLikeSqlDialect.d.ts +28 -10
  24. package/dist/dialect/pgLikeSqlDialect.d.ts.map +1 -1
  25. package/dist/dialect/pgLikeSqlDialect.js +56 -49
  26. package/dist/dialect/pgLikeSqlDialect.js.map +1 -1
  27. package/dist/dialect/queryContext.d.ts +13 -1
  28. package/dist/dialect/queryContext.d.ts.map +1 -1
  29. package/dist/dialect/queryContext.js +17 -2
  30. package/dist/dialect/queryContext.js.map +1 -1
  31. package/dist/dialect/vectorSqlDialect.d.ts +54 -0
  32. package/dist/dialect/vectorSqlDialect.d.ts.map +1 -0
  33. package/dist/dialect/vectorSqlDialect.js +70 -0
  34. package/dist/dialect/vectorSqlDialect.js.map +1 -0
  35. package/dist/entity/decorator/index-decorator.d.ts +6 -13
  36. package/dist/entity/decorator/index-decorator.d.ts.map +1 -1
  37. package/dist/entity/decorator/index-decorator.js.map +1 -1
  38. package/dist/http/handler.d.ts +5 -1
  39. package/dist/http/handler.d.ts.map +1 -1
  40. package/dist/http/handler.js.map +1 -1
  41. package/dist/maria/mariaDialect.d.ts +15 -4
  42. package/dist/maria/mariaDialect.d.ts.map +1 -1
  43. package/dist/maria/mariaDialect.js +25 -13
  44. package/dist/maria/mariaDialect.js.map +1 -1
  45. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +1 -1
  46. package/dist/migrate/generator/mongoSchemaGenerator.d.ts.map +1 -1
  47. package/dist/mongo/mongoDialect.d.ts +27 -6
  48. package/dist/mongo/mongoDialect.d.ts.map +1 -1
  49. package/dist/mongo/mongoDialect.js +107 -14
  50. package/dist/mongo/mongoDialect.js.map +1 -1
  51. package/dist/mongo/mongodbQuerier.d.ts.map +1 -1
  52. package/dist/mongo/mongodbQuerier.js +5 -4
  53. package/dist/mongo/mongodbQuerier.js.map +1 -1
  54. package/dist/mysql/mysqlDialect.d.ts +0 -1
  55. package/dist/mysql/mysqlDialect.d.ts.map +1 -1
  56. package/dist/mysql/mysqlDialect.js +0 -1
  57. package/dist/mysql/mysqlDialect.js.map +1 -1
  58. package/dist/postgres/postgresWireDriverCapabilities.d.ts +1 -1
  59. package/dist/postgres/postgresWireDriverCapabilities.js +1 -1
  60. package/dist/schema/schemaAST.d.ts.map +1 -1
  61. package/dist/schema/schemaAST.js +7 -19
  62. package/dist/schema/schemaAST.js.map +1 -1
  63. package/dist/schema/types.d.ts +1 -1
  64. package/dist/sqlite/sqliteDialect.d.ts +28 -8
  65. package/dist/sqlite/sqliteDialect.d.ts.map +1 -1
  66. package/dist/sqlite/sqliteDialect.js +65 -80
  67. package/dist/sqlite/sqliteDialect.js.map +1 -1
  68. package/dist/type/dialect.d.ts +199 -0
  69. package/dist/type/dialect.d.ts.map +1 -0
  70. package/dist/type/dialect.js +2 -0
  71. package/dist/type/dialect.js.map +1 -0
  72. package/dist/type/entity.d.ts +64 -43
  73. package/dist/type/entity.d.ts.map +1 -1
  74. package/dist/type/entity.js.map +1 -1
  75. package/dist/type/index.d.ts +5 -0
  76. package/dist/type/index.d.ts.map +1 -1
  77. package/dist/type/index.js +5 -0
  78. package/dist/type/index.js.map +1 -1
  79. package/dist/type/querier.d.ts +3 -5
  80. package/dist/type/querier.d.ts.map +1 -1
  81. package/dist/type/querier.js.map +1 -1
  82. package/dist/type/query.d.ts +5 -711
  83. package/dist/type/query.d.ts.map +1 -1
  84. package/dist/type/query.js +1 -51
  85. package/dist/type/query.js.map +1 -1
  86. package/dist/type/queryAggregate.d.ts +191 -0
  87. package/dist/type/queryAggregate.d.ts.map +1 -0
  88. package/dist/type/queryAggregate.js +39 -0
  89. package/dist/type/queryAggregate.js.map +1 -0
  90. package/dist/type/queryRaw.d.ts +35 -0
  91. package/dist/type/queryRaw.d.ts.map +1 -0
  92. package/dist/type/queryRaw.js +11 -0
  93. package/dist/type/queryRaw.js.map +1 -0
  94. package/dist/type/queryWhere.d.ts +271 -0
  95. package/dist/type/queryWhere.d.ts.map +1 -0
  96. package/dist/type/queryWhere.js +2 -0
  97. package/dist/type/queryWhere.js.map +1 -0
  98. package/dist/type/universalQuerier.d.ts +2 -1
  99. package/dist/type/universalQuerier.d.ts.map +1 -1
  100. package/dist/type/utility.d.ts +8 -1
  101. package/dist/type/utility.d.ts.map +1 -1
  102. package/dist/type/vector.d.ts +55 -0
  103. package/dist/type/vector.d.ts.map +1 -0
  104. package/dist/type/vector.js +2 -0
  105. package/dist/type/vector.js.map +1 -0
  106. package/dist/util/ansiSqlLiteral.d.ts +2 -0
  107. package/dist/util/ansiSqlLiteral.d.ts.map +1 -1
  108. package/dist/util/ansiSqlLiteral.js +5 -1
  109. package/dist/util/ansiSqlLiteral.js.map +1 -1
  110. package/dist/util/dialect.util.d.ts +5 -5
  111. package/dist/util/dialect.util.d.ts.map +1 -1
  112. package/dist/util/dialect.util.js +15 -10
  113. package/dist/util/dialect.util.js.map +1 -1
  114. package/dist/util/object.util.d.ts +12 -1
  115. package/dist/util/object.util.d.ts.map +1 -1
  116. package/dist/util/object.util.js +18 -0
  117. package/dist/util/object.util.js.map +1 -1
  118. package/dist/util/relationQuery.util.js +1 -1
  119. package/dist/util/relationQuery.util.js.map +1 -1
  120. package/package.json +2 -2
@@ -1,5 +1,8 @@
1
- import type { FieldKey, IdValue, JsonFieldPaths, JsonFieldPathValue, RelationKey, UpdatePayload } from './entity.js';
2
- import type { BooleanLike, ExpandScalar, PrimaryKey, QueryComparableScalar, Scalar, Type, Unpacked } from './utility.js';
1
+ import type { FieldKey, JsonFieldPaths, RelationKey } from './entity.js';
2
+ import type { QueryRaw } from './queryRaw.js';
3
+ import type { QueryWhere } from './queryWhere.js';
4
+ import type { BooleanLike, PrimaryKey, Unpacked } from './utility.js';
5
+ import type { QueryVectorSearch } from './vector.js';
3
6
  export type QueryOptions = {
4
7
  /**
5
8
  * Toggle named entity filters for this query. `false` disables all filters;
@@ -65,267 +68,6 @@ export type QueryConflictPaths<E> = {
65
68
  export type QueryPopulateRelationOptions<E> = (E extends unknown[] ? Query<Unpacked<E>> : QueryUnique<Unpacked<E>>) & {
66
69
  $required?: boolean;
67
70
  };
68
- /**
69
- * options for full-text-search operator.
70
- */
71
- export type QueryTextSearchOptions<E> = {
72
- /**
73
- * text to search for.
74
- */
75
- $value: string;
76
- /**
77
- * list of fields to search on.
78
- */
79
- $fields?: FieldKey<E>[];
80
- };
81
- /**
82
- * comparison by fields.
83
- */
84
- export type QueryWhereFieldMap<E> = {
85
- [K in FieldKey<E>]?: QueryWhereFieldValue<E[K]>;
86
- };
87
- /**
88
- * Field comparison, JSON dot-path access, and relation filtering - all fully typed.
89
- * JSON dot-paths are restricted to real JSON fields, and typed payloads type each path's value
90
- * (untyped `Json` payloads accept any `field.suffix` path with a permissive value). Relations are
91
- * filtered via nested typed objects; dotted relation paths are not supported (the dialects throw
92
- * for non-JSON dotted keys).
93
- */
94
- export type QueryWhereMap<E> = QueryWhereFieldMap<E> & QueryWhereRootOperator<E> & {
95
- [P in JsonFieldPaths<E>]?: QueryWhereFieldValue<JsonFieldPathValue<E, P>>;
96
- } & {
97
- [K in RelationKey<E>]?: QueryWhereMap<Unpacked<NonNullable<E[K]>>> | QueryRelationSizeFilter;
98
- };
99
- /**
100
- * Filter a to-many relation by its row count.
101
- * @example { users: { $size: 2 } }
102
- * @example { users: { $size: { $gte: 2 } } }
103
- */
104
- export type QueryRelationSizeFilter = {
105
- readonly $size: number | QuerySizeComparisonOps;
106
- };
107
- export type QueryWhereRootOperator<E> = {
108
- /**
109
- * joins query clauses with a logical `AND`, returns records that match all the clauses.
110
- */
111
- $and?: QueryWhereArray<E>;
112
- /**
113
- * joins query clauses with a logical `OR`, returns records that match any of the clauses.
114
- */
115
- $or?: QueryWhereArray<E>;
116
- /**
117
- * joins query clauses with a logical `AND`, returns records that do not match all the clauses.
118
- * @see {@link QueryWhereFieldOperatorMap.$not} for per-field negation.
119
- */
120
- $not?: QueryWhereArray<E>;
121
- /**
122
- * joins query clauses with a logical `OR`, returns records that do not match any of the clauses.
123
- */
124
- $nor?: QueryWhereArray<E>;
125
- /**
126
- * whether the specified fields match against a full-text search of the given string.
127
- */
128
- $text?: QueryTextSearchOptions<E>;
129
- /**
130
- * whether the record exists in the given sub-query.
131
- */
132
- $exists?: QueryRaw;
133
- /**
134
- * whether the record does not exists in the given sub-query.
135
- */
136
- $nexists?: QueryRaw;
137
- };
138
- /**
139
- * Per-field negation operators. `Pick`'s constraint ties this back to
140
- * {@link QueryWhereRootOperator} so a rename there breaks this union at compile time.
141
- */
142
- export type QueryNegateOp = keyof Pick<QueryWhereRootOperator<unknown>, '$not' | '$nor'>;
143
- /**
144
- * Comparison operators accepted by `$size` for range queries: {@link QueryHavingOp} plus `$between`.
145
- * Strips `null` from picked operators since array size is always numeric.
146
- */
147
- export type QuerySizeComparisonOps = {
148
- [K in QueryHavingOp | '$between']?: NonNullable<QueryWhereFieldOperatorMap<number>[K]>;
149
- };
150
- export type QueryWhereFieldOperatorMap<T> = {
151
- /**
152
- * whether a value is equal to the given value.
153
- */
154
- $eq?: ExpandScalar<T> | null;
155
- /**
156
- * whether a value is not equal to the given value.
157
- */
158
- $ne?: ExpandScalar<T> | null;
159
- /**
160
- * negates the given comparison for a single field.
161
- * @see {@link QueryWhereRootOperator.$not} for root-level clause negation.
162
- */
163
- $not?: QueryWhereFieldValue<T>;
164
- /**
165
- * whether a value is less than the given value.
166
- */
167
- $lt?: ExpandScalar<T>;
168
- /**
169
- * whether a value is less than or equal to the given value.
170
- */
171
- $lte?: ExpandScalar<T>;
172
- /**
173
- * whether a value is greater than the given value.
174
- */
175
- $gt?: ExpandScalar<T>;
176
- /**
177
- * whether a value is greater than or equal to the given value.
178
- */
179
- $gte?: ExpandScalar<T>;
180
- /**
181
- * whether a value is between two values (inclusive). Shorthand for $gte + $lte.
182
- * @example { age: { $between: [18, 65] } }
183
- */
184
- $between?: [ExpandScalar<T>, ExpandScalar<T>];
185
- /**
186
- * whether a string begins with the given string (case sensitive).
187
- */
188
- $startsWith?: string;
189
- /**
190
- * whether a string begins with the given string (case insensitive).
191
- */
192
- $istartsWith?: string;
193
- /**
194
- * whether a string ends with the given string (case sensitive).
195
- */
196
- $endsWith?: string;
197
- /**
198
- * whether a string ends with the given string (case insensitive).
199
- */
200
- $iendsWith?: string;
201
- /**
202
- * whether a string is contained within the given string (case sensitive).
203
- */
204
- $includes?: string;
205
- /**
206
- * whether a string is contained within the given string (case insensitive).
207
- */
208
- $iincludes?: string;
209
- /**
210
- * whether a string fulfills the given pattern (case sensitive).
211
- */
212
- $like?: string;
213
- /**
214
- * whether a string fulfills the given pattern (case insensitive).
215
- */
216
- $ilike?: string;
217
- /**
218
- * whether a string matches the given regular expression.
219
- */
220
- $regex?: string;
221
- /**
222
- * whether a value matches any of the given values.
223
- */
224
- $in?: ExpandScalar<T>[];
225
- /**
226
- * whether a value does not match any of the given values.
227
- */
228
- $nin?: ExpandScalar<T>[];
229
- /**
230
- * whether a value is null.
231
- * @example { deletedAt: { $isNull: true } }
232
- */
233
- $isNull?: boolean;
234
- /**
235
- * whether a value is not null.
236
- * @example { email: { $isNotNull: true } }
237
- */
238
- $isNotNull?: boolean;
239
- /**
240
- * whether an array contains all the specified values.
241
- * @example { tags: { $all: ['typescript', 'orm'] } }
242
- */
243
- $all?: unknown extends T ? unknown[] : NonNullable<T> extends readonly (infer U)[] ? ExpandScalar<U>[] : never;
244
- /**
245
- * whether an array has the specified length.
246
- * Accepts a number for exact match, or a comparison operator object for range queries.
247
- * @example { roles: { $size: 3 } }
248
- * @example { roles: { $size: { $gte: 2 } } }
249
- * @example { roles: { $size: { $gt: 0, $lte: 5 } } }
250
- */
251
- $size?: number | QuerySizeComparisonOps;
252
- /**
253
- * whether an array contains at least one element matching all specified conditions.
254
- * Each key of the element type maps to a value or an operator map for that key.
255
- * @example { addresses: { $elemMatch: { city: 'NYC', zip: '10001' } } }
256
- * @example { addresses: { $elemMatch: { city: { $like: 'New%' } } } }
257
- */
258
- $elemMatch?: unknown extends T ? QueryWhereElemMatch<unknown> : NonNullable<T> extends readonly (infer U)[] ? QueryWhereElemMatch<U> : never;
259
- };
260
- /**
261
- * Element-level conditions for `$elemMatch`. Scalar elements take an operator map for the element
262
- * itself (`{ tags: { $elemMatch: { $startsWith: 'ad' } } }`); object elements map each key to a
263
- * field comparison. An untyped element (`unknown`) accepts any keys but still requires the
264
- * object-of-conditions shape (a bare scalar is rejected).
265
- */
266
- export type QueryWhereElemMatch<U> = unknown extends U ? {
267
- [key: string]: QueryWhereFieldValue<unknown> | undefined;
268
- } : NonNullable<U> extends Scalar ? QueryWhereFieldOperators<NonNullable<U>> : {
269
- [K in keyof NonNullable<U>]?: QueryWhereFieldValue<NonNullable<U>[K]>;
270
- };
271
- /**
272
- * Simple relational comparison operators. `Pick`'s constraint ties this back to
273
- * {@link QueryWhereFieldOperatorMap} so a rename there breaks this union at compile time.
274
- */
275
- export type QueryCompareOp = keyof Pick<QueryWhereFieldOperatorMap<unknown>, '$gt' | '$gte' | '$lt' | '$lte'>;
276
- /**
277
- * String pattern-matching operators. `Pick`'s constraint ties this back to
278
- * {@link QueryWhereFieldOperatorMap} so a rename there breaks this union at compile time.
279
- */
280
- export type QueryLikeOp = keyof Pick<QueryWhereFieldOperatorMap<unknown>, '$startsWith' | '$istartsWith' | '$endsWith' | '$iendsWith' | '$includes' | '$iincludes' | '$like' | '$ilike'>;
281
- /**
282
- * `HAVING` clause operators: {@link QueryCompareOp} plus `$eq`/`$ne`. `Pick`'s constraint ties the
283
- * latter back to {@link QueryWhereFieldOperatorMap} so a rename there breaks this union at compile time.
284
- */
285
- export type QueryHavingOp = QueryCompareOp | keyof Pick<QueryWhereFieldOperatorMap<number>, '$eq' | '$ne'>;
286
- /**
287
- * String pattern-matching operators: {@link QueryLikeOp} plus `$regex`. `Pick`'s constraint ties
288
- * the latter back to {@link QueryWhereFieldOperatorMap} so a rename there breaks this union.
289
- */
290
- type QueryStringOp = QueryLikeOp | keyof Pick<QueryWhereFieldOperatorMap<unknown>, '$regex'>;
291
- /**
292
- * Array-only operators. `Pick`'s constraint ties this back to {@link QueryWhereFieldOperatorMap}
293
- * so a rename there breaks this union at compile time.
294
- */
295
- type QueryArrayOp = keyof Pick<QueryWhereFieldOperatorMap<unknown>, '$all' | '$size' | '$elemMatch'>;
296
- /**
297
- * Ordering operators: {@link QueryCompareOp} plus `$between`.
298
- */
299
- type QueryOrderedOp = QueryCompareOp | keyof Pick<QueryWhereFieldOperatorMap<unknown>, '$between'>;
300
- /**
301
- * Operators applicable to every field type: equality, membership, negation, and null checks.
302
- */
303
- type QueryCommonOp = Exclude<keyof QueryWhereFieldOperatorMap<unknown>, QueryStringOp | QueryArrayOp | QueryOrderedOp>;
304
- /**
305
- * Operator keys applicable to a field of type `T`. Brackets prevent union distribution so an
306
- * optional field (`string | undefined`) or a literal union (`'a' | 'b'`) gates as one type.
307
- */
308
- type QueryAllowedOp<T> = QueryCommonOp | ([NonNullable<T>] extends [QueryComparableScalar] ? QueryOrderedOp : never) | ([NonNullable<T>] extends [string] ? QueryStringOp : never) | ([NonNullable<T>] extends [readonly unknown[]] ? QueryArrayOp : never);
309
- /**
310
- * Operators applicable to a field of type `T`: string operators require string fields, ordering
311
- * operators comparable fields, array operators array fields. `unknown` stays fully permissive
312
- * (untyped JSON dot-paths, erased dialect shapes).
313
- */
314
- export type QueryWhereFieldOperators<T> = unknown extends T ? QueryWhereFieldOperatorMap<T> : Pick<QueryWhereFieldOperatorMap<T>, QueryAllowedOp<T>>;
315
- /**
316
- * Value for a field comparison. A bare array is an implicit `$in` for scalar fields only:
317
- * on array-typed fields (e.g. a vector `number[]`) an array of arrays is ambiguous, so
318
- * membership there requires an explicit operator.
319
- */
320
- export type QueryWhereFieldValue<T> = T | ([NonNullable<T>] extends [readonly unknown[]] ? never : T[]) | QueryWhereFieldOperators<T> | QueryRaw;
321
- /**
322
- * query filter array - used for `$and`, `$or`, `$not`, `$nor` operators.
323
- */
324
- export type QueryWhereArray<E> = (QueryWhereMap<E> | QueryRaw)[];
325
- /**
326
- * query filter.
327
- */
328
- export type QueryWhere<E> = IdValue<E> | IdValue<E>[] | QueryWhereMap<E> | QueryWhereArray<E> | QueryRaw;
329
71
  /**
330
72
  * Ambient per-request context (e.g. `{ tenantId, userId, roles }`) resolved by parameterized
331
73
  * filters. Set with `withContext(ctx, cb)`. It's an `interface` (not a type alias) so you can type
@@ -365,56 +107,14 @@ export type FilterOptions<E = unknown> = {
365
107
  /** What to do when the condition returns `undefined`. Defaults to `skip`, or `throw` for `security`. */
366
108
  readonly onMissing?: FilterOnMissing;
367
109
  };
368
- /**
369
- * Resolved filter metadata stored on `EntityMeta.filters`.
370
- */
371
- export type FilterMeta<E = unknown> = FilterOptions<E>;
372
110
  /**
373
111
  * direction for the sort.
374
112
  */
375
113
  export type QuerySortDirection = -1 | 1 | 'asc' | 'desc';
376
- /**
377
- * Distance metrics supported by vector similarity search.
378
- * - `cosine` - best for text/LLM embeddings (default)
379
- * - `l2` - Euclidean distance
380
- * - `inner` - inner (dot) product
381
- * - `l1` - Manhattan distance
382
- * - `hamming` - for binary vectors
383
- */
384
- export type VectorDistance = 'cosine' | 'l2' | 'inner' | 'l1' | 'hamming';
385
- /**
386
- * Vector similarity search options - used inside `$sort` on vector fields.
387
- *
388
- * @example
389
- * ```ts
390
- * querier.findMany(Article, {
391
- * $sort: { embedding: { $vector: queryVec } },
392
- * $limit: 10,
393
- * });
394
- * ```
395
- */
396
- export interface QueryVectorSearch {
397
- /** The query vector to compare against. */
398
- readonly $vector: readonly number[];
399
- /** Distance metric. Overrides entity-level default. Falls back to `'cosine'`. */
400
- readonly $distance?: VectorDistance;
401
- /** Project the computed distance as a named field in the result. */
402
- readonly $project?: string;
403
- }
404
114
  /**
405
115
  * Accepted value for a field in `$sort` - either a direction or a vector similarity search.
406
116
  */
407
117
  export type QuerySortValue = QuerySortDirection | QueryVectorSearch;
408
- /**
409
- * Augments an entity with the distance field projected by a vector-search `$sort.$project`. The
410
- * find methods return the plain entity, so annotate the result with this when you project a score:
411
- * ```ts
412
- * const results = (await querier.findMany(Article, {
413
- * $sort: { embedding: { $vector: queryVec, $project: 'similarity' } },
414
- * })) as WithDistance<Article, 'similarity'>[];
415
- * ```
416
- */
417
- export type WithDistance<E, K extends string = '_distance'> = E & Record<K, number>;
418
118
  /**
419
119
  * sort by map - supports field keys, JSON dot-notation paths (restricted to real JSON fields,
420
120
  * like `QueryWhereMap`), relation sort via nested objects, and vector similarity search on
@@ -487,15 +187,6 @@ export type QueryOne<E> = Omit<Query<E>, '$limit'>;
487
187
  * options to get an unique record.
488
188
  */
489
189
  export type QueryUnique<E> = Pick<QueryOne<E>, '$select' | '$exclude' | '$populate' | '$where'>;
490
- /**
491
- * Maps the offending keys to `never`, turning an excess key into a compile error; resolves to
492
- * `unknown` (an inert intersection member) when there are none. Used by `aggregate`'s `$group`,
493
- * which is captured as a generic (a bare generic skips excess-property checking). The find methods
494
- * don't need this: they take concrete `Query<E>` params, so TypeScript's native excess-property
495
- * checking rejects stray keys directly.
496
- * @internal
497
- */
498
- type Reject<K> = [K] extends [never] ? unknown : Record<K & string, never>;
499
190
  /**
500
191
  * stringified query.
501
192
  */
@@ -526,401 +217,4 @@ export type QueryUpdateResult = {
526
217
  */
527
218
  created?: boolean;
528
219
  };
529
- /**
530
- * options for the `raw` function.
531
- */
532
- export type QueryRawFnOptions = {
533
- /**
534
- * the current dialect.
535
- */
536
- dialect?: QueryDialect;
537
- /**
538
- * the prefix.
539
- */
540
- prefix?: string;
541
- /**
542
- * the escaped prefix.
543
- */
544
- escapedPrefix?: string;
545
- /**
546
- * the query context.
547
- */
548
- ctx?: QueryContext;
549
- };
550
- /**
551
- * a `raw` function
552
- */
553
- export type QueryRawFn = (opts?: QueryRawFnOptions) => void | Scalar;
554
- export declare const RAW_VALUE: unique symbol;
555
- export declare const RAW_ALIAS: unique symbol;
556
- export declare class QueryRaw {
557
- readonly [RAW_VALUE]: Scalar | QueryRawFn;
558
- readonly [RAW_ALIAS]?: string;
559
- constructor(value: Scalar | QueryRawFn, alias?: string);
560
- }
561
- /**
562
- * comparison options.
563
- */
564
- export type QueryComparisonOptions = QueryOptions & {
565
- /**
566
- * use precedence for the comparison or not.
567
- */
568
- usePrecedence?: boolean;
569
- };
570
- /**
571
- * query filter options.
572
- */
573
- export type QueryWhereOptions = QueryComparisonOptions & {
574
- /**
575
- * clause to be used in the filter.
576
- */
577
- clause?: 'WHERE' | 'AND' | false;
578
- };
579
- export interface QueryContext {
580
- append(sql: string): this;
581
- addValue(value: unknown): this;
582
- pushValue(...values: unknown[]): this;
583
- readonly sql: string;
584
- readonly values: unknown[];
585
- }
586
- /**
587
- * Capabilities of the database driver (transport layer).
588
- */
589
- export interface DriverCapabilities {
590
- /**
591
- * Whether JSON bind parameters are cast via text first (`($n::text)::jsonb`).
592
- * Bun SQL PostgreSQL uses this for reliable jsonb merge/push; `pg` does not.
593
- */
594
- readonly explicitJsonCast: boolean;
595
- /**
596
- * Whether the driver natively supports JS arrays for the underlying database type.
597
- * `PgDialect` keeps this `true` for node-postgres; Bun SQL PostgreSQL uses `false` and
598
- * `toPgArray` string literals instead.
599
- */
600
- readonly nativeArrays: boolean;
601
- /** Whether the dialect natively supports the JSONB binary JSON type (Postgres/CockroachDB). */
602
- readonly supportsJsonb: boolean;
603
- }
604
- /**
605
- * How a dialect surfaces the IDs generated by an INSERT statement:
606
- * - `'returning'`: the statement itself returns one row per inserted record (`RETURNING`,
607
- * or MongoDB's `insertedIds`), so IDs are exact for every row.
608
- * - `'firstId'`: the driver header only exposes the first generated ID (MySQL `insertId`);
609
- * the remaining IDs are inferred by incrementing it.
610
- * - `'lastId'`: the driver header only exposes the last generated ID (SQLite `lastInsertRowid`);
611
- * the remaining IDs are inferred backwards from it.
612
- */
613
- export type InsertIdSource = 'returning' | 'firstId' | 'lastId';
614
- /**
615
- * Features of the database engine (SQL syntax layer).
616
- */
617
- export interface EngineFeatures {
618
- readonly ifNotExists: boolean;
619
- readonly indexIfNotExists: boolean;
620
- readonly dropTableCascade: boolean;
621
- readonly renameColumn: boolean;
622
- readonly foreignKeyAlter: boolean;
623
- /** Whether the dialect supports inline COMMENT on columns (MySQL/MariaDB). */
624
- readonly columnComment: boolean;
625
- /**
626
- * How vector indexes are emitted: inline in CREATE TABLE (MySQL/MariaDB), a standalone
627
- * `CREATE INDEX ... USING <type> (col opclass)` (Postgres/SQLite), or a standalone
628
- * `CREATE VECTOR INDEX (col opclass)` with no access-method keyword (CockroachDB's native type).
629
- */
630
- readonly vectorIndexStyle: 'inline' | 'create' | 'native';
631
- /** Whether the dialect requires/allows (n) length constraints on vector types. */
632
- readonly vectorSupportsLength: boolean;
633
- /** Whether the dialect natively supports the TIMESTAMPTZ alias/type. */
634
- readonly supportsTimestamptz: boolean;
635
- /** Whether the dialect defaults to TEXT for strings when no length is specified (e.g. Postgres). */
636
- readonly defaultStringAsText: boolean;
637
- }
638
- export interface DialectFeatures extends EngineFeatures, DriverCapabilities {
639
- }
640
- export interface QueryDialect {
641
- /**
642
- * The dialect features.
643
- */
644
- readonly features: DialectFeatures;
645
- /**
646
- * obtains the records matching the given search parameters.
647
- * @param ctx the query context
648
- * @param entity the target entity
649
- * @param q the criteria options
650
- * @param opts the query options
651
- */
652
- find<E>(ctx: QueryContext, entity: Type<E>, q: Query<E>, opts?: QueryOptions): void;
653
- /**
654
- * counts the number of records matching the given search parameters.
655
- * @param ctx the query context
656
- * @param entity the target entity
657
- * @param q the criteria options
658
- * @param opts the query options
659
- */
660
- count<E>(ctx: QueryContext, entity: Type<E>, q: QuerySearch<E>, opts?: QueryOptions): void;
661
- /**
662
- * insert records.
663
- * @param ctx the query context
664
- * @param entity the target entity
665
- * @param payload the payload
666
- * @param opts the query options
667
- */
668
- insert<E>(ctx: QueryContext, entity: Type<E>, payload: E | E[], opts?: QueryOptions): void;
669
- /**
670
- * update records.
671
- * @param ctx the query context
672
- * @param entity the target entity
673
- * @param q the criteria options
674
- * @param payload
675
- * @param opts the query options
676
- */
677
- update<E>(ctx: QueryContext, entity: Type<E>, q: QuerySearch<E>, payload: UpdatePayload<E>, opts?: QueryOptions): void;
678
- /**
679
- * upsert records.
680
- * @param ctx the query context
681
- * @param entity the target entity
682
- * @param conflictPaths the conflict paths
683
- * @param payload
684
- */
685
- upsert<E>(ctx: QueryContext, entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: E | E[]): void;
686
- /**
687
- * delete records.
688
- * @param ctx the query context
689
- * @param entity the target entity
690
- * @param q the criteria options
691
- * @param opts the query options
692
- */
693
- delete<E>(ctx: QueryContext, entity: Type<E>, q: QuerySearch<E>, opts?: QueryOptions): void;
694
- /**
695
- * escape an identifier.
696
- * @param val the value to be escaped
697
- * @param forbidQualified don't escape dots
698
- * @param addDot use a dot as suffix
699
- */
700
- escapeId(val: string, forbidQualified?: boolean, addDot?: boolean): string;
701
- /**
702
- * escape a value.
703
- * @param val the value to escape
704
- */
705
- escape(val: unknown): string;
706
- /**
707
- * add a value to the query.
708
- * @param values the values array
709
- * @param value the value to add
710
- */
711
- addValue(values: unknown[], value: unknown): string;
712
- /**
713
- * normalizes a value according to the dialect.
714
- * @param value the value to normalize
715
- */
716
- normalizeValue(value: unknown): unknown;
717
- /**
718
- * create a new query context.
719
- */
720
- createContext(): QueryContext;
721
- }
722
- /**
723
- * Supported SQL dialect identifiers.
724
- */
725
- export type SqlDialectName = 'postgres' | 'cockroachdb' | 'mysql' | 'mariadb' | 'sqlite';
726
- /**
727
- * Minimal dialect interface exposing escapeIdChar for SQL operations
728
- */
729
- export interface SqlQueryDialect extends QueryDialect {
730
- /**
731
- * The SQL dialect name (postgres, mysql, mariadb, sqlite).
732
- */
733
- readonly dialectName: SqlDialectName;
734
- /**
735
- * the escape character for identifiers.
736
- */
737
- readonly escapeIdChar: '"' | '`';
738
- /**
739
- * Build an aggregate query.
740
- */
741
- aggregate<E, G extends QueryGroupMap<E>, A extends QueryAggMap<E>>(ctx: QueryContext, entity: Type<E>, q: QueryAggregate<E, G, A>, opts?: QueryOptions): void;
742
- /**
743
- * Get the placeholder for a parameter at the given index (1-based).
744
- * Default: '?' for MySQL/MariaDB/SQLite, '$n' for PostgreSQL.
745
- */
746
- placeholder(index: number): string;
747
- }
748
- declare const QUERY_AGGREGATE_OPS: readonly ['$count', '$sum', '$avg', '$min', '$max'];
749
- /**
750
- * Supported aggregate operations.
751
- */
752
- export type QueryAggregateOp = (typeof QUERY_AGGREGATE_OPS)[number];
753
- /**
754
- * Whether `op` is one of {@link QueryAggregateOp}'s known aggregate operators - validates operator
755
- * keys parsed from query data before trusting them as `QueryAggregateOp`.
756
- */
757
- export declare function isQueryAggregateOp(op: string): op is QueryAggregateOp;
758
- /**
759
- * DISTINCT-qualified aggregate ops, each mapped to the base op it applies to a field's distinct
760
- * values: `$countDistinct` → `COUNT(DISTINCT col)`, and likewise `$sumDistinct`/`$avgDistinct`. Flat
761
- * (not a nested `{ $distinct }` argument) so the op is self-documenting and greppable. `$min`/`$max`
762
- * are omitted: DISTINCT is a no-op for them.
763
- */
764
- declare const QUERY_AGGREGATE_DISTINCT_OP_BASE: {
765
- readonly $countDistinct: '$count';
766
- readonly $sumDistinct: '$sum';
767
- readonly $avgDistinct: '$avg';
768
- };
769
- /** DISTINCT-qualified aggregate operators (the keys of {@link QUERY_AGGREGATE_DISTINCT_OP_BASE}). */
770
- export type QueryAggregateDistinctOp = keyof typeof QUERY_AGGREGATE_DISTINCT_OP_BASE;
771
- /**
772
- * Resolve an aggregate op key into its base op and whether it is DISTINCT-qualified. A flat distinct
773
- * op resolves to its base op with `distinct: true`; a plain op to `distinct: false`. Throws otherwise
774
- * (`$min`/`$max` have no distinct variant).
775
- */
776
- export declare function resolveAggregateOp(key: string): {
777
- op: QueryAggregateOp;
778
- distinct: boolean;
779
- };
780
- /** The argument of an aggregate function: a field, or `'*'` (only meaningful for `COUNT(*)`). */
781
- export type QueryAggregateArg<E> = FieldKey<E> | '*';
782
- /** Ops whose argument must be a plain field: every op except `$count` (which also accepts `'*'`). */
783
- type QueryAggregateFieldOp = Exclude<QueryAggregateOp, '$count'> | QueryAggregateDistinctOp;
784
- /** Every aggregate op mapped to its accepted argument: `$count` takes a field or `'*'`, the rest a field. */
785
- type QueryAggregateArgMap<E> = Record<'$count', QueryAggregateArg<E>> & Record<QueryAggregateFieldOp, FieldKey<E>>;
786
- /** Exactly one key of `T`: the chosen op with its value; every other op key is forbidden (`never`). */
787
- type ExactlyOne<T> = {
788
- [K in keyof T]: Readonly<Record<K, T[K]>> & Partial<Readonly<Record<Exclude<keyof T, K>, never>>>;
789
- }[keyof T];
790
- /**
791
- * An aggregate function applied to a field. Exactly one operation per entry (a second op is a
792
- * compile error). Only `$count` accepts `'*'` (i.e. `COUNT(*)`); every other op requires a field.
793
- * DISTINCT variants are flat ops (`$countDistinct`/`$sumDistinct`/`$avgDistinct`) taking a field.
794
- *
795
- * @example { $count: '*' } → COUNT(*)
796
- * @example { $countDistinct: 'id' } → COUNT(DISTINCT "id")
797
- * @example { $sum: 'amount' } → SUM("amount")
798
- * @example { $sumDistinct: 'amount' } → SUM(DISTINCT "amount")
799
- * @example { $avg: 'age' } → AVG("age")
800
- */
801
- export type QueryAggregateFn<E> = ExactlyOne<QueryAggregateArgMap<E>>;
802
- /**
803
- * Aggregate ops whose grouped column always resolves to `number`, regardless of the aggregated
804
- * field's own type: the DISTINCT variants plus the base ops they map to (`$count`/`$sum`/`$avg`).
805
- */
806
- type QueryAggregateNumericOp = QueryAggregateDistinctOp | (typeof QUERY_AGGREGATE_DISTINCT_OP_BASE)[QueryAggregateDistinctOp];
807
- /** A single-key `{ [op]: unknown }` shape for each {@link QueryAggregateNumericOp}, matched to infer a `number` result. */
808
- type QueryAggregateNumericFn = {
809
- [K in QueryAggregateNumericOp]: {
810
- readonly [P in K]: unknown;
811
- };
812
- }[QueryAggregateNumericOp];
813
- /**
814
- * Group-by columns: an object mapping entity field keys to `true`, exactly like {@link QuerySelect}.
815
- * Typed against the entity, so a typo'd column is a compile error. Compute aggregate columns with
816
- * {@link QueryAggMap} (the `$agg` key), not here.
817
- *
818
- * @example
819
- * ```ts
820
- * { status: true } // → GROUP BY "status"
821
- * ```
822
- */
823
- export type QueryGroupMap<E> = {
824
- readonly [K in FieldKey<E>]?: true;
825
- };
826
- /**
827
- * Computed aggregate columns: an object mapping your chosen output alias to an aggregate function.
828
- * Alias names are free (you are naming new columns); the aggregated field reference inside each
829
- * function is typed against the entity.
830
- *
831
- * @example
832
- * ```ts
833
- * { count: { $count: '*' }, avgAge: { $avg: 'age' } }
834
- * // → COUNT(*) AS "count", AVG("age") AS "avgAge"
835
- * ```
836
- */
837
- export type QueryAggMap<E> = {
838
- readonly [alias: string]: QueryAggregateFn<E>;
839
- };
840
- /** The entity type of an aggregated field reference `F`, or `unknown` if it is not a known field. */
841
- type FieldValueType<E, F> = F extends keyof E ? E[F] : unknown;
842
- /**
843
- * Resolves a single computed column's type from its aggregate function: `$count`/`$sum`/`$avg` are
844
- * always `number`; `$min`/`$max` keep the aggregated field's own type.
845
- * @internal
846
- */
847
- type QueryAggregateFnResult<E, Fn> = Fn extends QueryAggregateNumericFn ? number : Fn extends {
848
- readonly $min: infer F;
849
- } ? FieldValueType<E, F> : Fn extends {
850
- readonly $max: infer F;
851
- } ? FieldValueType<E, F> : unknown;
852
- /**
853
- * Flattens an intersection into a single object literal for readable editor hovers.
854
- * @internal
855
- */
856
- type Simplify<T> = {
857
- [K in keyof T]: T[K];
858
- } & {};
859
- /**
860
- * Infers the aggregated result row: grouped columns (`G`) keep their entity type; computed columns
861
- * (`A`) resolve from their aggregate function via {@link QueryAggregateFnResult}.
862
- */
863
- export type QueryAggregateResult<E, G, A> = Simplify<{
864
- -readonly [K in keyof G & FieldKey<E>]: E[K];
865
- } & {
866
- -readonly [K in keyof A]: QueryAggregateFnResult<E, A[K]>;
867
- }>;
868
- /**
869
- * Erased runtime shape of a HAVING clause (alias → comparison), consumed by the dialect builders.
870
- * Values are `unknown` because the SQL is built generically; the typed, per-column value checking
871
- * lives in {@link QueryAggregate.$having}.
872
- *
873
- * @example { count: { $gt: 5 } } → HAVING COUNT(*) > 5
874
- */
875
- export type QueryHavingMap = {
876
- readonly [alias: string]: QueryWhereFieldValue<unknown> | undefined;
877
- };
878
- /**
879
- * Aggregate query - separate from `Query<E>` to keep return types honest.
880
- * Used exclusively with `querier.aggregate()`.
881
- *
882
- * @example
883
- * ```ts
884
- * querier.aggregate(User, {
885
- * $where: { deletedAt: { $isNull: true } },
886
- * $group: { status: true },
887
- * $agg: { count: { $count: '*' }, avgAge: { $avg: 'age' } },
888
- * $having: { count: { $gt: 5 } },
889
- * $sort: { count: -1 },
890
- * });
891
- * ```
892
- */
893
- export type QueryAggregate<E, G extends QueryGroupMap<E> = QueryGroupMap<E>, A extends QueryAggMap<E> = QueryAggMap<E>> = {
894
- /**
895
- * Row-level filtering, applied before grouping (SQL `WHERE`, MongoDB `$match`).
896
- */
897
- readonly $where?: QueryWhere<E>;
898
- /**
899
- * Columns to group by - `{ status: true }`, typed against the entity like `$select`. A computed
900
- * aggregate wrongly placed here (it belongs in `$agg`) is rejected via {@link Reject}, since
901
- * `$group` is captured as a generic and a bare generic skips excess-property checking.
902
- */
903
- readonly $group?: G & Reject<Exclude<keyof G, FieldKey<E>>>;
904
- /**
905
- * Computed aggregate columns - `{ count: { $count: '*' }, avgAge: { $avg: 'age' } }`.
906
- */
907
- readonly $agg?: A;
908
- /**
909
- * Post-aggregation filtering, applied after grouping (SQL `HAVING`, MongoDB post-group `$match`).
910
- * Keyed by the result columns (grouped columns + computed aliases), and each value is typed to that
911
- * column's result type - a `$min`/`$max` over a `Date` field compares against a `Date`, a grouped
912
- * column against its own type - reusing {@link QueryAggregateResult}. A name that is neither is a
913
- * compile error.
914
- */
915
- readonly $having?: {
916
- readonly [K in keyof QueryAggregateResult<E, G, A>]?: QueryWhereFieldValue<QueryAggregateResult<E, G, A>[K]>;
917
- };
918
- /**
919
- * Sort the aggregated results by a grouped column, a computed alias, or an entity field.
920
- */
921
- readonly $sort?: QuerySortMap<E> & {
922
- readonly [K in (keyof G & string) | (keyof A & string)]?: QuerySortDirection;
923
- };
924
- } & QueryPager;
925
- export {};
926
220
  //# sourceMappingURL=query.d.ts.map