turbine-orm 0.81.0 → 0.90.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 (295) hide show
  1. package/README.md +26 -25
  2. package/dist/checkout.d.ts +27 -2
  3. package/dist/checkout.js +75 -4
  4. package/dist/cjs/checkout.d.ts +27 -2
  5. package/dist/cjs/checkout.js +76 -3
  6. package/dist/cjs/cli/code-first-tags.d.ts +62 -0
  7. package/dist/cjs/cli/code-first-tags.js +124 -0
  8. package/dist/cjs/cli/compile-query.js +9 -0
  9. package/dist/cjs/cli/config.d.ts +35 -6
  10. package/dist/cjs/cli/config.js +17 -1
  11. package/dist/cjs/cli/destructive.d.ts +7 -4
  12. package/dist/cjs/cli/destructive.js +224 -20
  13. package/dist/cjs/cli/error-catalog.js +36 -0
  14. package/dist/cjs/cli/error-text.d.ts +15 -0
  15. package/dist/cjs/cli/error-text.js +40 -0
  16. package/dist/cjs/cli/index.d.ts +62 -4
  17. package/dist/cjs/cli/index.js +568 -108
  18. package/dist/cjs/cli/local-server-guard.d.ts +53 -0
  19. package/dist/cjs/cli/local-server-guard.js +119 -0
  20. package/dist/cjs/cli/local-server-output.d.ts +41 -0
  21. package/dist/cjs/cli/local-server-output.js +103 -0
  22. package/dist/cjs/cli/mcp.d.ts +8 -0
  23. package/dist/cjs/cli/mcp.js +121 -32
  24. package/dist/cjs/cli/migrate.d.ts +113 -5
  25. package/dist/cjs/cli/migrate.js +270 -21
  26. package/dist/cjs/cli/observe.d.ts +6 -1
  27. package/dist/cjs/cli/observe.js +85 -55
  28. package/dist/cjs/cli/pii-predicate-guard.d.ts +43 -23
  29. package/dist/cjs/cli/pii-predicate-guard.js +98 -37
  30. package/dist/cjs/cli/prisma-resolve.js +17 -13
  31. package/dist/cjs/cli/prisma-schema.js +12 -4
  32. package/dist/cjs/cli/studio-ui.generated.js +1 -1
  33. package/dist/cjs/cli/studio.d.ts +14 -2
  34. package/dist/cjs/cli/studio.js +244 -69
  35. package/dist/cjs/cli/ui.d.ts +1 -1
  36. package/dist/cjs/client.d.ts +558 -85
  37. package/dist/cjs/client.js +1270 -395
  38. package/dist/cjs/connection-guard.d.ts +13 -0
  39. package/dist/cjs/connection-guard.js +28 -0
  40. package/dist/cjs/connection-url.d.ts +51 -16
  41. package/dist/cjs/connection-url.js +67 -34
  42. package/dist/cjs/diagnostics.d.ts +81 -0
  43. package/dist/cjs/diagnostics.js +147 -0
  44. package/dist/cjs/dialect.d.ts +449 -20
  45. package/dist/cjs/dialect.js +117 -76
  46. package/dist/cjs/engine-config.d.ts +7 -6
  47. package/dist/cjs/errors.d.ts +126 -6
  48. package/dist/cjs/errors.js +256 -13
  49. package/dist/cjs/generate.d.ts +57 -7
  50. package/dist/cjs/generate.js +635 -279
  51. package/dist/cjs/global-filters-config.d.ts +59 -0
  52. package/dist/cjs/global-filters-config.js +367 -0
  53. package/dist/cjs/index.d.ts +9 -4
  54. package/dist/cjs/index.js +10 -2
  55. package/dist/cjs/introspect.d.ts +31 -6
  56. package/dist/cjs/introspect.js +108 -50
  57. package/dist/cjs/log-codes.d.ts +12 -0
  58. package/dist/cjs/log-codes.js +77 -0
  59. package/dist/cjs/logger.d.ts +87 -0
  60. package/dist/cjs/logger.js +98 -0
  61. package/dist/cjs/mssql.d.ts +8 -5
  62. package/dist/cjs/mssql.js +352 -65
  63. package/dist/cjs/mysql.d.ts +3 -5
  64. package/dist/cjs/mysql.js +420 -70
  65. package/dist/cjs/nested-write.d.ts +3 -0
  66. package/dist/cjs/nested-write.js +179 -114
  67. package/dist/cjs/pipeline-submittable.d.ts +12 -0
  68. package/dist/cjs/pipeline-submittable.js +118 -44
  69. package/dist/cjs/pipeline.js +21 -26
  70. package/dist/cjs/powdb-introspect.d.ts +5 -2
  71. package/dist/cjs/powdb-introspect.js +20 -15
  72. package/dist/cjs/powdb-shared.d.ts +36 -5
  73. package/dist/cjs/powdb-shared.js +67 -8
  74. package/dist/cjs/powdb.d.ts +4 -0
  75. package/dist/cjs/powdb.js +183 -51
  76. package/dist/cjs/powql.d.ts +394 -51
  77. package/dist/cjs/powql.js +1829 -284
  78. package/dist/cjs/prisma-compat.d.ts +23 -15
  79. package/dist/cjs/prisma-compat.js +507 -372
  80. package/dist/cjs/query/aggregates.d.ts +17 -1
  81. package/dist/cjs/query/aggregates.js +261 -29
  82. package/dist/cjs/query/batched-loader.d.ts +25 -6
  83. package/dist/cjs/query/batched-loader.js +103 -20
  84. package/dist/cjs/query/builder.d.ts +325 -184
  85. package/dist/cjs/query/builder.js +1452 -490
  86. package/dist/cjs/query/column-ref.d.ts +61 -0
  87. package/dist/cjs/query/column-ref.js +73 -0
  88. package/dist/cjs/query/compound-unique.d.ts +21 -0
  89. package/dist/cjs/query/compound-unique.js +98 -18
  90. package/dist/cjs/query/deferred.d.ts +53 -16
  91. package/dist/cjs/query/expr.d.ts +217 -0
  92. package/dist/cjs/query/expr.js +859 -0
  93. package/dist/cjs/query/filters.d.ts +155 -53
  94. package/dist/cjs/query/filters.js +613 -76
  95. package/dist/cjs/query/index.d.ts +2 -0
  96. package/dist/cjs/query/index.js +7 -1
  97. package/dist/cjs/query/json-value.d.ts +43 -0
  98. package/dist/cjs/query/json-value.js +59 -0
  99. package/dist/cjs/query/normalize-args.d.ts +87 -0
  100. package/dist/cjs/query/normalize-args.js +527 -0
  101. package/dist/cjs/query/option-surface.d.ts +16 -4
  102. package/dist/cjs/query/option-surface.js +57 -14
  103. package/dist/cjs/query/relation-names.d.ts +14 -0
  104. package/dist/cjs/query/relation-names.js +77 -18
  105. package/dist/cjs/query/relations.d.ts +30 -3
  106. package/dist/cjs/query/relations.js +219 -63
  107. package/dist/cjs/query/row-lock.d.ts +49 -0
  108. package/dist/cjs/query/row-lock.js +138 -0
  109. package/dist/cjs/query/sql-comment.d.ts +161 -0
  110. package/dist/cjs/query/sql-comment.js +381 -0
  111. package/dist/cjs/query/stream-idle.d.ts +132 -0
  112. package/dist/cjs/query/stream-idle.js +212 -0
  113. package/dist/cjs/query/table-client.d.ts +101 -0
  114. package/dist/cjs/query/table-client.js +74 -0
  115. package/dist/cjs/query/types.d.ts +677 -298
  116. package/dist/cjs/query/utils.d.ts +105 -6
  117. package/dist/cjs/query/utils.js +426 -19
  118. package/dist/cjs/query/warn-registry.d.ts +18 -0
  119. package/dist/cjs/query/warn-registry.js +18 -0
  120. package/dist/cjs/query/where-compile.d.ts +138 -14
  121. package/dist/cjs/query/where-compile.js +513 -29
  122. package/dist/cjs/query/where.d.ts +159 -59
  123. package/dist/cjs/query/where.js +716 -246
  124. package/dist/cjs/query/writes.d.ts +112 -50
  125. package/dist/cjs/query/writes.js +1498 -200
  126. package/dist/cjs/query-events.d.ts +4 -2
  127. package/dist/cjs/query-events.js +3 -1
  128. package/dist/cjs/realtime.d.ts +7 -3
  129. package/dist/cjs/realtime.js +13 -2
  130. package/dist/cjs/schema-builder.d.ts +55 -4
  131. package/dist/cjs/schema-builder.js +382 -18
  132. package/dist/cjs/schema-metadata.d.ts +21 -1
  133. package/dist/cjs/schema-metadata.js +29 -7
  134. package/dist/cjs/schema-sql.d.ts +75 -5
  135. package/dist/cjs/schema-sql.js +497 -45
  136. package/dist/cjs/schema.d.ts +26 -5
  137. package/dist/cjs/schema.js +110 -13
  138. package/dist/cjs/sql-placeholders.d.ts +56 -0
  139. package/dist/cjs/sql-placeholders.js +204 -0
  140. package/dist/cjs/sqlite.d.ts +75 -20
  141. package/dist/cjs/sqlite.js +593 -95
  142. package/dist/cjs/supplied-pool-types.d.ts +48 -0
  143. package/dist/cjs/supplied-pool-types.js +256 -0
  144. package/dist/cjs/transaction-control.d.ts +51 -0
  145. package/dist/cjs/transaction-control.js +316 -0
  146. package/dist/cjs/transaction-state.d.ts +342 -0
  147. package/dist/cjs/transaction-state.js +707 -0
  148. package/dist/cjs/typed-sql.d.ts +37 -3
  149. package/dist/cjs/typed-sql.js +102 -8
  150. package/dist/cli/code-first-tags.d.ts +62 -0
  151. package/dist/cli/code-first-tags.js +120 -0
  152. package/dist/cli/compile-query.js +9 -0
  153. package/dist/cli/config.d.ts +35 -6
  154. package/dist/cli/config.js +16 -1
  155. package/dist/cli/destructive.d.ts +7 -4
  156. package/dist/cli/destructive.js +224 -20
  157. package/dist/cli/error-catalog.js +36 -0
  158. package/dist/cli/error-text.d.ts +15 -0
  159. package/dist/cli/error-text.js +37 -0
  160. package/dist/cli/index.d.ts +62 -4
  161. package/dist/cli/index.js +569 -112
  162. package/dist/cli/local-server-guard.d.ts +53 -0
  163. package/dist/cli/local-server-guard.js +113 -0
  164. package/dist/cli/local-server-output.d.ts +41 -0
  165. package/dist/cli/local-server-output.js +98 -0
  166. package/dist/cli/mcp.d.ts +8 -0
  167. package/dist/cli/mcp.js +121 -34
  168. package/dist/cli/migrate.d.ts +113 -5
  169. package/dist/cli/migrate.js +261 -21
  170. package/dist/cli/observe.d.ts +6 -1
  171. package/dist/cli/observe.js +84 -54
  172. package/dist/cli/pii-predicate-guard.d.ts +43 -23
  173. package/dist/cli/pii-predicate-guard.js +100 -35
  174. package/dist/cli/prisma-resolve.js +15 -11
  175. package/dist/cli/prisma-schema.js +12 -4
  176. package/dist/cli/studio-ui.generated.js +1 -1
  177. package/dist/cli/studio.d.ts +14 -2
  178. package/dist/cli/studio.js +246 -71
  179. package/dist/cli/ui.d.ts +1 -1
  180. package/dist/client.d.ts +558 -85
  181. package/dist/client.js +1275 -400
  182. package/dist/connection-guard.d.ts +13 -0
  183. package/dist/connection-guard.js +27 -0
  184. package/dist/connection-url.d.ts +51 -16
  185. package/dist/connection-url.js +63 -34
  186. package/dist/diagnostics.d.ts +81 -0
  187. package/dist/diagnostics.js +144 -0
  188. package/dist/dialect.d.ts +449 -20
  189. package/dist/dialect.js +115 -43
  190. package/dist/engine-config.d.ts +7 -6
  191. package/dist/errors.d.ts +126 -6
  192. package/dist/errors.js +252 -12
  193. package/dist/generate.d.ts +57 -7
  194. package/dist/generate.js +635 -281
  195. package/dist/global-filters-config.d.ts +59 -0
  196. package/dist/global-filters-config.js +361 -0
  197. package/dist/index.d.ts +9 -4
  198. package/dist/index.js +4 -2
  199. package/dist/introspect.d.ts +31 -6
  200. package/dist/introspect.js +106 -50
  201. package/dist/log-codes.d.ts +12 -0
  202. package/dist/log-codes.js +74 -0
  203. package/dist/logger.d.ts +87 -0
  204. package/dist/logger.js +93 -0
  205. package/dist/mssql.d.ts +8 -5
  206. package/dist/mssql.js +354 -67
  207. package/dist/mysql.d.ts +3 -5
  208. package/dist/mysql.js +423 -73
  209. package/dist/nested-write.d.ts +3 -0
  210. package/dist/nested-write.js +177 -112
  211. package/dist/pipeline-submittable.d.ts +12 -0
  212. package/dist/pipeline-submittable.js +117 -44
  213. package/dist/pipeline.js +21 -26
  214. package/dist/powdb-introspect.d.ts +5 -2
  215. package/dist/powdb-introspect.js +21 -16
  216. package/dist/powdb-shared.d.ts +36 -5
  217. package/dist/powdb-shared.js +65 -8
  218. package/dist/powdb.d.ts +4 -0
  219. package/dist/powdb.js +183 -51
  220. package/dist/powql.d.ts +394 -51
  221. package/dist/powql.js +1836 -291
  222. package/dist/prisma-compat.d.ts +23 -15
  223. package/dist/prisma-compat.js +508 -373
  224. package/dist/query/aggregates.d.ts +17 -1
  225. package/dist/query/aggregates.js +263 -32
  226. package/dist/query/batched-loader.d.ts +25 -6
  227. package/dist/query/batched-loader.js +101 -21
  228. package/dist/query/builder.d.ts +325 -184
  229. package/dist/query/builder.js +1458 -495
  230. package/dist/query/column-ref.d.ts +61 -0
  231. package/dist/query/column-ref.js +66 -0
  232. package/dist/query/compound-unique.d.ts +21 -0
  233. package/dist/query/compound-unique.js +97 -19
  234. package/dist/query/deferred.d.ts +53 -16
  235. package/dist/query/expr.d.ts +217 -0
  236. package/dist/query/expr.js +848 -0
  237. package/dist/query/filters.d.ts +155 -53
  238. package/dist/query/filters.js +597 -72
  239. package/dist/query/index.d.ts +2 -0
  240. package/dist/query/index.js +4 -0
  241. package/dist/query/json-value.d.ts +43 -0
  242. package/dist/query/json-value.js +54 -0
  243. package/dist/query/normalize-args.d.ts +87 -0
  244. package/dist/query/normalize-args.js +517 -0
  245. package/dist/query/option-surface.d.ts +16 -4
  246. package/dist/query/option-surface.js +56 -13
  247. package/dist/query/relation-names.d.ts +14 -0
  248. package/dist/query/relation-names.js +77 -19
  249. package/dist/query/relations.d.ts +30 -3
  250. package/dist/query/relations.js +220 -67
  251. package/dist/query/row-lock.d.ts +49 -0
  252. package/dist/query/row-lock.js +131 -0
  253. package/dist/query/sql-comment.d.ts +161 -0
  254. package/dist/query/sql-comment.js +374 -0
  255. package/dist/query/stream-idle.d.ts +132 -0
  256. package/dist/query/stream-idle.js +203 -0
  257. package/dist/query/table-client.d.ts +101 -0
  258. package/dist/query/table-client.js +70 -0
  259. package/dist/query/types.d.ts +677 -298
  260. package/dist/query/utils.d.ts +105 -6
  261. package/dist/query/utils.js +414 -18
  262. package/dist/query/warn-registry.d.ts +18 -0
  263. package/dist/query/warn-registry.js +18 -0
  264. package/dist/query/where-compile.d.ts +138 -14
  265. package/dist/query/where-compile.js +508 -31
  266. package/dist/query/where.d.ts +159 -59
  267. package/dist/query/where.js +711 -248
  268. package/dist/query/writes.d.ts +112 -50
  269. package/dist/query/writes.js +1496 -202
  270. package/dist/query-events.d.ts +4 -2
  271. package/dist/query-events.js +3 -1
  272. package/dist/realtime.d.ts +7 -3
  273. package/dist/realtime.js +13 -2
  274. package/dist/schema-builder.d.ts +55 -4
  275. package/dist/schema-builder.js +381 -18
  276. package/dist/schema-metadata.d.ts +21 -1
  277. package/dist/schema-metadata.js +28 -7
  278. package/dist/schema-sql.d.ts +75 -5
  279. package/dist/schema-sql.js +494 -44
  280. package/dist/schema.d.ts +26 -5
  281. package/dist/schema.js +109 -13
  282. package/dist/sql-placeholders.d.ts +56 -0
  283. package/dist/sql-placeholders.js +200 -0
  284. package/dist/sqlite.d.ts +75 -20
  285. package/dist/sqlite.js +597 -99
  286. package/dist/supplied-pool-types.d.ts +48 -0
  287. package/dist/supplied-pool-types.js +247 -0
  288. package/dist/transaction-control.d.ts +51 -0
  289. package/dist/transaction-control.js +311 -0
  290. package/dist/transaction-state.d.ts +342 -0
  291. package/dist/transaction-state.js +696 -0
  292. package/dist/typed-sql.d.ts +37 -3
  293. package/dist/typed-sql.js +100 -8
  294. package/package.json +7 -4
  295. package/skills/turbine-orm/SKILL.md +56 -6
