okmodel 0.6.0 → 0.7.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 (157) hide show
  1. package/README.md +100 -1131
  2. package/dist/adapters/capabilities.d.ts +3 -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/bunsql-extra.d.ts +54 -3
  6. package/dist/adapters/pg/bunsql.d.ts +14 -1
  7. package/dist/adapters/pg/cursor.d.ts +17 -0
  8. package/dist/adapters/pg/no-inflight-timeout.d.ts +11 -8
  9. package/dist/adapters/pg/nodepostgres-extra.d.ts +22 -1
  10. package/dist/adapters/pg/nodepostgres.d.ts +12 -0
  11. package/dist/adapters/pg/pglite-wire.d.ts +24 -0
  12. package/dist/adapters/pg/pglite.d.ts +10 -0
  13. package/dist/adapters/pg/postgres-extra.d.ts +27 -11
  14. package/dist/adapters/pg/reserved.d.ts +42 -0
  15. package/dist/adapters/pg/session.d.ts +0 -18
  16. package/dist/contracts/connection.d.ts +7 -6
  17. package/dist/dialects/pg/floor.d.ts +68 -0
  18. package/dist/dialects/pg/index.d.ts +6 -1
  19. package/dist/dialects/pg/index.js +49 -159
  20. package/dist/dialects/pg/keys.d.ts +11 -8
  21. package/dist/dialects/pg/model.d.ts +40 -0
  22. package/dist/dialects/pg/morph.d.ts +43 -0
  23. package/dist/dialects/pg/operator-fit.d.ts +2 -2
  24. package/dist/dialects/pg/operators.d.ts +14 -7
  25. package/dist/dialects/pg/ops/bucket.d.ts +65 -0
  26. package/dist/dialects/pg/ops/inc.d.ts +2 -2
  27. package/dist/dialects/pg/ops/matches.d.ts +9 -12
  28. package/dist/dialects/pg/ops/relevance.d.ts +13 -0
  29. package/dist/dialects/pg/ops/search-query.d.ts +22 -0
  30. package/dist/dialects/pg/ops/window.d.ts +103 -0
  31. package/dist/dialects/pg/preset.d.ts +1 -1
  32. package/dist/dialects/pg/relations.d.ts +100 -3
  33. package/dist/dialects/pg/schema.d.ts +31 -3
  34. package/dist/dialects/pg/view/index.js +1 -1
  35. package/dist/runtime/aggregate.d.ts +8 -2
  36. package/dist/runtime/bucket-group.d.ts +70 -0
  37. package/dist/runtime/conflict.d.ts +22 -4
  38. package/dist/runtime/include.d.ts +0 -8
  39. package/dist/runtime/inflight.d.ts +1 -1
  40. package/dist/runtime/page.d.ts +4 -1
  41. package/dist/runtime/pg/bun.js +12 -6
  42. package/dist/runtime/pg/pg.js +5 -5
  43. package/dist/runtime/pg/pglite.d.ts +1 -0
  44. package/dist/runtime/pg/pglite.js +9 -9
  45. package/dist/runtime/pg/postgresjs.js +5 -5
  46. package/dist/runtime/plan.d.ts +95 -5
  47. package/dist/runtime/read-stream.d.ts +13 -16
  48. package/dist/runtime/result-name.d.ts +17 -0
  49. package/dist/runtime/server-check.d.ts +3 -3
  50. package/dist/runtime/sort-bind.d.ts +21 -0
  51. package/dist/runtime/sort.d.ts +56 -0
  52. package/dist/runtime/sync.d.ts +70 -0
  53. package/dist/runtime/tenancy/index.js +7 -5
  54. package/dist/runtime/text-search.d.ts +20 -0
  55. package/dist/runtime/traits/index.d.ts +80 -0
  56. package/dist/runtime/traits/index.js +175 -11
  57. package/dist/runtime/tree.d.ts +38 -0
  58. package/dist/runtime/types.d.ts +218 -22
  59. package/dist/runtime/validate/index.js +2 -2
  60. package/dist/runtime/version.d.ts +39 -0
  61. package/dist/runtime/window.d.ts +21 -0
  62. package/dist/runtime/write.d.ts +54 -2
  63. package/dist/shared/{wkme6tep.js → 14vx95q4.js} +8 -16
  64. package/dist/shared/1est4ezg.js +313 -0
  65. package/dist/shared/{4az561fn.js → 1qa0qajz.js} +8 -23
  66. package/dist/shared/{2cg3wnxc.js → 1w508jbr.js} +593 -130
  67. package/dist/shared/2c13q96h.js +18 -0
  68. package/dist/shared/{b4v57v3x.js → 2d3xq4ps.js} +2 -2
  69. package/dist/shared/{1nw1f3vs.js → 2shdbn8q.js} +7 -7
  70. package/dist/shared/3v7t1yrv.js +208 -0
  71. package/dist/shared/{x3jc53kg.js → 5e3tf63j.js} +2 -2
  72. package/dist/shared/5fe3kbsh.js +10 -0
  73. package/dist/shared/5v3xf80k.js +37 -0
  74. package/dist/shared/{c58secgj.js → 63qtkrca.js} +38 -4
  75. package/dist/shared/{2z7wv5tj.js → 67txcrcw.js} +55 -34
  76. package/dist/shared/79dt02vc.js +12 -0
  77. package/dist/shared/{8x72s86k.js → 7k9grvf6.js} +10 -4
  78. package/dist/shared/7kms6fvj.js +20 -0
  79. package/dist/shared/7mnme5tn.js +8 -0
  80. package/dist/shared/7n7ddwt4.js +6 -0
  81. package/dist/shared/{5j36z8dn.js → 81ebdx9p.js} +39 -70
  82. package/dist/shared/{knmes2kh.js → 8skf0cam.js} +1 -1
  83. package/dist/shared/9a4ae4p8.js +31 -0
  84. package/dist/shared/9y3mmmh1.js +436 -0
  85. package/dist/shared/ab9gmbwy.js +213 -0
  86. package/dist/shared/{f0f1n281.js → ax7qv55k.js} +2 -2
  87. package/dist/shared/{g90m9b0g.js → aytqh5y2.js} +6 -5
  88. package/dist/shared/{vjpnzwjz.js → b5pftnn2.js} +1 -1
  89. package/dist/shared/{ag4c7516.js → b76b8d95.js} +2 -2
  90. package/dist/shared/{vmfkhszw.js → bg3rym3g.js} +33 -26
  91. package/dist/shared/{mb2ycs1p.js → bm22fvzr.js} +15 -15
  92. package/dist/shared/{q3j1tq7a.js → bz84tkzm.js} +148 -23
  93. package/dist/shared/{31vm914h.js → cm3w0ywp.js} +15 -16
  94. package/dist/shared/cn957f8d.js +179 -0
  95. package/dist/shared/{gwn6v667.js → cnkky55j.js} +25 -14
  96. package/dist/shared/{ys0xzyaj.js → dkxgzaqd.js} +224 -19
  97. package/dist/shared/dzj09cye.js +10 -0
  98. package/dist/shared/exn3sd90.js +359 -0
  99. package/dist/shared/g6evj1j3.js +66 -0
  100. package/dist/shared/ga9j92qj.js +25 -0
  101. package/dist/shared/{t3g0k88x.js → gs74dbj5.js} +16 -12
  102. package/dist/shared/gzaveazc.js +285 -0
  103. package/dist/shared/{2jd1sn0e.js → hyh73qk6.js} +1 -1
  104. package/dist/shared/{r1fdd0f6.js → je4axnm8.js} +5 -2
  105. package/dist/shared/{1f0xa3cb.js → jvd0mqag.js} +3 -3
  106. package/dist/shared/jznfax0y.js +155 -0
  107. package/dist/shared/{cgbamx3e.js → kb2sdhfb.js} +7 -4
  108. package/dist/shared/{wt5rzv1h.js → kr0jzbw2.js} +5 -5
  109. package/dist/shared/{p6bjzq9q.js → ktz42yez.js} +12 -4
  110. package/dist/shared/{p248q79y.js → m6p12kbr.js} +2 -2
  111. package/dist/shared/{r6nwkxnt.js → m7n9h2a5.js} +4 -4
  112. package/dist/shared/{672t5vym.js → mss6ctgv.js} +2 -2
  113. package/dist/shared/{929h19xp.js → mtaszv5a.js} +40 -10
  114. package/dist/shared/{b3awxn7h.js → n816peh1.js} +1 -1
  115. package/dist/shared/nbw1z4yd.js +18 -0
  116. package/dist/shared/{nx9hh281.js → p6qc5gcp.js} +12 -11
  117. package/dist/shared/{pjr6xrm5.js → pbp1ss85.js} +20 -17
  118. package/dist/shared/pt94kz7f.js +6 -0
  119. package/dist/shared/q5c6ngn3.js +13 -0
  120. package/dist/shared/{xq0mvhts.js → rs73fca9.js} +4 -4
  121. package/dist/shared/{r11n8grd.js → sfz1ksn6.js} +7 -4
  122. package/dist/shared/{wynzeggs.js → svncdeh5.js} +6 -6
  123. package/dist/shared/{j60w0dvr.js → tbrvgw6z.js} +57 -38
  124. package/dist/shared/te5as7z7.js +622 -0
  125. package/dist/shared/{ttmg09vd.js → tsvww22q.js} +1 -1
  126. package/dist/shared/{y2t3jktd.js → ttsqgp4p.js} +19 -12
  127. package/dist/shared/{x72jb7ad.js → v8g1vgv8.js} +1 -1
  128. package/dist/shared/{sbdme3vy.js → vb6qfyve.js} +60 -10
  129. package/dist/shared/{5d8t84hg.js → vczs8gd4.js} +14 -14
  130. package/dist/shared/{5yv4k6a6.js → vqrjpcqn.js} +144 -2
  131. package/dist/shared/{3fqwmr09.js → w72kgg4q.js} +4 -4
  132. package/dist/shared/{1z04fa85.js → w79hsckn.js} +12 -57
  133. package/dist/shared/{09p049xa.js → wa07eas9.js} +42 -14
  134. package/dist/shared/{32cnm7kn.js → x933k9a3.js} +74 -38
  135. package/dist/shared/{n076ydsc.js → xhfsfkgk.js} +62 -28
  136. package/dist/shared/xjk7hnn5.js +272 -0
  137. package/dist/shared/{hazqqecq.js → xnxsed62.js} +50 -21
  138. package/dist/shared/y6njgyda.js +249 -0
  139. package/dist/shared/{8etn7d8w.js → z7s6fpxv.js} +1 -1
  140. package/dist/shared/{n7mcc1gk.js → zchaghkf.js} +4 -3
  141. package/dist/shared/zm0ptry0.js +40 -0
  142. package/dist/shared/{nsva2a6b.js → znm0bpp5.js} +3 -0
  143. package/dist/shared/zp9fmend.js +145 -0
  144. package/dist/tooling/cli.js +11 -11
  145. package/dist/tooling/migrate/engine.d.ts +3 -2
  146. package/dist/tooling/migrate/index.js +7 -7
  147. package/dist/tooling/testing/index.js +1 -1
  148. package/package.json +4 -2
  149. package/dist/shared/3qnhc7w5.js +0 -38
  150. package/dist/shared/7m88x3e9.js +0 -45
  151. package/dist/shared/8dqhth8c.js +0 -12
  152. package/dist/shared/d5azex6s.js +0 -6
  153. package/dist/shared/j3rkk835.js +0 -99
  154. package/dist/shared/k68eedmy.js +0 -85
  155. package/dist/shared/venqrjna.js +0 -216
  156. package/dist/shared/wxr8cwns.js +0 -6
  157. package/dist/shared/zm0mafk4.js +0 -92
