okmodel 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. package/README.md +100 -1131
  2. package/dist/adapters/capabilities.d.ts +35 -0
  3. package/dist/adapters/failure.d.ts +13 -2
  4. package/dist/adapters/lazy-errors.d.ts +22 -0
  5. package/dist/adapters/pg/bun-sql.d.ts +53 -0
  6. package/dist/adapters/pg/bunsql-extra.d.ts +54 -3
  7. package/dist/adapters/pg/bunsql.d.ts +15 -2
  8. package/dist/adapters/pg/cursor.d.ts +17 -0
  9. package/dist/adapters/pg/neon-extra.d.ts +18 -0
  10. package/dist/adapters/pg/neon.d.ts +104 -0
  11. package/dist/adapters/pg/no-inflight-timeout.d.ts +11 -8
  12. package/dist/adapters/pg/nodepostgres-extra.d.ts +22 -1
  13. package/dist/adapters/pg/nodepostgres.d.ts +12 -0
  14. package/dist/adapters/pg/pglite-wire.d.ts +24 -0
  15. package/dist/adapters/pg/pglite.d.ts +10 -0
  16. package/dist/adapters/pg/postgres-extra.d.ts +27 -11
  17. package/dist/adapters/pg/reserved.d.ts +42 -0
  18. package/dist/adapters/pg/session.d.ts +0 -18
  19. package/dist/contracts/connection.d.ts +7 -6
  20. package/dist/contracts/error.d.ts +1 -1
  21. package/dist/dialects/pg/floor.d.ts +68 -0
  22. package/dist/dialects/pg/fn/index.d.ts +39 -1
  23. package/dist/dialects/pg/fn/index.js +118 -26
  24. package/dist/dialects/pg/index.d.ts +8 -1
  25. package/dist/dialects/pg/index.js +435 -170
  26. package/dist/dialects/pg/introspect.d.ts +11 -0
  27. package/dist/dialects/pg/keys.d.ts +11 -8
  28. package/dist/dialects/pg/model.d.ts +40 -0
  29. package/dist/dialects/pg/morph.d.ts +43 -0
  30. package/dist/dialects/pg/operator-fit.d.ts +2 -2
  31. package/dist/dialects/pg/operators.d.ts +14 -7
  32. package/dist/dialects/pg/ops/bucket.d.ts +65 -0
  33. package/dist/dialects/pg/ops/fragment.d.ts +119 -0
  34. package/dist/dialects/pg/ops/inc.d.ts +2 -2
  35. package/dist/dialects/pg/ops/lane.d.ts +49 -0
  36. package/dist/dialects/pg/ops/matches.d.ts +9 -12
  37. package/dist/dialects/pg/ops/relevance.d.ts +13 -0
  38. package/dist/dialects/pg/ops/search-query.d.ts +22 -0
  39. package/dist/dialects/pg/ops/window.d.ts +103 -0
  40. package/dist/dialects/pg/preset.d.ts +1 -1
  41. package/dist/dialects/pg/relations.d.ts +100 -3
  42. package/dist/dialects/pg/schema.d.ts +31 -3
  43. package/dist/dialects/pg/view/client.d.ts +14 -6
  44. package/dist/dialects/pg/view/index.d.ts +73 -1
  45. package/dist/dialects/pg/view/index.js +156 -5
  46. package/dist/dialects/pg/view/scratch.d.ts +8 -5
  47. package/dist/runtime/aggregate.d.ts +8 -2
  48. package/dist/runtime/bucket-group.d.ts +70 -0
  49. package/dist/runtime/conflict.d.ts +22 -4
  50. package/dist/runtime/include.d.ts +0 -8
  51. package/dist/runtime/inflight.d.ts +1 -1
  52. package/dist/runtime/otel.d.ts +105 -0
  53. package/dist/runtime/otel.js +97 -0
  54. package/dist/runtime/page.d.ts +4 -1
  55. package/dist/runtime/pg/bun.js +12 -6
  56. package/dist/runtime/pg/neon.d.ts +38 -0
  57. package/dist/runtime/pg/neon.js +64 -0
  58. package/dist/runtime/pg/pg.js +5 -5
  59. package/dist/runtime/pg/pglite.d.ts +1 -0
  60. package/dist/runtime/pg/pglite.js +9 -9
  61. package/dist/runtime/pg/postgresjs.js +5 -5
  62. package/dist/runtime/plan.d.ts +95 -5
  63. package/dist/runtime/read-stream.d.ts +13 -16
  64. package/dist/runtime/result-name.d.ts +17 -0
  65. package/dist/runtime/server-check.d.ts +3 -3
  66. package/dist/runtime/sort-bind.d.ts +21 -0
  67. package/dist/runtime/sort.d.ts +56 -0
  68. package/dist/runtime/sql-fragment.d.ts +43 -0
  69. package/dist/runtime/sync.d.ts +70 -0
  70. package/dist/runtime/tenancy/index.js +15 -13
  71. package/dist/runtime/text-search.d.ts +20 -0
  72. package/dist/runtime/topology.d.ts +1 -1
  73. package/dist/runtime/traits/index.d.ts +80 -0
  74. package/dist/runtime/traits/index.js +184 -21
  75. package/dist/runtime/tree.d.ts +38 -0
  76. package/dist/runtime/types.d.ts +232 -22
  77. package/dist/runtime/validate/index.js +4 -4
  78. package/dist/runtime/version.d.ts +39 -0
  79. package/dist/runtime/window.d.ts +21 -0
  80. package/dist/runtime/write.d.ts +54 -2
  81. package/dist/shared/{929h19xp.js → 0wrea3jq.js} +141 -13
  82. package/dist/shared/{qq3899ht.js → 12z7aznj.js} +243 -14
  83. package/dist/shared/{1z04fa85.js → 14x60fbf.js} +12 -57
  84. package/dist/shared/{ek2wt2dz.js → 16kvjebh.js} +4 -4
  85. package/dist/shared/{wynzeggs.js → 195pzzzz.js} +8 -8
  86. package/dist/shared/1d9q9cv2.js +312 -0
  87. package/dist/shared/2c13q96h.js +18 -0
  88. package/dist/shared/{b4v57v3x.js → 2d3xq4ps.js} +2 -2
  89. package/dist/shared/{1f0xa3cb.js → 3449rcae.js} +5 -5
  90. package/dist/shared/{wkme6tep.js → 35q0n9tz.js} +8 -16
  91. package/dist/shared/3bb7wsqt.js +99 -0
  92. package/dist/shared/3t6kw83m.js +249 -0
  93. package/dist/shared/{5j36z8dn.js → 4m6hskg8.js} +39 -70
  94. package/dist/shared/{n076ydsc.js → 4vbf83xx.js} +69 -28
  95. package/dist/shared/{vmfkhszw.js → 63f4ksbz.js} +33 -26
  96. package/dist/shared/{c58secgj.js → 63qtkrca.js} +38 -4
  97. package/dist/shared/6m78c8ss.js +6 -0
  98. package/dist/shared/{x3jc53kg.js → 760ppr76.js} +15 -7
  99. package/dist/shared/7ghwamrf.js +40 -0
  100. package/dist/shared/7kms6fvj.js +20 -0
  101. package/dist/shared/7n7ddwt4.js +6 -0
  102. package/dist/shared/9a4ae4p8.js +31 -0
  103. package/dist/shared/{hazqqecq.js → 9dr2qnx7.js} +63 -34
  104. package/dist/shared/{h15jx9bc.js → 9dvh1dr6.js} +1 -1
  105. package/dist/shared/a62rb2da.js +13 -0
  106. package/dist/shared/{cgbamx3e.js → ae4j5f42.js} +23 -4
  107. package/dist/shared/agsfb86s.js +233 -0
  108. package/dist/shared/{8x72s86k.js → b6d6p0zc.js} +13 -7
  109. package/dist/shared/{ag4c7516.js → b76b8d95.js} +2 -2
  110. package/dist/shared/{j60w0dvr.js → bah9nbg3.js} +58 -38
  111. package/dist/shared/bnby0esn.js +10 -0
  112. package/dist/shared/bsek72fg.js +225 -0
  113. package/dist/shared/{2cg3wnxc.js → bxas03mq.js} +608 -141
  114. package/dist/shared/{31vm914h.js → cm3w0ywp.js} +15 -16
  115. package/dist/shared/{gwn6v667.js → cnkky55j.js} +25 -14
  116. package/dist/shared/{dk8v79p3.js → d5nmj7vv.js} +1 -1
  117. package/dist/shared/{ttmg09vd.js → dpc2r7rb.js} +8 -8
  118. package/dist/shared/dzj09cye.js +10 -0
  119. package/dist/shared/{sbdme3vy.js → e8zyaqvj.js} +60 -10
  120. package/dist/shared/{2jd1sn0e.js → ecn8mfdq.js} +6 -6
  121. package/dist/shared/exn3sd90.js +359 -0
  122. package/dist/shared/{t3g0k88x.js → f4jy1j7x.js} +39 -22
  123. package/dist/shared/{y2t3jktd.js → fjpnhqan.js} +20 -13
  124. package/dist/shared/g5yc06ka.js +272 -0
  125. package/dist/shared/ga9j92qj.js +25 -0
  126. package/dist/shared/{3fqwmr09.js → hfqmpasr.js} +6 -6
  127. package/dist/shared/{wt5rzv1h.js → hm5f8jby.js} +7 -7
  128. package/dist/shared/{ys0xzyaj.js → hqpxf4a4.js} +224 -19
  129. package/dist/shared/jebgrkeq.js +179 -0
  130. package/dist/shared/{09p049xa.js → jp36k7dp.js} +44 -16
  131. package/dist/shared/jx2m62cs.js +96 -0
  132. package/dist/shared/{r11n8grd.js → k86n8vq3.js} +7 -4
  133. package/dist/shared/{2z7wv5tj.js → kgwp4jdd.js} +56 -35
  134. package/dist/shared/{knmes2kh.js → kj9d8maq.js} +1 -1
  135. package/dist/shared/{g90m9b0g.js → m4xff2a6.js} +6 -5
  136. package/dist/shared/{r6nwkxnt.js → m7n9h2a5.js} +4 -4
  137. package/dist/shared/mfedzr74.js +145 -0
  138. package/dist/shared/{f0f1n281.js → mkrn359n.js} +60 -11
  139. package/dist/shared/{p248q79y.js → mnvjvqyp.js} +10 -10
  140. package/dist/shared/{672t5vym.js → mss6ctgv.js} +2 -2
  141. package/dist/shared/{4az561fn.js → mtw6jz76.js} +8 -23
  142. package/dist/shared/n05z9nwz.js +313 -0
  143. package/dist/shared/{pjr6xrm5.js → n0jmpgj1.js} +20 -17
  144. package/dist/shared/{p6bjzq9q.js → n41w4fbz.js} +14 -6
  145. package/dist/shared/{b3awxn7h.js → n454kcnw.js} +1 -1
  146. package/dist/shared/n7kg8mmx.js +61 -0
  147. package/dist/shared/nbw1z4yd.js +18 -0
  148. package/dist/shared/needfe47.js +66 -0
  149. package/dist/shared/{1nw1f3vs.js → njga14v4.js} +9 -9
  150. package/dist/shared/{5yv4k6a6.js → nmnsgj7x.js} +145 -3
  151. package/dist/shared/{vjpnzwjz.js → p3xbdcvt.js} +14 -18
  152. package/dist/shared/p5nh3r8q.js +622 -0
  153. package/dist/shared/{nx9hh281.js → pan0370z.js} +13 -12
  154. package/dist/shared/q0cqt2sp.js +12 -0
  155. package/dist/shared/qd9hhd8f.js +37 -0
  156. package/dist/shared/{mb2ycs1p.js → qfw14tna.js} +15 -15
  157. package/dist/shared/{9s0ypp87.js → sjk86yrx.js} +1 -1
  158. package/dist/shared/th3be82n.js +208 -0
  159. package/dist/shared/{ed0b8k4s.js → typ3vy7t.js} +1 -1
  160. package/dist/shared/{5d8t84hg.js → v1wad97q.js} +14 -14
  161. package/dist/shared/{x72jb7ad.js → v8g1vgv8.js} +1 -1
  162. package/dist/shared/{9628a9xt.js → vk7rag46.js} +1 -1
  163. package/dist/shared/{ze4hxsmy.js → w9ejzaqf.js} +1 -1
  164. package/dist/shared/{q3j1tq7a.js → wcrheftc.js} +148 -23
  165. package/dist/shared/wvdjznah.js +213 -0
  166. package/dist/shared/wz2a78mp.js +8 -0
  167. package/dist/shared/xfhe73sb.js +436 -0
  168. package/dist/shared/{r1fdd0f6.js → z581d7ny.js} +5 -2
  169. package/dist/shared/{8etn7d8w.js → z7s6fpxv.js} +1 -1
  170. package/dist/shared/{32cnm7kn.js → zbqbmmrp.js} +76 -40
  171. package/dist/shared/{n7mcc1gk.js → zchaghkf.js} +4 -3
  172. package/dist/shared/{xq0mvhts.js → zgex00fd.js} +6 -6
  173. package/dist/shared/{nsva2a6b.js → znm0bpp5.js} +3 -0
  174. package/dist/shared/zq1he88x.js +155 -0
  175. package/dist/tooling/cli.js +26 -13
  176. package/dist/tooling/driver-run.js +4971 -0
  177. package/dist/tooling/driver-test.d.ts +36 -0
  178. package/dist/tooling/migrate/commands.d.ts +2 -2
  179. package/dist/tooling/migrate/engine.d.ts +3 -2
  180. package/dist/tooling/migrate/index.js +9 -9
  181. package/dist/tooling/migrate/project.d.ts +3 -0
  182. package/dist/tooling/shared/03k6res6.js +210 -0
  183. package/dist/tooling/shared/08kemxjd.js +10 -0
  184. package/dist/tooling/shared/2revefqt.js +209 -0
  185. package/dist/tooling/shared/2wtvc7rw.js +1425 -0
  186. package/dist/tooling/shared/345tbc2k.js +16 -0
  187. package/dist/tooling/shared/3m1hkg7z.js +344 -0
  188. package/dist/tooling/shared/3rrw5w8f.js +81 -0
  189. package/dist/tooling/shared/3tq8pnb8.js +131 -0
  190. package/dist/tooling/shared/417zdsk7.js +194 -0
  191. package/dist/tooling/shared/4d2w25vw.js +40 -0
  192. package/dist/tooling/shared/54tqkxja.js +51 -0
  193. package/dist/tooling/shared/5bvw2nev.js +12 -0
  194. package/dist/tooling/shared/6nyfyw70.js +231 -0
  195. package/dist/tooling/shared/72fyg4zv.js +160 -0
  196. package/dist/tooling/shared/733a1tq3.js +38 -0
  197. package/dist/tooling/shared/7ae7rjmn.js +20 -0
  198. package/dist/tooling/shared/7kms6fvj.js +20 -0
  199. package/dist/tooling/shared/8sqrsw3s.js +49 -0
  200. package/dist/tooling/shared/96ps4g1z.js +32 -0
  201. package/dist/tooling/shared/9kazs5p6.js +195 -0
  202. package/dist/tooling/shared/9xzm7hjg.js +38 -0
  203. package/dist/tooling/shared/a6pp9d12.js +49 -0
  204. package/dist/tooling/shared/a7q7t4n3.js +22 -0
  205. package/dist/tooling/shared/aftb2mwr.js +18 -0
  206. package/dist/tooling/shared/bz2dqhab.js +311 -0
  207. package/dist/tooling/shared/cmptmb4f.js +12 -0
  208. package/dist/tooling/shared/ddjtfgnx.js +177 -0
  209. package/dist/tooling/shared/djydjpqt.js +261 -0
  210. package/dist/tooling/shared/dw08f3m8.js +9 -0
  211. package/dist/tooling/shared/dy672fz6.js +16 -0
  212. package/dist/tooling/shared/dzx85q70.js +66 -0
  213. package/dist/tooling/shared/ec71zqgt.js +270 -0
  214. package/dist/{shared/d5azex6s.js → tooling/shared/ep8zh3bk.js} +1 -1
  215. package/dist/tooling/shared/f9mphxej.js +3789 -0
  216. package/dist/tooling/shared/fb9k2qwd.js +89 -0
  217. package/dist/tooling/shared/g9ad4n80.js +211 -0
  218. package/dist/tooling/shared/gfvtj6d0.js +94 -0
  219. package/dist/tooling/shared/gmcf9cxf.js +294 -0
  220. package/dist/tooling/shared/htnaj77v.js +17 -0
  221. package/dist/tooling/shared/j9t5s12a.js +7 -0
  222. package/dist/tooling/shared/jne7b93p.js +42 -0
  223. package/dist/tooling/shared/ma2340rx.js +118 -0
  224. package/dist/tooling/shared/mtrqn2hn.js +505 -0
  225. package/dist/tooling/shared/n4jqhpqz.js +27 -0
  226. package/dist/tooling/shared/nf7jmhfa.js +20 -0
  227. package/dist/tooling/shared/p7f08ktn.js +332 -0
  228. package/dist/tooling/shared/ppnnnvj8.js +13 -0
  229. package/dist/tooling/shared/pqy21k24.js +312 -0
  230. package/dist/tooling/shared/pw8fgahx.js +69 -0
  231. package/dist/tooling/shared/pwsytxm5.js +17 -0
  232. package/dist/tooling/shared/rf83gr2d.js +94 -0
  233. package/dist/tooling/shared/rq5kk8j6.js +401 -0
  234. package/dist/tooling/shared/rs1jb051.js +12 -0
  235. package/dist/tooling/shared/smn6kz1p.js +157 -0
  236. package/dist/tooling/shared/spk1jg3r.js +1696 -0
  237. package/dist/tooling/shared/tn8gay14.js +143 -0
  238. package/dist/tooling/shared/vraj6d74.js +42 -0
  239. package/dist/tooling/shared/vs0t6qt8.js +64 -0
  240. package/dist/tooling/shared/vx86qjv8.js +150 -0
  241. package/dist/tooling/shared/w7qe8sj1.js +140 -0
  242. package/dist/tooling/shared/wt7j7nf6.js +15 -0
  243. package/dist/tooling/shared/wwnekq5n.js +6 -0
  244. package/dist/tooling/shared/xhrnjch9.js +185 -0
  245. package/dist/tooling/shared/xjs6zqtc.js +190 -0
  246. package/dist/tooling/shared/y031jct9.js +16 -0
  247. package/dist/tooling/shared/y5656f0e.js +233 -0
  248. package/dist/tooling/shared/yfr8hzhm.js +604 -0
  249. package/dist/tooling/shared/yk9mp7vb.js +250 -0
  250. package/dist/tooling/shared/yw30vnq2.js +139 -0
  251. package/dist/tooling/shared/z8d7ptht.js +618 -0
  252. package/dist/tooling/shared/zhwnfyb2.js +9 -0
  253. package/dist/tooling/shared/zvnhh1n0.js +198 -0
  254. package/dist/tooling/testing/index.js +3 -3
  255. package/package.json +17 -3
  256. package/dist/shared/3qnhc7w5.js +0 -38
  257. package/dist/shared/7m88x3e9.js +0 -45
  258. package/dist/shared/8dqhth8c.js +0 -12
  259. package/dist/shared/j3rkk835.js +0 -99
  260. package/dist/shared/k68eedmy.js +0 -85
  261. package/dist/shared/venqrjna.js +0 -216
  262. package/dist/shared/wxr8cwns.js +0 -6
  263. package/dist/shared/y34a8714.js +0 -150
  264. package/dist/shared/zm0mafk4.js +0 -92
  265. package/dist/shared/zy8r7qvz.js +0 -116
  266. package/dist/shared/{ywr8hmey.js → 606g0nbf.js} +3 -3
  267. package/dist/shared/{rpycarcr.js → gcefca6p.js} +4 -4
