turbine-orm 0.76.0 → 0.77.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 (87) hide show
  1. package/dist/cjs/cli/index.js +2 -2
  2. package/dist/cjs/cli/migrate.js +8 -8
  3. package/dist/cjs/cli/studio.js +6 -3
  4. package/dist/cjs/client.js +10 -10
  5. package/dist/cjs/dialect.js +1 -1
  6. package/dist/cjs/errors.d.ts +2 -2
  7. package/dist/cjs/errors.js +21 -25
  8. package/dist/cjs/generate.js +1 -1
  9. package/dist/cjs/introspect.js +5 -5
  10. package/dist/cjs/mssql.js +12 -12
  11. package/dist/cjs/mysql.js +5 -5
  12. package/dist/cjs/nested-write.js +31 -31
  13. package/dist/cjs/observe.js +1 -1
  14. package/dist/cjs/pipeline-submittable.js +5 -1
  15. package/dist/cjs/pipeline.js +8 -0
  16. package/dist/cjs/powdb-introspect.d.ts +1 -1
  17. package/dist/cjs/powdb-introspect.js +4 -4
  18. package/dist/cjs/powdb-shared.d.ts +348 -0
  19. package/dist/cjs/powdb-shared.js +587 -0
  20. package/dist/cjs/powdb.d.ts +12 -299
  21. package/dist/cjs/powdb.js +106 -567
  22. package/dist/cjs/powql.d.ts +1 -1
  23. package/dist/cjs/powql.js +89 -89
  24. package/dist/cjs/prisma-compat.js +16 -16
  25. package/dist/cjs/query/aggregates.js +19 -20
  26. package/dist/cjs/query/batched-loader.js +8 -8
  27. package/dist/cjs/query/builder.js +8 -8
  28. package/dist/cjs/query/compound-unique.js +2 -2
  29. package/dist/cjs/query/filters.js +1 -1
  30. package/dist/cjs/query/relations.js +60 -48
  31. package/dist/cjs/query/types.js +4 -4
  32. package/dist/cjs/query/utils.js +5 -5
  33. package/dist/cjs/query/warn-registry.d.ts +7 -0
  34. package/dist/cjs/query/warn-registry.js +7 -0
  35. package/dist/cjs/query/where-compile.js +1 -1
  36. package/dist/cjs/query/where.js +30 -31
  37. package/dist/cjs/query/writes.js +7 -7
  38. package/dist/cjs/realtime.js +4 -4
  39. package/dist/cjs/schema-metadata.js +1 -1
  40. package/dist/cjs/schema-sql.js +3 -3
  41. package/dist/cjs/seed.js +1 -1
  42. package/dist/cjs/sqlite.js +7 -7
  43. package/dist/cjs/typed-sql.js +1 -1
  44. package/dist/cli/index.js +2 -2
  45. package/dist/cli/migrate.js +8 -8
  46. package/dist/cli/studio.js +6 -3
  47. package/dist/client.js +10 -10
  48. package/dist/dialect.js +1 -1
  49. package/dist/errors.d.ts +2 -2
  50. package/dist/errors.js +21 -25
  51. package/dist/generate.js +1 -1
  52. package/dist/introspect.js +5 -5
  53. package/dist/mssql.js +12 -12
  54. package/dist/mysql.js +5 -5
  55. package/dist/nested-write.js +31 -31
  56. package/dist/observe.js +1 -1
  57. package/dist/pipeline-submittable.js +6 -2
  58. package/dist/pipeline.js +9 -1
  59. package/dist/powdb-introspect.d.ts +1 -1
  60. package/dist/powdb-introspect.js +2 -2
  61. package/dist/powdb-shared.d.ts +348 -0
  62. package/dist/powdb-shared.js +570 -0
  63. package/dist/powdb.d.ts +12 -299
  64. package/dist/powdb.js +71 -534
  65. package/dist/powql.d.ts +1 -1
  66. package/dist/powql.js +43 -43
  67. package/dist/prisma-compat.js +16 -16
  68. package/dist/query/aggregates.js +19 -20
  69. package/dist/query/batched-loader.js +8 -8
  70. package/dist/query/builder.js +8 -8
  71. package/dist/query/compound-unique.js +2 -2
  72. package/dist/query/filters.js +1 -1
  73. package/dist/query/relations.js +60 -48
  74. package/dist/query/types.js +4 -4
  75. package/dist/query/utils.js +5 -5
  76. package/dist/query/warn-registry.d.ts +7 -0
  77. package/dist/query/warn-registry.js +7 -0
  78. package/dist/query/where-compile.js +1 -1
  79. package/dist/query/where.js +30 -31
  80. package/dist/query/writes.js +7 -7
  81. package/dist/realtime.js +4 -4
  82. package/dist/schema-metadata.js +1 -1
  83. package/dist/schema-sql.js +3 -3
  84. package/dist/seed.js +1 -1
  85. package/dist/sqlite.js +7 -7
  86. package/dist/typed-sql.js +1 -1
  87. package/package.json +15 -7
package/dist/cjs/powql.js CHANGED
@@ -73,7 +73,7 @@ exports.PowqlInterface = exports.MAX_POWQL_DATETIME_TERMS = void 0;
73
73
  const node_crypto_1 = require("node:crypto");
74
74
  const errors_js_1 = require("./errors.js");
75
75
  const nested_write_js_1 = require("./nested-write.js");
76
- const powdb_js_1 = require("./powdb.js");
76
+ const powdb_shared_js_1 = require("./powdb-shared.js");
77
77
  const aggregates_js_1 = require("./query/aggregates.js");
78
78
  const compound_unique_js_1 = require("./query/compound-unique.js");
79
79
  const filters_js_1 = require("./query/filters.js");