package/dist/errors.js CHANGED
@@ -25,6 +25,8 @@ export const TurbineErrorCode = {
25
25
  EXCLUSION_VIOLATION: 'TURBINE_E016',
26
26
  UNSUPPORTED_FEATURE: 'TURBINE_E017',
27
27
  READ_ONLY: 'TURBINE_E018',
28
+ TRANSACTION_ROLLED_BACK: 'TURBINE_E019',
29
+ INVARIANT_VIOLATION: 'TURBINE_E020',
28
30
  };
29
31
  /**
30
32
  * The docs page anchor for a code: `TURBINE_E003` -> `.../errors#e003`.
@@ -607,12 +609,14 @@ function renderWhereForMessage(where, mode) {
607
609
  * `[TURBINE_E001] findUniqueOrThrow on "users" found no record matching where: {"id":1}`
608
610
  *
609
611
  * The full `where` object, `table`, and `operation` are always available as
610
- * structured properties on the error instance regardless of mode.
612
+ * structured properties on the error instance regardless of mode. `where`
613
+ * carries the caller's raw values, so under 'safe' it is NON-ENUMERABLE:
614
+ * `err.where` reads it, while `JSON.stringify`, `util.inspect` and error
615
+ * serializers that copy own enumerable fields leave it out.
611
616
  */
