okmodel 0.6.0 → 0.8.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 (267) hide show
  1. package/README.md +100 -1131
  2. package/dist/adapters/capabilities.d.ts +35 -0
  3. package/dist/adapters/failure.d.ts +13 -2
  4. package/dist/adapters/lazy-errors.d.ts +22 -0
  5. package/dist/adapters/pg/bun-sql.d.ts +53 -0
  6. package/dist/adapters/pg/bunsql-extra.d.ts +54 -3
  7. package/dist/adapters/pg/bunsql.d.ts +15 -2
  8. package/dist/adapters/pg/cursor.d.ts +17 -0
  9. package/dist/adapters/pg/neon-extra.d.ts +18 -0
  10. package/dist/adapters/pg/neon.d.ts +104 -0
  11. package/dist/adapters/pg/no-inflight-timeout.d.ts +11 -8
  12. package/dist/adapters/pg/nodepostgres-extra.d.ts +22 -1
  13. package/dist/adapters/pg/nodepostgres.d.ts +12 -0
  14. package/dist/adapters/pg/pglite-wire.d.ts +24 -0
  15. package/dist/adapters/pg/pglite.d.ts +10 -0
  16. package/dist/adapters/pg/postgres-extra.d.ts +27 -11
  17. package/dist/adapters/pg/reserved.d.ts +42 -0
  18. package/dist/adapters/pg/session.d.ts +0 -18
  19. package/dist/contracts/connection.d.ts +7 -6
  20. package/dist/contracts/error.d.ts +1 -1
  21. package/dist/dialects/pg/floor.d.ts +68 -0
  22. package/dist/dialects/pg/fn/index.d.ts +39 -1
  23. package/dist/dialects/pg/fn/index.js +118 -26
  24. package/dist/dialects/pg/index.d.ts +8 -1
  25. package/dist/dialects/pg/index.js +435 -170
  26. package/dist/dialects/pg/introspect.d.ts +11 -0
  27. package/dist/dialects/pg/keys.d.ts +11 -8
  28. package/dist/dialects/pg/model.d.ts +40 -0
  29. package/dist/dialects/pg/morph.d.ts +43 -0
  30. package/dist/dialects/pg/operator-fit.d.ts +2 -2
  31. package/dist/dialects/pg/operators.d.ts +14 -7
  32. package/dist/dialects/pg/ops/bucket.d.ts +65 -0
  33. package/dist/dialects/pg/ops/fragment.d.ts +119 -0
  34. package/dist/dialects/pg/ops/inc.d.ts +2 -2
  35. package/dist/dialects/pg/ops/lane.d.ts +49 -0
  36. package/dist/dialects/pg/ops/matches.d.ts +9 -12
  37. package/dist/dialects/pg/ops/relevance.d.ts +13 -0
  38. package/dist/dialects/pg/ops/search-query.d.ts +22 -0
  39. package/dist/dialects/pg/ops/window.d.ts +103 -0
  40. package/dist/dialects/pg/preset.d.ts +1 -1
  41. package/dist/dialects/pg/relations.d.ts +100 -3
  42. package/dist/dialects/pg/schema.d.ts +31 -3
  43. package/dist/dialects/pg/view/client.d.ts +14 -6
  44. package/dist/dialects/pg/view/index.d.ts +73 -1
  45. package/dist/dialects/pg/view/index.js +156 -5
  46. package/dist/dialects/pg/view/scratch.d.ts +8 -5
  47. package/dist/runtime/aggregate.d.ts +8 -2
  48. package/dist/runtime/bucket-group.d.ts +70 -0
  49. package/dist/runtime/conflict.d.ts +22 -4
  50. package/dist/runtime/include.d.ts +0 -8
  51. package/dist/runtime/inflight.d.ts +1 -1
  52. package/dist/runtime/otel.d.ts +105 -0
  53. package/dist/runtime/otel.js +97 -0
  54. package/dist/runtime/page.d.ts +4 -1
  55. package/dist/runtime/pg/bun.js +12 -6
  56. package/dist/runtime/pg/neon.d.ts +38 -0
  57. package/dist/runtime/pg/neon.js +64 -0
  58. package/dist/runtime/pg/pg.js +5 -5
  59. package/dist/runtime/pg/pglite.d.ts +1 -0
  60. package/dist/runtime/pg/pglite.js +9 -9
  61. package/dist/runtime/pg/postgresjs.js +5 -5
  62. package/dist/runtime/plan.d.ts +95 -5
  63. package/dist/runtime/read-stream.d.ts +13 -16
  64. package/dist/runtime/result-name.d.ts +17 -0
  65. package/dist/runtime/server-check.d.ts +3 -3
  66. package/dist/runtime/sort-bind.d.ts +21 -0
  67. package/dist/runtime/sort.d.ts +56 -0
  68. package/dist/runtime/sql-fragment.d.ts +43 -0
  69. package/dist/runtime/sync.d.ts +70 -0
  70. package/dist/runtime/tenancy/index.js +15 -13
  71. package/dist/runtime/text-search.d.ts +20 -0
  72. package/dist/runtime/topology.d.ts +1 -1
  73. package/dist/runtime/traits/index.d.ts +80 -0
  74. package/dist/runtime/traits/index.js +184 -21
  75. package/dist/runtime/tree.d.ts +38 -0
  76. package/dist/runtime/types.d.ts +232 -22
  77. package/dist/runtime/validate/index.js +4 -4
  78. package/dist/runtime/version.d.ts +39 -0
  79. package/dist/runtime/window.d.ts +21 -0
  80. package/dist/runtime/write.d.ts +54 -2
  81. package/dist/shared/{929h19xp.js → 0wrea3jq.js} +141 -13
  82. package/dist/shared/{qq3899ht.js → 12z7aznj.js} +243 -14
  83. package/dist/shared/{1z04fa85.js → 14x60fbf.js} +12 -57
  84. package/dist/shared/{ek2wt2dz.js → 16kvjebh.js} +4 -4
  85. package/dist/shared/{wynzeggs.js → 195pzzzz.js} +8 -8
  86. package/dist/shared/1d9q9cv2.js +312 -0
  87. package/dist/shared/2c13q96h.js +18 -0
  88. package/dist/shared/{b4v57v3x.js → 2d3xq4ps.js} +2 -2
  89. package/dist/shared/{1f0xa3cb.js → 3449rcae.js} +5 -5
  90. package/dist/shared/{wkme6tep.js → 35q0n9tz.js} +8 -16
  91. package/dist/shared/3bb7wsqt.js +99 -0
  92. package/dist/shared/3t6kw83m.js +249 -0
  93. package/dist/shared/{5j36z8dn.js → 4m6hskg8.js} +39 -70
  94. package/dist/shared/{n076ydsc.js → 4vbf83xx.js} +69 -28
  95. package/dist/shared/{vmfkhszw.js → 63f4ksbz.js} +33 -26
  96. package/dist/shared/{c58secgj.js → 63qtkrca.js} +38 -4
  97. package/dist/shared/6m78c8ss.js +6 -0
  98. package/dist/shared/{x3jc53kg.js → 760ppr76.js} +15 -7
  99. package/dist/shared/7ghwamrf.js +40 -0
  100. package/dist/shared/7kms6fvj.js +20 -0
  101. package/dist/shared/7n7ddwt4.js +6 -0
  102. package/dist/shared/9a4ae4p8.js +31 -0
  103. package/dist/shared/{hazqqecq.js → 9dr2qnx7.js} +63 -34
  104. package/dist/shared/{h15jx9bc.js → 9dvh1dr6.js} +1 -1
  105. package/dist/shared/a62rb2da.js +13 -0
  106. package/dist/shared/{cgbamx3e.js → ae4j5f42.js} +23 -4
  107. package/dist/shared/agsfb86s.js +233 -0
  108. package/dist/shared/{8x72s86k.js → b6d6p0zc.js} +13 -7
  109. package/dist/shared/{ag4c7516.js → b76b8d95.js} +2 -2
  110. package/dist/shared/{j60w0dvr.js → bah9nbg3.js} +58 -38
  111. package/dist/shared/bnby0esn.js +10 -0
  112. package/dist/shared/bsek72fg.js +225 -0
  113. package/dist/shared/{2cg3wnxc.js → bxas03mq.js} +608 -141
  114. package/dist/shared/{31vm914h.js → cm3w0ywp.js} +15 -16
  115. package/dist/shared/{gwn6v667.js → cnkky55j.js} +25 -14
  116. package/dist/shared/{dk8v79p3.js → d5nmj7vv.js} +1 -1
  117. package/dist/shared/{ttmg09vd.js → dpc2r7rb.js} +8 -8
  118. package/dist/shared/dzj09cye.js +10 -0
  119. package/dist/shared/{sbdme3vy.js → e8zyaqvj.js} +60 -10
  120. package/dist/shared/{2jd1sn0e.js → ecn8mfdq.js} +6 -6
  121. package/dist/shared/exn3sd90.js +359 -0
  122. package/dist/shared/{t3g0k88x.js → f4jy1j7x.js} +39 -22
  123. package/dist/shared/{y2t3jktd.js → fjpnhqan.js} +20 -13
  124. package/dist/shared/g5yc06ka.js +272 -0
  125. package/dist/shared/ga9j92qj.js +25 -0
  126. package/dist/shared/{3fqwmr09.js → hfqmpasr.js} +6 -6
  127. package/dist/shared/{wt5rzv1h.js → hm5f8jby.js} +7 -7
  128. package/dist/shared/{ys0xzyaj.js → hqpxf4a4.js} +224 -19
  129. package/dist/shared/jebgrkeq.js +179 -0
  130. package/dist/shared/{09p049xa.js → jp36k7dp.js} +44 -16
  131. package/dist/shared/jx2m62cs.js +96 -0
  132. package/dist/shared/{r11n8grd.js → k86n8vq3.js} +7 -4
  133. package/dist/shared/{2z7wv5tj.js → kgwp4jdd.js} +56 -35
  134. package/dist/shared/{knmes2kh.js → kj9d8maq.js} +1 -1
  135. package/dist/shared/{g90m9b0g.js → m4xff2a6.js} +6 -5
  136. package/dist/shared/{r6nwkxnt.js → m7n9h2a5.js} +4 -4
  137. package/dist/shared/mfedzr74.js +145 -0
  138. package/dist/shared/{f0f1n281.js → mkrn359n.js} +60 -11
  139. package/dist/shared/{p248q79y.js → mnvjvqyp.js} +10 -10
  140. package/dist/shared/{672t5vym.js → mss6ctgv.js} +2 -2
  141. package/dist/shared/{4az561fn.js → mtw6jz76.js} +8 -23
  142. package/dist/shared/n05z9nwz.js +313 -0
  143. package/dist/shared/{pjr6xrm5.js → n0jmpgj1.js} +20 -17
  144. package/dist/shared/{p6bjzq9q.js → n41w4fbz.js} +14 -6
  145. package/dist/shared/{b3awxn7h.js → n454kcnw.js} +1 -1
  146. package/dist/shared/n7kg8mmx.js +61 -0
  147. package/dist/shared/nbw1z4yd.js +18 -0
  148. package/dist/shared/needfe47.js +66 -0
  149. package/dist/shared/{1nw1f3vs.js → njga14v4.js} +9 -9
  150. package/dist/shared/{5yv4k6a6.js → nmnsgj7x.js} +145 -3
  151. package/dist/shared/{vjpnzwjz.js → p3xbdcvt.js} +14 -18
  152. package/dist/shared/p5nh3r8q.js +622 -0
  153. package/dist/shared/{nx9hh281.js → pan0370z.js} +13 -12
  154. package/dist/shared/q0cqt2sp.js +12 -0
  155. package/dist/shared/qd9hhd8f.js +37 -0
  156. package/dist/shared/{mb2ycs1p.js → qfw14tna.js} +15 -15
  157. package/dist/shared/{9s0ypp87.js → sjk86yrx.js} +1 -1
  158. package/dist/shared/th3be82n.js +208 -0
  159. package/dist/shared/{ed0b8k4s.js → typ3vy7t.js} +1 -1
  160. package/dist/shared/{5d8t84hg.js → v1wad97q.js} +14 -14
  161. package/dist/shared/{x72jb7ad.js → v8g1vgv8.js} +1 -1
  162. package/dist/shared/{9628a9xt.js → vk7rag46.js} +1 -1
  163. package/dist/shared/{ze4hxsmy.js → w9ejzaqf.js} +1 -1
  164. package/dist/shared/{q3j1tq7a.js → wcrheftc.js} +148 -23
  165. package/dist/shared/wvdjznah.js +213 -0
  166. package/dist/shared/wz2a78mp.js +8 -0
  167. package/dist/shared/xfhe73sb.js +436 -0
  168. package/dist/shared/{r1fdd0f6.js → z581d7ny.js} +5 -2
  169. package/dist/shared/{8etn7d8w.js → z7s6fpxv.js} +1 -1
  170. package/dist/shared/{32cnm7kn.js → zbqbmmrp.js} +76 -40
  171. package/dist/shared/{n7mcc1gk.js → zchaghkf.js} +4 -3
  172. package/dist/shared/{xq0mvhts.js → zgex00fd.js} +6 -6
  173. package/dist/shared/{nsva2a6b.js → znm0bpp5.js} +3 -0
  174. package/dist/shared/zq1he88x.js +155 -0
  175. package/dist/tooling/cli.js +26 -13
  176. package/dist/tooling/driver-run.js +4971 -0
  177. package/dist/tooling/driver-test.d.ts +36 -0
  178. package/dist/tooling/migrate/commands.d.ts +2 -2
  179. package/dist/tooling/migrate/engine.d.ts +3 -2
  180. package/dist/tooling/migrate/index.js +9 -9
  181. package/dist/tooling/migrate/project.d.ts +3 -0
  182. package/dist/tooling/shared/03k6res6.js +210 -0
  183. package/dist/tooling/shared/08kemxjd.js +10 -0
  184. package/dist/tooling/shared/2revefqt.js +209 -0
  185. package/dist/tooling/shared/2wtvc7rw.js +1425 -0
  186. package/dist/tooling/shared/345tbc2k.js +16 -0
  187. package/dist/tooling/shared/3m1hkg7z.js +344 -0
  188. package/dist/tooling/shared/3rrw5w8f.js +81 -0
  189. package/dist/tooling/shared/3tq8pnb8.js +131 -0
  190. package/dist/tooling/shared/417zdsk7.js +194 -0
  191. package/dist/tooling/shared/4d2w25vw.js +40 -0
  192. package/dist/tooling/shared/54tqkxja.js +51 -0
  193. package/dist/tooling/shared/5bvw2nev.js +12 -0
  194. package/dist/tooling/shared/6nyfyw70.js +231 -0
  195. package/dist/tooling/shared/72fyg4zv.js +160 -0
  196. package/dist/tooling/shared/733a1tq3.js +38 -0
  197. package/dist/tooling/shared/7ae7rjmn.js +20 -0
  198. package/dist/tooling/shared/7kms6fvj.js +20 -0
  199. package/dist/tooling/shared/8sqrsw3s.js +49 -0
  200. package/dist/tooling/shared/96ps4g1z.js +32 -0
  201. package/dist/tooling/shared/9kazs5p6.js +195 -0
  202. package/dist/tooling/shared/9xzm7hjg.js +38 -0
  203. package/dist/tooling/shared/a6pp9d12.js +49 -0
  204. package/dist/tooling/shared/a7q7t4n3.js +22 -0
  205. package/dist/tooling/shared/aftb2mwr.js +18 -0
  206. package/dist/tooling/shared/bz2dqhab.js +311 -0
  207. package/dist/tooling/shared/cmptmb4f.js +12 -0
  208. package/dist/tooling/shared/ddjtfgnx.js +177 -0
  209. package/dist/tooling/shared/djydjpqt.js +261 -0
  210. package/dist/tooling/shared/dw08f3m8.js +9 -0
  211. package/dist/tooling/shared/dy672fz6.js +16 -0
  212. package/dist/tooling/shared/dzx85q70.js +66 -0
  213. package/dist/tooling/shared/ec71zqgt.js +270 -0
  214. package/dist/{shared/d5azex6s.js → tooling/shared/ep8zh3bk.js} +1 -1
  215. package/dist/tooling/shared/f9mphxej.js +3789 -0
  216. package/dist/tooling/shared/fb9k2qwd.js +89 -0
  217. package/dist/tooling/shared/g9ad4n80.js +211 -0
  218. package/dist/tooling/shared/gfvtj6d0.js +94 -0
  219. package/dist/tooling/shared/gmcf9cxf.js +294 -0
  220. package/dist/tooling/shared/htnaj77v.js +17 -0
  221. package/dist/tooling/shared/j9t5s12a.js +7 -0
  222. package/dist/tooling/shared/jne7b93p.js +42 -0
  223. package/dist/tooling/shared/ma2340rx.js +118 -0
  224. package/dist/tooling/shared/mtrqn2hn.js +505 -0
  225. package/dist/tooling/shared/n4jqhpqz.js +27 -0
  226. package/dist/tooling/shared/nf7jmhfa.js +20 -0
  227. package/dist/tooling/shared/p7f08ktn.js +332 -0
  228. package/dist/tooling/shared/ppnnnvj8.js +13 -0
  229. package/dist/tooling/shared/pqy21k24.js +312 -0
  230. package/dist/tooling/shared/pw8fgahx.js +69 -0
  231. package/dist/tooling/shared/pwsytxm5.js +17 -0
  232. package/dist/tooling/shared/rf83gr2d.js +94 -0
  233. package/dist/tooling/shared/rq5kk8j6.js +401 -0
  234. package/dist/tooling/shared/rs1jb051.js +12 -0
  235. package/dist/tooling/shared/smn6kz1p.js +157 -0
  236. package/dist/tooling/shared/spk1jg3r.js +1696 -0
  237. package/dist/tooling/shared/tn8gay14.js +143 -0
  238. package/dist/tooling/shared/vraj6d74.js +42 -0
  239. package/dist/tooling/shared/vs0t6qt8.js +64 -0
  240. package/dist/tooling/shared/vx86qjv8.js +150 -0
  241. package/dist/tooling/shared/w7qe8sj1.js +140 -0
  242. package/dist/tooling/shared/wt7j7nf6.js +15 -0
  243. package/dist/tooling/shared/wwnekq5n.js +6 -0
  244. package/dist/tooling/shared/xhrnjch9.js +185 -0
  245. package/dist/tooling/shared/xjs6zqtc.js +190 -0
  246. package/dist/tooling/shared/y031jct9.js +16 -0
  247. package/dist/tooling/shared/y5656f0e.js +233 -0
  248. package/dist/tooling/shared/yfr8hzhm.js +604 -0
  249. package/dist/tooling/shared/yk9mp7vb.js +250 -0
  250. package/dist/tooling/shared/yw30vnq2.js +139 -0
  251. package/dist/tooling/shared/z8d7ptht.js +618 -0
  252. package/dist/tooling/shared/zhwnfyb2.js +9 -0
  253. package/dist/tooling/shared/zvnhh1n0.js +198 -0
  254. package/dist/tooling/testing/index.js +3 -3
  255. package/package.json +17 -3
  256. package/dist/shared/3qnhc7w5.js +0 -38
  257. package/dist/shared/7m88x3e9.js +0 -45
  258. package/dist/shared/8dqhth8c.js +0 -12
  259. package/dist/shared/j3rkk835.js +0 -99
  260. package/dist/shared/k68eedmy.js +0 -85
  261. package/dist/shared/venqrjna.js +0 -216
  262. package/dist/shared/wxr8cwns.js +0 -6
  263. package/dist/shared/y34a8714.js +0 -150
  264. package/dist/shared/zm0mafk4.js +0 -92
  265. package/dist/shared/zy8r7qvz.js +0 -116
  266. package/dist/shared/{ywr8hmey.js → 606g0nbf.js} +3 -3
  267. package/dist/shared/{rpycarcr.js → gcefca6p.js} +4 -4
