turbine-orm 0.50.0 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +66 -66
  2. package/dist/adapters/cockroachdb.d.ts +5 -5
  3. package/dist/adapters/cockroachdb.js +10 -10
  4. package/dist/adapters/index.d.ts +5 -5
  5. package/dist/adapters/index.js +7 -7
  6. package/dist/adapters/yugabytedb.d.ts +7 -7
  7. package/dist/adapters/yugabytedb.js +10 -10
  8. package/dist/cjs/adapters/cockroachdb.d.ts +5 -5
  9. package/dist/cjs/adapters/cockroachdb.js +10 -10
  10. package/dist/cjs/adapters/index.d.ts +5 -5
  11. package/dist/cjs/adapters/index.js +7 -7
  12. package/dist/cjs/adapters/yugabytedb.d.ts +7 -7
  13. package/dist/cjs/adapters/yugabytedb.js +10 -10
  14. package/dist/cjs/cli/config.d.ts +13 -2
  15. package/dist/cjs/cli/config.js +3 -2
  16. package/dist/cjs/cli/destructive.d.ts +1 -1
  17. package/dist/cjs/cli/destructive.js +1 -1
  18. package/dist/cjs/cli/index.d.ts +10 -10
  19. package/dist/cjs/cli/index.js +49 -45
  20. package/dist/cjs/cli/loader.d.ts +7 -7
  21. package/dist/cjs/cli/loader.js +9 -9
  22. package/dist/cjs/cli/mcp.js +4 -4
  23. package/dist/cjs/cli/migrate.d.ts +5 -5
  24. package/dist/cjs/cli/migrate.js +11 -11
  25. package/dist/cjs/cli/studio-ui.generated.js +1 -1
  26. package/dist/cjs/cli/ui.d.ts +2 -2
  27. package/dist/cjs/cli/ui.js +2 -2
  28. package/dist/cjs/client.d.ts +49 -38
  29. package/dist/cjs/client.js +57 -56
  30. package/dist/cjs/dialect.d.ts +62 -18
  31. package/dist/cjs/dialect.js +40 -2
  32. package/dist/cjs/errors.d.ts +5 -5
  33. package/dist/cjs/errors.js +11 -11
  34. package/dist/cjs/generate.d.ts +6 -6
  35. package/dist/cjs/generate.js +31 -29
  36. package/dist/cjs/index-advisor.d.ts +5 -5
  37. package/dist/cjs/index-advisor.js +0 -0
  38. package/dist/cjs/index.d.ts +1 -1
  39. package/dist/cjs/index.js +7 -7
  40. package/dist/cjs/introspect.d.ts +35 -9
  41. package/dist/cjs/introspect.js +83 -32
  42. package/dist/cjs/mssql.d.ts +11 -11
  43. package/dist/cjs/mssql.js +64 -29
  44. package/dist/cjs/mysql.d.ts +8 -8
  45. package/dist/cjs/mysql.js +61 -23
  46. package/dist/cjs/nested-write.d.ts +21 -2
  47. package/dist/cjs/nested-write.js +51 -14
  48. package/dist/cjs/optional-peer-import.cjs +7 -7
  49. package/dist/cjs/optional-peer-import.d.cts +7 -7
  50. package/dist/cjs/pipeline-submittable.d.ts +2 -2
  51. package/dist/cjs/pipeline-submittable.js +6 -6
  52. package/dist/cjs/pipeline.d.ts +1 -1
  53. package/dist/cjs/pipeline.js +4 -4
  54. package/dist/cjs/powdb-introspect.d.ts +1 -1
  55. package/dist/cjs/powdb-introspect.js +1 -1
  56. package/dist/cjs/powdb.d.ts +28 -28
  57. package/dist/cjs/powdb.js +66 -66
  58. package/dist/cjs/powql.d.ts +27 -27
  59. package/dist/cjs/powql.js +73 -52
  60. package/dist/cjs/query/aggregates.d.ts +1 -1
  61. package/dist/cjs/query/aggregates.js +5 -5
  62. package/dist/cjs/query/batched-loader.d.ts +11 -11
  63. package/dist/cjs/query/batched-loader.js +24 -24
  64. package/dist/cjs/query/builder.d.ts +39 -21
  65. package/dist/cjs/query/builder.js +99 -57
  66. package/dist/cjs/query/compound-unique.d.ts +1 -1
  67. package/dist/cjs/query/compound-unique.js +0 -0
  68. package/dist/cjs/query/deferred.d.ts +12 -6
  69. package/dist/cjs/query/deferred.js +1 -1
  70. package/dist/cjs/query/filters.d.ts +31 -11
  71. package/dist/cjs/query/filters.js +67 -14
  72. package/dist/cjs/query/index.d.ts +1 -1
  73. package/dist/cjs/query/index.js +1 -1
  74. package/dist/cjs/query/relations.d.ts +9 -9
  75. package/dist/cjs/query/relations.js +164 -57
  76. package/dist/cjs/query/types.d.ts +86 -35
  77. package/dist/cjs/query/types.js +1 -1
  78. package/dist/cjs/query/utils.d.ts +27 -10
  79. package/dist/cjs/query/utils.js +86 -14
  80. package/dist/cjs/query/where.d.ts +47 -28
  81. package/dist/cjs/query/where.js +130 -31
  82. package/dist/cjs/query/writes.d.ts +24 -5
  83. package/dist/cjs/query/writes.js +102 -13
  84. package/dist/cjs/realtime.d.ts +7 -7
  85. package/dist/cjs/realtime.js +9 -9
  86. package/dist/cjs/schema-builder.d.ts +18 -7
  87. package/dist/cjs/schema-builder.js +17 -10
  88. package/dist/cjs/schema-metadata.d.ts +3 -3
  89. package/dist/cjs/schema-metadata.js +9 -9
  90. package/dist/cjs/schema-sql.d.ts +9 -9
  91. package/dist/cjs/schema-sql.js +20 -20
  92. package/dist/cjs/schema.d.ts +19 -9
  93. package/dist/cjs/schema.js +6 -6
  94. package/dist/cjs/serverless.d.ts +15 -15
  95. package/dist/cjs/serverless.js +16 -16
  96. package/dist/cjs/sqlite.d.ts +8 -8
  97. package/dist/cjs/sqlite.js +53 -22
  98. package/dist/cjs/typed-sql.d.ts +4 -4
  99. package/dist/cjs/typed-sql.js +5 -5
  100. package/dist/cli/config.d.ts +13 -2
  101. package/dist/cli/config.js +3 -2
  102. package/dist/cli/destructive.d.ts +1 -1
  103. package/dist/cli/destructive.js +1 -1
  104. package/dist/cli/index.d.ts +10 -10
  105. package/dist/cli/index.js +49 -45
  106. package/dist/cli/loader.d.ts +7 -7
  107. package/dist/cli/loader.js +9 -9
  108. package/dist/cli/mcp.js +4 -4
  109. package/dist/cli/migrate.d.ts +5 -5
  110. package/dist/cli/migrate.js +11 -11
  111. package/dist/cli/studio-ui.generated.js +1 -1
  112. package/dist/cli/ui.d.ts +2 -2
  113. package/dist/cli/ui.js +2 -2
  114. package/dist/client.d.ts +49 -38
  115. package/dist/client.js +57 -56
  116. package/dist/dialect.d.ts +62 -18
  117. package/dist/dialect.js +40 -2
  118. package/dist/errors.d.ts +5 -5
  119. package/dist/errors.js +11 -11
  120. package/dist/generate.d.ts +6 -6
  121. package/dist/generate.js +31 -29
  122. package/dist/index-advisor.d.ts +5 -5
  123. package/dist/index-advisor.js +0 -0
  124. package/dist/index.d.ts +1 -1
  125. package/dist/index.js +7 -7
  126. package/dist/introspect.d.ts +35 -9
  127. package/dist/introspect.js +82 -32
  128. package/dist/mssql.d.ts +11 -11
  129. package/dist/mssql.js +64 -29
  130. package/dist/mysql.d.ts +8 -8
  131. package/dist/mysql.js +61 -23
  132. package/dist/nested-write.d.ts +21 -2
  133. package/dist/nested-write.js +51 -14
  134. package/dist/optional-peer-import.cjs +7 -7
  135. package/dist/optional-peer-import.d.cts +7 -7
  136. package/dist/pipeline-submittable.d.ts +2 -2
  137. package/dist/pipeline-submittable.js +6 -6
  138. package/dist/pipeline.d.ts +1 -1
  139. package/dist/pipeline.js +4 -4
  140. package/dist/powdb-introspect.d.ts +1 -1
  141. package/dist/powdb-introspect.js +1 -1
  142. package/dist/powdb.d.ts +28 -28
  143. package/dist/powdb.js +66 -66
  144. package/dist/powql.d.ts +27 -27
  145. package/dist/powql.js +73 -52
  146. package/dist/query/aggregates.d.ts +1 -1
  147. package/dist/query/aggregates.js +5 -5
  148. package/dist/query/batched-loader.d.ts +11 -11
  149. package/dist/query/batched-loader.js +24 -24
  150. package/dist/query/builder.d.ts +39 -21
  151. package/dist/query/builder.js +100 -58
  152. package/dist/query/compound-unique.d.ts +1 -1
  153. package/dist/query/compound-unique.js +0 -0
  154. package/dist/query/deferred.d.ts +12 -6
  155. package/dist/query/deferred.js +1 -1
  156. package/dist/query/filters.d.ts +31 -11
  157. package/dist/query/filters.js +66 -13
  158. package/dist/query/index.d.ts +1 -1
  159. package/dist/query/index.js +1 -1
  160. package/dist/query/relations.d.ts +9 -9
  161. package/dist/query/relations.js +165 -58
  162. package/dist/query/types.d.ts +86 -35
  163. package/dist/query/types.js +1 -1
  164. package/dist/query/utils.d.ts +27 -10
  165. package/dist/query/utils.js +84 -14
  166. package/dist/query/where.d.ts +47 -28
  167. package/dist/query/where.js +129 -32
  168. package/dist/query/writes.d.ts +24 -5
  169. package/dist/query/writes.js +101 -13
  170. package/dist/realtime.d.ts +7 -7
  171. package/dist/realtime.js +9 -9
  172. package/dist/schema-builder.d.ts +18 -7
  173. package/dist/schema-builder.js +17 -10
  174. package/dist/schema-metadata.d.ts +3 -3
  175. package/dist/schema-metadata.js +9 -9
  176. package/dist/schema-sql.d.ts +9 -9
  177. package/dist/schema-sql.js +20 -20
  178. package/dist/schema.d.ts +19 -9
  179. package/dist/schema.js +6 -6
  180. package/dist/serverless.d.ts +15 -15
  181. package/dist/serverless.js +16 -16
  182. package/dist/sqlite.d.ts +8 -8
  183. package/dist/sqlite.js +53 -22
  184. package/dist/typed-sql.d.ts +4 -4
  185. package/dist/typed-sql.js +5 -5
  186. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
