@intentius/sql-yodeler 0.0.0-stage → 0.1.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 (264) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +110 -2
  3. package/dist/bin.d.ts +2 -0
  4. package/dist/bin.js +14 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/chant/apply.d.ts +51 -0
  7. package/dist/chant/apply.js +104 -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 +44 -0
  13. package/dist/chant/drift.js +91 -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/cli.d.ts +4 -0
  22. package/dist/cli.js +59 -0
  23. package/dist/cli.js.map +1 -0
  24. package/dist/command.d.ts +17 -0
  25. package/dist/command.js +13 -0
  26. package/dist/command.js.map +1 -0
  27. package/dist/commands/apply.d.ts +3 -0
  28. package/dist/commands/apply.js +306 -0
  29. package/dist/commands/apply.js.map +1 -0
  30. package/dist/commands/drift.d.ts +3 -0
  31. package/dist/commands/drift.js +38 -0
  32. package/dist/commands/drift.js.map +1 -0
  33. package/dist/commands/index.d.ts +3 -0
  34. package/dist/commands/index.js +22 -0
  35. package/dist/commands/index.js.map +1 -0
  36. package/dist/commands/init.d.ts +3 -0
  37. package/dist/commands/init.js +135 -0
  38. package/dist/commands/init.js.map +1 -0
  39. package/dist/commands/lint.d.ts +3 -0
  40. package/dist/commands/lint.js +193 -0
  41. package/dist/commands/lint.js.map +1 -0
  42. package/dist/commands/new.d.ts +3 -0
  43. package/dist/commands/new.js +168 -0
  44. package/dist/commands/new.js.map +1 -0
  45. package/dist/commands/plan.d.ts +3 -0
  46. package/dist/commands/plan.js +171 -0
  47. package/dist/commands/plan.js.map +1 -0
  48. package/dist/commands/rebase.d.ts +3 -0
  49. package/dist/commands/rebase.js +167 -0
  50. package/dist/commands/rebase.js.map +1 -0
  51. package/dist/commands/repair.d.ts +3 -0
  52. package/dist/commands/repair.js +117 -0
  53. package/dist/commands/repair.js.map +1 -0
  54. package/dist/commands/status.d.ts +7 -0
  55. package/dist/commands/status.js +54 -0
  56. package/dist/commands/status.js.map +1 -0
  57. package/dist/config/define.d.ts +50 -0
  58. package/dist/config/define.js +20 -0
  59. package/dist/config/define.js.map +1 -0
  60. package/dist/config/index.d.ts +11 -0
  61. package/dist/config/index.js +12 -0
  62. package/dist/config/index.js.map +1 -0
  63. package/dist/config/load.d.ts +17 -0
  64. package/dist/config/load.js +102 -0
  65. package/dist/config/load.js.map +1 -0
  66. package/dist/config/settings.d.ts +40 -0
  67. package/dist/config/settings.js +88 -0
  68. package/dist/config/settings.js.map +1 -0
  69. package/dist/env-args.d.ts +18 -0
  70. package/dist/env-args.js +62 -0
  71. package/dist/env-args.js.map +1 -0
  72. package/dist/history/client.d.ts +17 -0
  73. package/dist/history/client.js +19 -0
  74. package/dist/history/client.js.map +1 -0
  75. package/dist/history/ddl.d.ts +58 -0
  76. package/dist/history/ddl.js +100 -0
  77. package/dist/history/ddl.js.map +1 -0
  78. package/dist/history/index.d.ts +25 -0
  79. package/dist/history/index.js +26 -0
  80. package/dist/history/index.js.map +1 -0
  81. package/dist/history/lock.d.ts +100 -0
  82. package/dist/history/lock.js +224 -0
  83. package/dist/history/lock.js.map +1 -0
  84. package/dist/history/postgres/ddl.d.ts +22 -0
  85. package/dist/history/postgres/ddl.js +47 -0
  86. package/dist/history/postgres/ddl.js.map +1 -0
  87. package/dist/history/postgres/index.d.ts +12 -0
  88. package/dist/history/postgres/index.js +13 -0
  89. package/dist/history/postgres/index.js.map +1 -0
  90. package/dist/history/postgres/lock.d.ts +48 -0
  91. package/dist/history/postgres/lock.js +95 -0
  92. package/dist/history/postgres/lock.js.map +1 -0
  93. package/dist/history/postgres/store.d.ts +39 -0
  94. package/dist/history/postgres/store.js +68 -0
  95. package/dist/history/postgres/store.js.map +1 -0
  96. package/dist/history/rows.d.ts +96 -0
  97. package/dist/history/rows.js +73 -0
  98. package/dist/history/rows.js.map +1 -0
  99. package/dist/history/store.d.ts +72 -0
  100. package/dist/history/store.js +134 -0
  101. package/dist/history/store.js.map +1 -0
  102. package/dist/history/topology.d.ts +41 -0
  103. package/dist/history/topology.js +54 -0
  104. package/dist/history/topology.js.map +1 -0
  105. package/dist/index.d.ts +10 -0
  106. package/dist/index.js +10 -0
  107. package/dist/index.js.map +1 -0
  108. package/dist/init/adopt.d.ts +70 -0
  109. package/dist/init/adopt.js +138 -0
  110. package/dist/init/adopt.js.map +1 -0
  111. package/dist/init/baseline.d.ts +61 -0
  112. package/dist/init/baseline.js +88 -0
  113. package/dist/init/baseline.js.map +1 -0
  114. package/dist/init/files.d.ts +23 -0
  115. package/dist/init/files.js +77 -0
  116. package/dist/init/files.js.map +1 -0
  117. package/dist/init/index.d.ts +16 -0
  118. package/dist/init/index.js +17 -0
  119. package/dist/init/index.js.map +1 -0
  120. package/dist/init/live.d.ts +28 -0
  121. package/dist/init/live.js +45 -0
  122. package/dist/init/live.js.map +1 -0
  123. package/dist/lint/check.d.ts +81 -0
  124. package/dist/lint/check.js +208 -0
  125. package/dist/lint/check.js.map +1 -0
  126. package/dist/lint/config.d.ts +21 -0
  127. package/dist/lint/config.js +43 -0
  128. package/dist/lint/config.js.map +1 -0
  129. package/dist/lint/index.d.ts +31 -0
  130. package/dist/lint/index.js +43 -0
  131. package/dist/lint/index.js.map +1 -0
  132. package/dist/lint/project-rules.d.ts +19 -0
  133. package/dist/lint/project-rules.js +32 -0
  134. package/dist/lint/project-rules.js.map +1 -0
  135. package/dist/lint/report.d.ts +7 -0
  136. package/dist/lint/report.js +48 -0
  137. package/dist/lint/report.js.map +1 -0
  138. package/dist/lint/rules.d.ts +53 -0
  139. package/dist/lint/rules.js +42 -0
  140. package/dist/lint/rules.js.map +1 -0
  141. package/dist/lint/silences.d.ts +49 -0
  142. package/dist/lint/silences.js +91 -0
  143. package/dist/lint/silences.js.map +1 -0
  144. package/dist/lint/statements.d.ts +38 -0
  145. package/dist/lint/statements.js +120 -0
  146. package/dist/lint/statements.js.map +1 -0
  147. package/dist/migrations/checksum.d.ts +56 -0
  148. package/dist/migrations/checksum.js +72 -0
  149. package/dist/migrations/checksum.js.map +1 -0
  150. package/dist/migrations/create.d.ts +73 -0
  151. package/dist/migrations/create.js +119 -0
  152. package/dist/migrations/create.js.map +1 -0
  153. package/dist/migrations/directory.d.ts +119 -0
  154. package/dist/migrations/directory.js +225 -0
  155. package/dist/migrations/directory.js.map +1 -0
  156. package/dist/migrations/document.d.ts +83 -0
  157. package/dist/migrations/document.js +82 -0
  158. package/dist/migrations/document.js.map +1 -0
  159. package/dist/migrations/index.d.ts +20 -0
  160. package/dist/migrations/index.js +21 -0
  161. package/dist/migrations/index.js.map +1 -0
  162. package/dist/pr/comment.d.ts +32 -0
  163. package/dist/pr/comment.js +99 -0
  164. package/dist/pr/comment.js.map +1 -0
  165. package/dist/pr/forge.d.ts +50 -0
  166. package/dist/pr/forge.js +105 -0
  167. package/dist/pr/forge.js.map +1 -0
  168. package/dist/pr/model.d.ts +91 -0
  169. package/dist/pr/model.js +113 -0
  170. package/dist/pr/model.js.map +1 -0
  171. package/dist/pr/render.d.ts +27 -0
  172. package/dist/pr/render.js +246 -0
  173. package/dist/pr/render.js.map +1 -0
  174. package/dist/project.d.ts +62 -0
  175. package/dist/project.js +92 -0
  176. package/dist/project.js.map +1 -0
  177. package/dist/rebase/index.d.ts +121 -0
  178. package/dist/rebase/index.js +390 -0
  179. package/dist/rebase/index.js.map +1 -0
  180. package/dist/rebase/repair.d.ts +41 -0
  181. package/dist/rebase/repair.js +68 -0
  182. package/dist/rebase/repair.js.map +1 -0
  183. package/dist/replay/clickhouse.d.ts +33 -0
  184. package/dist/replay/clickhouse.js +106 -0
  185. package/dist/replay/clickhouse.js.map +1 -0
  186. package/dist/replay/index.d.ts +36 -0
  187. package/dist/replay/index.js +54 -0
  188. package/dist/replay/index.js.map +1 -0
  189. package/dist/replay/postgres.d.ts +31 -0
  190. package/dist/replay/postgres.js +140 -0
  191. package/dist/replay/postgres.js.map +1 -0
  192. package/dist/replay/replay.d.ts +114 -0
  193. package/dist/replay/replay.js +98 -0
  194. package/dist/replay/replay.js.map +1 -0
  195. package/dist/replay/report.d.ts +18 -0
  196. package/dist/replay/report.js +72 -0
  197. package/dist/replay/report.js.map +1 -0
  198. package/dist/steps/backfill.d.ts +128 -0
  199. package/dist/steps/backfill.js +307 -0
  200. package/dist/steps/backfill.js.map +1 -0
  201. package/dist/steps/index.d.ts +52 -0
  202. package/dist/steps/index.js +52 -0
  203. package/dist/steps/index.js.map +1 -0
  204. package/dist/steps/kinds.d.ts +101 -0
  205. package/dist/steps/kinds.js +143 -0
  206. package/dist/steps/kinds.js.map +1 -0
  207. package/dist/steps/postgres-migration.d.ts +95 -0
  208. package/dist/steps/postgres-migration.js +149 -0
  209. package/dist/steps/postgres-migration.js.map +1 -0
  210. package/dist/steps/rebuild.d.ts +97 -0
  211. package/dist/steps/rebuild.js +162 -0
  212. package/dist/steps/rebuild.js.map +1 -0
  213. package/dist/steps/run.d.ts +45 -0
  214. package/dist/steps/run.js +72 -0
  215. package/dist/steps/run.js.map +1 -0
  216. package/dist/topology/render.d.ts +17 -0
  217. package/dist/topology/render.js +17 -0
  218. package/dist/topology/render.js.map +1 -0
  219. package/dist/version.d.ts +2 -0
  220. package/dist/version.js +11 -0
  221. package/dist/version.js.map +1 -0
  222. package/dist/versioned/approval.d.ts +35 -0
  223. package/dist/versioned/approval.js +53 -0
  224. package/dist/versioned/approval.js.map +1 -0
  225. package/dist/versioned/clickhouse.d.ts +24 -0
  226. package/dist/versioned/clickhouse.js +34 -0
  227. package/dist/versioned/clickhouse.js.map +1 -0
  228. package/dist/versioned/digest.d.ts +77 -0
  229. package/dist/versioned/digest.js +69 -0
  230. package/dist/versioned/digest.js.map +1 -0
  231. package/dist/versioned/driver.d.ts +41 -0
  232. package/dist/versioned/driver.js +13 -0
  233. package/dist/versioned/driver.js.map +1 -0
  234. package/dist/versioned/engine.d.ts +152 -0
  235. package/dist/versioned/engine.js +277 -0
  236. package/dist/versioned/engine.js.map +1 -0
  237. package/dist/versioned/explain.d.ts +123 -0
  238. package/dist/versioned/explain.js +289 -0
  239. package/dist/versioned/explain.js.map +1 -0
  240. package/dist/versioned/index.d.ts +37 -0
  241. package/dist/versioned/index.js +54 -0
  242. package/dist/versioned/index.js.map +1 -0
  243. package/dist/versioned/op.d.ts +62 -0
  244. package/dist/versioned/op.js +153 -0
  245. package/dist/versioned/op.js.map +1 -0
  246. package/dist/versioned/postgres/catalog.d.ts +33 -0
  247. package/dist/versioned/postgres/catalog.js +34 -0
  248. package/dist/versioned/postgres/catalog.js.map +1 -0
  249. package/dist/versioned/postgres/driver.d.ts +69 -0
  250. package/dist/versioned/postgres/driver.js +113 -0
  251. package/dist/versioned/postgres/driver.js.map +1 -0
  252. package/dist/versioned/postgres/executor.d.ts +104 -0
  253. package/dist/versioned/postgres/executor.js +172 -0
  254. package/dist/versioned/postgres/executor.js.map +1 -0
  255. package/dist/versioned/postgres/index.d.ts +11 -0
  256. package/dist/versioned/postgres/index.js +12 -0
  257. package/dist/versioned/postgres/index.js.map +1 -0
  258. package/dist/versioned/report.d.ts +22 -0
  259. package/dist/versioned/report.js +81 -0
  260. package/dist/versioned/report.js.map +1 -0
  261. package/dist/versioned/state.d.ts +108 -0
  262. package/dist/versioned/state.js +153 -0
  263. package/dist/versioned/state.js.map +1 -0
  264. package/package.json +51 -4
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Drift: the declared objects whose live definition changed out of band, or
3
+ * that are gone from the server. Read from `chant lifecycle diff <env> --live
4
+ * --json`, the sql lexicon's section of it:
5
+ *
6
+ * - `deep.drifted[].changes[]`: a declared object whose live definition
7
+ * differs, property by property, declared against live;
8
+ * - `resources.missing`: a declared object the server does not have;
9
+ * - `resources.unobserved` and `deep.unobserved`: a declared object chant
10
+ * could not read (no credentials, a kind it cannot observe). Not drift, and
11
+ * not clean either: that part of the environment is unknown.
12
+ *
13
+ * An object the project does not declare is never reported: chant only reads
14
+ * what the project declares, and only touches what carries its marker.
15
+ */
16
+ import { YodelError } from "../project.js";
17
+ import { lastJsonLine, runChant } from "./process.js";
18
+ /** Exit code: an owned object changed or is gone. */
19
+ export const DRIFTED = 2;
20
+ /** `2` on drift; `1` when there is none but part of the environment could not be read; `0` when clean. */
21
+ export function driftExitCode(drift) {
22
+ if (drift.changed.length > 0 || drift.missing.length > 0)
23
+ return DRIFTED;
24
+ return drift.unobserved.length > 0 ? 1 : 0;
25
+ }
26
+ /** The drift in a parsed `chant lifecycle diff --live --json` document. */
27
+ export function driftFromLifecycle(environment, doc) {
28
+ const lexicons = doc?.lexicons;
29
+ if (!lexicons) {
30
+ const stacks = doc?.stacks;
31
+ throw new YodelError(stacks
32
+ ? "chant lifecycle diff reported per stack; a yodel project is one database and one stack"
33
+ : "chant lifecycle diff --json printed no lexicons");
34
+ }
35
+ const sql = lexicons.sql ?? {};
36
+ const unobserved = new Map();
37
+ for (const u of [...(sql.resources?.unobserved ?? []), ...(sql.deep?.unobserved ?? [])]) {
38
+ if (!unobserved.has(u.name))
39
+ unobserved.set(u.name, u);
40
+ }
41
+ return {
42
+ environment,
43
+ changed: (sql.deep?.drifted ?? []).filter((d) => d.changes.length > 0),
44
+ missing: [...(sql.resources?.missing ?? [])].sort(),
45
+ unobserved: [...unobserved.values()].sort((a, b) => a.name.localeCompare(b.name)),
46
+ };
47
+ }
48
+ /** Runs `chant lifecycle diff <env> --live --json` in the project and reads the drift from it. */
49
+ export async function readDrift(project, env, options = {}) {
50
+ const result = await runChant(["lifecycle", "diff", env.name, "--live", "--json"], {
51
+ cwd: project.dir,
52
+ ...(options.env ? { env: options.env } : {}),
53
+ });
54
+ const doc = lastJsonLine(result.stdout);
55
+ if (result.code !== 0 || doc === undefined) {
56
+ const detail = (result.stderr || result.stdout).trim();
57
+ throw new YodelError(`chant lifecycle diff ${env.name} --live failed (exit ${String(result.code)})${detail ? `:\n${detail}` : ""}`);
58
+ }
59
+ return driftFromLifecycle(env.name, doc);
60
+ }
61
+ const show = (v) => (v === undefined ? "(none)" : typeof v === "string" ? v : JSON.stringify(v));
62
+ /** The drift as text. */
63
+ export function renderDrift(drift) {
64
+ const lines = [`Drift in ${drift.environment}`, ""];
65
+ if (drift.changed.length === 0 && drift.missing.length === 0) {
66
+ lines.push("No drift: every declared object matches the server.");
67
+ }
68
+ if (drift.changed.length > 0) {
69
+ lines.push("Changed out of band:");
70
+ for (const e of drift.changed) {
71
+ lines.push(` ${e.name} (${e.type})`);
72
+ for (const c of e.changes) {
73
+ lines.push(c.kind === "absent" ? ` ${c.path}: declared ${show(c.declared)}, absent live` : ` ${c.path}: declared ${show(c.declared)}, live ${show(c.live)}`);
74
+ }
75
+ }
76
+ }
77
+ if (drift.missing.length > 0) {
78
+ if (drift.changed.length > 0)
79
+ lines.push("");
80
+ lines.push("Gone (declared, not on the server):");
81
+ for (const name of drift.missing)
82
+ lines.push(` ${name}`);
83
+ }
84
+ if (drift.unobserved.length > 0) {
85
+ lines.push("", "Could not be read, so their state is unknown:");
86
+ for (const u of drift.unobserved)
87
+ lines.push(` ${u.name}: ${u.reason}${u.detail ? ` (${u.detail})` : ""}`);
88
+ }
89
+ return `${lines.join("\n")}\n`;
90
+ }
91
+ //# sourceMappingURL=drift.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift.js","sourceRoot":"","sources":["../../src/chant/drift.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The plan: the classified change from an environment's live database to the
3
+ * declared schema. This is `chant sql plan <env> <build>`, called as the
4
+ * library functions that command runs (`planAgainstServer` for ClickHouse,
5
+ * `planPgAgainstServer` for Postgres) rather than through the CLI.
6
+ */
7
+ import type { SchemaDiff } from "@intentius/chant-lexicon-sql/clickhouse/plan/diff";
8
+ import type { PgSchemaDiff } from "@intentius/chant-lexicon-sql/postgres/plan/diff";
9
+ import type { ClassifiedChange } from "@intentius/chant-lexicon-sql/core/classifier";
10
+ import { type Environment, type Project, type SqlDialect } from "../project.js";
11
+ import type { Build } from "./build.js";
12
+ /** A plan for one environment, in either dialect. */
13
+ export interface Plan {
14
+ environment: string;
15
+ dialect: SqlDialect;
16
+ /** chant's own diff, as `chant sql plan --json` prints it. */
17
+ diff: SchemaDiff | PgSchemaDiff;
18
+ /**
19
+ * The changes the plan refuses to make in place, each of which needs its
20
+ * own Op: a ClickHouse rebuild (`rebuilds`, run as `ClickHouseRebuildOp`)
21
+ * or a Postgres expand-and-contract change (`refused`, run as
22
+ * `PostgresMigrationOp`).
23
+ */
24
+ refused: ClassifiedChange[];
25
+ }
26
+ /** Exit code: the plan has a change that needs a rebuild (or expand-and-contract) Op. */
27
+ export declare const PLAN_NEEDS_OP = 2;
28
+ /** `2` when any change needs its own Op, `0` otherwise. */
29
+ export declare function planExitCode(plan: Plan): number;
30
+ /**
31
+ * The changes to objects the build declares. A plan also lists live objects
32
+ * the project does not declare, as drops; an ApplyOp never touches those
33
+ * (it only prunes objects carrying chant's marker), so they are not work
34
+ * left for apply. chant labels a declared object `<export> (<name>)` and an
35
+ * undeclared one by its name alone.
36
+ */
37
+ export declare function declaredChanges(plan: Plan, build: Build): ClassifiedChange[];
38
+ /** The plan as `yodel plan --json` prints it: chant's diff, with the environment and dialect it is of. */
39
+ export declare function planJson(plan: Plan): Record<string, unknown>;
40
+ /** Plans `build` against the server `sql.profiles.<env>` binds. */
41
+ export declare function planEnvironment(project: Project, env: Environment, build: Build, options?: {
42
+ env?: NodeJS.ProcessEnv;
43
+ }): Promise<Plan>;
44
+ /** The plan as text, chant's own report for the dialect. */
45
+ export declare function renderPlan(plan: Plan, title: string): Promise<string>;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * The plan: the classified change from an environment's live database to the
3
+ * declared schema. This is `chant sql plan <env> <build>`, called as the
4
+ * library functions that command runs (`planAgainstServer` for ClickHouse,
5
+ * `planPgAgainstServer` for Postgres) rather than through the CLI.
6
+ */
7
+ import { YodelError } from "../project.js";
8
+ /** Exit code: the plan has a change that needs a rebuild (or expand-and-contract) Op. */
9
+ export const PLAN_NEEDS_OP = 2;
10
+ /** `2` when any change needs its own Op, `0` otherwise. */
11
+ export function planExitCode(plan) {
12
+ return plan.refused.length > 0 ? PLAN_NEEDS_OP : 0;
13
+ }
14
+ /**
15
+ * The changes to objects the build declares. A plan also lists live objects
16
+ * the project does not declare, as drops; an ApplyOp never touches those
17
+ * (it only prunes objects carrying chant's marker), so they are not work
18
+ * left for apply. chant labels a declared object `<export> (<name>)` and an
19
+ * undeclared one by its name alone.
20
+ */
21
+ export function declaredChanges(plan, build) {
22
+ const exports = new Set(build.output.objects.map((o) => o.export));
23
+ return plan.diff.changes.filter((c) => {
24
+ const at = c.object.indexOf(" (");
25
+ return at > 0 && c.object.endsWith(")") && exports.has(c.object.slice(0, at));
26
+ });
27
+ }
28
+ /** The plan as `yodel plan --json` prints it: chant's diff, with the environment and dialect it is of. */
29
+ export function planJson(plan) {
30
+ return { environment: plan.environment, dialect: plan.dialect, ...plan.diff };
31
+ }
32
+ function bindError(e) {
33
+ return new YodelError(e instanceof Error ? e.message : String(e));
34
+ }
35
+ /** Plans `build` against the server `sql.profiles.<env>` binds. */
36
+ export async function planEnvironment(project, env, build, options = {}) {
37
+ const bind = { config: project.config, cwd: project.dir, ...(options.env ? { env: options.env } : {}) };
38
+ try {
39
+ if (project.dialect === "postgres") {
40
+ const { planPgAgainstServer } = await import("@intentius/chant-lexicon-sql/postgres/plan/commands");
41
+ const diff = await planPgAgainstServer(env.name, build.path, bind);
42
+ return { environment: env.name, dialect: "postgres", diff, refused: diff.refused };
43
+ }
44
+ const { planAgainstServer } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/commands");
45
+ const diff = await planAgainstServer(env.name, build.path, bind);
46
+ return { environment: env.name, dialect: "clickhouse", diff, refused: diff.rebuilds };
47
+ }
48
+ catch (e) {
49
+ throw bindError(e);
50
+ }
51
+ }
52
+ /** The plan as text, chant's own report for the dialect. */
53
+ export async function renderPlan(plan, title) {
54
+ if (plan.dialect === "postgres") {
55
+ const { renderPgDiff } = await import("@intentius/chant-lexicon-sql/postgres/plan/report");
56
+ return renderPgDiff(plan.diff, { title });
57
+ }
58
+ const { renderDiff } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/report");
59
+ return renderDiff(plan.diff, { title });
60
+ }
61
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/chant/plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Running the `chant` CLI that yodel depends on, for the commands that have
3
+ * no library surface (`build`, `run`, `lifecycle diff`).
4
+ *
5
+ * Published chant ships TypeScript source, and its own bin runs
6
+ * `node --import <tsx loader> src/cli/main.ts`. yodel does the same with its
7
+ * own copy of tsx, so the chant it runs is the one in its own dependencies,
8
+ * not whatever `chant` is first on PATH. That chant's `bin/` goes first on the
9
+ * child's PATH, because chant's Op activities shell out to `chant` themselves
10
+ * (`lifecycleDiff` runs `chant lifecycle diff`).
11
+ */
12
+ export interface ChantInstall {
13
+ /** The `@intentius/chant` package directory. */
14
+ root: string;
15
+ /** Its CLI entry, `src/cli/main.ts`. */
16
+ main: string;
17
+ /** Its `bin/`, which holds the `chant` script. */
18
+ bin: string;
19
+ /** The tsx loader to run it under, as a file URL. */
20
+ loader: string;
21
+ }
22
+ /** Where yodel's chant and tsx are installed. */
23
+ export declare function chantInstall(): ChantInstall;
24
+ export interface ChantResult {
25
+ code: number;
26
+ stdout: string;
27
+ stderr: string;
28
+ }
29
+ export interface RunChantOptions {
30
+ cwd: string;
31
+ env?: NodeJS.ProcessEnv;
32
+ /** Called with each chunk as it arrives, for output a person watches (an Op run). */
33
+ onStdout?: (text: string) => void;
34
+ onStderr?: (text: string) => void;
35
+ }
36
+ /** The environment a chant child runs with: the caller's, with chant's bin first on PATH. */
37
+ export declare function chantEnv(base?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
38
+ /** Runs `chant <args>` in `cwd` and resolves with its exit code and output. Never rejects on a non-zero exit. */
39
+ export declare function runChant(args: readonly string[], options: RunChantOptions): Promise<ChantResult>;
40
+ /** The last line of `stdout` that parses as a JSON object: chant prints its `--json` document as one line, after any log lines. */
41
+ export declare function lastJsonLine(stdout: string): unknown;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Running the `chant` CLI that yodel depends on, for the commands that have
3
+ * no library surface (`build`, `run`, `lifecycle diff`).
4
+ *
5
+ * Published chant ships TypeScript source, and its own bin runs
6
+ * `node --import <tsx loader> src/cli/main.ts`. yodel does the same with its
7
+ * own copy of tsx, so the chant it runs is the one in its own dependencies,
8
+ * not whatever `chant` is first on PATH. That chant's `bin/` goes first on the
9
+ * child's PATH, because chant's Op activities shell out to `chant` themselves
10
+ * (`lifecycleDiff` runs `chant lifecycle diff`).
11
+ */
12
+ import { spawn } from "node:child_process";
13
+ import { createRequire } from "node:module";
14
+ import { dirname, delimiter, join } from "node:path";
15
+ import { pathToFileURL } from "node:url";
16
+ let install;
17
+ /** Where yodel's chant and tsx are installed. */
18
+ export function chantInstall() {
19
+ if (install)
20
+ return install;
21
+ const require = createRequire(import.meta.url);
22
+ // "." resolves to <root>/src/index.ts; package.json is not an export.
23
+ const root = dirname(dirname(require.resolve("@intentius/chant")));
24
+ install = {
25
+ root,
26
+ main: join(root, "src", "cli", "main.ts"),
27
+ bin: join(root, "bin"),
28
+ loader: pathToFileURL(require.resolve("tsx")).href,
29
+ };
30
+ return install;
31
+ }
32
+ /** The environment a chant child runs with: the caller's, with chant's bin first on PATH. */
33
+ export function chantEnv(base = process.env) {
34
+ const { bin } = chantInstall();
35
+ return { ...base, PATH: [bin, base.PATH ?? ""].filter(Boolean).join(delimiter), FORCE_COLOR: "0", NO_COLOR: "1" };
36
+ }
37
+ /** Runs `chant <args>` in `cwd` and resolves with its exit code and output. Never rejects on a non-zero exit. */
38
+ export function runChant(args, options) {
39
+ const { main, loader } = chantInstall();
40
+ return new Promise((resolvePromise, reject) => {
41
+ const child = spawn(process.execPath, ["--import", loader, main, ...args], {
42
+ cwd: options.cwd,
43
+ env: chantEnv(options.env),
44
+ stdio: ["ignore", "pipe", "pipe"],
45
+ });
46
+ let stdout = "";
47
+ let stderr = "";
48
+ child.stdout.setEncoding("utf8");
49
+ child.stderr.setEncoding("utf8");
50
+ child.stdout.on("data", (chunk) => {
51
+ stdout += chunk;
52
+ options.onStdout?.(chunk);
53
+ });
54
+ child.stderr.on("data", (chunk) => {
55
+ stderr += chunk;
56
+ options.onStderr?.(chunk);
57
+ });
58
+ child.on("error", reject);
59
+ child.on("close", (code, signal) => {
60
+ resolvePromise({ code: code ?? (signal ? 128 : 1), stdout, stderr });
61
+ });
62
+ });
63
+ }
64
+ /** The last line of `stdout` that parses as a JSON object: chant prints its `--json` document as one line, after any log lines. */
65
+ export function lastJsonLine(stdout) {
66
+ const lines = stdout.split("\n").map((l) => l.trim()).filter((l) => l.startsWith("{"));
67
+ for (const line of lines.reverse()) {
68
+ try {
69
+ return JSON.parse(line);
70
+ }
71
+ catch {
72
+ // A log line that happens to start with "{"; keep looking.
73
+ }
74
+ }
75
+ // A pretty-printed document spans lines; try the whole of stdout from its first "{".
76
+ const at = stdout.indexOf("{");
77
+ if (at >= 0) {
78
+ try {
79
+ return JSON.parse(stdout.slice(at));
80
+ }
81
+ catch {
82
+ // Not JSON.
83
+ }
84
+ }
85
+ return undefined;
86
+ }
87
+ //# sourceMappingURL=process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/chant/process.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { Command, Io } from "./command.js";
2
+ export declare function help(list?: readonly Command[]): string;
3
+ /** Parses argv (without the node and script paths) and runs a verb; resolves to the exit code. */
4
+ export declare function main(argv: string[], io: Io, list?: readonly Command[]): Promise<number>;
package/dist/cli.js ADDED
@@ -0,0 +1,59 @@
1
+ import { parseArgs } from "node:util";
2
+ import { commands } from "./commands/index.js";
3
+ import { version } from "./version.js";
4
+ export function help(list = commands) {
5
+ const width = Math.max(...list.map((c) => c.name.length));
6
+ const lines = list.map((c) => {
7
+ const mark = c.implemented ? "" : " (not implemented yet)";
8
+ return ` ${c.name.padEnd(width)} ${c.summary}${mark}`;
9
+ });
10
+ return [
11
+ "Usage: yodel <command> [options]",
12
+ "",
13
+ "Schema management and migrations for ClickHouse and Postgres.",
14
+ "",
15
+ "Commands:",
16
+ ...lines,
17
+ "",
18
+ "Options:",
19
+ " -h, --help show this help",
20
+ " -v, --version print the version",
21
+ "",
22
+ ].join("\n");
23
+ }
24
+ /** Parses argv (without the node and script paths) and runs a verb; resolves to the exit code. */
25
+ export async function main(argv, io, list = commands) {
26
+ const verbAt = argv.findIndex((a) => !a.startsWith("-"));
27
+ const globals = verbAt === -1 ? argv : argv.slice(0, verbAt);
28
+ let values;
29
+ try {
30
+ ({ values } = parseArgs({
31
+ args: globals,
32
+ options: {
33
+ help: { type: "boolean", short: "h" },
34
+ version: { type: "boolean", short: "v" },
35
+ },
36
+ strict: true,
37
+ }));
38
+ }
39
+ catch (e) {
40
+ io.err(`yodel: ${e instanceof Error ? e.message : String(e)}\n\n${help(list)}`);
41
+ return 1;
42
+ }
43
+ if (values.version) {
44
+ io.out(`${version()}\n`);
45
+ return 0;
46
+ }
47
+ if (values.help || verbAt === -1) {
48
+ (values.help ? io.out : io.err)(help(list));
49
+ return values.help ? 0 : 1;
50
+ }
51
+ const name = argv[verbAt];
52
+ const command = list.find((c) => c.name === name);
53
+ if (!command) {
54
+ io.err(`yodel: unknown command "${String(name)}"\n\n${help(list)}`);
55
+ return 1;
56
+ }
57
+ return command.run(argv.slice(verbAt + 1), io);
58
+ }
59
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /** Where a command writes. Tests pass their own; the bin passes process.stdout and stderr. */
2
+ export interface Io {
3
+ out: (text: string) => void;
4
+ err: (text: string) => void;
5
+ }
6
+ /** One `yodel` verb. Each lives in its own module under src/commands/. */
7
+ export interface Command {
8
+ name: string;
9
+ /** One line for `yodel --help`. */
10
+ summary: string;
11
+ /** False until a later issue builds the verb; `yodel --help` marks it. */
12
+ implemented: boolean;
13
+ /** Runs the verb with the arguments after its name; resolves to the exit code. */
14
+ run: (args: string[], io: Io) => Promise<number>;
15
+ }
16
+ /** A verb that is listed but not built yet. Later issues replace these one by one. */
17
+ export declare function notImplemented(name: string, summary: string): Command;
@@ -0,0 +1,13 @@
1
+ /** A verb that is listed but not built yet. Later issues replace these one by one. */
2
+ export function notImplemented(name, summary) {
3
+ return {
4
+ name,
5
+ summary,
6
+ implemented: false,
7
+ run: (_args, io) => {
8
+ io.err(`yodel ${name}: not implemented yet\n`);
9
+ return Promise.resolve(2);
10
+ },
11
+ };
12
+ }
13
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAiBA,sFAAsF;AACtF,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,OAAe;IAC1D,OAAO;QACL,IAAI;QACJ,OAAO;QACP,WAAW,EAAE,KAAK;QAClB,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YACjB,EAAE,CAAC,GAAG,CAAC,SAAS,IAAI,yBAAyB,CAAC,CAAC;YAC/C,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from "../command.js";
2
+ /** `yodel apply <env>`; the exit codes are in `help`. */
3
+ export declare const apply: Command;