@intentius/sql-yodeler 0.2.0 → 0.4.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 (308) hide show
  1. package/README.md +3 -3
  2. package/dist/apply-steps/index.d.ts +65 -0
  3. package/dist/apply-steps/index.js +106 -0
  4. package/dist/apply-steps/index.js.map +1 -0
  5. package/dist/approval-mode/index.d.ts +78 -0
  6. package/dist/approval-mode/index.js +105 -0
  7. package/dist/approval-mode/index.js.map +1 -0
  8. package/dist/chant/access.d.ts +87 -0
  9. package/dist/chant/access.js +169 -0
  10. package/dist/chant/access.js.map +1 -0
  11. package/dist/chant/build.js +7 -0
  12. package/dist/chant/build.js.map +1 -1
  13. package/dist/chant/drift.d.ts +17 -1
  14. package/dist/chant/drift.js +55 -2
  15. package/dist/chant/drift.js.map +1 -1
  16. package/dist/chant/plan.d.ts +18 -2
  17. package/dist/chant/plan.js +21 -3
  18. package/dist/chant/plan.js.map +1 -1
  19. package/dist/ci/render.d.ts +333 -0
  20. package/dist/ci/render.js +885 -0
  21. package/dist/ci/render.js.map +1 -0
  22. package/dist/ci/replay.d.ts +17 -0
  23. package/dist/ci/replay.js +69 -0
  24. package/dist/ci/replay.js.map +1 -0
  25. package/dist/cleanup/index.d.ts +86 -0
  26. package/dist/cleanup/index.js +207 -0
  27. package/dist/cleanup/index.js.map +1 -0
  28. package/dist/commands/apply.d.ts +113 -0
  29. package/dist/commands/apply.js +370 -30
  30. package/dist/commands/apply.js.map +1 -1
  31. package/dist/commands/approve.d.ts +13 -0
  32. package/dist/commands/approve.js +239 -13
  33. package/dist/commands/approve.js.map +1 -1
  34. package/dist/commands/checkpoint.d.ts +3 -0
  35. package/dist/commands/checkpoint.js +78 -0
  36. package/dist/commands/checkpoint.js.map +1 -0
  37. package/dist/commands/ci.d.ts +3 -0
  38. package/dist/commands/ci.js +130 -0
  39. package/dist/commands/ci.js.map +1 -0
  40. package/dist/commands/cleanup.d.ts +13 -0
  41. package/dist/commands/cleanup.js +138 -0
  42. package/dist/commands/cleanup.js.map +1 -0
  43. package/dist/commands/config.d.ts +3 -0
  44. package/dist/commands/config.js +136 -0
  45. package/dist/commands/config.js.map +1 -0
  46. package/dist/commands/docs.d.ts +11 -0
  47. package/dist/commands/docs.js +108 -0
  48. package/dist/commands/docs.js.map +1 -0
  49. package/dist/commands/drift.d.ts +13 -1
  50. package/dist/commands/drift.js +52 -5
  51. package/dist/commands/drift.js.map +1 -1
  52. package/dist/commands/index.js +16 -0
  53. package/dist/commands/index.js.map +1 -1
  54. package/dist/commands/init.js +1 -1
  55. package/dist/commands/init.js.map +1 -1
  56. package/dist/commands/lint.js +39 -7
  57. package/dist/commands/lint.js.map +1 -1
  58. package/dist/commands/new.js +133 -34
  59. package/dist/commands/new.js.map +1 -1
  60. package/dist/commands/override.js +48 -16
  61. package/dist/commands/override.js.map +1 -1
  62. package/dist/commands/plan.js +47 -6
  63. package/dist/commands/plan.js.map +1 -1
  64. package/dist/commands/report.d.ts +13 -0
  65. package/dist/commands/report.js +121 -0
  66. package/dist/commands/report.js.map +1 -0
  67. package/dist/commands/revert.d.ts +20 -0
  68. package/dist/commands/revert.js +246 -0
  69. package/dist/commands/revert.js.map +1 -0
  70. package/dist/commands/status.js +32 -5
  71. package/dist/commands/status.js.map +1 -1
  72. package/dist/commands/test.d.ts +3 -0
  73. package/dist/commands/test.js +164 -0
  74. package/dist/commands/test.js.map +1 -0
  75. package/dist/config/base.d.ts +69 -0
  76. package/dist/config/base.js +121 -0
  77. package/dist/config/base.js.map +1 -0
  78. package/dist/config/define.d.ts +240 -3
  79. package/dist/config/define.js +4 -0
  80. package/dist/config/define.js.map +1 -1
  81. package/dist/config/index.d.ts +2 -0
  82. package/dist/config/index.js +2 -0
  83. package/dist/config/index.js.map +1 -1
  84. package/dist/config/load.d.ts +1 -1
  85. package/dist/config/load.js +156 -7
  86. package/dist/config/load.js.map +1 -1
  87. package/dist/config/settings.d.ts +22 -1
  88. package/dist/config/settings.js +34 -2
  89. package/dist/config/settings.js.map +1 -1
  90. package/dist/credentials.d.ts +119 -0
  91. package/dist/credentials.js +119 -0
  92. package/dist/credentials.js.map +1 -0
  93. package/dist/exit.js +1 -1
  94. package/dist/exit.js.map +1 -1
  95. package/dist/history/postgres/ddl.d.ts +18 -0
  96. package/dist/history/postgres/ddl.js +27 -2
  97. package/dist/history/postgres/ddl.js.map +1 -1
  98. package/dist/history/postgres/store.d.ts +2 -0
  99. package/dist/history/postgres/store.js +7 -1
  100. package/dist/history/postgres/store.js.map +1 -1
  101. package/dist/history/rows.d.ts +16 -3
  102. package/dist/history/rows.js +30 -1
  103. package/dist/history/rows.js.map +1 -1
  104. package/dist/history/store.d.ts +2 -0
  105. package/dist/history/store.js +2 -2
  106. package/dist/history/store.js.map +1 -1
  107. package/dist/index.d.ts +8 -1
  108. package/dist/index.js +3 -0
  109. package/dist/index.js.map +1 -1
  110. package/dist/init/adopt.js +1 -1
  111. package/dist/init/adopt.js.map +1 -1
  112. package/dist/init/clickhouse-access.d.ts +64 -0
  113. package/dist/init/clickhouse-access.js +211 -0
  114. package/dist/init/clickhouse-access.js.map +1 -0
  115. package/dist/init/live.d.ts +4 -0
  116. package/dist/init/live.js +16 -0
  117. package/dist/init/live.js.map +1 -1
  118. package/dist/lint/access.d.ts +18 -0
  119. package/dist/lint/access.js +34 -0
  120. package/dist/lint/access.js.map +1 -0
  121. package/dist/lint/check.js +38 -6
  122. package/dist/lint/check.js.map +1 -1
  123. package/dist/lint/config.d.ts +7 -1
  124. package/dist/lint/config.js +11 -5
  125. package/dist/lint/config.js.map +1 -1
  126. package/dist/lint/index.d.ts +2 -0
  127. package/dist/lint/index.js +2 -0
  128. package/dist/lint/index.js.map +1 -1
  129. package/dist/lint/naming.d.ts +62 -0
  130. package/dist/lint/naming.js +138 -0
  131. package/dist/lint/naming.js.map +1 -0
  132. package/dist/lint/report.js +1 -1
  133. package/dist/lint/report.js.map +1 -1
  134. package/dist/lint/routines.d.ts +26 -0
  135. package/dist/lint/routines.js +65 -0
  136. package/dist/lint/routines.js.map +1 -0
  137. package/dist/lint/rules.d.ts +51 -6
  138. package/dist/lint/rules.js +23 -6
  139. package/dist/lint/rules.js.map +1 -1
  140. package/dist/lint/schema-checks.d.ts +63 -0
  141. package/dist/lint/schema-checks.js +128 -0
  142. package/dist/lint/schema-checks.js.map +1 -0
  143. package/dist/lint/statements.d.ts +22 -1
  144. package/dist/lint/statements.js +40 -1
  145. package/dist/lint/statements.js.map +1 -1
  146. package/dist/mcp/tools.d.ts +1 -1
  147. package/dist/mcp/tools.js +1 -1
  148. package/dist/mcp/tools.js.map +1 -1
  149. package/dist/migrations/checkpoint.d.ts +45 -0
  150. package/dist/migrations/checkpoint.js +108 -0
  151. package/dist/migrations/checkpoint.js.map +1 -0
  152. package/dist/migrations/checks.d.ts +19 -1
  153. package/dist/migrations/checks.js +15 -0
  154. package/dist/migrations/checks.js.map +1 -1
  155. package/dist/migrations/create.d.ts +13 -4
  156. package/dist/migrations/create.js +24 -7
  157. package/dist/migrations/create.js.map +1 -1
  158. package/dist/migrations/document.d.ts +10 -0
  159. package/dist/migrations/document.js +1 -0
  160. package/dist/migrations/document.js.map +1 -1
  161. package/dist/migrations/index.d.ts +2 -0
  162. package/dist/migrations/index.js +2 -0
  163. package/dist/migrations/index.js.map +1 -1
  164. package/dist/migrations/routines.d.ts +21 -0
  165. package/dist/migrations/routines.js +30 -0
  166. package/dist/migrations/routines.js.map +1 -0
  167. package/dist/notify/index.d.ts +124 -0
  168. package/dist/notify/index.js +210 -0
  169. package/dist/notify/index.js.map +1 -0
  170. package/dist/notify/verify.d.ts +53 -0
  171. package/dist/notify/verify.js +71 -0
  172. package/dist/notify/verify.js.map +1 -0
  173. package/dist/pr/model.d.ts +7 -1
  174. package/dist/pr/model.js +29 -7
  175. package/dist/pr/model.js.map +1 -1
  176. package/dist/pr/render.d.ts +4 -1
  177. package/dist/pr/render.js +49 -9
  178. package/dist/pr/render.js.map +1 -1
  179. package/dist/pr/tenants.d.ts +37 -0
  180. package/dist/pr/tenants.js +138 -0
  181. package/dist/pr/tenants.js.map +1 -0
  182. package/dist/probe.d.ts +27 -0
  183. package/dist/probe.js +106 -0
  184. package/dist/probe.js.map +1 -0
  185. package/dist/project.d.ts +35 -2
  186. package/dist/project.js +62 -2
  187. package/dist/project.js.map +1 -1
  188. package/dist/replay/clickhouse.d.ts +31 -0
  189. package/dist/replay/clickhouse.js +103 -6
  190. package/dist/replay/clickhouse.js.map +1 -1
  191. package/dist/replay/replay.d.ts +14 -3
  192. package/dist/replay/replay.js +62 -31
  193. package/dist/replay/replay.js.map +1 -1
  194. package/dist/replay/report.js +1 -1
  195. package/dist/replay/report.js.map +1 -1
  196. package/dist/report/audit.d.ts +138 -0
  197. package/dist/report/audit.js +219 -0
  198. package/dist/report/audit.js.map +1 -0
  199. package/dist/report/jsonl.d.ts +21 -0
  200. package/dist/report/jsonl.js +52 -0
  201. package/dist/report/jsonl.js.map +1 -0
  202. package/dist/report/model.d.ts +68 -0
  203. package/dist/report/model.js +127 -0
  204. package/dist/report/model.js.map +1 -0
  205. package/dist/report/render.d.ts +18 -0
  206. package/dist/report/render.js +127 -0
  207. package/dist/report/render.js.map +1 -0
  208. package/dist/schema-docs/render.d.ts +49 -0
  209. package/dist/schema-docs/render.js +359 -0
  210. package/dist/schema-docs/render.js.map +1 -0
  211. package/dist/schemas.d.ts +7 -2
  212. package/dist/schemas.js +7 -2
  213. package/dist/schemas.js.map +1 -1
  214. package/dist/sources/ddl.d.ts +48 -0
  215. package/dist/sources/ddl.js +53 -0
  216. package/dist/sources/ddl.js.map +1 -0
  217. package/dist/sources/index.d.ts +69 -0
  218. package/dist/sources/index.js +170 -0
  219. package/dist/sources/index.js.map +1 -0
  220. package/dist/steps/backfill.d.ts +40 -5
  221. package/dist/steps/backfill.js +128 -8
  222. package/dist/steps/backfill.js.map +1 -1
  223. package/dist/steps/index.d.ts +19 -1
  224. package/dist/steps/index.js +34 -7
  225. package/dist/steps/index.js.map +1 -1
  226. package/dist/steps/kinds.d.ts +42 -4
  227. package/dist/steps/kinds.js +88 -14
  228. package/dist/steps/kinds.js.map +1 -1
  229. package/dist/steps/postgres-migration.d.ts +38 -25
  230. package/dist/steps/postgres-migration.js +49 -32
  231. package/dist/steps/postgres-migration.js.map +1 -1
  232. package/dist/steps/rebuild.d.ts +15 -6
  233. package/dist/steps/rebuild.js +12 -9
  234. package/dist/steps/rebuild.js.map +1 -1
  235. package/dist/tenants/index.d.ts +41 -0
  236. package/dist/tenants/index.js +121 -0
  237. package/dist/tenants/index.js.map +1 -0
  238. package/dist/tenants/target.d.ts +23 -0
  239. package/dist/tenants/target.js +29 -0
  240. package/dist/tenants/target.js.map +1 -0
  241. package/dist/tenants/wave.d.ts +128 -0
  242. package/dist/tenants/wave.js +254 -0
  243. package/dist/tenants/wave.js.map +1 -0
  244. package/dist/testing/define.d.ts +62 -0
  245. package/dist/testing/define.js +32 -0
  246. package/dist/testing/define.js.map +1 -0
  247. package/dist/testing/files.d.ts +5 -0
  248. package/dist/testing/files.js +18 -0
  249. package/dist/testing/files.js.map +1 -0
  250. package/dist/testing/report.d.ts +14 -0
  251. package/dist/testing/report.js +83 -0
  252. package/dist/testing/report.js.map +1 -0
  253. package/dist/testing/run.d.ts +104 -0
  254. package/dist/testing/run.js +328 -0
  255. package/dist/testing/run.js.map +1 -0
  256. package/dist/versioned/approval.d.ts +6 -0
  257. package/dist/versioned/approval.js +11 -5
  258. package/dist/versioned/approval.js.map +1 -1
  259. package/dist/versioned/checks.d.ts +8 -2
  260. package/dist/versioned/checks.js +34 -13
  261. package/dist/versioned/checks.js.map +1 -1
  262. package/dist/versioned/driver.d.ts +2 -2
  263. package/dist/versioned/engine.d.ts +16 -0
  264. package/dist/versioned/engine.js +20 -6
  265. package/dist/versioned/engine.js.map +1 -1
  266. package/dist/versioned/explain.d.ts +2 -0
  267. package/dist/versioned/explain.js +3 -1
  268. package/dist/versioned/explain.js.map +1 -1
  269. package/dist/versioned/index.d.ts +1 -0
  270. package/dist/versioned/index.js +1 -0
  271. package/dist/versioned/index.js.map +1 -1
  272. package/dist/versioned/op.d.ts +6 -1
  273. package/dist/versioned/op.js +7 -2
  274. package/dist/versioned/op.js.map +1 -1
  275. package/dist/versioned/policy.d.ts +33 -2
  276. package/dist/versioned/policy.js +59 -8
  277. package/dist/versioned/policy.js.map +1 -1
  278. package/dist/versioned/report.js +9 -0
  279. package/dist/versioned/report.js.map +1 -1
  280. package/dist/versioned/revert.d.ts +128 -0
  281. package/dist/versioned/revert.js +251 -0
  282. package/dist/versioned/revert.js.map +1 -0
  283. package/dist/versioned/state.d.ts +25 -0
  284. package/dist/versioned/state.js +37 -4
  285. package/dist/versioned/state.js.map +1 -1
  286. package/dist/waves/index.d.ts +224 -0
  287. package/dist/waves/index.js +353 -0
  288. package/dist/waves/index.js.map +1 -0
  289. package/dist/waves/promotion.d.ts +56 -0
  290. package/dist/waves/promotion.js +108 -0
  291. package/dist/waves/promotion.js.map +1 -0
  292. package/dist/waves/record.d.ts +34 -0
  293. package/dist/waves/record.js +20 -0
  294. package/dist/waves/record.js.map +1 -0
  295. package/package.json +11 -7
  296. package/schemas/apply.schema.json +162 -3
  297. package/schemas/checkpoint.schema.json +19 -0
  298. package/schemas/cleanup.schema.json +40 -0
  299. package/schemas/drift.schema.json +26 -1
  300. package/schemas/event.schema.json +36 -0
  301. package/schemas/lint-rules.schema.json +4 -0
  302. package/schemas/lint.schema.json +4 -0
  303. package/schemas/new.schema.json +41 -3
  304. package/schemas/plan.schema.json +157 -0
  305. package/schemas/report.schema.json +114 -0
  306. package/schemas/revert.schema.json +69 -0
  307. package/schemas/status.schema.json +64 -3
  308. package/schemas/test.schema.json +41 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe.js","sourceRoot":"","sources":["../src/probe.ts"],"names":[],"mappings":"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"}
