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/powql.d.ts CHANGED
@@ -34,7 +34,7 @@
34
34
  *
35
35
  * @module
36
36
  */
37
- import { type PowdbPool } from './powdb.js';
37
+ import type { PowdbPool } from './powdb.js';
38
38
  import type { MiddlewareFn, QueryInterfaceOptions } from './query/index.js';
39
39
  import type { AggregateArgs, AggregateResult, CountArgs, CreateArgs, CreateManyArgs, DeleteArgs, DeleteManyArgs, FindManyArgs, FindUniqueArgs, GroupByArgs, UpdateArgs, UpdateManyArgs, UpsertArgs } from './query/types.js';
40
40
  import { type SchemaMetadata } from './schema.js';
package/dist/powql.js CHANGED
@@ -37,7 +37,7 @@
37
37
  import { randomUUID } from 'node:crypto';
38
38
  import { NotFoundError, OptimisticLockError, ReadOnlyError, TimeoutError, UnsupportedFeatureError, ValidationError, } from './errors.js';
39
39
  import { executeNestedCreate, executeNestedUpdate, hasRelationFields, } from './nested-write.js';
40
- import { ALL_POWDB_CAPABILITIES, coerceNativeValue, isJsonColumn, isPowdbDatetimeColumn, isStaleFramePowdbError, PowdbFloatParam, PowdbJsonParam, powqlColumnType, quotePowqlDotted, quotePowqlIdent, requireCapability, rowToEntity, } from './powdb.js';
40
+ import { ALL_POWDB_CAPABILITIES, baseTsType, coerceNativeValue, isJsonColumn, isPowdbDatetimeColumn, isStaleFramePowdbError, PowdbFloatParam, PowdbJsonParam, powqlColumnType, quotePowqlDotted, quotePowqlIdent, requireCapability, rowToEntity, } from './powdb-shared.js';
41
41
  import { assertAggregatePiiOptIn } from './query/aggregates.js';
42
42
  import { assertWhereIdentifiesOneRow, expandCompoundUniqueWhere } from './query/compound-unique.js';
43
43
  import { ARRAY_OPERATOR_KEYS, isJsonFilter, isRelationPickOrderBy, orderByEntries } from './query/filters.js';
@@ -189,7 +189,7 @@ export class PowqlInterface {
189
189
  this.options = options;
190
190
  const meta = schema.tables[table];
191
191
  if (!meta) {
192
- throw new ValidationError(`[turbine] Unknown table "${table}". ${availableClause(Object.keys(schema.tables), 'The schema has no tables.')}`);
192
+ throw new ValidationError(`Unknown table "${table}". ${availableClause(Object.keys(schema.tables), 'The schema has no tables.')}`);
193
193
  }
194
194
  this.meta = meta;
195
195
  this.defaultLimit = options.defaultLimit;
@@ -222,7 +222,7 @@ export class PowqlInterface {
222
222
  const snake = resolved ?? ownLookup(this.meta.columnMap, field) ?? field;
223
223
  const col = this.meta.columns.find((c) => c.name === snake || c.field === field);
224
224
  if (!col) {
225
- throw new ValidationError(`[turbine] Unknown column "${field}" on table "${this.table}". Known: ${this.meta.columns
225
+ throw new ValidationError(`Unknown column "${field}" on table "${this.table}". Known: ${this.meta.columns
226
226
  .map((c) => c.field)
227
227
  .join(', ')}`);
228
228
  }
@@ -326,7 +326,7 @@ export class PowqlInterface {
326
326
  */
327
327
  writeRef(value, col, params) {
328
328
  if (typeof value === 'number' && !Number.isFinite(value) && this.isFloatCol(col)) {
329
- throw new ValidationError(`[turbine] Non-finite value for float column "${col.name}" on "${this.table}".`);
329
+ throw new ValidationError(`Non-finite value for float column "${col.name}" on "${this.table}".`);
330
330
  }
331
331
  return this.param(value, params, col);
332
332
  }
@@ -452,7 +452,7 @@ export class PowqlInterface {
452
452
  ['offset', offset],
453
453
  ]) {
454
454
  if (value !== undefined && value !== null && value < 0) {
455
- throw new ValidationError(`[turbine] ${context} on "${this.table}": \`${name}\` must not be negative (got ${value}).`);
455
+ throw new ValidationError(`${context} on "${this.table}": \`${name}\` must not be negative (got ${value}).`);
456
456
  }
457
457
  }
458
458
  }
@@ -502,7 +502,7 @@ export class PowqlInterface {
502
502
  // Relation filters are pre-resolved to scalar in/notIn by
503
503
  // resolveRelationFilters() before buildWhere runs, reaching here means
504
504
  // a caller skipped that step (an internal bug, not user error).
505
- throw new ValidationError(`[turbine] internal: relation filter "${key}" reached buildWhere unresolved (missing resolveRelationFilters()).`);
505
+ throw new ValidationError(`internal: relation filter "${key}" reached buildWhere unresolved (missing resolveRelationFilters()).`);
506
506
  }
