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
@@ -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
  *
@@ -8,15 +8,18 @@ export type IdDefault = "uuidv7" | "uuidv4" | "none";
8
8
  /**
9
9
  * Primary key.
10
10
  *
11
- * With no options, the database default is `uuidv7()` unless
12
- * `schema({ defaults: { id } })` says otherwise. `uuidv4` stores
13
- * `gen_random_uuid()` (built in from Postgres 13). `none` takes the id on
14
- * insert. A client generator (`uuidv4`, `uuidv7`, or `okid(...)` from
15
- * `okmodel/ids`) is filled on insert and stored with no database default.
16
- * OKID is `text` with collation `C`. A database default is omitted from
17
- * insert and update. `none` is required on insert and omitted from update.
11
+ * With no options, the database default is `gen_random_uuid()` unless
12
+ * `schema({ defaults: { id } })` says otherwise. That function is built in
13
+ * from Postgres 13, so a bare call works on every supported major. `uuidv7`
14
+ * stores `uuidv7()` and needs Postgres 18 (`minPostgres: 18`). Pick it for a large write-heavy
15
+ * table: the ids are time-ordered and the index stays local. Random ids are
16
+ * fine elsewhere. `none` takes the id on insert. A client generator
17
+ * (`uuidv4`, `uuidv7`, or `okid(...)` from `okmodel/ids`) is filled on insert
18
+ * and stored with no database default. OKID is `text` with collation `C`. A
19
+ * database default is omitted from insert and update. `none` is required on
20
+ * insert and omitted from update.
18
21
  *
19
- * @param options - Which default to store. Omitted means the schema default, or `uuidv7()`
22
+ * @param options - Which default to store. Omitted means the schema default, or `gen_random_uuid()`
20
23
  * @returns An id column
21
24
  */
22
25
  export declare function id(): ColumnBuilder<string, IdFlags>;
@@ -63,6 +63,39 @@ export type ColumnModel = {
63
63
  */
64
64
  readonly accepts?: readonly string[] | undefined;
65
65
  };
66
+ /**
67
+ * One table a morph include can return.
68
+ *
69
+ * `type` is the table's TypeScript name, which is what the type column stores.
70
+ */
71
+ export type MorphTarget = {
72
+ readonly type: string;
73
+ readonly table: string;
74
+ /** SQL name of the target table. */
75
+ readonly sql: string;
76
+ /** SQL name of the target's single primary-key column. */
77
+ readonly keySql: string;
78
+ };
79
+ /**
80
+ * A polymorphic pair: a type column and an id column.
81
+ *
82
+ * `to` is the owner side (one of several tables). `many` is the reverse on a target.
83
+ * Absent on every other relation, so a normal relation does not carry it.
84
+ */
85
+ export type MorphModel = {
86
+ readonly direction: "to" | "many";
87
+ /** Column stem. The fields are `${name}Type` and `${name}Id`. */
88
+ readonly name: string;
89
+ readonly typeField: string;
90
+ readonly idField: string;
91
+ /** SQL name of the type column. */
92
+ readonly typeSql: string;
93
+ /** SQL name of the id column. */
94
+ readonly idSql: string;
95
+ /** On a reverse many, the table name stored in the type column. */
96
+ readonly typeValue?: string;
97
+ readonly targets: readonly MorphTarget[];
98
+ };
66
99
  /**
67
100
  * A resolved relation.
68
101
  *
@@ -77,6 +110,13 @@ export type RelationModel = {
77
110
  readonly local: readonly string[];
78
111
  /** SQL names on the related table. */
79
112
  readonly remote: readonly string[];