@@ -1,12 +1,31 @@
1
+ import {
2
+ searchValue
3
+ } from "../../shared/dzj09cye.js";
4
+ import {
5
+ rowNumber2,
6
+ rank2,
7
+ denseRank2,
8
+ runningTotal2
9
+ } from "../../shared/9a4ae4p8.js";
1
10
  import {
2
11
  jsonReplacer2,
3
12
  json2,
4
13
  jsonb2
5
14
  } from "../../shared/9628a9xt.js";
15
+ import {
16
+ bucket2
17
+ } from "../../shared/nbw1z4yd.js";
6
18
  import {
7
19
  withOwner2
8
20
  } from "../../shared/xqve9598.js";
9
21
  import {
22
+ smallint2,
23
+ integer2,
24
+ bigint2,
25
+ identity2,
26
+ encodeBigintString,
27
+ decodeBigintString,
28
+ integerToken,
10
29
  encodeInstant,
11
30
  decodeInstant,
12
31
  encodeDate,
@@ -17,22 +36,25 @@ import {
17
36
  time2,
18
37
  timetz2,
19
38
  interval2
20
- } from "../../shared/5yv4k6a6.js";
39
+ } from "../../shared/vqrjpcqn.js";
21
40
  import {
22
41
  schema2
23
- } from "../../shared/hazqqecq.js";
42
+ } from "../../shared/xnxsed62.js";
24
43
  import {
25
44
  domainType
26
45
  } from "../../shared/ywspezzx.js";
