turbine-orm 0.50.0 → 0.51.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 (186) hide show
  1. package/README.md +66 -66
  2. package/dist/adapters/cockroachdb.d.ts +5 -5
  3. package/dist/adapters/cockroachdb.js +10 -10
  4. package/dist/adapters/index.d.ts +5 -5
  5. package/dist/adapters/index.js +7 -7
  6. package/dist/adapters/yugabytedb.d.ts +7 -7
  7. package/dist/adapters/yugabytedb.js +10 -10
  8. package/dist/cjs/adapters/cockroachdb.d.ts +5 -5
  9. package/dist/cjs/adapters/cockroachdb.js +10 -10
  10. package/dist/cjs/adapters/index.d.ts +5 -5
  11. package/dist/cjs/adapters/index.js +7 -7
  12. package/dist/cjs/adapters/yugabytedb.d.ts +7 -7
  13. package/dist/cjs/adapters/yugabytedb.js +10 -10
  14. package/dist/cjs/cli/config.d.ts +13 -2
  15. package/dist/cjs/cli/config.js +3 -2
  16. package/dist/cjs/cli/destructive.d.ts +1 -1
  17. package/dist/cjs/cli/destructive.js +1 -1
  18. package/dist/cjs/cli/index.d.ts +10 -10
  19. package/dist/cjs/cli/index.js +49 -45
  20. package/dist/cjs/cli/loader.d.ts +7 -7
  21. package/dist/cjs/cli/loader.js +9 -9
  22. package/dist/cjs/cli/mcp.js +4 -4
  23. package/dist/cjs/cli/migrate.d.ts +5 -5
  24. package/dist/cjs/cli/migrate.js +11 -11
  25. package/dist/cjs/cli/studio-ui.generated.js +1 -1
  26. package/dist/cjs/cli/ui.d.ts +2 -2
  27. package/dist/cjs/cli/ui.js +2 -2
  28. package/dist/cjs/client.d.ts +49 -38
  29. package/dist/cjs/client.js +57 -56
  30. package/dist/cjs/dialect.d.ts +62 -18
  31. package/dist/cjs/dialect.js +40 -2
  32. package/dist/cjs/errors.d.ts +5 -5
  33. package/dist/cjs/errors.js +11 -11
  34. package/dist/cjs/generate.d.ts +6 -6
  35. package/dist/cjs/generate.js +31 -29
  36. package/dist/cjs/index-advisor.d.ts +5 -5
  37. package/dist/cjs/index-advisor.js +0 -0
  38. package/dist/cjs/index.d.ts +1 -1
  39. package/dist/cjs/index.js +7 -7
  40. package/dist/cjs/introspect.d.ts +35 -9
  41. package/dist/cjs/introspect.js +83 -32
  42. package/dist/cjs/mssql.d.ts +11 -11
  43. package/dist/cjs/mssql.js +64 -29
  44. package/dist/cjs/mysql.d.ts +8 -8
  45. package/dist/cjs/mysql.js +61 -23
  46. package/dist/cjs/nested-write.d.ts +21 -2
  47. package/dist/cjs/nested-write.js +51 -14
  48. package/dist/cjs/optional-peer-import.cjs +7 -7
  49. package/dist/cjs/optional-peer-import.d.cts +7 -7
  50. package/dist/cjs/pipeline-submittable.d.ts +2 -2
  51. package/dist/cjs/pipeline-submittable.js +6 -6
  52. package/dist/cjs/pipeline.d.ts +1 -1
  53. package/dist/cjs/pipeline.js +4 -4
  54. package/dist/cjs/powdb-introspect.d.ts +1 -1
  55. package/dist/cjs/powdb-introspect.js +1 -1
  56. package/dist/cjs/powdb.d.ts +28 -28
  57. package/dist/cjs/powdb.js +66 -66
  58. package/dist/cjs/powql.d.ts +27 -27
  59. package/dist/cjs/powql.js +73 -52
  60. package/dist/cjs/query/aggregates.d.ts +1 -1
  61. package/dist/cjs/query/aggregates.js +5 -5
  62. package/dist/cjs/query/batched-loader.d.ts +11 -11
  63. package/dist/cjs/query/batched-loader.js +24 -24
  64. package/dist/cjs/query/builder.d.ts +39 -21
  65. package/dist/cjs/query/builder.js +99 -57
  66. package/dist/cjs/query/compound-unique.d.ts +1 -1
  67. package/dist/cjs/query/compound-unique.js +0 -0
  68. package/dist/cjs/query/deferred.d.ts +12 -6
  69. package/dist/cjs/query/deferred.js +1 -1
  70. package/dist/cjs/query/filters.d.ts +31 -11
  71. package/dist/cjs/query/filters.js +67 -14
  72. package/dist/cjs/query/index.d.ts +1 -1
  73. package/dist/cjs/query/index.js +1 -1
  74. package/dist/cjs/query/relations.d.ts +9 -9
  75. package/dist/cjs/query/relations.js +164 -57
  76. package/dist/cjs/query/types.d.ts +86 -35
  77. package/dist/cjs/query/types.js +1 -1
  78. package/dist/cjs/query/utils.d.ts +27 -10
  79. package/dist/cjs/query/utils.js +86 -14
  80. package/dist/cjs/query/where.d.ts +47 -28
  81. package/dist/cjs/query/where.js +130 -31
  82. package/dist/cjs/query/writes.d.ts +24 -5
  83. package/dist/cjs/query/writes.js +102 -13
  84. package/dist/cjs/realtime.d.ts +7 -7
  85. package/dist/cjs/realtime.js +9 -9
  86. package/dist/cjs/schema-builder.d.ts +18 -7
  87. package/dist/cjs/schema-builder.js +17 -10
  88. package/dist/cjs/schema-metadata.d.ts +3 -3
  89. package/dist/cjs/schema-metadata.js +9 -9
  90. package/dist/cjs/schema-sql.d.ts +9 -9
  91. package/dist/cjs/schema-sql.js +20 -20
  92. package/dist/cjs/schema.d.ts +19 -9
  93. package/dist/cjs/schema.js +6 -6
  94. package/dist/cjs/serverless.d.ts +15 -15
  95. package/dist/cjs/serverless.js +16 -16
  96. package/dist/cjs/sqlite.d.ts +8 -8
  97. package/dist/cjs/sqlite.js +53 -22
  98. package/dist/cjs/typed-sql.d.ts +4 -4
  99. package/dist/cjs/typed-sql.js +5 -5
  100. package/dist/cli/config.d.ts +13 -2
  101. package/dist/cli/config.js +3 -2
  102. package/dist/cli/destructive.d.ts +1 -1
  103. package/dist/cli/destructive.js +1 -1
  104. package/dist/cli/index.d.ts +10 -10
  105. package/dist/cli/index.js +49 -45
  106. package/dist/cli/loader.d.ts +7 -7
  107. package/dist/cli/loader.js +9 -9
  108. package/dist/cli/mcp.js +4 -4
  109. package/dist/cli/migrate.d.ts +5 -5
  110. package/dist/cli/migrate.js +11 -11
  111. package/dist/cli/studio-ui.generated.js +1 -1
  112. package/dist/cli/ui.d.ts +2 -2
  113. package/dist/cli/ui.js +2 -2
  114. package/dist/client.d.ts +49 -38
  115. package/dist/client.js +57 -56
  116. package/dist/dialect.d.ts +62 -18
  117. package/dist/dialect.js +40 -2
  118. package/dist/errors.d.ts +5 -5
  119. package/dist/errors.js +11 -11
  120. package/dist/generate.d.ts +6 -6
  121. package/dist/generate.js +31 -29
  122. package/dist/index-advisor.d.ts +5 -5
  123. package/dist/index-advisor.js +0 -0
  124. package/dist/index.d.ts +1 -1
  125. package/dist/index.js +7 -7
  126. package/dist/introspect.d.ts +35 -9
  127. package/dist/introspect.js +82 -32
  128. package/dist/mssql.d.ts +11 -11
  129. package/dist/mssql.js +64 -29
  130. package/dist/mysql.d.ts +8 -8
  131. package/dist/mysql.js +61 -23
  132. package/dist/nested-write.d.ts +21 -2
  133. package/dist/nested-write.js +51 -14
  134. package/dist/optional-peer-import.cjs +7 -7
  135. package/dist/optional-peer-import.d.cts +7 -7
  136. package/dist/pipeline-submittable.d.ts +2 -2
  137. package/dist/pipeline-submittable.js +6 -6
  138. package/dist/pipeline.d.ts +1 -1
  139. package/dist/pipeline.js +4 -4
  140. package/dist/powdb-introspect.d.ts +1 -1
  141. package/dist/powdb-introspect.js +1 -1
  142. package/dist/powdb.d.ts +28 -28
  143. package/dist/powdb.js +66 -66
  144. package/dist/powql.d.ts +27 -27
  145. package/dist/powql.js +73 -52
  146. package/dist/query/aggregates.d.ts +1 -1
  147. package/dist/query/aggregates.js +5 -5
  148. package/dist/query/batched-loader.d.ts +11 -11
  149. package/dist/query/batched-loader.js +24 -24
  150. package/dist/query/builder.d.ts +39 -21
  151. package/dist/query/builder.js +100 -58
  152. package/dist/query/compound-unique.d.ts +1 -1
  153. package/dist/query/compound-unique.js +0 -0
  154. package/dist/query/deferred.d.ts +12 -6
  155. package/dist/query/deferred.js +1 -1
  156. package/dist/query/filters.d.ts +31 -11
  157. package/dist/query/filters.js +66 -13
  158. package/dist/query/index.d.ts +1 -1
  159. package/dist/query/index.js +1 -1
  160. package/dist/query/relations.d.ts +9 -9
  161. package/dist/query/relations.js +165 -58
  162. package/dist/query/types.d.ts +86 -35
  163. package/dist/query/types.js +1 -1
  164. package/dist/query/utils.d.ts +27 -10
  165. package/dist/query/utils.js +84 -14
  166. package/dist/query/where.d.ts +47 -28
  167. package/dist/query/where.js +129 -32
  168. package/dist/query/writes.d.ts +24 -5
  169. package/dist/query/writes.js +101 -13
  170. package/dist/realtime.d.ts +7 -7
  171. package/dist/realtime.js +9 -9
  172. package/dist/schema-builder.d.ts +18 -7
  173. package/dist/schema-builder.js +17 -10
  174. package/dist/schema-metadata.d.ts +3 -3
  175. package/dist/schema-metadata.js +9 -9
  176. package/dist/schema-sql.d.ts +9 -9
  177. package/dist/schema-sql.js +20 -20
  178. package/dist/schema.d.ts +19 -9
  179. package/dist/schema.js +6 -6
  180. package/dist/serverless.d.ts +15 -15
  181. package/dist/serverless.js +16 -16
  182. package/dist/sqlite.d.ts +8 -8
  183. package/dist/sqlite.js +53 -22
  184. package/dist/typed-sql.d.ts +4 -4
  185. package/dist/typed-sql.js +5 -5
  186. package/package.json +2 -2
