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
@@ -6,47 +6,107 @@
6
6
  * PostgreSQL-native by default, but query generation now depends on this
7
7
  * contract for the SQL primitives that vary across MySQL and SQLite.
8
8
  */
9
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- var desc = Object.getOwnPropertyDescriptor(m, k);
12
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
- desc = { enumerable: true, get: function() { return m[k]; } };
14
- }
15
- Object.defineProperty(o, k2, desc);
16
- }) : (function(o, m, k, k2) {
17
- if (k2 === undefined) k2 = k;
18
- o[k2] = m[k];
19
- }));
20
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
- Object.defineProperty(o, "default", { enumerable: true, value: v });
22
- }) : function(o, v) {
23
- o["default"] = v;
24
- });
25
- var __importStar = (this && this.__importStar) || (function () {
26
- var ownKeys = function(o) {
27
- ownKeys = Object.getOwnPropertyNames || function (o) {
28
- var ar = [];
29
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
- return ar;
31
- };
32
- return ownKeys(o);
33
- };
34
- return function (mod) {
35
- if (mod && mod.__esModule) return mod;
36
- var result = {};
37
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
- __setModuleDefault(result, mod);
39
- return result;
40
- };
41
- })();
42
9
  Object.defineProperty(exports, "__esModule", { value: true });
43
10
  exports.postgresDialect = void 0;
11
+ exports.maxBindParameters = maxBindParameters;
12
+ exports.onConflictAction = onConflictAction;
44
13
  const errors_js_1 = require("./errors.js");
45
14
  const utils_js_1 = require("./query/utils.js");
46
15
  const schema_js_1 = require("./schema.js");
16
+ /** The bind-parameter limit for one statement on this dialect, or `undefined` when it has none. */
17
+ function maxBindParameters(dialect) {
18
+ const limit = dialect.capabilities.maxBindParameters;
19
+ return Number.isFinite(limit) ? limit : undefined;
20
+ }
21
+ /**
22
+ * PostgreSQL's multi-row `INSERT INTO t (cols) ...` with no conflict clause and
23
+ * no RETURNING: the shared body of `createMany` and its `onConflict` form.
24
+ *
25
+ * The default is `SELECT * FROM UNNEST($1::text[], ...)`, one bound array per
26
+ * COLUMN. The row-major form (`requireRowValues`) is required when a target
27
+ * column is itself array-typed, because the UNNEST transpose flattens nested
28
+ * arrays: one placeholder per cell instead of per column.
29
+ */
30
+ function pgBulkInsertBody(dialect, input) {
31
+ if (!input.columnArrayTypes || input.columnArrayTypes.length !== input.columns.length) {
32
+ throw new errors_js_1.ValidationError(`createMany bulk insert into "${input.table}": columnArrayTypes must supply one UNNEST cast ` +
33
+ `per column, got ${input.columnArrayTypes?.length ?? 0} for ${input.columns.length} columns ` +
34
+ `(${input.columns.join(', ')}). Schema metadata is missing a pgType for at least one column; ` +
35
+ 'regenerate it with `npx turbine generate`.');
36
+ }
37
+ if (input.requireRowValues) {
38
+ const params = [];
39
+ const tuples = input.rowValues.map((row) => {
40
+ const cells = input.columns.map((_, i) => {
41
+ params.push(row[i]);
42
+ // No cast: PostgreSQL infers each parameter's type from the INSERT
43
+ // target column, which is what single-row `create` already relies on
44
+ // and is what makes arrays and enums both work here. The casts in
45
+ // `columnArrayTypes` are ARRAY-OF-column-type, correct for the
46
+ // UNNEST transpose but wrong for an individual cell.
47
+ return dialect.paramPlaceholder(params.length);
48
+ });
49
+ return `(${cells.join(', ')})`;
50
+ });
51
+ return { sql: `INSERT INTO ${input.table} (${input.columns.join(', ')}) VALUES ${tuples.join(', ')}`, params };
52
+ }
53
+ const columnArrays = input.columns.map((_, columnIndex) => input.rowValues.map((row) => row[columnIndex]));
54
+ const unnestArgs = input.columns.map((_, i) => `${dialect.paramPlaceholder(i + 1)}::${input.columnArrayTypes[i]}`);
55
+ return {
56
+ sql: `INSERT INTO ${input.table} (${input.columns.join(', ')}) SELECT * FROM UNNEST(${unnestArgs.join(', ')})`,
57
+ params: columnArrays,
58
+ };
59
+ }
60
+ /**
61
+ * `DO NOTHING`, or `DO UPDATE SET ... [WHERE ...]`: the action of an
62
+ * `ON CONFLICT (target)` clause, shared by PostgreSQL and SQLite, whose
63
+ * grammars agree here. The update compiles after the row values are bound.
64
+ */
65
+ function onConflictAction(input, params, refs) {
66
+ if (!input.update)
67
+ return 'DO NOTHING';
68
+ const update = input.update(params, refs);
69
+ return `DO UPDATE SET ${update.setClauses.join(', ')}${update.where ? ` WHERE ${update.where}` : ''}`;
70
+ }
47
71
  /** PostgreSQL implementation of the dialect contract. */