- * turbine-orm SQL dialect contract
3
+ * turbine-orm, SQL dialect contract
4
4
  *
5
5
  * Phase-1 seam for future database packages. The current package remains
6
6
  * PostgreSQL-native by default, but query generation now depends on this
@@ -42,6 +42,7 @@ var __importStar = (this && this.__importStar) || (function () {
42
42
  Object.defineProperty(exports, "__esModule", { value: true });
43
43
  exports.postgresDialect = void 0;
44
44
  const errors_js_1 = require("./errors.js");
45
+ const utils_js_1 = require("./query/utils.js");
45
46
  const schema_js_1 = require("./schema.js");
46
47
  /** PostgreSQL implementation of the dialect contract. */
47
48
  exports.postgresDialect = {
@@ -116,6 +117,28 @@ exports.postgresDialect = {
116
117
  if (!input.columnArrayTypes || input.columnArrayTypes.length !== input.columns.length) {
117
118
  throw new errors_js_1.ValidationError('PostgreSQL bulk insert requires one array type per column');
118
119
  }
120
+ // Row-major form: required when a target column is itself array-typed,
121
+ // because the UNNEST transpose below flattens nested arrays (see
122
+ // `requireRowValues`). One placeholder per cell instead of per column.
123
+ if (input.requireRowValues) {
124
+ const params = [];
125
+ const tuples = input.rowValues.map((row) => {
126
+ const cells = input.columns.map((_, i) => {
127
+ params.push(row[i]);
128
+ // No cast: PostgreSQL infers each parameter's type from the INSERT
129
+ // target column, which is what single-row `create` already relies on
130
+ // and is what makes arrays and enums both work here. The casts in
131
+ // `columnArrayTypes` are ARRAY-OF-column-type, correct for the
132
+ // UNNEST transpose below but wrong for an individual cell.
133
+ return this.paramPlaceholder(params.length);
134
+ });
135
+ return `(${cells.join(', ')})`;
136
+ });
137
+ let rowSql = `INSERT INTO ${input.table} (${input.columns.join(', ')}) VALUES ${tuples.join(', ')}`;
138
+ if (input.skipDuplicates)
139
+ rowSql += ' ON CONFLICT DO NOTHING';
140
+ return { sql: `${rowSql}${this.buildReturningClause(input.returning)}`, params };
141
+ }
119
142
  const columnArrays = input.columns.map((_, columnIndex) => input.rowValues.map((row) => row[columnIndex]));
120
143
  const unnestArgs = input.columns.map((_, i) => `${this.paramPlaceholder(i + 1)}::${input.columnArrayTypes[i]}`);
121
144
  let sql = `INSERT INTO ${input.table} (${input.columns.join(', ')}) SELECT * FROM UNNEST(${unnestArgs.join(', ')})`;
@@ -160,6 +183,21 @@ exports.postgresDialect = {
160
183
  arrayType(baseType) {
161
184
  return (0, schema_js_1.pgArrayType)(baseType);
162
185
  },
186
+ jsonWireRule(columnType) {
187
+ // `json_build_object` renders these as a JSON number / bare token that does
188
+ // not match what the driver returns for the same column (numeric past
189
+ // double precision and int8 past 2^53 lose digits outright). Carry the
190
+ // driver's own wire TEXT instead and hand it back to the driver's parser
191
+ // for that OID, so the join strategy returns exactly what a top-level read
192
+ // returns.
193
+ const oid = (0, utils_js_1.jsonWireCoercionOid)(columnType);
194
+ if (oid === undefined)
195
+ return undefined;
196
+ return {
197
+ sql: (ref) => `${ref}::text`,
198
+ decode: (value) => (0, utils_js_1.coerceJsonWireValue)(oid, value),
199
+ };
200
+ },
163
201
  buildColumnType(input) {
164
202
  if (input.type === 'VARCHAR' && input.maxLength != null) {
165
203
  return `VARCHAR(${input.maxLength})`;
@@ -231,7 +269,7 @@ exports.postgresDialect = {
231
269
  return `ROLLBACK TO SAVEPOINT ${name}`;
232
270
  },
233
271
  buildSetSessionConfig(name, value) {
234
- // set_config(name, value, is_local=true) the parameterizable,
272
+ // set_config(name, value, is_local=true), the parameterizable,
235
273
  // transaction-local equivalent of `SET LOCAL` (which rejects bind params).
236
274
  return {
237
275
  sql: `SELECT set_config(${this.paramPlaceholder(1)}, ${this.paramPlaceholder(2)}, true)`,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * turbine-orm Error types
2
+ * turbine-orm, Error types
3
3
  *
4
4
  * Typed errors with error codes for programmatic handling.
5
5
  * All Turbine errors extend TurbineError which includes a `code` property.
@@ -39,7 +39,7 @@ export declare class TurbineError extends Error {
39
39
  *
40
40
  * Defaults to `'safe'` to avoid leaking PII into error logs (Sentry, Datadog,
41
41
  * etc.). The full `where` object is always available as `err.where` for
42
- * programmatic access only the human-readable message is redacted.
42
+ * programmatic access, only the human-readable message is redacted.
43
43
  *
44
44
  * Set via `setErrorMessageMode('verbose')` or by constructing TurbineClient
45
45
  * with `{ errorMessages: 'verbose' }`.
@@ -182,7 +182,7 @@ export declare class NotNullViolationError extends TurbineError {
182
182
  /**
183
183
  * Thrown when Postgres detects a deadlock (pg code 40P01).
184
184
  *
185
- * This error is **retryable** when caught, callers can safely retry the
185
+ * This error is **retryable**, when caught, callers can safely retry the
186
186
  * transaction (typically with backoff). Catch it explicitly:
187
187
  *
188
188
  * ```ts
@@ -207,9 +207,9 @@ export declare class DeadlockError extends TurbineError {
207
207
  }
208
208
  /**
209
209
  * Thrown when a Serializable transaction fails due to a serialization
210
- * conflict (pg code 40001 `could not serialize access due to ...`).
210
+ * conflict (pg code 40001, `could not serialize access due to ...`).
211
211
  *
212
- * This error is **retryable** by Postgres documentation, the recommended
212
+ * This error is **retryable**, by Postgres documentation, the recommended
213
213
  * response is to re-run the entire transaction. Catch it explicitly:
214
214
  *
215
215
  * ```ts
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /**
3
- * turbine-orm Error types
3
+ * turbine-orm, Error types
4
4
  *
5
5
  * Typed errors with error codes for programmatic handling.
6
6
  * All Turbine errors extend TurbineError which includes a `code` property.
@@ -148,7 +148,7 @@ class NotFoundError extends TurbineError {
148
148
  where;
149
149
  operation;
150
150
  constructor(input) {
151
- // Back-compat: string argument (or undefined) replicate legacy behavior.
151
+ // Back-compat: string argument (or undefined), replicate legacy behavior.
152
152
  if (typeof input === 'string' || input === undefined) {
153
153
  super(exports.TurbineErrorCode.NOT_FOUND, input ?? 'Record not found');
154
154
  this.name = 'NotFoundError';
@@ -270,7 +270,7 @@ class UniqueConstraintError extends TurbineError {
270
270
  // PII-safe by default: the raw pg `detail` string contains the
271
271
  // conflicting row VALUES (e.g. `Key (email)=(alice@x.com) already
272
272
  // exists.`). Only append it in 'verbose' mode. In 'safe' mode the
273
- // message carries keys/constraint/column names only the structured
273
+ // message carries keys/constraint/column names only, the structured
274
274
  // `.columns`/`.constraint`/`.column` fields and `.cause` still expose
275
275
  // the full detail for programmatic use.
276
276
  const detail = errorMessageMode === 'verbose' ? detailFromCause(cause) : undefined;
@@ -298,7 +298,7 @@ class ForeignKeyError extends TurbineError {
298
298
  // PII-safe by default: the raw pg `detail` string contains the
299
299
  // conflicting row VALUES (e.g. `Key (email)=(alice@x.com) already
300
300
  // exists.`). Only append it in 'verbose' mode. In 'safe' mode the
301
- // message carries keys/constraint/column names only the structured
301
+ // message carries keys/constraint/column names only, the structured
302
302
  // `.columns`/`.constraint`/`.column` fields and `.cause` still expose
303
303
  // the full detail for programmatic use.
304
304
  const detail = errorMessageMode === 'verbose' ? detailFromCause(cause) : undefined;
@@ -325,7 +325,7 @@ class NotNullViolationError extends TurbineError {
325
325
  // PII-safe by default: the raw pg `detail` string contains the
326
326
  // conflicting row VALUES (e.g. `Key (email)=(alice@x.com) already
327
327
  // exists.`). Only append it in 'verbose' mode. In 'safe' mode the
328
- // message carries keys/constraint/column names only the structured
328
+ // message carries keys/constraint/column names only, the structured
329
329
  // `.columns`/`.constraint`/`.column` fields and `.cause` still expose
330
330
  // the full detail for programmatic use.
331
331
  const detail = errorMessageMode === 'verbose' ? detailFromCause(cause) : undefined;
@@ -342,7 +342,7 @@ exports.NotNullViolationError = NotNullViolationError;
342
342
  /**
343
343
  * Thrown when Postgres detects a deadlock (pg code 40P01).
344
344
  *
345
- * This error is **retryable** when caught, callers can safely retry the
345
+ * This error is **retryable**, when caught, callers can safely retry the
346
346
  * transaction (typically with backoff). Catch it explicitly:
347
347
  *
348
348
  * ```ts
@@ -374,9 +374,9 @@ class DeadlockError extends TurbineError {
374
374
  exports.DeadlockError = DeadlockError;
375
375
  /**
376
376
  * Thrown when a Serializable transaction fails due to a serialization
377
- * conflict (pg code 40001 `could not serialize access due to ...`).
377
+ * conflict (pg code 40001, `could not serialize access due to ...`).
378
378
  *
379
- * This error is **retryable** by Postgres documentation, the recommended
379
+ * This error is **retryable**, by Postgres documentation, the recommended
380
380
  * response is to re-run the entire transaction. Catch it explicitly:
381
381
  *
382
382
  * ```ts
@@ -419,7 +419,7 @@ class CheckConstraintError extends TurbineError {
419
419
  // PII-safe by default: the raw pg `detail` string contains the
420
420
  // conflicting row VALUES (e.g. `Key (email)=(alice@x.com) already
421
421
  // exists.`). Only append it in 'verbose' mode. In 'safe' mode the
422
- // message carries keys/constraint/column names only the structured
422
+ // message carries keys/constraint/column names only, the structured
423
423
  // `.columns`/`.constraint`/`.column` fields and `.cause` still expose
424
424
  // the full detail for programmatic use.
425
425
  const detail = errorMessageMode === 'verbose' ? detailFromCause(cause) : undefined;
@@ -445,7 +445,7 @@ class ExclusionConstraintError extends TurbineError {
445
445
  // PII-safe by default: the raw pg `detail` string contains the
446
446
  // conflicting row VALUES (e.g. `Key (email)=(alice@x.com) already
447
447
  // exists.`). Only append it in 'verbose' mode. In 'safe' mode the
448
- // message carries keys/constraint/column names only the structured
448
+ // message carries keys/constraint/column names only, the structured
449
449
  // `.columns`/`.constraint`/`.column` fields and `.cause` still expose
450
450
  // the full detail for programmatic use.
451
451
  const detail = errorMessageMode === 'verbose' ? detailFromCause(cause) : undefined;
@@ -505,7 +505,7 @@ class OptimisticLockError extends TurbineError {
505
505
  versionField;
506
506
  expectedVersion;
507
507
  constructor(opts) {
508
- super(exports.TurbineErrorCode.OPTIMISTIC_LOCK, `[turbine] Optimistic lock failed on "${opts.table}" ` +
508
+ super(exports.TurbineErrorCode.OPTIMISTIC_LOCK, `[turbine] Optimistic lock failed on "${opts.table}", ` +
509
509
  `expected ${opts.versionField} = ${opts.expectedVersion} but row was modified by another transaction`);
510
510
  this.name = 'OptimisticLockError';
511
511
  this.table = opts.table;
@@ -1,10 +1,10 @@
1
1
  /**
2
- * turbine-orm Code generator
2
+ * turbine-orm, Code generator
3
3
  *
4
4
  * Takes an IntrospectedSchema and emits TypeScript files:
5
- * - types.ts Entity interfaces, Create/Update input types
6
- * - metadata.ts Runtime schema metadata (column maps, relations, etc.)
7
- * - index.ts Configured TurbineClient with typed table accessors
5
+ * - types.ts , Entity interfaces, Create/Update input types
6
+ * - metadata.ts , Runtime schema metadata (column maps, relations, etc.)
7
+ * - index.ts , Configured TurbineClient with typed table accessors
8
8
  *
9
9
  * Output goes to the specified directory (default: ./generated/turbine/).
10
10
  */
@@ -19,13 +19,13 @@ export interface GenerateOptions {
19
19
  /**
20
20
  * Also emit `zod.ts` with per-table `XSchema` / `XCreateSchema` /
21
21
  * `XUpdateSchema` Zod validators (H1). The file imports the user-side `zod`
22
- * package it is never imported by Turbine's runtime, so Zod stays out of the
22
+ * package, it is never imported by Turbine's runtime, so Zod stays out of the
23
23
  * library's dependency graph. Default: `false`.
24
24
  */
25
25
  zod?: boolean;
26
26
  /**
27
27
  * Omit the `Generated at: <ISO timestamp>` line from every generated file
28
- * header (T-8b reproducible codegen). With this set, byte-identical
28
+ * header (T-8b, reproducible codegen). With this set, byte-identical
29
29
  * schemas regenerate to byte-identical output, so regens produce empty
30
30
  * diffs. Default: `false` (timestamp included, unchanged behavior).
31
31
  */
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  /**
3
- * turbine-orm Code generator
3
+ * turbine-orm, Code generator
4
4
  *
5
5
  * Takes an IntrospectedSchema and emits TypeScript files:
6
- * - types.ts Entity interfaces, Create/Update input types
7
- * - metadata.ts Runtime schema metadata (column maps, relations, etc.)
8
- * - index.ts Configured TurbineClient with typed table accessors
6
+ * - types.ts , Entity interfaces, Create/Update input types
7
+ * - metadata.ts , Runtime schema metadata (column maps, relations, etc.)
8
+ * - index.ts , Configured TurbineClient with typed table accessors
9
9
  *
10
10
  * Output goes to the specified directory (default: ./generated/turbine/).
11
11
  */
@@ -78,7 +78,7 @@ function escSQ(value) {
78
78
  // ---------------------------------------------------------------------------
79
79
  function generate(options) {
80
80
  const outDir = options.outDir ?? './generated/turbine';
81
- // Path traversal protection ensure output stays within project root
81
+ // Path traversal protection, ensure output stays within project root
82
82
  const resolved = (0, node_path_1.resolve)(outDir);
83
83
  const rel = (0, node_path_1.relative)(process.cwd(), resolved);
84
84
  if (rel.startsWith('..') || (0, node_path_1.resolve)(rel) !== resolved) {
@@ -104,7 +104,7 @@ function generate(options) {
104
104
  const indexContent = generateIndex(schema, fileOptions);
105
105
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(outDir, 'index.ts'), indexContent, 'utf-8');
106
106
  files.push('index.ts');
107
- // Generate zod.ts (optional --zod flag)
107
+ // Generate zod.ts (optional, --zod flag)
108
108
  if (options.zod) {
109
109
  const zodContent = generateZod(schema, fileOptions);
110
110
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(outDir, 'zod.ts'), zodContent, 'utf-8');
@@ -263,7 +263,7 @@ function generatedFileHeader(options) {
263
263
  // unchanged schema produces byte-identical files.
264
264
  return [
265
265
  '/**',
266
- ' * Auto-generated by turbine-orm DO NOT EDIT',
266
+ ' * Auto-generated by turbine-orm, DO NOT EDIT',
267
267
  ' *',
268
268
  ...(options?.noTimestamp ? [] : [` * Generated at: ${new Date().toISOString()}`]),
269
269
  ' * @see https://turbineorm.dev',
@@ -277,7 +277,7 @@ function generatedFileHeader(options) {
277
277
  * column: `interface XWithY extends X` becomes TS2430, the `XCreate & { y?: … }`
278
278
  * intersection collapses (TS2322), and neither the column nor the relation is
279
279
  * targetable. Introspection no longer produces such names (they are
280
- * disambiguated at the source), but hand-written or legacy metadata may
280
+ * disambiguated at the source), but hand-written or legacy metadata may -
281
281
  * skip those relations here with a warning instead of emitting broken types.
282
282
  * The runtime metadata (metadata.ts) still carries every relation.
283
283
  */
@@ -287,7 +287,7 @@ function typeSafeRelations(table, warn = true) {
287
287
  for (const [relName, rel] of Object.entries(table.relations)) {
288
288
  if (columnFields.has(relName)) {
289
289
  if (warn) {
290
- console.warn(`[turbine] Relation "${relName}" on table "${table.name}" shadows a column field of the same name ` +
290
+ console.warn(`[turbine] Relation "${relName}" on table "${table.name}" shadows a column field of the same name, ` +
291
291
  `omitting it from the generated types. Rename the relation (or the column) to expose it.`);
292
292
  }
293
293
  continue;
@@ -361,7 +361,7 @@ function generateTypes(schema, options) {
361
361
  lines.push(`/** Input type for creating a row in \`${table.name}\` */`);
362
362
  lines.push(`export type ${typeName}Create = {`);
363
363
  for (const col of table.columns) {
364
- // STORED generated columns are computed by the database never writable.
364
+ // STORED generated columns are computed by the database, never writable.
365
365
  if (col.isGeneratedStored)
366
366
  continue;
367
367
  const isPk = table.primaryKey.includes(col.name);
@@ -393,7 +393,7 @@ function generateTypes(schema, options) {
393
393
  // Each relation is emitted as a `RelationDescriptor<Target, Cardinality,
394
394
  // TargetRelations>` brand-field interface. This is what enables the
395
395
  // recursive `WithResult` type to walk through nested `with` clauses at
396
- // any depth `RelationRelations<R[K]>` reads the third type parameter
396
+ // any depth, `RelationRelations<R[K]>` reads the third type parameter
397
397
  // and threads it into the next recursion step. If the target table has
398
398
  // no relations of its own, the descriptor uses `{}` (the default).
399
399
  const safeRelations = safeRelationsByTable.get(table.name) ?? [];
@@ -437,7 +437,7 @@ function generateTypes(schema, options) {
437
437
  const typeName = entityName(table.name);
438
438
  const safeRelations = safeRelationsByTable.get(table.name) ?? [];
439
439
  const hasRels = safeRelations.length > 0;
440
- // WhereUnique union of unique constraint shapes, deduplicating PK
440
+ // WhereUnique, union of unique constraint shapes, deduplicating PK
441
441
  const seen = new Set();
442
442
  const uniqueSets = [];
443
443
  // Always include the primary key first
@@ -514,7 +514,7 @@ function generateTypes(schema, options) {
514
514
  lines.push(`export type ${typeName}WhereUnique = ${branches.join(' | ')};`);
515
515
  lines.push('');
516
516
  }
517
- // CreateInput / UpdateInput extends base type with optional relation fields
517
+ // CreateInput / UpdateInput, extends base type with optional relation fields
518
518
  if (hasRels) {
519
519
  lines.push(`export type ${typeName}CreateInput = ${typeName}Create & {`);
520
520
  for (const [relName, rel] of safeRelations) {
@@ -568,11 +568,11 @@ function generateTypes(schema, options) {
568
568
  return lines.join('\n');
569
569
  }
570
570
  // ---------------------------------------------------------------------------
571
- // zod.ts generator (H1 `turbine generate --zod`)
571
+ // zod.ts generator (H1, `turbine generate --zod`)
572
572
  // ---------------------------------------------------------------------------
573
573
  /**
574
574
  * Map a TypeScript primitive (as produced by {@link pgTypeToTs}) to its Zod
575
- * expression. `Date` uses `z.coerce.date()` the generated schemas double as
575
+ * expression. `Date` uses `z.coerce.date()`, the generated schemas double as
576
576
  * request-body validators where dates arrive as ISO strings, and coercion keeps
577
577
  * both a `Date` and a valid date-string acceptable (documented decision).
578
578
  */
@@ -591,7 +591,7 @@ function zodScalar(ts) {
591
591
  case 'Buffer':
592
592
  return 'z.instanceof(Uint8Array)';
593
593
  case 'number[]':
594
- // pgvector `pgTypeToTs('vector')` yields `number[]`.
594
+ // pgvector, `pgTypeToTs('vector')` yields `number[]`.
595
595
  return 'z.array(z.number())';
596
596
  default:
597
597
  // json/jsonb and any unmapped user-defined type.
@@ -601,7 +601,7 @@ function zodScalar(ts) {
601
601
  /**
602
602
  * Base Zod expression for a column, resolving enums → `z.enum([...])`, arrays →
603
603
  * `.array()`, and vectors → `z.array(z.number())`. Does NOT append
604
- * `.nullable()` / `.optional()` callers layer those on per-schema.
604
+ * `.nullable()` / `.optional()`, callers layer those on per-schema.
605
605
  *
606
606
  * `forWrite` mirrors {@link writeColumnTsType}: the Create/Update schemas
607
607
  * validate WRITE input, where a `time` / `timetz` column also accepts a JS
@@ -636,7 +636,7 @@ function zodBaseType(col, enums, forWrite = false) {
636
636
  */
637
637
  function generateZod(schema, options) {
638
638
  const lines = [...generatedFileHeader(options)];
639
- // `zod` is a USER dependency this generated file imports it, but the Turbine
639
+ // `zod` is a USER dependency, this generated file imports it, but the Turbine
640
640
  // library runtime never does, so Zod stays out of the package's dep graph.
641
641
  lines.push("import { z } from 'zod';");
642
642
  lines.push('');
@@ -653,7 +653,7 @@ function generateZod(schema, options) {
653
653
  }
654
654
  lines.push('});');
655
655
  lines.push('');
656
- // Create schema STORED generated columns can never be written; PK,
656
+ // Create schema, STORED generated columns can never be written; PK,
657
657
  // defaulted, and nullable columns are optional.
658
658
  lines.push(`/** Zod schema for creating a \`${table.name}\` row */`);
659
659
  lines.push(`export const ${typeName}CreateSchema = z.object({`);
@@ -670,7 +670,7 @@ function generateZod(schema, options) {
670
670
  }
671
671
  lines.push('});');
672
672
  lines.push('');
673
- // Update schema PK and STORED generated columns omitted; all else optional.
673
+ // Update schema, PK and STORED generated columns omitted; all else optional.
674
674
  lines.push(`/** Zod schema for updating a \`${table.name}\` row */`);
675
675
  lines.push(`export const ${typeName}UpdateSchema = z.object({`);
676
676
  for (const col of table.columns) {
@@ -752,7 +752,7 @@ function generateMetadata(schema, options) {
752
752
  const refLiteral = Array.isArray(rel.referenceKey)
753
753
  ? `[${rel.referenceKey.map((c) => `'${escSQ(c)}'`).join(', ')}]`
754
754
  : `'${escSQ(rel.referenceKey)}'`;
755
- // manyToMany relations carry a `through` junction descriptor emit it so
755
+ // manyToMany relations carry a `through` junction descriptor, emit it so
756
756
  // the runtime query builder can JOIN through the junction table.
757
757
  let throughLiteral = '';
758
758
  if (rel.through) {
@@ -786,7 +786,7 @@ function generateMetadata(schema, options) {
786
786
  }
787
787
  lines.push(' ],');
788
788
  }
789
- // isView read-only marker; the runtime write guard reads it.
789
+ // isView, read-only marker; the runtime write guard reads it.
790
790
  if (table.isView)
791
791
  lines.push(' isView: true,');
792
792
  lines.push(' },');
@@ -839,7 +839,7 @@ function generateIndex(schema, options) {
839
839
  lines.push(`import type { ${typeImports.join(', ')} } from './types${ext}';`);
840
840
  lines.push('');
841
841
  // -------------------------------------------------------------------------
842
- // TypedTransactionClient same typed table accessors as TurbineClient,
842
+ // TypedTransactionClient, same typed table accessors as TurbineClient,
843
843
  // but scoped to a single transaction connection. The runtime instance is
844
844
  // an ordinary `TransactionClient` from turbine-orm; this declaration just
845
845
  // teaches TypeScript about the auto-attached accessors so users get
@@ -847,7 +847,7 @@ function generateIndex(schema, options) {
847
847
  // -------------------------------------------------------------------------
848
848
  lines.push('/**');
849
849
  lines.push(' * Transaction-scoped client with the same typed table accessors as TurbineClient.');
850
- lines.push(' * Created automatically by `db.$transaction(async (tx) => ...)` never instantiate');
850
+ lines.push(' * Created automatically by `db.$transaction(async (tx) => ...)`, never instantiate');
851
851
  lines.push(' * directly. All queries run on a dedicated connection within a BEGIN/COMMIT block.');
852
852
  lines.push(' */');
853
853
  lines.push('export class TypedTransactionClient extends BaseTransactionClient {');
@@ -912,7 +912,7 @@ function generateIndex(schema, options) {
912
912
  // so users get autocomplete on `tx.users`, `tx.posts`, etc.
913
913
  //
914
914
  // IMPORTANT: the merged member must be compatible with the base class's
915
- // $transaction ON ITS OWN (TS2415) since v0.26 the base method also has a
915
+ // $transaction ON ITS OWN (TS2415), since v0.26 the base method also has a
916
916
  // batch-array overload (`$transaction([...queries])`), so the merged
917
917
  // interface must redeclare BOTH signatures. Emitting only the callback form
918
918
  // makes every generated client fail `tsc` with "incorrectly extends".
@@ -1042,7 +1042,7 @@ function serializeColumn(col) {
1042
1042
  `arrayType: '${escSQ(col.arrayType ?? col.pgArrayType)}'`,
1043
1043
  `pgArrayType: '${escSQ(col.pgArrayType)}'`,
1044
1044
  ];
1045
- // Cross-schema type marker introspection records it only for types living
1045
+ // Cross-schema type marker, introspection records it only for types living
1046
1046
  // outside the introspected schema; it must survive codegen or the runtime
1047
1047
  // enum-cast guard in query/builder.ts loses the signal (N-5).
1048
1048
  if (col.pgTypeSchema !== undefined)
@@ -1051,7 +1051,7 @@ function serializeColumn(col) {
1051
1051
  // output stays byte-identical for the common client-default columns.
1052
1052
  if (col.isGenerated)
1053
1053
  parts.push(`isGenerated: true`);
1054
- // STORED generated columns the runtime write guard reads isGeneratedStored.
1054
+ // STORED generated columns, the runtime write guard reads isGeneratedStored.
1055
1055
  if (col.isGeneratedStored)
1056
1056
  parts.push(`isGeneratedStored: true`);
1057
1057
  if (col.generationExpression !== undefined) {
@@ -1062,6 +1062,8 @@ function serializeColumn(col) {
1062
1062
  // object built from `defineSchema` (pii: true) carries it through codegen.
1063
1063
  if (col.pii)
1064
1064
  parts.push(`pii: true`);
1065
+ if (col.updatedAt)
1066
+ parts.push(`updatedAt: true`);
1065
1067
  if (col.maxLength !== undefined)
1066
1068
  parts.push(`maxLength: ${col.maxLength}`);
1067
1069
  return `{ ${parts.join(', ')} }`;
@@ -1077,7 +1079,7 @@ function snakeToCamelStr(s) {
1077
1079
  * `T | UpdateOperatorInput<number> | null?` so users can write atomic
1078
1080
  * operators (`{ increment: 1 }`, `{ multiply: 2 }`, etc.) without casts.
1079
1081
  *
1080
- * The check is purely structural if the column's TS type contains
1082
+ * The check is purely structural, if the column's TS type contains
1081
1083
  * `'number'` (e.g. `number`, `number | null`), it's eligible. Other
1082
1084
  * scalar types (`string`, `boolean`, `Date`, `unknown`, `Buffer`,
1083
1085
  * `Date | null`, etc.) pass through unchanged.
@@ -1091,7 +1093,7 @@ function updateFieldType(tsType) {
1091
1093
  }
1092
1094
  /**
1093
1095
  * Detect whether a TypeScript type expression contains the `number` primitive
1094
- * as a top-level union member. Conservative on purpose only matches
1096
+ * as a top-level union member. Conservative on purpose, only matches
1095
1097
  * `number`, `number | null`, `null | number`, etc., not `number[]` or
1096
1098
  * `Record<string, number>`.
1097
1099
  */
@@ -1,11 +1,11 @@
1
1
  /**
2
- * Index advisor finds relation probes that lack index support.
2
+ * Index advisor, finds relation probes that lack index support.
3
3
  *
4
4
  * Turbine loads `with` relations as correlated subqueries: for every parent row,
5
5
  * the child table is probed by its FK column(s) (`child.fk = parent.pk`). Relation
6
6
  * filters (`some`/`none`/`every`, `is`/`isNot`) probe the same columns. This
7
7
  * strategy outperforms batched loading (`WHERE fk IN (ids)`) when the probed
8
- * column is indexed but with NO index, each probe is a full table scan and the
8
+ * column is indexed, but with NO index, each probe is a full table scan and the
9
9
  * cost multiplies by the parent rowcount, while batched loading would pay the
10
10
  * scan only once. A missing FK index that is invisible under a batched-loader
11
11
  * ORM becomes pathological under a correlated one.
@@ -27,7 +27,7 @@ export interface RelationProbe {
27
27
  export interface MissingRelationIndex {
28
28
  /** Table that gets probed per parent row */
29
29
  table: string;
30
- /** Probed column(s) equality lookups, so a covering index must LEAD with one of them */
30
+ /** Probed column(s), equality lookups, so a covering index must LEAD with one of them */
31
31
  columns: string[];
32
32
  /** Every relation that generates this probe */
33
33
  probes: RelationProbe[];
@@ -46,7 +46,7 @@ export interface CreateIndexSqlOptions {
46
46
  * it must also carry the `-- turbine:no-transaction` directive.
47
47
  */
48
48
  concurrently?: boolean;
49
- /** Emit `IF NOT EXISTS` (default true required for idempotent no-transaction migrations). */
49
+ /** Emit `IF NOT EXISTS` (default true, required for idempotent no-transaction migrations). */
50
50
  ifNotExists?: boolean;
51
51
  /**
52
52
  * Emit a partial index `... WHERE <col> IS NOT NULL`. Only applied for a
@@ -134,7 +134,7 @@ export declare function schemaHasIndexInfo(schema: SchemaMetadata): boolean;
134
134
  * Single-relation check for the dev-mode runtime warning: the (table, columns)
135
135
  * this relation probes and whether that probe is unindexed. Returns null when
136
136
  * indexed, unknown, or when the schema carries no index info at all (metadata
137
- * built without introspection warning would be a blanket false positive).
137
+ * built without introspection, warning would be a blanket false positive).
138
138
  */
139
139
  export declare function missingIndexForRelation(schema: SchemaMetadata, relDef: {
140
140
  name: string;
Binary file
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * turbine-orm
3
3
  *
4
- * Turbine TypeScript SDK type-safe Postgres queries with nested relations
4
+ * Turbine TypeScript SDK, type-safe Postgres queries with nested relations
5
5
  * and pipeline batching. Feels like Prisma, runs at raw-SQL speed.
6
6
  *
7
7
  * @example
package/dist/cjs/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * turbine-orm
4
4
  *
5
- * Turbine TypeScript SDK type-safe Postgres queries with nested relations
5
+ * Turbine TypeScript SDK, type-safe Postgres queries with nested relations
6
6
  * and pipeline batching. Feels like Prisma, runs at raw-SQL speed.
7
7
  *
8
8
  * @example
@@ -101,7 +101,7 @@ Object.defineProperty(exports, "AUTO_TO_ONE_JOIN_MAX_ROWS", { enumerable: true,
101
101
  Object.defineProperty(exports, "AUTO_TO_ONE_JOIN_ROWS_MAX", { enumerable: true, get: function () { return index_js_2.AUTO_TO_ONE_JOIN_ROWS_MAX; } });
102
102
  Object.defineProperty(exports, "AUTO_TO_ONE_JOIN_ROWS_MIN", { enumerable: true, get: function () { return index_js_2.AUTO_TO_ONE_JOIN_ROWS_MIN; } });
103
103
  Object.defineProperty(exports, "QueryInterface", { enumerable: true, get: function () { return index_js_2.QueryInterface; } });
104
- // Realtime LISTEN/NOTIFY pub/sub
104
+ // Realtime, LISTEN/NOTIFY pub/sub
105
105
  var realtime_js_1 = require("./realtime.js");
106
106
  Object.defineProperty(exports, "validateChannel", { enumerable: true, get: function () { return realtime_js_1.validateChannel; } });
107
107
  // Schema utilities
@@ -115,19 +115,19 @@ Object.defineProperty(exports, "singularize", { enumerable: true, get: function
115
115
  Object.defineProperty(exports, "snakeToCamel", { enumerable: true, get: function () { return schema_js_1.snakeToCamel; } });
116
116
  Object.defineProperty(exports, "snakeToPascal", { enumerable: true, get: function () { return schema_js_1.snakeToPascal; } });
117
117
  Object.defineProperty(exports, "withDbFieldNames", { enumerable: true, get: function () { return schema_js_1.withDbFieldNames; } });
118
- // Schema builder define schemas in TypeScript
118
+ // Schema builder, define schemas in TypeScript
119
119
  var schema_builder_js_1 = require("./schema-builder.js");
120
120
  Object.defineProperty(exports, "applyManyToManyRelations", { enumerable: true, get: function () { return schema_builder_js_1.applyManyToManyRelations; } });
121
121
  Object.defineProperty(exports, "ColumnBuilder", { enumerable: true, get: function () { return schema_builder_js_1.ColumnBuilder; } });
122
122
  Object.defineProperty(exports, "column", { enumerable: true, get: function () { return schema_builder_js_1.column; } });
123
123
  Object.defineProperty(exports, "defineSchema", { enumerable: true, get: function () { return schema_builder_js_1.defineSchema; } });
124
124
  Object.defineProperty(exports, "isDocFieldIndexDef", { enumerable: true, get: function () { return schema_builder_js_1.isDocFieldIndexDef; } });
125
- // Legacy compat (deprecated use object format with defineSchema)
125
+ // Legacy compat (deprecated, use object format with defineSchema)
126
126
  Object.defineProperty(exports, "table", { enumerable: true, get: function () { return schema_builder_js_1.table; } });
127
- // Schema metadata bridge defineSchema() → SchemaMetadata without a live DB
127
+ // Schema metadata bridge, defineSchema() → SchemaMetadata without a live DB
128
128
  var schema_metadata_js_1 = require("./schema-metadata.js");
129
129
  Object.defineProperty(exports, "schemaDefToMetadata", { enumerable: true, get: function () { return schema_metadata_js_1.schemaDefToMetadata; } });
130
- // Schema SQL generate DDL, diff, and push
130
+ // Schema SQL, generate DDL, diff, and push
131
131
  var schema_sql_js_1 = require("./schema-sql.js");
132
132
  Object.defineProperty(exports, "DestructivePushRefusal", { enumerable: true, get: function () { return schema_sql_js_1.DestructivePushRefusal; } });
133
133
  Object.defineProperty(exports, "schemaDiff", { enumerable: true, get: function () { return schema_sql_js_1.schemaDiff; } });
@@ -140,7 +140,7 @@ Object.defineProperty(exports, "defineSeed", { enumerable: true, get: function (
140
140
  // Serverless / edge factory
141
141
  var serverless_js_1 = require("./serverless.js");
142
142
  Object.defineProperty(exports, "turbineHttp", { enumerable: true, get: function () { return serverless_js_1.turbineHttp; } });
143
- // Typed raw SQL Turbine's TypedSQL escape hatch
143
+ // Typed raw SQL, Turbine's TypedSQL escape hatch
144
144
  var typed_sql_js_1 = require("./typed-sql.js");
145
145
  Object.defineProperty(exports, "buildTypedSql", { enumerable: true, get: function () { return typed_sql_js_1.buildTypedSql; } });
146
146
  Object.defineProperty(exports, "TypedSqlQuery", { enumerable: true, get: function () { return typed_sql_js_1.TypedSqlQuery; } });