612
617
  export class NotFoundError extends TurbineError {
613
618
  static CODE = TurbineErrorCode.NOT_FOUND;
614
619
  table;
615
- where;
616
620
  operation;
617
621
  constructor(input) {
618
622
  // Back-compat: string argument (or undefined), replicate legacy behavior.
@@ -639,7 +643,12 @@ export class NotFoundError extends TurbineError {
639
643
  super(TurbineErrorCode.NOT_FOUND, message, { cause });
640
644
  this.name = 'NotFoundError';
641
645
  this.table = table;
642
- this.where = where;
646
+ Object.defineProperty(this, 'where', {
647
+ value: where,
648
+ enumerable: currentErrorMessageMode() === 'verbose',
649
+ writable: false,
650
+ configurable: true,
651
+ });
643
652
  this.operation = operation;
644
653
  }
645
654
  }
@@ -647,18 +656,22 @@ export class NotFoundError extends TurbineError {
647
656
  export class TimeoutError extends TurbineError {
648
657
  static CODE = TurbineErrorCode.TIMEOUT;
649
658
  timeoutMs;
659
+ /** Whether the interrupted statement can have taken effect. See {@link TimeoutOutcome}. */
660
+ outcome;
650
661
  /**
651
662
  * @param timeoutMs the client-side timeout budget in ms. Pass `0` when the
652
663
  * duration is unknown (e.g. a server-side `statement_timeout` cancellation
653
664
  * surfaced via `wrapPgError`, where Turbine did not set the deadline).
654
665
  * @param context human label for the operation ("Query", "Transaction").
655
666
  * @param options optional `message` override and pg `cause` to preserve, used
656
- * when wrapping a driver error rather than a client-side timer expiry.
667
+ * when wrapping a driver error rather than a client-side timer expiry, and
668
+ * the `outcome` (default `'unknown'`, the only answer that is never wrong).
657
669
  */
658
670
  constructor(timeoutMs, context = 'Query', options) {
659
671
  super(TurbineErrorCode.TIMEOUT, options?.message ?? `${context} timed out after ${timeoutMs}ms`, options);
660
672
  this.name = 'TimeoutError';
661
673
  this.timeoutMs = timeoutMs;
674
+ this.outcome = options?.outcome ?? 'unknown';
662
675
  }
663
676
  }
664
677
  /** Thrown when query arguments fail validation (unknown column, invalid operator, etc.) */
@@ -948,6 +961,74 @@ export class SerializationFailureError extends TurbineError {
948
961
  this.name = 'SerializationFailureError';
949
962
  }
950
963
  }
964
+ /** Marks a {@link LockNotAvailableError} across copies of this module (it shares E013 with its parent). */
965
+ const LOCK_NOT_AVAILABLE_BRAND = Symbol.for('turbine-orm.lockNotAvailable');
966
+ /**
967
+ * A row lock could not be taken. A locking read with `noWait` found a row
968
+ * locked by another transaction (PostgreSQL 55P03, MySQL 3572), or a lock wait
969
+ * outlasted the server's lock timeout (PostgreSQL 55P03 under `lock_timeout`,
970
+ * MySQL 1205, SQL Server 1222).
971
+ *
972
+ * A {@link SerializationFailureError}: same code (E013) and `isRetryable`, so
973
+ * code that already retries E013 retries this too. Retry after a backoff, or
974
+ * read with `skipLocked` to move on to the rows that are free.
975
+ *
976
+ * On PostgreSQL the failed statement aborts the transaction it ran in. To keep
977
+ * the outer transaction alive, take the lock in a nested `tx.$transaction(...)`
978
+ * (a savepoint) and catch the error outside it.
979
+ */
980
+ export class LockNotAvailableError extends SerializationFailureError {
981
+ constructor(opts = {}) {
982
+ const { cause } = opts;
983
+ let message = opts.message;
984
+ if (!message) {
985
+ const driverMessage = cause?.message;
986
+ message =
987
+ `Row lock not available${driverMessage ? `: ${driverMessage}` : ''}. Another transaction holds the lock. ` +
988
+ 'Retry after a backoff, or read with skipLocked to take only the rows that are free.';
989
+ }
990
+ super({ message, cause });
991
+ this.name = 'LockNotAvailableError';
992
+ Object.defineProperty(this, LOCK_NOT_AVAILABLE_BRAND, {
993
+ value: true,
994
+ enumerable: false,
995
+ writable: false,
996
+ configurable: false,
997
+ });
998
+ }
999
+ /**
1000
+ * `instanceof` across two copies of this module. The code alone cannot tell
1001
+ * this class from its parent (both E013), so another copy's instance must
1002
+ * also carry this class's own brand. A caller's subclass answers only for
1003
+ * its own instances, as {@link TurbineError[Symbol.hasInstance]} does.
1004
+ */
1005
+ static [Symbol.hasInstance](value) {
1006
+ // biome-ignore lint/complexity/noThisInStatic: the receiver may be a caller's subclass, see TurbineError
1007
+ // biome-ignore lint/complexity/noUselessThisAlias: one alias carries one suppression
1008
+ const cls = this;
1009
+ if (Function.prototype[Symbol.hasInstance].call(cls, value))
1010
+ return true;
1011
+ if (cls !== LockNotAvailableError)
1012
+ return false;
1013
+ return (SerializationFailureError[Symbol.hasInstance](value) &&
1014
+ value[LOCK_NOT_AVAILABLE_BRAND] === true);
1015
+ }
1016
+ }
1017
+ /**
1018
+ * A lock that could not be taken: PostgreSQL 55P03 (`NOWAIT`, or
1019
+ * `lock_timeout`), MySQL 3572 (`NOWAIT`) and 1205 (lock wait timeout), SQL
1020
+ * Server 1222 (lock request timeout). The MySQL and SQL Server shapes arrive
1021
+ * with `.code` already set to 40001 by their engine modules, so the driver's
1022
+ * own number decides.
1023
+ */
1024
+ function isLockNotAvailableError(err, code) {
1025
+ if (code === '55P03' || code === 'ER_LOCK_NOWAIT')
1026
+ return true;
1027
+ const e = err;
1028
+ if (e.errno === 3572)
1029
+ return true;
1030
+ return code === '40001' && (e.errno === 1205 || e.number === 1222);
1031
+ }
951
1032
  /** Thrown when a CHECK constraint is violated (pg code 23514) */
952
1033
  export class CheckConstraintError extends TurbineError {
953
1034
  static CODE = TurbineErrorCode.CHECK_VIOLATION;
@@ -1114,23 +1195,111 @@ export class ReadOnlyError extends TurbineError {
1114
1195
  * fail-fast flag), so NOTHING can write here and writes must route to the
1115
1196
  * primary. `'rbac'`: the database is writable but THIS connection's role may
1116
1197
  * not write (per-connection permission), so re-authenticating may suffice.
1198
+ * `'transaction'`: the transaction is read-only (`$transaction({ readOnly:
1199
+ * true })`, `BEGIN READ ONLY`, or a read replica, where every transaction
1200
+ * is), so the write belongs in a read-write transaction on the primary.
1117
1201
  */
1118
1202
  reason;
1119
1203
  /**
1120
1204
  * @param detail human-readable description of the refused write (the engine
1121
- * message, or a local fail-fast description). A "route writes to a writable
1122
- * primary" hint is always appended.
1205
+ * message, or a local fail-fast description). A hint naming where the
1206
+ * write belongs is always appended.
1123
1207
  * @param options optional driver `cause` to preserve when wrapping a refusal,
1124
1208
  * and the refusal `reason` (default `'snapshot'`).
1125
1209
  */
1126
1210
  constructor(detail, options) {
1127
- super(TurbineErrorCode.READ_ONLY, `${detail} Route writes to a writable primary.`, {
1211
+ const reason = options?.reason ?? 'snapshot';
1212
+ super(TurbineErrorCode.READ_ONLY, `${detail} ${READ_ONLY_HINTS[reason]}`, {
1128
1213
  cause: options?.cause,
1129
1214
  });
1130
1215
  this.name = 'ReadOnlyError';
1131
- this.reason = options?.reason ?? 'snapshot';
1216
+ this.reason = reason;
1132
1217
  }
1133
1218
  }
1219
+ const READ_ONLY_HINTS = {
1220
+ snapshot: 'Route writes to a writable primary.',
1221
+ rbac: 'Route writes to a writable primary.',
1222
+ transaction: 'Run the write in a read-write transaction (not `readOnly: true` or BEGIN READ ONLY) on the primary, ' +
1223
+ 'not a read replica.',
1224
+ };
1225
+ /**
1226
+ * Thrown when work the caller expected to be saved was rolled back instead:
1227
+ * a `$transaction` or `transaction()` whose COMMIT the server answered with
1228
+ * ROLLBACK, a transaction that cannot commit because a statement inside it was
1229
+ * cut short by its `timeout`, or a nested `tx.$transaction(...)` block that
1230
+ * could not be kept for the same reasons.
1231
+ *
1232
+ * PostgreSQL aborts a transaction at its first error. Catching that error
1233
+ * inside the callback does not undo the abort, so the callback returns, the
1234
+ * COMMIT ends as a ROLLBACK, and none of the transaction's writes are saved.
1235
+ * The first failure is attached as `cause`. Nothing was committed, so the
1236
+ * whole transaction can be run again once the cause is dealt with; to keep the
1237
+ * rest of the work after an expected failure, run the statement that can fail
1238
+ * in its own nested `tx.$transaction(...)`.
1239
+ *
1240
+ * NOT retryable on its own: the failure that caused it is not known to be
1241
+ * transient. When that first failure WAS a deadlock or a serialization
1242
+ * conflict, the retryable class (`DeadlockError`, `SerializationFailureError`)
1243
+ * is thrown instead, so `$retry` re-runs the transaction.
1244
+ */
1245
+ export class TransactionRolledBackError extends TurbineError {
1246
+ static CODE = TurbineErrorCode.TRANSACTION_ROLLED_BACK;
1247
+ /**
1248
+ * @param message what was rolled back and how to keep the work next time.
1249
+ * @param options the first failure inside the transaction, as `cause`.
1250
+ */
1251
+ constructor(message, options) {
1252
+ super(TurbineErrorCode.TRANSACTION_ROLLED_BACK, message, options);
1253
+ this.name = 'TransactionRolledBackError';
1254
+ }
1255
+ }
1256
+ /**
1257
+ * The sentence every {@link InvariantError} message ends with, before the docs
1258
+ * link. Exported so a test can assert it without restating it.
1259
+ */
1260
+ export const INVARIANT_REPORT_HINT = 'This is a bug in turbine-orm, not in your code. Please report it at ' +
1261
+ 'https://github.com/zvndev/turbine-orm/issues with this message.';
1262
+ /**
1263
+ * Turbine detected a bug in itself: a branch that no argument can reach was
1264
+ * reached, or two internal paths that must agree did not (the SQL-template
1265
+ * cache's build and param-collect paths, for example).
1266
+ *
1267
+ * Not caused by the arguments, so rewriting the call is not the fix, and not
1268
+ * retryable: the same call fails the same way. `invariant` is a stable id for
1269
+ * the broken rule (`'sql-cache-lockstep'`, `'sql-cache-param-count'`, ...), so
1270
+ * a report or an alert can group on it. The message names no row or parameter
1271
+ * value.
1272
+ *
1273
+ * Thrown in place of executing a statement Turbine knows is wrong, which is
1274
+ * what makes the checks behind it safe to run in production.
1275
+ */
1276
+ export class InvariantError extends TurbineError {
1277
+ static CODE = TurbineErrorCode.INVARIANT_VIOLATION;
1278
+ /** Stable id of the broken invariant, e.g. `'sql-cache-lockstep'`. */
1279
+ invariant;
1280
+ /**
1281
+ * @param invariant stable id of the broken rule.
1282
+ * @param message what disagreed, with no row or parameter value in it. The
1283
+ * report hint is appended once.
1284
+ * @param options the error that exposed the broken rule, as `cause`.
1285
+ */
1286
+ constructor(invariant, message, options) {
1287
+ const body = message.includes(INVARIANT_REPORT_HINT) ? message : `${message} ${INVARIANT_REPORT_HINT}`;
1288
+ super(TurbineErrorCode.INVARIANT_VIOLATION, body, options);
1289
+ this.name = 'InvariantError';
1290
+ this.invariant = invariant;
1291
+ }
1292
+ }
1293
+ /**
1294
+ * A write refused because its transaction is read-only: PostgreSQL SQLSTATE
1295
+ * 25006, or MySQL's error 1792 (which carries the same SQLSTATE).
1296
+ */
1297
+ function isReadOnlyTransactionError(err, code) {
1298
+ if (code === '25006' || code === 'ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION')
1299
+ return true;
1300
+ const e = err;
1301
+ return e.errno === 1792 && e.sqlState === '25006';
1302
+ }
1134
1303
  /**
1135
1304
  * Parse column names out of a pg `detail` string like:
1136
1305
  * "Key (email)=(foo@bar) already exists."
@@ -1162,6 +1331,11 @@ const CONNECTION_ERROR_CODES = new Set([
1162
1331
  '08006', // connection_failure
1163
1332
  '08007', // transaction_resolution_unknown
1164
1333
  '08P01', // protocol_violation
1334
+ // A named prepared statement met a server connection that did not prepare it
1335
+ // (26000) or already holds it (42P05). Turbine names its own statements, so
1336
+ // the usual cause is a transaction-pooling endpoint switching backends.
1337
+ '42P05', // duplicate_prepared_statement
1338
+ '26000', // invalid_sql_statement_name
1165
1339
  // pg SQLSTATE class 28: the server answered and REFUSED us. These are the
1166
1340
  // most common first-run failures there are (wrong password, a pg_hba rule
1167
1341
  // that does not cover this user/host), and they used to fall through
@@ -1181,6 +1355,11 @@ const CONNECTION_ERROR_CODES = new Set([
1181
1355
  '57P01', // admin_shutdown
1182
1356
  '57P02', // crash_shutdown
1183
1357
  '57P03', // cannot_connect_now
1358
+ // The server ended a session that sat idle inside an open transaction past
1359
+ // idle_in_transaction_session_timeout (a FATAL: the connection is gone).
1360
+ // A cursor stream sets that limit on its own transaction, see
1361
+ // query/stream-idle.ts, so this is how a frozen process's stream ends.
1362
+ '25P03', // idle_in_transaction_session_timeout
1184
1363
  // Node driver-level socket errors (surface on err.code too)
1185
1364
  'ECONNREFUSED',
1186
1365
  'ECONNRESET',
@@ -1220,6 +1399,11 @@ const PG_CONNECTION_LOSS_MESSAGES = new Set([
1220
1399
  'Connection terminated',
1221
1400
  'Connection terminated due to connection timeout',
1222
1401
  ]);
1402
+ /** pg-pool's own words for a checkout that waited longer than `connectionTimeoutMillis`. */
1403
+ const PG_POOL_CHECKOUT_TIMEOUT_MESSAGE = 'timeout exceeded when trying to connect';
1404
+ const POOL_CHECKOUT_TIMEOUT_HINT = "Timed out waiting for a free connection from the pool. Something is holding connections for longer than the pool's " +
1405
+ 'connection timeout: long transactions or streams, or a query on the outer client inside a `$transaction` ' +
1406
+ 'callback, which needs a second connection (use `tx` there). Raise the pool size if the load is genuine.';
1223
1407
  /** The follow-on errors pg raises for a query sent to a client already known to be dead. */
1224
1408
  const PG_NOT_QUERYABLE_MESSAGES = new Set([
1225
1409
  'Client has encountered a connection error and is not queryable',
@@ -1278,6 +1462,11 @@ export function isStaleConnectionError(err) {
1278
1462
  }
1279
1463
  const CONNECTION_LOSS_HINT = 'The server or the network closed it (a restart, failover, idle timeout, compute suspend, or ' +
1280
1464
  'pg_terminate_backend). The pool discards the connection, so retrying the operation opens a fresh one.';
1465
+ const PREPARED_STATEMENT_POOLER_HINT = 'A named prepared statement met a server connection that did not prepare it, or that already holds it. A ' +
1466
+ 'transaction-pooling endpoint (PgBouncer in transaction mode, a managed "-pooler" host, port 6432 or 6543) ' +
1467
+ 'gives each transaction to a different server connection, which is the usual cause. Connect to the direct ' +
1468
+ 'endpoint, set `preparedStatements: false`, or turn on prepared-statement support in the pooler (PgBouncer ' +
1469
+ '1.21 or later, `max_prepared_statements` above 0).';
1281
1470
  /**
1282
1471
  * Actionable next step per connection-class code, appended to the driver's own
1283
1472
  * message. The driver message states WHAT happened ("password authentication
@@ -1287,11 +1476,18 @@ const CONNECTION_LOSS_HINT = 'The server or the network closed it (a restart, fa
1287
1476
  * A code with no entry here simply gets no hint appended.
1288
1477
  */
1289
1478
  const CONNECTION_ERROR_HINTS = {
1479
+ '42P05': PREPARED_STATEMENT_POOLER_HINT,
1480
+ '26000': PREPARED_STATEMENT_POOLER_HINT,
1290
1481
  '28P01': 'The server rejected the credentials. Check the password in your connection string (or DATABASE_URL), including any URL-encoding of special characters.',
1291
1482
  '28000': "The server refused this user/host combination. Check the user name and the server's pg_hba.conf rules for the client address.",
1292
1483
  '3D000': 'The database named in the connection string does not exist. Check the path segment after the host, and create the database if needed.',
1293
1484
  '53300': "The server has no free connection slots. Lower `poolSize` or raise the server's max_connections.",
1294
1485
  '57P03': 'The server is still starting up (or shutting down) and is not accepting connections yet.',
1486
+ '25P03': 'The server ended the session because it sat idle inside an open transaction for longer than ' +
1487
+ '`idle_in_transaction_session_timeout`. A cursor stream sets that limit to its idle timeout plus 10 s, so for ' +
1488
+ 'a stream this means the process ran nothing for that long (a frozen serverless instance, a blocked event ' +
1489
+ 'loop); for a transaction, that the callback awaited something else for longer than the server allows. The ' +
1490
+ 'connection is discarded and the pool opens a fresh one.',
1295
1491
  ECONNREFUSED: 'Nothing is listening on that host and port. Check the server is running and the port is right.',
1296
1492
  ENOTFOUND: 'The host in the connection string could not be resolved. Check the host name, and that the connection string itself is well formed.',
1297
1493
  EAI_AGAIN: 'DNS lookup for the host failed temporarily. Check network/DNS availability, then retry.',
@@ -1523,9 +1719,13 @@ function scrubUnclassifiedServerError(err, code) {
1523
1719
  * 23P01 (exclusion_violation) -> ExclusionConstraintError
1524
1720
  * 40P01 (deadlock_detected) -> DeadlockError (retryable)
1525
1721
  * 40001 (serialization_failure) -> SerializationFailureError (retryable)
1722
+ * 55P03 (lock_not_available) -> LockNotAvailableError (retryable, E013); also
1723
+ * MySQL 3572 / 1205 and SQL Server 1222
1526
1724
  * 57014 (query_canceled) -> TimeoutError (server-side statement_timeout)
1527
1725
  * 28P01 / 28000 (auth refused) -> ConnectionError, with a remediation hint
1528
1726
  * 3D000 (no such database) -> ConnectionError, with a remediation hint
1727
+ * 42P05 / 26000 (prepared statement name clash or miss, a transaction-mode
1728
+ * pooler) -> ConnectionError, with a remediation hint
1529
1729
  * connection-class codes -> ConnectionError (see CONNECTION_ERROR_CODES)
1530
1730
  * 22xxx (data exception) -> ValidationError naming the column (when the
1531
1731
  * server did) and the SQLSTATE; driver text
@@ -1554,8 +1754,26 @@ export function wrapPgError(err) {
1554
1754
  if (err instanceof Error && PG_CONNECTION_LOSS_MESSAGES.has(err.message)) {
1555
1755
  return new ConnectionError(`Database connection lost: ${err.message}. ${CONNECTION_LOSS_HINT}`, { cause: err });
1556
1756
  }
1757
+ // pg-pool's checkout timeout carries no code either. A pool Turbine owns
1758
+ // types it at checkout (checkout.ts); this covers a caller's own pg.Pool.
1759
+ if (err instanceof Error && err.message === PG_POOL_CHECKOUT_TIMEOUT_MESSAGE) {
1760
+ return new ConnectionError(POOL_CHECKOUT_TIMEOUT_HINT, { cause: err });
1761
+ }
1557
1762
  return err;
1558
1763
  }
1764
+ if (isReadOnlyTransactionError(err, e.code)) {
1765
+ const pgMessage = typeof e.message === 'string' && e.message.length > 0 ? e.message : 'write refused';
1766
+ return new ReadOnlyError(`${pgMessage} (SQLSTATE 25006).`, { cause: err, reason: 'transaction' });
1767
+ }
1768
+ if (isLockNotAvailableError(err, e.code))
1769
+ return new LockNotAvailableError({ cause: err });
1770
+ // A protocol violation answered with ERROR rather than FATAL concerns one
1771
+ // message, and the connection stays usable. The common cause is a Buffer
1772
+ // bound to a column that is not bytea: node-postgres sends a Buffer as
1773
+ // binary data, which the server cannot read as an integer or a date.
1774
+ if (e.code === '08P01' && e.severity === 'ERROR') {
1775
+ return wrapValueBearingPgError(err, e, 'Invalid input', 'a bound value could not be read as the type the statement expects', ' A Buffer is sent as binary data and fits only a bytea column; pass a number, string or Date for any other type.');
1776
+ }
1559
1777
  switch (e.code) {
1560
1778
  case '23505': {
1561
1779
  const cols = e.detail ? parseColumnsFromDetail(e.detail) : undefined;
@@ -1600,13 +1818,27 @@ export function wrapPgError(err) {
1600
1818
  cause: err,
1601
1819
  });
1602
1820
  case '57014':
1603
- // query_canceled: a server-side statement_timeout cancelled the query.
1604
- // Turbine did not set the deadline (that lives in Postgres config), so
1605
- // there is no client-side budget to report → timeoutMs = 0.
1821
+ // query_canceled: the statement was stopped, so it made no change. A
1822
+ // cancel request (what Turbine sends when a query or transaction
1823
+ // `timeout` expires) reads "due to user request"; anything else is the
1824
+ // server's own statement_timeout.
1606
1825
  return new TimeoutError(0, 'Query', {
1607
- message: 'Query canceled by server-side statement_timeout',
1826
+ message: typeof e.message === 'string' && /user request/i.test(e.message)
1827
+ ? 'Query cancelled on the server by a cancel request, which Turbine sends when a query or ' +
1828
+ 'transaction `timeout` expires. It made no change.'
1829
+ : 'Query canceled by server-side statement_timeout',
1608
1830
  cause: err,
1831
+ outcome: 'not-executed',
1609
1832
  });
1833
+ case '25P02':
1834
+ // in_failed_sql_transaction: a statement sent after an earlier one failed. Turbine's own
1835
+ // transactions refuse it first, with the failure attached (transaction-state.ts); this is
1836
+ // the driver's answer on a path that sent it anyway (a connection used outside Turbine).
1837
+ return new TransactionRolledBackError('A statement was sent after an earlier statement in the same transaction failed. PostgreSQL ignores ' +
1838
+ 'every statement after a failure until the transaction, or the savepoint it ran in, is rolled back, ' +
1839
+ 'so nothing more can be saved in it. Catching the error does not undo the abort: let it leave the ' +
1840
+ 'transaction, or run the statement that can fail in its own nested `tx.$transaction(...)`, which ' +
1841
+ 'rolls back only that savepoint. The earlier failure is the error that statement threw.', { cause: err });
1610
1842
  default:
1611
1843
  if (CONNECTION_ERROR_CODES.has(e.code)) {
1612
1844
  const pgMessage = typeof e.message === 'string' && e.message.length > 0 ? e.message : undefined;
@@ -1629,6 +1861,14 @@ export function wrapPgError(err) {
1629
1861
  : DATA_EXCEPTION_FALLBACK;
1630
1862
  return wrapValueBearingPgError(err, e, subject, phrase);
1631
1863
  }
1864
+ // 42883: no operator or function for these argument types, e.g. a bigint
1865
+ // column compared with text. PostgreSQL's message names types, never
1866
+ // values, so it is kept in both modes.
1867
+ if (e.code === '42883') {
1868
+ const pgMessage = typeof e.message === 'string' && e.message.length > 0 ? `${e.message} ` : '';
1869
+ return new ValidationError(`${pgMessage}(SQLSTATE 42883). A value of one type was compared with or passed to something that takes ` +
1870
+ "another, usually a value bound to a column of a different type. Pass a value of the column's type.", { cause: err, sqlstate: e.code });
1871
+ }
1632
1872
  // 42601 is any syntax error. Only the to_tsquery parse failure is a
1633
1873
  // caller-input problem Turbine can name (the `search` operator), so the
1634
1874
  // message text is the discriminator; every other 42601 takes the generic
@@ -8,10 +8,36 @@
8
8
  *
9
9
  * Output goes to the specified directory (default: ./generated/turbine/).
10
10
  */
11
- import { type PrismaCompatMap, type SchemaMetadata } from './schema.js';
11
+ import { type TurbineLogger } from './logger.js';
12
+ import { type ColumnMetadata, type PrismaCompatMap, type SchemaMetadata } from './schema.js';
13
+ /**
14
+ * Per-column TypeScript overrides from {@link GenerateOptions.columnTypes},
15
+ * keyed by database table name, then database column name.
16
+ */
17
+ type ColumnTypeOverrides = ReadonlyMap<string, ReadonlyMap<string, string>>;
18
+ /**
19
+ * Resolve the TypeScript type for a column, mapping enum-typed columns to their
20
+ * generated string-literal union (PascalCase enum name) instead of the
21
+ * `unknown` that {@link pgTypeToTs} yields for user-defined types. A
22
+ * `columnTypes` override replaces the type outright (nullability is still
23
+ * added). Falls back to the introspected `col.tsType` for everything else.
24
+ */
25
+ export declare function columnTsType(col: ColumnMetadata, enums: Record<string, string[]>, override?: string): string;
26
+ /**
27
+ * Validate {@link GenerateOptions.columnTypes} against the schema and index it.
28
+ * A key naming no table or column is a `ValidationError`, not a silent no-op,
29
+ * since an override that applies to nothing leaves the column typed `unknown`.
30
+ */
31
+ export declare function resolveColumnTypeOverrides(schema: SchemaMetadata, columnTypes: Readonly<Record<string, string>> | undefined): ColumnTypeOverrides | undefined;
12
32
  export interface GenerateOptions {
13
33
  /** The introspected schema to generate from */
14
34
  schema: SchemaMetadata;
35
+ /**
36
+ * Where generation notes go (a relation omitted from the generated types
37
+ * because it shadows a column). Defaults to the console logger. Never
38
+ * affects the generated files.
39
+ */
40
+ logger?: TurbineLogger;
15
41
  /** Output directory (default: './generated/turbine') */
16
42
  outDir?: string;
17
43
  /** Redact connection string from generated comments */
@@ -36,6 +62,10 @@ export interface GenerateOptions {
36
62
  *
37
63
  * - `'js'`: always `./types.js` (required by NodeNext `tsc` and by
38
64
  * tsc-compiled ESM run on Node; the pre-0.41 behavior).
65
+ * - `'ts'`: always `./types.ts`, so Node's native type stripping can run the
66
+ * generated files directly (`node app.ts`). A type checker needs
67
+ * `allowImportingTsExtensions` or `rewriteRelativeImportExtensions` to
68
+ * accept it. `'auto'` never picks this.
39
69
  * - `'none'`: always `./types` (correct for bundlers / `moduleResolution
40
70
  * bundler | node10`: webpack, Next.js/SWC, Vite/esbuild).
41
71
  * - `'auto'` (default): walk up from `outDir` to the nearest `tsconfig.json`
@@ -44,7 +74,7 @@ export interface GenerateOptions {
44
74
  * neither is, and fall back to `'.js'` when the tsconfig is missing,
45
75
  * unparseable, or ambiguous (so NodeNext consumers can never regress).
46
76
  */
47
- importExtension?: 'js' | 'none' | 'auto';
77
+ importExtension?: 'js' | 'ts' | 'none' | 'auto';
48
78
  /**
49
79
  * Rewrite generated column FIELD names to the raw database column names
50
80
  * (snake_case) instead of camelCase (F4). Opt-in; when unset the output is
@@ -54,18 +84,36 @@ export interface GenerateOptions {
54
84
  * names are unaffected.
55
85
  */
56
86
  keepColumnNames?: boolean;
87
+ /**
88
+ * TypeScript types for specific columns, keyed `"<table>.<column>"` with
89
+ * database names. The value is emitted as written into the row type and the
90
+ * `*Create` / `*Update` input types (`| null` is added for a nullable
91
+ * column), so a json/jsonb column can carry its real shape instead of
92
+ * `unknown`:
93
+ *
94
+ * columnTypes: { 'users.settings': "import('../src/settings.js').Settings" }
95
+ *
96
+ * A relative `import()` resolves from the output directory. The type is a
97
+ * compile-time claim: nothing checks stored values against it. A key naming
98
+ * no table or column is an error.
99
+ */
100
+ columnTypes?: Readonly<Record<string, string>>;
57
101
  }
58
102
  /** Per-file generator options (subset of {@link GenerateOptions} the emitters need). */
59
103
  export interface GenerateFileOptions {
60
104
  /** Omit the `Generated at:` header line for reproducible output. */
61
105
  noTimestamp?: boolean;
62
106
  /**
63
- * Resolved sibling-import extension for `generateIndex` (`'.js'` or `''`).
107
+ * Resolved sibling-import extension for `generateIndex` (`'.js'`, `'.ts'` or `''`).
64
108
  * Defaults to `'.js'` when unset so direct callers stay byte-stable.
65
109
  */
66
110
  importExt?: string;
67
111
  /** Human-readable resolved import mode, recorded as a comment in `index.ts`. */
68
112
  importMode?: string;
113
+ /** {@link GenerateOptions.columnTypes}; validated against the schema by the emitter. */
114
+ columnTypes?: Readonly<Record<string, string>>;
115
+ /** {@link GenerateOptions.logger}. */
116
+ logger?: TurbineLogger;
69
117
  }
70
118
  export declare function generate(options: GenerateOptions): {
71
119
  outDir: string;
@@ -77,12 +125,13 @@ export declare function generate(options: GenerateOptions): {
77
125
  * mode label for the generated comment.
78
126
  *
79
127
  * - `'js'` → `.js`
128
+ * - `'ts'` → `.ts`
80
129
  * - `'none'` → `''`
81
130
  * - `'auto'` → tsconfig-driven ({@link detectTsconfigExtension}); falls back
82
131
  * to `.js` (the pre-0.41 default) when detection is uncertain, so NodeNext
83
132
  * consumers can never regress.
84
133
  */
85
- export declare function resolveImportExtension(outDir: string, requested: 'js' | 'none' | 'auto'): {
134
+ export declare function resolveImportExtension(outDir: string, requested: 'js' | 'ts' | 'none' | 'auto'): {
86
135
  ext: string;
87
136
  mode: string;
88
137
  };
@@ -137,10 +186,10 @@ export declare function isEmittableIdentifier(name: string): boolean;
137
186
  export declare function assertEmittableSchema(schema: SchemaMetadata): void;
138
187
  /**
139
188
  * Generate the contents of `types.ts` (entity interfaces, *Create / *Update,
140
- * and *Relations brand-field interfaces). Exported so tests can pin the
141
- * generator output without writing files to disk.
189
+ * *Relations brand-field interfaces, and the write input types). Exported so
190
+ * tests can pin the generator output without writing files to disk.
142
191
  */
143
- export declare function generateTypes(schema: SchemaMetadata, options?: GenerateFileOptions): string;
192
+ export declare function generateTypes(input: SchemaMetadata, options?: GenerateFileOptions): string;
144
193
  /**
145
194
  * Generate the contents of `zod.ts`. Emits, per table, `XSchema` (the full
146
195
  * row), `XCreateSchema` (PK/defaulted/nullable columns optional, STORED
@@ -161,3 +210,4 @@ export declare function generateIndex(schema: SchemaMetadata, options?: Generate
161
210
  * stable input regenerates byte-identical output under `noTimestamp`.
162
211
  */
163
212
  export declare function generatePrismaMap(map: PrismaCompatMap, options?: GenerateFileOptions): string;
213
+ export {};