@@ -0,0 +1,436 @@
1
+ import {
2
+ runWrite
3
+ } from "./n4jqhpqz.js";
4
+ import {
5
+ withRowFilters,
6
+ emitWhere,
7
+ indexes,
8
+ quote,
9
+ isRecord,
10
+ fail2
11
+ } from "./kgwp4jdd.js";
12
+ import {
13
+ OkmError2
14
+ } from "./52szzakm.js";
15
+
16
+ // src/runtime/sort.ts
17
+ function insertAtEnd(table, columns, rows, group, tenantFields) {
18
+ const position = requiredColumn(table, "position");
19
+ const groupColumn = group === undefined ? undefined : requiredColumn(table, group);
20
+ const tenants = tenantColumns(table, tenantFields);
21
+ const planned = [];
22
+ const countOf = new Map;
23
+ const firstOf = new Map;
24
+ for (const row of rows) {
25
+ if (groupColumn !== undefined && !Object.hasOwn(row, groupColumn.field)) {
26
+ fail2("OKM1121", `insert on ${table.model.name} needs ${groupColumn.field} so position has a group.`, "Pass the group on the row. Position is assigned for you.");
27
+ }
28
+ const key = lockText(table.model.sql, wires(tenants, row), groupColumn === undefined ? null : cellWire(groupColumn, row[groupColumn.field]));
29
+ if (!firstOf.has(key))
30
+ firstOf.set(key, row);
31
+ const n = (countOf.get(key) ?? 0) + 1;
32
+ countOf.set(key, n);
33
+ planned.push({ key, n, row });
34
+ }
35
+ const params = [];
36
+ const bind = (wire, dataType) => {
37
+ params.push(wire);
38
+ return `$${String(params.length)}::${dataType}`;
39
+ };
40
+ const slotOf = new Map;
41
+ for (const key of firstOf.keys())
42
+ slotOf.set(key, bind(key, "text"));
43
+ const baseRows = [];
44
+ for (const [key, row] of firstOf) {
45
+ const parts = [slotOf.get(key) ?? bind(key, "text")];
46
+ if (groupColumn !== undefined)
47
+ parts.push(bind(cellWire(groupColumn, row[groupColumn.field]), groupColumn.dataType));
48
+ for (const column of tenants)
49
+ parts.push(bind(cellWire(column, row[column.field]), column.dataType));
50
+ baseRows.push(`(${parts.join(", ")})`);
51
+ }
52
+ const baseNames = ["okm_lock"];
53
+ if (groupColumn !== undefined)
54
+ baseNames.push("okm_g");
55
+ for (let index = 0;index < tenants.length; index += 1)
56
+ baseNames.push(`okm_t${String(index)}`);
57
+ const lists = planned.map((item) => {
58
+ const slot = slotOf.get(item.key) ?? bind(item.key, "text");
59
+ const slots = columns.map((column) => cell(column, item.row[column.field], bind));
60
+ slots.push(`((select b.pos from base b where b.okm_lock = ${slot}) + ${String(item.n)})::integer`);
61
+ return `(${slots.join(", ")})`;
62
+ });
63
+ const insertColumns = [...columns.map((column) => quote(column.sql)), quote(position.sql)];
64
+ const text = [
65
+ "with base as (",
66
+ "select i.okm_lock, coalesce(max(t.",
67
+ quote(position.sql),
68
+ "), 0) as pos from (values ",
69
+ baseRows.join(", "),
70
+ ") as i(",
71
+ baseNames.join(", "),
72
+ ") left join ",
73
+ quote(table.model.sql),
74
+ " as t on ",
75
+ joinOn(groupColumn, tenants),
76
+ " group by i.okm_lock",
77
+ ") insert into ",
78
+ quote(table.model.sql),
79
+ " (",
80
+ insertColumns.join(", "),
81
+ ") values ",
82
+ lists.join(", ")
83
+ ].join("");
84
+ return { lock: groupLock([...firstOf.keys()]), text, params };
85
+ }
86
+ async function move(host, tableName, id, place, view) {
87
+ await host.connected;
88
+ const table = indexes(host.schema).get(tableName);
89
+ if (table === undefined)
90
+ fail2("OKM1120", `Table ${tableName} is not in the schema.`);
91
+ const group = groupField(table);
92
+ if (!sortable(table)) {
93
+ fail2("OKM1120", `move on ${tableName} needs sortable().`, "Add sortable() from okmodel/traits.");
94
+ }
95
+ const anchor = readPlace(place, tableName);
96
+ const key = moveColumn(host.schema, table);
97
+ if (sameId(id, anchor.id)) {
98
+ const current = await readOne(host, table, key, id, group, view);
99
+ if (current === undefined)
100
+ missing(tableName, id);
101
+ return { position: current.position };
102
+ }
103
+ const moved = await readOne(host, table, key, id, group, view);
104
+ if (moved === undefined)
105
+ missing(tableName, id);
106
+ const other = await readOne(host, table, key, anchor.id, group, view);
107
+ if (other === undefined)
108
+ missing(tableName, anchor.id);
109
+ if (moved.groupWire !== other.groupWire) {
110
+ const which = group ?? "group";
111
+ throw new OkmError2("OKM1120", `move on ${tableName} cannot place ${show(id)} ${anchor.side} ${show(anchor.id)}. ${show(anchor.id)} is in another ${which}.`, { fix: { summary: `Choose an anchor in the same ${which}.` } });
112
+ }
113
+ const statements = withRowFilters(host.scope, view, () => moveStatements(host.schema, table, key, id, anchor.id, moved, anchor.side, group));
114
+ const results = await runWrite(host, statements, callOptions(host));
115
+ const row = results[1]?.rows[0];
116
+ if (count(row?.[0]) !== 1)
117
+ missing(tableName, id);
118
+ if (count(row?.[1]) !== 1)
119
+ missing(tableName, anchor.id);
120
+ return { position: count(row?.[2]) };
121
+ }
122
+ function sortable(table) {
123
+ const traits = table.model.traits;
124
+ if (traits === undefined)
125
+ return false;
126
+ for (const trait of traits)
127
+ if (trait.name === "sortable")
128
+ return true;
129
+ return false;
130
+ }
131
+ function groupField(table) {
132
+ const traits = table.model.traits;
133
+ if (traits === undefined)
134
+ return;
135
+ for (const trait of traits) {
136
+ if (trait.name !== "sortable")
137
+ continue;
138
+ const group = trait.group;
139
+ return typeof group === "string" ? group : undefined;
140
+ }
141
+ return;
142
+ }
143
+ function readPlace(place, table) {
144
+ if (!isRecord(place))
145
+ fail2("OKM1120", `move on ${table} needs { before } or { after }.`);
146
+ const before = Object.hasOwn(place, "before");
147
+ const after = Object.hasOwn(place, "after");
148
+ if (before === after) {
149
+ fail2("OKM1120", `move on ${table} needs before or after, not both.`, "Pass one anchor.");
150
+ }
151
+ for (const key of Object.keys(place)) {
152
+ if (key === "before" || key === "after")
153
+ continue;
154
+ fail2("OKM1120", `move on ${table} does not accept ${key}. Accepted options: before, after.`);
155
+ }
156
+ return { side: before ? "before" : "after", id: before ? place.before : place.after };
157
+ }
158
+ function moveColumn(schema, table) {
159
+ const tenants = new Set(tenantFieldNames(schema.tenancy, table));
160
+ const fields = table.model.primary.filter((field) => !tenants.has(field));
161
+ if (fields.length !== 1) {
162
+ fail2("OKM1120", `move on ${table.model.name} needs one primary key column besides the tenant key.`);
163
+ }
164
+ return requiredColumn(table, fields[0] ?? "");
165
+ }
166
+ function tenantFieldNames(tenancy, table) {
167
+ if (tenancy === undefined)
168
+ return [];
169
+ const keys = tenancy.keys ?? [tenancy.key];
170
+ return keys.filter((key) => table.columns.has(key));
171
+ }
172
+ async function readOne(host, table, key, id, group, view) {
173
+ const position = requiredColumn(table, "position");
174
+ const groupColumn = group === undefined ? undefined : requiredColumn(table, group);
175
+ const tenants = tenantColumns(table, tenantFieldNames(host.schema.tenancy, table));
176
+ const statement = withRowFilters(host.scope, view, () => {
177
+ const parts = [];
178
+ const params = [];
179
+ parts.push("select ");
180
+ parts.push(quote(position.sql));
181
+ if (groupColumn !== undefined) {
182
+ parts.push(", ");
183
+ parts.push(quote(groupColumn.sql));
184
+ }
185
+ for (const column of tenants) {
186
+ parts.push(", ");
187
+ parts.push(quote(column.sql));
188
+ }
189
+ parts.push(" from ");
190
+ parts.push(quote(table.model.sql));
191
+ parts.push(" as t where t.");
192
+ parts.push(quote(key.sql));
193
+ parts.push(" = $1::");
194
+ parts.push(key.dataType);
195
+ params.push(key.encode(id));
196
+ emitWhere(host.schema, table, undefined, sink(parts, params), "t", 0, true);
197
+ return { text: parts.join(""), params };
198
+ });
199
+ const result = await host.pool.execute(statement.text, statement.params, callOptions(host));
200
+ const found = result.rows[0];
201
+ if (found === undefined)
202
+ return;
203
+ let at = 1;
204
+ const groupWire = groupColumn === undefined ? null : decodeWire(groupColumn, found[at]);
205
+ if (groupColumn !== undefined)
206
+ at += 1;
207
+ const tenantWires = [];
208
+ for (const column of tenants) {
209
+ tenantWires.push(decodeWire(column, found[at]));
210
+ at += 1;
211
+ }
212
+ return { position: count(found[0]), groupWire, tenants: tenantWires };
213
+ }
214
+ function moveStatements(schema, table, key, id, anchor, moved, side, group) {
215
+ const lock = groupLock([lockText(table.model.sql, moved.tenants, moved.groupWire)]);
216
+ const place = moveStatement(schema, table, key, id, anchor, moved, side, group);
217
+ const tenants = tenantColumns(table, tenantFieldNames(schema.tenancy, table));
218
+ return [lock, place, flipStatement(table, moved, group, tenants)];
219
+ }
220
+ function moveStatement(schema, table, key, id, anchor, moved, side, group) {
221
+ const position = requiredColumn(table, "position");
222
+ const groupColumn = group === undefined ? undefined : requiredColumn(table, group);
223
+ const tenants = tenantColumns(table, tenantFieldNames(schema.tenancy, table));
224
+ const params = [];
225
+ const bind = (wire, dataType) => {
226
+ params.push(wire);
227
+ return `$${String(params.length)}::${dataType}`;
228
+ };
229
+ const groupSlot = groupColumn === undefined ? "" : bind(moved.groupWire, groupColumn.dataType);
230
+ const tenantSlots = tenants.map((column, index) => bind(moved.tenants[index] ?? null, column.dataType));
231
+ const movedSlot = bind(key.encode(id), key.dataType);
232
+ const anchorSlot = bind(key.encode(anchor), key.dataType);
233
+ const delta = bind(side === "before" ? "-0.5" : "0.5", "numeric");
234
+ const parts = [];
235
+ parts.push("with members as (select t.ctid as tid, t.tableoid as toid, t.");
236
+ parts.push(quote(position.sql));
237
+ parts.push(" as pos, t.");
238
+ parts.push(quote(key.sql));
239
+ parts.push(" as ident from ");
240
+ parts.push(quote(table.model.sql));
241
+ parts.push(" as t");
242
+ let filtered = false;
243
+ if (groupColumn !== undefined) {
244
+ parts.push(" where t.");
245
+ parts.push(quote(groupColumn.sql));
246
+ parts.push(" is not distinct from ");
247
+ parts.push(groupSlot);
248
+ filtered = true;
249
+ }
250
+ for (let index = 0;index < tenants.length; index += 1) {
251
+ const column = tenants[index];
252
+ if (column === undefined)
253
+ continue;
254
+ parts.push(filtered ? " and t." : " where t.");
255
+ parts.push(quote(column.sql));
256
+ parts.push(" is not distinct from ");
257
+ parts.push(tenantSlots[index] ?? "null");
258
+ filtered = true;
259
+ }
260
+ emitWhere(schema, table, undefined, sink(parts, params), "t", 0, filtered);
261
+ parts.push(" for update of t), numbered as (select ident, pos, tid, toid, row_number() over (order by pos, ident) as ord from members), placed as (select ident, pos, tid, toid, row_number() over (order by case when ident = ");
262
+ parts.push(movedSlot);
263
+ parts.push(" then (select ord from numbered where ident = ");
264
+ parts.push(anchorSlot);
265
+ parts.push(") + ");
266
+ parts.push(delta);
267
+ parts.push(" else ord end, case when ident = ");
268
+ parts.push(movedSlot);
269
+ parts.push(" then 0 else 1 end) as new_pos from numbered where (select count(*) from numbered where ident = ");
270
+ parts.push(movedSlot);
271
+ parts.push(") = 1 and (select count(*) from numbered where ident = ");
272
+ parts.push(anchorSlot);
273
+ parts.push(") = 1), changed as (update ");
274
+ parts.push(quote(table.model.sql));
275
+ parts.push(" as t set ");
276
+ parts.push(quote(position.sql));
277
+ parts.push(" = (-p.new_pos)::integer from placed as p where t.ctid = p.tid and t.tableoid = p.toid returning t.ctid) select (select count(*)::int from numbered where ident = ");
278
+ parts.push(movedSlot);
279
+ parts.push("), (select count(*)::int from numbered where ident = ");
280
+ parts.push(anchorSlot);
281
+ parts.push("), coalesce((select new_pos::int from placed where ident = ");
282
+ parts.push(movedSlot);
283
+ parts.push("), 0), (select count(*)::int from changed)");
284
+ return { text: parts.join(""), ...params.length > 0 ? { params } : {} };
285
+ }
286
+ function flipStatement(table, moved, group, tenants) {
287
+ const position = requiredColumn(table, "position");
288
+ const groupColumn = group === undefined ? undefined : requiredColumn(table, group);
289
+ const params = [];
290
+ const bind = (wire, dataType) => {
291
+ params.push(wire);
292
+ return `$${String(params.length)}::${dataType}`;
293
+ };
294
+ const parts = [
295
+ "update ",
296
+ quote(table.model.sql),
297
+ " as t set ",
298
+ quote(position.sql),
299
+ " = (-t.",
300
+ quote(position.sql),
301
+ ")::integer where t.",
302
+ quote(position.sql),
303
+ " < 0"
304
+ ];
305
+ if (groupColumn !== undefined) {
306
+ parts.push(" and t.");
307
+ parts.push(quote(groupColumn.sql));
308
+ parts.push(" is not distinct from ");
309
+ parts.push(bind(moved.groupWire, groupColumn.dataType));
310
+ }
311
+ for (let index = 0;index < tenants.length; index += 1) {
312
+ const column = tenants[index];
313
+ if (column === undefined)
314
+ continue;
315
+ parts.push(" and t.");
316
+ parts.push(quote(column.sql));
317
+ parts.push(" is not distinct from ");
318
+ parts.push(bind(moved.tenants[index] ?? null, column.dataType));
319
+ }
320
+ return { text: parts.join(""), ...params.length > 0 ? { params } : {} };
321
+ }
322
+ function joinOn(group, tenants) {
323
+ const parts = [];
324
+ if (group !== undefined)
325
+ parts.push(`t.${quote(group.sql)} is not distinct from i.okm_g`);
326
+ for (let index = 0;index < tenants.length; index += 1) {
327
+ const column = tenants[index];
328
+ if (column === undefined)
329
+ continue;
330
+ parts.push(`t.${quote(column.sql)} is not distinct from i.okm_t${String(index)}`);
331
+ }
332
+ return parts.length === 0 ? "true" : parts.join(" and ");
333
+ }
334
+ function lockText(sqlName, tenants, group) {
335
+ return JSON.stringify([sqlName, tenants, group]);
336
+ }
337
+ function groupLock(keys) {
338
+ const ordered = [...keys].sort(compareText);
339
+ const values = ordered.map((_, index) => `($${String(index + 1)}::text)`).join(", ");
340
+ return {
341
+ text: `select pg_advisory_xact_lock(hashtextextended(k.okm_lock, 0::bigint)) from (select v.okm_lock from (values ${values}) as v(okm_lock) order by v.okm_lock) as k`,
342
+ params: ordered
343
+ };
344
+ }
345
+ function compareText(left, right) {
346
+ if (left < right)
347
+ return -1;
348
+ if (left > right)
349
+ return 1;
350
+ return 0;
351
+ }
352
+ function wires(columns, row) {
353
+ return columns.map((column) => cellWire(column, row[column.field]));
354
+ }
355
+ function cellWire(column, value) {
356
+ if (value === undefined || value === null)
357
+ return null;
358
+ return column.encode(value);
359
+ }
360
+ function cell(column, value, bind) {
361
+ if (value === undefined)
362
+ return "default";
363
+ if (value === null)
364
+ return bind(null, column.dataType);
365
+ return bind(column.encode(value), column.dataType);
366
+ }
367
+ function decodeWire(column, value) {
368
+ if (value === null || value === undefined)
369
+ return null;
370
+ if (typeof value === "string") {
371
+ const decode = column.decode;
372
+ return column.encode(decode === undefined ? value : decode(value));
373
+ }
374
+ return column.encode(value);
375
+ }
376
+ function tenantColumns(table, fields) {
377
+ if (fields === undefined)
378
+ return [];
379
+ const columns = [];
380
+ for (const field of fields) {
381
+ const column = table.columns.get(field);
382
+ if (column !== undefined)
383
+ columns.push(column);
384
+ }
385
+ return columns;
386
+ }
387
+ function requiredColumn(table, field) {
388
+ const column = table.columns.get(field);
389
+ if (column === undefined)
390
+ fail2("OKM1120", `Table ${table.model.name} has no column ${field}.`);
391
+ return column;
392
+ }
393
+ function missing(table, id) {
394
+ throw new OkmError2("not_found", `move on ${table} could not find ${show(id)}.`, {
395
+ kind: "not_found",
396
+ table,
397
+ fix: { summary: "Pass the id of a row in this table." }
398
+ });
399
+ }
400
+ function show(id) {
401
+ if (typeof id === "string" || typeof id === "number")
402
+ return String(id);
403
+ return "that id";
404
+ }
405
+ function sameId(left, right) {
406
+ return left === right;
407
+ }
408
+ function count(value) {
409
+ if (typeof value === "number")
410
+ return value;
411
+ if (typeof value === "bigint")
412
+ return Number(value);
413
+ if (typeof value === "string" && value.length > 0)
414
+ return Number(value);
415
+ return 0;
416
+ }
417
+ function sink(parts, params) {
418
+ return {
419
+ text(value) {
420
+ parts.push(value);
421
+ },
422
+ param(encoded) {
423
+ params.push(encoded);
424
+ parts.push(`$${String(params.length)}`);
425
+ },
426
+ mark() {}
427
+ };
428
+ }
429
+ function callOptions(host) {
430
+ const limit = host.timeouts?.statement;
431
+ return limit === undefined ? undefined : { timeout: limit };
432
+ }
433
+ export {
434
+ insertAtEnd,
435
+ move
436
+ };
@@ -2,17 +2,20 @@ import {
2
2
  checkout2,
3
3
  describe2,
4
4
  stream2,
5
+ runBatch2,
5
6
  watchReserved2,
6
7
  holdCheckout2,
7
8
  holdListener2,
8
9
  watchQuery2
9
- } from "./q3j1tq7a.js";
10
- import"./wkme6tep.js";
10
+ } from "./wcrheftc.js";
11
+ import"./35q0n9tz.js";
12
+ import"./cm3w0ywp.js";
11
13
  export {
12
14
  checkout2 as checkout,
13
15
  describe2 as describe,
14
16
  holdCheckout2 as holdCheckout,
15
17
  holdListener2 as holdListener,
18
+ runBatch2 as runBatch,
16
19
  stream2 as stream,
17
20
  watchQuery2 as watchQuery,
18
21
  watchReserved2 as watchReserved
@@ -39,7 +39,7 @@ async function refreshView(session, name, concurrently) {
39
39
  throw error;
40
40
  }
41
41
  } catch (error) {
42
- const { mapPostgresError } = await import("./d5azex6s.js");
42
+ const { mapPostgresError } = await import("./63qtkrca.js");
43
43
  const mapped = mapPostgresError(error, {
44
44
  ...host.http !== undefined ? { http: host.http } : {},
45
45
  ...host.includeValues === true ? { includeValues: true } : {},
@@ -1,21 +1,27 @@
1
1
  import {
2
- noTimeout2
3
- } from "./8dqhth8c.js";
2
+ DriverError2
3
+ } from "./cm3w0ywp.js";
4
+ import {
5
+ noTimeout
6
+ } from "./q0cqt2sp.js";
4
7
  import {
5
8
  noticeBuffer,
6
- WireSession,
7
- cursorStream
8
- } from "./4az561fn.js";
9
+ WireSession
10
+ } from "./mtw6jz76.js";
9
11
  import {
10
12
  BUNSQL_CAPABILITIES,
11
13
  driverErrors,
12
14
  rejectClosed,
13
15
  mapFailure,
14
16
  runCall
15
- } from "./cgbamx3e.js";
17
+ } from "./ae4j5f42.js";
16
18
 