@@ -225,7 +225,7 @@ class PowqlInterface {
225
225
  this.options = options;
226
226
  const meta = schema.tables[table];
227
227
  if (!meta) {
228
- throw new errors_js_1.ValidationError(`[turbine] Unknown table "${table}". ${(0, utils_js_1.availableClause)(Object.keys(schema.tables), 'The schema has no tables.')}`);
228
+ throw new errors_js_1.ValidationError(`Unknown table "${table}". ${(0, utils_js_1.availableClause)(Object.keys(schema.tables), 'The schema has no tables.')}`);
229
229
  }
230
230
  this.meta = meta;
231
231
  this.defaultLimit = options.defaultLimit;
@@ -258,7 +258,7 @@ class PowqlInterface {
258
258
  const snake = resolved ?? (0, utils_js_1.ownLookup)(this.meta.columnMap, field) ?? field;
259
259
  const col = this.meta.columns.find((c) => c.name === snake || c.field === field);
260
260
  if (!col) {
261
- throw new errors_js_1.ValidationError(`[turbine] Unknown column "${field}" on table "${this.table}". Known: ${this.meta.columns
261
+ throw new errors_js_1.ValidationError(`Unknown column "${field}" on table "${this.table}". Known: ${this.meta.columns
262
262
  .map((c) => c.field)
263
263
  .join(', ')}`);
264
264
  }
@@ -325,7 +325,7 @@ class PowqlInterface {
325
325
  * included, so no existing schema sees a different statement.
326
326
  */
327
327
  colRefName(name, alias) {
328
- return alias ? `${alias}.${(0, powdb_js_1.quotePowqlIdent)(name)}` : `.${(0, powdb_js_1.quotePowqlDotted)(name)}`;
328
+ return alias ? `${alias}.${(0, powdb_shared_js_1.quotePowqlIdent)(name)}` : `.${(0, powdb_shared_js_1.quotePowqlDotted)(name)}`;
329
329
  }
330
330
  /**
331
331
  * Push a value into the param array and return its `$N` placeholder. When the
@@ -339,13 +339,13 @@ class PowqlInterface {
339
339
  let tagged = value;
340
340
  if (col && typeof value === 'number' && this.isFloatCol(col)) {
341
341
  // Float column: force a float-form literal even for an integer value.
342
- tagged = new powdb_js_1.PowdbFloatParam(value);
342
+ tagged = new powdb_shared_js_1.PowdbFloatParam(value);
343
343
  }
344
- else if (col && value !== null && typeof value === 'object' && !(value instanceof Date) && (0, powdb_js_1.isJsonColumn)(col)) {
344
+ else if (col && value !== null && typeof value === 'object' && !(value instanceof Date) && (0, powdb_shared_js_1.isJsonColumn)(col)) {
345
345
  // json document column: a JS object/array is serialized to canonical JSON
346
346
  // text and stored as a json document (a JS string passes through raw, same
347
347
  // contract as pg jsonb; `null` stays `null`).
348
- tagged = new powdb_js_1.PowdbJsonParam(value, col.name);
348
+ tagged = new powdb_shared_js_1.PowdbJsonParam(value, col.name);
349
349
  }
350
350
  params.push(tagged);
351
351
  return `$${params.length}`;
@@ -362,13 +362,13 @@ class PowqlInterface {
362
362
  */
363
363
  writeRef(value, col, params) {
364
364
  if (typeof value === 'number' && !Number.isFinite(value) && this.isFloatCol(col)) {
365
- throw new errors_js_1.ValidationError(`[turbine] Non-finite value for float column "${col.name}" on "${this.table}".`);
365
+ throw new errors_js_1.ValidationError(`Non-finite value for float column "${col.name}" on "${this.table}".`);
366
366
  }
367
367
  return this.param(value, params, col);
368
368
  }
369
369
  isFloatCol(col) {
370
370
  try {
371
- return (0, powdb_js_1.powqlColumnType)(col) === 'float';
371
+ return (0, powdb_shared_js_1.powqlColumnType)(col) === 'float';
372
372
  }
373
373
  catch {
374
374
  return false;
@@ -381,7 +381,7 @@ class PowqlInterface {
381
381
  * default so a hand-built test pool never crashes the version gates.
382
382
  */
383
383
  get capabilities() {
384
- return this.pool.capabilities ?? powdb_js_1.ALL_POWDB_CAPABILITIES;
384
+ return this.pool.capabilities ?? powdb_shared_js_1.ALL_POWDB_CAPABILITIES;
385
385
  }
386
386
  /**
387
387
  * The `limit` a query actually emits: the explicit `limit`, then the
@@ -488,7 +488,7 @@ class PowqlInterface {
488
488
  ['offset', offset],
489
489
  ]) {
490
490
  if (value !== undefined && value !== null && value < 0) {
491
- throw new errors_js_1.ValidationError(`[turbine] ${context} on "${this.table}": \`${name}\` must not be negative (got ${value}).`);
491
+ throw new errors_js_1.ValidationError(`${context} on "${this.table}": \`${name}\` must not be negative (got ${value}).`);
492
492
  }
493
493
  }
494
494
  }
@@ -538,7 +538,7 @@ class PowqlInterface {
538
538
  // Relation filters are pre-resolved to scalar in/notIn by
539
539
  // resolveRelationFilters() before buildWhere runs, reaching here means
540
540
  // a caller skipped that step (an internal bug, not user error).
541
- throw new errors_js_1.ValidationError(`[turbine] internal: relation filter "${key}" reached buildWhere unresolved (missing resolveRelationFilters()).`);
541
+ throw new errors_js_1.ValidationError(`internal: relation filter "${key}" reached buildWhere unresolved (missing resolveRelationFilters()).`);
542
542
  }
