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/client.js CHANGED
@@ -288,7 +288,7 @@ function assertUsableConnectionString(value, source) {
288
288
  // to `%20%20%20`, and resolve it against its placeholder host. Naming it as
289
289
  // empty is more useful than reporting the phantom host.
290
290
  if (value.trim().length === 0) {
291
- throw new ConnectionError(`[turbine] The ${source} is empty. Expected a Postgres connection string such as ` +
291
+ throw new ConnectionError(`The ${source} is empty. Expected a Postgres connection string such as ` +
292
292
  '"postgresql://user:password@host:5432/database".');
293
293
  }
294
294
  const verdict = classifyConnectionString(value);
@@ -299,7 +299,7 @@ function assertUsableConnectionString(value, source) {
299
299
  const tail = '(Check for a missing "//", a stray quote copied out of a .env file, or a shell-truncated value.) ' +
300
300
  'The value is not included here because it may contain a password.';
301
301
  if (verdict.kind === 'unparseable') {
302
- throw new ConnectionError(`[turbine] The ${source} cannot be parsed as a connection string, pg rejects it with "Invalid URL" ` +
302
+ throw new ConnectionError(`The ${source} cannot be parsed as a connection string, pg rejects it with "Invalid URL" ` +
303
303
  '(most often a non-numeric port). Expected something like ' +
304
304
  `"postgresql://user:password@host:5432/database". ${tail}`);
305
305
  }
@@ -310,7 +310,7 @@ function assertUsableConnectionString(value, source) {
310
310
  const keywordForm = /^[A-Za-z_][A-Za-z0-9_]*\s*=/.test(value.trimStart())
311
311
  ? 'It looks like a libpq "host=… dbname=…" keyword/value string, which node-postgres does not support. '
312
312
  : '';
313
- throw new ConnectionError(`[turbine] The ${source} names no host: it has no "postgres://" or "postgresql://" scheme, so pg would ` +
313
+ throw new ConnectionError(`The ${source} names no host: it has no "postgres://" or "postgresql://" scheme, so pg would ` +
314
314
  `resolve it as a relative URL and try to connect to its internal placeholder host. ${keywordForm}` +
315
315
  `Expected something like "postgresql://user:password@host:5432/database". ${tail}`);
316
316
  }
@@ -391,7 +391,7 @@ function resolveIsolationLevel(level) {
391
391
  return undefined;
392
392
  const sql = ownLookup(ISOLATION_LEVELS, level);
393
393
  if (sql === undefined) {
394
- throw new ValidationError(`[turbine] $transaction: unknown isolationLevel ${JSON.stringify(level)}. ` +
394
+ throw new ValidationError(`$transaction: unknown isolationLevel ${JSON.stringify(level)}. ` +
395
395
  `Expected one of: ${Object.keys(ISOLATION_LEVELS).join(', ')} (case-sensitive).`);
396
396
  }
397
397
  return sql;
@@ -740,7 +740,7 @@ export class TurbineClient {
740
740
  // output), not runtime SchemaMetadata, so name the conversion rather than
741
741
  // just the requirement.
742
742
  const looksLikeSchemaDef = schema !== null && typeof schema === 'object' && Object.hasOwn(schema, 'name') === false;
743
- throw new ValidationError('[turbine] TurbineClient requires schema metadata as its second argument. ' +
743
+ throw new ValidationError('TurbineClient requires schema metadata as its second argument. ' +
744
744
  'Run `npx turbine generate` and use the generated client (`turbine()` from your output dir), ' +
745
745
  'or pass the generated `schemaMetadata` object: new TurbineClient(config, schemaMetadata).' +
746
746
  (looksLikeSchemaDef
@@ -753,7 +753,7 @@ export class TurbineClient {
753
753
  // the cause. Validate one table's shape here, where the fix is obvious.
754
754
  for (const [name, meta] of Object.entries(schema.tables)) {
755
755
  if (!meta || typeof meta !== 'object' || !Array.isArray(meta.columns)) {
756
- throw new ValidationError(`[turbine] Table "${name}" in the schema passed to TurbineClient has no \`columns\` array, so this is ` +
756
+ throw new ValidationError(`Table "${name}" in the schema passed to TurbineClient has no \`columns\` array, so this is ` +
757
757
  'not runtime SchemaMetadata. A `defineSchema()` result is a SchemaDef: convert it with ' +
758
758
  '`schemaDefToMetadata(def)`, or use the metadata emitted by `npx turbine generate`.');
759
759
  }
@@ -1075,7 +1075,7 @@ export class TurbineClient {
1075
1075
  if (value === undefined)
1076
1076
  return undefined;
1077
1077
  if (value !== 'null' && value !== 'preserve') {
1078
- throw new ValidationError(`[turbine] Invalid temporalInfinity: ${JSON.stringify(value)}. Expected 'preserve' (default: read a Postgres ` +
1078
+ throw new ValidationError(`Invalid temporalInfinity: ${JSON.stringify(value)}. Expected 'preserve' (default: read a Postgres ` +
1079
1079
  'temporal `infinity` as the JS number `Infinity` / `-Infinity`, which round-trips through a write ' +
1080
1080
  "but breaks the declared `Date` type) or 'null' (read it as null, which serializes cleanly but " +
1081
1081
  'makes it indistinguishable from a stored NULL, so a read-modify-write destroys the value).');
@@ -1087,7 +1087,7 @@ export class TurbineClient {
1087
1087
  return undefined;
1088
1088
  const matched = PLAN_CACHE_MODES.find((m) => m === mode);
1089
1089
  if (matched === undefined) {
1090
- throw new ValidationError(`[turbine] Invalid planCacheMode: ${JSON.stringify(mode)}. Expected one of ${PLAN_CACHE_MODES.map((m) => `'${m}'`).join(', ')}.`);
1090
+ throw new ValidationError(`Invalid planCacheMode: ${JSON.stringify(mode)}. Expected one of ${PLAN_CACHE_MODES.map((m) => `'${m}'`).join(', ')}.`);
1091
1091
  }
1092
1092
  if (dialect.supportsPlanCacheMode !== true) {
1093
1093
  throw new UnsupportedFeatureError(`The planCacheMode option (plan_cache_mode = ${matched})`, dialect.name, '`plan_cache_mode` is a PostgreSQL plan-cache setting with no equivalent on this engine. Remove the option, ' +
@@ -1186,7 +1186,7 @@ export class TurbineClient {
1186
1186
  const settled = TurbineClient.utcTimestampParserMode;
1187
1187
  if (settled === undefined || settled === want)
1188
1188
  return;
1189
- throw new ValidationError(`[turbine] utcTimestamps: ${want} conflicts with utcTimestamps: ${settled}, which an earlier TurbineClient ` +
1189
+ throw new ValidationError(`utcTimestamps: ${want} conflicts with utcTimestamps: ${settled}, which an earlier TurbineClient ` +
1190
1190
  'in this process already applied. The zone-less temporal READ parsers (pg OIDs 1114, 1082, 1115, 1182) are ' +
1191
1191
  'process-global, so they cannot ' +
1192
1192
  'differ per client, while the WRITE side is per client. Serving both values would give this client a ' +
@@ -1709,7 +1709,7 @@ export class TurbineClient {
1709
1709
  }
1710
1710
  for (const [name, value] of Object.entries(options.sessionContext)) {
1711
1711
  if (!GUC_NAME_REGEX.test(name)) {
1712
- throw new ValidationError(`[turbine] Invalid session-context GUC name "${name}", must match ` +
1712
+ throw new ValidationError(`Invalid session-context GUC name "${name}", must match ` +
1713
1713
  '/^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)?$/ (optionally namespaced, e.g. "app.current_tenant")');
1714
1714
  }
1715
1715
  const cfg = this.dialect.buildSetSessionConfig(name, String(value));
package/dist/dialect.js CHANGED
@@ -81,7 +81,7 @@ export const postgresDialect = {
81
81
  },
82
82
  buildBulkInsertStatement(input) {
83
83
  if (!input.columnArrayTypes || input.columnArrayTypes.length !== input.columns.length) {
84
- throw new ValidationError(`[turbine] createMany bulk insert into "${input.table}": columnArrayTypes must supply one UNNEST cast ` +
84
+ throw new ValidationError(`createMany bulk insert into "${input.table}": columnArrayTypes must supply one UNNEST cast ` +
85
85
  `per column, got ${input.columnArrayTypes?.length ?? 0} for ${input.columns.length} columns ` +
86
86
  `(${input.columns.join(', ')}). Schema metadata is missing a pgType for at least one column; ` +
87
87
  'regenerate it with `npx turbine generate`.');
package/dist/errors.d.ts CHANGED
@@ -152,11 +152,11 @@ export declare function describeTargetForMessage(target: unknown): string;
152
152
  * When called with an options object and no explicit `message`, a Prisma-style
153
153
  * message is built automatically. By default, only the where-clause keys are
154
154
  * shown to avoid leaking PII into logs:
155
- * `[turbine] findUniqueOrThrow on "users" found no record matching where: { id }`
155
+ * `[TURBINE_E001] findUniqueOrThrow on "users" found no record matching where: { id }`
156
156
  *
157
157
  * Set `setErrorMessageMode('verbose')` (or pass `errorMessages: 'verbose'` to
158
158
  * the TurbineClient constructor) to include the full where values:
159
- * `[turbine] findUniqueOrThrow on "users" found no record matching where: {"id":1}`
159
+ * `[TURBINE_E001] findUniqueOrThrow on "users" found no record matching where: {"id":1}`
160
160
  *
161
161
  * The full `where` object, `table`, and `operation` are always available as
162
162
  * structured properties on the error instance regardless of mode.
package/dist/errors.js CHANGED
@@ -452,11 +452,11 @@ function renderWhereForMessage(where, mode) {
452
452
  * When called with an options object and no explicit `message`, a Prisma-style
453
453
  * message is built automatically. By default, only the where-clause keys are
454
454
  * shown to avoid leaking PII into logs:
455
- * `[turbine] findUniqueOrThrow on "users" found no record matching where: { id }`
455
+ * `[TURBINE_E001] findUniqueOrThrow on "users" found no record matching where: { id }`
456
456
  *
457
457
  * Set `setErrorMessageMode('verbose')` (or pass `errorMessages: 'verbose'` to
458
458
  * the TurbineClient constructor) to include the full where values:
459
- * `[turbine] findUniqueOrThrow on "users" found no record matching where: {"id":1}`
459
+ * `[TURBINE_E001] findUniqueOrThrow on "users" found no record matching where: {"id":1}`
460
460
  *
461
461
  * The full `where` object, `table`, and `operation` are always available as
462
462
  * structured properties on the error instance regardless of mode.
@@ -477,14 +477,14 @@ export class NotFoundError extends TurbineError {
477
477
  if (!message) {
478
478
  if (operation && table) {
479
479
  const wherePart = where !== undefined ? ` matching where: ${renderWhereForMessage(where, currentErrorMessageMode())}` : '';
480
- message = `[turbine] ${operation} on "${table}" found no record${wherePart}`;
480
+ message = `${operation} on "${table}" found no record${wherePart}`;
481
481
  }
482
482
  else if (table) {
483
483
  const wherePart = where !== undefined ? ` matching where ${renderWhereForMessage(where, currentErrorMessageMode())}` : '';
484
- message = `[turbine] No record found in "${table}"${wherePart}`;
484
+ message = `No record found in "${table}"${wherePart}`;
485
485
  }
486
486
  else {
487
- message = '[turbine] Record not found';
487
+ message = 'Record not found';
488
488
  }
489
489
  }
490
490
  super(TurbineErrorCode.NOT_FOUND, message, { cause });
@@ -506,7 +506,7 @@ export class TimeoutError extends TurbineError {
506
506
  * when wrapping a driver error rather than a client-side timer expiry.
507
507
  */
508
508
  constructor(timeoutMs, context = 'Query', options) {
509
- super(TurbineErrorCode.TIMEOUT, options?.message ?? `[turbine] ${context} timed out after ${timeoutMs}ms`, options);
509
+ super(TurbineErrorCode.TIMEOUT, options?.message ?? `${context} timed out after ${timeoutMs}ms`, options);
510
510
  this.name = 'TimeoutError';
511
511
  this.timeoutMs = timeoutMs;
512
512
  }
@@ -576,7 +576,7 @@ export class ConnectionError extends TurbineError {
576
576
  * placeholder password. Never derived from the caller's value.
577
577
  */
578
578
  export function malformedConnectionStringMessage(engine, example) {
579
- return (`[turbine] The ${engine} connection string could not be parsed as a URL. Expected something like "${example}". ` +
579
+ return (`The ${engine} connection string could not be parsed as a URL. Expected something like "${example}". ` +
580
580
  '(Check for a missing "//", a stray quote copied out of a .env file, or a shell-truncated value.) ' +
581
581
  'The value is not included here because it may contain a password.');
582
582
  }
@@ -598,7 +598,7 @@ export class MigrationError extends TurbineError {
598
598
  export class CircularRelationError extends TurbineError {
599
599
  path;
600
600
  constructor(path) {
601
- super(TurbineErrorCode.CIRCULAR_RELATION, `[turbine] Circular or too-deep relation nesting detected: ${path.join(' → ')}. Maximum nesting depth is 10.`);
601
+ super(TurbineErrorCode.CIRCULAR_RELATION, `Circular or too-deep relation nesting detected: ${path.join(' → ')}. Maximum nesting depth is 10.`);
602
602
  this.name = 'CircularRelationError';
603
603
  this.path = path;
604
604
  }
@@ -627,7 +627,7 @@ export class UniqueConstraintError extends TurbineError {
627
627
  if (!message) {
628
628
  const constraintPart = constraint ? ` on ${constraint}` : '';
629
629
  const columnsPart = columns && columns.length > 0 ? ` (${columns.join(', ')})` : '';
630
- message = `[turbine] Unique constraint violation${constraintPart}${columnsPart}`;
630
+ message = `Unique constraint violation${constraintPart}${columnsPart}`;
631
631
  // PII-safe by default: the raw pg `detail` string contains the
632
632
  // conflicting row VALUES (e.g. `Key (email)=(alice@x.com) already
633
633
  // exists.`). Only append it in 'verbose' mode. In 'safe' mode the
@@ -657,7 +657,7 @@ export class ForeignKeyError extends TurbineError {
657
657
  let message = opts.message;
658
658
  if (!message) {
659
659
  const constraintPart = constraint ? ` on ${constraint}` : '';
660
- message = `[turbine] Foreign key constraint violation${constraintPart}`;
660
+ message = `Foreign key constraint violation${constraintPart}`;
661
661
  // PII-safe by default: the raw pg `detail` string contains the
662
662
  // conflicting row VALUES (e.g. `Key (email)=(alice@x.com) already
663
663
  // exists.`). Only append it in 'verbose' mode. In 'safe' mode the
@@ -686,7 +686,7 @@ export class NotNullViolationError extends TurbineError {
686
686
  let message = opts.message;
687
687
  if (!message) {
688
688
  const columnPart = column ? ` on column "${column}"` : '';
689
- message = `[turbine] NOT NULL constraint violation${columnPart}`;
689
+ message = `NOT NULL constraint violation${columnPart}`;
690
690
  // PII-safe by default: the raw pg `detail` string contains the
691
691
  // conflicting row VALUES (e.g. `Key (email)=(alice@x.com) already
692
692
  // exists.`). Only append it in 'verbose' mode. In 'safe' mode the
@@ -731,7 +731,7 @@ export class DeadlockError extends TurbineError {
731
731
  let message = opts.message;
732
732
  if (!message) {
733
733
  const pgMessage = cause?.message;
734
- message = pgMessage ? `[turbine] Deadlock detected: ${pgMessage}` : '[turbine] Deadlock detected';
734
+ message = pgMessage ? `Deadlock detected: ${pgMessage}` : 'Deadlock detected';
735
735
  }
736
736
  super(TurbineErrorCode.DEADLOCK_DETECTED, message, { cause });
737
737
  this.name = 'DeadlockError';
@@ -763,9 +763,7 @@ export class SerializationFailureError extends TurbineError {
763
763
  let message = opts.message;
764
764
  if (!message) {
765
765
  const pgMessage = cause?.message;
766
- message = pgMessage
767
- ? `[turbine] Serializable transaction conflict: ${pgMessage}`
768
- : '[turbine] Serializable transaction conflict';
766
+ message = pgMessage ? `Serializable transaction conflict: ${pgMessage}` : 'Serializable transaction conflict';
769
767
  }
770
768
  super(TurbineErrorCode.SERIALIZATION_FAILURE, message, { cause });
771
769
  this.name = 'SerializationFailureError';
@@ -780,7 +778,7 @@ export class CheckConstraintError extends TurbineError {
780
778
  let message = opts.message;
781
779
  if (!message) {
782
780
  const constraintPart = constraint ? ` on ${constraint}` : '';
783
- message = `[turbine] Check constraint violation${constraintPart}`;
781
+ message = `Check constraint violation${constraintPart}`;
784
782
  // PII-safe by default: the raw pg `detail` string contains the
785
783
  // conflicting row VALUES (e.g. `Key (email)=(alice@x.com) already
786
784
  // exists.`). Only append it in 'verbose' mode. In 'safe' mode the
@@ -808,7 +806,7 @@ export class ExclusionConstraintError extends TurbineError {
808
806
  let message = opts.message;
809
807
  if (!message) {
810
808
  const constraintPart = constraint ? ` on ${constraint}` : '';
811
- message = `[turbine] Exclusion constraint violation${constraintPart}`;
809
+ message = `Exclusion constraint violation${constraintPart}`;
812
810
  // PII-safe by default: the raw pg `detail` string contains the
813
811
  // conflicting row VALUES (e.g. `Key (email)=(alice@x.com) already
814
812
  // exists.`). Only append it in 'verbose' mode. In 'safe' mode the
@@ -859,7 +857,7 @@ export class PipelineError extends TurbineError {
859
857
  const { results, failedIndex, failedTag, cause } = opts;
860
858
  const failedCount = results.filter((r) => r.status === 'error').length;
861
859
  const message = opts.message ??
862
- `[turbine] Pipeline completed with ${failedCount} error(s) out of ${results.length} queries` +
860
+ `Pipeline completed with ${failedCount} error(s) out of ${results.length} queries` +
863
861
  (failedTag ? ` (first failure: ${failedTag} at index ${failedIndex})` : '');
864
862
  super(TurbineErrorCode.PIPELINE, message, { cause });
865
863
  this.name = 'PipelineError';
@@ -873,7 +871,7 @@ export class OptimisticLockError extends TurbineError {
873
871
  versionField;
874
872
  expectedVersion;
875
873
  constructor(opts) {
876
- super(TurbineErrorCode.OPTIMISTIC_LOCK, `[turbine] Optimistic lock failed on "${opts.table}", ` +
874
+ super(TurbineErrorCode.OPTIMISTIC_LOCK, `Optimistic lock failed on "${opts.table}", ` +
877
875
  `expected ${opts.versionField} = ${opts.expectedVersion} but row was modified by another transaction`);
878
876
  this.name = 'OptimisticLockError';
879
877
  this.table = opts.table;
@@ -891,7 +889,7 @@ export class UnsupportedFeatureError extends TurbineError {
891
889
  feature;
892
890
  dialect;
893
891
  constructor(feature, dialect, hint) {
894
- super(TurbineErrorCode.UNSUPPORTED_FEATURE, `[turbine] ${feature} is unsupported on "${dialect}".${hint ? ` ${hint}` : ''}`);
892
+ super(TurbineErrorCode.UNSUPPORTED_FEATURE, `${feature} is unsupported on "${dialect}".${hint ? ` ${hint}` : ''}`);
895
893
  this.name = 'UnsupportedFeatureError';
896
894
  this.feature = feature;
897
895
  this.dialect = dialect;
@@ -928,7 +926,7 @@ export class ReadOnlyError extends TurbineError {
928
926
  * and the refusal `reason` (default `'snapshot'`).
929
927
  */
930
928
  constructor(detail, options) {
931
- super(TurbineErrorCode.READ_ONLY, `[turbine] ${detail} Route writes to a writable primary.`, {
929
+ super(TurbineErrorCode.READ_ONLY, `${detail} Route writes to a writable primary.`, {
932
930
  cause: options?.cause,
933
931
  });
934
932
  this.name = 'ReadOnlyError';
@@ -1101,7 +1099,7 @@ export function wrapPgError(err) {
1101
1099
  // Turbine did not set the deadline (that lives in Postgres config), so
1102
1100
  // there is no client-side budget to report → timeoutMs = 0.
1103
1101
  return new TimeoutError(0, 'Query', {
1104
- message: '[turbine] Query canceled by server-side statement_timeout',
1102
+ message: 'Query canceled by server-side statement_timeout',
1105
1103
  cause: err,
1106
1104
  });
1107
1105
  default:
@@ -1111,9 +1109,7 @@ export function wrapPgError(err) {
1111
1109
  // plain-object map would happily resolve `constructor` or `toString`
1112
1110
  // to a function and interpolate it into the message.
1113
1111
  const hint = Object.hasOwn(CONNECTION_ERROR_HINTS, e.code) ? CONNECTION_ERROR_HINTS[e.code] : undefined;
1114
- const head = pgMessage
1115
- ? `[turbine] Database connection error: ${pgMessage}`
1116
- : `[turbine] Database connection error (${e.code})`;
1112
+ const head = pgMessage ? `Database connection error: ${pgMessage}` : `Database connection error (${e.code})`;
1117
1113
  return new ConnectionError(hint ? `${head} (${e.code}) ${hint}` : head, { cause: err, sqlstate: e.code });
1118
1114
  }
1119
1115
  return err;
package/dist/generate.js CHANGED
@@ -363,7 +363,7 @@ export function isEmittableIdentifier(name) {
363
363
  function requireEmittable(derived, subject, role) {
364
364
  if (isEmittableIdentifier(derived))
365
365
  return;
366
- throw new ValidationError(`[turbine] Cannot generate code for ${subject}: it produces ${JSON.stringify(derived)} as ${role}, ` +
366
+ throw new ValidationError(`Cannot generate code for ${subject}: it produces ${JSON.stringify(derived)} as ${role}, ` +
367
367
  `which is not a valid TypeScript identifier. Rename the database object, or exclude it from generation ` +
368
368
  `(introspect \`exclude\`).`);
369
369
  }
@@ -337,7 +337,7 @@ export function assertSafeCatalogIdentifier(name, subject) {
337
337
  if (match === null)
338
338
  return;
339
339
  const code = match[0].charCodeAt(0).toString(16).padStart(4, '0');
340
- throw new ValidationError(`[turbine] Refusing to introspect ${subject}: its name contains the control character U+${code.toUpperCase()} ` +
340
+ throw new ValidationError(`Refusing to introspect ${subject}: its name contains the control character U+${code.toUpperCase()} ` +
341
341
  `at position ${match.index}. Such a name cannot be safely emitted into generated code, SQL comments, or ` +
342
342
  `tooling output. Rename the database object, or exclude it from introspection.`);
343
343
  }
@@ -434,22 +434,22 @@ export function applyRelationRenames(schema, renames) {
434
434
  for (const [table, mapping] of Object.entries(renames)) {
435
435
  const meta = tables[table];
436
436
  if (!meta) {
437
- throw new ValidationError(`[turbine] relationNames: unknown table "${table}". Known tables: ${Object.keys(tables).join(', ')}.`);
437
+ throw new ValidationError(`relationNames: unknown table "${table}". Known tables: ${Object.keys(tables).join(', ')}.`);
438
438
  }
439
439
  const relations = { ...meta.relations };
440
440
  const columnFields = new Set(Object.values(meta.columnMap));
441
441
  for (const [from, to] of Object.entries(mapping)) {
442
442
  if (!Object.hasOwn(relations, from)) {
443
- throw new ValidationError(`[turbine] relationNames: table "${table}" has no relation "${from}". ` +
443
+ throw new ValidationError(`relationNames: table "${table}" has no relation "${from}". ` +
444
444
  `Derived relations: ${Object.keys(relations).join(', ') || '(none)'}.`);
445
445
  }
446
446
  if (from === to)
447
447
  continue;
448
448
  if (Object.hasOwn(relations, to)) {
449
- throw new ValidationError(`[turbine] relationNames: cannot rename "${table}.${from}" to "${to}", that relation already exists.`);
449
+ throw new ValidationError(`relationNames: cannot rename "${table}.${from}" to "${to}", that relation already exists.`);
450
450
  }
451
451
  if (columnFields.has(to)) {
452
- throw new ValidationError(`[turbine] relationNames: cannot rename "${table}.${from}" to "${to}", a column on "${table}" ` +
452
+ throw new ValidationError(`relationNames: cannot rename "${table}.${from}" to "${to}", a column on "${table}" ` +
453
453
  `already uses that field name, and a relation must never shadow a column.`);
454
454
  }
455
455
  const def = relations[from];
package/dist/mssql.js CHANGED
@@ -652,11 +652,11 @@ export const mssqlDialect = {
652
652
  const rowCount = input.rowValues.length;
653
653
  const paramCount = input.rowValues.reduce((n, row) => n + row.length, 0);
654
654
  if (rowCount > MSSQL_MAX_INSERT_ROWS) {
655
- throw new ValidationError(`[turbine] SQL Server INSERT … VALUES is limited to ${MSSQL_MAX_INSERT_ROWS} rows per statement (got ${rowCount}). ` +
655
+ throw new ValidationError(`SQL Server INSERT … VALUES is limited to ${MSSQL_MAX_INSERT_ROWS} rows per statement (got ${rowCount}). ` +
656
656
  'Chunk the data or use individual create() calls.');
657
657
  }
658
658
  if (paramCount > MSSQL_MAX_PARAMS) {
659
- throw new ValidationError(`[turbine] SQL Server is limited to ${MSSQL_MAX_PARAMS} bound parameters per statement (got ${paramCount}). ` +
659
+ throw new ValidationError(`SQL Server is limited to ${MSSQL_MAX_PARAMS} bound parameters per statement (got ${paramCount}). ` +
660
660
  'Reduce the batch size.');
661
661
  }
662
662
  let n = 0;
@@ -904,7 +904,7 @@ function buildForJsonSubquery(dialect, ctx) {
904
904
  for (const [nestedRelName, nestedSpec] of sortedRelEntries(spec.with)) {
905
905
  const nestedRelDef = targetMeta.relations[nestedRelName];
906
906
  if (!nestedRelDef) {
907
- throw new RelationError(`[turbine] Unknown relation "${nestedRelName}" on table "${targetTable}". ` +
907
+ throw new RelationError(`Unknown relation "${nestedRelName}" on table "${targetTable}". ` +
908
908
  availableClause(Object.keys(targetMeta.relations), 'It has no relations.'));
909
909
  }
910
910
  const sub = ctx.recurse(nestedRelDef, nestedSpec, parentAlias, depth + 1, [...path, relDef.name]);
@@ -926,7 +926,7 @@ function buildForJsonSubquery(dialect, ctx) {
926
926
  if (typeof dir === 'object' && dir !== null) {
927
927
  const sortValue = dir.sort;
928
928
  if (typeof sortValue !== 'string') {
929
- throw new ValidationError(`[turbine] Nested orderBy on "${k}" (table "${targetTable}"): only plain directions and ` +
929
+ throw new ValidationError(`Nested orderBy on "${k}" (table "${targetTable}"): only plain directions and ` +
930
930
  `{ sort } specs are supported inside a relation orderBy on SQL Server.`);
931
931
  }
932
932
  if (dir.nulls !== undefined) {
@@ -939,7 +939,7 @@ function buildForJsonSubquery(dialect, ctx) {
939
939
  // resolve on SQL Server too.
940
940
  const col = targetMeta.columnMap[k] ?? camelToSnake(k);
941
941
  if (!targetMeta.allColumns.includes(col)) {
942
- throw new ValidationError(`[turbine] Unknown field "${k}" in orderBy on table "${targetTable}". ` +
942
+ throw new ValidationError(`Unknown field "${k}" in orderBy on table "${targetTable}". ` +
943
943
  `Known fields: ${Object.keys(targetMeta.columnMap).join(', ') || '(none)'}.`);
944
944
  }
945
945
  const safeDir = String(rawDir).toLowerCase() === 'desc' ? 'DESC' : 'ASC';
@@ -1005,7 +1005,7 @@ function buildForJsonManyToMany(dialect, ctx, h) {
1005
1005
  const { relDef, spec, params, parentRef, alias, targetTable, targetMeta } = ctx;
1006
1006
  const q = (name) => dialect.quoteIdentifier(name);
1007
1007
  if (!relDef.through) {
1008
- throw new ValidationError(`[turbine] manyToMany relation "${relDef.name}" is missing a \`through\` junction descriptor.`);
1008
+ throw new ValidationError(`manyToMany relation "${relDef.name}" is missing a \`through\` junction descriptor.`);
1009
1009
  }
1010
1010
  const qTarget = q(targetTable);
1011
1011
  const qJunction = q(relDef.through.table);
@@ -1014,12 +1014,12 @@ function buildForJsonManyToMany(dialect, ctx, h) {
1014
1014
  // JOIN: junction.targetKey = target.<PK>.
1015
1015
  const targetKeys = normalizeKeyColumns(relDef.through.targetKey);
1016
1016
  if (targetMeta.primaryKey.length === 0) {
1017
- throw new ValidationError(`[turbine] manyToMany relation "${relDef.name}" targets table "${targetTable}" which has no primary key; ` +
1017
+ throw new ValidationError(`manyToMany relation "${relDef.name}" targets table "${targetTable}" which has no primary key; ` +
1018
1018
  'cannot determine the join column.');
1019
1019
  }
1020
1020
  const targetPk = targetMeta.primaryKey;
1021
1021
  if (targetKeys.length !== targetPk.length) {
1022
- throw new ValidationError(`[turbine] manyToMany relation "${relDef.name}": through.targetKey has ${targetKeys.length} column(s) ` +
1022
+ throw new ValidationError(`manyToMany relation "${relDef.name}": through.targetKey has ${targetKeys.length} column(s) ` +
1023
1023
  `but target "${targetTable}" primary key has ${targetPk.length}.`);
1024
1024
  }
1025
1025
  const joinOn = targetKeys.map((jcol, i) => `${jalias}.${q(jcol)} = ${alias}.${q(targetPk[i])}`).join(' AND ');
@@ -1027,7 +1027,7 @@ function buildForJsonManyToMany(dialect, ctx, h) {
1027
1027
  const sourceKeys = normalizeKeyColumns(relDef.through.sourceKey);
1028
1028
  const refKeys = normalizeKeyColumns(relDef.referenceKey);
1029
1029
  if (sourceKeys.length !== refKeys.length) {
1030
- throw new ValidationError(`[turbine] manyToMany relation "${relDef.name}": through.sourceKey has ${sourceKeys.length} column(s) ` +
1030
+ throw new ValidationError(`manyToMany relation "${relDef.name}": through.sourceKey has ${sourceKeys.length} column(s) ` +
1031
1031
  `but referenceKey has ${refKeys.length}.`);
1032
1032
  }
1033
1033
  const correlation = sourceKeys.map((jcol, i) => `${jalias}.${q(jcol)} = ${qParent}.${q(refKeys[i])}`).join(' AND ');
@@ -1309,13 +1309,13 @@ async function loadMssql() {
1309
1309
  mod = (await importOptionalPeer('mssql'));
1310
1310
  }
1311
1311
  catch (err) {
1312
- throw new ConnectionError("[turbine] turbine-orm/mssql requires the optional peer dependency 'mssql'. Install it: npm i mssql. " +
1312
+ throw new ConnectionError("turbine-orm/mssql requires the optional peer dependency 'mssql'. Install it: npm i mssql. " +
1313
1313
  `(${err.message})`);
1314
1314
  }
1315
1315
  // `mssql` is a CommonJS module; the namespace may be on `default` under ESM interop.
1316
1316
  const ns = (mod.default ?? mod);
1317
1317
  if (typeof ns.ConnectionPool !== 'function' || typeof ns.Request !== 'function') {
1318
- throw new ConnectionError("[turbine] Loaded 'mssql' but it is missing ConnectionPool/Request exports.");
1318
+ throw new ConnectionError("Loaded 'mssql' but it is missing ConnectionPool/Request exports.");
1319
1319
  }
1320
1320
  return ns;
1321
1321
  }
@@ -1325,7 +1325,7 @@ async function loadMssql() {
1325
1325
  */
1326
1326
  function assertSupportedVersion(majorVersion) {
1327
1327
  if (majorVersion > 0 && majorVersion < 13) {
1328
- throw new ConnectionError(`[turbine] turbine-orm/mssql requires SQL Server 2016+ (FOR JSON / OPENJSON); got major version ${majorVersion}.`);
1328
+ throw new ConnectionError(`turbine-orm/mssql requires SQL Server 2016+ (FOR JSON / OPENJSON); got major version ${majorVersion}.`);
1329
1329
  }
1330
1330
  }
1331
1331
  function isMssqlPool(x) {
package/dist/mysql.js CHANGED
@@ -1015,7 +1015,7 @@ export async function introspectMysql(options) {
1015
1015
  schemaName = rows[0]?.db ?? '';
1016
1016
  }
1017
1017
  if (!schemaName) {
1018
- throw new ConnectionError('[turbine] Could not determine the MySQL database to introspect, pass a database in the connection string or a `schema` option.');
1018
+ throw new ConnectionError('Could not determine the MySQL database to introspect, pass a database in the connection string or a `schema` option.');
1019
1019
  }
1020
1020
  // `await` is LOAD-BEARING, not stylistic: `return somePromise` inside a
1021
1021
  // try/finally runs the finally BEFORE the promise settles, so `pool.end()`
@@ -1090,12 +1090,12 @@ async function loadCreatePool() {
1090
1090
  mod = (await importOptionalPeer('mysql2/promise'));
1091
1091
  }
1092
1092
  catch (err) {
1093
- throw new ConnectionError("[turbine] turbine-orm/mysql requires the optional peer dependency 'mysql2'. Install it: npm i mysql2. " +
1093
+ throw new ConnectionError("turbine-orm/mysql requires the optional peer dependency 'mysql2'. Install it: npm i mysql2. " +
1094
1094
  `(${err.message})`);
1095
1095
  }
1096
1096
  const createPool = mod.createPool ?? mod.default?.createPool;
1097
1097
  if (typeof createPool !== 'function') {
1098
- throw new ConnectionError("[turbine] Loaded 'mysql2/promise' but it has no createPool export.");
1098
+ throw new ConnectionError("Loaded 'mysql2/promise' but it has no createPool export.");
1099
1099
  }
1100
1100
  return createPool;
1101
1101
  }
@@ -1105,12 +1105,12 @@ async function loadCreatePool() {
1105
1105
  */
1106
1106
  function assertSupportedVersion(version) {
1107
1107
  if (/mariadb/i.test(version)) {
1108
- throw new ConnectionError(`[turbine] MariaDB is not supported by turbine-orm/mysql (got "${version}"). Use MySQL 8.0+.`);
1108
+ throw new ConnectionError(`MariaDB is not supported by turbine-orm/mysql (got "${version}"). Use MySQL 8.0+.`);
1109
1109
  }
1110
1110
  const m = /^(\d+)\.(\d+)/.exec(version);
1111
1111
  const major = m ? Number(m[1]) : 0;
1112
1112
  if (major < 8) {
1113
- throw new ConnectionError(`[turbine] turbine-orm/mysql requires MySQL 8.0+ (5.7 lacks JSON_ARRAYAGG); got "${version}".`);
1113
+ throw new ConnectionError(`turbine-orm/mysql requires MySQL 8.0+ (5.7 lacks JSON_ARRAYAGG); got "${version}".`);
1114
1114
  }
1115
1115
  }
1116
1116
  function isMysql2Pool(x) {