48
72
  exports.postgresDialect = {
49
73
  name: 'postgresql',
74
+ capabilities: Object.freeze({
75
+ distinctOn: true,
76
+ positionalJson: true,
77
+ nullsOrderingClause: true,
78
+ nullsSortHigh: true,
79
+ insensitiveInList: true,
80
+ jsonDocumentEquality: 'jsonb',
81
+ jsonExtractTyped: false,
82
+ jsonExactNumericCast: true,
83
+ numericTextComparison: false,
84
+ enforcesForeignKeys: true,
85
+ partitionLimitPushdown: true,
86
+ utcTimestampRewrite: true,
87
+ paramTypeCasts: true,
88
+ namedEnumTypes: true,
89
+ structuredValueColumns: 'pg-scalars',
90
+ // Counted in a 16-bit field.
91
+ maxBindParameters: 65535,
92
+ maxInsertRows: Number.POSITIVE_INFINITY,
93
+ upsertConflictTarget: 'explicit',
94
+ setClauseOrder: 'snapshot',
95
+ reselectLocksRows: false,
96
+ integerDivision: '/',
97
+ updateExpressions: true,
98
+ bulkUpsertAppliesRepeatedKeys: false,
99
+ readOnlyTransactions: true,
100
+ connectionParameters: true,
101
+ backendCancel: true,
102
+ idleTransactionTimeout: true,
103
+ abortsTransactionOnError: true,
104
+ connectionDriver: 'pg-compatible',
105
+ preparesEveryStatement: false,
106
+ statementSyntax: 'postgresql',
107
+ inlineForeignKeys: true,
108
+ unboundedTextKeys: true,
109
+ }),
50
110
  resultStrategy: 'returning',
51
111
  supportsReturning: true,
52
112
  supportsUpsertUpdateWhere: true,
@@ -64,6 +124,9 @@ exports.postgresDialect = {
64
124
  supportsAdvisoryLock: true,
65
125
  supportsPlanCacheMode: true,
66
126
  supportsLateralJoin: true,
127
+ rowLockModes: ['update', 'noKeyUpdate', 'share', 'keyShare'],
128
+ supportsPercentileAggregates: true,
129
+ supportsBulkUpsert: true,
67
130
  explainQuery: { prefix: 'EXPLAIN' },
68
131
  paramPlaceholder(index) {
69
132
  return `$${index}`;
@@ -116,40 +179,21 @@ exports.postgresDialect = {
116
179
  return `INSERT INTO ${input.table} (${input.columns.join(', ')}) VALUES (${input.valuePlaceholders.join(', ')})${this.buildReturningClause(input.returning)}`;
117
180
  },
118
181
  buildBulkInsertStatement(input) {
119
- if (!input.columnArrayTypes || input.columnArrayTypes.length !== input.columns.length) {
120
- throw new errors_js_1.ValidationError(`createMany bulk insert into "${input.table}": columnArrayTypes must supply one UNNEST cast ` +
121
- `per column, got ${input.columnArrayTypes?.length ?? 0} for ${input.columns.length} columns ` +
122
- `(${input.columns.join(', ')}). Schema metadata is missing a pgType for at least one column; ` +
123
- 'regenerate it with `npx turbine generate`.');
124
- }
125
- // Row-major form: required when a target column is itself array-typed,
126
- // because the UNNEST transpose below flattens nested arrays (see
127
- // `requireRowValues`). One placeholder per cell instead of per column.
128
- if (input.requireRowValues) {
129
- const params = [];
130
- const tuples = input.rowValues.map((row) => {
131
- const cells = input.columns.map((_, i) => {
132
- params.push(row[i]);
133
- // No cast: PostgreSQL infers each parameter's type from the INSERT
134
- // target column, which is what single-row `create` already relies on
135
- // and is what makes arrays and enums both work here. The casts in
136
- // `columnArrayTypes` are ARRAY-OF-column-type, correct for the
137
- // UNNEST transpose below but wrong for an individual cell.
138
- return this.paramPlaceholder(params.length);
139
- });
140
- return `(${cells.join(', ')})`;
141
- });
142
- let rowSql = `INSERT INTO ${input.table} (${input.columns.join(', ')}) VALUES ${tuples.join(', ')}`;
143
- if (input.skipDuplicates)
144
- rowSql += ' ON CONFLICT DO NOTHING';
145
- return { sql: `${rowSql}${this.buildReturningClause(input.returning)}`, params };
146
- }
147
- const columnArrays = input.columns.map((_, columnIndex) => input.rowValues.map((row) => row[columnIndex]));
148
- const unnestArgs = input.columns.map((_, i) => `${this.paramPlaceholder(i + 1)}::${input.columnArrayTypes[i]}`);
149
- let sql = `INSERT INTO ${input.table} (${input.columns.join(', ')}) SELECT * FROM UNNEST(${unnestArgs.join(', ')})`;
150
- if (input.skipDuplicates)
151
- sql += ' ON CONFLICT DO NOTHING';
152
- return { sql: `${sql}${this.buildReturningClause(input.returning)}`, params: columnArrays };
182
+ const body = pgBulkInsertBody(this, input);
183
+ const conflict = input.skipDuplicates ? ' ON CONFLICT DO NOTHING' : '';
184
+ return { sql: `${body.sql}${conflict}${this.buildReturningClause(input.returning)}`, params: body.params };
185
+ },
186
+ buildBulkUpsertStatement(input) {
187
+ // `INSERT ... SELECT * FROM UNNEST(...) ON CONFLICT ... DO UPDATE ... WHERE
188
+ // ... RETURNING` is valid as is: PostgreSQL has no parse ambiguity between
189
+ // the SELECT and the conflict clause.
190
+ const body = pgBulkInsertBody(this, input);
191
+ return {
192
+ sql: `${body.sql} ON CONFLICT (${input.conflictColumns.join(', ')}) ` +
193
+ onConflictAction(input, body.params, { target: input.table, incoming: 'EXCLUDED' }) +
194
+ this.buildReturningClause(input.returning),
195
+ params: body.params,
196
+ };
153
197
  },
154
198
  buildDefaultValuesInsertStatement(input) {
155
199
  const conflict = input.skipDuplicates ? ' ON CONFLICT DO NOTHING' : '';
@@ -382,13 +426,10 @@ exports.postgresDialect = {
382
426
  }
383
427
  }
384
428
  },
385
- // Postgres introspection wraps the information_schema / pg_catalog reader in
386
- // introspect.ts. A dynamic import keeps the static graph acyclic (introspect.ts
387
- // imports postgresDialect) and calls the raw catalog reader (never the router).
388
- introspector: {
389
- async introspect(options) {
390
- const { introspectPostgresCatalog } = await Promise.resolve().then(() => __importStar(require('./introspect.js')));
391
- return introspectPostgresCatalog(options);
392
- },
393
- },
429
+ // No `introspector`: `introspect()` reads the PostgreSQL catalog itself when a
430
+ // dialect has none. A field here would have to reach introspect.ts through a
431
+ // dynamic import (introspect.ts imports this dialect), and a bundler without
432
+ // code splitting inlines that import WHOLE, which put the entire catalog
433
+ // reader into the serverless entry and every engine entry (4 to 6 kB brotli
434
+ // each) for a function none of them call at runtime.
394
435
  };
@@ -26,20 +26,21 @@ import type { TurbineConfig } from './client.js';
26
26
  * the engine from its own SQL.
27
27
  * - `connectionString`, `host`, `port`, `database`, `user`, `password`, `ssl`,
28
28
  * `poolSize`, `idleTimeoutMs`, `connectionTimeoutMs`, `max`,
29
- * `idleTimeoutMillis`, `connectionTimeoutMillis`: pg connection and
30
- * pool-tuning fields, ignored by `TurbineClient` whenever `pool` is set (it
31
- * always is here). Each engine takes its connection target as its first
32
- * argument instead, in that driver's own vocabulary.
29
+ * `idleTimeoutMillis`, `connectionTimeoutMillis`, `maxLifetimeSeconds`: pg
30
+ * connection and pool-tuning fields, ignored by `TurbineClient` whenever
31
+ * `pool` is set (it always is here). Each engine takes its connection
32
+ * target as its first argument instead, in that driver's own vocabulary.
33
33
  * - `replicas`: entries are Postgres connection strings or pg-compatible
34
34
  * pools, which `TurbineClient` opens as `pg.Pool`s. There is no engine
35
35
  * equivalent to route reads to.
36
36
  *
37
37
  * Everything else is forwarded, including options that are Postgres-only by
38
- * CAPABILITY rather than by plumbing (`jsonEncoding: 'positional'`). Those throw
38
+ * CAPABILITY rather than by plumbing (`jsonEncoding: 'positional'`,
39
+ * `statementTimeoutMs`, `planCacheMode`). Those throw
39
40
  * a typed `UnsupportedFeatureError` (E017) when used, which is a better answer
40
41
  * than an option the type system says does not exist.
41
42
  */
42
- type EngineOwnedConfigKey = 'pool' | 'dialect' | 'preparedStatements' | 'connectionString' | 'host' | 'port' | 'database' | 'user' | 'password' | 'ssl' | 'poolSize' | 'idleTimeoutMs' | 'connectionTimeoutMs' | 'max' | 'idleTimeoutMillis' | 'connectionTimeoutMillis' | 'replicas';
43
+ type EngineOwnedConfigKey = 'pool' | 'dialect' | 'preparedStatements' | 'connectionString' | 'host' | 'port' | 'database' | 'user' | 'password' | 'ssl' | 'poolSize' | 'idleTimeoutMs' | 'connectionTimeoutMs' | 'max' | 'idleTimeoutMillis' | 'connectionTimeoutMillis' | 'maxLifetimeSeconds' | 'replicas';
43
44
  /**
44
45
  * The client-level options every engine factory accepts and forwards to
45
46
  * `TurbineClient` unchanged: all of {@link TurbineConfig} minus the connection
@@ -24,6 +24,8 @@ export declare const TurbineErrorCode: {
24
24
  readonly EXCLUSION_VIOLATION: "TURBINE_E016";
25
25
  readonly UNSUPPORTED_FEATURE: "TURBINE_E017";
26
26
  readonly READ_ONLY: "TURBINE_E018";
27
+ readonly TRANSACTION_ROLLED_BACK: "TURBINE_E019";
28
+ readonly INVARIANT_VIOLATION: "TURBINE_E020";
27
29
  };
28
30
  export type TurbineErrorCode = (typeof TurbineErrorCode)[keyof typeof TurbineErrorCode];
29
31
  /** Base error class for all Turbine errors */
@@ -198,7 +200,10 @@ export declare function describeTargetForMessage(target: unknown): string;
198
200
  * `[TURBINE_E001] findUniqueOrThrow on "users" found no record matching where: {"id":1}`
199
201
  *
200
202
  * The full `where` object, `table`, and `operation` are always available as
201
- * structured properties on the error instance regardless of mode.
203
+ * structured properties on the error instance regardless of mode. `where`
204
+ * carries the caller's raw values, so under 'safe' it is NON-ENUMERABLE:
205
+ * `err.where` reads it, while `JSON.stringify`, `util.inspect` and error
206
+ * serializers that copy own enumerable fields leave it out.
202
207
  */
203
208
  export declare class NotFoundError extends TurbineError {
204
209
  static readonly CODE: "TURBINE_E001";
@@ -213,21 +218,37 @@ export declare class NotFoundError extends TurbineError {
213
218
  message?: string;
214
219
  });
215
220
  }