@@ -1,20 +1,20 @@
1
1
  "use strict";
2
2
  /**
3
- * turbine-orm — Batched relation loader (the `relationLoadStrategy: 'batched'` path)
3
+ * turbine-orm, Batched relation loader (the `relationLoadStrategy: 'batched'` path)
4
4
  *
5
5
  * ## Why this exists
6
6
  *
7
7
  * Turbine's default `with`-clause strategy resolves nested relations in ONE SQL
8
- * statement using correlated `json_agg(json_build_object(...))` subqueries — one
8
+ * statement using correlated `json_agg(json_build_object(...))` subqueries, one
9
9
  * probe per parent row (see `buildRelationSubquery` in builder.ts). That is the
10
10
  * right default: a single round-trip, and when the child FK columns are indexed
11
11
  * each probe is an index seek. But it degrades in two situations:
12
12
  *
13
- * 1. **Missing FK index** — a correlated probe per parent row becomes
13
+ * 1. **Missing FK index**, a correlated probe per parent row becomes
14
14
  * N-parents × full-table-scan. A batched-loader ORM pays that missing index
15
15
  * only ONCE (a single `WHERE fk = ANY($1)` seq-scan), which is why schemas
16
16
  * migrated from those ORMs often lack the index the json_agg path needs.
17
- * 2. **Huge unpaginated result sets** — the JSON wire format
17
+ * 2. **Huge unpaginated result sets**, the JSON wire format
18
18
  * (`json_build_object` per row, re-serialized inside `json_agg`) is heavy to
19
19
  * encode/decode compared with flat rows.
20
20
  *
@@ -30,19 +30,19 @@
30
30
  * - **Same executor / connection path.** Every follow-up query runs through the
31
31
  * caller's own executor ({@link RelationLoadContext.exec}) and child query
32
32
  * interfaces built on the caller's pool. Inside a `$transaction` that pool is
33
- * the pinned-connection `txPool`, so batched loads join the transaction — no
33
+ * the pinned-connection `txPool`, so batched loads join the transaction, no
34
34
  * separate pool checkout per query.
35
35
  * - **Identical output shape.** The stitched result is byte-for-byte the same
36
36
  * shape the join strategy produces: relation arrays for hasMany/manyToMany
37
37
  * (`[]` when empty), single-or-null for hasOne/belongsTo, with the same
38
- * camelCase keys and Date coercion — because the child rows are parsed by the
38
+ * camelCase keys and Date coercion, because the child rows are parsed by the
39
39
  * very same `parseRow`/`buildFindMany` machinery via a child QueryInterface.
40
40
  * - **Stitch keys never leak.** To stitch, the follow-up query must select the
41
41
  * FK/PK it joins on even when the caller's `select`/`omit` excluded it; the
42
42
  * loader adds those columns for the query and strips them from the returned
43
43
  * entities afterwards ({@link includeKeysForBatching}).
44
44
  *
45
- * PowDB (powql.ts) has its own batched loaders for the same reasons — this is the
45
+ * PowDB (powql.ts) has its own batched loaders for the same reasons, this is the
46
46
  * clean Postgres/SQL implementation, deliberately NOT shared with PowQL.
47
47
  *
48
48
  * @module
@@ -61,14 +61,14 @@ const filters_js_1 = require("./filters.js");
61
61
  const utils_js_1 = require("./utils.js");
62
62
  /**
63
63
  * Max parent keys per follow-up query. On Postgres the whole key set travels as
64
- * ONE array parameter (`= ANY($1)`), so this is not a bind-parameter limit — it
64
+ * ONE array parameter (`= ANY($1)`), so this is not a bind-parameter limit, it
65
65
  * only bounds planner/memory cost per statement. Keep it large: every extra
66
66
  * chunk is an extra network round-trip, and round-trips are exactly what the
67
67
  * batched strategy exists to minimize (a 9-chunk load was measured 2× slower
68
68
  * than a single-statement one over a WAN link).
69
69
  */