package/dist/project.d.ts CHANGED
@@ -36,11 +36,27 @@ export interface Project {
36
36
  path: string;
37
37
  config: YodelConfig;
38
38
  } | undefined;
39
+ /**
40
+ * `sql.profiles.<env>.access` as chant.config.ts says it, before
41
+ * yodel.config.ts's `environments.<env>.access` is put in {@link config}'s
42
+ * profile. Only the environments whose profile sets it.
43
+ */
44
+ profileAccess?: Record<string, boolean>;
39
45
  }
40
46
  export interface Environment {
41
47
  name: string;
42
- /** `sql.profiles.<name>`. */
48
+ /** `sql.profiles.<name>`; a tenant's is its environment's, on the tenant's database or schema. */
43
49
  profile: SqlProfile;
50
+ /** A tenant of a tenant set (#56): `name` is `<env>/<tenant>`. */
51
+ tenant?: TenantOf;
52
+ }
53
+ /** Which tenant an {@link Environment} is. */
54
+ export interface TenantOf {
55
+ /** The environment whose tenant set names it. */
56
+ env: string;
57
+ name: string;
58
+ /** The database (ClickHouse) or schema (Postgres) the environment's profile names, which the migrations are written against. */
59
+ template: string;
44
60
  }
45
61
  /** The nearest directory at or above `start` that holds `chant.config.ts`. */
