@intentius/sql-yodeler 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +110 -2
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +14 -0
- package/dist/bin.js.map +1 -0
- package/dist/chant/apply.d.ts +51 -0
- package/dist/chant/apply.js +104 -0
- package/dist/chant/apply.js.map +1 -0
- package/dist/chant/build.d.ts +34 -0
- package/dist/chant/build.js +48 -0
- package/dist/chant/build.js.map +1 -0
- package/dist/chant/drift.d.ts +44 -0
- package/dist/chant/drift.js +91 -0
- package/dist/chant/drift.js.map +1 -0
- package/dist/chant/plan.d.ts +45 -0
- package/dist/chant/plan.js +61 -0
- package/dist/chant/plan.js.map +1 -0
- package/dist/chant/process.d.ts +41 -0
- package/dist/chant/process.js +87 -0
- package/dist/chant/process.js.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +59 -0
- package/dist/cli.js.map +1 -0
- package/dist/command.d.ts +17 -0
- package/dist/command.js +13 -0
- package/dist/command.js.map +1 -0
- package/dist/commands/apply.d.ts +3 -0
- package/dist/commands/apply.js +306 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/drift.d.ts +3 -0
- package/dist/commands/drift.js +38 -0
- package/dist/commands/drift.js.map +1 -0
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.js +22 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.js +135 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/lint.d.ts +3 -0
- package/dist/commands/lint.js +193 -0
- package/dist/commands/lint.js.map +1 -0
- package/dist/commands/new.d.ts +3 -0
- package/dist/commands/new.js +168 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/plan.d.ts +3 -0
- package/dist/commands/plan.js +171 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/rebase.d.ts +3 -0
- package/dist/commands/rebase.js +167 -0
- package/dist/commands/rebase.js.map +1 -0
- package/dist/commands/repair.d.ts +3 -0
- package/dist/commands/repair.js +117 -0
- package/dist/commands/repair.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.js +54 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config/define.d.ts +50 -0
- package/dist/config/define.js +20 -0
- package/dist/config/define.js.map +1 -0
- package/dist/config/index.d.ts +11 -0
- package/dist/config/index.js +12 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/load.d.ts +17 -0
- package/dist/config/load.js +102 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/settings.d.ts +40 -0
- package/dist/config/settings.js +88 -0
- package/dist/config/settings.js.map +1 -0
- package/dist/env-args.d.ts +18 -0
- package/dist/env-args.js +62 -0
- package/dist/env-args.js.map +1 -0
- package/dist/history/client.d.ts +17 -0
- package/dist/history/client.js +19 -0
- package/dist/history/client.js.map +1 -0
- package/dist/history/ddl.d.ts +58 -0
- package/dist/history/ddl.js +100 -0
- package/dist/history/ddl.js.map +1 -0
- package/dist/history/index.d.ts +25 -0
- package/dist/history/index.js +26 -0
- package/dist/history/index.js.map +1 -0
- package/dist/history/lock.d.ts +100 -0
- package/dist/history/lock.js +224 -0
- package/dist/history/lock.js.map +1 -0
- package/dist/history/postgres/ddl.d.ts +22 -0
- package/dist/history/postgres/ddl.js +47 -0
- package/dist/history/postgres/ddl.js.map +1 -0
- package/dist/history/postgres/index.d.ts +12 -0
- package/dist/history/postgres/index.js +13 -0
- package/dist/history/postgres/index.js.map +1 -0
- package/dist/history/postgres/lock.d.ts +48 -0
- package/dist/history/postgres/lock.js +95 -0
- package/dist/history/postgres/lock.js.map +1 -0
- package/dist/history/postgres/store.d.ts +39 -0
- package/dist/history/postgres/store.js +68 -0
- package/dist/history/postgres/store.js.map +1 -0
- package/dist/history/rows.d.ts +96 -0
- package/dist/history/rows.js +73 -0
- package/dist/history/rows.js.map +1 -0
- package/dist/history/store.d.ts +72 -0
- package/dist/history/store.js +134 -0
- package/dist/history/store.js.map +1 -0
- package/dist/history/topology.d.ts +41 -0
- package/dist/history/topology.js +54 -0
- package/dist/history/topology.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/init/adopt.d.ts +70 -0
- package/dist/init/adopt.js +138 -0
- package/dist/init/adopt.js.map +1 -0
- package/dist/init/baseline.d.ts +61 -0
- package/dist/init/baseline.js +88 -0
- package/dist/init/baseline.js.map +1 -0
- package/dist/init/files.d.ts +23 -0
- package/dist/init/files.js +77 -0
- package/dist/init/files.js.map +1 -0
- package/dist/init/index.d.ts +16 -0
- package/dist/init/index.js +17 -0
- package/dist/init/index.js.map +1 -0
- package/dist/init/live.d.ts +28 -0
- package/dist/init/live.js +45 -0
- package/dist/init/live.js.map +1 -0
- package/dist/lint/check.d.ts +81 -0
- package/dist/lint/check.js +208 -0
- package/dist/lint/check.js.map +1 -0
- package/dist/lint/config.d.ts +21 -0
- package/dist/lint/config.js +43 -0
- package/dist/lint/config.js.map +1 -0
- package/dist/lint/index.d.ts +31 -0
- package/dist/lint/index.js +43 -0
- package/dist/lint/index.js.map +1 -0
- package/dist/lint/project-rules.d.ts +19 -0
- package/dist/lint/project-rules.js +32 -0
- package/dist/lint/project-rules.js.map +1 -0
- package/dist/lint/report.d.ts +7 -0
- package/dist/lint/report.js +48 -0
- package/dist/lint/report.js.map +1 -0
- package/dist/lint/rules.d.ts +53 -0
- package/dist/lint/rules.js +42 -0
- package/dist/lint/rules.js.map +1 -0
- package/dist/lint/silences.d.ts +49 -0
- package/dist/lint/silences.js +91 -0
- package/dist/lint/silences.js.map +1 -0
- package/dist/lint/statements.d.ts +38 -0
- package/dist/lint/statements.js +120 -0
- package/dist/lint/statements.js.map +1 -0
- package/dist/migrations/checksum.d.ts +56 -0
- package/dist/migrations/checksum.js +72 -0
- package/dist/migrations/checksum.js.map +1 -0
- package/dist/migrations/create.d.ts +73 -0
- package/dist/migrations/create.js +119 -0
- package/dist/migrations/create.js.map +1 -0
- package/dist/migrations/directory.d.ts +119 -0
- package/dist/migrations/directory.js +225 -0
- package/dist/migrations/directory.js.map +1 -0
- package/dist/migrations/document.d.ts +83 -0
- package/dist/migrations/document.js +82 -0
- package/dist/migrations/document.js.map +1 -0
- package/dist/migrations/index.d.ts +20 -0
- package/dist/migrations/index.js +21 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/pr/comment.d.ts +32 -0
- package/dist/pr/comment.js +99 -0
- package/dist/pr/comment.js.map +1 -0
- package/dist/pr/forge.d.ts +50 -0
- package/dist/pr/forge.js +105 -0
- package/dist/pr/forge.js.map +1 -0
- package/dist/pr/model.d.ts +91 -0
- package/dist/pr/model.js +113 -0
- package/dist/pr/model.js.map +1 -0
- package/dist/pr/render.d.ts +27 -0
- package/dist/pr/render.js +246 -0
- package/dist/pr/render.js.map +1 -0
- package/dist/project.d.ts +62 -0
- package/dist/project.js +92 -0
- package/dist/project.js.map +1 -0
- package/dist/rebase/index.d.ts +121 -0
- package/dist/rebase/index.js +390 -0
- package/dist/rebase/index.js.map +1 -0
- package/dist/rebase/repair.d.ts +41 -0
- package/dist/rebase/repair.js +68 -0
- package/dist/rebase/repair.js.map +1 -0
- package/dist/replay/clickhouse.d.ts +33 -0
- package/dist/replay/clickhouse.js +106 -0
- package/dist/replay/clickhouse.js.map +1 -0
- package/dist/replay/index.d.ts +36 -0
- package/dist/replay/index.js +54 -0
- package/dist/replay/index.js.map +1 -0
- package/dist/replay/postgres.d.ts +31 -0
- package/dist/replay/postgres.js +140 -0
- package/dist/replay/postgres.js.map +1 -0
- package/dist/replay/replay.d.ts +114 -0
- package/dist/replay/replay.js +98 -0
- package/dist/replay/replay.js.map +1 -0
- package/dist/replay/report.d.ts +18 -0
- package/dist/replay/report.js +72 -0
- package/dist/replay/report.js.map +1 -0
- package/dist/steps/backfill.d.ts +128 -0
- package/dist/steps/backfill.js +307 -0
- package/dist/steps/backfill.js.map +1 -0
- package/dist/steps/index.d.ts +52 -0
- package/dist/steps/index.js +52 -0
- package/dist/steps/index.js.map +1 -0
- package/dist/steps/kinds.d.ts +101 -0
- package/dist/steps/kinds.js +143 -0
- package/dist/steps/kinds.js.map +1 -0
- package/dist/steps/postgres-migration.d.ts +95 -0
- package/dist/steps/postgres-migration.js +149 -0
- package/dist/steps/postgres-migration.js.map +1 -0
- package/dist/steps/rebuild.d.ts +97 -0
- package/dist/steps/rebuild.js +162 -0
- package/dist/steps/rebuild.js.map +1 -0
- package/dist/steps/run.d.ts +45 -0
- package/dist/steps/run.js +72 -0
- package/dist/steps/run.js.map +1 -0
- package/dist/topology/render.d.ts +17 -0
- package/dist/topology/render.js +17 -0
- package/dist/topology/render.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +11 -0
- package/dist/version.js.map +1 -0
- package/dist/versioned/approval.d.ts +35 -0
- package/dist/versioned/approval.js +53 -0
- package/dist/versioned/approval.js.map +1 -0
- package/dist/versioned/clickhouse.d.ts +24 -0
- package/dist/versioned/clickhouse.js +34 -0
- package/dist/versioned/clickhouse.js.map +1 -0
- package/dist/versioned/digest.d.ts +77 -0
- package/dist/versioned/digest.js +69 -0
- package/dist/versioned/digest.js.map +1 -0
- package/dist/versioned/driver.d.ts +41 -0
- package/dist/versioned/driver.js +13 -0
- package/dist/versioned/driver.js.map +1 -0
- package/dist/versioned/engine.d.ts +152 -0
- package/dist/versioned/engine.js +277 -0
- package/dist/versioned/engine.js.map +1 -0
- package/dist/versioned/explain.d.ts +123 -0
- package/dist/versioned/explain.js +289 -0
- package/dist/versioned/explain.js.map +1 -0
- package/dist/versioned/index.d.ts +37 -0
- package/dist/versioned/index.js +54 -0
- package/dist/versioned/index.js.map +1 -0
- package/dist/versioned/op.d.ts +62 -0
- package/dist/versioned/op.js +153 -0
- package/dist/versioned/op.js.map +1 -0
- package/dist/versioned/postgres/catalog.d.ts +33 -0
- package/dist/versioned/postgres/catalog.js +34 -0
- package/dist/versioned/postgres/catalog.js.map +1 -0
- package/dist/versioned/postgres/driver.d.ts +69 -0
- package/dist/versioned/postgres/driver.js +113 -0
- package/dist/versioned/postgres/driver.js.map +1 -0
- package/dist/versioned/postgres/executor.d.ts +104 -0
- package/dist/versioned/postgres/executor.js +172 -0
- package/dist/versioned/postgres/executor.js.map +1 -0
- package/dist/versioned/postgres/index.d.ts +11 -0
- package/dist/versioned/postgres/index.js +12 -0
- package/dist/versioned/postgres/index.js.map +1 -0
- package/dist/versioned/report.d.ts +22 -0
- package/dist/versioned/report.js +81 -0
- package/dist/versioned/report.js.map +1 -0
- package/dist/versioned/state.d.ts +108 -0
- package/dist/versioned/state.js +153 -0
- package/dist/versioned/state.js.map +1 -0
- package/package.json +51 -4
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Op steps inside a migration (#12): what `yodel apply` runs besides SQL.
|
|
3
|
+
*
|
|
4
|
+
* planStep(step) statement, rebuild, backfill, or refused (with why)
|
|
5
|
+
* stepSha(step, files) the hash a step's history rows record
|
|
6
|
+
* runRebuild(...) a ClickHouseRebuildOp step (./rebuild.ts)
|
|
7
|
+
* runBackfill(...) a backfill step, an Op of effect() batches (./backfill.ts)
|
|
8
|
+
* runPgMigration(...) a PostgresMigrationOp step (./postgres-migration.ts)
|
|
9
|
+
* defaultStepRunner what the versioned apply calls for an Op step
|
|
10
|
+
*/
|
|
11
|
+
import { YodelError } from "../project.js";
|
|
12
|
+
import { postgresServerReceipts, runBackfill, serverReceipts } from "./backfill.js";
|
|
13
|
+
import { rebuildChantConfig, runRebuild } from "./rebuild.js";
|
|
14
|
+
import { runPgMigration } from "./postgres-migration.js";
|
|
15
|
+
export * from "./kinds.js";
|
|
16
|
+
export * from "./run.js";
|
|
17
|
+
export * from "./rebuild.js";
|
|
18
|
+
export * from "./backfill.js";
|
|
19
|
+
export * from "./postgres-migration.js";
|
|
20
|
+
export const defaultStepRunner = async (ctx) => {
|
|
21
|
+
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 });
|
|
24
|
+
return { summary };
|
|
25
|
+
}
|
|
26
|
+
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 });
|
|
28
|
+
return { summary };
|
|
29
|
+
}
|
|
30
|
+
if (!ctx.port && !ctx.postgres)
|
|
31
|
+
throw new YodelError("a backfill step runs its SQL on the environment's server, and this environment has none");
|
|
32
|
+
const receipts = ctx.receipts ??
|
|
33
|
+
(ctx.postgres
|
|
34
|
+
? await postgresServerReceipts(ctx.postgres.client, ctx.postgres.receiptsSchema, ctx.environment)
|
|
35
|
+
: ctx.endpoint
|
|
36
|
+
? await serverReceipts(ctx.endpoint, ctx.environment)
|
|
37
|
+
: undefined);
|
|
38
|
+
if (!receipts)
|
|
39
|
+
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, {
|
|
41
|
+
environment: ctx.environment,
|
|
42
|
+
projectDir: ctx.projectDir,
|
|
43
|
+
migrationId: ctx.migration.id,
|
|
44
|
+
dir: ctx.migration.dir,
|
|
45
|
+
text: ctx.migration.files.extra?.[ctx.plan.file],
|
|
46
|
+
...(ctx.postgres ? { postgres: { client: ctx.postgres.client, timeouts: ctx.postgres.timeouts } } : { port: ctx.port }),
|
|
47
|
+
receipts,
|
|
48
|
+
log: ctx.log,
|
|
49
|
+
});
|
|
50
|
+
return { summary };
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/steps/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What each step of a migration is to `yodel apply`, and the hash its
|
|
3
|
+
* history rows record.
|
|
4
|
+
*
|
|
5
|
+
* A migration's `steps` (in `migration.json`) are chant's: a `statement`
|
|
6
|
+
* apply sends as SQL, an `op` step naming the Op that makes a change no
|
|
7
|
+
* statement makes, or a `manual` step a person acts on. Apply runs two kinds
|
|
8
|
+
* of Op step itself, inside the migration and under its lock and gate:
|
|
9
|
+
*
|
|
10
|
+
* - `ClickHouseRebuildOp`, the step `yodel new` writes for a ClickHouse sort
|
|
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`);
|
|
14
|
+
* - `PostgresMigrationOp`, the step `yodel new` writes for a Postgres column
|
|
15
|
+
* rename or type change across kinds (`./postgres-migration.ts`, #13).
|
|
16
|
+
*
|
|
17
|
+
* Everything else (a manual step, a rebuild in app mode) is refused before
|
|
18
|
+
* anything runs, with exit 2.
|
|
19
|
+
*/
|
|
20
|
+
import type { MigrationStep } from "@intentius/chant-lexicon-sql/migration-statements";
|
|
21
|
+
import { type MigrationFiles } from "../migrations/document.js";
|
|
22
|
+
/** The `op` of a backfill step. */
|
|
23
|
+
export declare const BACKFILL_OP = "backfill";
|
|
24
|
+
/** The module a backfill step runs, in the migration's directory, unless its `options.file` names another. */
|
|
25
|
+
export declare const BACKFILL_FILE = "backfill.ts";
|
|
26
|
+
export declare const REBUILD_OP = "ClickHouseRebuildOp";
|
|
27
|
+
export declare const PG_MIGRATION_OP = "PostgresMigrationOp";
|
|
28
|
+
type OpStep = Extract<MigrationStep, {
|
|
29
|
+
kind: "op";
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* A backfill step in `migration.json`. chant's `OpStep` shape, so every
|
|
33
|
+
* reader of steps sees an Op step:
|
|
34
|
+
*
|
|
35
|
+
* { "kind": "op", "object": "backfill", "type": "Yodel::Backfill", "name": "<migration name>",
|
|
36
|
+
* "op": "backfill", "importPath": "./backfill.ts", "options": { "file": "backfill.ts" },
|
|
37
|
+
* "declaration": "...", "changes": [], "detail": "..." }
|
|
38
|
+
*/
|
|
39
|
+
export interface BackfillStep extends Omit<OpStep, "op" | "options"> {
|
|
40
|
+
op: typeof BACKFILL_OP;
|
|
41
|
+
options: {
|
|
42
|
+
file: string;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export type DualWrite = {
|
|
46
|
+
mode: "materialized-view";
|
|
47
|
+
cutoverColumn: string;
|
|
48
|
+
cutoverDelay?: string;
|
|
49
|
+
} | {
|
|
50
|
+
mode: "app";
|
|
51
|
+
};
|
|
52
|
+
export interface RebuildOptions {
|
|
53
|
+
name: string;
|
|
54
|
+
table: string;
|
|
55
|
+
dualWrite: DualWrite;
|
|
56
|
+
}
|
|
57
|
+
/** A `PostgresMigrationOp` step's options: chant's `{ name, env, table, column }`, and what the author may add (`using`, `retain`, ...). */
|
|
58
|
+
export interface PgMigrationOptions {
|
|
59
|
+
name: string;
|
|
60
|
+
table: string;
|
|
61
|
+
column: string;
|
|
62
|
+
using?: string;
|
|
63
|
+
/** How long the old column is kept after the switch; default none, so the contract runs in the same apply. */
|
|
64
|
+
retain?: string;
|
|
65
|
+
batchSize?: number;
|
|
66
|
+
replicationLag?: {
|
|
67
|
+
max?: string;
|
|
68
|
+
wait?: string;
|
|
69
|
+
} | false;
|
|
70
|
+
lockTimeoutMs?: number;
|
|
71
|
+
statementTimeoutMs?: number;
|
|
72
|
+
}
|
|
73
|
+
export type StepPlan = {
|
|
74
|
+
run: "statement";
|
|
75
|
+
} | {
|
|
76
|
+
run: "rebuild";
|
|
77
|
+
options: RebuildOptions;
|
|
78
|
+
} | {
|
|
79
|
+
run: "pgMigration";
|
|
80
|
+
options: PgMigrationOptions;
|
|
81
|
+
} | {
|
|
82
|
+
run: "backfill";
|
|
83
|
+
file: string;
|
|
84
|
+
} | {
|
|
85
|
+
run: "refused";
|
|
86
|
+
reason: string;
|
|
87
|
+
};
|
|
88
|
+
/** The step as a backfill step, when it is one. */
|
|
89
|
+
export declare const asBackfill: (step: MigrationStep | BackfillStep) => BackfillStep | undefined;
|
|
90
|
+
/** How `yodel apply` treats one step. */
|
|
91
|
+
export declare function planStep(step: MigrationStep | BackfillStep): StepPlan;
|
|
92
|
+
/** One line naming a step, for logs and refusals. */
|
|
93
|
+
export declare function describeStep(step: MigrationStep | BackfillStep): string;
|
|
94
|
+
/**
|
|
95
|
+
* The hash a step's history rows record: for a statement, its SQL's (the
|
|
96
|
+
* history's `statementSha`); for an Op step, its canonical JSON and, for a
|
|
97
|
+
* backfill, the text of the module it runs. A step that ran and has since
|
|
98
|
+
* changed is how a part-way migration's edit is caught.
|
|
99
|
+
*/
|
|
100
|
+
export declare function stepSha(step: MigrationStep | BackfillStep, files?: Pick<MigrationFiles, "extra">): string;
|
|
101
|
+
export {};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What each step of a migration is to `yodel apply`, and the hash its
|
|
3
|
+
* history rows record.
|
|
4
|
+
*
|
|
5
|
+
* A migration's `steps` (in `migration.json`) are chant's: a `statement`
|
|
6
|
+
* apply sends as SQL, an `op` step naming the Op that makes a change no
|
|
7
|
+
* statement makes, or a `manual` step a person acts on. Apply runs two kinds
|
|
8
|
+
* of Op step itself, inside the migration and under its lock and gate:
|
|
9
|
+
*
|
|
10
|
+
* - `ClickHouseRebuildOp`, the step `yodel new` writes for a ClickHouse sort
|
|
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`);
|
|
14
|
+
* - `PostgresMigrationOp`, the step `yodel new` writes for a Postgres column
|
|
15
|
+
* rename or type change across kinds (`./postgres-migration.ts`, #13).
|
|
16
|
+
*
|
|
17
|
+
* Everything else (a manual step, a rebuild in app mode) is refused before
|
|
18
|
+
* anything runs, with exit 2.
|
|
19
|
+
*/
|
|
20
|
+
import { createHash } from "node:crypto";
|
|
21
|
+
import { normalizeLineEndings, sortKeys } from "../migrations/document.js";
|
|
22
|
+
/** The `op` of a backfill step. */
|
|
23
|
+
export const BACKFILL_OP = "backfill";
|
|
24
|
+
/** The module a backfill step runs, in the migration's directory, unless its `options.file` names another. */
|
|
25
|
+
export const BACKFILL_FILE = "backfill.ts";
|
|
26
|
+
export const REBUILD_OP = "ClickHouseRebuildOp";
|
|
27
|
+
export const PG_MIGRATION_OP = "PostgresMigrationOp";
|
|
28
|
+
const isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
29
|
+
/** The step as a backfill step, when it is one. */
|
|
30
|
+
export const asBackfill = (step) => step.kind === "op" && step.op === BACKFILL_OP ? step : undefined;
|
|
31
|
+
/** The file a backfill step names: relative to the migration's directory, `/`-separated, inside it. */
|
|
32
|
+
function backfillFile(options) {
|
|
33
|
+
const file = isRecord(options) ? options.file : undefined;
|
|
34
|
+
if (typeof file !== "string" || file === "")
|
|
35
|
+
return undefined;
|
|
36
|
+
const parts = file.split("/");
|
|
37
|
+
if (parts.some((p) => p === "" || p === "." || p === ".." || p.startsWith(".")) || file.includes("\\"))
|
|
38
|
+
return undefined;
|
|
39
|
+
return file;
|
|
40
|
+
}
|
|
41
|
+
/** How `yodel apply` treats one step. */
|
|
42
|
+
export function planStep(step) {
|
|
43
|
+
if (step.kind === "statement")
|
|
44
|
+
return { run: "statement" };
|
|
45
|
+
if (step.kind === "manual")
|
|
46
|
+
return { run: "refused", reason: `a manual step for ${step.object} (${step.name}): no statement and no Op makes it; ${step.detail}` };
|
|
47
|
+
const backfill = asBackfill(step);
|
|
48
|
+
if (backfill) {
|
|
49
|
+
const file = backfillFile(backfill.options);
|
|
50
|
+
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
|
+
}
|
|
52
|
+
if (step.op === REBUILD_OP) {
|
|
53
|
+
const o = step.options;
|
|
54
|
+
const dw = isRecord(o.dualWrite) ? o.dualWrite : undefined;
|
|
55
|
+
if (typeof o.name !== "string" || typeof o.table !== "string" || !dw) {
|
|
56
|
+
return { run: "refused", reason: `${REBUILD_OP} for ${step.object} (${step.name}) without its name, table and dualWrite options` };
|
|
57
|
+
}
|
|
58
|
+
if (dw.mode === "app") {
|
|
59
|
+
return {
|
|
60
|
+
run: "refused",
|
|
61
|
+
reason: `${REBUILD_OP} for ${step.object} (${step.name}) in app mode: the application has to stop writing to ${o.table} while it is rebuilt, ` +
|
|
62
|
+
`which needs the Op's own writes gate; yodel apply runs materialized-view mode only. Run the Op with chant run (migration.json holds its declaration)`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (dw.mode !== "materialized-view" || typeof dw.cutoverColumn !== "string") {
|
|
66
|
+
return { run: "refused", reason: `${REBUILD_OP} for ${step.object} (${step.name}): dualWrite ${JSON.stringify(dw)} is not one yodel apply runs` };
|
|
67
|
+
}
|
|
68
|
+
return { run: "rebuild", options: { name: o.name, table: o.table, dualWrite: dw } };
|
|
69
|
+
}
|
|
70
|
+
if (step.op === PG_MIGRATION_OP)
|
|
71
|
+
return planPgMigration(step);
|
|
72
|
+
return { run: "refused", reason: `${step.op} for ${step.object} (${step.name}), not SQL: yodel apply does not run that Op` };
|
|
73
|
+
}
|
|
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
|
+
const isLag = (v) => v === false || (isRecord(v) && Object.values(v).every((x) => typeof x === "string"));
|
|
83
|
+
function planPgMigration(step) {
|
|
84
|
+
const o = step.options;
|
|
85
|
+
const bad = (what) => ({ run: "refused", reason: `${PG_MIGRATION_OP} for ${step.object} (${step.name}): ${what}` });
|
|
86
|
+
if (!isString(o.name) || !isString(o.table) || !isString(o.column))
|
|
87
|
+
return bad("without its name, table and column options");
|
|
88
|
+
const using = optional(o, "using", isString);
|
|
89
|
+
const retain = optional(o, "retain", isString);
|
|
90
|
+
const batchSize = optional(o, "batchSize", isPositiveInt);
|
|
91
|
+
const lockTimeoutMs = optional(o, "lockTimeoutMs", isPositiveInt);
|
|
92
|
+
const statementTimeoutMs = optional(o, "statementTimeoutMs", isPositiveInt);
|
|
93
|
+
const replicationLag = optional(o, "replicationLag", isLag);
|
|
94
|
+
for (const [k, v] of Object.entries({ using, retain, batchSize, lockTimeoutMs, statementTimeoutMs, replicationLag })) {
|
|
95
|
+
if (v === null)
|
|
96
|
+
return bad(`options.${k} is ${JSON.stringify(o[k])}, which is not one it takes`);
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
run: "pgMigration",
|
|
100
|
+
options: {
|
|
101
|
+
name: o.name,
|
|
102
|
+
table: o.table,
|
|
103
|
+
column: o.column,
|
|
104
|
+
...(using ? { using } : {}),
|
|
105
|
+
...(retain ? { retain } : {}),
|
|
106
|
+
...(batchSize ? { batchSize } : {}),
|
|
107
|
+
...(lockTimeoutMs ? { lockTimeoutMs } : {}),
|
|
108
|
+
...(statementTimeoutMs ? { statementTimeoutMs } : {}),
|
|
109
|
+
...(replicationLag !== undefined && replicationLag !== null ? { replicationLag } : {}),
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/** One line naming a step, for logs and refusals. */
|
|
114
|
+
export function describeStep(step) {
|
|
115
|
+
if (step.kind === "statement")
|
|
116
|
+
return `${step.rule} ${step.class}, ${step.name}`;
|
|
117
|
+
if (step.kind === "manual")
|
|
118
|
+
return `manual step for ${step.object} (${step.name})`;
|
|
119
|
+
const backfill = asBackfill(step);
|
|
120
|
+
if (backfill)
|
|
121
|
+
return `backfill ${backfill.options.file}`;
|
|
122
|
+
return `${step.op} for ${step.object} (${step.name})`;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The hash a step's history rows record: for a statement, its SQL's (the
|
|
126
|
+
* history's `statementSha`); for an Op step, its canonical JSON and, for a
|
|
127
|
+
* backfill, the text of the module it runs. A step that ran and has since
|
|
128
|
+
* changed is how a part-way migration's edit is caught.
|
|
129
|
+
*/
|
|
130
|
+
export function stepSha(step, files) {
|
|
131
|
+
const hash = createHash("sha256");
|
|
132
|
+
if (step.kind === "statement")
|
|
133
|
+
return `sha256:${hash.update(step.sql, "utf8").digest("hex")}`;
|
|
134
|
+
hash.update(JSON.stringify(sortKeys(step)), "utf8");
|
|
135
|
+
const backfill = asBackfill(step);
|
|
136
|
+
if (backfill) {
|
|
137
|
+
const file = backfill.options.file;
|
|
138
|
+
const text = files?.extra?.[file];
|
|
139
|
+
hash.update(`\n${file} ${text === undefined ? "missing" : String(Buffer.byteLength(normalizeLineEndings(text), "utf8"))}\n${normalizeLineEndings(text ?? "")}`, "utf8");
|
|
140
|
+
}
|
|
141
|
+
return `sha256:${hash.digest("hex")}`;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=kinds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kinds.js","sourceRoot":"","sources":["../../src/steps/kinds.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `PostgresMigrationOp` step: a Postgres column rename (SQLPG205) or type
|
|
3
|
+
* change across kinds (SQLPG208), which `yodel new` writes as a step since
|
|
4
|
+
* Postgres cannot make it in place without breaking readers, run inside the
|
|
5
|
+
* migration as chant's expand-and-contract Op.
|
|
6
|
+
*
|
|
7
|
+
* The Op is chant's own (`PostgresMigrationOp` from the sql lexicon), built
|
|
8
|
+
* from the step's options with the apply's environment, and run by chant's
|
|
9
|
+
* local executor with the lexicon's activities, as `ClickHouseRebuildOp` is
|
|
10
|
+
* (`./rebuild.ts`):
|
|
11
|
+
*
|
|
12
|
+
* Plan, Expand, Dual write, Backfill, Carry over, Verify, Switch, Retain, Contract
|
|
13
|
+
*
|
|
14
|
+
* What differs from `chant run` of the Op:
|
|
15
|
+
*
|
|
16
|
+
* - The declaration is the migration's recorded schema (`migration.json`'s
|
|
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
|
|
22
|
+
* difference (a row whose new column is not the expression over the old,
|
|
23
|
+
* 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).
|
|
42
|
+
*/
|
|
43
|
+
import type { OpConfig, PhaseDefinition } from "@intentius/chant/op/types";
|
|
44
|
+
import type { ActivityFn } from "@intentius/chant/op/activity-registry";
|
|
45
|
+
import type { StepRecord } from "@intentius/chant/op/local-executor";
|
|
46
|
+
import type { PgMigrationOptions } from "./kinds.js";
|
|
47
|
+
import { type RunOpOptions } from "./run.js";
|
|
48
|
+
/** The retention a step runs with when its options set none: the contract runs in the same apply. */
|
|
49
|
+
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[];
|
|
52
|
+
/** The Op a step runs. `buildPath` is the recorded schema's file; `projectDir` holds chant.config.ts. */
|
|
53
|
+
export declare function pgMigrationOpConfig(options: PgMigrationOptions, ctx: {
|
|
54
|
+
environment: string;
|
|
55
|
+
projectDir: string;
|
|
56
|
+
buildPath: string;
|
|
57
|
+
lockTimeoutMs?: number | undefined;
|
|
58
|
+
}): Promise<OpConfig>;
|
|
59
|
+
export interface PgMigrationSummary {
|
|
60
|
+
op: "PostgresMigrationOp";
|
|
61
|
+
table: string;
|
|
62
|
+
column: string;
|
|
63
|
+
/** The Plan's state when the step began: `migrate`, or `switched` / `done` when an earlier run got that far. */
|
|
64
|
+
state?: string;
|
|
65
|
+
change?: string;
|
|
66
|
+
/** Backfill batches filled in this run, and skipped (their receipt was there). */
|
|
67
|
+
filled?: number;
|
|
68
|
+
skipped?: number;
|
|
69
|
+
backfilledRows?: number;
|
|
70
|
+
/** Indexes and constraints built on the new column in this run. */
|
|
71
|
+
carried?: number;
|
|
72
|
+
verifiedRows?: number;
|
|
73
|
+
switched?: boolean;
|
|
74
|
+
oldColumn?: string;
|
|
75
|
+
retainUntil?: string;
|
|
76
|
+
/** The contract dropped the old column. */
|
|
77
|
+
dropped?: boolean;
|
|
78
|
+
}
|
|
79
|
+
/** Folds one migration activity's result into the summary. */
|
|
80
|
+
export declare function summarizePg(summary: PgMigrationSummary, fn: string, result: unknown): void;
|
|
81
|
+
export interface RunPgMigrationOptions extends Omit<RunOpOptions, "activities" | "cwd"> {
|
|
82
|
+
projectDir: string;
|
|
83
|
+
/** The migration's recorded schema: the `chant build` output after it. */
|
|
84
|
+
schema: unknown;
|
|
85
|
+
/** The environment's lock timeout, used when the step's options set none. */
|
|
86
|
+
lockTimeoutMs?: number | undefined;
|
|
87
|
+
/** Activities to use in place of the lexicon's, for a test. */
|
|
88
|
+
activities?: Record<string, ActivityFn>;
|
|
89
|
+
log?: (line: string) => void;
|
|
90
|
+
}
|
|
91
|
+
/** 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
|
+
export declare function runPgMigration(options: PgMigrationOptions, run: RunPgMigrationOptions, summary?: PgMigrationSummary): Promise<{
|
|
93
|
+
summary: PgMigrationSummary;
|
|
94
|
+
records: StepRecord[];
|
|
95
|
+
}>;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A `PostgresMigrationOp` step: a Postgres column rename (SQLPG205) or type
|
|
3
|
+
* change across kinds (SQLPG208), which `yodel new` writes as a step since
|
|
4
|
+
* Postgres cannot make it in place without breaking readers, run inside the
|
|
5
|
+
* migration as chant's expand-and-contract Op.
|
|
6
|
+
*
|
|
7
|
+
* The Op is chant's own (`PostgresMigrationOp` from the sql lexicon), built
|
|
8
|
+
* from the step's options with the apply's environment, and run by chant's
|
|
9
|
+
* local executor with the lexicon's activities, as `ClickHouseRebuildOp` is
|
|
10
|
+
* (`./rebuild.ts`):
|
|
11
|
+
*
|
|
12
|
+
* Plan, Expand, Dual write, Backfill, Carry over, Verify, Switch, Retain, Contract
|
|
13
|
+
*
|
|
14
|
+
* What differs from `chant run` of the Op:
|
|
15
|
+
*
|
|
16
|
+
* - The declaration is the migration's recorded schema (`migration.json`'s
|
|
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
|
|
22
|
+
* difference (a row whose new column is not the expression over the old,
|
|
23
|
+
* 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).
|
|
42
|
+
*/
|
|
43
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
44
|
+
import { tmpdir } from "node:os";
|
|
45
|
+
import { join } from "node:path";
|
|
46
|
+
import { runOp, StepOpFailed } from "./run.js";
|
|
47
|
+
/** The retention a step runs with when its options set none: the contract runs in the same apply. */
|
|
48
|
+
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);
|
|
52
|
+
}
|
|
53
|
+
/** The Op a step runs. `buildPath` is the recorded schema's file; `projectDir` holds chant.config.ts. */
|
|
54
|
+
export async function pgMigrationOpConfig(options, ctx) {
|
|
55
|
+
const { PostgresMigrationOp } = await import("@intentius/chant-lexicon-sql/postgres/migrate/op");
|
|
56
|
+
const lockTimeoutMs = options.lockTimeoutMs ?? ctx.lockTimeoutMs;
|
|
57
|
+
const { op } = PostgresMigrationOp({
|
|
58
|
+
name: options.name,
|
|
59
|
+
env: ctx.environment,
|
|
60
|
+
table: options.table,
|
|
61
|
+
column: options.column,
|
|
62
|
+
...(options.using !== undefined ? { using: options.using } : {}),
|
|
63
|
+
retain: options.retain ?? STEP_RETAIN,
|
|
64
|
+
...(options.batchSize !== undefined ? { batchSize: options.batchSize } : {}),
|
|
65
|
+
...(options.replicationLag !== undefined ? { replicationLag: options.replicationLag } : {}),
|
|
66
|
+
...(lockTimeoutMs !== undefined ? { lockTimeoutMs } : {}),
|
|
67
|
+
...(options.statementTimeoutMs !== undefined ? { statementTimeoutMs: options.statementTimeoutMs } : {}),
|
|
68
|
+
build: false,
|
|
69
|
+
output: ctx.buildPath,
|
|
70
|
+
path: ctx.projectDir,
|
|
71
|
+
});
|
|
72
|
+
const full = op.props;
|
|
73
|
+
const rest = { ...full, phases: pgStepPhases(full) };
|
|
74
|
+
delete rest.onFailure;
|
|
75
|
+
return rest;
|
|
76
|
+
}
|
|
77
|
+
/** The migration activities whose results the history's summary keeps. */
|
|
78
|
+
const SUMMARIZED = ["postgresMigrationPlan", "postgresMigrationBackfill", "postgresMigrationCarry", "postgresMigrationVerify", "postgresMigrationSwitch", "postgresMigrationContract"];
|
|
79
|
+
const num = (v) => (typeof v === "number" ? v : undefined);
|
|
80
|
+
const str = (v) => (typeof v === "string" ? v : undefined);
|
|
81
|
+
/** Folds one migration activity's result into the summary. */
|
|
82
|
+
export function summarizePg(summary, fn, result) {
|
|
83
|
+
const r = (typeof result === "object" && result !== null ? result : {});
|
|
84
|
+
const put = (k, v) => {
|
|
85
|
+
if (v !== undefined)
|
|
86
|
+
summary[k] = v;
|
|
87
|
+
};
|
|
88
|
+
if (fn === "postgresMigrationPlan") {
|
|
89
|
+
put("state", str(r.state));
|
|
90
|
+
put("change", str(r.change));
|
|
91
|
+
}
|
|
92
|
+
if (fn === "postgresMigrationBackfill") {
|
|
93
|
+
put("filled", num(r.filled));
|
|
94
|
+
put("skipped", num(r.skipped));
|
|
95
|
+
put("backfilledRows", num(r.rows));
|
|
96
|
+
}
|
|
97
|
+
if (fn === "postgresMigrationCarry")
|
|
98
|
+
put("carried", num(r.built));
|
|
99
|
+
if (fn === "postgresMigrationVerify")
|
|
100
|
+
put("verifiedRows", num(r.rows));
|
|
101
|
+
if (fn === "postgresMigrationSwitch") {
|
|
102
|
+
put("switched", typeof r.switched === "boolean" ? r.switched : undefined);
|
|
103
|
+
put("oldColumn", str(r.oldColumn));
|
|
104
|
+
put("retainUntil", str(r.retainUntil));
|
|
105
|
+
}
|
|
106
|
+
if (fn === "postgresMigrationContract") {
|
|
107
|
+
put("dropped", typeof r.dropped === "boolean" ? r.dropped : undefined);
|
|
108
|
+
put("oldColumn", str(r.oldColumn));
|
|
109
|
+
put("retainUntil", str(r.retainUntil));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/** Runs a `PostgresMigrationOp` step to the end. The summary fills in as the activities return, so a failure still says how far it got. */
|
|
113
|
+
export async function runPgMigration(options, run, summary = { op: "PostgresMigrationOp", table: options.table, column: options.column }) {
|
|
114
|
+
const dir = mkdtempSync(join(tmpdir(), "yodel-pg-migration-"));
|
|
115
|
+
try {
|
|
116
|
+
const buildPath = join(dir, "schema.json");
|
|
117
|
+
writeFileSync(buildPath, JSON.stringify(run.schema));
|
|
118
|
+
const config = await pgMigrationOpConfig(options, { environment: run.environment, projectDir: run.projectDir, buildPath, lockTimeoutMs: run.lockTimeoutMs });
|
|
119
|
+
const lexicon = run.activities ?? (await import("@intentius/chant-lexicon-sql/op/activities"));
|
|
120
|
+
const wrapped = {};
|
|
121
|
+
for (const fn of SUMMARIZED) {
|
|
122
|
+
const inner = lexicon[fn];
|
|
123
|
+
if (!inner)
|
|
124
|
+
continue;
|
|
125
|
+
wrapped[fn] = async (args, signal) => {
|
|
126
|
+
const result = await inner(args, signal);
|
|
127
|
+
summarizePg(summary, fn, result);
|
|
128
|
+
return result;
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const records = await runOp(config, {
|
|
132
|
+
cwd: run.projectDir,
|
|
133
|
+
environment: run.environment,
|
|
134
|
+
activities: { ...(run.activities ?? {}), ...wrapped },
|
|
135
|
+
...(run.base ? { base: run.base } : {}),
|
|
136
|
+
...(run.signal ? { signal: run.signal } : {}),
|
|
137
|
+
...(run.onRecord ? { onRecord: run.onRecord } : {}),
|
|
138
|
+
}).catch((e) => {
|
|
139
|
+
if (e instanceof StepOpFailed)
|
|
140
|
+
e.summary = summary;
|
|
141
|
+
throw e;
|
|
142
|
+
});
|
|
143
|
+
return { summary, records };
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
rmSync(dir, { recursive: true, force: true });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=postgres-migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-migration.js","sourceRoot":"","sources":["../../src/steps/postgres-migration.ts"],"names":[],"mappings":"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"}
|