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
@@ -1,3 +1,7 @@
1
+ import"../../shared/12z7aznj.js";
2
+ import {
3
+ quoteIdent2
4
+ } from "../../shared/fk9vef30.js";
1
5
  import {
2
6
  searchValue
3
7
  } from "../../shared/dzj09cye.js";
@@ -11,7 +15,7 @@ import {
11
15
  jsonReplacer2,
12
16
  json2,
13
17
  jsonb2
14
- } from "../../shared/9628a9xt.js";
18
+ } from "../../shared/vk7rag46.js";
15
19
  import {
16
20
  bucket2
17
21
  } from "../../shared/nbw1z4yd.js";
@@ -36,13 +40,14 @@ import {
36
40
  time2,
37
41
  timetz2,
38
42
  interval2
39
- } from "../../shared/vqrjpcqn.js";
43
+ } from "../../shared/nmnsgj7x.js";
40
44
  import {
41
- schema2
42
- } from "../../shared/xnxsed62.js";
45
+ id2,
46
+ uuid2
47
+ } from "../../shared/ecn8mfdq.js";
43
48
  import {
44
- domainType
45
- } from "../../shared/ywspezzx.js";
49
+ schema2
50
+ } from "../../shared/9dr2qnx7.js";
46
51
  import {
47
52
  one2,
48
53
  many2,
@@ -51,10 +56,6 @@ import {
51
56
  morphMany2,
52
57
  morphTo2
53
58
  } from "../../shared/exn3sd90.js";
54
- import {
55
- id2,
56
- uuid2
57
- } from "../../shared/hyh73qk6.js";
58
59
  import {
59
60
  text2,
60
61
  varchar2,
@@ -62,17 +63,25 @@ import {
62
63
  citext2,
63
64
  encodeText,
64
65
  decodeText
65
- } from "../../shared/ed0b8k4s.js";
66
+ } from "../../shared/typ3vy7t.js";
66
67
  import {
67
68
  table2,
68
69
  index2,
69
70
  sql2
70
- } from "../../shared/rpycarcr.js";
71
+ } from "../../shared/gcefca6p.js";
71
72
  import {
72
73
  ColumnBuilder2,
73
74
  required,
74
75
  formatType
75
- } from "../../shared/ywr8hmey.js";
76
+ } from "../../shared/606g0nbf.js";
77
+ import {
78
+ isFragmentParts,
79
+ fragment2,
80
+ ident2
81
+ } from "../../shared/bsek72fg.js";
82
+ import {
83
+ domainType
84
+ } from "../../shared/ywspezzx.js";
76
85
  import {
77
86
  definition,
78
87
  rejected
@@ -82,11 +91,15 @@ import {
82
91
  compareText
83
92
  } from "../../shared/358zsv4r.js";
84
93
  import {
94
+ isOperator,
95
+ operatorName,
96
+ operatorValue,
85
97
  tag
86
98
  } from "../../shared/cn0n68ft.js";
87
99
  import {
88
100
  OkmError2,
89
- catalogError2
101
+ catalogError2,
102
+ throwNamed2
90
103
  } from "../../shared/52szzakm.js";
91
104
  var __defProp = Object.defineProperty;
92
105
  var __returnValue = (v) => v;
@@ -102,6 +115,10 @@ var __export = (target, all) => {
102
115
  set: __exportSetter.bind(all, name)
103
116
  });
104
117
  };
118
+ // src/dialects/pg/external.ts
119
+ function external(table) {
120
+ return withOwner2(table, "external");
121
+ }
105
122
  // src/dialects/pg/custom.ts