221
+ /**
222
+ * What a {@link TimeoutError} says about the statement it interrupted.
223
+ *
224
+ * - `'not-executed'`: the statement made no change. It was never sent (the
225
+ * deadline passed while waiting for a connection), or the server confirmed
226
+ * it was cancelled. Safe to retry.
227
+ * - `'unknown'`: the statement may still have completed. A write retried on
228
+ * this outcome can be applied twice; check the database first.
229
+ *
230
+ * A read changes nothing whatever this says, so a read is always safe to retry.
231
+ */
232
+ export type TimeoutOutcome = 'not-executed' | 'unknown';
216
233
  /** Thrown when a query or transaction exceeds the configured timeout */
217
234
  export declare class TimeoutError extends TurbineError {
218
235
  static readonly CODE: "TURBINE_E002";
219
236
  readonly timeoutMs: number;
237
+ /** Whether the interrupted statement can have taken effect. See {@link TimeoutOutcome}. */
238
+ readonly outcome: TimeoutOutcome;
220
239
  /**
221
240
  * @param timeoutMs the client-side timeout budget in ms. Pass `0` when the
222
241
  * duration is unknown (e.g. a server-side `statement_timeout` cancellation
223
242
  * surfaced via `wrapPgError`, where Turbine did not set the deadline).
224
243
  * @param context human label for the operation ("Query", "Transaction").
225
244
  * @param options optional `message` override and pg `cause` to preserve, used
226
- * when wrapping a driver error rather than a client-side timer expiry.
245
+ * when wrapping a driver error rather than a client-side timer expiry, and
246
+ * the `outcome` (default `'unknown'`, the only answer that is never wrong).
227
247
  */
228
248
  constructor(timeoutMs: number, context?: string, options?: {
229
249
  message?: string;
230
250
  cause?: unknown;
251
+ outcome?: TimeoutOutcome;
231
252
  });
232
253
  }