17
19
  // src/adapters/pg/bunsql.ts
18
- import { SQL } from "bun";
20
+ import { SQL as BunSQL } from "bun";
21
+ var clientPools = new WeakSet;
22
+ function markClientPool(pool) {
23
+ clientPools.add(pool);
24
+ }
19
25
  function open5(config) {
20
26
  const max = config.max ?? 10;
21
27
  const acquireMs = config.timeouts?.acquire;
@@ -25,7 +31,9 @@ function open5(config) {
25
31
  const isClosed = () => closed;
26
32
  const named = config.prepared === "named";
27
33
  const parked = [];
28
- const sql = new SQL(config.url, {
34
+ let dropped = 0;
35
+ let closures = 0;
36
+ const sql = new BunSQL(config.url, {
29
37
  max,
30
38
  idleTimeout: 0,
31
39
  maxLifetime: 0,
@@ -36,26 +44,53 @@ function open5(config) {
36
44
  application_name: "okmodel",
37
45
  ...config.searchPath !== undefined ? { search_path: config.searchPath } : {}
38
46
  },
39
- ...config.ssl !== undefined ? { tls: config.ssl } : {}
47
+ ...config.ssl !== undefined ? { tls: config.ssl } : {},
48
+ onclose() {
49
+ dropped += 1;
50
+ closures += 1;
51
+ }
40
52
  });
41
53
  const root = new WireSession((text, params) => send2(sql, text, params), notices, isClosed, false, () => {
42
54
  counters.busy += 1;
43
55
  }, () => {
44
56
  counters.busy = Math.max(0, counters.busy - 1);
45
57
  });
46
- const held = { sql, parked, acquireMs, counters, notices, isClosed };
47
- const checkout = () => closed ? rejectClosed() : import("./j3rkk835.js").then((mod) => mod.checkout(held));
48
- return {
58
+ const held = {
59
+ sql,
60
+ parked,
61
+ acquireMs,
62
+ counters,
63
+ notices,
64
+ isClosed,
65
+ closures: () => closures
66
+ };
67
+ const run = (text, params, watch) => {
68
+ const sent = dropped;
69
+ return root.query(text, params, watch).catch((error) => import("./wvdjznah.js").then((mod) => mod.recover(sql, error, text, root.depth(), clientPools.has(pool), dropped > sent, () => root.query(text, params, watch))));
70
+ };
71
+ const afterDrop = (text, params, watch) => {
72
+ if (dropped === 0)
73
+ return run(text, params, watch);
74
+ const seen = dropped;
75
+ return import("./wvdjznah.js").then((mod) => mod.drainClosed(sql).then(() => {
76
+ if (dropped === seen)
77
+ dropped = 0;
78
+ return run(text, params, watch);
79
+ }));
80
+ };
81
+ const checkout = () => closed ? rejectClosed() : import("./wvdjznah.js").then((mod) => mod.checkout(held));
82
+ const pool = {
49
83
  capabilities: BUNSQL_CAPABILITIES,
50
84
  execute(text, params, options) {
51
- noTimeout2(options);
52
- return runCall(closed, options, async (watch) => {
53
- await releaseParked(parked);
54
- return root.query(text, params, watch);
55
- });
85
+ const refused = noTimeout(options);
86
+ if (refused !== undefined)
87
+ return refused;
88
+ return runCall(closed, options, (watch) => releaseParked(parked).then(() => afterDrop(text, params, watch)));
56
89
  },
57
90
  async batch(statements, options) {
58
- noTimeout2(options);
91
+ const refused = noTimeout(options);
92
+ if (refused !== undefined)
93
+ return refused;
59
94
  const connection = await checkout();
60
95
  try {
61
96
  return await connection.batch(statements, options);
@@ -65,10 +100,13 @@ function open5(config) {
65
100
  },
66
101
  reserve: () => checkout(),
67
102
  stream(text, params) {
68
- return stream(text, params);
103
+ return async function* () {
104
+ const { streamRows } = await import("./wvdjznah.js");
105
+ yield* streamRows(checkout, text, params);
106
+ }();
69
107
  },
70
108
  listen(channel, onNotify) {
71
- return listen(channel, onNotify);
109
+ return import("./wvdjznah.js").then((mod) => mod.listen(sql, parked, closed, channel, onNotify));
72
110
  },
73
111
  stats: () => statsOf(counters, max),
74
112
  async close() {
@@ -77,31 +115,29 @@ function open5(config) {
77
115
  await sql.close();
78
116
  }
79
117
  };
80
- function stream(text, params) {
81
- return async function* () {
82
- const connection = await checkout();
83
- try {
84
- yield* cursorStream((statement, values) => connection.execute(statement, values), text, params);
85
- } finally {
86
- await connection.release();
87
- }
88
- }();
89
- }
90
- async function listen(channel, onNotify) {
91
- if (closed)
92
- return rejectClosed();
93
- await releaseParked(parked);
94
- const subscription = await sql.listen(channel, onNotify);
95
- return async () => {
96
- await subscription.unlisten();
97
- };
98
- }
118
+ return pool;
99
119
  }
100
120
  function send2(sql, text, params) {
121
+ const refused = refuseInt8(params);
122
+ if (refused !== undefined)
123
+ return refused;
101
124
  if (params === undefined || params.length === 0)
102
125
  return sql.unsafe(text).raw();
103
126
  return sql.unsafe(text, [...params]).raw();
104
127
  }
128
+ function refuseInt8(params) {
129
+ if (params === undefined)
130
+ return;
131
+ for (const value of params) {
132
+ if (value === null || value.length < 19 || !/^-?(?:0|[1-9]\d*)$/.test(value))
133
+ continue;
134
+ const parsed = BigInt(value);
135
+ if (parsed > 9223372036854775807n || parsed < -9223372036854775808n) {
136
+ return Promise.reject(new DriverError2("bigint out of range", { sqlstate: "22003" }));
137
+ }
138
+ }
139
+ return;
140
+ }
105
141
  async function reserve(sql, acquireMs, counters) {
106
142
  counters.waiting += 1;
107
143
  try {
@@ -151,4 +187,4 @@ function statsOf(counters, size) {
151
187
  };
152
188
  }
153
189
 
154
- export { open5, send2, reserve, park };
190
+ export { markClientPool, open5, send2, reserve, park };
@@ -18,6 +18,7 @@ var FAMILIES = {
18
18
  hasAnyKey: ["jsonb"],
19
19
  path: ["json", "jsonb"],
20
20
  matches: ["tsvector"],
21
+ relevance: ["tsvector"],
21
22
  "json.set": ["json", "jsonb"],
22
23
  "arr.append": ["array"],
23
24
  "arr.remove": ["array"]
@@ -53,7 +54,7 @@ var ACCEPTED = {
53
54
  jsonb: ["eq", "not", "contains", "containedBy", "hasKey", "hasAnyKey", "path", "json.set"],
54
55
  json: ["eq", "not", "path", "json.set"],
55
56
  range: ["eq", "not", "lt", "lte", "gt", "gte", "contains", "containedBy", "overlaps"],
56
- tsvector: ["eq", "not", "matches"],
57
+ tsvector: ["eq", "not", "matches", "relevance"],
57
58
  scalar: ["eq", "not", "lt", "lte", "gt", "gte", "between", "inList", "notIn", "inc"]
58
59
  };
59
60
  var SAFE_TYPE = /^[A-Za-z_][A-Za-z0-9_]*(\(\d+\))?(\[\])*$/;
@@ -81,7 +82,7 @@ function assertOperatorFits(column, name) {
81
82
  if (families.includes(columnFamily(column.dataType)))
82
83
  return;
83
84
  const accepted = ACCEPTED[columnFamily(column.dataType)];
84
- const search = name === "matches" && columnFamily(column.dataType) === "text" ? " Text search needs a tsvector column." : "";
85
+ const search = (name === "matches" || name === "relevance") && columnFamily(column.dataType) === "text" ? " Search needs a column built for search, not a plain text column." : "";
85
86
  throw new OkmError2("OKM1124", `Operator ${name} does not apply to ${column.dataType} column ${column.field}. Accepted operators: ${accepted.join(", ")}.${search}`, { fix: { summary: `Use one of: ${accepted.join(", ")}.` } });
86
87
  }
87
88
  function sqlType(dataType, column) {
@@ -110,7 +111,7 @@ function assertBoundText(value, role) {
110
111
  }
111
112
  function assertRegconfig(config) {
112
113
  if (!REGCONFIG.test(config)) {
113
- throw new OkmError2("OKM1122", `Text search config ${config} must be a regconfig name such as english or pg_catalog.simple.`, { fix: { summary: "Pass a regconfig name. Quotes and extra clauses are not accepted." } });
114
+ throw new OkmError2("OKM1122", `Language ${config} is not a text search language. Pass a name such as english.`, { fix: { summary: "Pass a language name such as english." } });
114
115
  }
115
116
  }
116
117
  function textArray(values, role) {