46
62
  export declare function findProjectDir(start: string): string | undefined;
@@ -51,6 +67,16 @@ export declare function findProjectDir(start: string): string | undefined;
51
67
  export declare function projectDialect(config: ProjectConfig, configPath: string): SqlDialect;
52
68
  /** Builds a {@link Project} from a config already loaded. Pure, for tests and callers that load the config themselves. */
53
69
  export declare function projectFromConfig(dir: string, configPath: string, config: ProjectConfig, yodel?: Project["yodel"]): Project;
70
+ /**
71
+ * `config` with each profile's `access` set to yodel.config.ts's
72
+ * `environments.<env>.access` where it sets one, so the chant functions yodel
73
+ * calls in process (the plan, the import, the server reads) manage access as
74
+ * yodel.config.ts says. Pure.
75
+ */
76
+ export declare function accessInProfiles(config: ProjectConfig, yodel: YodelConfig | undefined): {
77
+ config: ProjectConfig;
78
+ profileAccess: Record<string, boolean>;
79
+ };
54
80
  /**
55
81
  * Finds the project at or above `start` (default: the working directory) and
56
82
  * loads its `chant.config.ts` through chant's own loader, so it is validated
@@ -58,5 +84,12 @@ export declare function projectFromConfig(dir: string, configPath: string, confi
58
84
  * there is one.
59
85
  */
