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
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ /**
3
+ * turbine-orm: the `lock` read option (`SELECT ... FOR UPDATE OF "t"`).
4
+ *
5
+ * {@link resolveRowLock} is the one place a `lock` value is validated and
6
+ * rendered. The SQL build and the cache key both read its result, so the two
7
+ * cannot disagree about which lock a statement carries.
8
+ *
9
+ * The clause always names the queried table (`OF "t"`). That keeps the lock on
10
+ * the returned rows of that table and nothing else, on every relation
11
+ * strategy: correlated `with` subqueries are never locked anyway, and without
12
+ * `OF` PostgreSQL refuses the `flatten` and lateral-pick plans (their outer
13
+ * joins would put a table on the nullable side of the lock).
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.resolveRowLock = resolveRowLock;
17
+ exports.lockOutsideTransactionMessage = lockOutsideTransactionMessage;
18
+ exports.lockOnStreamMessage = lockOnStreamMessage;
19
+ exports.lockWithDistinctMessage = lockWithDistinctMessage;
20
+ exports.assertNoLockInAutocommitPipeline = assertNoLockInAutocommitPipeline;
21
+ const errors_js_1 = require("../errors.js");
22
+ const global_filters_config_js_1 = require("../global-filters-config.js");
23
+ const utils_js_1 = require("./utils.js");
24
+ const MODES = ['update', 'noKeyUpdate', 'share', 'keyShare'];
25
+ const MODE_SQL = {
26
+ update: 'UPDATE',
27
+ noKeyUpdate: 'NO KEY UPDATE',
28
+ share: 'SHARE',
29
+ keyShare: 'KEY SHARE',
30
+ };
31
+ /** One letter per mode for the SQL-template cache key. */
32
+ const MODE_FP = { update: 'u', noKeyUpdate: 'n', share: 's', keyShare: 'k' };
33
+ const LOCK_KEYS = ['mode', 'noWait', 'skipLocked'];
34
+ /** Why an engine refuses a lock mode, keyed by dialect name. */
35
+ const ENGINE_HINT = {
36
+ sqlite: 'SQLite has no row locks: a write transaction locks the whole database. Remove `lock`; inside ' +
37
+ '$transaction on SQLite, writes are already serialized.',
38
+ mysql: "MySQL supports lock: 'update' and lock: 'share' only. Use 'update' (stronger) or 'share' (weaker).",
39
+ mssql: "Row locks are not available on SQL Server in this release. Use $transaction({ isolationLevel: 'RepeatableRead' }) " +
40
+ 'or a raw query with table hints.',
41
+ powdb: 'PowDB has no row locks: a transaction holds the single writer gate.',
42
+ };
43
+ /**
44
+ * Validate `lock` for a read on `table` and render its clause.
45
+ *
46
+ * `undefined` means no lock. Anything that is not a mode string or a
47
+ * `{ mode, noWait?, skipLocked? }` object is `ValidationError` (E003), and so
48
+ * is asking for both wait policies at once. A mode the dialect does not list in
49
+ * {@link Dialect.rowLockModes} is `UnsupportedFeatureError` (E017).
50
+ */
51
+ function resolveRowLock(lock, dialect, table) {
52
+ if (lock === undefined)
53
+ return undefined;
54
+ let mode;
55
+ let noWait;
56
+ let skipLocked;
57
+ if (typeof lock === 'string') {
58
+ mode = lock;
59
+ }
60
+ else if (typeof lock === 'object' && lock !== null && !Array.isArray(lock)) {
61
+ for (const key of Object.keys(lock)) {
62
+ if (!LOCK_KEYS.includes(key)) {
63
+ const hint = (0, utils_js_1.suggestKey)(key, LOCK_KEYS);
64
+ throw new errors_js_1.ValidationError(`lock on "${table}": unknown key "${key}".${hint ? ` Did you mean "${hint}"?` : ''} ` +
65
+ 'A lock is a mode, or { mode, noWait: true } or { mode, skipLocked: true }.');
66
+ }
67
+ }
68
+ ({ mode, noWait, skipLocked } = lock);
69
+ assertFlag(noWait, 'noWait', table);
70
+ assertFlag(skipLocked, 'skipLocked', table);
71
+ if (noWait === true && skipLocked === true) {
72
+ throw new errors_js_1.ValidationError(`lock on "${table}": noWait and skipLocked cannot be combined. noWait fails at once when a row is ` +
73
+ 'locked by another transaction; skipLocked leaves that row out of the result. Pick one.');
74
+ }
75
+ }
76
+ else {
77
+ throw new errors_js_1.ValidationError(`lock on "${table}" must be a mode ('update', 'noKeyUpdate', 'share' or 'keyShare') or ` +
78
+ `{ mode, noWait?, skipLocked? }, received ${describe(lock)}. Leave it out for an unlocked read.`);
79
+ }
80
+ if (typeof mode !== 'string' || !MODES.includes(mode)) {
81
+ const hint = typeof mode === 'string' ? (0, utils_js_1.suggestKey)(mode, MODES) : null;
82
+ throw new errors_js_1.ValidationError(`lock on "${table}": unknown mode ${describe(mode)}.${hint ? ` Did you mean '${hint}'?` : ''} ` +
83
+ "Use 'update', 'noKeyUpdate', 'share' or 'keyShare'.");
84
+ }
85
+ const m = mode;
86
+ if (!(dialect.rowLockModes ?? []).includes(m)) {
87
+ throw new errors_js_1.UnsupportedFeatureError(`lock: '${m}'`, dialect.name, ENGINE_HINT[dialect.name] ?? 'This engine has no row-locking clause Turbine can emit.');
88
+ }
89
+ const wait = noWait === true ? ' NOWAIT' : skipLocked === true ? ' SKIP LOCKED' : '';
90
+ return {
91
+ sql: ` FOR ${MODE_SQL[m]} OF ${dialect.quoteIdentifier(table)}${wait}`,
92
+ fp: `${MODE_FP[m]}${noWait === true ? '.nw' : skipLocked === true ? '.sl' : ''}`,
93
+ };
94
+ }
95
+ /**
96
+ * The refusal for a locking read outside a transaction. In autocommit the lock
97
+ * is released when the statement ends, before the caller sees the rows, so a
98
+ * `skipLocked` queue claim outside a transaction claims nothing, silently.
99
+ */
100
+ function lockOutsideTransactionMessage(table, operation) {
101
+ return (`lock on "${table}".${operation}() needs a transaction: outside one the rows are unlocked again before ` +
102
+ `the call returns. Use db.$transaction(async (tx) => tx.${(0, global_filters_config_js_1.tableAccessorName)(table)}.${operation}({ ..., lock })).`);
103
+ }
104
+ /** The refusal for `lock` on a streaming read. */
105
+ function lockOnStreamMessage(table, operation) {
106
+ return (`lock is not supported on "${table}".${operation}(): a stream is not a locking read. Page with ` +
107
+ 'findMany({ lock, limit }) inside the transaction instead.');
108
+ }
109
+ /** The refusal for `lock` together with `distinct`. */
110
+ function lockWithDistinctMessage(table) {
111
+ return (`lock on "${table}" cannot be combined with distinct: PostgreSQL does not lock rows of a DISTINCT query. ` +
112
+ 'Lock first (findMany with lock), then de-duplicate.');
113
+ }
114
+ /**
115
+ * Refuse a locking read in a pipeline that runs each statement in autocommit
116
+ * (`pipeline(..., { transactional: false })`). A transactional pipeline, and
117
+ * `$transaction([...])`, keep the lock for the rest of the batch.
118
+ */
119
+ function assertNoLockInAutocommitPipeline(queries) {
120
+ const at = queries.findIndex((q) => q.rowLock === true);
121
+ if (at === -1)
122
+ return;
123
+ throw new errors_js_1.ValidationError(`pipeline query ${at} (${queries[at]?.tag ?? 'a read'}) is a locking read, and { transactional: false } runs ` +
124
+ 'it in autocommit, which releases the lock before the call returns. Drop transactional: false, or run the ' +
125
+ 'batch with db.$transaction([...]).');
126
+ }
127
+ function assertFlag(value, name, table) {
128
+ if (value === undefined || typeof value === 'boolean')
129
+ return;
130
+ throw new errors_js_1.ValidationError(`lock on "${table}": ${name} must be true or false, received ${describe(value)}.`);
131
+ }
132
+ function describe(value) {
133
+ if (typeof value === 'string')
134
+ return `'${value}'`;
135
+ if (value === null || typeof value !== 'object')
136
+ return String(value);
137
+ return Array.isArray(value) ? 'an array' : 'an object';
138
+ }
@@ -0,0 +1,161 @@
1
+ /**
2
+ * turbine-orm: `sqlComment`, sqlcommenter-style key/values on each statement
3
+ * Turbine builds, so `pg_stat_activity`, the server log, `auto_explain` and
4
+ * database APM tools can attribute a statement to a service, a model, a feature
5
+ * or a trace.
6
+ *
7
+ * SELECT ... LIMIT $2 /*action='findMany',application='billing',model='users'*\/
8
+ *
9
+ * FORMAT (the sqlcommenter spec): keys sorted, each value URL-encoded with
10
+ * `encodeURIComponent` and then `'` escaped as `\'`, each pair `key='value'`,
11
+ * pairs joined by commas, the whole comment appended after the statement with
12
+ * one space before it.
13
+ *
14
+ * WHY A VALUE CANNOT ESCAPE THE COMMENT. `encodeURIComponent` encodes `/`, so a
15
+ * value can hold neither `*\/` (the comment's end) nor `/*` (PostgreSQL and SQL
16
+ * Server nest block comments, so an opener would swallow the rest of the
17
+ * text). It also encodes every character a driver-side placeholder rewrite
18
+ * looks for (`$`, `?`, `:`, `@`) and `;`. Keys must match
19
+ * {@link SQL_COMMENT_KEY_PATTERN}, whose first-character rule also rules out
20
+ * MySQL's executable `/*!` and optimizer-hint `/*+` comments.
21
+ *
22
+ * WHERE IT IS APPENDED: at the execute seam, AFTER the SQL-template cache. The
23
+ * cache stores commentless text, so its keys, its hit rate and the lockstep
24
+ * checks are untouched by any comment, and a per-request value can never grow
25
+ * it. `$on('query')` events keep `sql` commentless and carry the comment in
26
+ * their own field.
27
+ *
28
+ * PREPARED-STATEMENT NAMES. node-postgres refuses to reuse a statement name for
29
+ * different text on one connection, and every name a connection prepares stays
30
+ * on the server until the connection closes. So:
31
+ *
32
+ * - no comment: the template's own name, as before;
33
+ * - static, model, action and tag only (constant per call site and label):
34
+ * `c_<16 hex>`, a hash of the template name and the comment, claimed from
35
+ * the same process-wide budget as every other name
36
+ * (`PREPARED_STATEMENT_BUDGET`), so the server-side cost stays bounded
37
+ * however many labels there are;
38
+ * - any dynamic value (a trace id, unique per request): unnamed, parsed on
39
+ * every execution and never kept. A per-request value under a name would
40
+ * prepare a new statement on every pooled connection for every request.
41
+ *
42
+ * Leaf apart from errors.ts, logger.ts, query-events.ts (the `$tag` scope) and
43
+ * utils.ts (the name budget); nothing here is Node-only.
44
+ */
45
+ import { type TurbineLogger } from '../logger.js';
46
+ import type { DeferredQuery } from './deferred.js';
47
+ /** `TurbineConfig.sqlComment`. */
48
+ export interface SqlCommentOptions {
49
+ /** Constant key/values on every statement this client builds: `{ application: 'billing' }`. */
50
+ static?: Readonly<Record<string, string>> | undefined;
51
+ /** Add `model` (the table) and `action` (`'findMany'`, `'update'`, ...) of the operation. */
52
+ model?: boolean | undefined;
53
+ /** Add the label of the innermost `db.$tag(label, fn)` scope as `tag`. */
54
+ tag?: boolean | undefined;
55
+ /**
56
+ * Per-statement values, computed in the caller's async context (for example
57
+ * a W3C `traceparent`). A key whose value is `undefined` is left out. A
58
+ * statement carrying any dynamic value is sent unnamed: parsed on every
59
+ * execution, never kept as a prepared statement. A key or value this
60
+ * function returns that cannot be used is dropped with a warning
61
+ * (`sql-comment-dropped`), and a throw drops all of them: a tracing hook
62
+ * never fails a query.
63
+ */
64
+ dynamic?: (() => Readonly<Record<string, string | undefined>> | undefined | null) | undefined;
65
+ }
66
+ /** What a comment key must look like. Lower case, so it can never open `/*!` or `/*+`. */
67
+ export declare const SQL_COMMENT_KEY_PATTERN: RegExp;
68
+ /** Longest value accepted, in characters before encoding. */
69
+ export declare const MAX_SQL_COMMENT_VALUE_LENGTH = 256;
70
+ /** One statement's comment. */
71
+ export interface StatementComment {
72
+ /** The comment exactly as appended, without the space before it: `/*key='value',...*\/`. */
73
+ readonly comment: string;
74
+ /** It carries a dynamic value, so the statement goes out unnamed. */
75
+ readonly dynamic: boolean;
76
+ }
77
+ /**
78
+ * Builds the comment for each statement and the name it is sent under. One per
79
+ * client, shared by every table accessor and transaction of that client.
80
+ */
81
+ export declare class SqlCommenter {
82
+ private readonly logger;
83
+ /** Static pairs, encoded and sorted. */
84
+ private readonly staticPairs;
85
+ /** Keys a dynamic value may not take: the static ones and the ones model / tag fill in. */
86
+ private readonly reservedKeys;
87
+ private readonly withModel;
88
+ private readonly withTag;
89
+ private readonly dynamic;
90
+ /** The comment when it depends on nothing per statement (no model, no tag). */
91
+ private readonly constant;
92
+ /** Rendered model / action / tag comments. Bounded: tags may come from data. */
93
+ private readonly rendered;
94
+ /** Claimed `c_` names by template name and comment. Holds only claimed names, so the budget bounds it. */
95
+ private readonly names;
96
+ /**
97
+ * Every statement gets a comment (a static key, or the model and action),
98
+ * so a template's own name is never sent and need not be claimed from the
99
+ * budget; the commented name is claimed instead.
100
+ */
101
+ readonly alwaysComments: boolean;
102
+ constructor(staticPairs: ReadonlyArray<readonly [string, string]>, withModel: boolean, withTag: boolean, dynamic: SqlCommentOptions['dynamic'], logger: TurbineLogger);
103
+ /**
104
+ * The comment for one statement of operation `action` on `model`, or
105
+ * `undefined` when it carries none. Reads the `$tag` scope and calls
106
+ * `dynamic` in the caller's async context, so call it where the statement
107
+ * is sent.
108
+ */
109
+ commentFor(model: string, action: string): StatementComment | undefined;
110
+ /**
111
+ * The name a statement with comment `c` is sent under, given its template's
112
+ * name. A template sent unnamed stays unnamed; a dynamic comment is unnamed;
113
+ * anything else gets a stable `c_` name from the process-wide budget, or
114
+ * goes unnamed once that is spent.
115
+ */
116
+ preparedName(templateName: string | undefined, c: StatementComment): string | undefined;
117
+ /** The usable dynamic pairs, encoded, or `undefined` when there are none. */
118
+ private dynamicPairs;
119
+ /** Why a dynamic key or value cannot be used, as [warning key, sentence], or `undefined`. */
120
+ private refusal;
121
+ /** One warning per reason and key, so a hook that misbehaves on every statement says it once. */
122
+ private dropped;
123
+ }
124
+ /**
125
+ * Validate `TurbineConfig.sqlComment` and build its commenter, or `undefined`
126
+ * when there is nothing to add. Throws `ValidationError` (E003) for a malformed
127
+ * option, and `UnsupportedFeatureError` (E017) where it cannot be honoured:
128
+ *
129
+ * - a backend that builds no SQL (PowDB, which injects its own query
130
+ * interface) has nothing to comment;
131
+ * - `dynamic` on an engine that prepares every statement text
132
+ * (`preparesEveryStatement`), which is MySQL: the MySQL engine sends each
133
+ * parameterized statement through mysql2's `execute()`, which keeps one
134
+ * SERVER-side prepared
135
+ * statement per distinct text per connection (up to 16,000 each), and the
136
+ * server caps the total across every client at `max_prepared_stmt_count`
137
+ * (16,382 by default). A value unique per request makes every text
138
+ * distinct, so a busy pool reaches that cap (error 1461) and every client
139
+ * of the server then fails to prepare.
140
+ */
141
+ export declare function resolveSqlComment(value: unknown, logger: TurbineLogger, engine: {
142
+ readonly dialect: string;
143
+ readonly preparesEveryStatement: boolean;
144
+ readonly buildsSql: boolean;
145
+ }): SqlCommenter | undefined;
146
+ /**
147
+ * `sql` with a comment Turbine appended removed, for code that reads statement
148
+ * text to decide how to run it (an engine shim telling a row-returning
149
+ * statement from a change count). A value can never contain `/*` (it is
150
+ * URL-encoded), so the last ` /*` of a statement ending in `*\/` is the
151
+ * comment's own opener; text Turbine did not comment is returned unchanged
152
+ * unless it, too, ends in a block comment, which is equally not code.
153
+ */
154
+ export declare function withoutTrailingComment(sql: string): string;
155
+ /**
156
+ * `q` as sent with `comment`: its statement, and every statement of its
157
+ * reselect plan (MySQL), carry the comment. Everything else on the query is
158
+ * kept. Used by the batch paths (`pipeline`, `$transaction([...])`), which run
159
+ * deferred queries without going through a query interface.
160
+ */
161
+ export declare function commentDeferred<T>(q: DeferredQuery<T>, comment: string | undefined): DeferredQuery<T>;