233
254
  /** Thrown when query arguments fail validation (unknown column, invalid operator, etc.) */
@@ -421,6 +442,33 @@ export declare class SerializationFailureError extends TurbineError {
421
442
  cause?: unknown;
422
443
  });
423
444
  }
445
+ /**
446
+ * A row lock could not be taken. A locking read with `noWait` found a row
447
+ * locked by another transaction (PostgreSQL 55P03, MySQL 3572), or a lock wait
448
+ * outlasted the server's lock timeout (PostgreSQL 55P03 under `lock_timeout`,
449
+ * MySQL 1205, SQL Server 1222).
450
+ *
451
+ * A {@link SerializationFailureError}: same code (E013) and `isRetryable`, so
452
+ * code that already retries E013 retries this too. Retry after a backoff, or
453
+ * read with `skipLocked` to move on to the rows that are free.
454
+ *
455
+ * On PostgreSQL the failed statement aborts the transaction it ran in. To keep
456
+ * the outer transaction alive, take the lock in a nested `tx.$transaction(...)`
457
+ * (a savepoint) and catch the error outside it.
458
+ */
459
+ export declare class LockNotAvailableError extends SerializationFailureError {
460
+ constructor(opts?: {
461
+ message?: string;
462
+ cause?: unknown;
463
+ });
464
+ /**
465
+ * `instanceof` across two copies of this module. The code alone cannot tell
466
+ * this class from its parent (both E013), so another copy's instance must
467
+ * also carry this class's own brand. A caller's subclass answers only for
468
+ * its own instances, as {@link TurbineError[Symbol.hasInstance]} does.
469
+ */
470
+ static [Symbol.hasInstance](value: unknown): boolean;
471
+ }
424
472
  /** Thrown when a CHECK constraint is violated (pg code 23514) */