60
86
  export declare function loadProject(start?: string): Promise<Project>;
61
- /** `sql.profiles.<name>`, or an error naming the environments the project declares. */
87
+ /**
88
+ * `sql.profiles.<name>`, or an error naming the environments the project
89
+ * declares. A tenant, `<env>/<tenant>`, is `<env>`'s profile on the
90
+ * tenant's database or schema; it is added to the loaded config's
91
+ * `sql.profiles` under its own name, so chant binds it like any profile.
92
+ * Whether a tenant set given by a file or a query names it is checked when
93
+ * its server is opened (`openVersioned`).
94
+ */
62
95
  export declare function resolveEnvironment(project: Project, name: string): Environment;
package/dist/project.js CHANGED
@@ -7,6 +7,7 @@
7
7
  */
8
8
  import { existsSync } from "node:fs";
9
9
  import { dirname, join, resolve } from "node:path";
10
+ import { splitTarget, TENANT_NAME } from "./tenants/target.js";
10
11
  /** An error a verb reports as one line on stderr, with the exit code it ends with. */
11
12
  export class YodelError extends Error {
12
13
  exitCode;
@@ -49,7 +50,30 @@ export function projectFromConfig(dir, configPath, config, yodel) {
49
50
  throw new YodelError(`${configPath}: lexicons does not include "sql"; add lexicons: ["sql"] and import "@intentius/chant-lexicon-sql"`);
50
51
  }
51
52
  const sourceDir = config.sourceDir ?? (existsSync(join(dir, "src")) ? "src" : ".");
52
- return { dir, configPath, config, dialect: projectDialect(config, configPath), sourceDir, ...(yodel ? { yodel } : {}) };
53
+ const { config: withAccess, profileAccess } = accessInProfiles(config, yodel?.config);
54
+ return { dir, configPath, config: withAccess, dialect: projectDialect(config, configPath), sourceDir, ...(yodel ? { yodel } : {}), profileAccess };
55
+ }
56
+ /**
57
+ * `config` with each profile's `access` set to yodel.config.ts's
58
+ * `environments.<env>.access` where it sets one, so the chant functions yodel
59
+ * calls in process (the plan, the import, the server reads) manage access as
60
+ * yodel.config.ts says. Pure.
61
+ */
62
+ export function accessInProfiles(config, yodel) {
63
+ const profiles = config.sql?.profiles ?? {};
64
+ const profileAccess = {};
65
+ for (const [name, profile] of Object.entries(profiles)) {
66
+ const access = profile.access;
67
+ if (typeof access === "boolean")
68
+ profileAccess[name] = access;
69
+ }
70
+ const own = Object.entries(yodel?.environments ?? {}).filter(([name, e]) => e.access !== undefined && profiles[name] !== undefined);
71
+ if (own.length === 0)
72
+ return { config, profileAccess };
73
+ const next = { ...profiles };
74
+ for (const [name, e] of own)
75
+ next[name] = { ...profiles[name], access: e.access };
76
+ return { config: { ...config, sql: { ...config.sql, profiles: next } }, profileAccess };
53
77
  }
