@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
@@ -4,11 +4,12 @@
4
4
  * planStep(step) statement, rebuild, backfill, or refused (with why)
5
5
  * stepSha(step, files) the hash a step's history rows record
6
6
  * runRebuild(...) a ClickHouseRebuildOp step (./rebuild.ts)
7
- * runBackfill(...) a backfill step, an Op of effect() batches (./backfill.ts)
7
+ * runBackfill(...) a backfill step, a form or an Op of effect() batches (./backfill.ts)
8
8
  * runPgMigration(...) a PostgresMigrationOp step (./postgres-migration.ts)
9
9
  * defaultStepRunner what the versioned apply calls for an Op step
10
10
  */
11
- import { YodelError } from "../project.js";
11
+ import { loadProject, resolveEnvironment, YodelError } from "../project.js";
12
+ import { renameIdentifier } from "../tenants/target.js";
12
13
  import { runBackfill, serverReceipts } from "./backfill.js";
13
14
  import { rebuildChantConfig, runRebuild } from "./rebuild.js";
14
15
  import { runPgMigration } from "./postgres-migration.js";
@@ -17,14 +18,39 @@ export * from "./run.js";
17
18
  export * from "./rebuild.js";
18
19
  export * from "./backfill.js";
19
20
  export * from "./postgres-migration.js";