106
123
  function custom(spec) {
107
124
  if (spec.sqlType.length === 0) {
@@ -815,6 +832,364 @@ function path(segments, op) {
815
832
  function startsWith(value) {
816
833
  return tag("startsWith", value);
817
834
  }
835
+ // src/dialects/pg/ops/lane.ts
836
+ var LANE = Symbol.for("okm.lane");
837
+ var READ = "read";
838
+ var WRITE = "write";
839
+ var BLOCKED = new Set(["__proto__", "constructor", "toString", "hasOwnProperty"]);
840
+ async function raw(handle, cls, statement, source) {
841
+ const lane = readLane(handle);
842
+ const kind = readClass(statement);
843
+ const indexed = openTable(lane);
844
+ const parts = readParts(source);
845
+ const compiled = compile(indexed, parts);
846
+ const word = verb(compiled.text);
847
+ if (kind === READ && word !== "select") {
848
+ bad("A raw read starts with select.", 'Pass "read" and a single select. A leading with is a write.');
849
+ }
850
+ if (kind === WRITE && word !== "insert" && word !== "update" && word !== "delete") {
851
+ bad("A raw write starts with insert, update, or delete.", 'Pass "write" and one insert, update, or delete.');
852
+ }
853
+ const tenancy = predicateOf(lane.session, indexed);
854
+ if (kind === WRITE && tenancy !== undefined) {
855
+ unverifiable("A raw write on a tenant table cannot keep the tenant predicate.", 'Use update or delete. unscoped("reason") is the reviewed hatch.');
856
+ }
857
+ const guard = kind === READ ? guardOf(indexed, tenancy, compiled.params.length) : undefined;
858
+ if (guard !== undefined)
859
+ requireKey(indexed, lane.session.schema.tenancy?.key, parts);
860
+ const text = guard === undefined ? compiled.text : wrap(indexed, lane.session.schema.tenancy?.key, compiled.text, guard.text);
861
+ const params = guard === undefined ? compiled.params : [...compiled.params, ...guard.params];
862
+ await lane.session.connected;
863
+ try {
864
+ const result = await lane.session.pool.execute(text, params, kind === WRITE ? { route: "primary" } : undefined);
865
+ return decodeRows(cls, result.rows, indexed);
866
+ } catch (error) {
867
+ return raise(lane, error);
868
+ }
869
+ }
870
+ async function explain(handle, query) {
871
+ const lane = readLane(handle);
872
+ const got = readPlanned(await readSql(query));
873
+ if (production())
874
+ return { text: got.text, params: [], plan: null };
875
+ await lane.session.connected;
876
+ let rows;
877
+ try {
878
+ const result = await lane.session.pool.execute(`explain ${got.text}`, got.params);
879
+ rows = result.rows;
880
+ } catch (error) {
881
+ return raise(lane, error);
882
+ }
883
+ const plan = [];
884
+ for (const row of rows) {
885
+ const line = row[0];
886
+ if (typeof line === "string")
887
+ plan.push(line);
888
+ }
889
+ return { text: got.text, params: got.params, plan };
890
+ }
891
+ async function raise(lane, error) {
892
+ const mapped = await lane.fail(lane.session, error);
893
+ lane.session.logger?.error?.({ code: mapped.code, summary: mapped.summary });
894
+ throw mapped;
895
+ }
896
+ function production() {
897
+ const proc = Reflect.get(globalThis, "process");
898
+ if (typeof proc !== "object" || proc === null)
899
+ return false;
900
+ const env = Reflect.get(proc, "env");
901
+ if (typeof env !== "object" || env === null)
902
+ return false;
903
+ return Reflect.get(env, "NODE_ENV") === "production";
904
+ }
905
+ function readLane(handle) {
906
+ const value = Reflect.get(handle, LANE);
907
+ if (!Array.isArray(value)) {
908
+ bad("Pass the table handle.", "raw and explain take the table, such as db.notes, including a table from for().");
909
+ }
910
+ const session = value[0];
911
+ const table = value[1];
912
+ const fail = value[2];
913
+ if (typeof table !== "string" || typeof fail !== "function" || !isSession(session)) {
914
+ bad("Pass the table handle.", "raw and explain take the table, such as db.notes, including a table from for().");
915
+ }
916
+ return { session, table, fail };
917
+ }
918
+ function isSession(value) {
919
+ if (typeof value !== "object" || value === null)
920
+ return false;
921
+ const schema = Reflect.get(value, "schema");
922
+ const connected = Reflect.get(value, "connected");
923
+ const pool = Reflect.get(value, "pool");
924
+ if (typeof schema !== "object" || schema === null)
925
+ return false;
926
+ if (typeof Reflect.get(schema, "model") !== "object")
927
+ return false;
928
+ if (typeof connected !== "object" || connected === null || typeof Reflect.get(connected, "then") !== "function") {
929
+ return false;
930
+ }
931
+ return typeof pool === "object" && pool !== null && typeof Reflect.get(pool, "execute") === "function";
932
+ }
933
+ function readSql(query) {
934
+ const sql = Reflect.get(query, "sql");
935
+ if (typeof sql !== "function") {
936
+ bad("Pass a query.", "explain takes the table and a query from that table, such as notes.find({ limit: 1 }).");
937
+ }
938
+ return sql.call(query);
939
+ }
940
+ function readPlanned(value) {
941
+ if (typeof value !== "object" || value === null) {
942
+ bad("The statement has no text.", "Call explain on a query.");
943
+ }
944
+ const text = Reflect.get(value, "text");
945
+ const params = Reflect.get(value, "params");
946
+ if (typeof text !== "string" || !Array.isArray(params)) {
947
+ bad("The statement has no text.", "Call explain on a query.");
948
+ }
949
+ const bound = [];
950
+ for (const param of params) {
951
+ if (typeof param !== "string" && param !== null) {
952
+ bad("A statement parameter was not text.", "Parameters are bound text.");
953
+ }
954
+ bound.push(param);
955
+ }
956
+ return { text, params: bound };
957
+ }
958
+ function openTable(lane) {
959
+ const model = lane.session.schema.model[lane.table];
960
+ if (model === undefined) {
961
+ bad(`Table ${lane.table} is not in the schema.`, "Call raw on a table this schema declares.");
962
+ }
963
+ const columns = new Map;
964
+ const names = [];
965
+ for (const column of model.columns) {
966
+ columns.set(column.field, column);
967
+ names.push(column.field);
968
+ }
969
+ names.sort();
970
+ return { model, columns, names };
971
+ }
972
+ function compile(table, parts) {
973
+ const params = [];
974
+ const chunks = [];
975
+ let count = 0;
976
+ const sink = {
977
+ text(value) {
978
+ chunks.push(value);
979
+ },
980
+ param(encoded) {
981
+ params.push(encoded);
982
+ count += 1;
983
+ chunks.push(`$${String(count)}`);
984
+ },
985
+ mark() {}
986
+ };
987
+ for (const part of parts)
988
+ writePart(part, sink, table);
989
+ return { text: chunks.join(""), params };
990
+ }
991
+ function writePart(part, sink, table) {
992
+ if (part.k === "t") {
993
+ sink.text(part.s);
994
+ return;
995
+ }
996
+ if (part.k === "p") {
997
+ sink.param(part.v);
998
+ return;
999
+ }
1000
+ if (part.k === "n") {
1001
+ sink.text("null");
1002
+ return;
1003
+ }
1004
+ if (part.k === "i") {
1005
+ writeIdent(part.n, sink, table);
1006
+ return;
1007
+ }
1008
+ if (part.k === "c") {
1009
+ throw new OkmError2("OKM1125", "fragment.column belongs on a where field.", {
1010
+ fix: { summary: "Use ident(name) in a raw statement." }
1011
+ });
1012
+ }
1013
+ sink.text("(");
1014
+ for (const nested of part.parts)
1015
+ writePart(nested, sink, table);
1016
+ sink.text(")");
1017
+ }
1018
+ function writeIdent(name, sink, table) {
1019
+ const column = table.columns.get(name);
1020
+ if (column === undefined) {
1021
+ throwNamed2("OKM1120", name, table.names, `Field ${name} is not on ${table.model.name}. Accepted names: ${table.names.join(", ")}.`);
1022
+ }
1023
+ if (column.hidden) {
1024
+ throw new OkmError2("OKM1120", `Field ${column.field} is hidden.`, {
1025
+ fix: { summary: "A raw statement cannot name a hidden field." }
1026
+ });
1027
+ }
1028
+ sink.text(quoteIdent2(column.sql));
1029
+ }
1030
+ function readClass(statement) {
1031
+ if (statement === READ || statement === WRITE)
1032
+ return statement;
1033
+ bad('The statement class is "read" or "write".', 'Pass "read" or "write".');
1034
+ }
1035
+ function readParts(source) {
1036
+ if (typeof source !== "object" || source === null) {
1037
+ bad("Pass fragment`...`.", "Identifiers are ident(name). A string, number, boolean, or null is a parameter.");
1038
+ }
1039
+ if (typeof Reflect.get(source, "as") === "string") {
1040
+ bad("Pass the fragment, not .as(name).", "The class names the row. Drop .as().");
1041
+ }
1042
+ if (!isOperator(source) || operatorName(source) !== "sql") {
1043
+ bad("Pass fragment`...`.", "Identifiers are ident(name). A string, number, boolean, or null is a parameter.");
1044
+ }
1045
+ const stored = operatorValue(source);
1046
+ if (!isFragmentParts(stored)) {
1047
+ bad("Pass fragment`...`.", "Call fragment`...`. Do not build the parts yourself.");
1048
+ }
1049
+ return stored;
1050
+ }
1051
+ function verb(text) {
1052
+ return /^[a-z]+/i.exec(text.trimStart())?.[0]?.toLowerCase() ?? "";
1053
+ }
1054
+ function predicateOf(session, table) {
1055
+ const tenancy = session.schema.tenancy;
1056
+ if (tenancy === undefined)
1057
+ return;
1058
+ const chunks = [];
1059
+ const params = [];
1060
+ let count = 0;
1061
+ const wrote = tenancy.predicate({
1062
+ table: table.model.name,
1063
+ fieldSql: (field) => table.columns.get(field)?.sql,
1064
+ encode: table.columns.get(tenancy.key)?.encode,
1065
+ alias: "okm_tenant",
1066
+ appended: false,
1067
+ scope: session.scope,
1068
+ sink: {
1069
+ text(value) {
1070
+ chunks.push(value);
1071
+ },
1072
+ param(encoded) {
1073
+ params.push(encoded);
1074
+ count += 1;
1075
+ chunks.push(`$${String(count)}`);
1076
+ },
1077
+ mark() {}
1078
+ }
1079
+ });
1080
+ if (!wrote)
1081
+ return;
1082
+ return { text: chunks.join("").replace(/^\s*where\s+/i, ""), params };
1083
+ }
1084
+ function guardOf(table, tenancy, userCount) {
1085
+ const archive = table.model.archive?.at;
1086
+ if (tenancy === undefined && archive === undefined)
1087
+ return;
1088
+ const parts = [];
1089
+ if (tenancy !== undefined)
1090
+ parts.push(shift(tenancy.text, userCount));
1091
+ if (archive !== undefined)
1092
+ parts.push(`okm_tenant.${quoteIdent2(archive)} is null`);
1093
+ return { text: parts.join(" and "), params: tenancy?.params ?? [] };
1094
+ }
1095
+ function requireKey(table, tenantKey, parts) {
1096
+ const key = rowKey(table, tenantKey);
1097
+ if (key === undefined) {
1098
+ unverifiable("A raw read needs one primary key column besides the tenant key.", "Declare one primary key. The tenant predicate binds that column.");
1099
+ }
1100
+ if (!namesIdent(parts, key)) {
1101
+ unverifiable(`A raw read must select ${key} with ident.`, `Put ident("${key}") in the select list. Do not alias it. The tenant predicate is added outside the statement.`);
1102
+ }
1103
+ }
1104
+ function rowKey(table, tenantKey) {
1105
+ const keys = table.model.primary.filter((field) => field !== tenantKey);
1106
+ return keys.length === 1 ? keys[0] : undefined;
1107
+ }
1108
+ function namesIdent(parts, name) {
1109
+ for (const part of parts) {
1110
+ if (part.k === "i" && part.n === name)
1111
+ return true;
1112
+ if (part.k === "f" && namesIdent(part.parts, name))
1113
+ return true;
1114
+ }
1115
+ return false;
1116
+ }
1117
+ function wrap(table, tenantKey, text, where) {
1118
+ const key = rowKey(table, tenantKey);
1119
+ const column = key === undefined ? undefined : table.columns.get(key);
1120
+ if (column === undefined) {
1121
+ unverifiable("A raw read needs one primary key column besides the tenant key.", "Declare one primary key. The tenant predicate binds that column.");
1122
+ }
1123
+ const quoted = quoteIdent2(column.sql);
1124
+ return `select okm_raw.* from (${text}) as okm_raw where okm_raw.${quoted} in (select ${quoted} from ${quoteIdent2(table.model.sql)} as okm_tenant where ${where})`;
1125
+ }
1126
+ function shift(text, by) {
1127
+ if (by === 0)
1128
+ return text;
1129
+ return text.replace(/\$(\d+)/g, (_match, digits) => `$${String(Number(digits) + by)}`);
1130
+ }
1131
+ function decodeRows(cls, rows, table) {
1132
+ const ctor = readClassCtor(cls);
1133
+ const sample = construct(ctor);
1134
+ const keys = Object.keys(sample);
1135
+ if (keys.length === 0) {
1136
+ bad("The class needs an initializer on every result column.", 'Write `id = ""` or `n = 0`. The initializer selects the decode, and the order is the select list.');
1137
+ }
1138
+ for (const key of keys) {
1139
+ if (BLOCKED.has(key))
1140
+ bad(`Field ${key} is reserved.`, "Rename the class field.");
1141
+ }
1142
+ return rows.map((wire) => {
1143
+ const row = construct(ctor);
1144
+ for (let index = 0;index < keys.length; index += 1) {
1145
+ const key = keys[index];
1146
+ if (key === undefined)
1147
+ continue;
1148
+ Reflect.set(row, key, decodeWire(wire[index], Reflect.get(sample, key), table.columns.get(key)));
1149
+ }
1150
+ return row;
1151
+ });
1152
+ }
1153
+ function readClassCtor(cls) {
1154
+ if (typeof cls !== "function") {
1155
+ bad("Pass a class.", "The result of raw is one instance of that class per row.");
1156
+ }
1157
+ return cls;
1158
+ }
1159
+ function construct(ctor) {
1160
+ try {
1161
+ return new ctor;
1162
+ } catch {
1163
+ bad("The class must construct with no arguments.", "Give each field an initializer and no constructor arguments.");
1164
+ }
1165
+ }
1166
+ function decodeWire(wire, sample, column) {
1167
+ if (wire === null || wire === undefined)
1168
+ return null;
1169
+ if (column !== undefined)
1170
+ return column.decode === undefined ? wire : column.decode(wire);
1171
+ if (typeof sample === "number") {
1172
+ const parsed = Number(wire);
1173
+ if (!Number.isFinite(parsed)) {
1174
+ bad("A class field initialized with a number received a non-numeric value.", "Use a numeric expression, or initialize the field with a string.");
1175
+ }
1176
+ return parsed;
1177
+ }
1178
+ if (typeof sample === "boolean") {
1179
+ if (wire === "t" || wire === "true" || wire === "1")
1180
+ return true;
1181
+ if (wire === "f" || wire === "false" || wire === "0")
1182
+ return false;
1183
+ bad("A class field initialized with a boolean received another value.", "Use a boolean expression, or initialize the field with a string.");
1184
+ }
1185
+ return wire;
1186
+ }
1187
+ function bad(message, fix) {
1188
+ throw new OkmError2("OKM1602", message, { fix: { summary: fix } });
1189
+ }
1190
+ function unverifiable(message, fix) {
1191
+ throw new OkmError2("OKM1702", message, { fix: { summary: fix } });
1192
+ }
818
1193
  export {
819
1194
  ColumnBuilder2 as ColumnBuilder,
820
1195
  exports_arr_ns as arr,
@@ -838,12 +1213,16 @@ export {
838
1213
  enumColumn as enum,
839
1214
  eq,
840
1215
  every,
1216
+ explain,
1217
+ external,
1218
+ fragment2 as fragment,
841
1219
  gt,
842
1220
  gte,
843
1221
  has,
844
1222
  hasAnyKey,
845
1223
  hasKey,
846
1224
  id2 as id,
1225
+ ident2 as ident,
847
1226
  identity2 as identity,
848
1227
  ilike,
849
1228
  inList,
@@ -881,6 +1260,7 @@ export {
881
1260
  path,
882
1261
  point,
883
1262
  rank2 as rank,
1263
+ raw,
884
1264
  real,
885
1265
  relevance,
886
1266
  rowNumber2 as rowNumber,
@@ -52,6 +52,17 @@ export declare function introspectSchema(runner: CatalogQuery, concrete: string,
52
52
  * Types only, comma-separated, no spaces. Argument names are left out.
53
53
  */
54
54
  export declare const FUNCTION_ARG_TYPES = "replace(oidvectortypes(p.proargtypes), ' ', '')";
55
+ /**
56
+ * The `BEGIN ATOMIC` block inside `pg_get_functiondef`.
57
+ *
58
+ * A definition that does not contain that block is returned whole. The slice
59
+ * stops at the last `END`, which is the block closer. A `CASE` closer earlier
60
+ * in the reprint stays inside the block.
61
+ *
62
+ * @param definition - `pg_get_functiondef` text
63
+ * @returns The body introspection stores
64
+ */
65
+ export declare function atomicBody(definition: string): string;
55
66
  /**
56
67
  * Applies one expression as a check and reads Postgres's reprint.
57
68
  *
@@ -7,7 +7,7 @@
7
7
  declare const brand: unique symbol;
8
8
  declare const RUNTIME: unique symbol;
9
9
  /** Operator names the read path compiles. */
10
- export type OperatorName = "eq" | "lt" | "lte" | "gt" | "gte" | "between" | "startsWith" | "contains" | "endsWith" | "like" | "ilike" | "inList" | "notIn" | "not" | "or" | "and" | "has" | "none" | "every" | "inc" | "containedBy" | "overlaps" | "hasKey" | "hasAnyKey" | "path" | "matches" | "relevance" | "similar" | "wordSimilar" | "json.set" | "arr.append" | "arr.remove";
10
+ export type OperatorName = "eq" | "lt" | "lte" | "gt" | "gte" | "between" | "startsWith" | "contains" | "endsWith" | "like" | "ilike" | "inList" | "notIn" | "not" | "or" | "and" | "has" | "none" | "every" | "inc" | "containedBy" | "overlaps" | "hasKey" | "hasAnyKey" | "path" | "matches" | "relevance" | "similar" | "wordSimilar" | "sql" | "json.set" | "arr.append" | "arr.remove";
11
11
  /** A tagged operator. `value` is the operand the helper stored. */
12
12
  export type Tagged<Name extends OperatorName, V> = {
13
13
  readonly [brand]: Name;
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Composed SQL fragments (rule 15, D266).
3
+ *
4
+ * The check-constraint `sql` tag stays a string. A query fragment is a tagged
5
+ * operator named `sql`, so the planner compiles it on the existing lazy
6
+ * operator path. Values are parameters. `ident` stores a name the compiler
7
+ * quotes. `fragment.column` is the where field the fragment is attached to.
8
+ */
9
+ import { type Eq } from "../operators.js";
10
+ import type { Window } from "./window.js";
11
+ declare const identBrand: unique symbol;
12
+ declare const columnBrand: unique symbol;
13
+ /** One piece of a fragment. The compiler walks this list. */
14
+ export type FragmentPart = {
15
+ readonly k: "t";
16
+ readonly s: string;
17
+ } | {
18
+ readonly k: "p";
19
+ readonly v: string;
20
+ } | {
21
+ readonly k: "n";
22
+ } | {
23
+ readonly k: "i";
24
+ readonly n: string;
25
+ } | {
26
+ readonly k: "c";
27
+ } | {
28
+ readonly k: "f";
29
+ readonly parts: readonly FragmentPart[];
30
+ };
31
+ /** A name `ident` stored. The compiler quotes it. */
32
+ export type FragmentIdent = {
33
+ readonly [identBrand]: string;
34
+ };
35
+ /** The where field a fragment is attached to. */
36
+ export type FragmentColumn = {
37
+ readonly [columnBrand]: true;
38
+ };
39
+ /**
40
+ * A composed fragment.
41
+ *
42
+ * It is a where operand. `.as(name)` is the select form, and that result is a
43
+ * number.
44
+ */
45
+ export type Fragment = Eq<never> & {
46
+ /**
47
+ * Names the select result.
48
+ *
49
+ * @typeParam A - Result key
50
+ * @param name - Result key. Not a column name
51
+ * @returns A select entry
52
+ */
53
+ as<const A extends string>(name: A): Window<A, number>;
54
+ };
55
+ /**
56
+ * Reports whether `value` is the part list `fragment` stored.
57
+ *
58
+ * @param value - Operator operand
59
+ * @returns `true` when every part has a known kind
60
+ */
61
+ export declare function isFragmentParts(value: unknown): value is readonly FragmentPart[];
62
+ /**
63
+ * Reads a select fragment.
64
+ *
65
+ * @param value - One `select` entry
66
+ * @returns The result name and the parts, or `undefined` when it is not a fragment
67
+ */
68
+ export declare function readSelectFragment(value: unknown): {
69
+ readonly as: string;
70
+ readonly parts: readonly FragmentPart[];
71
+ readonly textual?: true;
72
+ } | undefined;
73
+ /**
74
+ * A function call stored as a `sql` fragment.
75
+ *
76
+ * The planner compiles it on the same path as {@link fragment}. `textual`
77
+ * makes `.as(name)` keep the wire string. A numeric call parses a number.
78
+ *
79
+ * @param parts - Expression parts, including the function name
80
+ * @param textual - When true, a select result stays text
81
+ * @returns A where operand. Call `.as(name)` to use it in `select`
82
+ */
83
+ export declare function sqlExpression(parts: readonly FragmentPart[], textual?: boolean): Fragment;
84
+ /**
85
+ * Reads the field name `ident` stored.
86
+ *
87
+ * @param value - A fragment interpolation
88
+ * @returns The field name, or `undefined` when `value` is not an ident
89
+ */
90
+ export declare function identName(value: unknown): string | undefined;
91
+ /**
92
+ * A composed SQL fragment.
93
+ *
94
+ * `column` is the where field this fragment is attached to.
95
+ */
96
+ export declare const fragment: {
97
+ /**
98
+ * Builds a composed SQL fragment.
99
+ *
100
+ * @param strings - Literal SQL
101
+ * @param values - Parameters, identifiers, the column, or nested fragments
102
+ * @returns A where operand
103
+ */
104
+ (strings: TemplateStringsArray, ...values: readonly unknown[]): Fragment;
105
+ /** The where field this fragment is attached to, quoted by the compiler. */
106
+ readonly column: FragmentColumn;
107
+ };
108
+ /**
109
+ * Stores a field name for a fragment to resolve.
110
+ *
111
+ * The name is the TypeScript field, the same name `where` uses. Casing and
112
+ * `sqlName` are applied when the compiler quotes the column. A hidden field
113
+ * is OKM1120 at planning. Empty names and control characters are OKM1122.
114
+ *
115
+ * @param name - Field name
116
+ * @returns A value `fragment` resolves against the table
117
+ */
118
+ export declare function ident(name: string): FragmentIdent;
119
+ export {};
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Typed raw SQL and `explain()` (P103, P104, D268).
3
+ *
4
+ * Exported from `okmodel/pg`. An app that does not import them drops this
5
+ * module. The table handle carries the session under `Symbol.for("okm.lane")`.
6
+ * The statement class is explicit. Parameters come from the fragment. The
7
+ * tenant predicate, when it applies, is written outside the fragment.
8
+ */
9
+ /**
10
+ * What `explain()` returns.
11
+ *
12
+ * `plan` is null in production, and `params` is empty there.
13
+ */
14
+ export type ExplainResult = {
15
+ /** The statement `explain` describes. */
16
+ readonly text: string;
17
+ /** Bound parameters. Empty in production. */
18
+ readonly params: readonly (string | null)[];
19
+ /** `EXPLAIN` lines, or null when the statement was not sent. */
20
+ readonly plan: readonly string[] | null;
21
+ };
22
+ /**
23
+ * Runs one typed raw statement on a table handle.
24
+ *
25
+ * `cls` is constructed once per row. Own enumerable keys of that instance, in
26
+ * order, are the result columns. A key that is a field of the table uses that
27
+ * field's decode. Any other key uses the initializer: a number, a boolean, or
28
+ * driver text. `null` stays `null`.
29
+ *
30
+ * @typeParam C - Result class. Each row is an instance
31
+ * @param handle - Table handle (`db.notes`, including one from `for()`)
32
+ * @param cls - Class with an initializer on every result column
33
+ * @param statement - `"read"` or `"write"`
34
+ * @param source - A `fragment` template. Identifiers are `ident(name)`
35
+ * @returns One instance per row
36
+ */
37
+ export declare function raw<C extends new () => object>(handle: object, cls: C, statement: "read" | "write", source: unknown): Promise<InstanceType<C>[]>;
38
+ /**
39
+ * Describes a query.
40
+ *
41
+ * Outside production this sends `EXPLAIN` and returns the lines. In production
42
+ * (`NODE_ENV` is `"production"`) it does not send the statement. `plan` is
43
+ * null and `params` is empty.
44
+ *
45
+ * @param handle - Table handle that owns the query's session
46
+ * @param query - A query from that table. `sql()` is the statement
47
+ * @returns The statement and, outside production, the plan lines
48
+ */
49
+ export declare function explain(handle: object, query: object): Promise<ExplainResult>;