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,212 @@
1
+ "use strict";
2
+ /**
3
+ * turbine-orm: the abandoned-stream idle guard.
4
+ *
5
+ * A cursor stream holds a checked-out connection between pulls (and, on
6
+ * PostgreSQL, an open transaction whose snapshot pins the xmin horizon for the
7
+ * whole database). A consumer that stops pulling without calling `return()`
8
+ * leaves the stream suspended at a `yield` forever, and a suspended generator
9
+ * runs no code, so nothing would ever release either. This guard is the code
10
+ * that runs instead: a timer that notices the consumer has asked for nothing for
11
+ * the configured time and closes the stream from outside.
12
+ *
13
+ * The consuming generator owns the {@link StreamIdleState}: it sets `suspended`
14
+ * around each yield and bumps `pulls` when the consumer resumes it. That is two
15
+ * writes per yield and no timer work, which is what keeps a per-row stream as
16
+ * cheap as before (a timer refreshed per row costs about 15% per row; a
17
+ * `setTimeout` per row more than doubles it).
18
+ *
19
+ * Leaf module: imports errors.ts only, so it stays in the serverless graph
20
+ * without pulling anything node-only.
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.StreamIdleGuard = exports.MAX_STREAM_IDLE_TIMEOUT_MS = exports.STREAM_IDLE_BACKSTOP_GRACE_MS = exports.DEFAULT_STREAM_IDLE_TIMEOUT_MS = void 0;
24
+ exports.resolveStreamIdleTimeout = resolveStreamIdleTimeout;
25
+ exports.newStreamIdleState = newStreamIdleState;
26
+ exports.streamIdleExpiredError = streamIdleExpiredError;
27
+ exports.streamBackstopStatement = streamBackstopStatement;
28
+ exports.watchStreamConnection = watchStreamConnection;
29
+ const errors_js_1 = require("../errors.js");
30
+ /** The default for `streamIdleTimeoutMs` (client) and `idleTimeoutMs` (per call). */
31
+ exports.DEFAULT_STREAM_IDLE_TIMEOUT_MS = 300_000;
32
+ /**
33
+ * How much later than the idle timeout the PostgreSQL server-side limit fires.
34
+ * The client timer always expires a stream first (it ticks at most every
35
+ * {@link MAX_TICK_MS}, half this grace), so the server limit only acts when the
36
+ * process has stopped running timers: frozen between serverless invocations,
37
+ * or an event loop blocked for longer than the grace.
38
+ */
39
+ exports.STREAM_IDLE_BACKSTOP_GRACE_MS = 10_000;
40
+ /**
41
+ * The largest idle timeout accepted. PostgreSQL's
42
+ * `idle_in_transaction_session_timeout` is a 32-bit count of milliseconds, and
43
+ * the backstop adds the grace to it.
44
+ */
45
+ exports.MAX_STREAM_IDLE_TIMEOUT_MS = 2_147_483_647 - exports.STREAM_IDLE_BACKSTOP_GRACE_MS;
46
+ /** The longest gap between two idle checks, so expiry lands within 5 s of the timeout. */
47
+ const MAX_TICK_MS = 5_000;
48
+ /**
49
+ * Validate an idle timeout: a whole number of milliseconds from 0 (disabled)
50
+ * to {@link MAX_STREAM_IDLE_TIMEOUT_MS}, else E003. `undefined` means "not
51
+ * set here", so the caller falls back to the next level.
52
+ */
53
+ function resolveStreamIdleTimeout(value, name) {
54
+ if (value === undefined)
55
+ return undefined;
56
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0 || value > exports.MAX_STREAM_IDLE_TIMEOUT_MS) {
57
+ throw new errors_js_1.ValidationError(`Invalid ${name}: ${typeof value === 'string' ? JSON.stringify(value) : String(value)}. Expected a whole ` +
58
+ `number of milliseconds from 0 (no idle timeout) to ${exports.MAX_STREAM_IDLE_TIMEOUT_MS}.`);
59
+ }
60
+ return value;
61
+ }
62
+ function newStreamIdleState() {
63
+ return { pulls: 0, suspended: false, rows: 0, expired: undefined };
64
+ }
65
+ /** The E002 the next pull on an expired stream throws. */
66
+ function streamIdleExpiredError(action, table, timeoutMs, unit) {
67
+ return new errors_js_1.TimeoutError(timeoutMs, 'Stream', {
68
+ message: `${action} on "${table}" was closed after ${timeoutMs} ms with no ${unit} requested: its cursor and ` +
69
+ `connection were released so an abandoned stream cannot hold a pooled connection and the database's ` +
70
+ `snapshot. Consume faster, raise streamIdleTimeoutMs (client) or idleTimeoutMs (this call), or pass 0 ` +
71
+ 'to disable.',
72
+ outcome: 'not-executed',
73
+ });
74
+ }
75
+ /**
76
+ * The PostgreSQL server-side limit for a stream's own transaction:
77
+ * `idle_in_transaction_session_timeout` set to the idle timeout plus the grace,
78
+ * TRANSACTION-LOCAL (`set_config(..., true)`), so it ends with the stream's
79
+ * COMMIT and cannot reach another client through a transaction pooler.
80
+ *
81
+ * A stricter limit already in force (a role or server setting below ours) is
82
+ * kept, so a stream never loosens what the operator configured. The value is a
83
+ * validated integer, never caller text: a GUC value cannot be a bind parameter.
84
+ * Reading `pg_settings` rather than calling `set_config` directly also means an
85
+ * engine without the setting gets no row and no error.
86
+ */
87
+ function streamBackstopStatement(timeoutMs) {
88
+ const limit = timeoutMs + exports.STREAM_IDLE_BACKSTOP_GRACE_MS;
89
+ if (!Number.isSafeInteger(limit) || limit <= exports.STREAM_IDLE_BACKSTOP_GRACE_MS || limit > 2_147_483_647) {
90
+ throw new errors_js_1.ValidationError(`Invalid stream idle timeout ${String(timeoutMs)} for the server-side limit.`);
91
+ }
92
+ return ("SELECT set_config('idle_in_transaction_session_timeout', CASE WHEN s.setting::bigint > 0 AND " +
93
+ `s.setting::bigint < ${limit} THEN s.setting ELSE '${limit}' END, true) FROM pg_settings s ` +
94
+ "WHERE s.name = 'idle_in_transaction_session_timeout'");
95
+ }
96
+ /**
97
+ * The timer half of the guard. One per open cursor stream, `unref()`ed so it
98
+ * never keeps a process alive.
99
+ *
100
+ * It ticks every `min(timeout / 4, 5 s)`. A tick that finds the stream
101
+ * suspended with no pull since the previous tick counts as idle; enough idle
102
+ * ticks in a row to cover the timeout expire the stream, so expiry lands
103
+ * between 1x the timeout and the timeout plus one tick. Time Turbine spends
104
+ * fetching never counts, because the stream is not suspended then.
105
+ *
106
+ * With `keepalive` set (PostgreSQL, where {@link streamBackstopStatement} is
107
+ * in force), a tick also sends a no-op statement when the connection has been
108
+ * quiet for half the timeout. A consumer that pulls rows of an already-fetched
109
+ * batch slowly is alive while the server sees an idle transaction; without the
110
+ * keepalive the server limit would end a stream the consumer is still reading.
111
+ * The server limit therefore only fires when this timer cannot run.
112
+ */
113
+ class StreamIdleGuard {
114
+ state;
115
+ timeoutMs;
116
+ expiredError;
117
+ onExpire;
118
+ keepalive;
119
+ timer;
120
+ idleTicksToExpire;
121
+ lastPulls;
122
+ idleTicks = 0;
123
+ lastStatementAt = Date.now();
124
+ statementsInFlight = 0;
125
+ keepaliveInFlight = false;
126
+ /** Settles once an expired stream's cleanup has run (connection released). */
127
+ expiry;
128
+ constructor(state, timeoutMs, expiredError, onExpire, keepalive) {
129
+ this.state = state;
130
+ this.timeoutMs = timeoutMs;
131
+ this.expiredError = expiredError;
132
+ this.onExpire = onExpire;
133
+ this.keepalive = keepalive;
134
+ const tickMs = Math.max(1, Math.min(Math.floor(timeoutMs / 4), MAX_TICK_MS));
135
+ this.idleTicksToExpire = Math.ceil(timeoutMs / tickMs);
136
+ this.lastPulls = state.pulls;
137
+ this.timer = setInterval(() => this.tick(), tickMs);
138
+ this.timer.unref?.();
139
+ }
140
+ /** Bracket a statement on the stream's connection, so the keepalive knows it is busy. */
141
+ statementStarted() {
142
+ this.statementsInFlight++;
143
+ this.lastStatementAt = Date.now();
144
+ }
145
+ statementSettled() {
146
+ this.statementsInFlight--;
147
+ this.lastStatementAt = Date.now();
148
+ }
149
+ stop() {
150
+ clearInterval(this.timer);
151
+ }
152
+ tick() {
153
+ if (this.expiry)
154
+ return;
155
+ if (!this.state.suspended || this.state.pulls !== this.lastPulls) {
156
+ this.lastPulls = this.state.pulls;
157
+ this.idleTicks = 0;
158
+ }
159
+ else if (++this.idleTicks >= this.idleTicksToExpire) {
160
+ this.stop();
161
+ // Set before any await, so a pull that races the cleanup already sees it.
162
+ this.state.expired = this.expiredError();
163
+ this.expiry = this.onExpire();
164
+ return;
165
+ }
166
+ if (this.keepalive &&
167
+ !this.keepaliveInFlight &&
168
+ this.statementsInFlight === 0 &&
169
+ Date.now() - this.lastStatementAt >= this.timeoutMs / 2) {
170
+ this.keepaliveInFlight = true;
171
+ this.statementStarted();
172
+ // A failed keepalive is not reported here: the stream's next statement
173
+ // meets the same broken connection and reports it with context.
174
+ this.keepalive()
175
+ .catch(() => undefined)
176
+ .finally(() => {
177
+ this.keepaliveInFlight = false;
178
+ this.statementSettled();
179
+ });
180
+ }
181
+ }
182
+ }
183
+ exports.StreamIdleGuard = StreamIdleGuard;
184
+ /**
185
+ * The stream's connection, as the dialect sees it, with two additions: every
186
+ * statement is reported to the guard (for the keepalive), and, when `backstop`
187
+ * is given, the dialect's own BEGIN carries {@link streamBackstopStatement} in
188
+ * the same simple-protocol round trip, so the limit is in force from the
189
+ * transaction's first statement at no extra cost. Matching the exact BEGIN text
190
+ * the dialect emits keeps the dialect itself unchanged; the live backstop test
191
+ * fails if that text ever stops matching.
192
+ */
193
+ function watchStreamConnection(base, guard, backstop) {
194
+ let backstopSent = false;
195
+ return {
196
+ query: async (text, values) => {
197
+ let sql = text;
198
+ if (backstop && !backstopSent && values === undefined && text === backstop.begin) {
199
+ backstopSent = true;
200
+ sql = `${text}; ${backstop.statement}`;
201
+ }
202
+ const g = guard();
203
+ g?.statementStarted();
204
+ try {
205
+ return await base.query(sql, values);
206
+ }
207
+ finally {
208
+ g?.statementSettled();
209
+ }
210
+ },
211
+ };
212
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * turbine-orm, the table accessor contract.
3
+ *
4
+ * `db.users` is a `QueryInterface` on the SQL engines and a `PowqlInterface` on
5
+ * PowDB. The second is a parallel class, not a subclass, so without a shared
6
+ * type the compiler cannot see a method one engine has and the other lacks, and
7
+ * the user meets it as `TypeError: ... is not a function` at run time.
8
+ *
9
+ * {@link TableClient} is that shared type. It is DERIVED from QueryInterface
10
+ * (a `Pick` of the classified methods), so the SQL builder stays the one source
11
+ * of truth for every signature, and `PowqlInterface implements TableClient`
12
+ * makes a missing or mismatched method a build error.
13
+ *
14
+ * Type-only imports: this module emits {@link TABLE_METHODS} and nothing else,
15
+ * so it adds no edge to the import graph.
16
+ */
17
+ import type { QueryInterface } from './builder.js';
18
+ import type { DefaultInputTypes, TableInputTypes } from './types.js';
19
+ /**
20
+ * How a table method is routed.
21
+ *
22
+ * - `read`: may be served by a read replica (`READ_OPERATIONS` in client.ts is
23
+ * derived from these).
24
+ * - `write`: always runs on the primary.
25
+ * - `deferred`: returns a `DeferredQuery` for `db.pipeline()` /
26
+ * `$transaction([...])` without running anything.
27
+ * - `primary`: anything else on the accessor; runs on the primary.
28
+ */
29
+ export type TableMethodKind = 'read' | 'write' | 'deferred' | 'primary';
30
+ /**
31
+ * Every public method of a table accessor, with its routing class.
32
+ *
33
+ * `satisfies` refuses a key QueryInterface does not have; the exhaustiveness
34
+ * check below refuses a QueryInterface member missing from here.
35
+ */
36
+ export declare const TABLE_METHODS: {
37
+ readonly findMany: "read";
38
+ readonly findFirst: "read";
39
+ readonly findFirstOrThrow: "read";
40
+ readonly findUnique: "read";
41
+ readonly findUniqueOrThrow: "read";
42
+ readonly count: "read";
43
+ readonly aggregate: "read";
44
+ readonly groupBy: "read";
45
+ readonly findManyStream: "read";
46
+ readonly findManyStreamBatches: "read";
47
+ readonly explain: "primary";
48
+ readonly cacheStats: "primary";
49
+ readonly create: "write";
50
+ readonly createMany: "write";
51
+ readonly update: "write";
52
+ readonly updateMany: "write";
53
+ readonly delete: "write";
54
+ readonly deleteMany: "write";
55
+ readonly upsert: "write";
56
+ readonly buildFindMany: "deferred";
57
+ readonly buildFindFirst: "deferred";
58
+ readonly buildFindFirstOrThrow: "deferred";
59
+ readonly buildFindUnique: "deferred";
60
+ readonly buildFindUniqueOrThrow: "deferred";
61
+ readonly buildCount: "deferred";
62
+ readonly buildAggregate: "deferred";
63
+ readonly buildGroupBy: "deferred";
64
+ readonly buildCreate: "deferred";
65
+ readonly buildCreateMany: "deferred";
66
+ readonly buildUpdate: "deferred";
67
+ readonly buildUpdateMany: "deferred";
68
+ readonly buildDelete: "deferred";
69
+ readonly buildDeleteMany: "deferred";
70
+ readonly buildUpsert: "deferred";
71
+ };
72
+ /** A method name in the table accessor contract. */
73
+ export type TableMethod = keyof typeof TABLE_METHODS;
74
+ /**
75
+ * Public QueryInterface members that are SQL-engine internals (cache
76
+ * fingerprinting, the upsert lookup decision, a test hook), deliberately
77
+ * outside the accessor contract, so PowDB need not implement them.
78
+ */
79
+ export type SqlInternalMember = 'collectWhereParams' | 'fingerprintWhere' | 'withFingerprint' | 'upsertNeedsLookup' | 'resetUnlimitedWarnings';
80
+ /** Public QueryInterface members classified neither as a table method nor as internal. */
81
+ type Unclassified = Exclude<keyof QueryInterface<object>, TableMethod | SqlInternalMember>;
82
+ /**
83
+ * Fails the build, naming the member, when QueryInterface gains a public
84
+ * member nobody classified: add it to TABLE_METHODS (and to PowqlInterface) or
85
+ * to SqlInternalMember.
86
+ */
87
+ type AssertEveryMemberClassified<U extends never> = U;
88
+ export type EveryQueryInterfaceMemberClassified = AssertEveryMemberClassified<Unclassified>;
89
+ /** The table accessor contract every engine's accessor class implements. */
90
+ export type TableClient<T extends object, R extends object = {}, M extends TableInputTypes = DefaultInputTypes<T, R>> = Pick<QueryInterface<T, R, M>, TableMethod>;
91
+ /**
92
+ * View a factory-built accessor as the `QueryInterface` the client's public
93
+ * `table()` type names.
94
+ *
95
+ * Sound because the exhaustiveness check above guarantees `TableClient` holds
96
+ * every public QueryInterface member except the SQL internals, which nothing
97
+ * outside the SQL builder reaches through an accessor without first checking
98
+ * the member exists. The cast hides only private members.
99
+ */
100
+ export declare function asQueryInterface<T extends object>(client: TableClient<T>): QueryInterface<T>;
101
+ export {};
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ /**
3
+ * turbine-orm, the table accessor contract.
4
+ *
5
+ * `db.users` is a `QueryInterface` on the SQL engines and a `PowqlInterface` on
6
+ * PowDB. The second is a parallel class, not a subclass, so without a shared
7
+ * type the compiler cannot see a method one engine has and the other lacks, and
8
+ * the user meets it as `TypeError: ... is not a function` at run time.
9
+ *
10
+ * {@link TableClient} is that shared type. It is DERIVED from QueryInterface
11
+ * (a `Pick` of the classified methods), so the SQL builder stays the one source
12
+ * of truth for every signature, and `PowqlInterface implements TableClient`
13
+ * makes a missing or mismatched method a build error.
14
+ *
15
+ * Type-only imports: this module emits {@link TABLE_METHODS} and nothing else,
16
+ * so it adds no edge to the import graph.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.TABLE_METHODS = void 0;
20
+ exports.asQueryInterface = asQueryInterface;
21
+ /**
22
+ * Every public method of a table accessor, with its routing class.
23
+ *
24
+ * `satisfies` refuses a key QueryInterface does not have; the exhaustiveness
25
+ * check below refuses a QueryInterface member missing from here.
26
+ */
27
+ exports.TABLE_METHODS = {
28
+ findMany: 'read',
29
+ findFirst: 'read',
30
+ findFirstOrThrow: 'read',
31
+ findUnique: 'read',
32
+ findUniqueOrThrow: 'read',
33
+ count: 'read',
34
+ aggregate: 'read',
35
+ groupBy: 'read',
36
+ findManyStream: 'read',
37
+ findManyStreamBatches: 'read',
38
+ explain: 'primary',
39
+ cacheStats: 'primary',
40
+ create: 'write',
41
+ createMany: 'write',
42
+ update: 'write',
43
+ updateMany: 'write',
44
+ delete: 'write',
45
+ deleteMany: 'write',
46
+ upsert: 'write',
47
+ buildFindMany: 'deferred',
48
+ buildFindFirst: 'deferred',
49
+ buildFindFirstOrThrow: 'deferred',
50
+ buildFindUnique: 'deferred',
51
+ buildFindUniqueOrThrow: 'deferred',
52
+ buildCount: 'deferred',
53
+ buildAggregate: 'deferred',
54
+ buildGroupBy: 'deferred',
55
+ buildCreate: 'deferred',
56
+ buildCreateMany: 'deferred',
57
+ buildUpdate: 'deferred',
58
+ buildUpdateMany: 'deferred',
59
+ buildDelete: 'deferred',
60
+ buildDeleteMany: 'deferred',
61
+ buildUpsert: 'deferred',
62
+ };
63
+ /**
64
+ * View a factory-built accessor as the `QueryInterface` the client's public
65
+ * `table()` type names.
66
+ *
67
+ * Sound because the exhaustiveness check above guarantees `TableClient` holds
68
+ * every public QueryInterface member except the SQL internals, which nothing
69
+ * outside the SQL builder reaches through an accessor without first checking
70
+ * the member exists. The cast hides only private members.
71
+ */
72
+ function asQueryInterface(client) {
73
+ return client;
74
+ }