70
70
  const MAX_RELATION_KEYS = 32_000;
71
- /** Nesting cap — parity with the join strategy's depth-10 guard. */
71
+ /** Nesting cap, parity with the join strategy's depth-10 guard. */
72
72
  const MAX_DEPTH = 10;
73
73
  /**
74
74
  * The default projection of `meta` expressed in FIELD names: which fields the
@@ -100,7 +100,7 @@ function defaultProjectionFields(meta, includePii) {
100
100
  *
101
101
  * Used both for the base query (parent keys) and each follow-up query (child
102
102
  * keys) so a caller's `select: { title: true }` on a relation still stitches even
103
- * though the FK was not requested — and the FK never appears in the output.
103
+ * though the FK was not requested, and the FK never appears in the output.
104
104
  */
105
105
  function includeKeysForBatching(select, omit, fields,
106
106
  /**
@@ -122,7 +122,7 @@ defaultProjection) {
122
122
  for (const f of unique) {
123
123
  if (!next[f]) {
124
124
  next[f] = true;
125
- strip.push(f); // not requested by the caller — added only to stitch
125
+ strip.push(f); // not requested by the caller, added only to stitch
126
126
  }
127
127
  }
128
128
  return { select: next, omit, strip };
@@ -182,7 +182,7 @@ function neededParentKeyFields(parentMeta, withClause) {
182
182
  }
183
183
  const rel = (0, utils_js_1.ownLookup)(parentMeta.relations, relName);
184
184
  if (!rel)
185
- continue; // unknown relation — the join path throws; let the loader surface it
185
+ continue; // unknown relation, the join path throws; let the loader surface it
186
186
  for (const col of localKeyColumns(rel)) {
187
187
  fields.add(parentMeta.reverseColumnMap[col] ?? col);
188
188
  }
@@ -231,18 +231,18 @@ function resolveCountRelations(parentMeta, countSpec) {
231
231
  }
232
232
  return out;
233
233
  }
234
- /** Stringified stitch key — robust to number/uuid/bigint type drift across a join. */
234
+ /** Stringified stitch key, robust to number/uuid/bigint type drift across a join. */
235
235
  function keyOf(value) {
236
236
  return String(value);
237
237
  }
238
238
  /**
239
- * Reject pick-row relation ordering anywhere inside a `with` tree's orderBy —
239
+ * Reject pick-row relation ordering anywhere inside a `with` tree's orderBy -
240
240
  * strategy parity with the join path, which throws this exact E003 at SQL
241
241
  * build time (`pickOrderNestedError` in builder.ts). Without this guard the
242
242
  * loaders would forward `options.orderBy` as the child reader's TOP-LEVEL
243
- * findMany orderBy, where the pick shape compiles fine — so the same query
243
+ * findMany orderBy, where the pick shape compiles fine, so the same query
244
244
  * would execute on 'batched' but throw on 'join'. Walks the whole tree up
245
- * front so acceptance never depends on which levels have rows — the batched
245
+ * front so acceptance never depends on which levels have rows, the batched
246
246
  * runners in builder.ts call this BEFORE the base query (a zero-row base
247
247
  * result must still reject, exactly like the join strategy's build-time throw).
248
248
  */
@@ -278,13 +278,13 @@ async function loadRelationsBatched(ctx, parents, withClause, timeout, depth = 0
278
278
  if (parents.length === 0)
279
279
  return;
280
280
  // Sibling relations are independent (each writes only its own parent[relName]
281
- // and reads only parent keys), so load them concurrently — on a pool that's
281
+ // and reads only parent keys), so load them concurrently, on a pool that's
282
282
  // real parallelism, inside a transaction pg queues them on the one connection.
283
283
  const loads = [];
284
284
  for (const [relName, spec] of Object.entries(withClause)) {
285
285
  if (!spec)
286
286
  continue;
287
- // Reserved `_count` key — one grouped COUNT(*) follow-up per counted relation.
287
+ // Reserved `_count` key, one grouped COUNT(*) follow-up per counted relation.
288
288
  if (relName === '_count') {
289
289
  loads.push(loadCounts(ctx, parents, spec));
290
290
  continue;
@@ -309,7 +309,7 @@ async function loadToOneOrMany(ctx, parents, rel, relName, options, timeout, dep
309
309
  const fk = (0, schema_js_1.normalizeKeyColumns)(rel.foreignKey);
310
310
  const rk = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
311
311
  if (fk.length > 1 || rk.length > 1) {
312
- throw new errors_js_1.UnsupportedFeatureError('composite-key batched relation loading', 'relationLoadStrategy: "batched"', `relation "${relName}" — use the default 'join' strategy for composite-key relations`);
312
+ throw new errors_js_1.UnsupportedFeatureError('composite-key batched relation loading', 'relationLoadStrategy: "batched"', `relation "${relName}", use the default 'join' strategy for composite-key relations`);
313
313
  }
314
314
  const targetMeta = requireTable(ctx.schema, rel.to, relName);
315
315
  // Local key lives on the parent; the correlating key lives on the child.
@@ -384,7 +384,7 @@ async function loadManyToMany(ctx, parents, rel, relName, options, timeout, dept
384
384
  const sourceRef = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
385
385
  const targetMeta = requireTable(ctx.schema, rel.to, relName);
386
386
  if (sourceJ.length > 1 || targetJ.length > 1 || sourceRef.length > 1 || targetMeta.primaryKey.length !== 1) {
387
- throw new errors_js_1.UnsupportedFeatureError('composite-key batched manyToMany loading', 'relationLoadStrategy: "batched"', `relation "${relName}" — use the default 'join' strategy for composite-key m2m relations`);
387
+ throw new errors_js_1.UnsupportedFeatureError('composite-key batched manyToMany loading', 'relationLoadStrategy: "batched"', `relation "${relName}", use the default 'join' strategy for composite-key m2m relations`);
388
388
  }
389
389
  const sourceJCol = sourceJ[0];
390
390
  const targetJCol = targetJ[0];
@@ -483,7 +483,7 @@ async function loadManyToMany(ctx, parents, rel, relName, options, timeout, dept
483
483
  * Load correlated `_count` values for the counted relations. One grouped
484
484
  * follow-up per relation (`SELECT key, COUNT(*) … WHERE key = ANY($1) GROUP BY
485
485
  * key`), attached onto each parent's `_count` object (0 when a parent has no
486
- * matching rows) — byte-identical to the join strategy's `_count` output.
486
+ * matching rows), byte-identical to the join strategy's `_count` output.
487
487
  */
488
488
  async function loadCounts(ctx, parents, countSpec) {
489
489
  const rels = resolveCountRelations(ctx.parentMeta, countSpec);
@@ -508,7 +508,7 @@ async function loadOneCount(ctx, parents, rel) {
508
508
  const sourceRef = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
509
509
  const sourceJ = (0, schema_js_1.normalizeKeyColumns)(through.sourceKey);
510
510
  if (sourceRef.length > 1 || sourceJ.length > 1) {
511
- throw new errors_js_1.UnsupportedFeatureError('composite-key batched _count', 'relationLoadStrategy: "batched"', `relation "${rel.name}" — use the default 'join' strategy for composite-key m2m _count`);
511
+ throw new errors_js_1.UnsupportedFeatureError('composite-key batched _count', 'relationLoadStrategy: "batched"', `relation "${rel.name}", use the default 'join' strategy for composite-key m2m _count`);
512
512
  }
513
513
  parentKeyCol = sourceRef[0];
514
514
  childTable = through.table;
@@ -519,7 +519,7 @@ async function loadOneCount(ctx, parents, rel) {
519
519
  const fk = (0, schema_js_1.normalizeKeyColumns)(rel.foreignKey);
520
520
  const rk = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
521
521
  if (fk.length > 1 || rk.length > 1) {
522
- throw new errors_js_1.UnsupportedFeatureError('composite-key batched _count', 'relationLoadStrategy: "batched"', `relation "${rel.name}" — use the default 'join' strategy for composite-key _count`);
522
+ throw new errors_js_1.UnsupportedFeatureError('composite-key batched _count', 'relationLoadStrategy: "batched"', `relation "${rel.name}", use the default 'join' strategy for composite-key _count`);
523
523
  }
524
524
  parentKeyCol = rk[0];
525
525
  childTable = rel.to;
@@ -538,7 +538,7 @@ async function loadOneCount(ctx, parents, rel) {
538
538
  // two strategies return identical counts under a filter. hasMany filters
539
539
  // the counted table directly; m2m counts junction rows but restricts them
540
540
  // to junction rows whose TARGET survives the target table's filter via
541
- // EXISTS — mirroring buildRelationCountExpr's EXISTS-on-target (which also
541
+ // EXISTS, mirroring buildRelationCountExpr's EXISTS-on-target (which also
542
542
  // skips the filter when the junction targetKey arity doesn't match the
543
543
  // target PK). Rendered after the $1 key array.
544
544
  let gf = null;
@@ -1,14 +1,14 @@
1
1
  /**
2
- * turbine-orm — Query builder
2
+ * turbine-orm, Query builder
3
3
  *
4
4
  * Each table accessor (db.users, db.posts, etc.) returns a QueryInterface<T>
5
5
  * that builds parameterized SQL and executes it through the connection pool.
6
6
  *
7
7
  * Nested relations use json_build_object + json_agg subqueries for single-query
8
- * resolution — a PostgreSQL-native approach that eliminates N+1 query patterns.
8
+ * resolution, a PostgreSQL-native approach that eliminates N+1 query patterns.
9
9
  *
10
10
  * Schema-driven: all column names, types, and relations come from introspected
11
- * metadata — nothing is hardcoded.
11
+ * metadata, nothing is hardcoded.
12
12
  */
13
13
  import type pg from 'pg';
14
14
  import type { SchemaMetadata } from '../schema.js';
@@ -103,6 +103,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
103
103
  private readonly middlewares;
104
104
  private readonly defaultLimit?;
105
105
  private readonly warnOnUnlimited;
106
+ private readonly scopedConnect;
106
107
  private readonly utcTimestamps;
107
108
  private readonly preparedStatementsEnabled;
108
109
  /**
@@ -150,7 +151,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
150
151
  private readonly globalFilters?;
151
152
  /**
152
153
  * Tracks tables that have already triggered an unlimited-query warning so
153
- * the user is not spammed once per row. Per-instance state — each
154
+ * the user is not spammed once per row. Per-instance state, each
154
155
  * QueryInterface is bound to a single table, so this set will only ever
155
156
  * contain at most one entry, but using a Set keeps the API consistent with
156
157
  * the audit's "Set<string>" guidance and leaves room for future
@@ -165,7 +166,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
165
166
  private readonly columnArrayTypeMap;
166
167
  /**
167
168
  * Columns whose type lives in a DIFFERENT schema than the introspected one
168
- * (ColumnMetadata.pgTypeSchema is recorded only in that case) — such columns
169
+ * (ColumnMetadata.pgTypeSchema is recorded only in that case), such columns
169
170
  * must never receive this schema's `::"enum"` cast (see enumTypeForColumn).
170
171
  */
171
172
  private readonly crossSchemaTypeColumns;
@@ -179,7 +180,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
179
180
  private readonly camelDateFieldCache;
180
181
  /** True when this QI runs inside an active transaction (set via _txScoped option). */
181
182
  private readonly txScoped;
182
- /** Original options reference — forwarded to child QIs in nested writes. */
183
+ /** Original options reference, forwarded to child QIs in nested writes. */
183
184
  private readonly options?;
184
185
  /** Set by executeWithMiddleware so queryWithTimeout can include it in events. */
185
186
  private currentAction;
@@ -195,7 +196,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
195
196
  /**
196
197
  * The active query's `skipGlobalFilters` opt-out, set at the top of each
197
198
  * `build*` method and read deep in the (synchronous) SQL-build + param-collect
198
- * tree — so relation subqueries, relation filters, `_count`, and relation
199
+ * tree, so relation subqueries, relation filters, `_count`, and relation
199
200
  * `orderBy` all see it without threading it through dozens of signatures.
200
201
  * Only load-bearing when {@link globalFilters} is configured; build+collect are
201
202
  * synchronous per call, so this transient is never observed across an await.
@@ -240,7 +241,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
240
241
  * SQLite use ` LIMIT <ph>` and/or ` OFFSET <ph>`. SQL Server has no `LIMIT`, so
241
242
  * its dialect implements {@link Dialect.buildLimitOffset} to emit
242
243
  * `[ORDER BY (SELECT NULL)] OFFSET <off> ROWS [FETCH NEXT <lim> ROWS ONLY]`.
243
- * Param-push order (limit before offset) is owned by the caller and unchanged —
244
+ * Param-push order (limit before offset) is owned by the caller and unchanged -
244
245
  * this only varies the SQL text, so PG output stays byte-identical.
245
246
  */
246
247
  private buildPagination;
@@ -431,7 +432,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
431
432
  * join for a to-one relation.
432
433
  *
433
434
  * Resolution order:
434
- * 1. an explicit `autoToOneJoinMaxRows` — an instruction, used verbatim
435
+ * 1. an explicit `autoToOneJoinMaxRows`, an instruction, used verbatim
435
436
  * (no clamping: the caller has measured their own workload);
436
437
  * 2. the configured `autoRoundTripMs` divided by
437
438
  * {@link AUTO_JOIN_PENALTY_MS_PER_ROW}, clamped to
@@ -445,7 +446,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
445
446
  * put, so any single constant is wrong for someone by more than the margin it
446
447
  * is trying to save. Placing the switch AT the break-even is also what removes
447
448
  * the old cliff: two plans that cost the same at the boundary make the regret
448
- * there ~1.0x, rising only as the true row count moves away from it — where
449
+ * there ~1.0x, rising only as the true row count moves away from it, where
449
450
  * the previous fixed 1000 put its WORST case (1.44x measured) immediately
450
451
  * below its own switch point.
451
452
  *
@@ -492,7 +493,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
492
493
  * Build the {@link RelationLoadContext} the batched loader needs, closing over
493
494
  * this interface's pool/dialect/executor. Child readers are constructed on the
494
495
  * SAME pool (so they join an active transaction) with `defaultLimit` cleared
495
- * and unlimited-warnings silenced — a relation load must fetch every matching
496
+ * and unlimited-warnings silenced, a relation load must fetch every matching
496
497
  * child, and the per-relation `limit` is applied client-side by the loader.
497
498
  */
498
499
  private batchedContext;
@@ -582,7 +583,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
582
583
  *
583
584
  * - `'returning'` / `'output'`: the statement returns its own affected rows
584
585
  * (`RETURNING *` / `OUTPUT INSERTED.*`). Byte-identical to the historical
585
- * single `queryWithTimeout` + `transform(result)` path — the PostgreSQL
586
+ * single `queryWithTimeout` + `transform(result)` path, the PostgreSQL
586
587
  * route is unchanged.
587
588
  * - `'reselect'`: the engine cannot return rows from a write, so the build
588
589
  * method attached a {@link DeferredQuery.reselect} plan that runs the
@@ -612,7 +613,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
612
613
  *
613
614
  * Middleware can inspect and log query parameters, measure timing, and
614
615
  * transform the result returned by `next()`. Note: query SQL is generated
615
- * BEFORE middleware runs — `params.args` is a read-only snapshot, and
616
+ * BEFORE middleware runs, `params.args` is a read-only snapshot, and
616
617
  * mutating it does NOT change the executed SQL. Cross-cutting filters
617
618
  * (e.g. soft deletes) belong in the query itself: pass an explicit
618
619
  * `where: { deletedAt: null }` or wrap the table accessor in a small helper.
@@ -626,7 +627,7 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
626
627
  * strategy's shape for the one row.
627
628
  */
628
629
  private runFindUniqueBatched;
629
- buildFindUnique<W extends TypedWithClause<R> = {}>(args: FindUniqueArgs<T, R, W, Record<string, boolean> | undefined, Record<string, boolean> | undefined>): DeferredQuery<T | null>;
630
+ buildFindUnique<W extends TypedWithClause<R> = {}, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined>(args: FindUniqueArgs<T, R, W, S, O>): DeferredQuery<QueryResult<T, R, W, S, O> | null>;
630
631
  findMany<W extends TypedWithClause<R> = {}, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined>(args?: FindManyArgs<T, R, W, S, O>): Promise<QueryResult<T, R, W, S, O>[]>;
631
632
  /**
632
633
  * Return the engine's query plan for a {@link findMany}-shaped query as plain
@@ -672,12 +673,29 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
672
673
  * disabled in config).
673
674
  */
674
675
  private maybeWarnUnlimited;
676
+ /**
677
+ * Whether `where` can match at most one row, because it pins every column of
678
+ * the primary key or of some unique column set to a literal value.
679
+ *
680
+ * The unlimited-read warning is about accidentally fetching a whole table,
681
+ * so firing it on `findMany({ where: { id: 1 } })` is noise: that query is
682
+ * bounded by a uniqueness constraint just as firmly as by a `limit`, and a
683
+ * warning that cries wolf on correct code trains people to disable it.
684
+ *
685
+ * Deliberately conservative. Only DIRECT equality on a literal counts: an
686
+ * operator object (`{ id: { in: [...] } }`, `{ id: { gt: 1 } }`) can match
687
+ * many rows, and any `OR` / `NOT` / relation filter can widen the result, so
688
+ * anything that is not a plain scalar equality leaves the warning in place.
689
+ * A compound-unique SELECTOR (`{ orgId_userId: {...} }`) is expanded first,
690
+ * so both spellings are recognized.
691
+ */
692
+ private whereMatchesAtMostOneRow;
675
693
  /**
676
694
  * Recursively measure the maximum depth of a `with` clause tree.
677
695
  * Used by the dev-only deep-with warning guard.
678
696
  */
679
697
  private measureWithDepth;
680
- buildFindMany<W extends TypedWithClause<R> = {}>(args?: FindManyArgs<T, R, W, Record<string, boolean> | undefined, Record<string, boolean> | undefined>): DeferredQuery<T[]>;
698
+ buildFindMany<W extends TypedWithClause<R> = {}, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined>(args?: FindManyArgs<T, R, W, S, O>): DeferredQuery<QueryResult<T, R, W, S, O>[]>;
681
699
  /**
682
700
  * Stream rows from a findMany query using PostgreSQL cursors.
683
701
  * Returns an AsyncIterable that yields individual rows, fetching in batches internally.
@@ -712,11 +730,11 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
712
730
  */
713
731
  findManyStream<W extends TypedWithClause<R> = {}, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined>(args?: FindManyStreamArgs<T, R, W, S, O>): AsyncGenerator<QueryResult<T, R, W, S, O>, void, undefined>;
714
732
  findFirst<W extends TypedWithClause<R> = {}, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined>(args?: FindManyArgs<T, R, W, S, O>): Promise<QueryResult<T, R, W, S, O> | null>;
715
- buildFindFirst<W extends TypedWithClause<R> = {}>(args?: FindManyArgs<T, R, W, Record<string, boolean> | undefined, Record<string, boolean> | undefined>): DeferredQuery<T | null>;
733
+ buildFindFirst<W extends TypedWithClause<R> = {}, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined>(args?: FindManyArgs<T, R, W, S, O>): DeferredQuery<QueryResult<T, R, W, S, O> | null>;
716
734
  findFirstOrThrow<W extends TypedWithClause<R> = {}, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined>(args?: FindManyArgs<T, R, W, S, O>): Promise<QueryResult<T, R, W, S, O>>;
717
- buildFindFirstOrThrow<W extends TypedWithClause<R> = {}>(args?: FindManyArgs<T, R, W, Record<string, boolean> | undefined, Record<string, boolean> | undefined>): DeferredQuery<T>;
735
+ buildFindFirstOrThrow<W extends TypedWithClause<R> = {}, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined>(args?: FindManyArgs<T, R, W, S, O>): DeferredQuery<QueryResult<T, R, W, S, O>>;
718
736
  findUniqueOrThrow<W extends TypedWithClause<R> = {}, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined>(args: FindUniqueArgs<T, R, W, S, O>): Promise<QueryResult<T, R, W, S, O>>;
719
- buildFindUniqueOrThrow<W extends TypedWithClause<R> = {}>(args: FindUniqueArgs<T, R, W, Record<string, boolean> | undefined, Record<string, boolean> | undefined>): DeferredQuery<T>;
737
+ buildFindUniqueOrThrow<W extends TypedWithClause<R> = {}, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined>(args: FindUniqueArgs<T, R, W, S, O>): DeferredQuery<QueryResult<T, R, W, S, O>>;
720
738
  create(args: CreateArgs<T, R>): Promise<T>;
721
739
  createMany(args: CreateManyArgs<T>): Promise<T[]>;
722
740
  update(args: UpdateArgs<T, R>): Promise<T>;
@@ -831,12 +849,12 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
831
849
  /**
832
850
  * Build ORDER BY clause from an object.
833
851
  *
834
- * Each value is either a plain direction (`'asc'`/`'desc'`) or — for pgvector
835
- * columns — a `{ distance: { to, metric, direction? } }` KNN ordering object.
852
+ * Each value is either a plain direction (`'asc'`/`'desc'`) or, for pgvector
853
+ * columns, a `{ distance: { to, metric, direction? } }` KNN ordering object.
836
854
  * Vector ordering binds the query vector as a `$n::vector` param, so a `params`
837
855
  * array MUST be supplied when a vector ordering may be present (top-level
838
856
  * findMany path). When `params` is omitted (groupBy / relation path) a vector
839
- * ordering throws — KNN ordering is only supported at the top level.
857
+ * ordering throws, KNN ordering is only supported at the top level.
840
858
  */
841
859
  /** Parse a flat row: convert snake_case to camelCase + Date coercion */
842
860
  /**