27
46
  import {
28
47
  one2,
29
48
  many2,
30
- manyThrough2
31
- } from "../../shared/k68eedmy.js";
49
+ manyThrough2,
50
+ morph2,
51
+ morphMany2,
52
+ morphTo2
53
+ } from "../../shared/exn3sd90.js";
32
54
  import {
33
55
  id2,
34
56
  uuid2
35
- } from "../../shared/2jd1sn0e.js";
57
+ } from "../../shared/hyh73qk6.js";
36
58
  import {
37
59
  text2,
38
60
  varchar2,
@@ -49,7 +71,6 @@ import {
49
71
  import {
50
72
  ColumnBuilder2,
51
73
  required,
52
- openColumn,
53
74
  formatType
54
75
  } from "../../shared/ywr8hmey.js";
55
76
  import {
@@ -95,146 +116,6 @@ function custom(spec) {
95
116
  ...spec.extension !== undefined ? { extension: spec.extension } : {}
96
117
  });
97
118
  }
98
- // src/dialects/pg/integer.ts
99
- function smallint() {
100
- return required({
101
- baseType: "smallint",
102
- encode: (value) => integerToken(value, -32768, 32767, "smallint"),
103
- decode: (wire) => decodeBounded(wire, -32768, 32767, "smallint"),
104
- sqlForm: "raw"
105
- });
106
- }
107
- function integer() {
108
- return required({
109
- baseType: "integer",
110
- encode: (value) => integerToken(value, -2147483648, 2147483647, "integer"),
111
- decode: (wire) => decodeBounded(wire, -2147483648, 2147483647, "integer"),
112
- sqlForm: "raw"
113
- });
114
- }
115
- function bigint(options) {
116
- const mode = options?.as ?? "string";
117
- if (mode === "number") {
118
- return required({
119
- baseType: "bigint",
120
- encode: encodeBigintNumber,
121
- decode: decodeBigintNumber,
122
- sqlForm: "raw",
123
- typeLabel: "number"
124
- });
125
- }
126
- if (mode === "bigint") {
127
- return required({
128
- baseType: "bigint",
129
- encode: encodeBigintValue,
130
- decode: decodeBigintValue,
131
- sqlForm: "raw",
132
- typeLabel: "bigint"
133
- });
134
- }
135
- if (mode !== "string") {
136
- definition(`bigint as ${String(mode)} must be string, number, or bigint.`);
137
- }
138
- return required({
139
- baseType: "bigint",
140
- encode: encodeBigintString,
141
- decode: decodeBigintString,
142
- sqlForm: "raw"
143
- });
144
- }
145
- function identity(options) {
146
- const mode = options?.as ?? "string";
147
- if (mode === "number") {
148
- return openColumn({
149
- ...identityFlags(),
150
- encode: encodeBigintNumber,
151
- decode: decodeBigintNumber,
152
- typeLabel: "number"
153
- });
154
- }
155
- if (mode === "bigint") {
156
- return openColumn({
157
- ...identityFlags(),
158
- encode: encodeBigintValue,
159
- decode: decodeBigintValue,
160
- typeLabel: "bigint"
161
- });
162
- }
163
- if (mode !== "string") {
164
- definition(`identity as ${String(mode)} must be string, number, or bigint.`);
165
- }
166
- return openColumn({
167
- ...identityFlags(),
168
- encode: encodeBigintString,
169
- decode: decodeBigintString
170
- });
171
- }
172
- function encodeBigintString(value) {
173
- parseBigint(value);
174
- return value;
175
- }
176
- function decodeBigintString(wire) {
177
- return encodeBigintString(wire);
178
- }
179
- function encodeBigintNumber(value) {
180
- if (!Number.isSafeInteger(value)) {
181
- rejected(`bigint number ${String(value)} must be an integer from ${String(Number.MIN_SAFE_INTEGER)} to ${String(Number.MAX_SAFE_INTEGER)}.`);
182
- }
183
- return String(value);
184
- }
185
- function decodeBigintNumber(wire) {
186
- const parsed = parseBigint(wire);
187
- const value = Number(parsed);
188
- if (!Number.isSafeInteger(value)) {
189
- rejected(`bigint ${wire} must be an integer from ${String(Number.MIN_SAFE_INTEGER)} to ${String(Number.MAX_SAFE_INTEGER)} when as is number.`);
190
- }
191
- return value;
192
- }
193
- function encodeBigintValue(value) {
194
- return value.toString();
195
- }
196
- function decodeBigintValue(wire) {
197
- return parseBigint(wire);
198
- }
199
- function integerToken(value, min, max, role) {
200
- if (!Number.isInteger(value) || value < min || value > max) {
201
- rejected(`${role} ${String(value)} must be an integer from ${String(min)} to ${String(max)}.`);
202
- }
203
- return String(value);
204
- }
205
- function decodeBounded(wire, min, max, role) {
206
- if (!integerText().test(wire)) {
207
- rejected(`${role} ${wire} must be an integer, for example 0 or -12.`);
208
- }
209
- const value = Number(wire);
210
- integerToken(value, min, max, role);
211
- return value;
212
- }
213
- function identityFlags() {
214
- return {
215
- baseType: "bigint",
216
- nullable: false,
217
- hasDefault: true,
218
- generated: false,
219
- guarded: false,
220
- hidden: false,
221
- omitWrite: true,
222
- sqlForm: "raw",
223
- identity: { always: true },
224
- primaryKey: true
225
- };
226
- }
227
- function parseBigint(wire) {
228
- if (!integerText().test(wire)) {
229
- rejected(`bigint ${wire} must be an integer with no leading zeros, for example 0 or -12.`);
230
- }
231
- return BigInt(wire);
232
- }
233
- function integerText() {
234
- integerPattern ??= /^-?(?:0|[1-9]\d*)$/;
235
- return integerPattern;
236
- }
237
- var integerPattern;
238
119
  // src/dialects/pg/finite.ts
239
120
  function decimalText(value, role) {
240
121
  if (!Number.isFinite(value)) {
@@ -761,11 +642,11 @@ function canonicalScalar(typeName) {
761
642
  // src/dialects/pg/namespace.ts
762
643
  var t = {
763
644
  id: id2,
764
- identity,
645
+ identity: identity2,
765
646
  uuid: uuid2,
766
- smallint,
767
- integer,
768
- bigint,
647
+ smallint: smallint2,
648
+ integer: integer2,
649
+ bigint: bigint2,
769
650
  numeric,
770
651
  real,
771
652
  double,
@@ -887,11 +768,11 @@ function like(pattern) {
887
768
  }
888
769
  // src/dialects/pg/ops/matches.ts
889
770
  function matches(query, options) {
890
- return tag("matches", {
891
- query,
892
- mode: options?.mode ?? "websearch",
893
- config: options?.config
894
- });
771
+ return tag("matches", searchValue(query, options));
772
+ }
773
+ // src/dialects/pg/ops/relevance.ts
774
+ function relevance(query, options) {
775
+ return tag("relevance", searchValue(query, options));
895
776
  }
896
777
  // src/dialects/pg/ops/lt.ts
897
778
  function lt(value) {
@@ -938,8 +819,9 @@ export {
938
819
  ColumnBuilder2 as ColumnBuilder,
939
820
  exports_arr_ns as arr,
940
821
  between,
941
- bigint,
822
+ bigint2 as bigint,
942
823
  boolean,
824
+ bucket2 as bucket,
943
825
  bytea,
944
826
  char2 as char,
945
827
  cidr,
@@ -949,6 +831,7 @@ export {
949
831
  custom,
950
832
  date2 as date,
951
833
  daterange,
834
+ denseRank2 as denseRank,
952
835
  domain,
953
836
  double,
954
837
  endsWith,
@@ -961,7 +844,7 @@ export {
961
844
  hasAnyKey,
962
845
  hasKey,
963
846
  id2 as id,
964
- identity,
847
+ identity2 as identity,
965
848
  ilike,
966
849
  inList,
967
850
  inc,
@@ -969,7 +852,7 @@ export {
969
852
  inet,
970
853
  int4range,
971
854
  int8range,
972
- integer,
855
+ integer2 as integer,
973
856
  interval2 as interval,
974
857
  exports_json_ns as json,
975
858
  jsonReplacer2 as jsonReplacer,
@@ -984,6 +867,9 @@ export {
984
867
  many2 as many,
985
868
  manyThrough2 as manyThrough,
986
869
  matches,
870
+ morph2 as morph,
871
+ morphMany2 as morphMany,
872
+ morphTo2 as morphTo,
987
873
  none,
988
874
  not,
989
875
  notIn,
@@ -994,9 +880,13 @@ export {
994
880
  overlaps,
995
881
  path,
996
882
  point,
883
+ rank2 as rank,
997
884
  real,
885
+ relevance,
886
+ rowNumber2 as rowNumber,
887
+ runningTotal2 as runningTotal,
998
888
  schema2 as schema,
999
- smallint,
889
+ smallint2 as smallint,
1000
890
  sql2 as sql,
1001
891
  startsWith,
1002
892
  t,
@@ -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" | "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 {};
@@ -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
@@ -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;