113
+ /**
114
+ * Set on a morph relation.
115
+ *
116
+ * The include planner reads `to`. A reverse many reads `many` and emits
117
+ * through {@link RelationModel.through}.
118
+ */
119
+ readonly morph?: MorphModel;
80
120
  /**
81
121
  * Set on a `manyThrough` relation.
82
122
  *
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Resolver and emitters of a `morph` relation.
3
+ *
4
+ * The relation object carries both. `schema()` calls the resolver, and the
5
+ * planner calls the emitter with its own helpers, so a schema that never
6
+ * calls `morph` or `morphMany` does not ship this module. A target in another
7
+ * tenant or archived never shows: the include planner applies those predicates
8
+ * to each target, the same way it does for any relation.
9
+ */
10
+ import type { RelationModel } from "./model.js";
11
+ import type { RelationScope } from "./relations.js";
12
+ /**
13
+ * Resolves `morph(name, targets)` on the table that holds the type and id columns.
14
+ *
15
+ * @param scope - What `schema()` knows
16
+ * @param name - Column stem: `${name}Type` and `${name}Id`
17
+ * @param targets - Closed list of target table names
18
+ * @returns The resolved to-one relation
19
+ */
20
+ export declare function resolveMorph(scope: RelationScope, name: string, targets: readonly string[]): RelationModel;
21
+ /**
22
+ * Resolves `morphMany(table, name)` on a target table.
23
+ *
24
+ * The many reads the owner table's type and id columns. The owner must declare
25
+ * `morph(name, targets)` and list this table.
26
+ *
27
+ * @param scope - What `schema()` knows. `owner` is the target table
28
+ * @param table - Table that holds the type and id columns
29
+ * @param name - Column stem declared on that table
30
+ * @returns The resolved to-many relation
31
+ */
32
+ export declare function resolveMorphMany(scope: RelationScope, table: string, name: string): RelationModel;
33
+ /**
34
+ * Refuses `morphTo` when the name, type, or id is missing.
35
+ *
36
+ * `null` used to throw a TypeError on `.length`. An empty name or type stays
37
+ * OKM1020. A null or non-string id, or a null type, is OKM1120.
38
+ *
39
+ * @param name - Column stem
40
+ * @param type - Target table name
41
+ * @param id - That table's primary key
42
+ */
43
+ export declare function assertMorphTo(name: unknown, type: unknown, id: unknown): void;
@@ -58,9 +58,9 @@ export declare function assertNoControl(value: string, role: string): void;
58
58
  */
59
59
  export declare function assertBoundText(value: string, role: string): void;
60
60
  /**
61
- * Rejects a regconfig name that is not an identifier.
61
+ * Rejects a text search language that is not an identifier.
62
62
  *
63
- * @param config - Text search configuration
63
+ * @param config - Language name, such as `english`
64
64
  */
65
65
  export declare function assertRegconfig(config: string): void;
66
66
  /**
@@ -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" | "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;
@@ -38,16 +38,23 @@ export type PathValue<V> = {
38
38
  };
39
39
  /** `col #>> segments` compared with `op`. */
40
40
  export type Path<V extends string | number | boolean> = Tagged<"path", PathValue<V>>;
41
- /** How `matches` turns query text into a tsquery. */
42
- export type MatchMode = "websearch" | "plain" | "phrase";
43
- /** Full-text query. `config` is a regconfig name when set. */
41
+ /**
42
+ * How search text is matched.
43
+ *
44
+ * `natural` is web-search style. `all-words` requires every word. `phrase`
45
+ * keeps the words in order. `advanced` is PostgreSQL query syntax.
46
+ */
47
+ export type SearchMatch = "natural" | "all-words" | "phrase" | "advanced";
48
+ /** Text to look for, how to match it, and the text search language when one was passed. */
44
49
  export type MatchValue = {
45
50
  readonly query: string;
46
- readonly mode: MatchMode;
47
- readonly config: string | undefined;
51
+ readonly match: SearchMatch;
52
+ readonly language: string | undefined;
48
53
  };
49
- /** `@@` against a tsvector column. */
54
+ /** `@@` against a search column. */
50
55
  export type Matches = Tagged<"matches", MatchValue>;
56
+ /** Order by how well a search column matches. Most relevant first. */
57
+ export type Relevance = Tagged<"relevance", MatchValue>;
51
58
  /** Text stored on a `pg_trgm` operator. `schema` is the extension's install schema. */
