@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.
- package/LICENSE +202 -0
- package/README.md +112 -2
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +29 -0
- package/dist/bin.js.map +1 -0
- package/dist/chant/apply.d.ts +59 -0
- package/dist/chant/apply.js +116 -0
- package/dist/chant/apply.js.map +1 -0
- package/dist/chant/build.d.ts +34 -0
- package/dist/chant/build.js +48 -0
- package/dist/chant/build.js.map +1 -0
- package/dist/chant/drift.d.ts +112 -0
- package/dist/chant/drift.js +238 -0
- package/dist/chant/drift.js.map +1 -0
- package/dist/chant/plan.d.ts +45 -0
- package/dist/chant/plan.js +61 -0
- package/dist/chant/plan.js.map +1 -0
- package/dist/chant/process.d.ts +41 -0
- package/dist/chant/process.js +87 -0
- package/dist/chant/process.js.map +1 -0
- package/dist/chant/runnable.d.ts +19 -0
- package/dist/chant/runnable.js +47 -0
- package/dist/chant/runnable.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +99 -0
- package/dist/cli.js.map +1 -0
- package/dist/command.d.ts +23 -0
- package/dist/command.js +13 -0
- package/dist/command.js.map +1 -0
- package/dist/commands/apply.d.ts +3 -0
- package/dist/commands/apply.js +426 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/approve.d.ts +5 -0
- package/dist/commands/approve.js +111 -0
- package/dist/commands/approve.js.map +1 -0
- package/dist/commands/drift.d.ts +14 -0
- package/dist/commands/drift.js +267 -0
- package/dist/commands/drift.js.map +1 -0
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.js +28 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.js +139 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/lint.d.ts +3 -0
- package/dist/commands/lint.js +202 -0
- package/dist/commands/lint.js.map +1 -0
- package/dist/commands/mcp.d.ts +3 -0
- package/dist/commands/mcp.js +50 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/new.d.ts +5 -0
- package/dist/commands/new.js +292 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/override.d.ts +3 -0
- package/dist/commands/override.js +118 -0
- package/dist/commands/override.js.map +1 -0
- package/dist/commands/plan.d.ts +3 -0
- package/dist/commands/plan.js +183 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/rebase.d.ts +3 -0
- package/dist/commands/rebase.js +167 -0
- package/dist/commands/rebase.js.map +1 -0
- package/dist/commands/repair.d.ts +14 -0
- package/dist/commands/repair.js +125 -0
- package/dist/commands/repair.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.js +54 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config/define.d.ts +148 -0
- package/dist/config/define.js +20 -0
- package/dist/config/define.js.map +1 -0
- package/dist/config/index.d.ts +11 -0
- package/dist/config/index.js +12 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/load.d.ts +17 -0
- package/dist/config/load.js +162 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/settings.d.ts +53 -0
- package/dist/config/settings.js +116 -0
- package/dist/config/settings.js.map +1 -0
- package/dist/env-args.d.ts +24 -0
- package/dist/env-args.js +92 -0
- package/dist/env-args.js.map +1 -0
- package/dist/exit.d.ts +20 -0
- package/dist/exit.js +28 -0
- package/dist/exit.js.map +1 -0
- package/dist/history/client.d.ts +25 -0
- package/dist/history/client.js +42 -0
- package/dist/history/client.js.map +1 -0
- package/dist/history/ddl.d.ts +58 -0
- package/dist/history/ddl.js +100 -0
- package/dist/history/ddl.js.map +1 -0
- package/dist/history/index.d.ts +25 -0
- package/dist/history/index.js +26 -0
- package/dist/history/index.js.map +1 -0
- package/dist/history/lock.d.ts +104 -0
- package/dist/history/lock.js +230 -0
- package/dist/history/lock.js.map +1 -0
- package/dist/history/postgres/ddl.d.ts +22 -0
- package/dist/history/postgres/ddl.js +47 -0
- package/dist/history/postgres/ddl.js.map +1 -0
- package/dist/history/postgres/index.d.ts +12 -0
- package/dist/history/postgres/index.js +13 -0
- package/dist/history/postgres/index.js.map +1 -0
- package/dist/history/postgres/lock.d.ts +48 -0
- package/dist/history/postgres/lock.js +95 -0
- package/dist/history/postgres/lock.js.map +1 -0
- package/dist/history/postgres/store.d.ts +39 -0
- package/dist/history/postgres/store.js +68 -0
- package/dist/history/postgres/store.js.map +1 -0
- package/dist/history/rows.d.ts +96 -0
- package/dist/history/rows.js +73 -0
- package/dist/history/rows.js.map +1 -0
- package/dist/history/store.d.ts +72 -0
- package/dist/history/store.js +134 -0
- package/dist/history/store.js.map +1 -0
- package/dist/history/topology.d.ts +41 -0
- package/dist/history/topology.js +54 -0
- package/dist/history/topology.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/init/adopt.d.ts +70 -0
- package/dist/init/adopt.js +143 -0
- package/dist/init/adopt.js.map +1 -0
- package/dist/init/baseline.d.ts +61 -0
- package/dist/init/baseline.js +88 -0
- package/dist/init/baseline.js.map +1 -0
- package/dist/init/files.d.ts +23 -0
- package/dist/init/files.js +77 -0
- package/dist/init/files.js.map +1 -0
- package/dist/init/index.d.ts +16 -0
- package/dist/init/index.js +17 -0
- package/dist/init/index.js.map +1 -0
- package/dist/init/live.d.ts +39 -0
- package/dist/init/live.js +68 -0
- package/dist/init/live.js.map +1 -0
- package/dist/lint/check.d.ts +88 -0
- package/dist/lint/check.js +227 -0
- package/dist/lint/check.js.map +1 -0
- package/dist/lint/config.d.ts +21 -0
- package/dist/lint/config.js +43 -0
- package/dist/lint/config.js.map +1 -0
- package/dist/lint/index.d.ts +31 -0
- package/dist/lint/index.js +43 -0
- package/dist/lint/index.js.map +1 -0
- package/dist/lint/project-rules.d.ts +19 -0
- package/dist/lint/project-rules.js +32 -0
- package/dist/lint/project-rules.js.map +1 -0
- package/dist/lint/report.d.ts +7 -0
- package/dist/lint/report.js +48 -0
- package/dist/lint/report.js.map +1 -0
- package/dist/lint/rules.d.ts +53 -0
- package/dist/lint/rules.js +42 -0
- package/dist/lint/rules.js.map +1 -0
- package/dist/lint/silences.d.ts +49 -0
- package/dist/lint/silences.js +91 -0
- package/dist/lint/silences.js.map +1 -0
- package/dist/lint/statements.d.ts +38 -0
- package/dist/lint/statements.js +120 -0
- package/dist/lint/statements.js.map +1 -0
- package/dist/mcp/server.d.ts +40 -0
- package/dist/mcp/server.js +106 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +72 -0
- package/dist/mcp/tools.js +178 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/migrations/checks.d.ts +28 -0
- package/dist/migrations/checks.js +97 -0
- package/dist/migrations/checks.js.map +1 -0
- package/dist/migrations/checksum.d.ts +56 -0
- package/dist/migrations/checksum.js +72 -0
- package/dist/migrations/checksum.js.map +1 -0
- package/dist/migrations/create.d.ts +75 -0
- package/dist/migrations/create.js +120 -0
- package/dist/migrations/create.js.map +1 -0
- package/dist/migrations/directory.d.ts +119 -0
- package/dist/migrations/directory.js +229 -0
- package/dist/migrations/directory.js.map +1 -0
- package/dist/migrations/document.d.ts +106 -0
- package/dist/migrations/document.js +83 -0
- package/dist/migrations/document.js.map +1 -0
- package/dist/migrations/index.d.ts +21 -0
- package/dist/migrations/index.js +22 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/pr/comment.d.ts +32 -0
- package/dist/pr/comment.js +99 -0
- package/dist/pr/comment.js.map +1 -0
- package/dist/pr/forge.d.ts +54 -0
- package/dist/pr/forge.js +119 -0
- package/dist/pr/forge.js.map +1 -0
- package/dist/pr/issue.d.ts +68 -0
- package/dist/pr/issue.js +107 -0
- package/dist/pr/issue.js.map +1 -0
- package/dist/pr/model.d.ts +99 -0
- package/dist/pr/model.js +137 -0
- package/dist/pr/model.js.map +1 -0
- package/dist/pr/render.d.ts +29 -0
- package/dist/pr/render.js +279 -0
- package/dist/pr/render.js.map +1 -0
- package/dist/project.d.ts +62 -0
- package/dist/project.js +92 -0
- package/dist/project.js.map +1 -0
- package/dist/rebase/index.d.ts +121 -0
- package/dist/rebase/index.js +390 -0
- package/dist/rebase/index.js.map +1 -0
- package/dist/rebase/repair.d.ts +41 -0
- package/dist/rebase/repair.js +68 -0
- package/dist/rebase/repair.js.map +1 -0
- package/dist/replay/clickhouse.d.ts +33 -0
- package/dist/replay/clickhouse.js +106 -0
- package/dist/replay/clickhouse.js.map +1 -0
- package/dist/replay/index.d.ts +39 -0
- package/dist/replay/index.js +57 -0
- package/dist/replay/index.js.map +1 -0
- package/dist/replay/postgres.d.ts +31 -0
- package/dist/replay/postgres.js +140 -0
- package/dist/replay/postgres.js.map +1 -0
- package/dist/replay/replay.d.ts +114 -0
- package/dist/replay/replay.js +98 -0
- package/dist/replay/replay.js.map +1 -0
- package/dist/replay/report.d.ts +18 -0
- package/dist/replay/report.js +72 -0
- package/dist/replay/report.js.map +1 -0
- package/dist/replay/shared.d.ts +28 -0
- package/dist/replay/shared.js +77 -0
- package/dist/replay/shared.js.map +1 -0
- package/dist/schemas.d.ts +34 -0
- package/dist/schemas.js +38 -0
- package/dist/schemas.js.map +1 -0
- package/dist/server.d.ts +40 -0
- package/dist/server.js +87 -0
- package/dist/server.js.map +1 -0
- package/dist/steps/backfill.d.ts +132 -0
- package/dist/steps/backfill.js +307 -0
- package/dist/steps/backfill.js.map +1 -0
- package/dist/steps/index.d.ts +52 -0
- package/dist/steps/index.js +52 -0
- package/dist/steps/index.js.map +1 -0
- package/dist/steps/kinds.d.ts +101 -0
- package/dist/steps/kinds.js +143 -0
- package/dist/steps/kinds.js.map +1 -0
- package/dist/steps/postgres-migration.d.ts +95 -0
- package/dist/steps/postgres-migration.js +149 -0
- package/dist/steps/postgres-migration.js.map +1 -0
- package/dist/steps/rebuild.d.ts +97 -0
- package/dist/steps/rebuild.js +155 -0
- package/dist/steps/rebuild.js.map +1 -0
- package/dist/steps/run.d.ts +45 -0
- package/dist/steps/run.js +72 -0
- package/dist/steps/run.js.map +1 -0
- package/dist/topology/render.d.ts +17 -0
- package/dist/topology/render.js +17 -0
- package/dist/topology/render.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +11 -0
- package/dist/version.js.map +1 -0
- package/dist/versioned/approval.d.ts +35 -0
- package/dist/versioned/approval.js +53 -0
- package/dist/versioned/approval.js.map +1 -0
- package/dist/versioned/checks.d.ts +29 -0
- package/dist/versioned/checks.js +54 -0
- package/dist/versioned/checks.js.map +1 -0
- package/dist/versioned/clickhouse.d.ts +24 -0
- package/dist/versioned/clickhouse.js +42 -0
- package/dist/versioned/clickhouse.js.map +1 -0
- package/dist/versioned/digest.d.ts +77 -0
- package/dist/versioned/digest.js +69 -0
- package/dist/versioned/digest.js.map +1 -0
- package/dist/versioned/driver.d.ts +51 -0
- package/dist/versioned/driver.js +13 -0
- package/dist/versioned/driver.js.map +1 -0
- package/dist/versioned/engine.d.ts +206 -0
- package/dist/versioned/engine.js +370 -0
- package/dist/versioned/engine.js.map +1 -0
- package/dist/versioned/explain.d.ts +123 -0
- package/dist/versioned/explain.js +294 -0
- package/dist/versioned/explain.js.map +1 -0
- package/dist/versioned/index.d.ts +46 -0
- package/dist/versioned/index.js +77 -0
- package/dist/versioned/index.js.map +1 -0
- package/dist/versioned/op.d.ts +72 -0
- package/dist/versioned/op.js +185 -0
- package/dist/versioned/op.js.map +1 -0
- package/dist/versioned/policy.d.ts +67 -0
- package/dist/versioned/policy.js +161 -0
- package/dist/versioned/policy.js.map +1 -0
- package/dist/versioned/postgres/catalog.d.ts +33 -0
- package/dist/versioned/postgres/catalog.js +34 -0
- package/dist/versioned/postgres/catalog.js.map +1 -0
- package/dist/versioned/postgres/driver.d.ts +71 -0
- package/dist/versioned/postgres/driver.js +140 -0
- package/dist/versioned/postgres/driver.js.map +1 -0
- package/dist/versioned/postgres/executor.d.ts +104 -0
- package/dist/versioned/postgres/executor.js +172 -0
- package/dist/versioned/postgres/executor.js.map +1 -0
- package/dist/versioned/postgres/index.d.ts +11 -0
- package/dist/versioned/postgres/index.js +12 -0
- package/dist/versioned/postgres/index.js.map +1 -0
- package/dist/versioned/postgres/waits.d.ts +46 -0
- package/dist/versioned/postgres/waits.js +78 -0
- package/dist/versioned/postgres/waits.js.map +1 -0
- package/dist/versioned/report.d.ts +25 -0
- package/dist/versioned/report.js +84 -0
- package/dist/versioned/report.js.map +1 -0
- package/dist/versioned/stand-down.d.ts +30 -0
- package/dist/versioned/stand-down.js +56 -0
- package/dist/versioned/stand-down.js.map +1 -0
- package/dist/versioned/state.d.ts +108 -0
- package/dist/versioned/state.js +153 -0
- package/dist/versioned/state.js.map +1 -0
- package/package.json +61 -4
- package/schemas/apply.schema.json +269 -0
- package/schemas/common.schema.json +213 -0
- package/schemas/drift.schema.json +36 -0
- package/schemas/init.schema.json +31 -0
- package/schemas/lint-rules.schema.json +54 -0
- package/schemas/lint.schema.json +290 -0
- package/schemas/mcp.schema.json +70 -0
- package/schemas/new.schema.json +71 -0
- package/schemas/plan.schema.json +371 -0
- package/schemas/rebase.schema.json +54 -0
- package/schemas/repair.schema.json +20 -0
- package/schemas/status.schema.json +310 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
import { guarded } from "../env-args.js";
|
|
3
|
+
import { loadProject, resolveEnvironment, YodelError } from "../project.js";
|
|
4
|
+
import { migrationId } from "../migrations/index.js";
|
|
5
|
+
import { adopt, BASELINE_NAME } from "../init/index.js";
|
|
6
|
+
const usage = "usage: yodel init --from <env> [--json] [--dir <project>] [--force] [--name <name>]";
|
|
7
|
+
const help = `${usage}
|
|
8
|
+
|
|
9
|
+
Adopts an existing database. Reads the live database sql.profiles.<env>
|
|
10
|
+
binds, with chant's import (what chant import --from <env> runs), writes
|
|
11
|
+
its declarations to the source directory (sourceDir, else src/), builds
|
|
12
|
+
them and plans them against the same database, which must show no change.
|
|
13
|
+
Then writes the baseline migration, migrations/<YYYYMMDDTHHMM>-baseline/,
|
|
14
|
+
the first migration (no parent), whose statements create everything, and
|
|
15
|
+
records it applied in the history table (yodel.config.ts history.database,
|
|
16
|
+
else YODEL_HISTORY_DATABASE, default yodeler) without running any of them.
|
|
17
|
+
From there, yodel plan <env> shows no change, yodel status <env> lists the
|
|
18
|
+
baseline applied with nothing pending, and yodel new writes the next
|
|
19
|
+
migration after the baseline.
|
|
20
|
+
|
|
21
|
+
The live database is only read. The one write to the server is the
|
|
22
|
+
baseline's history row (and the history's database and table, when they
|
|
23
|
+
are not there yet). If any step fails, every file init wrote is taken back.
|
|
24
|
+
|
|
25
|
+
What must exist first: a project directory with a chant.config.ts that has
|
|
26
|
+
lexicons: ["sql"], sql.dialect and sql.profiles.<env> (credentials by env
|
|
27
|
+
var), and a package.json from which chant and @intentius/chant-lexicon-sql
|
|
28
|
+
resolve, since chant builds the declarations. For ClickHouse the profile
|
|
29
|
+
must list the project's databases (sql.profiles.<env>.databases), for
|
|
30
|
+
Postgres its schemas (sql.profiles.<env>.schemas), and the history's
|
|
31
|
+
database (schema) must not be one of them. init does not write
|
|
32
|
+
chant.config.ts.
|
|
33
|
+
|
|
34
|
+
Postgres: the same, the history being <history database>.history in a
|
|
35
|
+
schema of that name (default yodeler.history), and the profile listing the
|
|
36
|
+
project's schemas (sql.profiles.<env>.schemas), the history's not among them.
|
|
37
|
+
|
|
38
|
+
Ownership: chant's import strips chant's ownership marker from comments,
|
|
39
|
+
and the plan compares declared definitions without it, so objects made by
|
|
40
|
+
hand (no marker) plan clean. init does not stamp the marker on them: they
|
|
41
|
+
stay unmarked, so chant never prunes them, until a declarative apply
|
|
42
|
+
restamps their comments.
|
|
43
|
+
|
|
44
|
+
Options:
|
|
45
|
+
--from <env> the environment to adopt (required)
|
|
46
|
+
--name <name> the baseline migration's name (default ${BASELINE_NAME})
|
|
47
|
+
--force overwrite declaration files the source directory already has
|
|
48
|
+
--json print what was done as JSON
|
|
49
|
+
-C, --dir <dir> the project directory (default: the working directory)
|
|
50
|
+
|
|
51
|
+
Exit codes:
|
|
52
|
+
0 adopted: declarations and the baseline written, the baseline recorded applied
|
|
53
|
+
4 refused, nothing written: the source directory already declares a
|
|
54
|
+
schema (without --force), the project already has migrations, the
|
|
55
|
+
history already records migrations, the environment holds nothing, or
|
|
56
|
+
a ClickHouse profile with no databases or with the history's database
|
|
57
|
+
5 another apply holds the lock; nothing recorded, nothing kept
|
|
58
|
+
1 anything else failed, and nothing was kept: a bad config, a server it
|
|
59
|
+
cannot read, a build or a plan that is not clean after the import
|
|
60
|
+
`;
|
|
61
|
+
function parseInitArgs(args) {
|
|
62
|
+
let parsed;
|
|
63
|
+
try {
|
|
64
|
+
parsed = parseArgs({
|
|
65
|
+
args,
|
|
66
|
+
allowPositionals: false,
|
|
67
|
+
strict: true,
|
|
68
|
+
options: {
|
|
69
|
+
from: { type: "string" },
|
|
70
|
+
json: { type: "boolean" },
|
|
71
|
+
dir: { type: "string", short: "C" },
|
|
72
|
+
force: { type: "boolean" },
|
|
73
|
+
name: { type: "string" },
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
throw new YodelError(`${e instanceof Error ? e.message : String(e)}\n${usage}`);
|
|
79
|
+
}
|
|
80
|
+
const { values } = parsed;
|
|
81
|
+
if (typeof values.from !== "string" || values.from === "")
|
|
82
|
+
throw new YodelError(`--from <env> is required\n${usage}`);
|
|
83
|
+
const name = typeof values.name === "string" ? values.name : BASELINE_NAME;
|
|
84
|
+
migrationId(name, new Date()); // a bad name fails before anything is read
|
|
85
|
+
return {
|
|
86
|
+
from: values.from,
|
|
87
|
+
json: values.json === true,
|
|
88
|
+
dir: typeof values.dir === "string" ? values.dir : process.cwd(),
|
|
89
|
+
force: values.force === true,
|
|
90
|
+
name,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** `yodel init --json` (schemas/init.schema.json). */
|
|
94
|
+
export function initJson(a) {
|
|
95
|
+
return {
|
|
96
|
+
environment: a.environment,
|
|
97
|
+
dialect: a.dialect,
|
|
98
|
+
status: "adopted",
|
|
99
|
+
objects: a.objects,
|
|
100
|
+
schemaFiles: a.schemaFiles,
|
|
101
|
+
migration: { path: a.migrationPath, ...a.baseline },
|
|
102
|
+
recorded: { history: a.recorded.database, seq: a.recorded.row.seq, note: a.recorded.row.note, appliedBy: a.recorded.row.applied_by },
|
|
103
|
+
warnings: a.warnings,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function report(io, json, a) {
|
|
107
|
+
if (json) {
|
|
108
|
+
io.out(`${JSON.stringify(initJson(a), null, 2)}\n`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const lines = [
|
|
112
|
+
`Adopted ${a.environment} (${a.dialect}): ${String(a.objects.length)} object${a.objects.length === 1 ? "" : "s"}`,
|
|
113
|
+
...a.objects.map((o) => ` ${o}`),
|
|
114
|
+
"",
|
|
115
|
+
`Declarations: ${a.schemaFiles.join(", ")}`,
|
|
116
|
+
`Baseline: ${a.migrationPath}/ (${String(a.baseline.statements)} statement${a.baseline.statements === 1 ? "" : "s"}, ${a.baseline.checksum})`,
|
|
117
|
+
`Recorded: applied in ${a.recorded.database}.history as a baseline; none of its statements was run`,
|
|
118
|
+
"",
|
|
119
|
+
`yodel plan ${a.environment} shows no change, and yodel status ${a.environment} lists the baseline applied.`,
|
|
120
|
+
];
|
|
121
|
+
for (const w of a.warnings)
|
|
122
|
+
lines.push(`warning: ${w}`);
|
|
123
|
+
io.out(`${lines.join("\n")}\n`);
|
|
124
|
+
}
|
|
125
|
+
/** `yodel init --from <env>`; the exit codes are in `help`. */
|
|
126
|
+
export const init = {
|
|
127
|
+
name: "init",
|
|
128
|
+
summary: "adopt a live database: declarations and a baseline recorded applied",
|
|
129
|
+
implemented: true,
|
|
130
|
+
run: (args, io) => guarded("init", io, args, help, async () => {
|
|
131
|
+
const a = parseInitArgs(args);
|
|
132
|
+
const project = await loadProject(a.dir);
|
|
133
|
+
const env = resolveEnvironment(project, a.from);
|
|
134
|
+
const adopted = await adopt(project, env, { force: a.force, name: a.name, log: (l) => { io.err(`${l}\n`); } });
|
|
135
|
+
report(io, a.json, adopted);
|
|
136
|
+
return 0;
|
|
137
|
+
}),
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
import { guarded } from "../env-args.js";
|
|
3
|
+
import { loadProject, resolveEnvironment, YodelError } from "../project.js";
|
|
4
|
+
import { scanMigrations } from "../migrations/index.js";
|
|
5
|
+
import { inspect, migrationsDir, openVersioned } from "../versioned/index.js";
|
|
6
|
+
import { LINT_RULES, lintExitCode, lintJson, lintMigrations, lintSettings, renderLint, updateChecksum } from "../lint/index.js";
|
|
7
|
+
import { projectRules, REPLAY_RULE, replayRule } from "../lint/project-rules.js";
|
|
8
|
+
import { renderReplay, replayHistory, replayJson } from "../replay/index.js";
|
|
9
|
+
const usage = "usage: yodel lint [--env <env>] [--replay <env> [--reset] [--reset-shared <profile>]... [--keep]] [--json] [--dir <project>] [--update-checksum <id>]... [--rules]";
|
|
10
|
+
const help = `${usage}
|
|
11
|
+
|
|
12
|
+
Checks the migrations directory against every lint rule, offline: no server
|
|
13
|
+
and no dev database. Every rule is free and runs in CI on every pull request.
|
|
14
|
+
|
|
15
|
+
Rules (yodel lint --rules lists them with their levels):
|
|
16
|
+
fork two migrations follow the same parent (yodel rebase)
|
|
17
|
+
directory not one readable chain: a bad name or file, a missing
|
|
18
|
+
parent, a cycle, a migration of another dialect
|
|
19
|
+
checksum a migration's files no longer hash to its checksum
|
|
20
|
+
unreadable-object an object in a recorded schema, or a step, the sql
|
|
21
|
+
lexicon cannot read or classify; an error, never skipped
|
|
22
|
+
destructive a drop that removes data for good
|
|
23
|
+
pg-rewrite Postgres: a rewrite or full scan under ACCESS EXCLUSIVE
|
|
24
|
+
pg-lock Postgres: writes blocked for a whole index build or scan
|
|
25
|
+
ch-mutation ClickHouse: a mutation rewriting parts, no rollback
|
|
26
|
+
ch-rebuild ClickHouse: a rebuild (ClickHouseRebuildOp)
|
|
27
|
+
refused-step a step yodel apply refuses (a manual step, an Op it
|
|
28
|
+
does not run)
|
|
29
|
+
migration-sql migration.sql does not hold a statement migration.json
|
|
30
|
+
records (apply runs migration.json's)
|
|
31
|
+
silence a yodel:allow line that is wrong or silences nothing
|
|
32
|
+
replay with --replay <env>: the history, replayed into a fresh
|
|
33
|
+
database on <env>'s server, does not give a migration's
|
|
34
|
+
recorded schema (names the first that differs)
|
|
35
|
+
|
|
36
|
+
Silencing: a line above a statement in its migration.sql,
|
|
37
|
+
-- yodel:allow <rule> <reason>
|
|
38
|
+
silences that statement rule (destructive, pg-rewrite, pg-lock,
|
|
39
|
+
ch-mutation, ch-rebuild) for that one statement. The reason is required,
|
|
40
|
+
and yodel apply records the rule, the statement and the reason in every
|
|
41
|
+
history row the migration writes (the silences column). Adding the line
|
|
42
|
+
changes the migration's checksum: for a migration not yet applied anywhere,
|
|
43
|
+
record the new one with --update-checksum <id>.
|
|
44
|
+
|
|
45
|
+
Levels: yodel.config.ts lint.rules sets a rule to "error", "warning" or
|
|
46
|
+
"off", e.g. lint: { rules: { "ch-mutation": "warning" } }. fork, directory,
|
|
47
|
+
checksum and unreadable-object are always errors.
|
|
48
|
+
|
|
49
|
+
Options:
|
|
50
|
+
--env <env> also compare with <env>'s history: a
|
|
51
|
+
checksum error is then an applied migration whose
|
|
52
|
+
files changed since it ran; a pending migration's
|
|
53
|
+
edit is a warning
|
|
54
|
+
--update-checksum <id> first write <id>'s migration.json checksum to match
|
|
55
|
+
its files (repeatable); refused with --env when <id>
|
|
56
|
+
is applied there
|
|
57
|
+
--replay <env> also replay every migration in order into <env>'s
|
|
58
|
+
server (a throwaway emulator: chant emulator up
|
|
59
|
+
--lexicon sql) and compare each with its recorded
|
|
60
|
+
schema; the databases or schemas the history names
|
|
61
|
+
must not exist there yet
|
|
62
|
+
--reset with --replay: drop those databases or schemas
|
|
63
|
+
first when they exist. Destructive: never against a
|
|
64
|
+
server whose data matters
|
|
65
|
+
--reset-shared <profile>
|
|
66
|
+
with --replay: replay even though <profile> binds
|
|
67
|
+
the same server and names one of those databases or
|
|
68
|
+
schemas, which the replay then empties (repeatable).
|
|
69
|
+
Refused without it, --reset or not
|
|
70
|
+
--keep with --replay: leave the replayed database in place
|
|
71
|
+
--rules list the rules and their levels, and exit
|
|
72
|
+
--json print the findings as JSON
|
|
73
|
+
-C, --dir <dir> the project directory (default: the working directory)
|
|
74
|
+
|
|
75
|
+
Exit codes:
|
|
76
|
+
0 no errors (warnings and silenced findings do not fail)
|
|
77
|
+
3 at least one error (a replay that differs counts)
|
|
78
|
+
4 --replay: the target already holds what the history names, and --reset
|
|
79
|
+
was not given, or another profile binds the same server and names one
|
|
80
|
+
of them and --reset-shared does not name it; nothing was run
|
|
81
|
+
1 lint could not run: a bad config, an unknown migration for
|
|
82
|
+
--update-checksum, a server that does not answer (--env)
|
|
83
|
+
`;
|
|
84
|
+
function parseLintArgs(args) {
|
|
85
|
+
let parsed;
|
|
86
|
+
try {
|
|
87
|
+
parsed = parseArgs({
|
|
88
|
+
args,
|
|
89
|
+
allowPositionals: false,
|
|
90
|
+
strict: true,
|
|
91
|
+
options: {
|
|
92
|
+
env: { type: "string" },
|
|
93
|
+
replay: { type: "string" },
|
|
94
|
+
reset: { type: "boolean" },
|
|
95
|
+
"reset-shared": { type: "string", multiple: true },
|
|
96
|
+
keep: { type: "boolean" },
|
|
97
|
+
json: { type: "boolean" },
|
|
98
|
+
dir: { type: "string", short: "C" },
|
|
99
|
+
"update-checksum": { type: "string", multiple: true },
|
|
100
|
+
rules: { type: "boolean" },
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
throw new YodelError(`${e instanceof Error ? e.message : String(e)}\n${usage}`);
|
|
106
|
+
}
|
|
107
|
+
const v = parsed.values;
|
|
108
|
+
const update = v["update-checksum"];
|
|
109
|
+
const replay = typeof v.replay === "string" ? v.replay : undefined;
|
|
110
|
+
const resetShared = Array.isArray(v["reset-shared"]) ? v["reset-shared"].filter((r) => typeof r === "string") : [];
|
|
111
|
+
if (replay === undefined && (v.reset === true || v.keep === true || resetShared.length > 0))
|
|
112
|
+
throw new YodelError(`--reset, --reset-shared and --keep go with --replay <env>\n${usage}`);
|
|
113
|
+
return {
|
|
114
|
+
env: typeof v.env === "string" ? v.env : undefined,
|
|
115
|
+
replay,
|
|
116
|
+
reset: v.reset === true,
|
|
117
|
+
resetShared,
|
|
118
|
+
keep: v.keep === true,
|
|
119
|
+
json: v.json === true,
|
|
120
|
+
dir: typeof v.dir === "string" ? v.dir : process.cwd(),
|
|
121
|
+
update: Array.isArray(update) ? update.filter((u) => typeof u === "string") : [],
|
|
122
|
+
rules: v.rules === true,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function allRules() {
|
|
126
|
+
return { ...LINT_RULES, ...Object.fromEntries(projectRules.map((r) => [r.rule.id, r.rule])), [REPLAY_RULE.id]: REPLAY_RULE };
|
|
127
|
+
}
|
|
128
|
+
function listRules(io, json, project) {
|
|
129
|
+
const rules = allRules();
|
|
130
|
+
const settings = lintSettings(project.yodel?.config.lint, rules, project.yodel?.path);
|
|
131
|
+
const rows = Object.values(rules).map((r) => ({ ...r, configured: settings.levels[r.id] ?? r.level }));
|
|
132
|
+
if (json) {
|
|
133
|
+
io.out(`${JSON.stringify(rows, null, 2)}\n`);
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
const width = Math.max(...rows.map((r) => r.id.length));
|
|
137
|
+
for (const r of rows) {
|
|
138
|
+
const marks = [r.configured, r.silenceable ? "silenceable" : "", r.dialect ?? ""].filter(Boolean).join(", ");
|
|
139
|
+
io.out(`${r.id.padEnd(width)} ${marks}\n${" ".repeat(width + 2)}${r.summary}\n`);
|
|
140
|
+
}
|
|
141
|
+
return 0;
|
|
142
|
+
}
|
|
143
|
+
/** `yodel lint`; the exit codes are in `help`. */
|
|
144
|
+
export const lint = {
|
|
145
|
+
name: "lint",
|
|
146
|
+
summary: "check the migrations against the lint rules",
|
|
147
|
+
implemented: true,
|
|
148
|
+
run: (args, io) => guarded("lint", io, args, help, async () => {
|
|
149
|
+
const a = parseLintArgs(args);
|
|
150
|
+
const project = await loadProject(a.dir);
|
|
151
|
+
if (a.rules)
|
|
152
|
+
return listRules(io, a.json, project);
|
|
153
|
+
const settings = lintSettings(project.yodel?.config.lint, allRules(), project.yodel?.path);
|
|
154
|
+
const dir = migrationsDir(project);
|
|
155
|
+
const options = { dialect: project.dialect, project, settings, rules: projectRules };
|
|
156
|
+
if (a.env !== undefined) {
|
|
157
|
+
const env = resolveEnvironment(project, a.env);
|
|
158
|
+
const ordered = scanMigrations(dir).ordered;
|
|
159
|
+
if (ordered) {
|
|
160
|
+
const venv = await openVersioned(project, env);
|
|
161
|
+
const { status } = await inspect(venv, ordered, { sync: false });
|
|
162
|
+
options.history = { environment: env.name, status };
|
|
163
|
+
}
|
|
164
|
+
else if (!a.json) {
|
|
165
|
+
io.err(`yodel lint: the migrations directory is not one chain, so it is not compared with ${env.name}'s history; fix the findings below first\n`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (a.update.length > 0) {
|
|
169
|
+
const byId = new Map(scanMigrations(dir).migrations.map((m) => [m.id, m]));
|
|
170
|
+
for (const id of a.update) {
|
|
171
|
+
const m = byId.get(id);
|
|
172
|
+
if (!m)
|
|
173
|
+
throw new YodelError(`--update-checksum ${id}: no such migration in ${dir}`);
|
|
174
|
+
const applied = options.history?.status.applied.some((x) => x.id === id);
|
|
175
|
+
if (applied)
|
|
176
|
+
throw new YodelError(`--update-checksum ${id}: it is applied in ${String(options.history?.environment)}; record an intended edit there with yodel repair ${id} --reason ... ${String(options.history?.environment)}`);
|
|
177
|
+
const changed = updateChecksum(m);
|
|
178
|
+
if (!a.json)
|
|
179
|
+
io.err(changed ? `${id}: checksum ${changed.from} is now ${changed.to}\n` : `${id}: its checksum already matches its files\n`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
let replay;
|
|
183
|
+
if (a.replay !== undefined) {
|
|
184
|
+
const env = resolveEnvironment(project, a.replay);
|
|
185
|
+
if (scanMigrations(dir).ordered) {
|
|
186
|
+
// A target that is not fresh throws here, exit 4, before anything is linted or run.
|
|
187
|
+
replay = await replayHistory(project, env, { reset: a.reset, resetShared: a.resetShared, keep: a.keep, log: (l) => { io.err(`replay: ${l}\n`); } });
|
|
188
|
+
options.rules = [...projectRules, replayRule(replay)];
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
io.err(`yodel lint: the migrations directory is not one chain, so it is not replayed; fix the findings below first\n`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const report = await lintMigrations(dir, options);
|
|
195
|
+
if (a.json)
|
|
196
|
+
io.out(`${JSON.stringify({ ...lintJson(report), ...(replay ? { replay: replayJson(replay) } : {}) }, null, 2)}\n`);
|
|
197
|
+
else
|
|
198
|
+
io.out(`${replay ? `${renderReplay(replay)}\n` : ""}${renderLint(report)}`);
|
|
199
|
+
return lintExitCode(report);
|
|
200
|
+
}),
|
|
201
|
+
};
|
|
202
|
+
//# sourceMappingURL=lint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,UAAU,EAAgB,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAmC,MAAM,kBAAkB,CAAC;AACjK,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAqB,MAAM,oBAAoB,CAAC;AAEhG,MAAM,KAAK,GAAG,oKAAoK,CAAC;AAEnL,MAAM,IAAI,GAAG,GAAG,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyEpB,CAAC;AAcF,SAAS,aAAa,CAAC,IAAc;IACnC,IAAI,MAAoC,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,SAAS,CAAC;YACjB,IAAI;YACJ,gBAAgB,EAAE,KAAK;YACvB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE;gBACP,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACvB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBAC1B,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;gBAC1B,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAClD,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;gBACzB,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;gBACzB,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE;gBACnC,iBAAiB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;gBACrD,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;aAC3B;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,UAAU,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,MAAM,MAAM,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChI,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,8DAA8D,KAAK,EAAE,CAAC,CAAC;IACzL,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;QAClD,MAAM;QACN,KAAK,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI;QACvB,WAAW;QACX,IAAI,EAAE,CAAC,CAAC,IAAI,KAAK,IAAI;QACrB,IAAI,EAAE,CAAC,CAAC,IAAI,KAAK,IAAI;QACrB,GAAG,EAAE,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;QACtD,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;QAC7F,KAAK,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI;KACxB,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ;IACf,OAAO,EAAE,GAAG,UAAU,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;AAC/H,CAAC;AAED,SAAS,SAAS,CAAC,EAAM,EAAE,IAAa,EAAE,OAAgB;IACxD,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,IAA2C,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC7H,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACvG,IAAI,IAAI,EAAE,CAAC;QACT,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7C,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7G,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,kDAAkD;AAClD,MAAM,CAAC,MAAM,IAAI,GAAY;IAC3B,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,6CAA6C;IACtD,WAAW,EAAE,IAAI;IACjB,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAChB,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,CAAC,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,IAA2C,EAAE,QAAQ,EAAE,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAClI,MAAM,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QAEnC,MAAM,OAAO,GAAgB,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;QAClG,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,kBAAkB,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;YAC/C,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YAC5C,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;gBAC/C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACjE,OAAO,CAAC,OAAO,GAAG,EAAE,WAAW,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;YACtD,CAAC;iBAAM,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBACnB,EAAE,CAAC,GAAG,CAAC,qFAAqF,GAAG,CAAC,IAAI,4CAA4C,CAAC,CAAC;YACpJ,CAAC;QACH,CAAC;QAED,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3E,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;gBAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACvB,IAAI,CAAC,CAAC;oBAAE,MAAM,IAAI,UAAU,CAAC,qBAAqB,EAAE,0BAA0B,GAAG,EAAE,CAAC,CAAC;gBACrF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;gBACzE,IAAI,OAAO;oBAAE,MAAM,IAAI,UAAU,CAAC,qBAAqB,EAAE,sBAAsB,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,qDAAqD,EAAE,iBAAiB,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;gBACnO,MAAM,OAAO,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;gBAClC,IAAI,CAAC,CAAC,CAAC,IAAI;oBAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,cAAc,OAAO,CAAC,IAAI,WAAW,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,4CAA4C,CAAC,CAAC;YAC9I,CAAC;QACH,CAAC;QAED,IAAI,MAAgC,CAAC;QACrC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,kBAAkB,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;YAClD,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;gBAChC,oFAAoF;gBACpF,MAAM,GAAG,MAAM,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACpJ,OAAO,CAAC,KAAK,GAAG,CAAC,GAAG,YAAY,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;YACxD,CAAC;iBAAM,CAAC;gBACN,EAAE,CAAC,GAAG,CAAC,8GAA8G,CAAC,CAAC;YACzH,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAClD,IAAI,CAAC,CAAC,IAAI;YAAE,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;;YAC1H,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACjF,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC,CAAC;CACL,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { guarded } from "../env-args.js";
|
|
4
|
+
import { loadProject, YodelError } from "../project.js";
|
|
5
|
+
import { YodelMcpServer } from "../mcp/server.js";
|
|
6
|
+
import { yodelTools } from "../mcp/tools.js";
|
|
7
|
+
const usage = "usage: yodel mcp [--dir <project>]";
|
|
8
|
+
const help = `${usage}
|
|
9
|
+
|
|
10
|
+
Serves read-only tools for a coding agent over the Model Context Protocol, on
|
|
11
|
+
stdin and stdout: status, plan, lint, drift, history and explain. Each runs
|
|
12
|
+
the yodel command of the same name with --json, in the project, and returns
|
|
13
|
+
its exit code and output in an envelope (schemas/mcp.schema.json). There is
|
|
14
|
+
no tool that applies, approves, repairs, rebases or writes a migration, and
|
|
15
|
+
the server refuses to start with one. A plan carries the commands that are a
|
|
16
|
+
person's to run: the approve command, and an override for a denied policy rule.
|
|
17
|
+
|
|
18
|
+
Start it with the reader's credentials in the environment, the ones
|
|
19
|
+
yodel plan uses; the tools read the servers chant.config.ts names.
|
|
20
|
+
|
|
21
|
+
Options:
|
|
22
|
+
-C, --dir <dir> the project directory (default: the working directory)
|
|
23
|
+
|
|
24
|
+
Exit codes:
|
|
25
|
+
0 stdin closed
|
|
26
|
+
1 the server could not start: no project in the directory
|
|
27
|
+
`;
|
|
28
|
+
/** `yodel mcp`; the exit codes are in `help`. */
|
|
29
|
+
export const mcp = {
|
|
30
|
+
name: "mcp",
|
|
31
|
+
summary: "serve read-only tools to a coding agent (MCP, stdio)",
|
|
32
|
+
implemented: true,
|
|
33
|
+
run: (args, io) => guarded("mcp", io, args, help, async () => {
|
|
34
|
+
let dir;
|
|
35
|
+
try {
|
|
36
|
+
const { values } = parseArgs({ args, strict: true, allowPositionals: false, options: { dir: { type: "string", short: "C" } } });
|
|
37
|
+
dir = resolve(values.dir ?? process.cwd());
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
throw new YodelError(`${e instanceof Error ? e.message : String(e)}\n${usage}`);
|
|
41
|
+
}
|
|
42
|
+
// Refuse to start outside a project, rather than answer every call with the same error.
|
|
43
|
+
dir = (await loadProject(dir)).dir;
|
|
44
|
+
const server = new YodelMcpServer(yodelTools(dir));
|
|
45
|
+
io.err(`yodel mcp: serving ${server.list().map((t) => t.name).join(", ")} for ${dir} on stdio\n`);
|
|
46
|
+
await server.serve();
|
|
47
|
+
return 0;
|
|
48
|
+
}),
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,KAAK,GAAG,oCAAoC,CAAC;AAEnD,MAAM,IAAI,GAAG,GAAG,KAAK;;;;;;;;;;;;;;;;;;;CAmBpB,CAAC;AAEF,iDAAiD;AACjD,MAAM,CAAC,MAAM,GAAG,GAAY;IAC1B,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,sDAAsD;IAC/D,WAAW,EAAE,IAAI;IACjB,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAChB,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE;QACxC,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;YAChI,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,UAAU,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;QAClF,CAAC;QACD,wFAAwF;QACxF,GAAG,GAAG,CAAC,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QACnD,EAAE,CAAC,GAAG,CAAC,sBAAsB,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,aAAa,CAAC,CAAC;QAClG,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;CACL,CAAC"}
|