@intentius/sql-yodeler 0.0.0-stage → 0.2.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 (324) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +112 -2
  3. package/dist/bin.d.ts +2 -0
  4. package/dist/bin.js +29 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/chant/apply.d.ts +59 -0
  7. package/dist/chant/apply.js +116 -0
  8. package/dist/chant/apply.js.map +1 -0
  9. package/dist/chant/build.d.ts +34 -0
  10. package/dist/chant/build.js +48 -0
  11. package/dist/chant/build.js.map +1 -0
  12. package/dist/chant/drift.d.ts +112 -0
  13. package/dist/chant/drift.js +238 -0
  14. package/dist/chant/drift.js.map +1 -0
  15. package/dist/chant/plan.d.ts +45 -0
  16. package/dist/chant/plan.js +61 -0
  17. package/dist/chant/plan.js.map +1 -0
  18. package/dist/chant/process.d.ts +41 -0
  19. package/dist/chant/process.js +87 -0
  20. package/dist/chant/process.js.map +1 -0
  21. package/dist/chant/runnable.d.ts +19 -0
  22. package/dist/chant/runnable.js +47 -0
  23. package/dist/chant/runnable.js.map +1 -0
  24. package/dist/cli.d.ts +8 -0
  25. package/dist/cli.js +99 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/command.d.ts +23 -0
  28. package/dist/command.js +13 -0
  29. package/dist/command.js.map +1 -0
  30. package/dist/commands/apply.d.ts +3 -0
  31. package/dist/commands/apply.js +426 -0
  32. package/dist/commands/apply.js.map +1 -0
  33. package/dist/commands/approve.d.ts +5 -0
  34. package/dist/commands/approve.js +111 -0
  35. package/dist/commands/approve.js.map +1 -0
  36. package/dist/commands/drift.d.ts +14 -0
  37. package/dist/commands/drift.js +267 -0
  38. package/dist/commands/drift.js.map +1 -0
  39. package/dist/commands/index.d.ts +3 -0
  40. package/dist/commands/index.js +28 -0
  41. package/dist/commands/index.js.map +1 -0
  42. package/dist/commands/init.d.ts +6 -0
  43. package/dist/commands/init.js +139 -0
  44. package/dist/commands/init.js.map +1 -0
  45. package/dist/commands/lint.d.ts +3 -0
  46. package/dist/commands/lint.js +202 -0
  47. package/dist/commands/lint.js.map +1 -0
  48. package/dist/commands/mcp.d.ts +3 -0
  49. package/dist/commands/mcp.js +50 -0
  50. package/dist/commands/mcp.js.map +1 -0
  51. package/dist/commands/new.d.ts +5 -0
  52. package/dist/commands/new.js +292 -0
  53. package/dist/commands/new.js.map +1 -0
  54. package/dist/commands/override.d.ts +3 -0
  55. package/dist/commands/override.js +118 -0
  56. package/dist/commands/override.js.map +1 -0
  57. package/dist/commands/plan.d.ts +3 -0
  58. package/dist/commands/plan.js +183 -0
  59. package/dist/commands/plan.js.map +1 -0
  60. package/dist/commands/rebase.d.ts +3 -0
  61. package/dist/commands/rebase.js +167 -0
  62. package/dist/commands/rebase.js.map +1 -0
  63. package/dist/commands/repair.d.ts +14 -0
  64. package/dist/commands/repair.js +125 -0
  65. package/dist/commands/repair.js.map +1 -0
  66. package/dist/commands/status.d.ts +7 -0
  67. package/dist/commands/status.js +54 -0
  68. package/dist/commands/status.js.map +1 -0
  69. package/dist/config/define.d.ts +148 -0
  70. package/dist/config/define.js +20 -0
  71. package/dist/config/define.js.map +1 -0
  72. package/dist/config/index.d.ts +11 -0
  73. package/dist/config/index.js +12 -0
  74. package/dist/config/index.js.map +1 -0
  75. package/dist/config/load.d.ts +17 -0
  76. package/dist/config/load.js +162 -0
  77. package/dist/config/load.js.map +1 -0
  78. package/dist/config/settings.d.ts +53 -0
  79. package/dist/config/settings.js +116 -0
  80. package/dist/config/settings.js.map +1 -0
  81. package/dist/env-args.d.ts +24 -0
  82. package/dist/env-args.js +92 -0
  83. package/dist/env-args.js.map +1 -0
  84. package/dist/exit.d.ts +20 -0
  85. package/dist/exit.js +28 -0
  86. package/dist/exit.js.map +1 -0
  87. package/dist/history/client.d.ts +25 -0
  88. package/dist/history/client.js +42 -0
  89. package/dist/history/client.js.map +1 -0
  90. package/dist/history/ddl.d.ts +58 -0
  91. package/dist/history/ddl.js +100 -0
  92. package/dist/history/ddl.js.map +1 -0
  93. package/dist/history/index.d.ts +25 -0
  94. package/dist/history/index.js +26 -0
  95. package/dist/history/index.js.map +1 -0
  96. package/dist/history/lock.d.ts +104 -0
  97. package/dist/history/lock.js +230 -0
  98. package/dist/history/lock.js.map +1 -0
  99. package/dist/history/postgres/ddl.d.ts +22 -0
  100. package/dist/history/postgres/ddl.js +47 -0
  101. package/dist/history/postgres/ddl.js.map +1 -0
  102. package/dist/history/postgres/index.d.ts +12 -0
  103. package/dist/history/postgres/index.js +13 -0
  104. package/dist/history/postgres/index.js.map +1 -0
  105. package/dist/history/postgres/lock.d.ts +48 -0
  106. package/dist/history/postgres/lock.js +95 -0
  107. package/dist/history/postgres/lock.js.map +1 -0
  108. package/dist/history/postgres/store.d.ts +39 -0
  109. package/dist/history/postgres/store.js +68 -0
  110. package/dist/history/postgres/store.js.map +1 -0
  111. package/dist/history/rows.d.ts +96 -0
  112. package/dist/history/rows.js +73 -0
  113. package/dist/history/rows.js.map +1 -0
  114. package/dist/history/store.d.ts +72 -0
  115. package/dist/history/store.js +134 -0
  116. package/dist/history/store.js.map +1 -0
  117. package/dist/history/topology.d.ts +41 -0
  118. package/dist/history/topology.js +54 -0
  119. package/dist/history/topology.js.map +1 -0
  120. package/dist/index.d.ts +10 -0
  121. package/dist/index.js +10 -0
  122. package/dist/index.js.map +1 -0
  123. package/dist/init/adopt.d.ts +70 -0
  124. package/dist/init/adopt.js +143 -0
  125. package/dist/init/adopt.js.map +1 -0
  126. package/dist/init/baseline.d.ts +61 -0
  127. package/dist/init/baseline.js +88 -0
  128. package/dist/init/baseline.js.map +1 -0
  129. package/dist/init/files.d.ts +23 -0
  130. package/dist/init/files.js +77 -0
  131. package/dist/init/files.js.map +1 -0
  132. package/dist/init/index.d.ts +16 -0
  133. package/dist/init/index.js +17 -0
  134. package/dist/init/index.js.map +1 -0
  135. package/dist/init/live.d.ts +39 -0
  136. package/dist/init/live.js +68 -0
  137. package/dist/init/live.js.map +1 -0
  138. package/dist/lint/check.d.ts +88 -0
  139. package/dist/lint/check.js +227 -0
  140. package/dist/lint/check.js.map +1 -0
  141. package/dist/lint/config.d.ts +21 -0
  142. package/dist/lint/config.js +43 -0
  143. package/dist/lint/config.js.map +1 -0
  144. package/dist/lint/index.d.ts +31 -0
  145. package/dist/lint/index.js +43 -0
  146. package/dist/lint/index.js.map +1 -0
  147. package/dist/lint/project-rules.d.ts +19 -0
  148. package/dist/lint/project-rules.js +32 -0
  149. package/dist/lint/project-rules.js.map +1 -0
  150. package/dist/lint/report.d.ts +7 -0
  151. package/dist/lint/report.js +48 -0
  152. package/dist/lint/report.js.map +1 -0
  153. package/dist/lint/rules.d.ts +53 -0
  154. package/dist/lint/rules.js +42 -0
  155. package/dist/lint/rules.js.map +1 -0
  156. package/dist/lint/silences.d.ts +49 -0
  157. package/dist/lint/silences.js +91 -0
  158. package/dist/lint/silences.js.map +1 -0
  159. package/dist/lint/statements.d.ts +38 -0
  160. package/dist/lint/statements.js +120 -0
  161. package/dist/lint/statements.js.map +1 -0
  162. package/dist/mcp/server.d.ts +40 -0
  163. package/dist/mcp/server.js +106 -0
  164. package/dist/mcp/server.js.map +1 -0
  165. package/dist/mcp/tools.d.ts +72 -0
  166. package/dist/mcp/tools.js +178 -0
  167. package/dist/mcp/tools.js.map +1 -0
  168. package/dist/migrations/checks.d.ts +28 -0
  169. package/dist/migrations/checks.js +97 -0
  170. package/dist/migrations/checks.js.map +1 -0
  171. package/dist/migrations/checksum.d.ts +56 -0
  172. package/dist/migrations/checksum.js +72 -0
  173. package/dist/migrations/checksum.js.map +1 -0
  174. package/dist/migrations/create.d.ts +75 -0
  175. package/dist/migrations/create.js +120 -0
  176. package/dist/migrations/create.js.map +1 -0
  177. package/dist/migrations/directory.d.ts +119 -0
  178. package/dist/migrations/directory.js +229 -0
  179. package/dist/migrations/directory.js.map +1 -0
  180. package/dist/migrations/document.d.ts +106 -0
  181. package/dist/migrations/document.js +83 -0
  182. package/dist/migrations/document.js.map +1 -0
  183. package/dist/migrations/index.d.ts +21 -0
  184. package/dist/migrations/index.js +22 -0
  185. package/dist/migrations/index.js.map +1 -0
  186. package/dist/pr/comment.d.ts +32 -0
  187. package/dist/pr/comment.js +99 -0
  188. package/dist/pr/comment.js.map +1 -0
  189. package/dist/pr/forge.d.ts +54 -0
  190. package/dist/pr/forge.js +119 -0
  191. package/dist/pr/forge.js.map +1 -0
  192. package/dist/pr/issue.d.ts +68 -0
  193. package/dist/pr/issue.js +107 -0
  194. package/dist/pr/issue.js.map +1 -0
  195. package/dist/pr/model.d.ts +99 -0
  196. package/dist/pr/model.js +137 -0
  197. package/dist/pr/model.js.map +1 -0
  198. package/dist/pr/render.d.ts +29 -0
  199. package/dist/pr/render.js +279 -0
  200. package/dist/pr/render.js.map +1 -0
  201. package/dist/project.d.ts +62 -0
  202. package/dist/project.js +92 -0
  203. package/dist/project.js.map +1 -0
  204. package/dist/rebase/index.d.ts +121 -0
  205. package/dist/rebase/index.js +390 -0
  206. package/dist/rebase/index.js.map +1 -0
  207. package/dist/rebase/repair.d.ts +41 -0
  208. package/dist/rebase/repair.js +68 -0
  209. package/dist/rebase/repair.js.map +1 -0
  210. package/dist/replay/clickhouse.d.ts +33 -0
  211. package/dist/replay/clickhouse.js +106 -0
  212. package/dist/replay/clickhouse.js.map +1 -0
  213. package/dist/replay/index.d.ts +39 -0
  214. package/dist/replay/index.js +57 -0
  215. package/dist/replay/index.js.map +1 -0
  216. package/dist/replay/postgres.d.ts +31 -0
  217. package/dist/replay/postgres.js +140 -0
  218. package/dist/replay/postgres.js.map +1 -0
  219. package/dist/replay/replay.d.ts +114 -0
  220. package/dist/replay/replay.js +98 -0
  221. package/dist/replay/replay.js.map +1 -0
  222. package/dist/replay/report.d.ts +18 -0
  223. package/dist/replay/report.js +72 -0
  224. package/dist/replay/report.js.map +1 -0
  225. package/dist/replay/shared.d.ts +28 -0
  226. package/dist/replay/shared.js +77 -0
  227. package/dist/replay/shared.js.map +1 -0
  228. package/dist/schemas.d.ts +34 -0
  229. package/dist/schemas.js +38 -0
  230. package/dist/schemas.js.map +1 -0
  231. package/dist/server.d.ts +40 -0
  232. package/dist/server.js +87 -0
  233. package/dist/server.js.map +1 -0
  234. package/dist/steps/backfill.d.ts +132 -0
  235. package/dist/steps/backfill.js +307 -0
  236. package/dist/steps/backfill.js.map +1 -0
  237. package/dist/steps/index.d.ts +52 -0
  238. package/dist/steps/index.js +52 -0
  239. package/dist/steps/index.js.map +1 -0
  240. package/dist/steps/kinds.d.ts +101 -0
  241. package/dist/steps/kinds.js +143 -0
  242. package/dist/steps/kinds.js.map +1 -0
  243. package/dist/steps/postgres-migration.d.ts +95 -0
  244. package/dist/steps/postgres-migration.js +149 -0
  245. package/dist/steps/postgres-migration.js.map +1 -0
  246. package/dist/steps/rebuild.d.ts +97 -0
  247. package/dist/steps/rebuild.js +155 -0
  248. package/dist/steps/rebuild.js.map +1 -0
  249. package/dist/steps/run.d.ts +45 -0
  250. package/dist/steps/run.js +72 -0
  251. package/dist/steps/run.js.map +1 -0
  252. package/dist/topology/render.d.ts +17 -0
  253. package/dist/topology/render.js +17 -0
  254. package/dist/topology/render.js.map +1 -0
  255. package/dist/version.d.ts +2 -0
  256. package/dist/version.js +11 -0
  257. package/dist/version.js.map +1 -0
  258. package/dist/versioned/approval.d.ts +35 -0
  259. package/dist/versioned/approval.js +53 -0
  260. package/dist/versioned/approval.js.map +1 -0
  261. package/dist/versioned/checks.d.ts +29 -0
  262. package/dist/versioned/checks.js +54 -0
  263. package/dist/versioned/checks.js.map +1 -0
  264. package/dist/versioned/clickhouse.d.ts +24 -0
  265. package/dist/versioned/clickhouse.js +42 -0
  266. package/dist/versioned/clickhouse.js.map +1 -0
  267. package/dist/versioned/digest.d.ts +77 -0
  268. package/dist/versioned/digest.js +69 -0
  269. package/dist/versioned/digest.js.map +1 -0
  270. package/dist/versioned/driver.d.ts +51 -0
  271. package/dist/versioned/driver.js +13 -0
  272. package/dist/versioned/driver.js.map +1 -0
  273. package/dist/versioned/engine.d.ts +206 -0
  274. package/dist/versioned/engine.js +370 -0
  275. package/dist/versioned/engine.js.map +1 -0
  276. package/dist/versioned/explain.d.ts +123 -0
  277. package/dist/versioned/explain.js +294 -0
  278. package/dist/versioned/explain.js.map +1 -0
  279. package/dist/versioned/index.d.ts +46 -0
  280. package/dist/versioned/index.js +77 -0
  281. package/dist/versioned/index.js.map +1 -0
  282. package/dist/versioned/op.d.ts +72 -0
  283. package/dist/versioned/op.js +185 -0
  284. package/dist/versioned/op.js.map +1 -0
  285. package/dist/versioned/policy.d.ts +67 -0
  286. package/dist/versioned/policy.js +161 -0
  287. package/dist/versioned/policy.js.map +1 -0
  288. package/dist/versioned/postgres/catalog.d.ts +33 -0
  289. package/dist/versioned/postgres/catalog.js +34 -0
  290. package/dist/versioned/postgres/catalog.js.map +1 -0
  291. package/dist/versioned/postgres/driver.d.ts +71 -0
  292. package/dist/versioned/postgres/driver.js +140 -0
  293. package/dist/versioned/postgres/driver.js.map +1 -0
  294. package/dist/versioned/postgres/executor.d.ts +104 -0
  295. package/dist/versioned/postgres/executor.js +172 -0
  296. package/dist/versioned/postgres/executor.js.map +1 -0
  297. package/dist/versioned/postgres/index.d.ts +11 -0
  298. package/dist/versioned/postgres/index.js +12 -0
  299. package/dist/versioned/postgres/index.js.map +1 -0
  300. package/dist/versioned/postgres/waits.d.ts +46 -0
  301. package/dist/versioned/postgres/waits.js +78 -0
  302. package/dist/versioned/postgres/waits.js.map +1 -0
  303. package/dist/versioned/report.d.ts +25 -0
  304. package/dist/versioned/report.js +84 -0
  305. package/dist/versioned/report.js.map +1 -0
  306. package/dist/versioned/stand-down.d.ts +30 -0
  307. package/dist/versioned/stand-down.js +56 -0
  308. package/dist/versioned/stand-down.js.map +1 -0
  309. package/dist/versioned/state.d.ts +108 -0
  310. package/dist/versioned/state.js +153 -0
  311. package/dist/versioned/state.js.map +1 -0
  312. package/package.json +61 -4
  313. package/schemas/apply.schema.json +269 -0
  314. package/schemas/common.schema.json +213 -0
  315. package/schemas/drift.schema.json +36 -0
  316. package/schemas/init.schema.json +31 -0
  317. package/schemas/lint-rules.schema.json +54 -0
  318. package/schemas/lint.schema.json +290 -0
  319. package/schemas/mcp.schema.json +70 -0
  320. package/schemas/new.schema.json +71 -0
  321. package/schemas/plan.schema.json +371 -0
  322. package/schemas/rebase.schema.json +54 -0
  323. package/schemas/repair.schema.json +20 -0
  324. package/schemas/status.schema.json +310 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * The statement rules: each step of a migration against the class chant's
