okmodel 0.7.0 → 0.9.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 (258) hide show
  1. package/README.md +14 -0
  2. package/dist/adapters/capabilities.d.ts +32 -0
  3. package/dist/adapters/failure.d.ts +1 -1
  4. package/dist/adapters/pg/bun-sql.d.ts +53 -0
  5. package/dist/adapters/pg/bunsql-extra.d.ts +1 -1
  6. package/dist/adapters/pg/bunsql.d.ts +1 -1
  7. package/dist/adapters/pg/neon-extra.d.ts +18 -0
  8. package/dist/adapters/pg/neon.d.ts +104 -0
  9. package/dist/adapters/pg/no-inflight-timeout.d.ts +1 -1
  10. package/dist/contracts/error.d.ts +1 -1
  11. package/dist/dialects/pg/ext/btree-gin.d.ts +26 -0
  12. package/dist/dialects/pg/ext/btree-gin.js +20 -0
  13. package/dist/dialects/pg/ext/btree-gist.d.ts +26 -0
  14. package/dist/dialects/pg/ext/btree-gist.js +20 -0
  15. package/dist/dialects/pg/ext/call.d.ts +53 -0
  16. package/dist/dialects/pg/ext/citext.js +1 -1
  17. package/dist/dialects/pg/ext/feature.d.ts +26 -0
  18. package/dist/dialects/pg/ext/fuzzystrmatch.d.ts +34 -0
  19. package/dist/dialects/pg/ext/fuzzystrmatch.js +33 -0
  20. package/dist/dialects/pg/ext/hstore.d.ts +41 -0
  21. package/dist/dialects/pg/ext/hstore.js +29 -0
  22. package/dist/dialects/pg/ext/index.d.ts +56 -0
  23. package/dist/dialects/pg/ext/index.js +1 -1
  24. package/dist/dialects/pg/ext/ltree.d.ts +41 -0
  25. package/dist/dialects/pg/ext/ltree.js +29 -0
  26. package/dist/dialects/pg/ext/pg-trgm.js +4 -13
  27. package/dist/dialects/pg/ext/pgcrypto.d.ts +33 -0
  28. package/dist/dialects/pg/ext/pgcrypto.js +33 -0
  29. package/dist/dialects/pg/ext/unaccent.d.ts +26 -0
  30. package/dist/dialects/pg/ext/unaccent.js +21 -0
  31. package/dist/dialects/pg/ext/using.d.ts +23 -0
  32. package/dist/dialects/pg/ext/versions.d.ts +36 -0
  33. package/dist/dialects/pg/external.d.ts +19 -0
  34. package/dist/dialects/pg/fn/index.d.ts +39 -1
  35. package/dist/dialects/pg/fn/index.js +118 -26
  36. package/dist/dialects/pg/index.d.ts +3 -0
  37. package/dist/dialects/pg/index.js +394 -14
  38. package/dist/dialects/pg/introspect.d.ts +11 -0
  39. package/dist/dialects/pg/operators.d.ts +1 -1
  40. package/dist/dialects/pg/ops/fragment.d.ts +119 -0
  41. package/dist/dialects/pg/ops/lane.d.ts +49 -0
  42. package/dist/dialects/pg/view/client.d.ts +14 -6
  43. package/dist/dialects/pg/view/index.d.ts +73 -1
  44. package/dist/dialects/pg/view/index.js +156 -5
  45. package/dist/dialects/pg/view/scratch.d.ts +11 -5
  46. package/dist/runtime/artifact-file.d.ts +22 -0
  47. package/dist/runtime/client.d.ts +10 -0
  48. package/dist/runtime/drift-detail.d.ts +2 -1
  49. package/dist/runtime/drift.d.ts +3 -10
  50. package/dist/runtime/otel.d.ts +105 -0
  51. package/dist/runtime/otel.js +97 -0
  52. package/dist/runtime/pg/bun.js +4 -4
  53. package/dist/runtime/pg/neon.d.ts +38 -0
  54. package/dist/runtime/pg/neon.js +64 -0
  55. package/dist/runtime/pg/pg.js +4 -4
  56. package/dist/runtime/pg/pglite.js +4 -4
  57. package/dist/runtime/pg/postgresjs.js +4 -4
  58. package/dist/runtime/plan.d.ts +1 -1
  59. package/dist/runtime/server-check.d.ts +36 -6
  60. package/dist/runtime/sql-fragment.d.ts +43 -0
  61. package/dist/runtime/tenancy/index.js +10 -10
  62. package/dist/runtime/topology.d.ts +1 -1
  63. package/dist/runtime/traits/index.js +16 -17
  64. package/dist/runtime/types.d.ts +15 -1
  65. package/dist/runtime/validate/index.js +4 -4
  66. package/dist/shared/{81ebdx9p.js → 0j6qe91y.js} +4 -4
  67. package/dist/shared/{qq3899ht.js → 12z7aznj.js} +243 -14
  68. package/dist/shared/{gzaveazc.js → 1d9q9cv2.js} +29 -2
  69. package/dist/shared/{w79hsckn.js → 1mxm04fy.js} +5 -5
  70. package/dist/shared/{7k9grvf6.js → 2szgv6yj.js} +5 -5
  71. package/dist/shared/{gs74dbj5.js → 2zdxkt7b.js} +933 -111
  72. package/dist/shared/{m6p12kbr.js → 3456242y.js} +23 -23
  73. package/dist/shared/3bb7wsqt.js +99 -0
  74. package/dist/shared/{y6njgyda.js → 3t6kw83m.js} +2 -2
  75. package/dist/shared/{xhfsfkgk.js → 4vbf83xx.js} +9 -2
  76. package/dist/shared/{pt94kz7f.js → 5kyb3tqx.js} +1 -1
  77. package/dist/shared/61bmrmhr.js +35 -0
  78. package/dist/shared/{x933k9a3.js → 62b603gr.js} +10 -10
  79. package/dist/shared/{jgqj11w4.js → 6f0z3hzh.js} +4 -0
  80. package/dist/shared/{tsvww22q.js → 6nae0spm.js} +156 -95
  81. package/dist/shared/{mtaszv5a.js → 71n0jmhc.js} +102 -4
  82. package/dist/shared/{5e3tf63j.js → 760ppr76.js} +14 -6
  83. package/dist/shared/7ba5h6pb.js +17 -0
  84. package/dist/shared/{sfz1ksn6.js → 8jesqsrk.js} +2 -2
  85. package/dist/shared/{5v3xf80k.js → 8n688yjg.js} +1 -1
  86. package/dist/shared/{rs73fca9.js → 8qzkd9f3.js} +6 -6
  87. package/dist/shared/{ax7qv55k.js → 90sg0w5a.js} +202 -25
  88. package/dist/shared/{zm0ptry0.js → 99qp9vtg.js} +1 -1
  89. package/dist/shared/{xnxsed62.js → 9dr2qnx7.js} +14 -14
  90. package/dist/shared/{1w508jbr.js → 9dtgn1z2.js} +21 -17
  91. package/dist/shared/{h15jx9bc.js → 9dvh1dr6.js} +1 -1
  92. package/dist/shared/{q5c6ngn3.js → a62rb2da.js} +1 -1
  93. package/dist/shared/{te5as7z7.js → aksb89mn.js} +3 -3
  94. package/dist/shared/{bz84tkzm.js → bphrgwz9.js} +2 -2
  95. package/dist/shared/bsek72fg.js +225 -0
  96. package/dist/shared/{7mnme5tn.js → c3mvnq7a.js} +1 -1
  97. package/dist/shared/{p6qc5gcp.js → ccsmhv9r.js} +25 -7
  98. package/dist/shared/{pbp1ss85.js → cexb7z6b.js} +2 -2
  99. package/dist/shared/{ab9gmbwy.js → cf8zdz5p.js} +5 -5
  100. package/dist/shared/{jvd0mqag.js → ckz05z15.js} +5 -5
  101. package/dist/shared/{dk8v79p3.js → d5nmj7vv.js} +1 -1
  102. package/dist/shared/{14vx95q4.js → dd5pmnky.js} +7 -7
  103. package/dist/shared/{vb6qfyve.js → ds229x4r.js} +2 -2
  104. package/dist/shared/{1qa0qajz.js → e275q7sd.js} +1 -1
  105. package/dist/shared/{zp9fmend.js → ebhz8vh6.js} +4 -4
  106. package/dist/shared/{hyh73qk6.js → ecn8mfdq.js} +5 -5
  107. package/dist/shared/{je4axnm8.js → fdsz3w80.js} +2 -2
  108. package/dist/shared/{9s0ypp87.js → fk9vef30.js} +85 -74
  109. package/dist/shared/{g6evj1j3.js → g89fmz5s.js} +1 -1
  110. package/dist/shared/{aytqh5y2.js → ghqzdp94.js} +2 -2
  111. package/dist/shared/h9811jjm.js +17 -0
  112. package/dist/shared/{dkxgzaqd.js → hqpxf4a4.js} +1 -1
  113. package/dist/shared/{8skf0cam.js → jpybhf98.js} +1 -1
  114. package/dist/shared/{67txcrcw.js → kgwp4jdd.js} +4 -4
  115. package/dist/shared/kzgrnckd.js +29 -0
  116. package/dist/shared/mazpbcdj.js +233 -0
  117. package/dist/shared/{kb2sdhfb.js → mfvx6kjx.js} +17 -1
  118. package/dist/shared/{svncdeh5.js → mgaq2sd3.js} +11 -8
  119. package/dist/shared/{5mtf6cj3.js → mvmm3xpb.js} +5 -2
  120. package/dist/shared/{b5pftnn2.js → myk8fswx.js} +66 -21
  121. package/dist/shared/{2shdbn8q.js → n306gqkd.js} +9 -9
  122. package/dist/shared/{n816peh1.js → n454kcnw.js} +1 -1
  123. package/dist/shared/n5whk3mt.js +665 -0
  124. package/dist/shared/n7kg8mmx.js +61 -0
  125. package/dist/shared/{vqrjpcqn.js → nmnsgj7x.js} +1 -1
  126. package/dist/shared/{tbrvgw6z.js → npdftanb.js} +19 -26
  127. package/dist/shared/{ek2wt2dz.js → pg4ezgyf.js} +11 -30
  128. package/dist/shared/{5fe3kbsh.js → pgsak1yw.js} +1 -1
  129. package/dist/shared/{bm22fvzr.js → qfw14tna.js} +2 -2
  130. package/dist/shared/{wa07eas9.js → qvwwp1mp.js} +62 -41
  131. package/dist/shared/rbxt795q.js +1766 -0
  132. package/dist/shared/{xjk7hnn5.js → s7he5e5d.js} +2 -2
  133. package/dist/shared/{w72kgg4q.js → ss2kv2rs.js} +6 -6
  134. package/dist/shared/stfa9xcw.js +450 -0
  135. package/dist/shared/{3v7t1yrv.js → th3be82n.js} +2 -2
  136. package/dist/shared/{79dt02vc.js → tr64w5p0.js} +1 -1
  137. package/dist/shared/{cn957f8d.js → tw1nvvfj.js} +3 -3
  138. package/dist/shared/{ed0b8k4s.js → typ3vy7t.js} +1 -1
  139. package/dist/shared/{9628a9xt.js → vk7rag46.js} +1 -1
  140. package/dist/shared/{ze4hxsmy.js → w9ejzaqf.js} +1 -1
  141. package/dist/shared/{vczs8gd4.js → wvtjg5m3.js} +2 -2
  142. package/dist/shared/{9y3mmmh1.js → xfhe73sb.js} +1 -1
  143. package/dist/shared/xqacq37x.js +61 -0
  144. package/dist/shared/{1est4ezg.js → xtsydxjg.js} +3 -3
  145. package/dist/shared/xv8qj97g.js +96 -0
  146. package/dist/shared/{bg3rym3g.js → xwhdcrm4.js} +2 -2
  147. package/dist/shared/{kr0jzbw2.js → yvabyg9k.js} +7 -7
  148. package/dist/shared/yybhre6n.js +136 -0
  149. package/dist/shared/zdqf8k5d.js +8 -0
  150. package/dist/shared/{jznfax0y.js → zq1he88x.js} +4 -4
  151. package/dist/tooling/cli.js +108 -23
  152. package/dist/tooling/driver-run.js +4654 -0
  153. package/dist/tooling/driver-test.d.ts +36 -0
  154. package/dist/tooling/github/comment.d.ts +50 -0
  155. package/dist/tooling/github/post-comment.d.ts +17 -0
  156. package/dist/tooling/migrate/commands.d.ts +3 -2
  157. package/dist/tooling/migrate/config.d.ts +13 -0
  158. package/dist/tooling/migrate/export.d.ts +165 -0
  159. package/dist/tooling/migrate/ext-surface.d.ts +80 -0
  160. package/dist/tooling/migrate/ext.d.ts +31 -4
  161. package/dist/tooling/migrate/import-drizzle.d.ts +40 -0
  162. package/dist/tooling/migrate/index.d.ts +3 -0
  163. package/dist/tooling/migrate/index.js +55 -10
  164. package/dist/tooling/migrate/lint-rules.d.ts +18 -1
  165. package/dist/tooling/migrate/lint.d.ts +14 -1
  166. package/dist/tooling/migrate/place.d.ts +18 -0
  167. package/dist/tooling/migrate/plan-json.d.ts +65 -0
  168. package/dist/tooling/migrate/project.d.ts +13 -1
  169. package/dist/tooling/migrate/pull-emit.d.ts +98 -0
  170. package/dist/tooling/migrate/pull-routines.d.ts +126 -0
  171. package/dist/tooling/migrate/pull-verify.d.ts +26 -0
  172. package/dist/tooling/migrate/pull.d.ts +62 -0
  173. package/dist/tooling/migrate/reprint.d.ts +32 -0
  174. package/dist/tooling/migrate/sandbox.d.ts +8 -2
  175. package/dist/tooling/migrate/schema-api.d.ts +43 -0
  176. package/dist/tooling/migrate/sql-lex.d.ts +18 -0
  177. package/dist/tooling/shared/04svnxxj.js +344 -0
  178. package/dist/tooling/shared/0j0jtse1.js +13 -0
  179. package/dist/tooling/shared/0r05zhyq.js +618 -0
  180. package/dist/tooling/shared/1800eymw.js +49 -0
  181. package/dist/tooling/shared/35zemrmf.js +12 -0
  182. package/dist/tooling/shared/3rmaz3pq.js +140 -0
  183. package/dist/tooling/shared/3yn79q5m.js +12 -0
  184. package/dist/tooling/shared/54tqkxja.js +51 -0
  185. package/dist/tooling/shared/57btdkgm.js +209 -0
  186. package/dist/tooling/shared/5bmksndh.js +118 -0
  187. package/dist/tooling/shared/5p8km5jb.js +38 -0
  188. package/dist/tooling/shared/5x3pf400.js +185 -0
  189. package/dist/tooling/shared/5zrzffnk.js +6 -0
  190. package/dist/tooling/shared/62fxpc1p.js +332 -0
  191. package/dist/tooling/shared/68tf18v4.js +20 -0
  192. package/dist/tooling/shared/6vk28rjp.js +98 -0
  193. package/dist/tooling/shared/76pv6qff.js +9 -0
  194. package/dist/tooling/shared/7aews1zg.js +311 -0
  195. package/dist/tooling/shared/7b3xp9gc.js +195 -0
  196. package/dist/tooling/shared/7kms6fvj.js +20 -0
  197. package/dist/tooling/shared/7pxncnzs.js +40 -0
  198. package/dist/tooling/shared/829fjxyw.js +198 -0
  199. package/dist/tooling/shared/8m5znpdt.js +66 -0
  200. package/dist/tooling/shared/8yr7ges1.js +211 -0
  201. package/dist/tooling/shared/96ps4g1z.js +32 -0
  202. package/dist/tooling/shared/9qr9rkbh.js +143 -0
  203. package/dist/tooling/shared/9sfbtwsk.js +49 -0
  204. package/dist/tooling/shared/9wsnsvbf.js +10 -0
  205. package/dist/tooling/shared/a2xe04bm.js +18 -0
  206. package/dist/tooling/shared/a4pzghha.js +20 -0
  207. package/dist/tooling/shared/am04v8na.js +233 -0
  208. package/dist/tooling/shared/asgr07mp.js +194 -0
  209. package/dist/tooling/shared/c0xevn1h.js +312 -0
  210. package/dist/tooling/shared/dhatassp.js +134 -0
  211. package/dist/tooling/shared/ezqn88nj.js +1696 -0
  212. package/dist/tooling/shared/f77nnfqy.js +231 -0
  213. package/dist/tooling/shared/fh07z1dt.js +15 -0
  214. package/dist/tooling/shared/gqwevek4.js +81 -0
  215. package/dist/tooling/shared/hfq3n3bd.js +4116 -0
  216. package/dist/tooling/shared/htnaj77v.js +17 -0
  217. package/dist/tooling/shared/j664qjrt.js +64 -0
  218. package/dist/tooling/shared/jpgmjsx3.js +38 -0
  219. package/dist/tooling/shared/jr2nmr81.js +497 -0
  220. package/dist/tooling/shared/jsjjz875.js +139 -0
  221. package/dist/tooling/shared/kbqnrs1x.js +1425 -0
  222. package/dist/tooling/shared/kz715295.js +94 -0
  223. package/dist/tooling/shared/m3xt8b1h.js +22 -0
  224. package/dist/tooling/shared/m4hhb8aa.js +9 -0
  225. package/dist/tooling/shared/mw5npye0.js +16 -0
  226. package/dist/tooling/shared/n4jqhpqz.js +27 -0
  227. package/dist/tooling/shared/nxq95eb6.js +42 -0
  228. package/dist/tooling/shared/qartgazh.js +70 -0
  229. package/dist/tooling/shared/rcywj2w8.js +190 -0
  230. package/dist/tooling/shared/s6qha57m.js +16 -0
  231. package/dist/tooling/shared/shjs0379.js +150 -0
  232. package/dist/tooling/shared/sjwkt1pg.js +16 -0
  233. package/dist/tooling/shared/stebqyyd.js +401 -0
  234. package/dist/tooling/shared/t4xveemq.js +250 -0
  235. package/dist/tooling/shared/t6zjeake.js +261 -0
  236. package/dist/tooling/shared/tcwpjvxe.js +9 -0
  237. package/dist/tooling/shared/tpssp7ac.js +160 -0
  238. package/dist/tooling/shared/v6j1ep6w.js +42 -0
  239. package/dist/tooling/shared/vwr2y833.js +270 -0
  240. package/dist/tooling/shared/w17sj05d.js +7 -0
  241. package/dist/tooling/shared/w5d89rb4.js +131 -0
  242. package/dist/tooling/shared/wbwq1jsa.js +157 -0
  243. package/dist/tooling/shared/wezxf3h8.js +17 -0
  244. package/dist/tooling/shared/yb4kd19s.js +12 -0
  245. package/dist/tooling/shared/ybdew6j7.js +294 -0
  246. package/dist/tooling/shared/yfedr1zb.js +6 -0
  247. package/dist/tooling/shared/yhp829bx.js +177 -0
  248. package/dist/tooling/shared/ytk1tjs0.js +604 -0
  249. package/dist/tooling/shared/zs9aymcp.js +210 -0
  250. package/dist/tooling/shared/zx3v9phv.js +8 -0
  251. package/dist/tooling/testing/index.js +3 -3
  252. package/package.json +50 -9
  253. package/dist/shared/ktz42yez.js +0 -113
  254. package/dist/shared/ttsqgp4p.js +0 -71
  255. package/dist/shared/y34a8714.js +0 -150
  256. package/dist/shared/zy8r7qvz.js +0 -116
  257. package/dist/shared/{ywr8hmey.js → 606g0nbf.js} +3 -3
  258. package/dist/shared/{rpycarcr.js → gcefca6p.js} +4 -4