@@ -0,0 +1,69 @@
1
+ import {
2
+ withHttp,
3
+ attachHttp
4
+ } from "./mtrqn2hn.js";
5
+ import {
6
+ OkmError,
7
+ POSTGRES_FLOOR,
8
+ isPostgresMajor,
9
+ parsePostgresFloor,
10
+ serverNeedsPostgres
11
+ } from "./f9mphxej.js";
12
+
13
+ // src/runtime/server-check.ts
14
+ var versionQuery = "select current_setting('server_version_num'), version(), (select (xpath('//catalog_hash/text()', query_to_xml('select catalog_hash from okm_meta where id = ''head''', true, false, '')))[1]::text where to_regclass('okm_meta') is not null)";
15
+ async function acceptServer(pool, schema, rows, http, requireMeta, options, source) {
16
+ for (const name in schema.model) {
17
+ if (schema.model[name]?.presets !== undefined) {
18
+ (await import("./ma2340rx.js")).checkSchema(schema);
19
+ break;
20
+ }
21
+ }
22
+ const version = rows[0]?.[1];
23
+ if (version === null || version === undefined || !version.startsWith("PostgreSQL")) {
24
+ throw new OkmError("OKM1801", "The server is not PostgreSQL. The schema dialect is postgres.", withHttp(http, {
25
+ fix: { summary: "Open the schema with the Postgres driver that matches it." }
26
+ }));
27
+ }
28
+ const recorded = rows[0]?.[2];
29
+ if (recorded === null || recorded === undefined || recorded.length === 0) {
30
+ if (requireMeta) {
31
+ throw new OkmError("OKM1520", "okm_meta has no catalog hash.", withHttp(http, {
32
+ fix: {
33
+ summary: "Apply migrations so okm_meta records the catalog, or omit requireMeta to adopt this database."
34
+ }
35
+ }));
36
+ }
37
+ } else {
38
+ const { assertCompatible } = await import("./fb9k2qwd.js");
39
+ try {
40
+ await assertCompatible(pool, schema, recorded, source, options);
41
+ } catch (error) {
42
+ if (error instanceof OkmError)
43
+ throw attachHttp(http, error);
44
+ throw error;
45
+ }
46
+ }
47
+ const major = Math.floor(Number(rows[0]?.[0] ?? "0") / 1e4);
48
+ const raw = schema.requires?.postgres;
49
+ if (raw === undefined) {
50
+ if (major < POSTGRES_FLOOR) {
51
+ throw new OkmError("OKM1803", serverNeedsPostgres(major, POSTGRES_FLOOR), withHttp(http, {
52
+ fix: {
53
+ summary: `Upgrade to PostgreSQL ${String(POSTGRES_FLOOR)} or higher.`
54
+ }
55
+ }));
56
+ }
57
+ return;
58
+ }
59
+ const need = parsePostgresFloor(raw);
60
+ if (!isPostgresMajor(need) || major < need) {
61
+ throw new OkmError("OKM1802", serverNeedsPostgres(major, isPostgresMajor(need) ? need : POSTGRES_FLOOR), withHttp(http, {
62
+ fix: { summary: "Upgrade the server, or lower minPostgres to a major the server meets." }
63
+ }));
64
+ }
65
+ }
66
+ export {
67
+ acceptServer,
68
+ versionQuery
69
+ };
@@ -0,0 +1,17 @@
1
+ import {
2
+ primaryUrl
3
+ } from "./f9mphxej.js";
4
+
5
+ // packages/harness/src/postgres.ts
6
+ import postgres from "postgres";
7
+ function openPostgres(url = primaryUrl()) {
8
+ return postgres(url, {
9
+ max: 1,
10
+ connect_timeout: 5,
11
+ idle_timeout: 1,
12
+ onnotice: () => {}
13
+ });
14
+ }
15
+ export {
16
+ openPostgres
17
+ };
@@ -0,0 +1,94 @@
1
+ import {
2
+ OkmError
3
+ } from "./f9mphxej.js";
4
+
5
+ // src/runtime/compat-words.ts
6
+ var BEHIND_EXPAND = "behind by expand";
7
+ var BEHIND_CONTRACT = "behind by contract";
8
+ var AHEAD_CONTRACT = "ahead by contract";
9
+
10
+ // src/runtime/drift-detail.ts
11
+ function driftVerdict(codeHash, recordedHash, migrations) {
12
+ const codeAt = indexOfHash(migrations, codeHash);
13
+ const recordedAt = indexOfHash(migrations, recordedHash);
14
+ if (codeAt >= 0 && recordedAt >= codeAt) {
15
+ for (let index = codeAt + 1;index <= recordedAt; index += 1) {
16
+ const migration = migrations[index];
17
+ if (migration !== undefined && migration.expand !== true) {
18
+ return { state: "ahead by contract", migrationId: migration.id };
19
+ }
20
+ }
21
+ return { state: "ok" };
22
+ }
23
+ if (codeAt >= 0 && recordedAt >= 0 && recordedAt < codeAt) {
24
+ const next = migrations[recordedAt + 1];
25
+ if (next !== undefined) {
26
+ return {
27
+ state: next.expand ? "behind by expand" : "behind by contract",
28
+ migrationId: next.id
29
+ };
30
+ }
31
+ }
32
+ if (recordedAt >= 0) {
33
+ const at = migrations[recordedAt];
34
+ if (at !== undefined)
35
+ return { state: "behind", migrationId: at.id };
36
+ }
37
+ const last = migrations.at(-1);
38
+ return { state: "behind", migrationId: last?.id ?? "" };
39
+ }
40
+ async function assertDrift(pool, codeHash, recordedHash, options) {
41
+ let rows;
42
+ try {
43
+ const result = await pool.execute("select migration_id, class, catalog_hash from okm_history order by migration_id, step_index", undefined, options);
44
+ rows = result.rows;
45
+ } catch (error) {
46
+ throw gapError({ state: "behind", migrationId: "" }, error);
47
+ }
48
+ const verdict = driftVerdict(codeHash, recordedHash, groupMigrations(rows));
49
+ if (verdict.state === "ok")
50
+ return;
51
+ throw gapError(verdict);
52
+ }
53
+ function indexOfHash(migrations, hash) {
54
+ let found = -1;
55
+ for (let index = 0;index < migrations.length; index += 1) {
56
+ if (migrations[index]?.catalogHash === hash)
57
+ found = index;
58
+ }
59
+ return found;
60
+ }
61
+ function groupMigrations(rows) {
62
+ const grouped = [];
63
+ for (const row of rows) {
64
+ const id = row[0];
65
+ const stepClass = row[1];
66
+ const hash = row[2];
67
+ if (id == null || stepClass == null || hash == null)
68
+ continue;
69
+ const expand = stepClass === "expand";
70
+ const last = grouped.at(-1);
71
+ if (last !== undefined && last.id === id) {
72
+ grouped[grouped.length - 1] = {
73
+ id,
74
+ catalogHash: hash,
75
+ expand: last.expand && expand
76
+ };
77
+ continue;
78
+ }
79
+ grouped.push({ id, catalogHash: hash, expand });
80
+ }
81
+ return grouped;
82
+ }
83
+ function gapError(verdict, cause) {
84
+ const named = verdict.migrationId;
85
+ const phrase = verdict.state === "ahead by contract" ? `${AHEAD_CONTRACT} migration ${named}` : verdict.state === "behind by expand" ? `${BEHIND_EXPAND} migration ${named}` : verdict.state === "behind by contract" ? `${BEHIND_CONTRACT} migration ${named}` : named.length > 0 ? `behind the app at migration ${named}` : "behind the app";
86
+ const fix = named.length > 0 ? `Apply ${named}, or change the deploy order.` : "Apply migrations, or change the deploy order.";
87
+ return new OkmError("OKM1520", `The database is ${phrase}.`, {
88
+ ...cause === undefined ? {} : { cause },
89
+ fix: { summary: fix }
90
+ });
91
+ }
92
+ export {
93
+ assertDrift
94
+ };
@@ -0,0 +1,401 @@
1
+ import {
2
+ refuseUncancellableTimeout
3
+ } from "./zhwnfyb2.js";
4
+ import {
5
+ openClient,
6
+ withHttp,
7
+ settleCall
8
+ } from "./mtrqn2hn.js";
9
+ import {
10
+ OkmError,
11
+ isConnectionLost,
12
+ rejectKeys,
13
+ isRecord,
14
+ fail2
15
+ } from "./f9mphxej.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,12 @@
1
+ import {
2
+ rejectUncancellable
3
+ } from "./xhrnjch9.js";
4
+
5
+ // src/adapters/pg/no-inflight-timeout.ts
6
+ function noTimeout(options) {
7
+ if ((options?.timeout ?? 0) <= 0)
8
+ return;
9
+ return rejectUncancellable();
10
+ }
11
+
12
+ export { noTimeout };