21
+ /** `value` with the template renamed in every string it holds (#56), as statements are. */
22
+ export function renameDeep(value, rename) {
23
+ if (typeof value === "string")
24
+ return rename(value);
25
+ if (Array.isArray(value))
26
+ return value.map((v) => renameDeep(v, rename));
27
+ if (typeof value === "object" && value !== null)
28
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, renameDeep(v, rename)]));
29
+ return value;
30
+ }
31
+ /**
32
+ * What an Op step runs with on a tenant (#56): its options and the recorded
33
+ * schema with the template renamed to the tenant, and the project's chant
34
+ * config with the tenant's profile in it, which the Op's activities bind
35
+ * with in place of chant.config.ts.
36
+ */
37
+ export async function tenantStep(projectDir, environment, tenant) {
38
+ const project = await loadProject(projectDir);
39
+ resolveEnvironment(project, environment);
40
+ return { rename: (s) => renameIdentifier(s, tenant.template, tenant.name), config: project.config };
41
+ }
20
42
  export const defaultStepRunner = async (ctx) => {
43
+ const tenant = ctx.tenant ? await tenantStep(ctx.projectDir, ctx.environment, ctx.tenant) : undefined;
44
+ const schema = tenant ? renameDeep(ctx.migration.document.schema, tenant.rename) : ctx.migration.document.schema;
21
45
  if (ctx.plan.run === "rebuild") {
22
- const config = await rebuildChantConfig(ctx.projectDir, ctx.environment);
23
- const { summary } = await runRebuild(ctx.plan.options, { environment: ctx.environment, projectDir: ctx.projectDir, schema: ctx.migration.document.schema, log: ctx.log, config });
46
+ const options = tenant ? { ...ctx.plan.options, table: tenant.rename(ctx.plan.options.table) } : ctx.plan.options;
47
+ const config = await rebuildChantConfig(ctx.projectDir, ctx.environment, process.env, tenant?.config);
48
+ const { summary } = await runRebuild(options, { environment: ctx.environment, projectDir: ctx.projectDir, schema, log: ctx.log, config, ...(ctx.rebuildReceipts ? { receipts: ctx.rebuildReceipts } : {}) });
24
49
  return { summary };
25
50
  }
26
51
  if (ctx.plan.run === "pgMigration") {
27
- const { summary } = await runPgMigration(ctx.plan.options, { environment: ctx.environment, projectDir: ctx.projectDir, schema: ctx.migration.document.schema, lockTimeoutMs: ctx.lockTimeoutMs, log: ctx.log });
52
+ const options = tenant ? { ...ctx.plan.options, table: tenant.rename(ctx.plan.options.table) } : ctx.plan.options;
53
+ const { summary } = await runPgMigration(options, { environment: ctx.environment, projectDir: ctx.projectDir, schema, lockTimeoutMs: ctx.lockTimeoutMs, log: ctx.log, config: tenant?.config });
28
54
  return { summary };
29
55
  }
30
56
  if (!ctx.port && !ctx.postgres)
@@ -37,15 +63,16 @@ export const defaultStepRunner = async (ctx) => {
37
63
  : undefined);
38
64
  if (!receipts)
39
65
  throw new YodelError("a backfill step needs a receipt store, and this environment has no server endpoint for one");
40
- const { summary } = await runBackfill(ctx.plan.file, {
66
+ const { summary } = await runBackfill(ctx.plan.form ?? ctx.plan.file, {
41
67
  environment: ctx.environment,
42
68
  projectDir: ctx.projectDir,
43
69
  migrationId: ctx.migration.id,
44
70
  dir: ctx.migration.dir,
45
- text: ctx.migration.files.extra?.[ctx.plan.file],
71
+ text: ctx.plan.file === undefined ? undefined : ctx.migration.files.extra?.[ctx.plan.file],
46
72
  ...(ctx.postgres ? { postgres: { client: ctx.postgres.client, timeouts: ctx.postgres.timeouts } } : { port: ctx.port }),
47
73
  receipts,
48
74
  log: ctx.log,
75
+ ...(tenant ? { rename: tenant.rename } : {}),
49
76
  });
50
77
  return { summary };
51
78
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/steps/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/steps/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,UAAU,EAAqC,MAAM,eAAe,CAAC;AAC/G,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAyB,MAAM,eAAe,CAAC;AAEnF,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAA4B,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,yBAAyB,CAAC;AA2BxC,2FAA2F;AAC3F,MAAM,UAAU,UAAU,CAAC,KAAc,EAAE,MAA6B;IACtE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACzE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9I,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAkB,EAAE,WAAmB,EAAE,MAAgB;IACxF,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,CAAC;IAC9C,kBAAkB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACzC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;AACtG,CAAC;AAKD,MAAM,CAAC,MAAM,iBAAiB,GAAe,KAAK,EAAE,GAAG,EAAE,EAAE;IACzD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACtG,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;IACjH,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;QAClH,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACtG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7M,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;QAClH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAChM,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ;QAAE,MAAM,IAAI,UAAU,CAAC,yFAAyF,CAAC,CAAC;IAChJ,MAAM,QAAQ,GACZ,GAAG,CAAC,QAAQ;QACZ,CAAC,GAAG,CAAC,QAAQ;YACX,CAAC,CAAC,MAAM,cAAc,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,GAAG,CAAC,WAAW,CAAC;YAC/G,CAAC,CAAC,GAAG,CAAC,QAAQ;gBACZ,CAAC,CAAC,MAAM,cAAc,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC,WAAW,CAAC;gBACrE,CAAC,CAAC,SAAS,CAAC,CAAC;IACnB,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,UAAU,CAAC,4FAA4F,CAAC,CAAC;IAClI,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;QACpE,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,WAAW,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE;QAC7B,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,GAAG;QACtB,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;QAC1F,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;QACvH,QAAQ;QACR,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7C,CAAC,CAAC;IACH,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC,CAAC"}
@@ -9,8 +9,10 @@
9
9
  *
10
10
  * - `ClickHouseRebuildOp`, the step `yodel new` writes for a ClickHouse sort
11
11
  * key, engine or key-column change (`./rebuild.ts`);
12
- * - `backfill`, a data backfill the author writes as an Op of `effect()`
13
- * steps in a module in the migration's directory (`./backfill.ts`);
12
+ * - `backfill`, a data backfill: written as a form in the step's options
13
+ * (a table, a key and a batch size, or a list of batches, and the SQL of
14
+ * one batch), or as an Op of `effect()` steps in a module in the
15
+ * migration's directory (`./backfill.ts`);
14
16
  * - `PostgresMigrationOp`, the step `yodel new` writes for a Postgres column
15
17
  * rename or type change across kinds (`./postgres-migration.ts`, #13).
16
18
  *
@@ -28,9 +30,30 @@ export declare const PG_MIGRATION_OP = "PostgresMigrationOp";
28
30
  type OpStep = Extract<MigrationStep, {
29
31
  kind: "op";
30
32
  }>;
33
+ /**
34
+ * A backfill written as a form, yodel's own terms for the common case: the
35
+ * step's options in `migration.json`, which yodel turns into an Op of
36
+ * `effect()` batches, one receipt each.
37
+ *
38
+ * Batches are either ranges of an integer `key` of `table`, `batchSize`
39
+ * wide (`{from}` and `{to}` in the SQL, from inclusive, to exclusive, read
40
+ * from the table's smallest and largest key when the step runs), or the
41
+ * values `batches` lists (`{batch}` in the SQL). `sql` is one statement, or
42
+ * several run in order, for one batch.
43
+ */
44
+ export interface BackfillForm {
45
+ table: string;
46
+ key?: string;
47
+ batchSize?: number;
48
+ batches?: Array<string | number>;
49
+ sql: string | string[];
50
+ /** Settings for each statement: ClickHouse query settings (`mutations_sync`), Postgres `set_config` for the batch's transaction. */
51
+ settings?: Record<string, string>;
52
+ }
31
53
  /**
32
54
  * A backfill step in `migration.json`. chant's `OpStep` shape, so every
33
- * reader of steps sees an Op step:
55
+ * reader of steps sees an Op step. Its options are a {@link BackfillForm},
56
+ * or name the module that exports the Op:
34
57
  *
35
58
  * { "kind": "op", "object": "backfill", "type": "Yodel::Backfill", "name": "<migration name>",
36
59
  * "op": "backfill", "importPath": "./backfill.ts", "options": { "file": "backfill.ts" },
@@ -40,7 +63,7 @@ export interface BackfillStep extends Omit<OpStep, "op" | "options"> {
40
63
  op: typeof BACKFILL_OP;
41
64
  options: {
42
65
  file: string;
43
- };
66
+ } | BackfillForm;
44
67
  }
45
68
  export type DualWrite = {
46
69
  mode: "materialized-view";
@@ -53,6 +76,8 @@ export interface RebuildOptions {
53
76
  name: string;
54
77
  table: string;
55
78
  dualWrite: DualWrite;
79
+ /** How long the old table is kept after the swap; default chant's (7 days). */
80
+ retain?: string;
56
81
  }
57
82
  /** A `PostgresMigrationOp` step's options: chant's `{ name, env, table, column }`, and what the author may add (`using`, `retain`, ...). */
58
83
  export interface PgMigrationOptions {
@@ -81,12 +106,25 @@ export type StepPlan = {
81
106
  } | {
82
107
  run: "backfill";
83
108
  file: string;
109
+ form?: undefined;
110
+ } | {
111
+ run: "backfill";
112
+ form: BackfillForm;
113
+ file?: undefined;
84
114
  } | {
85
115
  run: "refused";
86
116
  reason: string;
87
117
  };
88
118
  /** The step as a backfill step, when it is one. */
89
119
  export declare const asBackfill: (step: MigrationStep | BackfillStep) => BackfillStep | undefined;
120
+ /** The placeholders a form's SQL takes: `{from}` and `{to}` with a key, `{batch}` with a list. */
121
+ export declare const formPlaceholders: (form: Pick<BackfillForm, "key">) => string[];
122
+ /** What is wrong with a backfill form, if anything. */
123
+ export declare function formProblems(options: unknown): string[];
124
+ /** The step's options as a form, when they are one (no `file`). */
125
+ export declare function asForm(options: unknown): BackfillForm | undefined;
126
+ /** One line saying how a form batches: `shop.orders by id, 10000 a batch` or `shop.orders, 3 batches`. */
127
+ export declare function describeForm(form: BackfillForm): string;
90
128
  /** How `yodel apply` treats one step. */
91
129
  export declare function planStep(step: MigrationStep | BackfillStep): StepPlan;
92
130
  /** One line naming a step, for logs and refusals. */
@@ -9,8 +9,10 @@
9
9
  *
10
10
  * - `ClickHouseRebuildOp`, the step `yodel new` writes for a ClickHouse sort
11
11
  * key, engine or key-column change (`./rebuild.ts`);
12
- * - `backfill`, a data backfill the author writes as an Op of `effect()`
13
- * steps in a module in the migration's directory (`./backfill.ts`);
12
+ * - `backfill`, a data backfill: written as a form in the step's options
13
+ * (a table, a key and a batch size, or a list of batches, and the SQL of
14
+ * one batch), or as an Op of `effect()` steps in a module in the
15
+ * migration's directory (`./backfill.ts`);
14
16
  * - `PostgresMigrationOp`, the step `yodel new` writes for a Postgres column
15
17
  * rename or type change across kinds (`./postgres-migration.ts`, #13).
16
18
  *
@@ -26,6 +28,14 @@ export const BACKFILL_FILE = "backfill.ts";
26
28
  export const REBUILD_OP = "ClickHouseRebuildOp";
27
29
  export const PG_MIGRATION_OP = "PostgresMigrationOp";
28
30
  const isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
31
+ const optional = (o, key, ok) => {
32
+ const v = o[key];
33
+ if (v === undefined)
34
+ return undefined;
35
+ return ok(v) ? v : null;
36
+ };
37
+ const isString = (v) => typeof v === "string" && v !== "";
38
+ const isPositiveInt = (v) => typeof v === "number" && Number.isInteger(v) && v > 0;
29
39
  /** The step as a backfill step, when it is one. */
30
40
  export const asBackfill = (step) => step.kind === "op" && step.op === BACKFILL_OP ? step : undefined;
31
41
  /** The file a backfill step names: relative to the migration's directory, `/`-separated, inside it. */
@@ -38,6 +48,69 @@ function backfillFile(options) {
38
48
  return undefined;
39
49
  return file;
40
50
  }
51
+ /** The placeholders a form's SQL takes: `{from}` and `{to}` with a key, `{batch}` with a list. */
52
+ export const formPlaceholders = (form) => (form.key !== undefined ? ["{from}", "{to}"] : ["{batch}"]);
53
+ /** What is wrong with a backfill form, if anything. */
54
+ export function formProblems(options) {
55
+ if (!isRecord(options))
56
+ return ["a backfill form is an object"];
57
+ const o = options;
58
+ const problems = [];
59
+ const known = new Set(["table", "key", "batchSize", "batches", "sql", "settings"]);
60
+ for (const k of Object.keys(o))
61
+ if (!known.has(k))
62
+ problems.push(`"${k}" is not a field of a backfill (${[...known].join(", ")})`);
63
+ if (!isString(o.table))
64
+ problems.push(`"table" names the table the backfill fills, for example "shop.orders"`);
65
+ const sql = typeof o.sql === "string" ? [o.sql] : Array.isArray(o.sql) ? o.sql : undefined;
66
+ if (!sql || sql.length === 0 || !sql.every((x) => typeof x === "string" && x.trim() !== ""))
67
+ problems.push(`"sql" is the SQL of one batch: a statement, or a list of them`);
68
+ const byKey = o.key !== undefined || o.batchSize !== undefined;
69
+ if (byKey && o.batches !== undefined)
70
+ problems.push(`give "key" and "batchSize", or "batches", not both`);
71
+ else if (byKey) {
72
+ if (!isString(o.key))
73
+ problems.push(`"key" is an integer column of the table, the batches are ranges of it`);
74
+ if (!isPositiveInt(o.batchSize))
75
+ problems.push(`"batchSize" is how wide each range of the key is, a positive integer`);
76
+ }
77
+ else if (o.batches !== undefined) {
78
+ if (!Array.isArray(o.batches) || o.batches.length === 0 || !o.batches.every((b) => typeof b === "string" || (typeof b === "number" && Number.isFinite(b)))) {
79
+ problems.push(`"batches" lists the batches, strings or numbers, for example ["202601", "202602"]`);
80
+ }
81
+ else if (new Set(o.batches.map(String)).size !== o.batches.length)
82
+ problems.push(`"batches" lists a batch twice`);
83
+ }
84
+ else
85
+ problems.push(`give "key" and "batchSize" (ranges of an integer key), or "batches" (a list)`);
86
+ if (o.settings !== undefined && !(isRecord(o.settings) && Object.values(o.settings).every((v) => typeof v === "string" || typeof v === "number")))
87
+ problems.push(`"settings" maps a setting's name to its value`);
88
+ if (sql && problems.length === 0) {
89
+ const want = formPlaceholders(o);
90
+ const text = sql.join("\n");
91
+ if (!want.some((p) => text.includes(p)))
92
+ problems.push(`"sql" uses none of ${want.join(" and ")}, so every batch would run the same statement`);
93
+ }
94
+ return problems;
95
+ }
96
+ /** The step's options as a form, when they are one (no `file`). */
97
+ export function asForm(options) {
98
+ if (!isRecord(options) || "file" in options)
99
+ return undefined;
100
+ if (formProblems(options).length > 0)
101
+ return undefined;
102
+ const o = options;
103
+ return {
104
+ table: o.table,
105
+ ...(o.key !== undefined ? { key: o.key, batchSize: o.batchSize } : { batches: o.batches }),
106
+ sql: o.sql,
107
+ ...(o.settings ? { settings: Object.fromEntries(Object.entries(o.settings).map(([k, v]) => [k, String(v)])) } : {}),
108
+ };
109
+ }
110
+ /** One line saying how a form batches: `shop.orders by id, 10000 a batch` or `shop.orders, 3 batches`. */
111
+ export function describeForm(form) {
112
+ return form.key !== undefined ? `${form.table} by ${form.key}, ${String(form.batchSize)} a batch` : `${form.table}, ${String(form.batches?.length ?? 0)} batch${form.batches?.length === 1 ? "" : "es"} (${(form.batches ?? []).join(", ")})`;
113
+ }
41
114
  /** How `yodel apply` treats one step. */
42
115
  export function planStep(step) {
43
116
  if (step.kind === "statement")
@@ -46,6 +119,10 @@ export function planStep(step) {
46
119
  return { run: "refused", reason: `a manual step for ${step.object} (${step.name}): no statement and no Op makes it; ${step.detail}` };
47
120
  const backfill = asBackfill(step);
48
121
  if (backfill) {
122
+ if (isRecord(backfill.options) && !("file" in backfill.options)) {
123
+ const form = asForm(backfill.options);
124
+ return form ? { run: "backfill", form } : { run: "refused", reason: `a backfill step whose form is not one yodel runs: ${formProblems(backfill.options).join("; ")}` };
125
+ }
49
126
  const file = backfillFile(backfill.options);
50
127
  return file ? { run: "backfill", file } : { run: "refused", reason: `a backfill step whose options.file is not a file in the migration's directory (${JSON.stringify(backfill.options)})` };
51
128
  }
@@ -65,20 +142,15 @@ export function planStep(step) {
65
142
  if (dw.mode !== "materialized-view" || typeof dw.cutoverColumn !== "string") {
66
143
  return { run: "refused", reason: `${REBUILD_OP} for ${step.object} (${step.name}): dualWrite ${JSON.stringify(dw)} is not one yodel apply runs` };
67
144
  }
68
- return { run: "rebuild", options: { name: o.name, table: o.table, dualWrite: dw } };
145
+ const retain = optional(o, "retain", isString);
146
+ if (retain === null)
147
+ return { run: "refused", reason: `${REBUILD_OP} for ${step.object} (${step.name}): options.retain is ${JSON.stringify(o.retain)}, which is not a duration` };
148
+ return { run: "rebuild", options: { name: o.name, table: o.table, dualWrite: dw, ...(retain ? { retain } : {}) } };
69
149
  }
70
150
  if (step.op === PG_MIGRATION_OP)
71
151
  return planPgMigration(step);
72
152
  return { run: "refused", reason: `${step.op} for ${step.object} (${step.name}), not SQL: yodel apply does not run that Op` };
73
153
  }
74
- const optional = (o, key, ok) => {
75
- const v = o[key];
76
- if (v === undefined)
77
- return undefined;
78
- return ok(v) ? v : null;
79
- };
80
- const isString = (v) => typeof v === "string" && v !== "";
81
- const isPositiveInt = (v) => typeof v === "number" && Number.isInteger(v) && v > 0;
82
154
  const isLag = (v) => v === false || (isRecord(v) && Object.values(v).every((x) => typeof x === "string"));
83
155
  function planPgMigration(step) {
84
156
  const o = step.options;
@@ -117,8 +189,10 @@ export function describeStep(step) {
117
189
  if (step.kind === "manual")
118
190
  return `manual step for ${step.object} (${step.name})`;
119
191
  const backfill = asBackfill(step);
120
- if (backfill)
121
- return `backfill ${backfill.options.file}`;
192
+ if (backfill) {
193
+ const form = asForm(backfill.options);
194
+ return form ? `backfill of ${describeForm(form)}` : `backfill ${"file" in backfill.options ? backfill.options.file : "(a form yodel does not run)"}`;
195
+ }
122
196
  return `${step.op} for ${step.object} (${step.name})`;
123
197
  }
124
198
  /**
@@ -133,7 +207,7 @@ export function stepSha(step, files) {
133
207
  return `sha256:${hash.update(step.sql, "utf8").digest("hex")}`;
134
208
  hash.update(JSON.stringify(sortKeys(step)), "utf8");
135
209
  const backfill = asBackfill(step);
136
- if (backfill) {
210
+ if (backfill && "file" in backfill.options) {
137
211
  const file = backfill.options.file;
138
212
  const text = files?.extra?.[file];
139
213
  hash.update(`\n${file} ${text === undefined ? "missing" : String(Buffer.byteLength(normalizeLineEndings(text), "utf8"))}\n${normalizeLineEndings(text ?? "")}`, "utf8");
@@ -1 +1 @@
1
- {"version":3,"file":"kinds.js","sourceRoot":"","sources":["../../src/steps/kinds.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"kinds.js","sourceRoot":"","sources":["../../src/steps/kinds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAuB,MAAM,2BAA2B,CAAC;AAEhG,mCAAmC;AACnC,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;AACtC,8GAA8G;AAC9G,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;AAC3C,MAAM,CAAC,MAAM,UAAU,GAAG,qBAAqB,CAAC;AAChD,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAuErD,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAgC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACxH,MAAM,QAAQ,GAAG,CAAI,CAA0B,EAAE,GAAW,EAAE,EAA0B,EAAwB,EAAE;IAChH,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACjB,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1B,CAAC,CAAC;AACF,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;AAChF,MAAM,aAAa,GAAG,CAAC,CAAU,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEzG,mDAAmD;AACnD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAkC,EAA4B,EAAE,CACzF,IAAI,CAAC,IAAI,KAAK,IAAI,IAAK,IAAI,CAAC,EAAa,KAAK,WAAW,CAAC,CAAC,CAAE,IAAgC,CAAC,CAAC,CAAC,SAAS,CAAC;AAE5G,uGAAuG;AACvG,SAAS,YAAY,CAAC,OAAgB;IACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1D,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAC9D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACzH,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kGAAkG;AAClG,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAA+B,EAAY,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AAE3I,uDAAuD;AACvD,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,CAAC,8BAA8B,CAAC,CAAC;IAChE,MAAM,CAAC,GAAG,OAAO,CAAC;IAClB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;IACnF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,mCAAmC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;IAC/G,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3F,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;IAC5K,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC;IAC/D,IAAI,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;SACrG,IAAI,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;QAC7G,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;IACzH,CAAC;SAAM,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3J,QAAQ,CAAC,IAAI,CAAC,mFAAmF,CAAC,CAAC;QACrG,CAAC;aAAM,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM;YAAE,QAAQ,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IACtH,CAAC;;QAAM,QAAQ,CAAC,IAAI,CAAC,8EAA8E,CAAC,CAAC;IACrG,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;IAClN,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,sBAAsB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC;IAClJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,MAAM,CAAC,OAAgB;IACrC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,IAAI,OAAO;QAAE,OAAO,SAAS,CAAC;IAC9D,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IACvD,MAAM,CAAC,GAAG,OAAkC,CAAC;IAC7C,OAAO;QACL,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,SAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAiC,EAAE,CAAC;QAC9H,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,QAAmC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/I,CAAC;AACJ,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,YAAY,CAAC,IAAkB;IAC7C,OAAO,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,GAAG,KAAK,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,OAAO,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAChP,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,QAAQ,CAAC,IAAkC;IACzD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;IAC3D,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,qBAAqB,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,uCAAuC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;IAClK,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACtC,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,qDAAqD,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACzK,CAAC;QACD,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,kFAAkF,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;IAC9L,CAAC;IACD,IAAI,IAAI,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QACvB,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3D,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;YACrE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,UAAU,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,iDAAiD,EAAE,CAAC;QACrI,CAAC;QACD,IAAI,EAAE,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACtB,OAAO;gBACL,GAAG,EAAE,SAAS;gBACd,MAAM,EACJ,GAAG,UAAU,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,yDAAyD,CAAC,CAAC,KAAK,wBAAwB;oBACtI,sJAAsJ;aACzJ,CAAC;QACJ,CAAC;QACD,IAAI,EAAE,CAAC,IAAI,KAAK,mBAAmB,IAAI,OAAO,EAAE,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;YAC5E,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,UAAU,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,gBAAgB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,8BAA8B,EAAE,CAAC;QACpJ,CAAC;QACD,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/C,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,UAAU,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,wBAAwB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,2BAA2B,EAAE,CAAC;QAClL,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,EAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;IAClI,CAAC;IACD,IAAI,IAAI,CAAC,EAAE,KAAK,eAAe;QAAE,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;IAC9D,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,8CAA8C,EAAE,CAAC;AAC/H,CAAC;AAED,MAAM,KAAK,GAAG,CAAC,CAAU,EAA6C,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;AAE9J,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;IACvB,MAAM,GAAG,GAAG,CAAC,IAAY,EAAY,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,eAAe,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC;IACtI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;QAAE,OAAO,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC7H,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC;IAClE,MAAM,kBAAkB,GAAG,QAAQ,CAAC,CAAC,EAAE,oBAAoB,EAAE,aAAa,CAAC,CAAC;IAC5E,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAC5D,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC;QACrH,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO,GAAG,CAAC,WAAW,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC;IACnG,CAAC;IACD,OAAO;QACL,GAAG,EAAE,aAAa;QAClB,OAAO,EAAE;YACP,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3B,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7B,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,GAAG,CAAC,cAAc,KAAK,SAAS,IAAI,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvF;KACF,CAAC;AACJ,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,YAAY,CAAC,IAAkC;IAC7D,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;IACjF,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,mBAAmB,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,GAAG,CAAC;IACnF,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,CAAC,CAAC,eAAe,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,MAAM,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,6BAA6B,EAAE,CAAC;IACvJ,CAAC;IACD,OAAO,GAAG,IAAI,CAAC,EAAE,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,GAAG,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,IAAkC,EAAE,KAAqC;IAC/F,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,UAAU,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IAC9F,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,QAAQ,IAAI,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;QACnC,MAAM,IAAI,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,oBAAoB,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAC1K,CAAC;IACD,OAAO,UAAU,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACxC,CAAC"}
@@ -15,40 +15,51 @@
15
15
  *
16
16
  * - The declaration is the migration's recorded schema (`migration.json`'s
17
17
  * `schema`), written to a temporary build file, not a fresh `chant build`.
18
- * - Its two gates (before the switch, before the contract) are left out. The
19
- * approval is the migration's: the step and its options are in the
20
- * migration's checksum, so in the plan digest the migrations Op's gate
21
- * approved. The verification still runs before the switch, and a
18
+ * - It is built with `gates: "outer"`: the approval is the migration's (the
19
+ * step and its options are in the migration's checksum, so in the plan
20
+ * digest the migrations Op's gate approved), so the Op has neither of its
21
+ * gates (before the switch, before the contract) and no Contract phase of
22
+ * its own. The verification still runs before the switch, and a
22
23
  * difference (a row whose new column is not the expression over the old,
23
24
  * a NULL where NOT NULL is declared) fails the step with nothing switched.
24
- * - The old column's retention is the step's `options.retain` when it sets
25
- * one, else none (`0s`): the contract drops the old column (and a rename's
26
- * trigger) in the same run, right after the switch, as the migration's
27
- * recorded schema says it is gone. A step that sets `retain` keeps the old
28
- * column that long; the step succeeds with it kept, its note says until
29
- * when, and dropping it after the date is `chant run` of the Op's
30
- * declaration (in `migration.json`), whose contract is convergent.
31
- * - Its onFailure (which drops what the expand added) is left out, so a step
32
- * that failed or was stopped resumes on the next `yodel apply`. Every
33
- * phase of the Op re-reads the server and does what is left of it: the
34
- * expand finds the new column there and adds nothing, the dual write finds
35
- * its trigger, the backfill skips every batch whose receipt is in
36
- * `<schema>.__chant_receipts` (each receipt commits with its batch, so a
37
- * batch is never filled twice), the carry over builds only the indexes and
38
- * constraints not yet built (an INVALID one it left is built again), the
39
- * verification runs again over every row, and a switch that already ran is
40
- * not run again. To start over instead, drop the new column, its trigger
41
- * and function (chant's working objects, named in their comments).
25
+ * - After the Retain phase the step runs the lexicon's contract activity
26
+ * (`postgresMigrationContract`, the Op's own Contract step, with the same
27
+ * arguments), under the same approval. It drops the old column (and a
28
+ * rename's trigger) only once its retention date has passed. The
29
+ * retention is the step's `options.retain` when it sets one, else none
30
+ * (`0s`): the contract drops the old column in the same run, right after
31
+ * the switch, as the migration's recorded schema says it is gone. A step
32
+ * that sets `retain` keeps the old column that long; the step succeeds
33
+ * with it kept, its note says until when, and dropping it after the date
34
+ * is `chant run` of the Op's declaration (in `migration.json`), whose
35
+ * contract is convergent.
36
+ * - It is built with `onFailure: "keep"`, so a step that failed or was
37
+ * stopped keeps what the expand added and resumes on the next `yodel
38
+ * apply`. Every phase of the Op re-reads the server and does what is left
39
+ * of it: the expand finds the new column there and adds nothing, the dual
40
+ * write finds its trigger, the backfill skips every batch whose receipt
41
+ * is in `<schema>.__chant_receipts` (each receipt commits with its batch,
42
+ * so a batch is never filled twice), the carry over builds only the
43
+ * indexes and constraints not yet built (an INVALID one it left is built
44
+ * again), the verification runs again over every row, and a switch that
45
+ * already ran is not run again. To start over instead, drop the new
46
+ * column, its trigger and function (chant's working objects, named in
47
+ * their comments; a refusal says so).
42
48
  */
43
- import type { OpConfig, PhaseDefinition } from "@intentius/chant/op/types";
49
+ import type { OpConfig } from "@intentius/chant/op/types";
44
50
  import type { ActivityFn } from "@intentius/chant/op/activity-registry";
45
51
  import type { StepRecord } from "@intentius/chant/op/local-executor";
46
52
  import type { PgMigrationOptions } from "./kinds.js";
53
+ import type { ProjectConfig } from "../project.js";
47
54
  import { type RunOpOptions } from "./run.js";
48
55
  /** The retention a step runs with when its options set none: the contract runs in the same apply. */
49
56
  export declare const STEP_RETAIN = "0s";
50
- /** `PostgresMigrationOp`'s phases as a step runs them: no gates, no onFailure. */
51
- export declare function pgStepPhases(config: OpConfig): PhaseDefinition[];
57
+ /**
58
+ * The Op's Contract step for a config built with `gates: "outer"`: the
59
+ * lexicon's contract activity with the Retain step's arguments. It drops the
60
+ * old column only once its retention date has passed.
61
+ */
62
+ export declare function contractPhase(config: OpConfig): OpConfig["phases"][number];
52
63
  /** The Op a step runs. `buildPath` is the recorded schema's file; `projectDir` holds chant.config.ts. */
53
64
  export declare function pgMigrationOpConfig(options: PgMigrationOptions, ctx: {
54
65
  environment: string;
@@ -87,6 +98,8 @@ export interface RunPgMigrationOptions extends Omit<RunOpOptions, "activities" |
87
98
  /** Activities to use in place of the lexicon's, for a test. */
88
99
  activities?: Record<string, ActivityFn>;
89
100
  log?: (line: string) => void;
101
+ /** The chant config the activities bind with (a tenant's, #56). Default: they load chant.config.ts. */
102
+ config?: ProjectConfig | undefined;
90
103
  }
91
104
  /** Runs a `PostgresMigrationOp` step to the end. The summary fills in as the activities return, so a failure still says how far it got. */
92
105
  export declare function runPgMigration(options: PgMigrationOptions, run: RunPgMigrationOptions, summary?: PgMigrationSummary): Promise<{
@@ -15,30 +15,36 @@
15
15
  *
16
16
  * - The declaration is the migration's recorded schema (`migration.json`'s
17
17
  * `schema`), written to a temporary build file, not a fresh `chant build`.
18
- * - Its two gates (before the switch, before the contract) are left out. The
19
- * approval is the migration's: the step and its options are in the
20
- * migration's checksum, so in the plan digest the migrations Op's gate
21
- * approved. The verification still runs before the switch, and a
18
+ * - It is built with `gates: "outer"`: the approval is the migration's (the
19
+ * step and its options are in the migration's checksum, so in the plan
20
+ * digest the migrations Op's gate approved), so the Op has neither of its
21
+ * gates (before the switch, before the contract) and no Contract phase of
22
+ * its own. The verification still runs before the switch, and a
22
23
  * difference (a row whose new column is not the expression over the old,
23
24
  * a NULL where NOT NULL is declared) fails the step with nothing switched.
24
- * - The old column's retention is the step's `options.retain` when it sets
25
- * one, else none (`0s`): the contract drops the old column (and a rename's
26
- * trigger) in the same run, right after the switch, as the migration's
27
- * recorded schema says it is gone. A step that sets `retain` keeps the old
28
- * column that long; the step succeeds with it kept, its note says until
29
- * when, and dropping it after the date is `chant run` of the Op's
30
- * declaration (in `migration.json`), whose contract is convergent.
31
- * - Its onFailure (which drops what the expand added) is left out, so a step
32
- * that failed or was stopped resumes on the next `yodel apply`. Every
33
- * phase of the Op re-reads the server and does what is left of it: the
34
- * expand finds the new column there and adds nothing, the dual write finds
35
- * its trigger, the backfill skips every batch whose receipt is in
36
- * `<schema>.__chant_receipts` (each receipt commits with its batch, so a
37
- * batch is never filled twice), the carry over builds only the indexes and
38
- * constraints not yet built (an INVALID one it left is built again), the
39
- * verification runs again over every row, and a switch that already ran is
40
- * not run again. To start over instead, drop the new column, its trigger
41
- * and function (chant's working objects, named in their comments).
25
+ * - After the Retain phase the step runs the lexicon's contract activity
26
+ * (`postgresMigrationContract`, the Op's own Contract step, with the same
27
+ * arguments), under the same approval. It drops the old column (and a
28
+ * rename's trigger) only once its retention date has passed. The
29
+ * retention is the step's `options.retain` when it sets one, else none
30
+ * (`0s`): the contract drops the old column in the same run, right after
31
+ * the switch, as the migration's recorded schema says it is gone. A step
32
+ * that sets `retain` keeps the old column that long; the step succeeds
33
+ * with it kept, its note says until when, and dropping it after the date
34
+ * is `chant run` of the Op's declaration (in `migration.json`), whose
35
+ * contract is convergent.
36
+ * - It is built with `onFailure: "keep"`, so a step that failed or was
37
+ * stopped keeps what the expand added and resumes on the next `yodel
38
+ * apply`. Every phase of the Op re-reads the server and does what is left
39
+ * of it: the expand finds the new column there and adds nothing, the dual
40
+ * write finds its trigger, the backfill skips every batch whose receipt
41
+ * is in `<schema>.__chant_receipts` (each receipt commits with its batch,
42
+ * so a batch is never filled twice), the carry over builds only the
43
+ * indexes and constraints not yet built (an INVALID one it left is built
44
+ * again), the verification runs again over every row, and a switch that
45
+ * already ran is not run again. To start over instead, drop the new
46
+ * column, its trigger and function (chant's working objects, named in
47
+ * their comments; a refusal says so).
42
48
  */
43
49
  import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
44
50
  import { tmpdir } from "node:os";
@@ -46,9 +52,16 @@ import { join } from "node:path";
46
52
  import { runOp, StepOpFailed } from "./run.js";
47
53
  /** The retention a step runs with when its options set none: the contract runs in the same apply. */
48
54
  export const STEP_RETAIN = "0s";
49
- /** `PostgresMigrationOp`'s phases as a step runs them: no gates, no onFailure. */
50
- export function pgStepPhases(config) {
51
- return config.phases.map((p) => ({ ...p, steps: p.steps.filter((s) => s.kind !== "gate") })).filter((p) => p.steps.length > 0);
55
+ /**
56
+ * The Op's Contract step for a config built with `gates: "outer"`: the
57
+ * lexicon's contract activity with the Retain step's arguments. It drops the
58
+ * old column only once its retention date has passed.
59
+ */
60
+ export function contractPhase(config) {
61
+ const retain = config.phases.flatMap((p) => p.steps).find((s) => s.kind === "activity" && s.fn === "postgresMigrationRetain");
62
+ if (!retain)
63
+ throw new Error(`PostgresMigrationOp "${config.name}" has no Retain step`);
64
+ return { name: "Contract", steps: [{ kind: "activity", fn: "postgresMigrationContract", ...(retain.args ? { args: retain.args } : {}) }] };
52
65
  }
53
66
  /** The Op a step runs. `buildPath` is the recorded schema's file; `projectDir` holds chant.config.ts. */
54
67
  export async function pgMigrationOpConfig(options, ctx) {
@@ -68,11 +81,11 @@ export async function pgMigrationOpConfig(options, ctx) {
68
81
  build: false,
69
82
  output: ctx.buildPath,
70
83
  path: ctx.projectDir,
84
+ gates: "outer",
85
+ onFailure: "keep",
71
86
  });
72
- const full = op.props;
73
- const rest = { ...full, phases: pgStepPhases(full) };
74
- delete rest.onFailure;
75
- return rest;
87
+ const config = op.props;
88
+ return { ...config, phases: [...config.phases, contractPhase(config)] };
76
89
  }
77
90
  /** The migration activities whose results the history's summary keeps. */
78
91
  const SUMMARIZED = ["postgresMigrationPlan", "postgresMigrationBackfill", "postgresMigrationCarry", "postgresMigrationVerify", "postgresMigrationSwitch", "postgresMigrationContract"];
@@ -118,13 +131,17 @@ export async function runPgMigration(options, run, summary = { op: "PostgresMigr
118
131
  const config = await pgMigrationOpConfig(options, { environment: run.environment, projectDir: run.projectDir, buildPath, lockTimeoutMs: run.lockTimeoutMs });
119
132
  const lexicon = run.activities ?? (await import("@intentius/chant-lexicon-sql/op/activities"));
120
133
  const wrapped = {};
121
- for (const fn of SUMMARIZED) {
134
+ // A migration activity takes its config as a third argument (chant's PostgresMigrationDeps).
135
+ const deps = run.config ? { config: run.config } : undefined;
136
+ const summarized = SUMMARIZED;
137
+ for (const fn of Object.keys(lexicon).filter((f) => f.startsWith("postgresMigration") && (deps !== undefined || summarized.includes(f)))) {
122
138
  const inner = lexicon[fn];
123
139
  if (!inner)
124
140
  continue;
125
141
  wrapped[fn] = async (args, signal) => {
126
- const result = await inner(args, signal);
127
- summarizePg(summary, fn, result);
142
+ const result = await (deps ? inner(args, signal, deps) : inner(args, signal));
143
+ if (summarized.includes(fn))
144
+ summarizePg(summary, fn, result);
128
145
  return result;
129
146
  };
130
147
  }