@@ -0,0 +1,401 @@
1
+ import {
2
+ refuseUncancellableTimeout
3
+ } from "./tcwpjvxe.js";
4
+ import {
5
+ openClient,
6
+ withHttp,
7
+ settleCall
8
+ } from "./jr2nmr81.js";
9
+ import {
10
+ OkmError,
11
+ isConnectionLost,
12
+ rejectKeys,
13
+ isRecord,
14
+ fail2
15
+ } from "./hfq3n3bd.js";
16
+
17
+ // src/runtime/transaction.ts
18
+ var BEGIN = {
19
+ "read committed": "BEGIN ISOLATION LEVEL READ COMMITTED",
20
+ "repeatable read": "BEGIN ISOLATION LEVEL REPEATABLE READ",
21
+ serializable: "BEGIN ISOLATION LEVEL SERIALIZABLE"
22
+ };
23
+
24
+ class Frame {
25
+ done = false;
26
+ failed = undefined;
27
+ stopped = undefined;
28
+ savepoints = 0;
29
+ signal;
30
+ abort;
31
+ active = 0;
32
+ halt;
33
+ idle = undefined;
34
+ cut = () => {
35
+ return;
36
+ };
37
+ conn;
38
+ idleMs;
39
+ constructor(conn, idleMs, stoppable) {
40
+ this.conn = conn;
41
+ this.idleMs = idleMs;
42
+ this.abort = stoppable ? new AbortController : undefined;
43
+ this.signal = this.abort?.signal;
44
+ this.halt = new Promise((_, reject) => {
45
+ this.cut = reject;
46
+ });
47
+ this.halt.catch(() => {
48
+ return;
49
+ });
50
+ }
51
+ stop(error) {
52
+ if (this.done || this.stopped !== undefined)
53
+ return;
54
+ this.stopped = error;
55
+ this.abort?.abort();
56
+ this.cut(error);
57
+ }
58
+ check() {
59
+ if (this.done) {
60
+ throw new OkmError("driver", "The transaction has finished. Use the client the callback received only while the callback runs.", { kind: "driver" });
61
+ }
62
+ if (this.stopped !== undefined)
63
+ throw this.stopped;
64
+ }
65
+ enter() {
66
+ this.active += 1;
67
+ this.rest();
68
+ }
69
+ leave() {
70
+ this.active -= 1;
71
+ if (this.active === 0)
72
+ this.arm();
73
+ }
74
+ arm() {
75
+ this.rest();
76
+ if (this.idleMs === undefined || this.done || this.active > 0)
77
+ return;
78
+ this.idle = setTimeout(() => {
79
+ this.stop(new OkmError("timeout", `The transaction sat idle for ${String(this.idleMs)} ms (timeouts.idleInTransaction).`, { kind: "timeout" }));
80
+ }, this.idleMs);
81
+ }
82
+ rest() {
83
+ if (this.idle !== undefined)
84
+ clearTimeout(this.idle);
85
+ this.idle = undefined;
86
+ }
87
+ note(error, whole) {
88
+ const kind = error?.kind;
89
+ if (!whole || kind === "cancelled" || kind === "timeout")
90
+ this.failed ??= error;
91
+ }
92
+ }
93
+ async function tx(session, args) {
94
+ if (typeof args[0] === "function" && args.length > 1) {
95
+ fail2("OKM1120", "options go first: tx(options, fn).");
96
+ }
97
+ const fn = typeof args[0] === "function" ? args[0] : args[1];
98
+ const given = typeof args[0] === "function" ? {} : args[0] ?? {};
99
+ try {
100
+ if (typeof fn !== "function")
101
+ fail2("OKM1121", "tx expects a callback: tx(fn) or tx(options, fn).");
102
+ if (!isRecord(given))
103
+ fail2("OKM1121", "tx options must be an object.");
104
+ rejectKeys(given, ["isolation", "retry", "signal", "timeout"], "tx");
105
+ const options = given;
106
+ check(options);
107
+ await refuseUncancellableTimeout(session.pool, options.timeout);
108
+ const call = fn;
109
+ return session.tx === undefined ? await outer(session, call, options) : await nested(session, call, options);
110
+ } catch (error) {
111
+ return failWith(session, error);
112
+ }
113
+ }
114
+ function failWith(session, error) {
115
+ if (error instanceof OkmError || !(error instanceof Error) || error.name !== "DriverError") {
116
+ return Promise.reject(error);
117
+ }
118
+ return settleCall(session, error);
119
+ }
120
+ function check(options) {
121
+ if (options.isolation !== undefined && !Object.hasOwn(BEGIN, options.isolation)) {
122
+ fail2("OKM1120", `isolation must be one of: ${Object.keys(BEGIN).join(", ")}.`);
123
+ }
124
+ const { retry, timeout } = options;
125
+ if (retry !== undefined && (!Number.isInteger(retry) || retry < 0)) {
126
+ fail2("OKM1121", "retry must be an integer from 0 up.");
127
+ }
128
+ if (timeout !== undefined && (typeof timeout !== "number" || !(timeout > 0))) {
129
+ fail2("OKM1121", "timeout must be a number of milliseconds above 0.");
130
+ }
131
+ }
132
+ async function outer(session, fn, options) {
133
+ const pool = session.pool;
134
+ if (pool.reserve === undefined || pool.capabilities.transactions !== "interactive") {
135
+ throw new OkmError("OKM1111", `tx() needs a driver with transactions: "interactive". This driver has "${pool.capabilities.transactions}".`, withHttp(session.http, {
136
+ fix: { summary: "Use batch() for an atomic unit on this driver." }
137
+ }));
138
+ }
139
+ await session.connected;
140
+ const started = Date.now();
141
+ const limit = options.timeout ?? session.timeouts?.transaction;
142
+ const deadline = limit === undefined ? undefined : started + limit;
143
+ const retries = options.retry ?? 0;
144
+ for (let attempt = 0;; attempt += 1) {
145
+ try {
146
+ return await once(session, fn, options, deadline);
147
+ } catch (error) {
148
+ const kind = error instanceof OkmError ? error.kind : undefined;
149
+ if (attempt >= retries || kind !== "serialization" && kind !== "deadlock")
150
+ throw error;
151
+ await pause(attempt);
152
+ if (options.signal?.aborted === true)
153
+ throw cancelled();
154
+ if (deadline !== undefined && Date.now() >= deadline)
155
+ throw timedOut();
156
+ }
157
+ }
158
+ }
159
+ function pause(attempt) {
160
+ const ms = Math.random() * Math.min(100, 4 * 2 ** attempt);
161
+ return new Promise((resolve) => setTimeout(resolve, ms));
162
+ }
163
+ function cancelled() {
164
+ return new OkmError("cancelled", "The transaction was cancelled.", { kind: "cancelled" });
165
+ }
166
+ function timedOut() {
167
+ return new OkmError("timeout", "The transaction timed out.", { kind: "timeout" });
168
+ }
169
+ async function once(session, fn, options, deadline) {
170
+ const signal = options.signal;
171
+ if (signal?.aborted === true)
172
+ throw cancelled();
173
+ if (deadline !== undefined && Date.now() >= deadline)
174
+ throw timedOut();
175
+ const conn = await reserve(session);
176
+ const frame = new Frame(conn, session.timeouts?.idleInTransaction, signal !== undefined || deadline !== undefined);
177
+ const after = [];
178
+ const hear = session.hookm === undefined ? undefined : await import("./96ps4g1z.js");
179
+ const onAbort = () => frame.stop(cancelled());
180
+ signal?.addEventListener("abort", onAbort, { once: true });
181
+ const timer = deadline === undefined ? undefined : setTimeout(() => frame.stop(timedOut()), deadline - Date.now());
182
+ let began = false;
183
+ let committing = false;
184
+ let committed = false;
185
+ try {
186
+ await step(session, frame, options.isolation === undefined ? "BEGIN" : BEGIN[options.isolation]);
187
+ began = true;
188
+ hear?.phase(session.hookm, "start", 0);
189
+ frame.arm();
190
+ const t = openClient(held(session, frame, after, 0));
191
+ const value = await Promise.race([fn(t), frame.halt]);
192
+ frame.check();
193
+ if (frame.failed !== undefined)
194
+ throw frame.failed;
195
+ frame.rest();
196
+ committing = true;
197
+ await commit(session, frame);
198
+ committed = true;
199
+ return value;
200
+ } catch (error) {
201
+ if (began && !committed) {
202
+ if (!committing)
203
+ await frame.conn.execute("ROLLBACK").catch(() => {
204
+ return;
205
+ });
206
+ if (!(error instanceof OkmError && error.kind === "outcome_unknown")) {
207
+ hear?.phase(session.hookm, "rollback", 0);
208
+ }
209
+ }
210
+ return await failWith(session, error);
211
+ } finally {
212
+ frame.rest();
213
+ frame.done = true;
214
+ if (timer !== undefined)
215
+ clearTimeout(timer);
216
+ signal?.removeEventListener("abort", onAbort);
217
+ try {
218
+ await conn.release();
219
+ } catch (error) {
220
+ hear?.report(session, error);
221
+ }
222
+ if (committed) {
223
+ hear?.phase(session.hookm, "commit", 0);
224
+ await run(session, after, hear);
225
+ }
226
+ }
227
+ }
228
+ async function reserve(session) {
229
+ try {
230
+ return await session.pool.reserve();
231
+ } catch (error) {
232
+ return failWith(session, error);
233
+ }
234
+ }
235
+ function step(session, frame, text) {
236
+ return frame.conn.execute(text).catch((error) => failWith(session, error));
237
+ }
238
+ async function commit(session, frame) {
239
+ try {
240
+ await frame.conn.execute("COMMIT");
241
+ } catch (error) {
242
+ if (isConnectionLost(error)) {
243
+ throw new OkmError("OKM1401", "The commit was sent and its result never arrived. The transaction may or may not have committed.", withHttp(session.http, {
244
+ kind: "outcome_unknown",
245
+ cause: error,
246
+ fix: {
247
+ summary: "Check whether the write landed, using an idempotency key, before retrying."
248
+ }
249
+ }));
250
+ }
251
+ throw error;
252
+ }
253
+ }
254
+ async function run(session, after, hear) {
255
+ for (const callback of after) {
256
+ try {
257
+ await callback();
258
+ } catch (error) {
259
+ if (hear !== undefined)
260
+ hear.report(session, error);
261
+ else
262
+ (await import("./96ps4g1z.js")).report(session, error);
263
+ }
264
+ }
265
+ }
266
+ async function nested(session, fn, options) {
267
+ if (Object.keys(options).length > 0) {
268
+ fail2("OKM1121", "isolation, retry, timeout, and signal belong to the outermost tx(). A nested tx() is a savepoint on the same transaction.");
269
+ }
270
+ const { state: frame, depth } = session.tx;
271
+ frame.check();
272
+ frame.savepoints += 1;
273
+ const name = `okm_t${String(frame.savepoints)}`;
274
+ const hear = session.hookm === undefined ? undefined : await import("./96ps4g1z.js");
275
+ const saved = frame.failed;
276
+ const after = [];
277
+ let released = false;
278
+ const hooks = session.pool;
279
+ const pending = hooks.okmScopePending?.();
280
+ if (pending !== undefined)
281
+ await pending;
282
+ try {
283
+ await step(session, frame, `SAVEPOINT ${name}`);
284
+ hear?.phase(session.hookm, "start", depth + 1);
285
+ const t = openClient(held(session, frame, after, depth + 1));
286
+ const value = await Promise.race([fn(t), frame.halt]);
287
+ frame.check();
288
+ if (frame.failed !== saved)
289
+ throw frame.failed;
290
+ await step(session, frame, `RELEASE SAVEPOINT ${name}`);
291
+ released = true;
292
+ hear?.phase(session.hookm, "commit", depth + 1);
293
+ session.tx.after.push(...after);
294
+ return value;
295
+ } catch (error) {
296
+ if (!released && frame.stopped === undefined) {
297
+ await frame.conn.execute(`ROLLBACK TO SAVEPOINT ${name}`).catch(() => {
298
+ return;
299
+ });
300
+ hooks.okmForgetScope?.();
301
+ frame.failed = saved;
302
+ hear?.phase(session.hookm, "rollback", depth + 1);
303
+ }
304
+ return await failWith(session, error);
305
+ }
306
+ }
307
+ function held(session, frame, after, depth) {
308
+ const base = session.pool;
309
+ const guarded = async (run, whole) => {
310
+ frame.check();
311
+ frame.enter();
312
+ try {
313
+ return await run();
314
+ } catch (error) {
315
+ frame.note(error, whole);
316
+ throw error;
317
+ } finally {
318
+ frame.leave();
319
+ }
320
+ };
321
+ const pool = depth === 0 ? {
322
+ capabilities: base.capabilities,
323
+ execute: (text, params, options) => {
324
+ if (options?.route === "replica")
325
+ replicaInside();
326
+ return guarded(() => frame.conn.execute(text, params, stoppable(frame, options)), false);
327
+ },
328
+ batch: (statements, options) => {
329
+ if (options?.route === "replica")
330
+ replicaInside();
331
+ return guarded(() => frame.conn.batch(statements, stoppable(frame, options)), true);
332
+ },
333
+ stats: () => base.stats(),
334
+ close: () => Promise.resolve()
335
+ } : base;
336
+ const next = {
337
+ ...session,
338
+ pool,
339
+ tx: {
340
+ depth,
341
+ state: frame,
342
+ after,
343
+ extras: {
344
+ afterCommit(callback) {
345
+ if (typeof callback !== "function") {
346
+ fail2("OKM1121", "afterCommit expects a function.");
347
+ }
348
+ frame.check();
349
+ after.push(callback);
350
+ },
351
+ async advisoryLock(key, options) {
352
+ const [text, wire] = lockKey(key);
353
+ try {
354
+ await pool.execute(text, [wire], callOf(options));
355
+ } catch (error) {
356
+ await failWith(next, error);
357
+ }
358
+ }
359
+ }
360
+ }
361
+ };
362
+ return next;
363
+ }
364
+ function stoppable(frame, options) {
365
+ const own = frame.signal;
366
+ if (own === undefined)
367
+ return options;
368
+ return {
369
+ ...options,
370
+ signal: options?.signal === undefined ? own : AbortSignal.any([options.signal, own])
371
+ };
372
+ }
373
+ function lockKey(key) {
374
+ if (typeof key === "string") {
375
+ return ["select pg_advisory_xact_lock(hashtextextended($1, 0))", key];
376
+ }
377
+ const fits = typeof key === "number" ? Number.isSafeInteger(key) : typeof key === "bigint" && key >= -(2n ** 63n) && key < 2n ** 63n;
378
+ if (!fits)
379
+ fail2("OKM1121", "advisoryLock takes a string, a safe integer, or a bigint that fits in 64 bits.");
380
+ return ["select pg_advisory_xact_lock($1::bigint)", String(key)];
381
+ }
382
+ function callOf(options) {
383
+ if (options?.signal === undefined && options?.timeout === undefined && options?.route === undefined) {
384
+ return;
385
+ }
386
+ return {
387
+ ...options?.signal !== undefined ? { signal: options.signal } : {},
388
+ ...options?.timeout !== undefined ? { timeout: options.timeout } : {},
389
+ ...options?.route !== undefined ? { route: options.route } : {}
390
+ };
391
+ }
392
+ function replicaInside() {
393
+ throw new OkmError("OKM1840", "This operation needs the primary.", {
394
+ fix: {
395
+ summary: "Run the operation on the primary. Writes, batch, locks, and tx() never go to a replica."
396
+ }
397
+ });
398
+ }
399
+ export {
400
+ tx
401
+ };
@@ -0,0 +1,250 @@
1
+ import {
2
+ stack2
3
+ } from "./35zemrmf.js";
4
+ import {
5
+ updateSliceBody2,
6
+ rejectDuplicateTargets2,
7
+ emitSet2,
8
+ Sql2,
9
+ writeSet2,
10
+ rejectMixedSets2,
11
+ readClaim2,
12
+ rejectUpdateKeys2,
13
+ requireFilter2,
14
+ returningOption2,
15
+ expectOf2,
16
+ allowSet2,
17
+ noteGuarded2
18
+ } from "./ezqn88nj.js";
19
+ import"./w5d89rb4.js";
20
+ import {
21
+ emitWhere,
22
+ projectExpr,
23
+ quote,
24
+ isRecord,
25
+ fail2
26
+ } from "./hfq3n3bd.js";
27
+
28
+ // src/runtime/version.ts
29
+ function planVersioned(schema, table, input, options, mods) {
30
+ if (mods.all !== undefined) {
31
+ fail2("OKM1120", `update on ${table.model.name} cannot use .all() with versioned().`, "Pass a per-row list with the version you read for each row.");
32
+ }
33
+ const allow = allowSet2(table, options.allow);
34
+ noteGuarded2(table, allow, "update");
35
+ const column = versionColumn(table);
36
+ const returning = returningOption2(table, options.returning);
37
+ const expect = expectOf2(options, mods);
38
+ if (Array.isArray(input) && input.length === 0) {
39
+ return {
40
+ statements: [],
41
+ outputs: outputsOf(undefined),
42
+ shape: "count",
43
+ expect,
44
+ versioned: { fields: [], sent: [] }
45
+ };
46
+ }
47
+ const rows = readRows(schema, table, input, allow, mods, column);
48
+ const fields = writtenFields(rows);
49
+ const sent = rows.map((row) => row.version);
50
+ const claim = Array.isArray(input) ? undefined : isRecord(input) ? readClaim2(input) : undefined;
51
+ const statement = claim !== undefined ? claimStatement(schema, table, rows[0], claim, column, returning) : targetStatement(schema, table, rows, column, returning);
52
+ const width = statement.params?.length ?? 0;
53
+ if (width > 30000) {
54
+ fail2("OKM1120", `update on ${table.model.name} is too large to check version in one statement.`, "Split the list.");
55
+ }
56
+ return {
57
+ statements: [statement],
58
+ outputs: outputsOf(returning),
59
+ shape: returning === undefined ? "count" : "rows",
60
+ expect,
61
+ versioned: { fields, sent }
62
+ };
63
+ }
64
+ function versionColumn(table) {
65
+ const column = table.columns.get("version");
66
+ if (column === undefined) {
67
+ fail2("OKM1120", `Table ${table.model.name} is versioned and has no version column.`);
68
+ }
69
+ return column;
70
+ }
71
+ function readRows(schema, table, input, allow, mods, column) {
72
+ if (Array.isArray(input)) {
73
+ if (input.length === 0)
74
+ fail2("OKM1120", "update set is empty.");
75
+ const rows = input.map((item) => readRow(schema, table, item, allow, mods, column, true));
76
+ rejectDuplicateTargets2(table, rows);
77
+ rejectMixedSets2(rows);
78
+ return rows;
79
+ }
80
+ return [readRow(schema, table, input, allow, mods, column, false)];
81
+ }
82
+ function readRow(schema, table, input, allow, mods, column, row) {
83
+ if (!isRecord(input))
84
+ fail2("OKM1121", "update expects { where, set, version } or a list of rows.");
85
+ rejectUpdateKeys2(input, row);
86
+ if (!Object.hasOwn(input, "version")) {
87
+ fail2("OKM1120", `update on ${table.model.name} needs the version you read.`, "Pass version from the row you read. If this write conflicts, reread and retry.");
88
+ }
89
+ const version = readVersion(input.version, table.model.name, column);
90
+ const set = writeSet2(table, input.set, allow, schema.tenancy);
91
+ if (Object.keys(set).length === 0)
92
+ fail2("OKM1120", "update set is empty.");
93
+ refusePath(schema, table, set);
94
+ const where = input.where !== undefined ? input.where : input.id !== undefined ? { id: input.id } : undefined;
95
+ requireFilter2(table, where, mods, "update");
96
+ return { where: stack2(where, mods.presets), set, version };
97
+ }
98
+ function readVersion(value, table, column) {
99
+ if (typeof value !== "number" || !Number.isSafeInteger(value)) {
100
+ fail2("OKM1121", `version on ${table} must be an integer.`, "Pass the version you read.");
101
+ }
102
+ column.encode(value);
103
+ return value;
104
+ }
105
+ function refusePath(schema, table, set) {
106
+ if (schema.tenancy?.isPath?.(table.model.name) !== true)
107
+ return;
108
+ const field = schema.tenancy.pathOf?.(table.model.name)?.[0]?.localField;
109
+ if (field === undefined || !Object.hasOwn(set, field))
110
+ return;
111
+ fail2("OKM1120", `update on ${table.model.name} cannot change ${field} and check version in one write.`, "Point it at a parent in a later update.");
112
+ }
113
+ function writtenFields(rows) {
114
+ const names = [];
115
+ for (const row of rows) {
116
+ for (const key of Object.keys(row.set))
117
+ if (!names.includes(key))
118
+ names.push(key);
119
+ }
120
+ return names;
121
+ }
122
+ function targetStatement(schema, table, rows, column, returning) {
123
+ const sql = new Sql2;
124
+ sql.text("with ");
125
+ for (let index = 0;index < rows.length; index += 1) {
126
+ const row = rows[index];
127
+ if (row === undefined)
128
+ continue;
129
+ if (index > 0)
130
+ sql.text(", ");
131
+ sql.text("m");
132
+ sql.text(String(index));
133
+ sql.text(" as (select s.ctid as tid, s.tableoid as toid, s.");
134
+ sql.text(quote(column.sql));
135
+ sql.text(" as okm_version from ");
136
+ sql.text(quote(table.model.sql));
137
+ sql.text(" as s");
138
+ emitWhere(schema, table, row.where, sql.sink(), "s", 0);
139
+ sql.text(" for update of s)");
140
+ }
141
+ sql.text(", gate as (select count(*)::int as n from (");
142
+ for (let index = 0;index < rows.length; index += 1) {
143
+ const row = rows[index];
144
+ if (row === undefined)
145
+ continue;
146
+ if (index > 0)
147
+ sql.text(" union all ");
148
+ sql.text("select 1 from m");
149
+ sql.text(String(index));
150
+ sql.text(" where okm_version is distinct from ");
151
+ sql.param(column.encode(row.version), column.dataType);
152
+ }
153
+ sql.text(") as okm_diff), updated as (");
154
+ updateSliceBody2(schema, table, rows, sql, true, {
155
+ afterWhere(body, index) {
156
+ const row = rows[index];
157
+ if (row === undefined)
158
+ return;
159
+ body.text(" and t.");
160
+ body.text(quote(column.sql));
161
+ body.text(" = ");
162
+ body.param(column.encode(row.version), column.dataType);
163
+ },
164
+ afterSet(body) {
165
+ bump(body, column);
166
+ }
167
+ });
168
+ sql.text(" and (select n from gate) = 0");
169
+ closeUpdated(sql, returning, "gate");
170
+ return sql.statement();
171
+ }
172
+ function claimStatement(schema, table, row, limit, column, returning) {
173
+ if (row === undefined)
174
+ fail2("OKM1120", "update set is empty.");
175
+ const sql = new Sql2;
176
+ sql.text("with claimed as (select s.tableoid as toid, s.ctid as tid from ");
177
+ sql.text(quote(table.model.sql));
178
+ sql.text(" as s");
179
+ emitWhere(schema, table, row.where, sql.sink(), "s", 0);
180
+ sql.text(" and s.");
181
+ sql.text(quote(column.sql));
182
+ sql.text(" = ");
183
+ sql.param(column.encode(row.version), column.dataType);
184
+ sql.text(" for update of s skip locked limit ");
185
+ sql.param(String(limit), "integer");
186
+ sql.text("), stale_free as (select 1 as hit from ");
187
+ sql.text(quote(table.model.sql));
188
+ sql.text(" as s");
189
+ emitWhere(schema, table, row.where, sql.sink(), "s", 0);
190
+ sql.text(" and s.");
191
+ sql.text(quote(column.sql));
192
+ sql.text(" is distinct from ");
193
+ sql.param(column.encode(row.version), column.dataType);
194
+ sql.text(" for update of s skip locked limit 1), updated as (update ");
195
+ sql.text(quote(table.model.sql));
196
+ sql.text(" as t set ");
197
+ emitSet2(sql, table, row.set, "t");
198
+ bump(sql, column);
199
+ sql.text(" where (t.tableoid, t.ctid) in (select toid, tid from claimed)");
200
+ closeUpdated(sql, returning, "claim");
201
+ return sql.statement();
202
+ }
203
+ function bump(sql, column) {
204
+ sql.text(", ");
205
+ sql.text(quote(column.sql));
206
+ sql.text(" = t.");
207
+ sql.text(quote(column.sql));
208
+ sql.text(" + 1");
209
+ }
210
+ function closeUpdated(sql, returning, source) {
211
+ const stale = source === "gate" ? "(select n from gate)" : "(case when (select count(*) from updated) > 0 then 0 else (select count(*)::int from stale_free) end)";
212
+ if (returning === undefined || returning.length === 0) {
213
+ sql.text(" returning 1) select ");
214
+ sql.text(stale);
215
+ sql.text(", (select count(*)::int from updated)");
216
+ return;
217
+ }
218
+ sql.text(" returning t.ctid as okm_tid");
219
+ for (let index = 0;index < returning.length; index += 1) {
220
+ const column = returning[index];
221
+ if (column === undefined)
222
+ continue;
223
+ sql.text(", ");
224
+ sql.text(projectExpr(`t.${quote(column.sql)}`, column.dataType));
225
+ sql.text(" as okm_");
226
+ sql.text(String(index));
227
+ }
228
+ sql.text(") select ");
229
+ sql.text(stale);
230
+ sql.text(", case when u.okm_tid is null then 0 else 1 end");
231
+ for (let index = 0;index < returning.length; index += 1) {
232
+ sql.text(", u.okm_");
233
+ sql.text(String(index));
234
+ }
235
+ sql.text(" from (select 1) as okm_one left join updated u on true");
236
+ }
237
+ function outputsOf(columns) {
238
+ const list = columns ?? [];
239
+ return {
240
+ fields: list.map((column, index) => ({
241
+ key: column.field,
242
+ at: index + 2,
243
+ decode: column.decode
244
+ })),
245
+ includes: []
246
+ };
247
+ }
248
+ export {
249
+ planVersioned
250
+ };