52
59
  export type TrigramQuery = {
53
60
  readonly query: string;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Time bucket for `aggregate` `groupBy` (spec §10, §13 tool 4).
3
+ *
4
+ * The brand is a symbol. JSON cannot create one, so a request cannot add a
5
+ * bucket. A plain object in `groupBy` stays OKM1120. The SQL loads with the
6
+ * first `aggregate()` whose `groupBy` contains a bucket.
7
+ */
8
+ declare const brand: unique symbol;
9
+ /** Calendar and clock units `bucket` accepts. */
10
+ export type BucketUnit = "second" | "minute" | "hour" | "day" | "week" | "month" | "quarter" | "year";
11
+ /** Week that starts on Monday (ISO), Sunday, or Saturday. */
12
+ export type WeekStart = "monday" | "sunday" | "saturday";
13
+ /**
14
+ * A `bucket()` call.
15
+ *
16
+ * `C` is the column, `U` the unit, and `A` the result key.
17
+ */
18
+ export type Bucket<C extends string, U extends string, A extends string> = {
19
+ readonly [brand]: C;
20
+ readonly unit: U;
21
+ readonly as: A;
22
+ };
23
+ /** What {@link bucket} stores. The aggregate chunk reads this. */
24
+ export type BucketInput = {
25
+ readonly column: unknown;
26
+ readonly unit: unknown;
27
+ readonly as: unknown;
28
+ readonly tz: unknown;
29
+ readonly weekStart: unknown;
30
+ };
31
+ /**
32
+ * Groups a timestamp or date column by a calendar or clock unit.
33
+ *
34
+ * `tz` is required for `timestamptz` and refused for `date`. `timestamp`
35
+ * without a zone is refused. `as` is the result key. `__proto__`, `constructor`,
36
+ * `toString`, and `hasOwnProperty` are refused when the aggregate runs.
37
+ * `weekStart` applies only
38
+ * to `week` and defaults to Monday. A NULL timestamp is its own group: the
39
+ * `as` key is present and the value is null.
40
+ *
41
+ * Day, week, month, quarter, and year come back as `Temporal.PlainDate` (the
42
+ * local date the period starts). Second, minute, and hour come back as
43
+ * `Temporal.Instant` (the period start).
44
+ *
45
+ * @typeParam C - Column name
46
+ * @typeParam U - Unit
47
+ * @typeParam A - Result key
48
+ * @param column - Field to bucket
49
+ * @param unit - Period
50
+ * @param options - Zone, result key, and week start
51
+ * @returns A tagged bucket. Pass it in `groupBy`
52
+ */
53
+ export declare function bucket<const C extends string, const U extends BucketUnit, const A extends string>(column: C, unit: U, options: {
54
+ readonly tz?: string;
55
+ readonly as: A;
56
+ readonly weekStart?: WeekStart;
57
+ }): Bucket<C, U, A>;
58
+ /**
59
+ * Reports whether `value` is a {@link bucket} call.
60
+ *
61
+ * @param value - One `groupBy` entry
62
+ * @returns `true` when {@link bucket} created it
63
+ */
64
+ export declare function isBucket(value: unknown): value is BucketInput;
65
+ export {};
@@ -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 {};
@@ -2,9 +2,9 @@ import { type Tagged } from "../operators.js";
2
2
  /** Adds to the stored number. `undefined` in `set` still leaves the field unchanged. */
3
3
  export type Inc<V> = Tagged<"inc", V>;
4
4
  /**
5
- * Atomic increment used in `update` `set` (spec §11).
5
+ * Adds to a stored number in `update` `set` (spec §11).
6
6
  *
7
- * JSON and array operators are not this helper.
7
+ * A null number stays null. JSON and array operators are not this helper.
8
8
  *
9
9
  * @typeParam V - Amount
10
10
  * @param value - Amount to add
@@ -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>;
@@ -1,16 +1,13 @@
1
- import { type MatchMode, type Matches } from "../operators.js";
1
+ import { type Matches } from "../operators.js";
2
+ import { type SearchOptions } from "./search-query.js";
2
3
  /**
3
- * Full-text match (`@@`) for a tsvector column.
4
+ * Full-text match for a search column.
4
5
  *
5
- * The default mode is `websearch_to_tsquery`, which does not throw on user
6
- * input. `"plain"` uses `plainto_tsquery` and `"phrase"` uses `phraseto_tsquery`.
7
- * A text column is not searched here.
6
+ * The default match is natural, which does not throw on user input. A plain
7
+ * text column is not searched here. `relevance` orders by the same match.
8
8
  *
9
- * @param query - Search text
10
- * @param options - Mode and regconfig name
11
- * @returns A tagged operator
9
+ * @param query - Text to look for
10
+ * @param options - How to match, and the text search language
11
+ * @returns A tagged operator for `where`
12
12
  */
13
- export declare function matches(query: string, options?: {
14
- readonly mode?: MatchMode;
15
- readonly config?: string;
16
- }): Matches;
13
+ export declare function matches(query: string, options?: SearchOptions): Matches;
@@ -0,0 +1,13 @@
1
+ import { type Relevance } from "../operators.js";
2
+ import { type SearchOptions } from "./search-query.js";
3
+ /**
4
+ * Orders a search column by how well it matches.
5
+ *
6
+ * Most relevant first. Pass it as an `orderBy` value. `find({ search })`
7
+ * compiles to `matches` plus this, so the SQL is the same.
8
+ *
9
+ * @param query - Text to look for
10
+ * @param options - How to match, and the text search language. Same words as `matches`
11
+ * @returns A tagged order
12
+ */
13
+ export declare function relevance(query: string, options?: SearchOptions): Relevance;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Shared operand for `matches` and `relevance`.
3
+ *
4
+ * Both helpers store this shape. The SQL compiler reads it once, so `search`
5
+ * and the two helpers emit the same text.
6
+ */
7
+ import type { MatchValue, SearchMatch } from "../operators.js";
8
+ /** Options `matches` and `relevance` take. */
9
+ export type SearchOptions = {
10
+ /** How to match. Omitted means `natural`. */
11
+ readonly match?: SearchMatch;
12
+ /** Text search language, such as `english`. Omitted uses the database default. */
13
+ readonly language?: string;
14
+ };
15
+ /**
16
+ * Stores the text, the match, and the language.
17
+ *
18
+ * @param query - Text to look for
19
+ * @param options - Match and language. Omitted means natural, database language
20
+ * @returns The operand both helpers tag
21
+ */
22
+ export declare function searchValue(query: string, options?: SearchOptions): MatchValue;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Window helpers for `select` (spec §10, §13 tool 12).
3
+ *
4
+ * The brand is a symbol. JSON cannot create one, so a request cannot add a
5
+ * window. A plain object in `select` stays OKM1120. The SQL loads on the first
6
+ * `find` or `one` whose `select` contains one.
7
+ */
8
+ declare const brand: unique symbol;
9
+ /** `asc` is nulls last and `desc` is nulls first unless `nulls` is set. */
10
+ type SortDir = "asc" | "desc" | {
11
+ readonly dir: "asc" | "desc";
12
+ readonly nulls?: "first" | "last";
13
+ };
14
+ /** Columns the window orders by. Names are checked when the call runs. */
15
+ export type WindowOrder = {
16
+ readonly [field: string]: SortDir | undefined;
17
+ };
18
+ /** What a window helper stores. The planner reads this. */
19
+ export type WindowCall = {
20
+ readonly label: "rowNumber" | "rank" | "denseRank" | "runningTotal";
21
+ readonly fn: "row_number" | "rank" | "dense_rank" | "sum";
22
+ readonly column: string | undefined;
23
+ readonly partitionBy: readonly string[] | undefined;
24
+ readonly orderBy: unknown;
25
+ readonly as: string;
26
+ };
27
+ /**
28
+ * A window helper.
29
+ *
30
+ * `A` is the result key. `V` is `number` for a rank, or the source column for
31
+ * a running total.
32
+ */
33
+ export type Window<A extends string, V extends string | number> = {
34
+ readonly [brand]: V;
35
+ readonly as: A;
36
+ };
37
+ /**
38
+ * Options every window helper takes.
39
+ *
40
+ * `partitionBy` is the group. Omit it to number the whole result. `orderBy`
41
+ * is the order inside that group. The primary key breaks ties. `as` is the
42
+ * result key. `__proto__`, `constructor`, `toString`, and `hasOwnProperty`
43
+ * are refused when the call runs.
44
+ */
45
+ type WindowOptions<A extends string> = {
46
+ readonly partitionBy?: readonly string[];
47
+ readonly orderBy: WindowOrder;
48
+ readonly as: A;
49
+ };
50
+ /**
51
+ * Reports whether `value` is a window helper.
52
+ *
53
+ * @param value - One `select` entry
54
+ * @returns `true` when a helper in this module created it
55
+ */
56
+ export declare function isWindow(value: unknown): value is WindowCall;
57
+ /**
58
+ * Row number inside a group, starting at 1.
59
+ *
60
+ * Ties get distinct numbers. The primary key breaks them.
61
+ *
62
+ * @typeParam A - Result key
63
+ * @param options - Group, order, and result key
64
+ * @returns A tagged window. Pass it in `select` on `find` or `one`
65
+ */
66
+ export declare function rowNumber<const A extends string>(options: WindowOptions<A>): Window<A, number>;
67
+ /**
68
+ * Rank inside a group, with gaps after a tie.
69
+ *
70
+ * Two rows with the same order share a rank. The next rank skips. The primary
71
+ * key breaks the order when you need a stable row, and it does not split the
72
+ * rank.
73
+ *
74
+ * @typeParam A - Result key
75
+ * @param options - Group, order, and result key
76
+ * @returns A tagged window. Pass it in `select` on `find` or `one`
77
+ */
78
+ export declare function rank<const A extends string>(options: WindowOptions<A>): Window<A, number>;
79
+ /**
80
+ * Rank inside a group, without gaps after a tie.
81
+ *
82
+ * Two rows with the same order share a rank. The next rank is the next number.
83
+ *
84
+ * @typeParam A - Result key
85
+ * @param options - Group, order, and result key
86
+ * @returns A tagged window. Pass it in `select` on `find` or `one`
87
+ */
88
+ export declare function denseRank<const A extends string>(options: WindowOptions<A>): Window<A, number>;
89
+ /**
90
+ * Running total of a number column.
91
+ *
92
+ * The total follows `orderBy` inside the group. A null number does not add.
93
+ * The result uses the column's value type: a number, or the exact decimal
94
+ * string of a `numeric` column.
95
+ *
96
+ * @typeParam C - Column
97
+ * @typeParam A - Result key
98
+ * @param column - Field to total
99
+ * @param options - Group, order, and result key
100
+ * @returns A tagged window. Pass it in `select` on `find` or `one`
101
+ */
102
+ export declare function runningTotal<const C extends string, const A extends string>(column: C, options: WindowOptions<A>): Window<A, C>;
103
+ export {};
@@ -44,7 +44,7 @@ export type Preset<Row> = (q: PresetQuery<Row>, ...args: never[]) => PresetQuery
44
44
  * The first group are client methods. The second is reserved for later
45
45
  * releases. `then` would make a table handle look like a promise.
46
46
  */
47
- export type ReservedPreset = "find" | "one" | "page" | "aggregate" | "count" | "exists" | "insert" | "update" | "delete" | "archive" | "restore" | "withArchived" | "onlyArchived" | "then" | "lock" | "watch" | "subscribe" | "stream" | "inspect" | "explain" | "with" | "for" | "as";
47
+ export type ReservedPreset = "find" | "one" | "page" | "aggregate" | "count" | "exists" | "insert" | "update" | "delete" | "descendants" | "ancestors" | "sync" | "archive" | "restore" | "withArchived" | "onlyArchived" | "then" | "lock" | "watch" | "subscribe" | "stream" | "inspect" | "explain" | "with" | "for" | "as";
48
48
  /**
49
49
  * The `presets` option. A reserved name is a type error here, and OKM1040 when
50
50
  * the schema is used.