54
78
  /**
55
79
  * Finds the project at or above `start` (default: the working directory) and
@@ -70,12 +94,27 @@ export async function loadProject(start = process.cwd()) {
70
94
  throw new YodelError(e instanceof Error ? e.message : String(e));
71
95
  }
72
96
  const config = loaded.config;
97
+ // An environment whose reader and writer are one identity is refused before anything reads or writes (#50).
98
+ const { sharedCredentialsIn } = await import("./credentials.js");
99
+ const shared = sharedCredentialsIn(config.sql?.profiles ?? {});
100
+ if (shared)
101
+ throw new YodelError(`refused: ${shared}`, 4);
73
102
  const { loadYodelConfig } = await import("./config/load.js");
74
103
  const yodel = await loadYodelConfig(dir, Object.keys(config.sql?.profiles ?? {}));
75
104
  return projectFromConfig(dir, loaded.configPath ?? join(dir, "chant.config.ts"), config, yodel);
76
105
  }
77
- /** `sql.profiles.<name>`, or an error naming the environments the project declares. */
106
+ /**
107
+ * `sql.profiles.<name>`, or an error naming the environments the project
108
+ * declares. A tenant, `<env>/<tenant>`, is `<env>`'s profile on the
109
+ * tenant's database or schema; it is added to the loaded config's
110
+ * `sql.profiles` under its own name, so chant binds it like any profile.
111
+ * Whether a tenant set given by a file or a query names it is checked when
112
+ * its server is opened (`openVersioned`).
113
+ */
78
114
  export function resolveEnvironment(project, name) {
115
+ const { env: base, tenant } = splitTarget(name);
116
+ if (tenant !== undefined)
117
+ return resolveTenant(project, base, tenant);
79
118
  const profiles = project.config.sql?.profiles ?? {};
80
119
  const profile = profiles[name];
81
120
  if (!profile) {
@@ -89,4 +128,25 @@ export function resolveEnvironment(project, name) {
89
128
  }
90
129
  return { name, profile };
91
130
  }
131
+ function resolveTenant(project, base, tenant) {
132
+ const env = resolveEnvironment(project, base);
133
+ const set = project.yodel?.config.environments?.[base]?.tenants;
134
+ if (!set)
135
+ throw new YodelError(`no environment "${base}/${tenant}": ${base} has no tenant set (yodel.config.ts environments.${base}.tenants)`);
136
+ if (!TENANT_NAME.test(tenant))
137
+ throw new YodelError(`"${tenant}" is not a tenant name (letters, digits and _, not starting with a digit)`);
138
+ if (Array.isArray(set) && !set.includes(tenant))
139
+ throw new YodelError(`no tenant "${tenant}" in ${base}'s tenant set (${set.join(", ")})`);
140
+ const key = project.dialect === "postgres" ? "schemas" : "databases";
141
+ const named = env.profile[key];
142
+ const template = Array.isArray(named) && named.length === 1 && typeof named[0] === "string" ? named[0] : undefined;
143
+ if (!template) {
144
+ throw new YodelError(`${base} has a tenant set, so sql.profiles.${base}.${key} must name exactly one ${project.dialect === "postgres" ? "schema" : "database"}: the template its tenants are made from, which the migrations are written against`);
145
+ }
146
+ const name = `${base}/${tenant}`;
147
+ const profile = { ...env.profile, [key]: [tenant] };
148
+ const sql = (project.config.sql ??= {});
149
+ sql.profiles = { ...(sql.profiles ?? {}), [name]: profile };
150
+ return { name, profile, tenant: { env: base, name: tenant, template } };
151
+ }
92
152
  //# sourceMappingURL=project.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,18 @@
13
13
  * so is a database a migration should have dropped. chant's working objects
14
14
  * (a rebuild's retained `__chant_old` table) are not read, as a plan does
15
15
  * not read them.
16
+ *
17
+ * Functions, users, roles and row policies (#46) belong to no database (a
18
+ * row policy outlives its table's), so emptying the databases leaves them:
19
+ * the ones the history declares are counted as occupying the server and
20
+ * dropped with the databases. A grantee's grants go with the grantee.
21
+ * A user declared without `IDENTIFIED` is the environment's to create, with
22
+ * its password, and no migration creates it: the replay stands in for the
23
+ * environment and creates it with a random password before the first
24
+ * statement, so the grants and `ALTER USER` statements that name it run,
25
+ * and gives it its declared clauses (`DEFAULT ROLE`, `SETTINGS`, ...)
26
+ * before each migration is compared, as the environment that made it as
27
+ * declared would ({@link alterToDeclared}).
16
28
  */
17
29
  import { type Environment, type Project } from "../project.js";
18
30
  import { type ClickHousePort } from "../history/index.js";
@@ -29,5 +41,24 @@ export interface ClickHouseReplayOptions {
29
41
  }
30
42
  /** The databases a ClickHouse build output names, with bare names in `defaultDatabase`. */
31
43
  export declare function clickhouseDatabases(schema: unknown, defaultDatabase: string): Promise<string[]>;
44
+ /** A function, user, role or row policy a history declares, which emptying its databases does not remove. */
45
+ export interface GlobalObject {
46
+ kind: "function" | "user" | "role" | "rowPolicy";
47
+ name: string;
48
+ /** A user declared without `IDENTIFIED`, which the environment creates. */
49
+ withheld?: true;
50
+ /** A row policy's table, `database.table`. */
51
+ on?: string;
52
+ }
53
+ /** The functions, users, roles and row policies a ClickHouse build output declares. */
54
+ export declare function clickhouseGlobals(schema: unknown, defaultDatabase: string): Promise<GlobalObject[]>;
55
+ /**
56
+ * A user declared without `IDENTIFIED`, given its declared clauses:
57
+ * `CREATE USER u DEFAULT ROLE r` as `ALTER USER u DEFAULT ROLE r`, or
58
+ * `undefined` when it declares none (or is not such a user).
59
+ */
60
+ export declare function alterToDeclared(ddl: string): string | undefined;
61
+ /** `DROP ... IF EXISTS` for one, row policies before the users and roles they apply to. */
62
+ export declare const dropGlobal: (g: GlobalObject) => string;
32
63
  /** The replay driver for `env`, a ClickHouse environment, over the history `ordered`. */
33
64
  export declare function clickhouseReplay(project: Project, env: Environment, ordered: readonly Migration[], options?: ClickHouseReplayOptions): Promise<ReplayDriver>;
@@ -13,7 +13,20 @@
13
13
  * so is a database a migration should have dropped. chant's working objects
14
14
  * (a rebuild's retained `__chant_old` table) are not read, as a plan does
15
15
  * not read them.
16
+ *
17
+ * Functions, users, roles and row policies (#46) belong to no database (a
18
+ * row policy outlives its table's), so emptying the databases leaves them:
19
+ * the ones the history declares are counted as occupying the server and
20
+ * dropped with the databases. A grantee's grants go with the grantee.
21
+ * A user declared without `IDENTIFIED` is the environment's to create, with
22
+ * its password, and no migration creates it: the replay stands in for the
23
+ * environment and creates it with a random password before the first
24
+ * statement, so the grants and `ALTER USER` statements that name it run,
25
+ * and gives it its declared clauses (`DEFAULT ROLE`, `SETTINGS`, ...)
26
+ * before each migration is compared, as the environment that made it as
27
+ * declared would ({@link alterToDeclared}).
16
28
  */
29
+ import { randomBytes } from "node:crypto";
17
30
  import { YodelError } from "../project.js";
18
31
  import { environmentSettings } from "../config/settings.js";
19
32
  import { httpPort } from "../history/index.js";
@@ -23,11 +36,44 @@ const SYSTEM = new Set(["system", "information_schema", "INFORMATION_SCHEMA"]);
23
36
  const DEFAULT = "default";
24
37
  const ident = (s) => `\`${s.replace(/`/g, "``")}\``;
25
38
  const quote = (s) => `'${s.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
39
+ /** The kinds that belong to no database: a function, a user, a role, a grantee's grants. */
40
+ const GLOBAL_KINDS = new Set(["function", "user", "role", "grants"]);
26
41
  /** The databases a ClickHouse build output names, with bare names in `defaultDatabase`. */
27
42
  export async function clickhouseDatabases(schema, defaultDatabase) {
28
43
  const { schemaFromBuildOutput } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/schema");
29
- return [...new Set(schemaFromBuildOutput(JSON.stringify(schema), defaultDatabase).map((o) => o.canonical.database ?? o.canonical.name))];
44
+ return [...new Set(schemaFromBuildOutput(JSON.stringify(schema), defaultDatabase).filter((o) => !GLOBAL_KINDS.has(o.canonical.kind)).map((o) => o.canonical.database ?? o.canonical.name))];
45
+ }
46
+ /** The functions, users, roles and row policies a ClickHouse build output declares. */
47
+ export async function clickhouseGlobals(schema, defaultDatabase) {
48
+ const { schemaFromBuildOutput } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/schema");
49
+ return schemaFromBuildOutput(JSON.stringify(schema), defaultDatabase).flatMap((o) => {
50
+ const c = o.canonical;
51
+ if (c.kind === "user" && c.access?.identified === undefined)
52
+ return [{ kind: "user", name: c.name, withheld: true }];
53
+ if (c.kind === "function" || c.kind === "user" || c.kind === "role")
54
+ return [{ kind: c.kind, name: c.name }];
55
+ if (c.kind === "rowPolicy")
56
+ return [{ kind: "rowPolicy", name: c.name, on: `${c.database ?? defaultDatabase}.${c.table ?? ""}` }];
57
+ return [];
58
+ });
59
+ }
60
+ const CREATE_USER = /^\s*CREATE\s+USER\s+(?:IF\s+NOT\s+EXISTS\s+|OR\s+REPLACE\s+)?(`(?:[^`]|``)*`|[^\s,]+)(?:\s+ON\s+CLUSTER\s+\S+)?/i;
61
+ /**
62
+ * A user declared without `IDENTIFIED`, given its declared clauses:
63
+ * `CREATE USER u DEFAULT ROLE r` as `ALTER USER u DEFAULT ROLE r`, or
64
+ * `undefined` when it declares none (or is not such a user).
65
+ */
66
+ export function alterToDeclared(ddl) {
67
+ const m = CREATE_USER.exec(ddl);
68
+ if (!m || /\bIDENTIFIED\b/i.test(ddl))
69
+ return undefined;
70
+ const rest = ddl.slice(m[0].length).trim().replace(/;\s*$/, "");
71
+ return rest === "" ? undefined : `ALTER USER ${m[1] ?? ""} ${rest}`;
30
72
  }
73
+ const KEYWORD = { function: "FUNCTION", user: "USER", role: "ROLE", rowPolicy: "ROW POLICY" };
74
+ const onTable = (on) => on.split(".").map(ident).join(".");
75
+ /** `DROP ... IF EXISTS` for one, row policies before the users and roles they apply to. */
76
+ export const dropGlobal = (g) => `DROP ${KEYWORD[g.kind]} IF EXISTS ${ident(g.name)}${g.on !== undefined ? ` ON ${onTable(g.on)}` : ""}`;
31
77
  /** The replay driver for `env`, a ClickHouse environment, over the history `ordered`. */
32
78
  export async function clickhouseReplay(project, env, ordered, options = {}) {
33
79
  const processEnv = options.processEnv ?? process.env;
@@ -40,9 +86,19 @@ export async function clickhouseReplay(project, env, ordered, options = {}) {
40
86
  const topology = settings.topology;
41
87
  const defaultDatabase = (m) => m.document.defaultDatabase ?? target.defaultDatabase;
42
88
  const named = new Set();
43
- for (const m of ordered)
89
+ const globals = new Map();
90
+ for (const m of ordered) {
44
91
  for (const d of await clickhouseDatabases(m.document.schema, defaultDatabase(m)))
45
92
  named.add(d);
93
+ for (const g of await clickhouseGlobals(m.document.schema, defaultDatabase(m))) {
94
+ // Withheld in one migration and created in another is created by the history: not the replay's to make.
95
+ const seen = globals.get(dropGlobal(g));
96
+ const made = { kind: g.kind, name: g.name, ...(g.on !== undefined ? { on: g.on } : {}) };
97
+ globals.set(dropGlobal(g), seen && !(seen.withheld && g.withheld) ? made : g);
98
+ }
99
+ }
100
+ const order = { rowPolicy: 0, user: 1, role: 2, function: 3 };
101
+ const declaredGlobals = [...globals.values()].sort((a, b) => order[a.kind] - order[b.kind] || a.name.localeCompare(b.name));
46
102
  const scope = [...named].sort();
47
103
  const system = scope.filter((d) => SYSTEM.has(d));
48
104
  if (system.length > 0)
@@ -53,6 +109,28 @@ export async function clickhouseReplay(project, env, ordered, options = {}) {
53
109
  const port = options.port ?? (await httpPort(endpoint));
54
110
  const log = options.log ?? (() => undefined);
55
111
  const runStep = options.runStep ?? defaultStepRunner;
112
+ /** The declared functions, users, roles and row policies the server holds, as `<kind> <name>`. */
113
+ const globalsThere = async () => {
114
+ const there = async (kind, sql) => new Set((await port.query(sql)).map((r) => r.name));
115
+ const names = (kind) => declaredGlobals.filter((g) => g.kind === kind).map((g) => quote(g.kind === "rowPolicy" ? `${g.name} ON ${g.on ?? ""}` : g.name));
116
+ const out = [];
117
+ const sets = [
118
+ ["function", `SELECT name FROM system.functions WHERE origin = 'SQLUserDefined' AND name IN (${names("function").join(", ")})`],
119
+ ["user", `SELECT name FROM system.users WHERE name IN (${names("user").join(", ")})`],
120
+ ["role", `SELECT name FROM system.roles WHERE name IN (${names("role").join(", ")})`],
121
+ ["rowPolicy", `SELECT concat(short_name, ' ON ', database, '.', table) AS name FROM system.row_policies WHERE name IN (${names("rowPolicy").join(", ")}) OR concat(short_name, ' ON ', database, '.', table) IN (${names("rowPolicy").join(", ")})`],
122
+ ];
123
+ for (const [kind, sql] of sets) {
124
+ if (names(kind).length === 0)
125
+ continue;
126
+ const held = await there(kind, sql);
127
+ out.push(...declaredGlobals.filter((g) => g.kind === kind && held.has(g.kind === "rowPolicy" ? `${g.name} ON ${g.on ?? ""}` : g.name)));
128
+ }
129
+ return out;
130
+ };
131
+ // The withheld users are made before the first statement after the server is emptied, and dropped with the rest.
132
+ let environmentUsers = false;
133
+ const describeGlobal = (g) => `${g.kind === "rowPolicy" ? "row policy" : g.kind} ${g.name}${g.on !== undefined ? ` ON ${g.on}` : ""}`;
56
134
  const tablesInDefault = async () => (await port.query(`SELECT name FROM system.tables WHERE database = ${quote(DEFAULT)} AND NOT is_temporary ORDER BY name`)).map((r) => r.name);
57
135
  return {
58
136
  dialect: "clickhouse",
@@ -63,7 +141,7 @@ export async function clickhouseReplay(project, env, ordered, options = {}) {
63
141
  const there = others.length === 0 ? [] : (await port.query(`SELECT name FROM system.databases WHERE name IN (${others.map(quote).join(", ")}) ORDER BY name`)).map((r) => r.name);
64
142
  if (scope.includes(DEFAULT) && (await tablesInDefault()).length > 0)
65
143
  there.unshift(`${DEFAULT} (not empty)`);
66
- return there;
144
+ return [...there, ...(await globalsThere()).map(describeGlobal)];
67
145
  },
68
146
  async clear() {
69
147
  for (const d of scope) {
@@ -73,28 +151,47 @@ export async function clickhouseReplay(project, env, ordered, options = {}) {
73
151
  for (const t of await tablesInDefault())
74
152
  await port.query(`DROP TABLE IF EXISTS ${ident(DEFAULT)}.${ident(t)} SYNC`);
75
153
  }
154
+ for (const g of declaredGlobals)
155
+ await port.query(dropGlobal(g));
156
+ environmentUsers = false;
76
157
  },
77
158
  async statement(_m, _index, step) {
159
+ if (!environmentUsers) {
160
+ for (const g of declaredGlobals.filter((x) => x.withheld)) {
161
+ await port.query(`CREATE USER IF NOT EXISTS ${ident(g.name)} IDENTIFIED BY ${quote(randomBytes(24).toString("base64url"))}`);
162
+ log(`created user ${g.name}, which the history declares without a password, with a random one, as the environment would`);
163
+ }
164
+ environmentUsers = true;
165
+ }
78
166
  await port.query(renderForEnvironment(step.sql, topology), step.waitsForMutation ? { settings: { mutations_sync: "2" } } : {});
79
167
  },
80
- async opStep(m, index) {
168
+ async opStep(m, index, opts = {}) {
81
169
  const step = m.document.steps[index];
82
170
  if (!step)
83
171
  return { refused: `${m.id} has no step ${String(index)}` };
84
172
  const plan = planStep(step);
85
173
  if (plan.run !== "rebuild")
86
174
  return { refused: plan.run === "refused" ? plan.reason : `step ${String(index)} is not one the replay runs` };
87
- const { summary } = await runStep({ environment: env.name, projectDir: project.dir, port, endpoint, migration: m, index, plan, log: (line) => { log(` ${line}`); } });
175
+ const { summary } = await runStep({ environment: env.name, projectDir: project.dir, port, endpoint, migration: m, index, plan, log: (line) => { log(` ${line}`); }, ...(opts.receipts ? { rebuildReceipts: opts.receipts } : {}) });
88
176
  const s = summary;
89
177
  return { ran: true, ...(s?.swapped !== undefined ? { note: s.swapped ? "swapped" : "not swapped" } : {}) };
90
178
  },
91
179
  async compare(m) {
180
+ for (const o of m.document.schema.objects.filter((x) => x.type === "ClickHouse::User")) {
181
+ const alter = alterToDeclared(o.ddl);
182
+ if (alter)
183
+ await port.query(renderForEnvironment(alter, topology));
184
+ }
92
185
  const { keyedByQualifiedName, schemaFromBuildOutput, schemaFromServer } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/schema");
93
186
  const { diffSchemas } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/diff");
94
187
  const { dropFormattingOnly } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/server-format");
95
188
  const db = defaultDatabase(m);
189
+ const { scopeOf } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/normalize");
190
+ const { declaredAccess } = await import("@intentius/chant-lexicon-sql/clickhouse/live/catalog");
96
191
  const declared = keyedByQualifiedName(schemaFromBuildOutput(JSON.stringify(m.document.schema), db, topology));
97
- const live = await schemaFromServer({ ...target, databases: scope, defaultDatabase: db }, new Set(scope));
192
+ // A function, user, role or grantee is its own scope (chant's scopeOf), read when the migration declares it.
193
+ const scopes = new Set([...scope, ...declared.filter((o) => GLOBAL_KINDS.has(o.canonical.kind)).map((o) => scopeOf(o.canonical))]);
194
+ const live = await schemaFromServer({ ...target, databases: scope, defaultDatabase: db }, scopes, undefined, declaredAccess(declared.map((o) => o.canonical)));
98
195
  const diff = diffSchemas(live, declared);
99
196
  const changes = await dropFormattingOnly(endpoint, diff.changes);
100
197
  const label = new Map(declared.map((o) => [o.key, `${o.exportName} (${o.key})`]));
@@ -1 +1 @@
1
- {"version":3,"file":"clickhouse.js","sourceRoot":"","sources":["../../src/replay/clickhouse.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"clickhouse.js","sourceRoot":"","sources":["../../src/replay/clickhouse.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,12 @@
22
22
  * replayed: the check stops there, naming it ({@link ReplayResult} outcome
23
23
  * `unreplayable`).
24
24
  *
25
+ * A checkpoint (#63) is left out of the chain: it creates its parent's
26
+ * recorded schema from nothing. After the chain, each checkpoint is
27
+ * replayed on its own into the database emptied again, and compared with
28
+ * its recorded schema, the one the chain was shown to give. So a fresh
29
+ * environment that starts from it ends where one that ran the chain does.
30
+ *
25
31
  * The database is the replay's: it must be fresh when the replay starts
26
32
  * (every database or schema the history names absent, the default one
27
33
  * empty), or emptied first when the caller says so (`reset`), and it is
@@ -31,7 +37,8 @@
31
37
  import type { ClassifiedChange } from "@intentius/chant-lexicon-sql/core/classifier";
32
38
  import type { StatementStep } from "@intentius/chant-lexicon-sql/migration-statements";
33
39
  import { type SqlDialect } from "../project.js";
34
- import type { Migration } from "../migrations/index.js";
40
+ import { type Migration } from "../migrations/index.js";
41
+ import type { RebuildReceiptStore } from "../steps/rebuild.js";
35
42
  /** Exit code: the target is not fresh and `reset` was not given; nothing was run. */
36
43
  export declare const NOT_FRESH = 4;
37
44
  /** Exit code: a step the replay cannot run (a manual step, an Op it does not run). */
@@ -58,8 +65,10 @@ export interface ReplayDriver {
58
65
  clear(): Promise<void>;
59
66
  /** Sends one statement step of `m`, as apply sends it. Throws the server's error. */
60
67
  statement(m: Migration, index: number, step: StatementStep): Promise<void>;
61
- /** Runs an Op step that is neither a backfill nor refused by {@link planStep}; or says why it cannot. */
62
- opStep(m: Migration, index: number): Promise<OpStepOutcome>;
68
+ /** Runs an Op step that is neither a backfill nor refused by {@link planStep}; or says why it cannot. `receipts` keeps a rebuild's partition receipts instead of the server. */
69
+ opStep(m: Migration, index: number, options?: {
70
+ receipts?: RebuildReceiptStore;
71
+ }): Promise<OpStepOutcome>;
63
72
  /** The replayed database against `m`'s recorded schema. Empty when they match. */
64
73
  compare(m: Migration): Promise<ReplayChange[]>;
65
74
  close(): Promise<void>;
@@ -72,6 +81,8 @@ export interface ReplayedMigration {
72
81
  ran: string[];
73
82
  /** Steps skipped, as `step <i>: <what> (<why>)`. */
74
83
  skipped: string[];
84
+ /** A checkpoint (#63), replayed on its own into an empty database after the chain. */
85
+ checkpoint?: true;
75
86
  }
76
87
  export type ReplayResult = {
77
88
  dialect: SqlDialect;
@@ -22,6 +22,12 @@
22
22
  * replayed: the check stops there, naming it ({@link ReplayResult} outcome
23
23
  * `unreplayable`).
24
24
  *
25
+ * A checkpoint (#63) is left out of the chain: it creates its parent's
26
+ * recorded schema from nothing. After the chain, each checkpoint is
27
+ * replayed on its own into the database emptied again, and compared with
28
+ * its recorded schema, the one the chain was shown to give. So a fresh
29
+ * environment that starts from it ends where one that ran the chain does.
30
+ *
25
31
  * The database is the replay's: it must be fresh when the replay starts
26
32
  * (every database or schema the history names absent, the default one
27
33
  * empty), or emptied first when the caller says so (`reset`), and it is
@@ -29,6 +35,7 @@
29
35
  * table; no lock is taken.
30
36
  */
31
37
  import { YodelError } from "../project.js";
38
+ import { isCheckpoint } from "../migrations/index.js";
32
39
  import { asBackfill, describeStep, planStep } from "../steps/kinds.js";
33
40
  /** Exit code: the target is not fresh and `reset` was not given; nothing was run. */
34
41
  export const NOT_FRESH = 4;
@@ -52,42 +59,66 @@ export async function replayMigrations(ordered, driver, options = {}) {
52
59
  await driver.clear();
53
60
  }
54
61
  const matched = [];
55
- try {
56
- for (const m of ordered) {
57
- const done = { id: m.id, statements: 0, ran: [], skipped: [] };
58
- log(`${m.id}: replaying`);
59
- for (const [i, step] of m.document.steps.entries()) {
60
- const s = step;
61
- if (s.kind === "statement") {
62
- try {
63
- await driver.statement(m, i, s);
64
- }
65
- catch (e) {
66
- return { ...base, reset: occupied.length > 0, matched, outcome: "failed", migration: m.id, step: i, error: firstLine(message(e)) };
67
- }
68
- done.statements++;
69
- continue;
62
+ const reset = occupied.length > 0;
63
+ /** Replays one migration's steps on what the database holds now, then compares; a failure, or the migration replayed. */
64
+ const replayOne = async (m) => {
65
+ const done = { id: m.id, statements: 0, ran: [], skipped: [], ...(isCheckpoint(m) ? { checkpoint: true } : {}) };
66
+ log(`${m.id}: replaying${isCheckpoint(m) ? " (a checkpoint, into an empty database)" : ""}`);
67
+ for (const [i, step] of m.document.steps.entries()) {
68
+ const s = step;
69
+ if (s.kind === "statement") {
70
+ try {
71
+ await driver.statement(m, i, s);
70
72
  }
71
- if (asBackfill(s)) {
72
- done.skipped.push(`step ${String(i)}: ${describeStep(s)} (moves data; the replayed database has none)`);
73
- continue;
73
+ catch (e) {
74
+ return { ...base, reset, matched, outcome: "failed", migration: m.id, step: i, error: firstLine(message(e)) };
74
75
  }
75
- const plan = planStep(s);
76
- const outcome = plan.run === "refused" ? { refused: plan.reason } : await driver.opStep(m, i);
77
- if ("refused" in outcome) {
78
- return { ...base, reset: occupied.length > 0, matched, outcome: "unreplayable", migration: m.id, step: i, reason: outcome.refused };
79
- }
80
- done.ran.push(`step ${String(i)}: ${describeStep(s)}${outcome.note ? ` (${outcome.note})` : ""}`);
76
+ done.statements++;
77
+ continue;
78
+ }
79
+ if (asBackfill(s)) {
80
+ done.skipped.push(`step ${String(i)}: ${describeStep(s)} (moves data; the replayed database has none)`);
81
+ continue;
81
82
  }
82
- const changes = await driver.compare(m);
83
- if (changes.length > 0) {
84
- log(`${m.id}: differs from its recorded schema (${String(changes.length)} difference${changes.length === 1 ? "" : "s"})`);
85
- return { ...base, reset: occupied.length > 0, matched, outcome: "differs", migration: done, changes };
83
+ const plan = planStep(s);
84
+ const outcome = plan.run === "refused" ? { refused: plan.reason } : await driver.opStep(m, i);
85
+ if ("refused" in outcome) {
86
+ return { ...base, reset, matched, outcome: "unreplayable", migration: m.id, step: i, reason: outcome.refused };
86
87
  }
87
- log(`${m.id}: matches its recorded schema`);
88
- matched.push(done);
88
+ done.ran.push(`step ${String(i)}: ${describeStep(s)}${outcome.note ? ` (${outcome.note})` : ""}`);
89
+ }
90
+ const changes = await driver.compare(m);
91
+ if (changes.length > 0) {
92
+ log(`${m.id}: differs from its recorded schema (${String(changes.length)} difference${changes.length === 1 ? "" : "s"})`);
93
+ return { ...base, reset, matched, outcome: "differs", migration: done, changes };
94
+ }
95
+ log(`${m.id}: matches its recorded schema`);
96
+ return done;
97
+ };
98
+ const failed = (r) => "outcome" in r;
99
+ try {
100
+ // The chain, first to newest. A checkpoint (#63) creates its parent's schema from nothing, so on top of the chain it would only fail: it is replayed on its own below.
101
+ const checkpoints = [];
102
+ for (const m of ordered) {
103
+ if (isCheckpoint(m)) {
104
+ checkpoints.push(m);
105
+ log(`${m.id}: a checkpoint; replayed on its own, into an empty database, after the chain`);
106
+ continue;
107
+ }
108
+ const r = await replayOne(m);
109
+ if (failed(r))
110
+ return r;
111
+ matched.push(r);
112
+ }
113
+ // Each checkpoint into an empty database: its statements must give its recorded schema, its parent's, which the chain was just shown to give.
114
+ for (const m of checkpoints) {
115
+ await driver.clear();
116
+ const r = await replayOne(m);
117
+ if (failed(r))
118
+ return r;
119
+ matched.push(r);
89
120
  }
90
- return { ...base, reset: occupied.length > 0, matched, outcome: "matches" };
121
+ return { ...base, reset, matched, outcome: "matches" };
91
122
  }
92
123
  finally {
93
124
  // Emptying afterwards is housekeeping: its failure is reported, never put in place of the result.