543
543
  else {
544
544
  // A JsonFilter (or a bare `{ path }`) can compile to zero clauses; skip
@@ -581,9 +581,9 @@ class PowqlInterface {
581
581
  * read through `introspectPowdbDatabase`, or hand-written metadata.
582
582
  */
583
583
  assertDatetimePredicateSupported(col) {
584
- if (!(0, powdb_js_1.isPowdbDatetimeColumn)(col))
584
+ if (!(0, powdb_shared_js_1.isPowdbDatetimeColumn)(col))
585
585
  return;
586
- (0, powdb_js_1.requireCapability)(this.capabilities, 'datetimeCompare', `comparisons on the PowDB datetime column "${col.name}"`, 'Reading that column is unaffected, and so are ordering, grouping and `is null` checks; only comparing it ' +
586
+ (0, powdb_shared_js_1.requireCapability)(this.capabilities, 'datetimeCompare', `comparisons on the PowDB datetime column "${col.name}"`, 'Reading that column is unaffected, and so are ordering, grouping and `is null` checks; only comparing it ' +
587
587
  'against a bound timestamp needs the fix. A nested `with` (the default nested-projection / join paths) ' +
588
588
  'correlates column to column, so it loads the relation without any such comparison.');
589
589
  }
@@ -602,8 +602,8 @@ class PowqlInterface {
602
602
  // path filters (≥ 0.12). `isJsonFilter` matches `path`/`equals`/`contains`/
603
603
  // `hasKey`; on a NON-json column those fall through to the scalar operator
604
604
  // path below (e.g. `equals` stays a plain equality), exactly like SQL.
605
- if ((0, powdb_js_1.isJsonColumn)(colMeta) && (0, filters_js_1.isJsonFilter)(value)) {
606
- (0, powdb_js_1.requireCapability)(this.capabilities, 'jsonDocs', 'JSON path filters');
605
+ if ((0, powdb_shared_js_1.isJsonColumn)(colMeta) && (0, filters_js_1.isJsonFilter)(value)) {
606
+ (0, powdb_shared_js_1.requireCapability)(this.capabilities, 'jsonDocs', 'JSON path filters');
607
607
  return this.buildJsonPathCondition(colMeta, value, params, alias);
608
608
  }
609
609
  rejectUnsupportedFilter(op, field);
@@ -668,7 +668,7 @@ class PowqlInterface {
668
668
  conds.push(`${lhs} like ${this.bindLike(`%${(0, utils_js_1.escapeLike)(String(opVal))}`, params, insensitive)}`);
669
669
  break;
670
670
  default:
671
- throw new errors_js_1.ValidationError(`[turbine] Unsupported operator "${opName}" on PowDB.`);
671
+ throw new errors_js_1.ValidationError(`Unsupported operator "${opName}" on PowDB.`);
672
672
  }
673
673
  }
674
674
  return conds.length > 1 ? `(${conds.join(' and ')})` : (conds[0] ?? this.alwaysFalse());
@@ -756,14 +756,14 @@ class PowqlInterface {
756
756
  if (v === undefined)
757
757
  continue;
758
758
  if (filter.path === undefined) {
759
- throw new errors_js_1.ValidationError(`[turbine] JSON range operator '${op}' on ${col.name} requires a \`path\` ` +
759
+ throw new errors_js_1.ValidationError(`JSON range operator '${op}' on ${col.name} requires a \`path\` ` +
760
760
  `(e.g. { path: ['meta', 'score'], ${op}: ${JSON.stringify(v)} }).`);
761
761
  }
762
762
  if (typeof v !== 'number' && typeof v !== 'string') {
763
- throw new errors_js_1.ValidationError(`[turbine] JSON range operator '${op}' on ${col.name} requires a number or string, got ${JSON.stringify(v)}.`);
763
+ throw new errors_js_1.ValidationError(`JSON range operator '${op}' on ${col.name} requires a number or string, got ${JSON.stringify(v)}.`);
764
764
  }
765
765
  if (typeof v === 'number' && !Number.isFinite(v)) {
766
- throw new errors_js_1.ValidationError(`[turbine] JSON range operator '${op}' on ${col.name} requires a finite number.`);
766
+ throw new errors_js_1.ValidationError(`JSON range operator '${op}' on ${col.name} requires a finite number.`);
767
767
  }
768
768
  conds.push(`${pathP()} ${powOp} ${this.param(v, params)}`);
769
769
  }
@@ -779,7 +779,7 @@ class PowqlInterface {
779
779
  // generator bug rather than a user error, and must not silently widen the
780
780
  // query the way it used to.
781
781
  if (!conds.length) {
782
- throw new errors_js_1.ValidationError(`[turbine] internal: JSON filter on "${col.name}" compiled to no condition. This is a bug in turbine-orm.`);
782
+ throw new errors_js_1.ValidationError(`internal: JSON filter on "${col.name}" compiled to no condition. This is a bug in turbine-orm.`);
783
783
  }
784
784
  return conds.length > 1 ? `(${conds.join(' and ')})` : conds[0];
785
785
  }
@@ -805,7 +805,7 @@ class PowqlInterface {
805
805
  // missing-value row to match `notIn []`, so NO presence guard is appended here).
806
806
  return negate ? '(1 = 1)' : this.alwaysFalse();
807
807
  }
808
- if (col && (0, powdb_js_1.isPowdbDatetimeColumn)(col))
808
+ if (col && (0, powdb_shared_js_1.isPowdbDatetimeColumn)(col))
809
809
  return this.buildDatetimeInList(lhs, values, params, negate, col);
810
810
  const items = values.map((v) => this.bind(v, params, insensitive)).join(', ');
811
811
  if (negate) {
@@ -871,7 +871,7 @@ class PowqlInterface {
871
871
  * identically however the statement was assembled.
872
872
  */
873
873
  inClause(ref, values, params, col) {
874
- if (col && (0, powdb_js_1.isPowdbDatetimeColumn)(col)) {
874
+ if (col && (0, powdb_shared_js_1.isPowdbDatetimeColumn)(col)) {
875
875
  this.assertDatetimePredicateSupported(col);
876
876
  return this.buildDatetimeInList(ref, values, params, false, col);
877
877
  }
@@ -885,7 +885,7 @@ class PowqlInterface {
885
885
  */
886
886
  keyChunkSize(meta, colName) {
887
887
  const col = meta?.columns.find((c) => c.name === colName);
888
- return col && (0, powdb_js_1.isPowdbDatetimeColumn)(col) ? exports.MAX_POWQL_DATETIME_TERMS : MAX_RELATION_KEYS;
888
+ return col && (0, powdb_shared_js_1.isPowdbDatetimeColumn)(col) ? exports.MAX_POWQL_DATETIME_TERMS : MAX_RELATION_KEYS;
889
889
  }
890
890
  /**
891
891
  * Pre-resolve every relation filter (`some`/`none`/`every`) in a where clause
@@ -945,7 +945,7 @@ class PowqlInterface {
945
945
  }
946
946
  const targetMeta = this.schema.tables[rel.to];
947
947
  if (!targetMeta)
948
- throw new errors_js_1.ValidationError(`[turbine] Relation "${rel.name}" targets unknown table "${rel.to}".`);
948
+ throw new errors_js_1.ValidationError(`Relation "${rel.name}" targets unknown table "${rel.to}".`);
949
949
  // hasMany/hasOne: localKey = our referenceKey, collect the child's foreignKey.
950
950
  // belongsTo: localKey = our foreignKey, collect the target's referenceKey.
951
951
  const localCol = rel.type === 'belongsTo' ? fk[0] : rk[0];
@@ -974,13 +974,13 @@ class PowqlInterface {
974
974
  async resolveManyToManyCondition(rel, mode, innerWhere, innerEmpty, timeout) {
975
975
  const through = rel.through;
976
976
  if (!through)
977
- throw new errors_js_1.ValidationError(`[turbine] manyToMany relation "${rel.name}" is missing its junction (\`through\`).`);
977
+ throw new errors_js_1.ValidationError(`manyToMany relation "${rel.name}" is missing its junction (\`through\`).`);
978
978
  const sourceJ = (0, schema_js_1.normalizeKeyColumns)(through.sourceKey);
979
979
  const targetJ = (0, schema_js_1.normalizeKeyColumns)(through.targetKey);
980
980
  const sourceRef = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
981
981
  const targetMeta = this.schema.tables[rel.to];
982
982
  if (!targetMeta)
983
- throw new errors_js_1.ValidationError(`[turbine] Relation "${rel.name}" targets unknown table "${rel.to}".`);
983
+ throw new errors_js_1.ValidationError(`Relation "${rel.name}" targets unknown table "${rel.to}".`);
984
984
  if (sourceJ.length > 1 || targetJ.length > 1 || sourceRef.length > 1 || targetMeta.primaryKey.length > 1) {
985
985
  throw new errors_js_1.UnsupportedFeatureError('composite-key manyToMany filters', 'PowDB', `relation "${rel.name}", PowQL has no tuple-\`in\` for composite junction/target keys`);
986
986
  }
@@ -1012,7 +1012,7 @@ class PowqlInterface {
1012
1012
  const chunk = targetPks.slice(i, i + junctionChunk);
1013
1013
  const params = [];
1014
1014
  const keyClause = this.inClause(this.colRefName(targetJCol), chunk, params, targetJColMeta);
1015
- const { rows } = await this.exec(`${(0, powdb_js_1.quotePowqlIdent)(through.table)} filter ${keyClause} { ${this.colRefName(sourceJCol)} }`, params, timeout, 'findMany');
1015
+ const { rows } = await this.exec(`${(0, powdb_shared_js_1.quotePowqlIdent)(through.table)} filter ${keyClause} { ${this.colRefName(sourceJCol)} }`, params, timeout, 'findMany');
1016
1016
  for (const r of rows) {
1017
1017
  const v = r[sourceJCol];
1018
1018
  if (v != null)
@@ -1289,10 +1289,10 @@ class PowqlInterface {
1289
1289
  /** Compile one {@link JsonPathOrderBy} entry to `order .col->$n asc` (+ optional numeric cast). */
1290
1290
  buildJsonPathOrder(field, spec, params, alias) {
1291
1291
  const col = this.column(field);
1292
- if (!(0, powdb_js_1.isJsonColumn)(col)) {
1292
+ if (!(0, powdb_shared_js_1.isJsonColumn)(col)) {
1293
1293
  throw new errors_js_1.UnsupportedFeatureError('JSON-path ordering', 'PowDB', `field "${field}" is not a json column`);
1294
1294
  }
1295
- (0, powdb_js_1.requireCapability)(this.capabilities, 'jsonDocs', 'JSON path ordering');
1295
+ (0, powdb_shared_js_1.requireCapability)(this.capabilities, 'jsonDocs', 'JSON path ordering');
1296
1296
  if (spec.nulls === 'first') {
1297
1297
  throw new errors_js_1.UnsupportedFeatureError('NULLS FIRST placement', 'PowDB', `field "${field}": PowDB orders missing / JSON-null keys LAST in both directions`);
1298
1298
  }
@@ -1318,9 +1318,9 @@ class PowqlInterface {
1318
1318
  }
1319
1319
  /** Build the E018 refusal for a write / `begin` on a read-only pool. */
1320
1320
  readOnlyError(operation) {
1321
- // Pass a clean detail: the ReadOnlyError constructor owns both the
1322
- // `[turbine] ` prefix and the "Route writes to a writable primary." hint,
1323
- // so adding either here would double them.
1321
+ // Pass a clean detail: the ReadOnlyError constructor owns the "Route writes
1322
+ // to a writable primary." hint, so adding it here would double it. The
1323
+ // `[TURBINE_E018]` tag is added once, later, by formatErrorMessage.
1324
1324
  return new errors_js_1.ReadOnlyError(`${operation} on "${this.table}" refused: this PowDB connection is read-only.`);
1325
1325
  }
1326
1326
  /**
@@ -1382,7 +1382,7 @@ class PowqlInterface {
1382
1382
  return false;
1383
1383
  if (!POWQL_READ_ACTIONS.has(action))
1384
1384
  return false;
1385
- return (0, powdb_js_1.isStaleFramePowdbError)(err);
1385
+ return (0, powdb_shared_js_1.isStaleFramePowdbError)(err);
1386
1386
  }
1387
1387
  emit(action, sql, params, duration, rows, error) {
1388
1388
  if (!this.onQuery)
@@ -1428,7 +1428,7 @@ class PowqlInterface {
1428
1428
  * coerces its string cells correctly. Defaults to the pool capability for the
1429
1429
  * rare caller with no per-result flag (hand-built test pools). */
1430
1430
  shape(rows, native = Boolean(this.capabilities.nativeRaw)) {
1431
- return rows.map((r) => (0, powdb_js_1.rowToEntity)(r, this.meta, native));
1431
+ return rows.map((r) => (0, powdb_shared_js_1.rowToEntity)(r, this.meta, native));
1432
1432
  }
1433
1433
  // -------------------------------------------------------------------------
1434
1434
  // Reads
@@ -1556,7 +1556,7 @@ class PowqlInterface {
1556
1556
  // Aliased scan: every parent column keys itself (`col: t0.col`) so the
1557
1557
  // result columns keep their bare snake names, then the nested blocks.
1558
1558
  const aliasCtr = { n: 1 };
1559
- const parts = cols.map((c) => `${(0, powdb_js_1.quotePowqlIdent)(c)}: t0.${(0, powdb_js_1.quotePowqlIdent)(c)}`);
1559
+ const parts = cols.map((c) => `${(0, powdb_shared_js_1.quotePowqlIdent)(c)}: t0.${(0, powdb_shared_js_1.quotePowqlIdent)(c)}`);
1560
1560
  for (const plan of nestedPlans) {
1561
1561
  parts.push(await this.buildNestedBlock(plan, 't0', aliasCtr, params, args.timeout));
1562
1562
  }
@@ -1687,7 +1687,7 @@ class PowqlInterface {
1687
1687
  */
1688
1688
  async loadRelations(parents, withClause, timeout, depth = 0, parent, includePii = false) {
1689
1689
  if (depth >= 10) {
1690
- throw new errors_js_1.ValidationError(`[turbine] Nested 'with' on PowDB exceeded depth 10 (relation cycle?).`);
1690
+ throw new errors_js_1.ValidationError(`Nested 'with' on PowDB exceeded depth 10 (relation cycle?).`);
1691
1691
  }
1692
1692
  if (!parents.length)
1693
1693
  return;
@@ -1702,7 +1702,7 @@ class PowqlInterface {
1702
1702
  continue;
1703
1703
  const rel = this.meta.relations[relName];
1704
1704
  if (!rel)
1705
- throw new errors_js_1.ValidationError(`[turbine] Unknown relation "${relName}" on "${this.table}".`);
1705
+ throw new errors_js_1.ValidationError(`Unknown relation "${relName}" on "${this.table}".`);
1706
1706
  if (strategyIsJoin && parent && this.joinEligible(rel, opt, parent.args, parents.length)) {
1707
1707
  if (this.capabilities.serverJoins) {
1708
1708
  await this.loadRelationViaJoin(parents, rel, relName, opt, parent, timeout, includePii);
@@ -1713,7 +1713,7 @@ class PowqlInterface {
1713
1713
  // E017; a CLIENT-LEVEL default silently falls back to the keyed loaders
1714
1714
  // (so pointing an existing app at an older engine keeps working).
1715
1715
  if (parent.args.relationLoadStrategy === 'join') {
1716
- (0, powdb_js_1.requireCapability)(this.capabilities, 'serverJoins', 'native PowQL relation joins');
1716
+ (0, powdb_shared_js_1.requireCapability)(this.capabilities, 'serverJoins', 'native PowQL relation joins');
1717
1717
  }
1718
1718
  }
1719
1719
  if (rel.type === 'manyToMany') {
@@ -1829,13 +1829,13 @@ class PowqlInterface {
1829
1829
  async loadManyToMany(parents, rel, relName, opt, timeout, includePii = false) {
1830
1830
  const through = rel.through;
1831
1831
  if (!through)
1832
- throw new errors_js_1.ValidationError(`[turbine] manyToMany relation "${relName}" is missing its junction (\`through\`).`);
1832
+ throw new errors_js_1.ValidationError(`manyToMany relation "${relName}" is missing its junction (\`through\`).`);
1833
1833
  const sourceJ = (0, schema_js_1.normalizeKeyColumns)(through.sourceKey);
1834
1834
  const targetJ = (0, schema_js_1.normalizeKeyColumns)(through.targetKey);
1835
1835
  const sourceRef = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
1836
1836
  const targetMeta = this.schema.tables[rel.to];
1837
1837
  if (!targetMeta)
1838
- throw new errors_js_1.ValidationError(`[turbine] Relation "${relName}" targets unknown table "${rel.to}".`);
1838
+ throw new errors_js_1.ValidationError(`Relation "${relName}" targets unknown table "${rel.to}".`);
1839
1839
  if (sourceJ.length > 1 || targetJ.length > 1 || sourceRef.length > 1 || targetMeta.primaryKey.length > 1) {
1840
1840
  throw new errors_js_1.UnsupportedFeatureError('composite-key manyToMany', 'PowDB', `relation "${relName}", PowQL has no tuple-\`in\`, so composite junction/target keys can't be loaded`);
1841
1841
  }
@@ -1864,7 +1864,7 @@ class PowqlInterface {
1864
1864
  const chunk = parentKeys.slice(i, i + junctionChunk);
1865
1865
  const params = [];
1866
1866
  const keyClause = this.inClause(this.colRefName(sourceJCol), chunk, params, sourceJColMeta);
1867
- const powql = `${(0, powdb_js_1.quotePowqlIdent)(through.table)} filter ${keyClause} ` +
1867
+ const powql = `${(0, powdb_shared_js_1.quotePowqlIdent)(through.table)} filter ${keyClause} ` +
1868
1868
  `{ ${this.colRefName(sourceJCol)}, ${this.colRefName(targetJCol)} }`;
1869
1869
  const { rows } = await this.exec(powql, params, timeout, 'findMany');
1870
1870
  for (const row of rows) {
@@ -2069,7 +2069,7 @@ class PowqlInterface {
2069
2069
  const options = (opt === true ? {} : opt);
2070
2070
  const targetMeta = this.schema.tables[rel.to];
2071
2071
  if (!targetMeta)
2072
- throw new errors_js_1.ValidationError(`[turbine] Relation "${relName}" targets unknown table "${rel.to}".`);
2072
+ throw new errors_js_1.ValidationError(`Relation "${relName}" targets unknown table "${rel.to}".`);
2073
2073
  const targetQi = new PowqlInterface(this.pool, rel.to, this.schema, [], this.options);
2074
2074
  const fk = (0, schema_js_1.normalizeKeyColumns)(rel.foreignKey);
2075
2075
  const rk = (0, schema_js_1.normalizeKeyColumns)(rel.referenceKey);
@@ -2087,9 +2087,9 @@ class PowqlInterface {
2087
2087
  this.assertPagination(options.limit, options.offset, `relation "${relName}"`);
2088
2088
  const limitClause = options.limit !== undefined ? ` limit ${this.param(options.limit, params)}` : '';
2089
2089
  const offsetClause = options.offset ? ` offset ${this.param(options.offset, params)}` : '';
2090
- const proj = this.joinProjection(childCols, `p.${(0, powdb_js_1.quotePowqlIdent)(parentKeyCol)}`, 'c');
2090
+ const proj = this.joinProjection(childCols, `p.${(0, powdb_shared_js_1.quotePowqlIdent)(parentKeyCol)}`, 'c');
2091
2091
  const powql = `${targetQi.qt} as c join ${this.qt} as p ` +
2092
- `on c.${(0, powdb_js_1.quotePowqlIdent)(childKeyCol)} = p.${(0, powdb_js_1.quotePowqlIdent)(parentKeyCol)}` +
2092
+ `on c.${(0, powdb_shared_js_1.quotePowqlIdent)(childKeyCol)} = p.${(0, powdb_shared_js_1.quotePowqlIdent)(parentKeyCol)}` +
2093
2093
  `${filter}${order}${limitClause}${offsetClause} ${proj}`;
2094
2094
  // A READ: thread a read-shaped action through the exec seam.
2095
2095
  const { rows, native } = await targetQi.exec(powql, params, timeout, 'findMany');
@@ -2109,11 +2109,11 @@ class PowqlInterface {
2109
2109
  async loadManyToManyViaJoin(parents, rel, relName, opt, parent, timeout, includePii = false) {
2110
2110
  const through = rel.through;
2111
2111
  if (!through)
2112
- throw new errors_js_1.ValidationError(`[turbine] manyToMany relation "${relName}" is missing its junction (\`through\`).`);
2112
+ throw new errors_js_1.ValidationError(`manyToMany relation "${relName}" is missing its junction (\`through\`).`);
2113
2113
  const options = (opt === true ? {} : opt);
2114
2114
  const targetMeta = this.schema.tables[rel.to];
2115
2115
  if (!targetMeta)
2116
- throw new errors_js_1.ValidationError(`[turbine] Relation "${relName}" targets unknown table "${rel.to}".`);
2116
+ throw new errors_js_1.ValidationError(`Relation "${relName}" targets unknown table "${rel.to}".`);
2117
2117
  const targetQi = new PowqlInterface(this.pool, rel.to, this.schema, [], this.options);
2118
2118
  const sourceJCol = (0, schema_js_1.normalizeKeyColumns)(through.sourceKey)[0];
2119
2119
  const targetJCol = (0, schema_js_1.normalizeKeyColumns)(through.targetKey)[0];
@@ -2123,10 +2123,10 @@ class PowqlInterface {
2123
2123
  const params = [];
2124
2124
  const { cols: childCols, forcedPk: childForcedPk } = this.joinChildCols(targetQi, options, includePii);
2125
2125
  const filter = await this.joinFilter(targetQi, parent.resolvedWhere, options.where, 't', params, options.timeout ?? timeout);
2126
- const proj = this.joinProjection(childCols, `j.${(0, powdb_js_1.quotePowqlIdent)(sourceJCol)}`, 't');
2126
+ const proj = this.joinProjection(childCols, `j.${(0, powdb_shared_js_1.quotePowqlIdent)(sourceJCol)}`, 't');
2127
2127
  const powql = `${targetQi.qt} as t ` +
2128
- `join ${(0, powdb_js_1.quotePowqlIdent)(through.table)} as j on t.${(0, powdb_js_1.quotePowqlIdent)(targetPkCol)} = j.${(0, powdb_js_1.quotePowqlIdent)(targetJCol)} ` +
2129
- `join ${this.qt} as p on j.${(0, powdb_js_1.quotePowqlIdent)(sourceJCol)} = p.${(0, powdb_js_1.quotePowqlIdent)(sourceRefCol)}` +
2128
+ `join ${(0, powdb_shared_js_1.quotePowqlIdent)(through.table)} as j on t.${(0, powdb_shared_js_1.quotePowqlIdent)(targetPkCol)} = j.${(0, powdb_shared_js_1.quotePowqlIdent)(targetJCol)} ` +
2129
+ `join ${this.qt} as p on j.${(0, powdb_shared_js_1.quotePowqlIdent)(sourceJCol)} = p.${(0, powdb_shared_js_1.quotePowqlIdent)(sourceRefCol)}` +
2130
2130
  `${filter} ${proj}`;
2131
2131
  const { rows, native } = await targetQi.exec(powql, params, timeout, 'findMany');
2132
2132
  const byKey = this.bucketByTpk(targetQi, rows, native, childForcedPk);
@@ -2143,7 +2143,7 @@ class PowqlInterface {
2143
2143
  joinChildCols(targetQi, options, includePii = false) {
2144
2144
  const plan = targetQi.projectionPlan(options.select, options.omit, includePii);
2145
2145
  if (plan.cols.includes('__tpk')) {
2146
- throw new errors_js_1.ValidationError(`[turbine] relation target "${targetQi.table}" has a column named "__tpk", which collides with the reserved ` +
2146
+ throw new errors_js_1.ValidationError(`relation target "${targetQi.table}" has a column named "__tpk", which collides with the reserved ` +
2147
2147
  `join correlation alias. Rename the column or load this relation with relationLoadStrategy: 'batched'.`);
2148
2148
  }
2149
2149
  return plan;
@@ -2156,7 +2156,7 @@ class PowqlInterface {
2156
2156
  joinProjection(childCols, tpkExpr, childAlias) {
2157
2157
  const parts = [
2158
2158
  `__tpk: ${tpkExpr}`,
2159
- ...childCols.map((c) => `${(0, powdb_js_1.quotePowqlIdent)(c)}: ${childAlias}.${(0, powdb_js_1.quotePowqlIdent)(c)}`),
2159
+ ...childCols.map((c) => `${(0, powdb_shared_js_1.quotePowqlIdent)(c)}: ${childAlias}.${(0, powdb_shared_js_1.quotePowqlIdent)(c)}`),
2160
2160
  ];
2161
2161
  return `{ ${parts.join(', ')} }`;
2162
2162
  }
@@ -2278,7 +2278,7 @@ class PowqlInterface {
2278
2278
  const { cols, forcedPk } = targetQi.projectionPlan(options.select, options.omit, includePii);
2279
2279
  const byName = new Map(targetQi.meta.columns.map((c) => [c.name, c]));
2280
2280
  for (const c of cols) {
2281
- const ts = (byName.get(c)?.tsType ?? '').replace(/\s*\|\s*null$/i, '').trim();
2281
+ const ts = (0, powdb_shared_js_1.baseTsType)(byName.get(c)?.tsType ?? '');
2282
2282
  if (ts === 'bigint' || ts === 'Uint8Array')
2283
2283
  return null;
2284
2284
  }
@@ -2326,7 +2326,7 @@ class PowqlInterface {
2326
2326
  // Exactly one equi-correlation predicate (the 0.18 correlation rule); the
2327
2327
  // child where chains behind it as a parenthesized `and` group, which the
2328
2328
  // grammar accepts even when the group itself contains `or`.
2329
- const correlation = `${alias}.${(0, powdb_js_1.quotePowqlIdent)(childKeyCol)} = ${parentAlias}.${(0, powdb_js_1.quotePowqlIdent)(parentKeyCol)}`;
2329
+ const correlation = `${alias}.${(0, powdb_shared_js_1.quotePowqlIdent)(childKeyCol)} = ${parentAlias}.${(0, powdb_shared_js_1.quotePowqlIdent)(parentKeyCol)}`;
2330
2330
  const resolved = await targetQi.resolveRelationFilters(options.where, timeout);
2331
2331
  const childWhere = targetQi.buildWhere(resolved, params, alias);
2332
2332
  const filter = childWhere ? `${correlation} and (${childWhere})` : correlation;
@@ -2337,11 +2337,11 @@ class PowqlInterface {
2337
2337
  ? ` limit ${this.param(options.limit, params)}`
2338
2338
  : '';
2339
2339
  const offsetClause = !single && options.offset ? ` offset ${this.param(options.offset, params)}` : '';
2340
- const parts = plan.cols.map((c) => `${(0, powdb_js_1.quotePowqlIdent)(c)}: ${alias}.${(0, powdb_js_1.quotePowqlIdent)(c)}`);
2340
+ const parts = plan.cols.map((c) => `${(0, powdb_shared_js_1.quotePowqlIdent)(c)}: ${alias}.${(0, powdb_shared_js_1.quotePowqlIdent)(c)}`);
2341
2341
  for (const child of plan.children) {
2342
2342
  parts.push(await targetQi.buildNestedBlock(child, alias, aliasCtr, params, timeout));
2343
2343
  }
2344
- return (`${(0, powdb_js_1.quotePowqlIdent)(relName)}: ${targetQi.qt} as ${alias} ` +
2344
+ return (`${(0, powdb_shared_js_1.quotePowqlIdent)(relName)}: ${targetQi.qt} as ${alias} ` +
2345
2345
  `filter ${filter}${order}${limitClause}${offsetClause} { ${parts.join(', ')} }`);
2346
2346
  }
2347
2347
  /**
@@ -2370,7 +2370,7 @@ class PowqlInterface {
2370
2370
  }
2371
2371
  }
2372
2372
  const items = Array.isArray(value) ? value : [];
2373
- const shaped = items.map((o) => (0, powdb_js_1.rowToEntity)(o, plan.targetQi.meta, true));
2373
+ const shaped = items.map((o) => (0, powdb_shared_js_1.rowToEntity)(o, plan.targetQi.meta, true));
2374
2374
  for (const child of shaped) {
2375
2375
  for (const sub of plan.children)
2376
2376
  plan.targetQi.attachOneNested(child, sub);
@@ -2415,7 +2415,7 @@ class PowqlInterface {
2415
2415
  }
2416
2416
  /** True when `name` is a bare PowQL identifier (quoting leaves it unchanged). */
2417
2417
  isBareIdent(name) {
2418
- return (0, powdb_js_1.quotePowqlIdent)(name) === name;
2418
+ return (0, powdb_shared_js_1.quotePowqlIdent)(name) === name;
2419
2419
  }
2420
2420
  /**
2421
2421
  * Find the declared to-one link on THIS table that matches `rel` exactly: same
@@ -2485,7 +2485,7 @@ class PowqlInterface {
2485
2485
  // at least one projected child column is bigint/bytes. Otherwise nested
2486
2486
  // projections already handle it (and cache), so leave it to them.
2487
2487
  const hasCarrierBlockedCol = userCols.some((c) => {
2488
- const ts = (byName.get(c)?.tsType ?? '').replace(/\s*\|\s*null$/i, '').trim();
2488
+ const ts = (0, powdb_shared_js_1.baseTsType)(byName.get(c)?.tsType ?? '');
2489
2489
  return ts === 'bigint' || ts === 'Uint8Array';
2490
2490
  });
2491
2491
  if (!hasCarrierBlockedCol)
@@ -2530,8 +2530,8 @@ class PowqlInterface {
2530
2530
  * parse exactly like their bare forms and yield the same result-column names.
2531
2531
  */
2532
2532
  linkPathFields(plan, parentAlias) {
2533
- const link = (0, powdb_js_1.quotePowqlDotted)(plan.linkName);
2534
- return plan.cols.map((c) => `${(0, powdb_js_1.quotePowqlIdent)(`${plan.keyPrefix}${c}`)}: ${parentAlias}.${link}.${(0, powdb_js_1.quotePowqlDotted)(c)}`);
2533
+ const link = (0, powdb_shared_js_1.quotePowqlDotted)(plan.linkName);
2534
+ return plan.cols.map((c) => `${(0, powdb_shared_js_1.quotePowqlIdent)(`${plan.keyPrefix}${c}`)}: ${parentAlias}.${link}.${(0, powdb_shared_js_1.quotePowqlDotted)(c)}`);
2535
2535
  }
2536
2536
  /**
2537
2537
  * Reconstruct each link-path relation's child entity from its flat hop fields
@@ -2553,7 +2553,7 @@ class PowqlInterface {
2553
2553
  raw[c] = row[`${plan.keyPrefix}${c}`];
2554
2554
  delete row[`${plan.keyPrefix}${c}`];
2555
2555
  }
2556
- const child = (0, powdb_js_1.rowToEntity)(raw, plan.targetQi.meta, native);
2556
+ const child = (0, powdb_shared_js_1.rowToEntity)(raw, plan.targetQi.meta, native);
2557
2557
  if (child[pkField] == null) {
2558
2558
  row[plan.relName] = null;
2559
2559
  continue;
@@ -2610,7 +2610,7 @@ class PowqlInterface {
2610
2610
  * statement; plain `this.table` stays in error messages.
2611
2611
  */
2612
2612
  get qt() {
2613
- return (0, powdb_js_1.quotePowqlIdent)(this.table);
2613
+ return (0, powdb_shared_js_1.quotePowqlIdent)(this.table);
2614
2614
  }
2615
2615
  async create(args) {
2616
2616
  return this.withMiddleware('create', args, async () => {
@@ -2621,7 +2621,7 @@ class PowqlInterface {
2621
2621
  const assigns = this.scalarData(data);
2622
2622
  const params = [];
2623
2623
  const body = assigns
2624
- .map((a) => `${(0, powdb_js_1.quotePowqlIdent)(a.col.name)} := ${this.writeRef(a.value, a.col, params)}`)
2624
+ .map((a) => `${(0, powdb_shared_js_1.quotePowqlIdent)(a.col.name)} := ${this.writeRef(a.value, a.col, params)}`)
2625
2625
  .join(', ');
2626
2626
  // `returning` surfaces the inserted row (all columns, schema order) in one round-trip.
2627
2627
  const { rows, native } = await this.exec(`insert ${this.qt} { ${body} } returning`, params, args.timeout, 'create');
@@ -2669,7 +2669,7 @@ class PowqlInterface {
2669
2669
  parts.push(`does not supply ${quoteList(missing)}`);
2670
2670
  if (unexpected.length > 0)
2671
2671
  parts.push(`supplies ${quoteList(unexpected)}, which the first row does not`);
2672
- throw new errors_js_1.ValidationError(`[turbine] createMany on "${this.table}": row ${i} ${parts.join(' and ')}. ` +
2672
+ throw new errors_js_1.ValidationError(`createMany on "${this.table}": row ${i} ${parts.join(' and ')}. ` +
2673
2673
  'Every row must supply the same fields (a field set to `undefined` counts as omitted, exactly as it does ' +
2674
2674
  'in `create`). PowQL itself would insert the ragged rows, but the SQL engines build ONE statement whose ' +
2675
2675
  "column list comes from the first row, so there a later row's extra field is dropped and a field it " +
@@ -2691,7 +2691,7 @@ class PowqlInterface {
2691
2691
  const params = [];
2692
2692
  const tuples = inputs.map((d) => {
2693
2693
  const assigns = this.scalarData(d);
2694
- return `{ ${assigns.map((a) => `${(0, powdb_js_1.quotePowqlIdent)(a.col.name)} := ${this.writeRef(a.value, a.col, params)}`).join(', ')} }`;
2694
+ return `{ ${assigns.map((a) => `${(0, powdb_shared_js_1.quotePowqlIdent)(a.col.name)} := ${this.writeRef(a.value, a.col, params)}`).join(', ')} }`;
2695
2695
  });
2696
2696
  // Multi-row insert with `returning` hands back every inserted row in one round-trip.
2697
2697
  const { rows, native } = await this.exec(`insert ${this.qt} ${tuples.join(', ')} returning`, params, args.timeout, 'createMany');
@@ -2721,7 +2721,7 @@ class PowqlInterface {
2721
2721
  // by a caller who believed they held the lock.
2722
2722
  const lock = args.optimisticLock;
2723
2723
  if (lock) {
2724
- const versionCol = (0, powdb_js_1.quotePowqlIdent)(this.column(lock.field).name);
2724
+ const versionCol = (0, powdb_shared_js_1.quotePowqlIdent)(this.column(lock.field).name);
2725
2725
  setClause += `, ${versionCol} := ${this.ref(lock.field)} + 1`;
2726
2726
  params.push(lock.expected);
2727
2727
  const check = `${this.ref(lock.field)} = $${params.length}`;
@@ -2767,7 +2767,7 @@ class PowqlInterface {
2767
2767
  }
2768
2768
  const colMeta = this.column(field);
2769
2769
  const ref = this.ref(field);
2770
- const col = (0, powdb_js_1.quotePowqlIdent)(colMeta.name);
2770
+ const col = (0, powdb_shared_js_1.quotePowqlIdent)(colMeta.name);
2771
2771
  if (value !== null && typeof value === 'object' && !(value instanceof Date)) {
2772
2772
  const opObj = value;
2773
2773
  if ('set' in opObj)
@@ -2781,14 +2781,14 @@ class PowqlInterface {
2781
2781
  else if ('divide' in opObj)
2782
2782
  parts.push(`${col} := ${ref} / ${this.writeRef(opObj.divide, colMeta, params)}`);
2783
2783
  else
2784
- throw new errors_js_1.ValidationError(`[turbine] Unsupported update operator on "${field}".`);
2784
+ throw new errors_js_1.ValidationError(`Unsupported update operator on "${field}".`);
2785
2785
  }
2786
2786
  else {
2787
2787
  parts.push(`${col} := ${this.writeRef(value, colMeta, params)}`);
2788
2788
  }
2789
2789
  }
2790
2790
  if (!parts.length)
2791
- throw new errors_js_1.ValidationError(`[turbine] update on "${this.table}" has no fields to set.`);
2791
+ throw new errors_js_1.ValidationError(`update on "${this.table}" has no fields to set.`);
2792
2792
  return parts.join(', ');
2793
2793
  }
2794
2794
  // -------------------------------------------------------------------------
@@ -2918,7 +2918,7 @@ class PowqlInterface {
2918
2918
  }
2919
2919
  const params = [];
2920
2920
  const createBody = this.scalarData(createData)
2921
- .map((a) => `${(0, powdb_js_1.quotePowqlIdent)(a.col.name)} := ${this.writeRef(a.value, a.col, params)}`)
2921
+ .map((a) => `${(0, powdb_shared_js_1.quotePowqlIdent)(a.col.name)} := ${this.writeRef(a.value, a.col, params)}`)
2922
2922
  .join(', ');
2923
2923
  const updateBody = this.buildUpdateAssignments(args.update, params);
2924
2924
  // PowDB 0.7.0's `upsert` statement does NOT accept a trailing `returning`
@@ -2950,7 +2950,7 @@ class PowqlInterface {
2950
2950
  return { field, value: createData[field] ?? createData[pk] };
2951
2951
  });
2952
2952
  if (pkPairs.some((p) => p.value == null)) {
2953
- throw new errors_js_1.ValidationError(`[turbine] upsert on "${this.table}" needs every composite-PK field in \`create\` (${pkPairs
2953
+ throw new errors_js_1.ValidationError(`upsert on "${this.table}" needs every composite-PK field in \`create\` (${pkPairs
2954
2954
  .map((p) => p.field)
2955
2955
  .join(', ')}).`);
2956
2956
  }
@@ -3003,7 +3003,7 @@ class PowqlInterface {
3003
3003
  const col = this.column(field);
3004
3004
  if (!col.nullable)
3005
3005
  return;
3006
- (0, powdb_js_1.requireCapability)(this.capabilities, 'projectedCountNonNull', `per-field \`_count\` of the nullable column "${col.name}"`, 'Below that version the engine ignored the column projection and returned the ROW count, which differs from ' +
3006
+ (0, powdb_shared_js_1.requireCapability)(this.capabilities, 'projectedCountNonNull', `per-field \`_count\` of the nullable column "${col.name}"`, 'Below that version the engine ignored the column projection and returned the ROW count, which differs from ' +
3007
3007
  'every SQL engine exactly when the column is nullable. `_count: true` (a row count) and a per-field ' +
3008
3008
  '`_count` of a NOT NULL column are correct on every version and are never refused.');
3009
3009
  }
@@ -3068,7 +3068,7 @@ class PowqlInterface {
3068
3068
  return spec !== undefined && Object.values(spec).some((v) => v != null && typeof v === 'object');
3069
3069
  });
3070
3070
  if (usesJson) {
3071
- (0, powdb_js_1.requireCapability)(this.capabilities, 'jsonDocs', 'JSON-path groupBy keys / aggregate targets');
3071
+ (0, powdb_shared_js_1.requireCapability)(this.capabilities, 'jsonDocs', 'JSON-path groupBy keys / aggregate targets');
3072
3072
  }
3073
3073
  // `emitNative` decides whether the query GENERATION needs the legacy-wire
3074
3074
  // `json_type` discriminator (pool-level capability). The DECODE side reads
@@ -3086,7 +3086,7 @@ class PowqlInterface {
3086
3086
  const usedKeys = new Set();
3087
3087
  const claim = (key, what) => {
3088
3088
  if (key === '_count' || usedKeys.has(key)) {
3089
- throw new errors_js_1.ValidationError(`[turbine] groupBy output name "${key}" (${what}) collides with another output column on table ` +
3089
+ throw new errors_js_1.ValidationError(`groupBy output name "${key}" (${what}) collides with another output column on table ` +
3090
3090
  `"${this.table}": set an explicit \`alias\` (or rename the aggregate key) to disambiguate.`);
3091
3091
  }
3092
3092
  usedKeys.add(key);
@@ -3116,8 +3116,8 @@ class PowqlInterface {
3116
3116
  }
3117
3117
  else {
3118
3118
  const col = this.column(entry.field);
3119
- if (!(0, powdb_js_1.isJsonColumn)(col)) {
3120
- throw new errors_js_1.ValidationError(`[turbine] groupBy JSON group key on "${entry.field}" (table "${this.table}") requires a json column.`);
3119
+ if (!(0, powdb_shared_js_1.isJsonColumn)(col)) {
3120
+ throw new errors_js_1.ValidationError(`groupBy JSON group key on "${entry.field}" (table "${this.table}") requires a json column.`);
3121
3121
  }
3122
3122
  (0, aggregates_js_1.assertAggregatePiiOptIn)(this.table, this.meta, entry.field, col.name, 'groupBy JSON `by` key', (0, types_js_1.resolveUnsafeFlag)(args.includePii, 'includePii'));
3123
3123
  this.assertJsonPath('group key', entry.field, entry.path);
@@ -3222,8 +3222,8 @@ class PowqlInterface {
3222
3222
  }
3223
3223
  else {
3224
3224
  const col = this.column(target.field);
3225
- if (!(0, powdb_js_1.isJsonColumn)(col)) {
3226
- throw new errors_js_1.ValidationError(`[turbine] groupBy ${fn} target "${key}" on "${target.field}" (table "${this.table}") requires a json column.`);
3225
+ if (!(0, powdb_shared_js_1.isJsonColumn)(col)) {
3226
+ throw new errors_js_1.ValidationError(`groupBy ${fn} target "${key}" on "${target.field}" (table "${this.table}") requires a json column.`);
3227
3227
  }
3228
3228
  if (fn === '_min' || fn === '_max') {
3229
3229
  (0, aggregates_js_1.assertAggregatePiiOptIn)(this.table, this.meta, target.field, col.name, `groupBy ${fn} JSON target`, (0, types_js_1.resolveUnsafeFlag)(args.includePii, 'includePii'));
@@ -3231,7 +3231,7 @@ class PowqlInterface {
3231
3231
  this.assertJsonPath(`${fn} target "${key}"`, target.field, target.path);
3232
3232
  const alwaysNumeric = fn === '_sum' || fn === '_avg';
3233
3233
  if (alwaysNumeric && target.type === 'text') {
3234
- throw new errors_js_1.ValidationError(`[turbine] groupBy ${fn} target "${key}" on table "${this.table}": ` +
3234
+ throw new errors_js_1.ValidationError(`groupBy ${fn} target "${key}" on table "${this.table}": ` +
3235
3235
  `${fn} over a JSON path is always numeric: remove \`type: 'text'\`.`);
3236
3236
  }
3237
3237
  const numeric = alwaysNumeric || target.type === 'numeric';
@@ -3270,7 +3270,7 @@ class PowqlInterface {
3270
3270
  if (r.kind === 'plain') {
3271
3271
  const cell = raw[r.rowKey];
3272
3272
  out[r.resultKey] = resultNative
3273
- ? (0, powdb_js_1.coerceNativeValue)(cell, r.col)
3273
+ ? (0, powdb_shared_js_1.coerceNativeValue)(cell, r.col)
3274
3274
  : typeof cell === 'string'
3275
3275
  ? coerceScalar(cell, r.col.tsType)
3276
3276
  : cell;
@@ -3299,7 +3299,7 @@ class PowqlInterface {
3299
3299
  if (!Array.isArray(path) ||
3300
3300
  path.length === 0 ||
3301
3301
  path.some((el) => typeof el !== 'string' && !(typeof el === 'number' && Number.isFinite(el)))) {
3302
- throw new errors_js_1.ValidationError(`[turbine] groupBy ${context} on "${field}" (table "${this.table}") requires a non-empty \`path\` ` +
3302
+ throw new errors_js_1.ValidationError(`groupBy ${context} on "${field}" (table "${this.table}") requires a non-empty \`path\` ` +
3303
3303
  `array of keys/indexes (e.g. { field: '${field}', path: ['category'] }).`);
3304
3304
  }
3305
3305
  }
@@ -3351,7 +3351,7 @@ class PowqlInterface {
3351
3351
  // must come from the fixed allowlist, never from the caller's key.
3352
3352
  const fn = POWQL_HAVING_AGG_FNS.get(aggKey);
3353
3353
  if (!fn) {
3354
- throw new errors_js_1.ValidationError(`[turbine] Unknown aggregate "${aggKey}" in having for field "${key}" on table "${this.table}". ` +
3354
+ throw new errors_js_1.ValidationError(`Unknown aggregate "${aggKey}" in having for field "${key}" on table "${this.table}". ` +
3355
3355
  `Supported: ${[...POWQL_HAVING_AGG_FNS.keys()].join(', ')}.`);
3356
3356
  }
3357
3357
  const inner = this.lookupGroupKey(aggInner, key) ?? this.ref(key);
@@ -3389,14 +3389,14 @@ class PowqlInterface {
3389
3389
  if (key === '_count') {
3390
3390
  const expr = aggOrderExprs.get('_count');
3391
3391
  if (!expr) {
3392
- throw new errors_js_1.ValidationError(`[turbine] Cannot order groupBy by "_count" on table "${this.table}": _count is not selected. ` +
3392
+ throw new errors_js_1.ValidationError(`Cannot order groupBy by "_count" on table "${this.table}": _count is not selected. ` +
3393
3393
  `Orderable keys: ${validKeys()}.`);
3394
3394
  }
3395
3395
  parts.push(`${expr} ${this.groupOrderDir(value, '_count')}`);
3396
3396
  continue;
3397
3397
  }
3398
3398
  if (typeof value !== 'object' || value === null || Array.isArray(value)) {
3399
- throw new errors_js_1.ValidationError(`[turbine] Invalid groupBy orderBy for "${key}" on table "${this.table}": ` +
3399
+ throw new errors_js_1.ValidationError(`Invalid groupBy orderBy for "${key}" on table "${this.table}": ` +
3400
3400
  `expected a field map like { ${key}: { amount: 'desc' } }.`);
3401
3401
  }
3402
3402
  for (const [field, dirSpec] of Object.entries(value)) {
@@ -3406,7 +3406,7 @@ class PowqlInterface {
3406
3406
  // the registry is keyed by the canonical one.
3407
3407
  const expr = aggOrderExprs.get(`${key}:${field}`) ?? this.aggOrderExpr(aggOrderExprs, key, field);
3408
3408
  if (!expr) {
3409
- throw new errors_js_1.ValidationError(`[turbine] Cannot order groupBy by "${key}.${field}" on table "${this.table}": ` +
3409
+ throw new errors_js_1.ValidationError(`Cannot order groupBy by "${key}.${field}" on table "${this.table}": ` +
3410
3410
  `that aggregate is not requested in this call. Orderable keys: ${validKeys()}.`);
3411
3411
  }
3412
3412
  parts.push(`${expr} ${this.groupOrderDir(dirSpec, `${key}.${field}`)}`);
@@ -3415,7 +3415,7 @@ class PowqlInterface {
3415
3415
  }
3416
3416
  const expr = this.lookupGroupKey(byOrderExprs, key);
3417
3417
  if (!expr) {
3418
- throw new errors_js_1.ValidationError(`[turbine] Unknown field "${key}" in groupBy orderBy on table "${this.table}". Orderable keys: ${validKeys()}.`);
3418
+ throw new errors_js_1.ValidationError(`Unknown field "${key}" in groupBy orderBy on table "${this.table}". Orderable keys: ${validKeys()}.`);
3419
3419
  }
3420
3420
  parts.push(`${expr} ${this.groupOrderDir(value, key)}`);
3421
3421
  }
@@ -3505,7 +3505,7 @@ class PowqlInterface {
3505
3505
  return;
3506
3506
  if (compiledWhere.length > 0)
3507
3507
  return;
3508
- throw new errors_js_1.ValidationError(`[turbine] ${action} on "${this.table}" refused: the \`where\` clause is empty. ` +
3508
+ throw new errors_js_1.ValidationError(`${action} on "${this.table}" refused: the \`where\` clause is empty. ` +
3509
3509
  "Pass `allowFullTableScan: UNSAFE` to opt in (import { UNSAFE } from 'turbine-orm'), " +
3510
3510
  'or check that your filter values are defined.');
3511
3511
  }
@@ -3513,7 +3513,7 @@ class PowqlInterface {
3513
3513
  exports.PowqlInterface = PowqlInterface;
3514
3514
  /** Coerce a group-key scalar string by the column's TS type (numbers/bools). */
3515
3515
  function coerceScalar(raw, tsType) {
3516
- const ts = tsType.replace(/\s*\|\s*null$/i, '').trim();
3516
+ const ts = (0, powdb_shared_js_1.baseTsType)(tsType);
3517
3517
  if (raw === 'null')
3518
3518
  return null;
3519
3519
  if (ts === 'number' || ts === 'bigint') {