507
507
  else {
508
508
  // A JsonFilter (or a bare `{ path }`) can compile to zero clauses; skip
@@ -632,7 +632,7 @@ export class PowqlInterface {
632
632
  conds.push(`${lhs} like ${this.bindLike(`%${escapeLike(String(opVal))}`, params, insensitive)}`);
633
633
  break;
634
634
  default:
635
- throw new ValidationError(`[turbine] Unsupported operator "${opName}" on PowDB.`);
635
+ throw new ValidationError(`Unsupported operator "${opName}" on PowDB.`);
636
636
  }
637
637
  }
638
638
  return conds.length > 1 ? `(${conds.join(' and ')})` : (conds[0] ?? this.alwaysFalse());
@@ -720,14 +720,14 @@ export class PowqlInterface {
720
720
  if (v === undefined)
721
721
  continue;
722
722
  if (filter.path === undefined) {
723
- throw new ValidationError(`[turbine] JSON range operator '${op}' on ${col.name} requires a \`path\` ` +
723
+ throw new ValidationError(`JSON range operator '${op}' on ${col.name} requires a \`path\` ` +
724
724
  `(e.g. { path: ['meta', 'score'], ${op}: ${JSON.stringify(v)} }).`);
725
725
  }
726
726
  if (typeof v !== 'number' && typeof v !== 'string') {
727
- throw new ValidationError(`[turbine] JSON range operator '${op}' on ${col.name} requires a number or string, got ${JSON.stringify(v)}.`);
727
+ throw new ValidationError(`JSON range operator '${op}' on ${col.name} requires a number or string, got ${JSON.stringify(v)}.`);
728
728
  }
729
729
  if (typeof v === 'number' && !Number.isFinite(v)) {
730
- throw new ValidationError(`[turbine] JSON range operator '${op}' on ${col.name} requires a finite number.`);
730
+ throw new ValidationError(`JSON range operator '${op}' on ${col.name} requires a finite number.`);
731
731
  }
732
732
  conds.push(`${pathP()} ${powOp} ${this.param(v, params)}`);
733
733
  }
@@ -743,7 +743,7 @@ export class PowqlInterface {
743
743
  // generator bug rather than a user error, and must not silently widen the
744
744
  // query the way it used to.
745
745
  if (!conds.length) {
746
- throw new ValidationError(`[turbine] internal: JSON filter on "${col.name}" compiled to no condition. This is a bug in turbine-orm.`);
746
+ throw new ValidationError(`internal: JSON filter on "${col.name}" compiled to no condition. This is a bug in turbine-orm.`);
747
747
  }
748
748
  return conds.length > 1 ? `(${conds.join(' and ')})` : conds[0];
749
749
  }
@@ -909,7 +909,7 @@ export class PowqlInterface {
909
909
  }
910
910
  const targetMeta = this.schema.tables[rel.to];
911
911
  if (!targetMeta)
912
- throw new ValidationError(`[turbine] Relation "${rel.name}" targets unknown table "${rel.to}".`);
912
+ throw new ValidationError(`Relation "${rel.name}" targets unknown table "${rel.to}".`);
913
913
  // hasMany/hasOne: localKey = our referenceKey, collect the child's foreignKey.
914
914
  // belongsTo: localKey = our foreignKey, collect the target's referenceKey.
915
915
  const localCol = rel.type === 'belongsTo' ? fk[0] : rk[0];
@@ -938,13 +938,13 @@ export class PowqlInterface {
938
938
  async resolveManyToManyCondition(rel, mode, innerWhere, innerEmpty, timeout) {
939
939
  const through = rel.through;
940
940
  if (!through)
941
- throw new ValidationError(`[turbine] manyToMany relation "${rel.name}" is missing its junction (\`through\`).`);
941
+ throw new ValidationError(`manyToMany relation "${rel.name}" is missing its junction (\`through\`).`);
942
942
  const sourceJ = normalizeKeyColumns(through.sourceKey);
943
943
  const targetJ = normalizeKeyColumns(through.targetKey);
944
944
  const sourceRef = normalizeKeyColumns(rel.referenceKey);
945
945
  const targetMeta = this.schema.tables[rel.to];
946
946
  if (!targetMeta)
947
- throw new ValidationError(`[turbine] Relation "${rel.name}" targets unknown table "${rel.to}".`);
947
+ throw new ValidationError(`Relation "${rel.name}" targets unknown table "${rel.to}".`);
948
948
  if (sourceJ.length > 1 || targetJ.length > 1 || sourceRef.length > 1 || targetMeta.primaryKey.length > 1) {
949
949
  throw new UnsupportedFeatureError('composite-key manyToMany filters', 'PowDB', `relation "${rel.name}", PowQL has no tuple-\`in\` for composite junction/target keys`);
950
950
  }
@@ -1282,9 +1282,9 @@ export class PowqlInterface {
1282
1282
  }
1283
1283
  /** Build the E018 refusal for a write / `begin` on a read-only pool. */
1284
1284
  readOnlyError(operation) {
1285
- // Pass a clean detail: the ReadOnlyError constructor owns both the
1286
- // `[turbine] ` prefix and the "Route writes to a writable primary." hint,
1287
- // so adding either here would double them.
1285
+ // Pass a clean detail: the ReadOnlyError constructor owns the "Route writes
1286
+ // to a writable primary." hint, so adding it here would double it. The
1287
+ // `[TURBINE_E018]` tag is added once, later, by formatErrorMessage.
1288
1288
  return new ReadOnlyError(`${operation} on "${this.table}" refused: this PowDB connection is read-only.`);
1289
1289
  }
1290
1290
  /**
@@ -1651,7 +1651,7 @@ export class PowqlInterface {
1651
1651
  */
1652
1652
  async loadRelations(parents, withClause, timeout, depth = 0, parent, includePii = false) {
1653
1653
  if (depth >= 10) {
1654
- throw new ValidationError(`[turbine] Nested 'with' on PowDB exceeded depth 10 (relation cycle?).`);
1654
+ throw new ValidationError(`Nested 'with' on PowDB exceeded depth 10 (relation cycle?).`);
1655
1655
  }
1656
1656
  if (!parents.length)
1657
1657
  return;
@@ -1666,7 +1666,7 @@ export class PowqlInterface {
1666
1666
  continue;
1667
1667
  const rel = this.meta.relations[relName];
1668
1668
  if (!rel)
1669
- throw new ValidationError(`[turbine] Unknown relation "${relName}" on "${this.table}".`);
1669
+ throw new ValidationError(`Unknown relation "${relName}" on "${this.table}".`);
1670
1670
  if (strategyIsJoin && parent && this.joinEligible(rel, opt, parent.args, parents.length)) {
1671
1671
  if (this.capabilities.serverJoins) {
1672
1672
  await this.loadRelationViaJoin(parents, rel, relName, opt, parent, timeout, includePii);
@@ -1793,13 +1793,13 @@ export class PowqlInterface {
1793
1793
  async loadManyToMany(parents, rel, relName, opt, timeout, includePii = false) {
1794
1794
  const through = rel.through;
1795
1795
  if (!through)
1796
- throw new ValidationError(`[turbine] manyToMany relation "${relName}" is missing its junction (\`through\`).`);
1796
+ throw new ValidationError(`manyToMany relation "${relName}" is missing its junction (\`through\`).`);
1797
1797
  const sourceJ = normalizeKeyColumns(through.sourceKey);
1798
1798
  const targetJ = normalizeKeyColumns(through.targetKey);
1799
1799
  const sourceRef = normalizeKeyColumns(rel.referenceKey);
1800
1800
  const targetMeta = this.schema.tables[rel.to];
1801
1801
  if (!targetMeta)
1802
- throw new ValidationError(`[turbine] Relation "${relName}" targets unknown table "${rel.to}".`);
1802
+ throw new ValidationError(`Relation "${relName}" targets unknown table "${rel.to}".`);
1803
1803
  if (sourceJ.length > 1 || targetJ.length > 1 || sourceRef.length > 1 || targetMeta.primaryKey.length > 1) {
1804
1804
  throw new UnsupportedFeatureError('composite-key manyToMany', 'PowDB', `relation "${relName}", PowQL has no tuple-\`in\`, so composite junction/target keys can't be loaded`);
1805
1805
  }
@@ -2033,7 +2033,7 @@ export class PowqlInterface {
2033
2033
  const options = (opt === true ? {} : opt);
2034
2034
  const targetMeta = this.schema.tables[rel.to];
2035
2035
  if (!targetMeta)
2036
- throw new ValidationError(`[turbine] Relation "${relName}" targets unknown table "${rel.to}".`);
2036
+ throw new ValidationError(`Relation "${relName}" targets unknown table "${rel.to}".`);
2037
2037
  const targetQi = new PowqlInterface(this.pool, rel.to, this.schema, [], this.options);
2038
2038
  const fk = normalizeKeyColumns(rel.foreignKey);
2039
2039
  const rk = normalizeKeyColumns(rel.referenceKey);
@@ -2073,11 +2073,11 @@ export class PowqlInterface {
2073
2073
  async loadManyToManyViaJoin(parents, rel, relName, opt, parent, timeout, includePii = false) {
2074
2074
  const through = rel.through;
2075
2075
  if (!through)
2076
- throw new ValidationError(`[turbine] manyToMany relation "${relName}" is missing its junction (\`through\`).`);
2076
+ throw new ValidationError(`manyToMany relation "${relName}" is missing its junction (\`through\`).`);
2077
2077
  const options = (opt === true ? {} : opt);
2078
2078
  const targetMeta = this.schema.tables[rel.to];
2079
2079
  if (!targetMeta)
2080
- throw new ValidationError(`[turbine] Relation "${relName}" targets unknown table "${rel.to}".`);
2080
+ throw new ValidationError(`Relation "${relName}" targets unknown table "${rel.to}".`);
2081
2081
  const targetQi = new PowqlInterface(this.pool, rel.to, this.schema, [], this.options);
2082
2082
  const sourceJCol = normalizeKeyColumns(through.sourceKey)[0];
2083
2083
  const targetJCol = normalizeKeyColumns(through.targetKey)[0];
@@ -2107,7 +2107,7 @@ export class PowqlInterface {
2107
2107
  joinChildCols(targetQi, options, includePii = false) {
2108
2108
  const plan = targetQi.projectionPlan(options.select, options.omit, includePii);
2109
2109
  if (plan.cols.includes('__tpk')) {
2110
- throw new ValidationError(`[turbine] relation target "${targetQi.table}" has a column named "__tpk", which collides with the reserved ` +
2110
+ throw new ValidationError(`relation target "${targetQi.table}" has a column named "__tpk", which collides with the reserved ` +
2111
2111
  `join correlation alias. Rename the column or load this relation with relationLoadStrategy: 'batched'.`);
2112
2112
  }
2113
2113
  return plan;
@@ -2242,7 +2242,7 @@ export class PowqlInterface {
2242
2242
  const { cols, forcedPk } = targetQi.projectionPlan(options.select, options.omit, includePii);
2243
2243
  const byName = new Map(targetQi.meta.columns.map((c) => [c.name, c]));
2244
2244
  for (const c of cols) {
2245
- const ts = (byName.get(c)?.tsType ?? '').replace(/\s*\|\s*null$/i, '').trim();
2245
+ const ts = baseTsType(byName.get(c)?.tsType ?? '');
2246
2246
  if (ts === 'bigint' || ts === 'Uint8Array')
2247
2247
  return null;
2248
2248
  }
@@ -2449,7 +2449,7 @@ export class PowqlInterface {
2449
2449
  // at least one projected child column is bigint/bytes. Otherwise nested
2450
2450
  // projections already handle it (and cache), so leave it to them.
2451
2451
  const hasCarrierBlockedCol = userCols.some((c) => {
2452
- const ts = (byName.get(c)?.tsType ?? '').replace(/\s*\|\s*null$/i, '').trim();
2452
+ const ts = baseTsType(byName.get(c)?.tsType ?? '');
2453
2453
  return ts === 'bigint' || ts === 'Uint8Array';
2454
2454
  });
2455
2455
  if (!hasCarrierBlockedCol)
@@ -2633,7 +2633,7 @@ export class PowqlInterface {
2633
2633
  parts.push(`does not supply ${quoteList(missing)}`);
2634
2634
  if (unexpected.length > 0)
2635
2635
  parts.push(`supplies ${quoteList(unexpected)}, which the first row does not`);
2636
- throw new ValidationError(`[turbine] createMany on "${this.table}": row ${i} ${parts.join(' and ')}. ` +
2636
+ throw new ValidationError(`createMany on "${this.table}": row ${i} ${parts.join(' and ')}. ` +
2637
2637
  'Every row must supply the same fields (a field set to `undefined` counts as omitted, exactly as it does ' +
2638
2638
  'in `create`). PowQL itself would insert the ragged rows, but the SQL engines build ONE statement whose ' +
2639
2639
  "column list comes from the first row, so there a later row's extra field is dropped and a field it " +
@@ -2745,14 +2745,14 @@ export class PowqlInterface {
2745
2745
  else if ('divide' in opObj)
2746
2746
  parts.push(`${col} := ${ref} / ${this.writeRef(opObj.divide, colMeta, params)}`);
2747
2747
  else
2748
- throw new ValidationError(`[turbine] Unsupported update operator on "${field}".`);
2748
+ throw new ValidationError(`Unsupported update operator on "${field}".`);
2749
2749
  }
2750
2750
  else {
2751
2751
  parts.push(`${col} := ${this.writeRef(value, colMeta, params)}`);
2752
2752
  }
2753
2753
  }
2754
2754
  if (!parts.length)
2755
- throw new ValidationError(`[turbine] update on "${this.table}" has no fields to set.`);
2755
+ throw new ValidationError(`update on "${this.table}" has no fields to set.`);
2756
2756
  return parts.join(', ');
2757
2757
  }
2758
2758
  // -------------------------------------------------------------------------
@@ -2914,7 +2914,7 @@ export class PowqlInterface {
2914
2914
  return { field, value: createData[field] ?? createData[pk] };
2915
2915
  });
2916
2916
  if (pkPairs.some((p) => p.value == null)) {
2917
- throw new ValidationError(`[turbine] upsert on "${this.table}" needs every composite-PK field in \`create\` (${pkPairs
2917
+ throw new ValidationError(`upsert on "${this.table}" needs every composite-PK field in \`create\` (${pkPairs
2918
2918
  .map((p) => p.field)
2919
2919
  .join(', ')}).`);
2920
2920
  }
@@ -3050,7 +3050,7 @@ export class PowqlInterface {
3050
3050
  const usedKeys = new Set();
3051
3051
  const claim = (key, what) => {
3052
3052
  if (key === '_count' || usedKeys.has(key)) {
3053
- throw new ValidationError(`[turbine] groupBy output name "${key}" (${what}) collides with another output column on table ` +
3053
+ throw new ValidationError(`groupBy output name "${key}" (${what}) collides with another output column on table ` +
3054
3054
  `"${this.table}": set an explicit \`alias\` (or rename the aggregate key) to disambiguate.`);
3055
3055
  }
3056
3056
  usedKeys.add(key);
@@ -3081,7 +3081,7 @@ export class PowqlInterface {
3081
3081
  else {
3082
3082
  const col = this.column(entry.field);
3083
3083
  if (!isJsonColumn(col)) {
3084
- throw new ValidationError(`[turbine] groupBy JSON group key on "${entry.field}" (table "${this.table}") requires a json column.`);
3084
+ throw new ValidationError(`groupBy JSON group key on "${entry.field}" (table "${this.table}") requires a json column.`);
3085
3085
  }
3086
3086
  assertAggregatePiiOptIn(this.table, this.meta, entry.field, col.name, 'groupBy JSON `by` key', resolveUnsafeFlag(args.includePii, 'includePii'));
3087
3087
  this.assertJsonPath('group key', entry.field, entry.path);
@@ -3187,7 +3187,7 @@ export class PowqlInterface {
3187
3187
  else {
3188
3188
  const col = this.column(target.field);
3189
3189
  if (!isJsonColumn(col)) {
3190
- throw new ValidationError(`[turbine] groupBy ${fn} target "${key}" on "${target.field}" (table "${this.table}") requires a json column.`);
3190
+ throw new ValidationError(`groupBy ${fn} target "${key}" on "${target.field}" (table "${this.table}") requires a json column.`);
3191
3191
  }
3192
3192
  if (fn === '_min' || fn === '_max') {
3193
3193
  assertAggregatePiiOptIn(this.table, this.meta, target.field, col.name, `groupBy ${fn} JSON target`, resolveUnsafeFlag(args.includePii, 'includePii'));
@@ -3195,7 +3195,7 @@ export class PowqlInterface {
3195
3195
  this.assertJsonPath(`${fn} target "${key}"`, target.field, target.path);
3196
3196
  const alwaysNumeric = fn === '_sum' || fn === '_avg';
3197
3197
  if (alwaysNumeric && target.type === 'text') {
3198
- throw new ValidationError(`[turbine] groupBy ${fn} target "${key}" on table "${this.table}": ` +
3198
+ throw new ValidationError(`groupBy ${fn} target "${key}" on table "${this.table}": ` +
3199
3199
  `${fn} over a JSON path is always numeric: remove \`type: 'text'\`.`);
3200
3200
  }
3201
3201
  const numeric = alwaysNumeric || target.type === 'numeric';
@@ -3263,7 +3263,7 @@ export class PowqlInterface {
3263
3263
  if (!Array.isArray(path) ||
3264
3264
  path.length === 0 ||
3265
3265
  path.some((el) => typeof el !== 'string' && !(typeof el === 'number' && Number.isFinite(el)))) {
3266
- throw new ValidationError(`[turbine] groupBy ${context} on "${field}" (table "${this.table}") requires a non-empty \`path\` ` +
3266
+ throw new ValidationError(`groupBy ${context} on "${field}" (table "${this.table}") requires a non-empty \`path\` ` +
3267
3267
  `array of keys/indexes (e.g. { field: '${field}', path: ['category'] }).`);
3268
3268
  }
3269
3269
  }
@@ -3315,7 +3315,7 @@ export class PowqlInterface {
3315
3315
  // must come from the fixed allowlist, never from the caller's key.
3316
3316
  const fn = POWQL_HAVING_AGG_FNS.get(aggKey);
3317
3317
  if (!fn) {
3318
- throw new ValidationError(`[turbine] Unknown aggregate "${aggKey}" in having for field "${key}" on table "${this.table}". ` +
3318
+ throw new ValidationError(`Unknown aggregate "${aggKey}" in having for field "${key}" on table "${this.table}". ` +
3319
3319
  `Supported: ${[...POWQL_HAVING_AGG_FNS.keys()].join(', ')}.`);
3320
3320
  }
3321
3321
  const inner = this.lookupGroupKey(aggInner, key) ?? this.ref(key);
@@ -3353,14 +3353,14 @@ export class PowqlInterface {
3353
3353
  if (key === '_count') {
3354
3354
  const expr = aggOrderExprs.get('_count');
3355
3355
  if (!expr) {
3356
- throw new ValidationError(`[turbine] Cannot order groupBy by "_count" on table "${this.table}": _count is not selected. ` +
3356
+ throw new ValidationError(`Cannot order groupBy by "_count" on table "${this.table}": _count is not selected. ` +
3357
3357
  `Orderable keys: ${validKeys()}.`);
3358
3358
  }
3359
3359
  parts.push(`${expr} ${this.groupOrderDir(value, '_count')}`);
3360
3360
  continue;
3361
3361
  }
3362
3362
  if (typeof value !== 'object' || value === null || Array.isArray(value)) {
3363
- throw new ValidationError(`[turbine] Invalid groupBy orderBy for "${key}" on table "${this.table}": ` +
3363
+ throw new ValidationError(`Invalid groupBy orderBy for "${key}" on table "${this.table}": ` +
3364
3364
  `expected a field map like { ${key}: { amount: 'desc' } }.`);
3365
3365
  }
3366
3366
  for (const [field, dirSpec] of Object.entries(value)) {
@@ -3370,7 +3370,7 @@ export class PowqlInterface {
3370
3370
  // the registry is keyed by the canonical one.
3371
3371
  const expr = aggOrderExprs.get(`${key}:${field}`) ?? this.aggOrderExpr(aggOrderExprs, key, field);
3372
3372
  if (!expr) {
3373
- throw new ValidationError(`[turbine] Cannot order groupBy by "${key}.${field}" on table "${this.table}": ` +
3373
+ throw new ValidationError(`Cannot order groupBy by "${key}.${field}" on table "${this.table}": ` +
3374
3374
  `that aggregate is not requested in this call. Orderable keys: ${validKeys()}.`);
3375
3375
  }
3376
3376
  parts.push(`${expr} ${this.groupOrderDir(dirSpec, `${key}.${field}`)}`);
@@ -3379,7 +3379,7 @@ export class PowqlInterface {
3379
3379
  }
3380
3380
  const expr = this.lookupGroupKey(byOrderExprs, key);
3381
3381
  if (!expr) {
3382
- throw new ValidationError(`[turbine] Unknown field "${key}" in groupBy orderBy on table "${this.table}". Orderable keys: ${validKeys()}.`);
3382
+ throw new ValidationError(`Unknown field "${key}" in groupBy orderBy on table "${this.table}". Orderable keys: ${validKeys()}.`);
3383
3383
  }
3384
3384
  parts.push(`${expr} ${this.groupOrderDir(value, key)}`);
3385
3385
  }
@@ -3469,14 +3469,14 @@ export class PowqlInterface {
3469
3469
  return;
3470
3470
  if (compiledWhere.length > 0)
3471
3471
  return;
3472
- throw new ValidationError(`[turbine] ${action} on "${this.table}" refused: the \`where\` clause is empty. ` +
3472
+ throw new ValidationError(`${action} on "${this.table}" refused: the \`where\` clause is empty. ` +
3473
3473
  "Pass `allowFullTableScan: UNSAFE` to opt in (import { UNSAFE } from 'turbine-orm'), " +
3474
3474
  'or check that your filter values are defined.');
3475
3475
  }
3476
3476
  }
3477
3477
  /** Coerce a group-key scalar string by the column's TS type (numbers/bools). */
3478
3478
  function coerceScalar(raw, tsType) {
3479
- const ts = tsType.replace(/\s*\|\s*null$/i, '').trim();
3479
+ const ts = baseTsType(tsType);
3480
3480
  if (raw === 'null')
3481
3481
  return null;
3482
3482
  if (ts === 'number' || ts === 'bigint') {
@@ -324,7 +324,7 @@ function assertTranslateDepth(depth, clause) {
324
324
  // The two clauses core also walks raise core's own error, verbatim.
325
325
  if (clause === 'where' || clause === 'having')
326
326
  assertWhereDepth(depth, clause);
327
- throw new ValidationError(`[turbine] \`${clause}\` nests more than ${MAX_WHERE_DEPTH} levels deep. That is far past anything a real ` +
327
+ throw new ValidationError(`\`${clause}\` nests more than ${MAX_WHERE_DEPTH} levels deep. That is far past anything a real ` +
328
328
  `query needs, and an unbounded walk over caller-supplied nesting is a stack-overflow surface, so it is ` +
329
329
  `refused. If this is a generated argument, flatten it: a single array of N entries is one level, not N.`);
330
330
  }
@@ -715,7 +715,7 @@ function translateOmit(ctx, mm, omit) {
715
715
  if (val === false || val == null)
716
716
  continue;
717
717
  if (mm.relations[key]) {
718
- throw new ValidationError(`[turbine] prisma-compat: \`omit\` on model "${modelName(ctx, mm)}" takes scalar fields, but "${key}" ` +
718
+ throw new ValidationError(`prisma-compat: \`omit\` on model "${modelName(ctx, mm)}" takes scalar fields, but "${key}" ` +
719
719
  'is a relation. Leave the relation out of `include` instead.');
720
720
  }
721
721
  out[renameField(mm, key)] = true;
@@ -741,10 +741,10 @@ function translateProjection(ctx, mm, args, depth = 0) {
741
741
  const select = args.select;
742
742
  const omitArg = args.omit;
743
743
  if (include && select) {
744
- throw new ValidationError('[turbine] prisma-compat: `include` and `select` are mutually exclusive.');
744
+ throw new ValidationError('prisma-compat: `include` and `select` are mutually exclusive.');
745
745
  }
746
746
  if (select && omitArg) {
747
- throw new ValidationError('[turbine] prisma-compat: `select` and `omit` are mutually exclusive. ' +
747
+ throw new ValidationError('prisma-compat: `select` and `omit` are mutually exclusive. ' +
748
748
  'A `select` already lists exactly the fields you want.');
749
749
  }
750
750
  const omit = omitArg ? translateOmit(ctx, mm, omitArg) : undefined;
@@ -761,7 +761,7 @@ function translateProjection(ctx, mm, args, depth = 0) {
761
761
  }
762
762
  const rel = mm.relations[key];
763
763
  if (!rel) {
764
- throw new ValidationError(`[turbine] prisma-compat: unknown relation "${key}" in include on model "${modelName(ctx, mm)}".`);
764
+ throw new ValidationError(`prisma-compat: unknown relation "${key}" in include on model "${modelName(ctx, mm)}".`);
765
765
  }
766
766
  withClause[rel.name] = translateWithOption(ctx, mm, rel.name, val, depth + 1);
767
767
  hasWith = true;
@@ -816,7 +816,7 @@ function assertWriteProjectionField(ctx, mm, op, clause, key) {
816
816
  return;
817
817
  const known = Object.keys(mm.fields);
818
818
  const suggestion = suggestKey(key, new Set(known));
819
- throw new ValidationError(`[turbine] prisma-compat: unknown field "${key}" in \`${clause}\` on ${modelName(ctx, mm)}.${op}().` +
819
+ throw new ValidationError(`prisma-compat: unknown field "${key}" in \`${clause}\` on ${modelName(ctx, mm)}.${op}().` +
820
820
  (suggestion ? ` Did you mean "${suggestion}"?` : '') +
821
821
  ` Known fields: ${known.join(', ') || '(none)'}.`);
822
822
  }
@@ -848,10 +848,10 @@ function resolveWriteProjection(ctx, mm, op, args) {
848
848
  const select = args.select;
849
849
  const omitArg = args.omit;
850
850
  if (include && select) {
851
- throw new ValidationError('[turbine] prisma-compat: `include` and `select` are mutually exclusive.');
851
+ throw new ValidationError('prisma-compat: `include` and `select` are mutually exclusive.');
852
852
  }
853
853
  if (select && omitArg) {
854
- throw new ValidationError('[turbine] prisma-compat: `select` and `omit` are mutually exclusive. ' +
854
+ throw new ValidationError('prisma-compat: `select` and `omit` are mutually exclusive. ' +
855
855
  'A `select` already lists exactly the fields you want.');
856
856
  }
857
857
  if (include) {
@@ -885,7 +885,7 @@ function resolveWriteProjection(ctx, mm, op, args) {
885
885
  if (val === false || val == null)
886
886
  continue;
887
887
  if (mm.relations[key]) {
888
- throw new ValidationError(`[turbine] prisma-compat: \`omit\` on model "${modelName(ctx, mm)}" takes scalar fields, but "${key}" ` +
888
+ throw new ValidationError(`prisma-compat: \`omit\` on model "${modelName(ctx, mm)}" takes scalar fields, but "${key}" ` +
889
889
  'is a relation.');
890
890
  }
891
891
  assertWriteProjectionField(ctx, mm, op, 'omit', key);
@@ -1768,7 +1768,7 @@ function makeDelegate(ctx, mm, getQI, runInTx) {
1768
1768
  };
1769
1769
  const requireWhere = (args, op) => {
1770
1770
  if (!args || args.where === undefined) {
1771
- throw new ValidationError(`[turbine] prisma-compat: ${op} on "${modelName(ctx, mm)}" requires a \`where\`.`);
1771
+ throw new ValidationError(`prisma-compat: ${op} on "${modelName(ctx, mm)}" requires a \`where\`.`);
1772
1772
  }
1773
1773
  return args;
1774
1774
  };
@@ -1934,7 +1934,7 @@ function makeDelegate(ctx, mm, getQI, runInTx) {
1934
1934
  function poolOf(db) {
1935
1935
  const pool = db.pool;
1936
1936
  if (!pool)
1937
- throw new ValidationError('[turbine] prisma-compat: raw SQL needs a TurbineClient with an active pool.');
1937
+ throw new ValidationError('prisma-compat: raw SQL needs a TurbineClient with an active pool.');
1938
1938
  return pool;
1939
1939
  }
1940
1940
  function placeholderOf(db) {
@@ -2127,7 +2127,7 @@ const EMPTY_EXTENSIONS = { client: {}, model: new Map(), allModels: {} };
2127
2127
  */
2128
2128
  function applyExtension(prev, ext, modelKeys, clientKeys) {
2129
2129
  if (typeof ext !== 'object' || ext === null) {
2130
- throw new ValidationError('[turbine] prisma-compat: $extends expects an extension object or a function ' +
2130
+ throw new ValidationError('prisma-compat: $extends expects an extension object or a function ' +
2131
2131
  `(Prisma.defineExtension callback form), received ${ext === null ? 'null' : typeof ext}.`);
2132
2132
  }
2133
2133
  for (const [component, value] of Object.entries(ext)) {
@@ -2145,7 +2145,7 @@ function applyExtension(prev, ext, modelKeys, clientKeys) {
2145
2145
  const client = { ...prev.client };
2146
2146
  for (const [name, member] of Object.entries(ext.client ?? {})) {
2147
2147
  if (clientKeys.has(name)) {
2148
- throw new ValidationError(`[turbine] prisma-compat: $extends \`client\` member "${name}" would shadow an existing client ` +
2148
+ throw new ValidationError(`prisma-compat: $extends \`client\` member "${name}" would shadow an existing client ` +
2149
2149
  'member (a model delegate or a client-level method). Rename it.');
2150
2150
  }
2151
2151
  client[name] = member;
@@ -2159,7 +2159,7 @@ function applyExtension(prev, ext, modelKeys, clientKeys) {
2159
2159
  }
2160
2160
  const canonical = modelKeys.get(key);
2161
2161
  if (!canonical) {
2162
- throw new ValidationError(`[turbine] prisma-compat: $extends \`model\` key "${key}" is not a model on this client. ` +
2162
+ throw new ValidationError(`prisma-compat: $extends \`model\` key "${key}" is not a model on this client. ` +
2163
2163
  `Known models: ${[...new Set(modelKeys.values())].sort().join(', ') || '(none)'}.`);
2164
2164
  }
2165
2165
  model.set(canonical, { ...(model.get(canonical) ?? {}), ...members });
@@ -2265,7 +2265,7 @@ export function createPrismaCompatClient(client, map, options = {}) {
2265
2265
  */
2266
2266
  const txRunRaw = (tx) => async (text, params) => {
2267
2267
  if (typeof tx.rawQuery !== 'function') {
2268
- throw decorate(new ValidationError('[turbine] prisma-compat: raw SQL inside $transaction needs a transaction client that can execute it ' +
2268
+ throw decorate(new ValidationError('prisma-compat: raw SQL inside $transaction needs a transaction client that can execute it ' +
2269
2269
  '(core TransactionClient.rawQuery). Refusing to run the statement on a pool connection, which would ' +
2270
2270
  'silently place it outside the transaction.'), ctx.options.prismaErrorCodes);
2271
2271
  }
@@ -2310,7 +2310,7 @@ export function createPrismaCompatClient(client, map, options = {}) {
2310
2310
  const batchables = arg.map((p, i) => {
2311
2311
  const b = batchableOf(p);
2312
2312
  if (!b) {
2313
- throw new ValidationError(`[turbine] prisma-compat: $transaction([...]) item ${i} is not a lazy model call. Pass un-awaited delegate calls (e.g. prisma.User.create(...)).`);
2313
+ throw new ValidationError(`prisma-compat: $transaction([...]) item ${i} is not a lazy model call. Pass un-awaited delegate calls (e.g. prisma.User.create(...)).`);
2314
2314
  }
2315
2315
  return b;
2316
2316
  });