3
+ * classifier gave it (`migration.json` records the rule and class of every
4
+ * statement, and the changes an Op or manual step makes). Pure.
5
+ *
6
+ * - `destructive`: a statement marked destructive (a table or column drop),
7
+ * or an Op step one of whose changes is.
8
+ * - `ch-mutation`: a ClickHouse statement of class `rewrite`, or one that
9
+ * waits for its mutation (a column type or TTL change).
10
+ * - `ch-rebuild`: a `ClickHouseRebuildOp` step.
11
+ * - `pg-rewrite`: a Postgres statement of class `rewrite` (ACCESS EXCLUSIVE
12
+ * for a rewrite or a full scan).
13
+ * - `pg-lock`: a Postgres statement that blocks writes for a whole build or
14
+ * scan: an index created or dropped on an existing table without
15
+ * `CONCURRENTLY` (SQLPG240 to SQLPG243), a primary key or unique
16
+ * constraint built in place rather than `USING INDEX` (SQLPG221), a
17
+ * foreign key or domain constraint validated in place rather than added
18
+ * `NOT VALID` (SQLPG219, SQLPG262).
19
+ *
20
+ * `COMMENT ON` statements are skipped: chant writes one after a `CREATE`
21
+ * with the same rule, and a comment is catalog only.
22
+ *
23
+ * A statement whose rule is not one of the lexicon's, or a step of a kind
24
+ * it does not know, is `unreadable-object`: lint cannot tell what it does,
25
+ * and never passes what it cannot read.
26
+ */
27
+ import { CLASSIFIER_RULES } from "@intentius/chant-lexicon-sql/clickhouse/plan/rules";
28
+ import { PG_CLASSIFIER_RULES } from "@intentius/chant-lexicon-sql/postgres/plan/rules";
29
+ import { planStep, REBUILD_OP } from "../steps/kinds.js";
30
+ const catalog = (dialect) => (dialect === "clickhouse" ? CLASSIFIER_RULES : PG_CLASSIFIER_RULES);
31
+ /** The classifier rule's id and title, e.g. `SQLCH202 Drop a column`. */
32
+ function titled(dialect, rule) {
33
+ const r = catalog(dialect)[rule];
34
+ return r ? `${rule} ${r.title}` : rule;
35
+ }
36
+ const COMMENT = /^\s*COMMENT\s+ON\b/i;
37
+ const INDEX_DDL = /^\s*(?:CREATE\s+(?:UNIQUE\s+)?INDEX|DROP\s+INDEX|REINDEX)\b/i;
38
+ const CONCURRENTLY = /\bCONCURRENTLY\b/i;
39
+ const NOT_VALID = /\bNOT\s+VALID\b/i;
40
+ const USING_INDEX = /\bUSING\s+INDEX\b/i;
41
+ const ALTER_TABLE = /^\s*ALTER\s+TABLE\b/i;
42
+ /** Why a Postgres statement blocks writes for a whole build or scan, or `undefined`. */
43
+ function pgLock(step) {
44
+ const sql = step.sql;
45
+ if (step.class === "create")
46
+ return undefined; // an index on a table created in the same migration blocks nobody
47
+ if (["SQLPG221", "SQLPG240", "SQLPG241", "SQLPG242", "SQLPG243"].includes(step.rule) && INDEX_DDL.test(sql) && !CONCURRENTLY.test(sql)) {
48
+ return /^\s*DROP/i.test(sql)
49
+ ? "drops an index without CONCURRENTLY: ACCESS EXCLUSIVE on the table, blocking reads and writes behind it; use DROP INDEX CONCURRENTLY"
50
+ : "builds an index without CONCURRENTLY: SHARE on the table, blocking every write until the build ends; declare the index CONCURRENTLY";
51
+ }
52
+ if (step.rule === "SQLPG221" && ALTER_TABLE.test(sql) && !USING_INDEX.test(sql)) {
53
+ return "builds the constraint's index under ACCESS EXCLUSIVE; build a unique index CONCURRENTLY first, then ADD CONSTRAINT ... USING INDEX";
54
+ }
55
+ if (step.rule === "SQLPG219" && !NOT_VALID.test(sql)) {
56
+ return "reads every row under SHARE ROW EXCLUSIVE on both tables, blocking writes to them for the scan; add it NOT VALID and validate it in a later migration";
57
+ }
58
+ if (step.rule === "SQLPG262" && !NOT_VALID.test(sql)) {
59
+ return "checks every column of the domain's type in every table while it holds its lock; add it NOT VALID and validate it later";
60
+ }
61
+ return undefined;
62
+ }
63
+ /** What lint cannot read in a step, or `undefined`. */
64
+ export function unreadableStep(dialect, step) {
65
+ const kind = step.kind;
66
+ if (kind !== "statement" && kind !== "op" && kind !== "manual")
67
+ return `a step of kind ${JSON.stringify(kind)}, which is not statement, op or manual`;
68
+ if (step.kind === "statement") {
69
+ if (typeof step.sql !== "string" || step.sql.trim() === "")
70
+ return "a statement step with no SQL";
71
+ const known = catalog(dialect)[step.rule];
72
+ return known ? undefined : `a statement whose rule ${JSON.stringify(step.rule)} is not one of the ${dialect} classifier's, so what it does cannot be checked`;
73
+ }
74
+ for (const c of step.changes) {
75
+ if (!catalog(dialect)[c.rule])
76
+ return `a ${step.kind} step whose change ${JSON.stringify(c.rule)} is not one of the ${dialect} classifier's rules`;
77
+ }
78
+ return undefined;
79
+ }
80
+ /** The statement-rule findings for one step, before levels and silences. */
81
+ export function stepFindings(dialect, step) {
82
+ const out = [];
83
+ if (step.kind === "statement") {
84
+ if (COMMENT.test(step.sql))
85
+ return out;
86
+ const what = `${titled(dialect, step.rule)} on ${step.name}`;
87
+ if (step.destructive)
88
+ out.push({ rule: "destructive", message: `${what}: removes data that cannot be recovered` });
89
+ if (dialect === "clickhouse" && (step.class === "rewrite" || step.waitsForMutation === true)) {
90
+ out.push({ rule: "ch-mutation", message: `${what}: a mutation that rewrites existing parts in the background, with no rollback` });
91
+ }
92
+ if (dialect === "postgres") {
93
+ if (step.class === "rewrite") {
94
+ const r = catalog(dialect)[step.rule];
95
+ out.push({ rule: "pg-rewrite", message: `${what}: blocks reads and writes on the table while it runs${r ? ` (${r.restriction})` : ""}` });
96
+ }
97
+ const lock = pgLock(step);
98
+ if (lock)
99
+ out.push({ rule: "pg-lock", message: `${what}: ${lock}` });
100
+ }
101
+ return out;
102
+ }
103
+ if (step.kind === "op") {
104
+ const destructive = step.changes.filter((c) => c.destructive);
105
+ if (destructive.length > 0) {
106
+ out.push({ rule: "destructive", message: `${step.op} for ${step.name} removes data that cannot be recovered: ${destructive.map((c) => `${titled(dialect, c.rule)} (${c.field})`).join(", ")}` });
107
+ }
108
+ if (step.op === REBUILD_OP) {
109
+ const why = step.changes.filter((c) => c.class === "rebuild").map((c) => `${titled(dialect, c.rule)} (${c.field})`);
110
+ out.push({ rule: "ch-rebuild", message: `${REBUILD_OP} rebuilds ${step.name}: every row is copied into a new table and swapped in${why.length > 0 ? `, for ${why.join(", ")}` : ""}` });
111
+ }
112
+ }
113
+ return out;
114
+ }
115
+ /** Why yodel apply refuses a step, or `undefined` for one it runs. */
116
+ export function refusedStep(step) {
117
+ const plan = planStep(step);
118
+ return plan.run === "refused" ? plan.reason : undefined;
119
+ }
120
+ //# sourceMappingURL=statements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statements.js","sourceRoot":"","sources":["../../src/lint/statements.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * `yodel mcp`: a Model Context Protocol server on stdio, newline-delimited
3
+ * JSON-RPC 2.0. It answers `initialize`, `ping`, `tools/list` and
4
+ * `tools/call`, and serves only the read-only tools of ./tools.ts; the
5
+ * constructor refuses any other list ({@link assertReadOnly}).
6
+ */
7
+ import { type YodelTool } from "./tools.js";
8
+ /** Protocol revisions this server answers with, newest first; a client asking for another gets the newest. */
9
+ export declare const PROTOCOL_VERSIONS: readonly ["2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05"];
10
+ export declare const INSTRUCTIONS: string;
11
+ interface Request {
12
+ jsonrpc?: string;
13
+ id?: string | number | null;
14
+ method?: unknown;
15
+ params?: Record<string, unknown>;
16
+ }
17
+ type Response = {
18
+ jsonrpc: "2.0";
19
+ id: string | number | null;
20
+ } & ({
21
+ result: unknown;
22
+ } | {
23
+ error: {
24
+ code: number;
25
+ message: string;
26
+ };
27
+ });
28
+ export declare class YodelMcpServer {
29
+ private readonly tools;
30
+ constructor(tools: readonly YodelTool[]);
31
+ /** What `tools/list` answers: name, description, input schema and annotations. */
32
+ list(): Array<Pick<YodelTool, "name" | "description" | "inputSchema" | "annotations">>;
33
+ /** Answers one message; `null` for a notification (no id), which gets no response. */
34
+ handle(message: Request): Promise<Response | null>;
35
+ private dispatch;
36
+ private call;
37
+ /** Serves stdin and stdout until stdin closes. Anything else the process logs goes to stderr. */
38
+ serve(input?: NodeJS.ReadableStream, write?: (line: string) => void): Promise<void>;
39
+ }
40
+ export {};
@@ -0,0 +1,106 @@
1
+ /**
2
+ * `yodel mcp`: a Model Context Protocol server on stdio, newline-delimited
3
+ * JSON-RPC 2.0. It answers `initialize`, `ping`, `tools/list` and
4
+ * `tools/call`, and serves only the read-only tools of ./tools.ts; the
5
+ * constructor refuses any other list ({@link assertReadOnly}).
6
+ */
7
+ import { createInterface } from "node:readline";
8
+ import { version } from "../version.js";
9
+ import { assertReadOnly } from "./tools.js";
10
+ /** Protocol revisions this server answers with, newest first; a client asking for another gets the newest. */
11
+ export const PROTOCOL_VERSIONS = ["2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05"];
12
+ export const INSTRUCTIONS = "Read-only tools over a SQL Yodeler project: status, plan, lint, drift, history and explain. Each result is an envelope whose results follow the JSON Schema named in resultsSchema. " +
13
+ "Nothing here applies, approves, overrides a policy rule, repairs, rebases or writes a migration. A plan carries the commands that are a person's (approve, override) in forPerson: show them to the person, and never run them. " +
14
+ "Never run `yodel apply` against a shared environment, never run `chant approve` or `yodel approve`, never edit the `chant/lifecycle` branch, never merge; approvals and applies belong to people.";
15
+ export class YodelMcpServer {
16
+ tools;
17
+ constructor(tools) {
18
+ assertReadOnly(tools);
19
+ this.tools = new Map(tools.map((t) => [t.name, t]));
20
+ }
21
+ /** What `tools/list` answers: name, description, input schema and annotations. */
22
+ list() {
23
+ return [...this.tools.values()].map(({ name, description, inputSchema, annotations }) => ({ name, description, inputSchema, annotations }));
24
+ }
25
+ /** Answers one message; `null` for a notification (no id), which gets no response. */
26
+ async handle(message) {
27
+ if (message.id === undefined)
28
+ return null;
29
+ const id = message.id;
30
+ try {
31
+ return { jsonrpc: "2.0", id, result: await this.dispatch(message.method, message.params ?? {}) };
32
+ }
33
+ catch (e) {
34
+ const code = e instanceof MethodNotFound ? -32601 : e instanceof InvalidParams ? -32602 : -32603;
35
+ return { jsonrpc: "2.0", id, error: { code, message: e instanceof Error ? e.message : String(e) } };
36
+ }
37
+ }
38
+ async dispatch(method, params) {
39
+ switch (method) {
40
+ case "initialize": {
41
+ const asked = typeof params.protocolVersion === "string" ? params.protocolVersion : undefined;
42
+ return {
43
+ protocolVersion: asked && PROTOCOL_VERSIONS.includes(asked) ? asked : PROTOCOL_VERSIONS[0],
44
+ capabilities: { tools: { listChanged: false } },
45
+ serverInfo: { name: "yodel", version: version() },
46
+ instructions: INSTRUCTIONS,
47
+ };
48
+ }
49
+ case "ping":
50
+ return {};
51
+ case "tools/list":
52
+ return { tools: this.list() };
53
+ case "tools/call":
54
+ return this.call(params);
55
+ default:
56
+ throw new MethodNotFound(`unknown method ${JSON.stringify(method)}`);
57
+ }
58
+ }
59
+ async call(params) {
60
+ const name = params.name;
61
+ const tool = typeof name === "string" ? this.tools.get(name) : undefined;
62
+ if (!tool)
63
+ throw new InvalidParams(`unknown tool ${JSON.stringify(name)}; yodel mcp serves ${[...this.tools.keys()].join(", ")}`);
64
+ const args = (params.arguments ?? {});
65
+ try {
66
+ const envelope = await tool.handler(args);
67
+ return { content: [{ type: "text", text: JSON.stringify(envelope, null, 2) }], structuredContent: envelope, isError: envelope.results === null };
68
+ }
69
+ catch (e) {
70
+ return { content: [{ type: "text", text: e instanceof Error ? e.message : String(e) }], isError: true };
71
+ }
72
+ }
73
+ /** Serves stdin and stdout until stdin closes. Anything else the process logs goes to stderr. */
74
+ serve(input = process.stdin, write = (l) => process.stdout.write(l)) {
75
+ // stdout carries the protocol only: a project's config or Op printing with console.log would break it.
76
+ console.log = console.info = (...a) => {
77
+ process.stderr.write(`${a.map(String).join(" ")}\n`);
78
+ };
79
+ const rl = createInterface({ input, terminal: false });
80
+ let queue = Promise.resolve();
81
+ rl.on("line", (line) => {
82
+ if (line.trim() === "")
83
+ return;
84
+ // One request at a time, in order: the tools run commands in this process.
85
+ queue = queue.then(async () => {
86
+ let message;
87
+ try {
88
+ message = JSON.parse(line);
89
+ }
90
+ catch {
91
+ write(`${JSON.stringify({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "parse error" } })}\n`);
92
+ return;
93
+ }
94
+ const response = await this.handle(message);
95
+ if (response)
96
+ write(`${JSON.stringify(response)}\n`);
97
+ });
98
+ });
99
+ return new Promise((resolve) => rl.on("close", () => void queue.then(resolve)));
100
+ }
101
+ }
102
+ class MethodNotFound extends Error {
103
+ }
104
+ class InvalidParams extends Error {
105
+ }
106
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * `yodel mcp`'s tools. Each runs read-only `yodel` commands in this process
3
+ * with `--json` and returns what they print, in one envelope
4
+ * (schemas/mcp.schema.json). There is no tool that applies, approves,
5
+ * repairs, rebases, writes a migration or overrides a policy, and
6
+ * {@link assertReadOnly} refuses a tool list that has one, so the server does
7
+ * not start with it.
8
+ */
9
+ import type { Command } from "../command.js";
10
+ import { SCHEMA_VERSION } from "../schemas.js";
11
+ /** The only verbs a tool may run, and only with the flags {@link runVerb} allows. */
12
+ export declare const READ_VERBS: Readonly<Record<string, Command>>;
13
+ /** Never a tool, and never run by one: each writes to a database, a history, the migrations directory or the gate ledger. */
14
+ export declare const WRITE_VERBS: readonly ["apply", "approve", "override", "repair", "rebase", "new", "init"];
15
+ export interface ToolEnvelope {
16
+ schema: typeof SCHEMA_VERSION;
17
+ tool: string;
18
+ /** The command line the tool ran. */
19
+ command: string;
20
+ /** Its exit code: the same as on a terminal. */
21
+ exit: number;
22
+ /** What it printed with --json; null when it printed nothing to parse. */
23
+ results: unknown;
24
+ /** The `$id` of the schema `results` follows. */
25
+ resultsSchema: string;
26
+ /** What it wrote to stderr: why it failed, when `results` is null, else notices. */
27
+ error?: string;
28
+ /** Steps that are a person's, with the command they run. An agent shows them and never runs them. */
29
+ forPerson?: Array<{
30
+ action: string;
31
+ command: string;
32
+ }>;
33
+ }
34
+ export interface YodelTool {
35
+ name: string;
36
+ description: string;
37
+ inputSchema: {
38
+ type: "object";
39
+ properties: Record<string, unknown>;
40
+ required?: string[];
41
+ additionalProperties?: boolean;
42
+ };
43
+ annotations: {
44
+ readOnlyHint: boolean;
45
+ destructiveHint?: boolean;
46
+ idempotentHint?: boolean;
47
+ openWorldHint?: boolean;
48
+ };
49
+ /** The yodel verbs the tool runs. */
50
+ verbs: readonly string[];
51
+ handler: (args: Record<string, unknown>) => Promise<ToolEnvelope>;
52
+ }
53
+ /** Throws when any tool could write: a write verb by name, a verb outside {@link READ_VERBS}, or no read-only annotation. */
54
+ export declare function assertReadOnly(tools: readonly YodelTool[]): void;
55
+ /** Runs a read verb in this process with `--json` and captures what it prints. */
56
+ export declare function runVerb(verb: string, args: readonly string[]): Promise<{
57
+ code: number;
58
+ out: string;
59
+ err: string;
60
+ }>;
61
+ interface PlanResults {
62
+ approve?: unknown;
63
+ policy?: Array<{
64
+ id: string;
65
+ outcome: string;
66
+ }>;
67
+ }
68
+ /** A plan's steps that are a person's: overriding each policy rule that denies it (when it should not stand), and approving it. */
69
+ export declare function personSteps(env: string, plan: PlanResults | null): NonNullable<ToolEnvelope["forPerson"]>;
70
+ /** The tools, for the project in `dir`. */
71
+ export declare function yodelTools(dir: string): YodelTool[];
72
+ export {};
@@ -0,0 +1,178 @@
1
+ /**
2
+ * `yodel mcp`'s tools. Each runs read-only `yodel` commands in this process
3
+ * with `--json` and returns what they print, in one envelope
4
+ * (schemas/mcp.schema.json). There is no tool that applies, approves,
5
+ * repairs, rebases, writes a migration or overrides a policy, and
6
+ * {@link assertReadOnly} refuses a tool list that has one, so the server does
7
+ * not start with it.
8
+ */
9
+ import { DOCS_URL } from "../cli.js";
10
+ import { EXIT_CODES } from "../exit.js";
11
+ import { YodelError } from "../project.js";
12
+ import { COMMAND_SCHEMAS, SCHEMA_VERSION, schemaId } from "../schemas.js";
13
+ import { drift } from "../commands/drift.js";
14
+ import { lint } from "../commands/lint.js";
15
+ import { plan } from "../commands/plan.js";
16
+ import { status } from "../commands/status.js";
17
+ /** The only verbs a tool may run, and only with the flags {@link runVerb} allows. */
18
+ export const READ_VERBS = { status, plan, lint, drift };
19
+ /** Never a tool, and never run by one: each writes to a database, a history, the migrations directory or the gate ledger. */
20
+ export const WRITE_VERBS = ["apply", "approve", "override", "repair", "rebase", "new", "init"];
21
+ /** Flags that make a read verb write: a replay database, a checksum, a forge comment, the Op's Apply step. */
22
+ const WRITE_FLAGS = ["--replay", "--reset", "--reset-shared", "--keep", "--update-checksum", "--comment", "--execute"];
23
+ /** Throws when any tool could write: a write verb by name, a verb outside {@link READ_VERBS}, or no read-only annotation. */
24
+ export function assertReadOnly(tools) {
25
+ const problems = [];
26
+ for (const t of tools) {
27
+ const named = WRITE_VERBS.find((v) => t.name === v || t.name.startsWith(`${v}_`) || t.name.endsWith(`_${v}`));
28
+ if (named)
29
+ problems.push(`tool ${t.name} is named for yodel ${named}, which writes`);
30
+ for (const v of t.verbs)
31
+ if (!Object.hasOwn(READ_VERBS, v))
32
+ problems.push(`tool ${t.name} runs yodel ${v}, which is not one of the read verbs (${Object.keys(READ_VERBS).join(", ")})`);
33
+ if (!t.annotations.readOnlyHint || t.annotations.destructiveHint === true)
34
+ problems.push(`tool ${t.name} is not annotated read-only`);
35
+ }
36
+ if (problems.length > 0)
37
+ throw new YodelError(`refused to start: yodel mcp serves read-only tools only, and ${problems.join("; ")}`);
38
+ }
39
+ /** Runs a read verb in this process with `--json` and captures what it prints. */
40
+ export async function runVerb(verb, args) {
41
+ const command = Object.hasOwn(READ_VERBS, verb) ? READ_VERBS[verb] : undefined;
42
+ if (!command)
43
+ throw new YodelError(`yodel mcp runs only ${Object.keys(READ_VERBS).join(", ")}; not ${verb}`);
44
+ const flag = args.map((a) => a.split("=")[0] ?? a).find((a) => WRITE_FLAGS.includes(a));
45
+ if (flag)
46
+ throw new YodelError(`yodel mcp does not run yodel ${verb} ${flag}: it writes`);
47
+ let out = "";
48
+ let err = "";
49
+ const io = { out: (t) => (out += t), err: (t) => (err += t) };
50
+ const code = await command.run([...args, "--json"], io);
51
+ return { code, out, err };
52
+ }
53
+ const parse = (text) => {
54
+ try {
55
+ return text.trim() === "" ? null : JSON.parse(text);
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ };
61
+ /** `--dir` when the server was started for a project elsewhere. */
62
+ const dirArgs = (dir) => ["--dir", dir];
63
+ const envArg = (args, required) => {
64
+ const env = args.env;
65
+ if (env === undefined && !required)
66
+ return undefined;
67
+ if (typeof env !== "string" || !/^[\w.-]+$/.test(env))
68
+ throw new YodelError("env: expected the name of an environment in chant.config.ts");
69
+ return env;
70
+ };
71
+ async function envelope(tool, verb, args, schema, shape = (r) => r) {
72
+ const ran = await runVerb(verb, args);
73
+ const parsed = parse(ran.out);
74
+ const results = parsed === null ? null : shape(parsed);
75
+ return {
76
+ schema: SCHEMA_VERSION,
77
+ tool,
78
+ command: ["yodel", verb, ...args.filter((a, i) => a !== "--dir" && args[i - 1] !== "--dir"), "--json"].join(" "),
79
+ exit: ran.code,
80
+ results,
81
+ resultsSchema: schema,
82
+ ...(ran.err.trim() !== "" ? { error: ran.err.trim() } : {}),
83
+ };
84
+ }
85
+ const envInput = (required, what) => ({
86
+ type: "object",
87
+ properties: { env: { type: "string", description: what } },
88
+ ...(required ? { required: ["env"] } : {}),
89
+ additionalProperties: false,
90
+ });
91
+ /** A plan's steps that are a person's: overriding each policy rule that denies it (when it should not stand), and approving it. */
92
+ export function personSteps(env, plan) {
93
+ const steps = (plan?.policy ?? [])
94
+ .filter((r) => r.outcome === "denied")
95
+ .map((r) => ({ action: `override policy rule ${r.id}, if a person on policy.overriders decides it should not stand`, command: `yodel override ${env} --rule ${r.id} --reason "<why>"` }));
96
+ if (typeof plan?.approve === "string")
97
+ steps.push({ action: "approve this plan, after reading it", command: plan.approve });
98
+ return steps;
99
+ }
100
+ const READ_ONLY = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
101
+ const ENV = "The environment, as chant.config.ts names it.";
102
+ /** The tools, for the project in `dir`. */
103
+ export function yodelTools(dir) {
104
+ return [
105
+ {
106
+ name: "status",
107
+ description: `yodel status <env> --json: applied, pending, out-of-order and part-way migrations, checksum mismatches, and the plan digest apply would ask approval for. Exit 3 when migrations are pending, 4 when apply would refuse. results: ${schemaId(COMMAND_SCHEMAS.status)}`,
108
+ inputSchema: envInput(true, ENV),
109
+ annotations: READ_ONLY,
110
+ verbs: ["status"],
111
+ handler: (a) => envelope("status", "status", [envArg(a, true), ...dirArgs(dir)], schemaId(COMMAND_SCHEMAS.status)),
112
+ },
113
+ {
114
+ name: "plan",
115
+ description: `yodel plan <env> --json: what yodel apply would run and the plan digest. When a person must approve the plan, or may override a policy rule that denies it, forPerson has the command they run. Never run those commands: approvals and overrides belong to people. results: ${schemaId(COMMAND_SCHEMAS.plan)}`,
116
+ inputSchema: envInput(true, ENV),
117
+ annotations: READ_ONLY,
118
+ verbs: ["plan"],
119
+ handler: async (a) => {
120
+ const env = envArg(a, true);
121
+ const e = await envelope("plan", "plan", [env, ...dirArgs(dir)], schemaId(COMMAND_SCHEMAS.plan));
122
+ const forPerson = personSteps(env, e.results);
123
+ return forPerson.length > 0 ? { ...e, forPerson } : e;
124
+ },
125
+ },
126
+ {
127
+ name: "lint",
128
+ description: `yodel lint [--env <env>] --json: the lint findings and silences; with env, also against that environment's history. Exit 3 on an error finding. The replay check is not offered: it writes to a database. results: ${schemaId(COMMAND_SCHEMAS.lint)}`,
129
+ inputSchema: envInput(false, `${ENV} Optional: compare the migrations with its history.`),
130
+ annotations: READ_ONLY,
131
+ verbs: ["lint"],
132
+ handler: (a) => {
133
+ const env = envArg(a, false);
134
+ return envelope("lint", "lint", [...(env ? ["--env", env] : []), ...dirArgs(dir)], schemaId(COMMAND_SCHEMAS.lint));
135
+ },
136
+ },
137
+ {
138
+ name: "drift",
139
+ description: `yodel drift <env> --json: the declared objects changed out of band or gone. Exit 2 on drift. results: ${schemaId(COMMAND_SCHEMAS.drift)}`,
140
+ inputSchema: envInput(true, ENV),
141
+ annotations: READ_ONLY,
142
+ verbs: ["drift"],
143
+ handler: (a) => envelope("drift", "drift", [envArg(a, true), ...dirArgs(dir)], schemaId(COMMAND_SCHEMAS.drift)),
144
+ },
145
+ {
146
+ name: "history",
147
+ description: `The migrations an environment's history records applied: who applied each, when, under which plan digest, and any repairs. From yodel status <env> --json. results: ${schemaId("mcp")}#/$defs/history`,
148
+ inputSchema: envInput(true, ENV),
149
+ annotations: READ_ONLY,
150
+ verbs: ["status"],
151
+ handler: (a) => envelope("history", "status", [envArg(a, true), ...dirArgs(dir)], `${schemaId("mcp")}#/$defs/history`, (r) => {
152
+ const s = r;
153
+ return { environment: s.environment, ...(s.server ? { server: s.server } : {}), history: s.history, applied: s.applied };
154
+ }),
155
+ },
156
+ {
157
+ name: "explain",
158
+ description: `What a lint rule checks and whether it can be silenced (topic: the rule's id, as a finding names it), or what an exit code means (topic: 0 to 5). results: ${schemaId("mcp")}#/$defs/explain`,
159
+ inputSchema: { type: "object", properties: { topic: { type: "string", description: "A lint rule id (pg-lock, checksum, ...) or an exit code (0 to 5)." } }, required: ["topic"], additionalProperties: false },
160
+ annotations: READ_ONLY,
161
+ verbs: ["lint"],
162
+ handler: async (a) => {
163
+ const topic = typeof a.topic === "string" ? a.topic.trim() : "";
164
+ const schema = `${schemaId("mcp")}#/$defs/explain`;
165
+ const exit = EXIT_CODES.find(([code]) => String(code) === topic);
166
+ if (exit) {
167
+ return { schema: SCHEMA_VERSION, tool: "explain", command: "yodel --help", exit: 0, resultsSchema: schema, results: { topic, kind: "exit-code", code: exit[0], meaning: exit[1], docs: `${DOCS_URL}#the-commands` } };
168
+ }
169
+ const e = await envelope("explain", "lint", ["--rules", ...dirArgs(dir)], schema, (r) => {
170
+ const rule = r.find((x) => x.id === topic);
171
+ return rule ? { topic, kind: "lint-rule", rule, docs: `${DOCS_URL}lint/` } : null;
172
+ });
173
+ return e.results === null && e.exit === 0 ? { ...e, exit: 1, error: `no lint rule or exit code ${JSON.stringify(topic)}; yodel lint --rules lists the rules` } : e;
174
+ },
175
+ },
176
+ ];
177
+ }
178
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,qFAAqF;AACrF,MAAM,CAAC,MAAM,UAAU,GAAsC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAE3F,6HAA6H;AAC7H,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAU,CAAC;AAExG,8GAA8G;AAC9G,MAAM,WAAW,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAE,mBAAmB,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;AA6BvH,6HAA6H;AAC7H,MAAM,UAAU,cAAc,CAAC,KAA2B;IACxD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9G,IAAI,KAAK;YAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,uBAAuB,KAAK,gBAAgB,CAAC,CAAC;QACrF,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK;YAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,eAAe,CAAC,yCAAyC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxL,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,IAAI,CAAC,CAAC,WAAW,CAAC,eAAe,KAAK,IAAI;YAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,6BAA6B,CAAC,CAAC;IACxI,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,gEAAgE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACvI,CAAC;AAED,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAY,EAAE,IAAuB;IACjE,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,UAAU,CAAC,uBAAuB,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAC7G,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF,IAAI,IAAI;QAAE,MAAM,IAAI,UAAU,CAAC,gCAAgC,IAAI,IAAI,IAAI,aAAa,CAAC,CAAC;IAC1F,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,MAAM,EAAE,GAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC;IAClE,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;IACxD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,KAAK,GAAG,CAAC,IAAY,EAAW,EAAE;IACtC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAa,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,mEAAmE;AACnE,MAAM,OAAO,GAAG,CAAC,GAAW,EAAY,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAE1D,MAAM,MAAM,GAAG,CAAC,IAA6B,EAAE,QAAiB,EAAsB,EAAE;IACtF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;IACrB,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IACrD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,6DAA6D,CAAC,CAAC;IAC3I,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAE,IAAY,EAAE,IAAc,EAAE,MAAc,EAAE,QAAuC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjI,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACvD,OAAO;QACL,MAAM,EAAE,cAAc;QACtB,IAAI;QACJ,OAAO,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,OAAO,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAChH,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,OAAO;QACP,aAAa,EAAE,MAAM;QACrB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5D,CAAC;AACJ,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,QAAiB,EAAE,IAAY,EAAE,EAAE,CAAC,CAAC;IACrD,IAAI,EAAE,QAAiB;IACvB,UAAU,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;IAC1D,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1C,oBAAoB,EAAE,KAAK;CAC5B,CAAC,CAAC;AAOH,mIAAmI;AACnI,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,IAAwB;IAC/D,MAAM,KAAK,GAAG,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC;SAC/B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC;SACrC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,wBAAwB,CAAC,CAAC,EAAE,gEAAgE,EAAE,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAAC,CAAC,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC;IAC5L,IAAI,OAAO,IAAI,EAAE,OAAO,KAAK,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,qCAAqC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5H,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,SAAS,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;AAE7G,MAAM,GAAG,GAAG,+CAA+C,CAAC;AAE5D,2CAA2C;AAC3C,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO;QACL;YACE,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,qOAAqO,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE;YACpR,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC;YAChC,WAAW,EAAE,SAAS;YACtB,KAAK,EAAE,CAAC,QAAQ,CAAC;YACjB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAW,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;SAC7H;QACD;YACE,IAAI,EAAE,MAAM;YACZ,WAAW,EAAE,gRAAgR,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE;YAC7T,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC;YAChC,WAAW,EAAE,SAAS;YACtB,KAAK,EAAE,CAAC,MAAM,CAAC;YACf,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;gBACnB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,EAAE,IAAI,CAAW,CAAC;gBACtC,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;gBACjG,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,OAA6B,CAAC,CAAC;gBACpE,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACxD,CAAC;SACF;QACD;YACE,IAAI,EAAE,MAAM;YACZ,WAAW,EAAE,sNAAsN,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE;YACnQ,WAAW,EAAE,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,qDAAqD,CAAC;YACzF,WAAW,EAAE,SAAS;YACtB,KAAK,EAAE,CAAC,MAAM,CAAC;YACf,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;gBACb,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBAC7B,OAAO,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;YACrH,CAAC;SACF;QACD;YACE,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,yGAAyG,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE;YACvJ,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC;YAChC,WAAW,EAAE,SAAS;YACtB,KAAK,EAAE,CAAC,OAAO,CAAC;YAChB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAW,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;SAC1H;QACD;YACE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,uKAAuK,QAAQ,CAAC,KAAK,CAAC,iBAAiB;YACpN,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC;YAChC,WAAW,EAAE,SAAS;YACtB,KAAK,EAAE,CAAC,QAAQ,CAAC;YACjB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CACb,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAW,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE;gBACrH,MAAM,CAAC,GAAG,CAA4B,CAAC;gBACvC,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YAC3H,CAAC,CAAC;SACL;QACD;YACE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,8JAA8J,QAAQ,CAAC,KAAK,CAAC,iBAAiB;YAC3M,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mEAAmE,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,oBAAoB,EAAE,KAAK,EAAE;YAC9M,WAAW,EAAE,SAAS;YACtB,KAAK,EAAE,CAAC,MAAM,CAAC;YACf,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;gBACnB,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChE,MAAM,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC;gBACnD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC;gBACjE,IAAI,IAAI,EAAE,CAAC;oBACT,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,QAAQ,eAAe,EAAE,EAAE,CAAC;gBACxN,CAAC;gBACD,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,SAAS,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE;oBACtF,MAAM,IAAI,GAAI,CAA2B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;oBACtE,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,QAAQ,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;gBACpF,CAAC,CAAC,CAAC;gBACH,OAAO,CAAC,CAAC,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,6BAA6B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,sCAAsC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACrK,CAAC;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Pre-migration checks (#52): what `checks` in `migration.json` may hold,
3
+ * and whether a query's rows pass one. Pure; `../versioned/checks.ts` runs
4
+ * them against a server.
5
+ *
6
+ * A check is part of `migration.json`, so of the migration's checksum and of
7
+ * the plan digest: editing, adding or removing one moves the digest, and an
8
+ * approval given before does not carry over.
9
+ */
10
+ import type { MigrationCheck } from "./document.js";
11
+ export type { MigrationCheck };
12
+ /** What is wrong with a `checks` value read from `migration.json`, or `undefined` when it is well formed. */
13
+ export declare function checksProblem(value: unknown): string | undefined;
14
+ /** What a check expects, in words. */
15
+ export declare function describeExpect(check: MigrationCheck): string;
16
+ export interface CheckOutcome {
17
+ name: string;
18
+ passed: boolean;
19
+ /** What the query returned, in a few words. */
20
+ detail: string;
21
+ }
22
+ /** Whether `rows`, what the check's query returned, pass it. */
23
+ export declare function judgeCheck(check: MigrationCheck, rows: ReadonlyArray<Record<string, unknown>>): CheckOutcome;
24
+ /**
25
+ * A `--check` argument: `<sql>`, or `<name>: <sql>`; the name defaults to
26
+ * `check-<n>`, n counting from 1. The check expects no rows.
27
+ */
28
+ export declare function parseCheckArg(arg: string, n: number): MigrationCheck;