425
473
  export declare class CheckConstraintError extends TurbineError {
426
474
  static readonly CODE: "TURBINE_E011";
@@ -542,18 +590,86 @@ export declare class ReadOnlyError extends TurbineError {
542
590
  * fail-fast flag), so NOTHING can write here and writes must route to the
543
591
  * primary. `'rbac'`: the database is writable but THIS connection's role may
544
592
  * not write (per-connection permission), so re-authenticating may suffice.
593
+ * `'transaction'`: the transaction is read-only (`$transaction({ readOnly:
594
+ * true })`, `BEGIN READ ONLY`, or a read replica, where every transaction
595
+ * is), so the write belongs in a read-write transaction on the primary.
545
596
  */
546
- readonly reason: 'snapshot' | 'rbac';
597
+ readonly reason: ReadOnlyReason;
547
598
  /**
548
599
  * @param detail human-readable description of the refused write (the engine
549
- * message, or a local fail-fast description). A "route writes to a writable
550
- * primary" hint is always appended.
600
+ * message, or a local fail-fast description). A hint naming where the
601
+ * write belongs is always appended.
551
602
  * @param options optional driver `cause` to preserve when wrapping a refusal,
552
603
  * and the refusal `reason` (default `'snapshot'`).
553
604
  */
554
605
  constructor(detail: string, options?: {
555
606
  cause?: unknown;
556
- reason?: 'snapshot' | 'rbac';
607
+ reason?: ReadOnlyReason;
608
+ });
609
+ }
610
+ /** Why a {@link ReadOnlyError} write was refused. */
611
+ export type ReadOnlyReason = 'snapshot' | 'rbac' | 'transaction';
612
+ /**
613
+ * Thrown when work the caller expected to be saved was rolled back instead:
614
+ * a `$transaction` or `transaction()` whose COMMIT the server answered with
615
+ * ROLLBACK, a transaction that cannot commit because a statement inside it was
616
+ * cut short by its `timeout`, or a nested `tx.$transaction(...)` block that
617
+ * could not be kept for the same reasons.
618
+ *
619
+ * PostgreSQL aborts a transaction at its first error. Catching that error
620
+ * inside the callback does not undo the abort, so the callback returns, the
621
+ * COMMIT ends as a ROLLBACK, and none of the transaction's writes are saved.
622
+ * The first failure is attached as `cause`. Nothing was committed, so the
623
+ * whole transaction can be run again once the cause is dealt with; to keep the
624
+ * rest of the work after an expected failure, run the statement that can fail
625
+ * in its own nested `tx.$transaction(...)`.
626
+ *
627
+ * NOT retryable on its own: the failure that caused it is not known to be
628
+ * transient. When that first failure WAS a deadlock or a serialization
629
+ * conflict, the retryable class (`DeadlockError`, `SerializationFailureError`)
630
+ * is thrown instead, so `$retry` re-runs the transaction.
631
+ */
632
+ export declare class TransactionRolledBackError extends TurbineError {
633
+ static readonly CODE: "TURBINE_E019";
634
+ /**
635
+ * @param message what was rolled back and how to keep the work next time.
636
+ * @param options the first failure inside the transaction, as `cause`.
637
+ */
638
+ constructor(message: string, options?: {
639
+ cause?: unknown;
640
+ });
641
+ }
642
+ /**
643
+ * The sentence every {@link InvariantError} message ends with, before the docs
644
+ * link. Exported so a test can assert it without restating it.
645
+ */
646
+ export declare const INVARIANT_REPORT_HINT: string;
647
+ /**
648
+ * Turbine detected a bug in itself: a branch that no argument can reach was
649
+ * reached, or two internal paths that must agree did not (the SQL-template
650
+ * cache's build and param-collect paths, for example).
651
+ *
652
+ * Not caused by the arguments, so rewriting the call is not the fix, and not
653
+ * retryable: the same call fails the same way. `invariant` is a stable id for
654
+ * the broken rule (`'sql-cache-lockstep'`, `'sql-cache-param-count'`, ...), so
655
+ * a report or an alert can group on it. The message names no row or parameter
656
+ * value.
657
+ *
658
+ * Thrown in place of executing a statement Turbine knows is wrong, which is
659
+ * what makes the checks behind it safe to run in production.
660
+ */
661
+ export declare class InvariantError extends TurbineError {
662
+ static readonly CODE: "TURBINE_E020";
663
+ /** Stable id of the broken invariant, e.g. `'sql-cache-lockstep'`. */
664
+ readonly invariant: string;
665
+ /**
666
+ * @param invariant stable id of the broken rule.
667
+ * @param message what disagreed, with no row or parameter value in it. The
668
+ * report hint is appended once.
669
+ * @param options the error that exposed the broken rule, as `cause`.
670
+ */
671
+ constructor(invariant: string, message: string, options?: {
672
+ cause?: unknown;
557
673
  });
558
674
  }
559
675
  /**
@@ -593,9 +709,13 @@ export declare function isStaleConnectionError(err: unknown): boolean;
593
709
  * 23P01 (exclusion_violation) -> ExclusionConstraintError
594
710
  * 40P01 (deadlock_detected) -> DeadlockError (retryable)
595
711
  * 40001 (serialization_failure) -> SerializationFailureError (retryable)
712
+ * 55P03 (lock_not_available) -> LockNotAvailableError (retryable, E013); also
713
+ * MySQL 3572 / 1205 and SQL Server 1222
596
714
  * 57014 (query_canceled) -> TimeoutError (server-side statement_timeout)
597
715
  * 28P01 / 28000 (auth refused) -> ConnectionError, with a remediation hint
598
716
  * 3D000 (no such database) -> ConnectionError, with a remediation hint
717
+ * 42P05 / 26000 (prepared statement name clash or miss, a transaction-mode
718
+ * pooler) -> ConnectionError, with a remediation hint
599
719
  * connection-class codes -> ConnectionError (see CONNECTION_ERROR_CODES)
600
720
  * 22xxx (data exception) -> ValidationError naming the column (when the
601
721
  * server did) and the SQLSTATE; driver text