@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.
- package/README.md +3 -3
- package/dist/apply-steps/index.d.ts +65 -0
- package/dist/apply-steps/index.js +106 -0
- package/dist/apply-steps/index.js.map +1 -0
- package/dist/approval-mode/index.d.ts +78 -0
- package/dist/approval-mode/index.js +105 -0
- package/dist/approval-mode/index.js.map +1 -0
- package/dist/chant/access.d.ts +87 -0
- package/dist/chant/access.js +169 -0
- package/dist/chant/access.js.map +1 -0
- package/dist/chant/build.js +7 -0
- package/dist/chant/build.js.map +1 -1
- package/dist/chant/drift.d.ts +17 -1
- package/dist/chant/drift.js +55 -2
- package/dist/chant/drift.js.map +1 -1
- package/dist/chant/plan.d.ts +18 -2
- package/dist/chant/plan.js +21 -3
- package/dist/chant/plan.js.map +1 -1
- package/dist/ci/render.d.ts +333 -0
- package/dist/ci/render.js +885 -0
- package/dist/ci/render.js.map +1 -0
- package/dist/ci/replay.d.ts +17 -0
- package/dist/ci/replay.js +69 -0
- package/dist/ci/replay.js.map +1 -0
- package/dist/cleanup/index.d.ts +86 -0
- package/dist/cleanup/index.js +207 -0
- package/dist/cleanup/index.js.map +1 -0
- package/dist/commands/apply.d.ts +113 -0
- package/dist/commands/apply.js +370 -30
- package/dist/commands/apply.js.map +1 -1
- package/dist/commands/approve.d.ts +13 -0
- package/dist/commands/approve.js +239 -13
- package/dist/commands/approve.js.map +1 -1
- package/dist/commands/checkpoint.d.ts +3 -0
- package/dist/commands/checkpoint.js +78 -0
- package/dist/commands/checkpoint.js.map +1 -0
- package/dist/commands/ci.d.ts +3 -0
- package/dist/commands/ci.js +130 -0
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/cleanup.d.ts +13 -0
- package/dist/commands/cleanup.js +138 -0
- package/dist/commands/cleanup.js.map +1 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.js +136 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/docs.d.ts +11 -0
- package/dist/commands/docs.js +108 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/drift.d.ts +13 -1
- package/dist/commands/drift.js +52 -5
- package/dist/commands/drift.js.map +1 -1
- package/dist/commands/index.js +16 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/lint.js +39 -7
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/new.js +133 -34
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/override.js +48 -16
- package/dist/commands/override.js.map +1 -1
- package/dist/commands/plan.js +47 -6
- package/dist/commands/plan.js.map +1 -1
- package/dist/commands/report.d.ts +13 -0
- package/dist/commands/report.js +121 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/revert.d.ts +20 -0
- package/dist/commands/revert.js +246 -0
- package/dist/commands/revert.js.map +1 -0
- package/dist/commands/status.js +32 -5
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/test.d.ts +3 -0
- package/dist/commands/test.js +164 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/config/base.d.ts +69 -0
- package/dist/config/base.js +121 -0
- package/dist/config/base.js.map +1 -0
- package/dist/config/define.d.ts +240 -3
- package/dist/config/define.js +4 -0
- package/dist/config/define.js.map +1 -1
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/load.d.ts +1 -1
- package/dist/config/load.js +156 -7
- package/dist/config/load.js.map +1 -1
- package/dist/config/settings.d.ts +22 -1
- package/dist/config/settings.js +34 -2
- package/dist/config/settings.js.map +1 -1
- package/dist/credentials.d.ts +119 -0
- package/dist/credentials.js +119 -0
- package/dist/credentials.js.map +1 -0
- package/dist/exit.js +1 -1
- package/dist/exit.js.map +1 -1
- package/dist/history/postgres/ddl.d.ts +18 -0
- package/dist/history/postgres/ddl.js +27 -2
- package/dist/history/postgres/ddl.js.map +1 -1
- package/dist/history/postgres/store.d.ts +2 -0
- package/dist/history/postgres/store.js +7 -1
- package/dist/history/postgres/store.js.map +1 -1
- package/dist/history/rows.d.ts +16 -3
- package/dist/history/rows.js +30 -1
- package/dist/history/rows.js.map +1 -1
- package/dist/history/store.d.ts +2 -0
- package/dist/history/store.js +2 -2
- package/dist/history/store.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/init/adopt.js +1 -1
- package/dist/init/adopt.js.map +1 -1
- package/dist/init/clickhouse-access.d.ts +64 -0
- package/dist/init/clickhouse-access.js +211 -0
- package/dist/init/clickhouse-access.js.map +1 -0
- package/dist/init/live.d.ts +4 -0
- package/dist/init/live.js +16 -0
- package/dist/init/live.js.map +1 -1
- package/dist/lint/access.d.ts +18 -0
- package/dist/lint/access.js +34 -0
- package/dist/lint/access.js.map +1 -0
- package/dist/lint/check.js +38 -6
- package/dist/lint/check.js.map +1 -1
- package/dist/lint/config.d.ts +7 -1
- package/dist/lint/config.js +11 -5
- package/dist/lint/config.js.map +1 -1
- package/dist/lint/index.d.ts +2 -0
- package/dist/lint/index.js +2 -0
- package/dist/lint/index.js.map +1 -1
- package/dist/lint/naming.d.ts +62 -0
- package/dist/lint/naming.js +138 -0
- package/dist/lint/naming.js.map +1 -0
- package/dist/lint/report.js +1 -1
- package/dist/lint/report.js.map +1 -1
- package/dist/lint/routines.d.ts +26 -0
- package/dist/lint/routines.js +65 -0
- package/dist/lint/routines.js.map +1 -0
- package/dist/lint/rules.d.ts +51 -6
- package/dist/lint/rules.js +23 -6
- package/dist/lint/rules.js.map +1 -1
- package/dist/lint/schema-checks.d.ts +63 -0
- package/dist/lint/schema-checks.js +128 -0
- package/dist/lint/schema-checks.js.map +1 -0
- package/dist/lint/statements.d.ts +22 -1
- package/dist/lint/statements.js +40 -1
- package/dist/lint/statements.js.map +1 -1
- package/dist/mcp/tools.d.ts +1 -1
- package/dist/mcp/tools.js +1 -1
- package/dist/mcp/tools.js.map +1 -1
- package/dist/migrations/checkpoint.d.ts +45 -0
- package/dist/migrations/checkpoint.js +108 -0
- package/dist/migrations/checkpoint.js.map +1 -0
- package/dist/migrations/checks.d.ts +19 -1
- package/dist/migrations/checks.js +15 -0
- package/dist/migrations/checks.js.map +1 -1
- package/dist/migrations/create.d.ts +13 -4
- package/dist/migrations/create.js +24 -7
- package/dist/migrations/create.js.map +1 -1
- package/dist/migrations/document.d.ts +10 -0
- package/dist/migrations/document.js +1 -0
- package/dist/migrations/document.js.map +1 -1
- package/dist/migrations/index.d.ts +2 -0
- package/dist/migrations/index.js +2 -0
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/routines.d.ts +21 -0
- package/dist/migrations/routines.js +30 -0
- package/dist/migrations/routines.js.map +1 -0
- package/dist/notify/index.d.ts +124 -0
- package/dist/notify/index.js +210 -0
- package/dist/notify/index.js.map +1 -0
- package/dist/notify/verify.d.ts +53 -0
- package/dist/notify/verify.js +71 -0
- package/dist/notify/verify.js.map +1 -0
- package/dist/pr/model.d.ts +7 -1
- package/dist/pr/model.js +29 -7
- package/dist/pr/model.js.map +1 -1
- package/dist/pr/render.d.ts +4 -1
- package/dist/pr/render.js +49 -9
- package/dist/pr/render.js.map +1 -1
- package/dist/pr/tenants.d.ts +37 -0
- package/dist/pr/tenants.js +138 -0
- package/dist/pr/tenants.js.map +1 -0
- package/dist/probe.d.ts +27 -0
- package/dist/probe.js +106 -0
- package/dist/probe.js.map +1 -0
- package/dist/project.d.ts +35 -2
- package/dist/project.js +62 -2
- package/dist/project.js.map +1 -1
- package/dist/replay/clickhouse.d.ts +31 -0
- package/dist/replay/clickhouse.js +103 -6
- package/dist/replay/clickhouse.js.map +1 -1
- package/dist/replay/replay.d.ts +14 -3
- package/dist/replay/replay.js +62 -31
- package/dist/replay/replay.js.map +1 -1
- package/dist/replay/report.js +1 -1
- package/dist/replay/report.js.map +1 -1
- package/dist/report/audit.d.ts +138 -0
- package/dist/report/audit.js +219 -0
- package/dist/report/audit.js.map +1 -0
- package/dist/report/jsonl.d.ts +21 -0
- package/dist/report/jsonl.js +52 -0
- package/dist/report/jsonl.js.map +1 -0
- package/dist/report/model.d.ts +68 -0
- package/dist/report/model.js +127 -0
- package/dist/report/model.js.map +1 -0
- package/dist/report/render.d.ts +18 -0
- package/dist/report/render.js +127 -0
- package/dist/report/render.js.map +1 -0
- package/dist/schema-docs/render.d.ts +49 -0
- package/dist/schema-docs/render.js +359 -0
- package/dist/schema-docs/render.js.map +1 -0
- package/dist/schemas.d.ts +7 -2
- package/dist/schemas.js +7 -2
- package/dist/schemas.js.map +1 -1
- package/dist/sources/ddl.d.ts +48 -0
- package/dist/sources/ddl.js +53 -0
- package/dist/sources/ddl.js.map +1 -0
- package/dist/sources/index.d.ts +69 -0
- package/dist/sources/index.js +170 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/steps/backfill.d.ts +40 -5
- package/dist/steps/backfill.js +128 -8
- package/dist/steps/backfill.js.map +1 -1
- package/dist/steps/index.d.ts +19 -1
- package/dist/steps/index.js +34 -7
- package/dist/steps/index.js.map +1 -1
- package/dist/steps/kinds.d.ts +42 -4
- package/dist/steps/kinds.js +88 -14
- package/dist/steps/kinds.js.map +1 -1
- package/dist/steps/postgres-migration.d.ts +38 -25
- package/dist/steps/postgres-migration.js +49 -32
- package/dist/steps/postgres-migration.js.map +1 -1
- package/dist/steps/rebuild.d.ts +15 -6
- package/dist/steps/rebuild.js +12 -9
- package/dist/steps/rebuild.js.map +1 -1
- package/dist/tenants/index.d.ts +41 -0
- package/dist/tenants/index.js +121 -0
- package/dist/tenants/index.js.map +1 -0
- package/dist/tenants/target.d.ts +23 -0
- package/dist/tenants/target.js +29 -0
- package/dist/tenants/target.js.map +1 -0
- package/dist/tenants/wave.d.ts +128 -0
- package/dist/tenants/wave.js +254 -0
- package/dist/tenants/wave.js.map +1 -0
- package/dist/testing/define.d.ts +62 -0
- package/dist/testing/define.js +32 -0
- package/dist/testing/define.js.map +1 -0
- package/dist/testing/files.d.ts +5 -0
- package/dist/testing/files.js +18 -0
- package/dist/testing/files.js.map +1 -0
- package/dist/testing/report.d.ts +14 -0
- package/dist/testing/report.js +83 -0
- package/dist/testing/report.js.map +1 -0
- package/dist/testing/run.d.ts +104 -0
- package/dist/testing/run.js +328 -0
- package/dist/testing/run.js.map +1 -0
- package/dist/versioned/approval.d.ts +6 -0
- package/dist/versioned/approval.js +11 -5
- package/dist/versioned/approval.js.map +1 -1
- package/dist/versioned/checks.d.ts +8 -2
- package/dist/versioned/checks.js +34 -13
- package/dist/versioned/checks.js.map +1 -1
- package/dist/versioned/driver.d.ts +2 -2
- package/dist/versioned/engine.d.ts +16 -0
- package/dist/versioned/engine.js +20 -6
- package/dist/versioned/engine.js.map +1 -1
- package/dist/versioned/explain.d.ts +2 -0
- package/dist/versioned/explain.js +3 -1
- package/dist/versioned/explain.js.map +1 -1
- package/dist/versioned/index.d.ts +1 -0
- package/dist/versioned/index.js +1 -0
- package/dist/versioned/index.js.map +1 -1
- package/dist/versioned/op.d.ts +6 -1
- package/dist/versioned/op.js +7 -2
- package/dist/versioned/op.js.map +1 -1
- package/dist/versioned/policy.d.ts +33 -2
- package/dist/versioned/policy.js +59 -8
- package/dist/versioned/policy.js.map +1 -1
- package/dist/versioned/report.js +9 -0
- package/dist/versioned/report.js.map +1 -1
- package/dist/versioned/revert.d.ts +128 -0
- package/dist/versioned/revert.js +251 -0
- package/dist/versioned/revert.js.map +1 -0
- package/dist/versioned/state.d.ts +25 -0
- package/dist/versioned/state.js +37 -4
- package/dist/versioned/state.js.map +1 -1
- package/dist/waves/index.d.ts +224 -0
- package/dist/waves/index.js +353 -0
- package/dist/waves/index.js.map +1 -0
- package/dist/waves/promotion.d.ts +56 -0
- package/dist/waves/promotion.js +108 -0
- package/dist/waves/promotion.js.map +1 -0
- package/dist/waves/record.d.ts +34 -0
- package/dist/waves/record.js +20 -0
- package/dist/waves/record.js.map +1 -0
- package/package.json +11 -7
- package/schemas/apply.schema.json +162 -3
- package/schemas/checkpoint.schema.json +19 -0
- package/schemas/cleanup.schema.json +40 -0
- package/schemas/drift.schema.json +26 -1
- package/schemas/event.schema.json +36 -0
- package/schemas/lint-rules.schema.json +4 -0
- package/schemas/lint.schema.json +4 -0
- package/schemas/new.schema.json +41 -3
- package/schemas/plan.schema.json +157 -0
- package/schemas/report.schema.json +114 -0
- package/schemas/revert.schema.json +69 -0
- package/schemas/status.schema.json +64 -3
- package/schemas/test.schema.json +41 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-migration.js","sourceRoot":"","sources":["../../src/steps/postgres-migration.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"postgres-migration.js","sourceRoot":"","sources":["../../src/steps/postgres-migration.ts"],"names":[],"mappings":"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"}
|
package/dist/steps/rebuild.d.ts
CHANGED
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
* is in the plan digest the migrations Op's gate approved), so the Op has
|
|
21
21
|
* no gate and no Drop phase. The verification still runs before the swap,
|
|
22
22
|
* and a difference fails the step with nothing swapped. The old table is
|
|
23
|
-
* kept, `<table>__chant_old`, until its retention date
|
|
23
|
+
* kept, `<table>__chant_old`, until its retention date: the step's
|
|
24
|
+
* `options.retain` (`yodel new --retain`) after the swap, else 7 days.
|
|
24
25
|
* - It is built with `onFailure: "keep"`, so a step that failed or was
|
|
25
26
|
* killed part way keeps `<table>__chant_new` and `<table>__chant_dual` and
|
|
26
27
|
* resumes from the backfill's receipts on the next `yodel apply`: every
|
|
@@ -37,6 +38,7 @@
|
|
|
37
38
|
* on each server, distinct per shard, and refuses the cluster without it.
|
|
38
39
|
*/
|
|
39
40
|
import type { OpConfig } from "@intentius/chant/op/types";
|
|
41
|
+
import type { ReceiptStore } from "@intentius/chant/op/receipt-store";
|
|
40
42
|
import type { ActivityFn } from "@intentius/chant/op/activity-registry";
|
|
41
43
|
import type { StepRecord } from "@intentius/chant/op/local-executor";
|
|
42
44
|
import type { Topology } from "@intentius/chant-lexicon-sql/clickhouse/topology";
|
|
@@ -46,12 +48,13 @@ import { type RunOpOptions } from "./run.js";
|
|
|
46
48
|
/** `config` with `sql.profiles.<environment>.topology` set to `topology`. Pure; `config` is not changed. */
|
|
47
49
|
export declare function withProfileTopology(config: ProjectConfig, environment: string, topology: Topology): ProjectConfig;
|
|
48
50
|
/**
|
|
49
|
-
* The chant config a rebuild step's activities bind with: the project's
|
|
50
|
-
* with the environment's resolved topology on
|
|
51
|
-
* not find it there itself. `
|
|
52
|
-
*
|
|
51
|
+
* The chant config a rebuild step's activities bind with: the project's
|
|
52
|
+
* (or `base`, a tenant's, #56), with the environment's resolved topology on
|
|
53
|
+
* its profile when chant would not find it there itself. `base` (or
|
|
54
|
+
* `undefined`, chant.config.ts) when chant's own resolution already gives
|
|
55
|
+
* the same topology (set in the profile, or no topology anywhere).
|
|
53
56
|
*/
|
|
54
|
-
export declare function rebuildChantConfig(projectDir: string, environment: string, env?: NodeJS.ProcessEnv): Promise<ProjectConfig | undefined>;
|
|
57
|
+
export declare function rebuildChantConfig(projectDir: string, environment: string, env?: NodeJS.ProcessEnv, base?: ProjectConfig): Promise<ProjectConfig | undefined>;
|
|
55
58
|
/** The Op a rebuild step runs. `buildPath` is the recorded schema's file; `projectDir` holds chant.config.ts. */
|
|
56
59
|
export declare function rebuildOpConfig(options: RebuildOptions, ctx: {
|
|
57
60
|
environment: string;
|
|
@@ -80,6 +83,10 @@ export interface RebuildSummary {
|
|
|
80
83
|
}
|
|
81
84
|
/** Folds one rebuild activity's result into the summary. */
|
|
82
85
|
export declare function summarize(summary: RebuildSummary, fn: string, result: unknown): void;
|
|
86
|
+
/** Where a rebuild's backfill keeps its partition receipts: a receipt store that also reads every receipt under an address prefix at once. */
|
|
87
|
+
export interface RebuildReceiptStore extends ReceiptStore {
|
|
88
|
+
readAll(prefix: string): Promise<Map<string, string>>;
|
|
89
|
+
}
|
|
83
90
|
export interface RunRebuildOptions extends Omit<RunOpOptions, "activities" | "cwd"> {
|
|
84
91
|
projectDir: string;
|
|
85
92
|
/** The migration's recorded schema: the `chant build` output after it. */
|
|
@@ -89,6 +96,8 @@ export interface RunRebuildOptions extends Omit<RunOpOptions, "activities" | "cw
|
|
|
89
96
|
log?: (line: string) => void;
|
|
90
97
|
/** The chant config the rebuild activities bind with (see {@link rebuildChantConfig}). Default: they load chant.config.ts. */
|
|
91
98
|
config?: ProjectConfig | undefined;
|
|
99
|
+
/** The backfill's partition receipts. Default: the lexicon's store on the server, `chant_receipts.receipts`. */
|
|
100
|
+
receipts?: RebuildReceiptStore | undefined;
|
|
92
101
|
}
|
|
93
102
|
/** Runs a rebuild step to the end. The summary is filled in as the activities return, so a failure still says how far it got. */
|
|
94
103
|
export declare function runRebuild(options: RebuildOptions, run: RunRebuildOptions, summary?: RebuildSummary): Promise<{
|
package/dist/steps/rebuild.js
CHANGED
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
* is in the plan digest the migrations Op's gate approved), so the Op has
|
|
21
21
|
* no gate and no Drop phase. The verification still runs before the swap,
|
|
22
22
|
* and a difference fails the step with nothing swapped. The old table is
|
|
23
|
-
* kept, `<table>__chant_old`, until its retention date
|
|
23
|
+
* kept, `<table>__chant_old`, until its retention date: the step's
|
|
24
|
+
* `options.retain` (`yodel new --retain`) after the swap, else 7 days.
|
|
24
25
|
* - It is built with `onFailure: "keep"`, so a step that failed or was
|
|
25
26
|
* killed part way keeps `<table>__chant_new` and `<table>__chant_dual` and
|
|
26
27
|
* resumes from the backfill's receipts on the next `yodel apply`: every
|
|
@@ -53,17 +54,18 @@ export function withProfileTopology(config, environment, topology) {
|
|
|
53
54
|
return { ...config, sql: { ...config.sql, profiles: { ...profiles, [environment]: { ...profile, topology } } } };
|
|
54
55
|
}
|
|
55
56
|
/**
|
|
56
|
-
* The chant config a rebuild step's activities bind with: the project's
|
|
57
|
-
* with the environment's resolved topology on
|
|
58
|
-
* not find it there itself. `
|
|
59
|
-
*
|
|
57
|
+
* The chant config a rebuild step's activities bind with: the project's
|
|
58
|
+
* (or `base`, a tenant's, #56), with the environment's resolved topology on
|
|
59
|
+
* its profile when chant would not find it there itself. `base` (or
|
|
60
|
+
* `undefined`, chant.config.ts) when chant's own resolution already gives
|
|
61
|
+
* the same topology (set in the profile, or no topology anywhere).
|
|
60
62
|
*/
|
|
61
|
-
export async function rebuildChantConfig(projectDir, environment, env = process.env) {
|
|
63
|
+
export async function rebuildChantConfig(projectDir, environment, env = process.env, base) {
|
|
62
64
|
const project = await loadProject(projectDir);
|
|
63
65
|
const settings = environmentSettings(project, environment, env);
|
|
64
66
|
if (settings.topologySource === "default" || settings.topologySource === `sql.profiles.${environment}.topology`)
|
|
65
|
-
return
|
|
66
|
-
return withProfileTopology(project.config, environment, settings.topology);
|
|
67
|
+
return base;
|
|
68
|
+
return withProfileTopology(base ?? project.config, environment, settings.topology);
|
|
67
69
|
}
|
|
68
70
|
/** The Op a rebuild step runs. `buildPath` is the recorded schema's file; `projectDir` holds chant.config.ts. */
|
|
69
71
|
export async function rebuildOpConfig(options, ctx) {
|
|
@@ -73,6 +75,7 @@ export async function rebuildOpConfig(options, ctx) {
|
|
|
73
75
|
env: ctx.environment,
|
|
74
76
|
table: options.table,
|
|
75
77
|
dualWrite: options.dualWrite,
|
|
78
|
+
...(options.retain !== undefined ? { retain: options.retain } : {}),
|
|
76
79
|
build: false,
|
|
77
80
|
output: ctx.buildPath,
|
|
78
81
|
path: ctx.projectDir,
|
|
@@ -121,7 +124,7 @@ export async function runRebuild(options, run, summary = { op: "ClickHouseRebuil
|
|
|
121
124
|
const lexicon = run.activities ?? (await import("@intentius/chant-lexicon-sql/op/activities"));
|
|
122
125
|
const wrapped = {};
|
|
123
126
|
// A rebuild activity takes its config as a third argument (chant's ClickHouseRebuildDeps).
|
|
124
|
-
const deps = run.config ? { config: run.config } : undefined;
|
|
127
|
+
const deps = run.config || run.receipts ? { ...(run.config ? { config: run.config } : {}), ...(run.receipts ? { backfill: { receipts: run.receipts } } : {}) } : undefined;
|
|
125
128
|
const summarized = SUMMARIZED;
|
|
126
129
|
for (const fn of Object.keys(lexicon).filter((f) => f.startsWith("clickhouseRebuild") && (deps !== undefined || summarized.includes(f)))) {
|
|
127
130
|
const inner = lexicon[fn];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rebuild.js","sourceRoot":"","sources":["../../src/steps/rebuild.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rebuild.js","sourceRoot":"","sources":["../../src/steps/rebuild.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tenant sets (#56): one environment over many databases (ClickHouse) or
|
|
3
|
+
* schemas (Postgres) with the same migrations.
|
|
4
|
+
*
|
|
5
|
+
* `yodel.config.ts` `environments.<env>.tenants` lists them (names, a file,
|
|
6
|
+
* or a read-only query on the environment's server). Each tenant is a
|
|
7
|
+
* target of its own, `<env>/<tenant>`: its profile is the environment's on
|
|
8
|
+
* the tenant's database or schema (`resolveEnvironment`), its history is
|
|
9
|
+
* `<history database>_<tenant>` (`environmentSettings`), and every
|
|
10
|
+
* statement and check is sent with the template's name replaced by the
|
|
11
|
+
* tenant's ({@link tenantDriver}). The apply pipeline renders the
|
|
12
|
+
* environment's wave with a run per tenant, one gate over all of them.
|
|
13
|
+
*/
|
|
14
|
+
import type { TenantSet } from "../config/define.js";
|
|
15
|
+
import { type Environment, type Project, type TenantOf } from "../project.js";
|
|
16
|
+
import type { VersionedDriver } from "../versioned/driver.js";
|
|
17
|
+
export * from "./target.js";
|
|
18
|
+
/** `env`'s tenant set in yodel.config.ts, if it has one. */
|
|
19
|
+
export declare const tenantSetOf: (project: Pick<Project, "yodel">, env: string) => TenantSet | undefined;
|
|
20
|
+
/** Reads a tenant file: a JSON array of names, or one name per line (`#` starts a comment). */
|
|
21
|
+
export declare function readTenantFile(path: string): string[];
|
|
22
|
+
/**
|
|
23
|
+
* The tenants of `env`, in the order the set gives them; undefined when it
|
|
24
|
+
* has no set. A query runs read-only on the environment's server, with its
|
|
25
|
+
* profile, and its rows' first column are the names.
|
|
26
|
+
*/
|
|
27
|
+
export declare function listTenants(project: Project, env: string): Promise<string[] | undefined>;
|
|
28
|
+
/** Throws unless `env`'s tenant set names the tenant `env` is. */
|
|
29
|
+
export declare function checkTenant(project: Project, env: Environment): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* The targets `names` stand for: an environment with a tenant set is each
|
|
32
|
+
* of its tenants, `<env>/<tenant>`; any other name is itself.
|
|
33
|
+
*/
|
|
34
|
+
export declare function expandTargets(project: Project, names: readonly string[]): Promise<string[]>;
|
|
35
|
+
/**
|
|
36
|
+
* A tenant's driver: the environment's, with the template's name replaced
|
|
37
|
+
* by the tenant's in every statement and check it sends. An Op step (a
|
|
38
|
+
* rebuild, a backfill) gets the tenant in its context, and its runner
|
|
39
|
+
* renames what the step names (`../steps/index.ts`).
|
|
40
|
+
*/
|
|
41
|
+
export declare function tenantDriver(driver: VersionedDriver, tenant: TenantOf): VersionedDriver;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tenant sets (#56): one environment over many databases (ClickHouse) or
|
|
3
|
+
* schemas (Postgres) with the same migrations.
|
|
4
|
+
*
|
|
5
|
+
* `yodel.config.ts` `environments.<env>.tenants` lists them (names, a file,
|
|
6
|
+
* or a read-only query on the environment's server). Each tenant is a
|
|
7
|
+
* target of its own, `<env>/<tenant>`: its profile is the environment's on
|
|
8
|
+
* the tenant's database or schema (`resolveEnvironment`), its history is
|
|
9
|
+
* `<history database>_<tenant>` (`environmentSettings`), and every
|
|
10
|
+
* statement and check is sent with the template's name replaced by the
|
|
11
|
+
* tenant's ({@link tenantDriver}). The apply pipeline renders the
|
|
12
|
+
* environment's wave with a run per tenant, one gate over all of them.
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
15
|
+
import { resolve } from "node:path";
|
|
16
|
+
import { resolveEnvironment, YodelError } from "../project.js";
|
|
17
|
+
import { renameIdentifier, splitTarget, TENANT_NAME, tenantTarget } from "./target.js";
|
|
18
|
+
export * from "./target.js";
|
|
19
|
+
/** `env`'s tenant set in yodel.config.ts, if it has one. */
|
|
20
|
+
export const tenantSetOf = (project, env) => project.yodel?.config.environments?.[env]?.tenants;
|
|
21
|
+
function checked(names, where) {
|
|
22
|
+
const bad = names.filter((n) => !TENANT_NAME.test(n));
|
|
23
|
+
if (bad.length > 0)
|
|
24
|
+
throw new YodelError(`${where} lists ${bad.map((b) => JSON.stringify(b)).join(", ")}, which ${bad.length === 1 ? "is not a tenant name" : "are not tenant names"} (letters, digits and _, not starting with a digit)`);
|
|
25
|
+
return [...new Set(names)];
|
|
26
|
+
}
|
|
27
|
+
/** Reads a tenant file: a JSON array of names, or one name per line (`#` starts a comment). */
|
|
28
|
+
export function readTenantFile(path) {
|
|
29
|
+
if (!existsSync(path))
|
|
30
|
+
throw new YodelError(`the tenant file ${path} does not exist`);
|
|
31
|
+
const text = readFileSync(path, "utf8");
|
|
32
|
+
if (text.trimStart().startsWith("[")) {
|
|
33
|
+
let parsed;
|
|
34
|
+
try {
|
|
35
|
+
parsed = JSON.parse(text);
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
throw new YodelError(`${path}: ${e instanceof Error ? e.message : String(e)}`);
|
|
39
|
+
}
|
|
40
|
+
if (!Array.isArray(parsed) || !parsed.every((t) => typeof t === "string"))
|
|
41
|
+
throw new YodelError(`${path}: expected a JSON array of tenant names`);
|
|
42
|
+
return checked(parsed, path);
|
|
43
|
+
}
|
|
44
|
+
return checked(text.split("\n").map((l) => l.replace(/#.*/, "").trim()).filter(Boolean), path);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The tenants of `env`, in the order the set gives them; undefined when it
|
|
48
|
+
* has no set. A query runs read-only on the environment's server, with its
|
|
49
|
+
* profile, and its rows' first column are the names.
|
|
50
|
+
*/
|
|
51
|
+
export async function listTenants(project, env) {
|
|
52
|
+
const set = tenantSetOf(project, env);
|
|
53
|
+
if (set === undefined)
|
|
54
|
+
return undefined;
|
|
55
|
+
if (Array.isArray(set))
|
|
56
|
+
return [...set];
|
|
57
|
+
if ("file" in set)
|
|
58
|
+
return readTenantFile(resolve(project.dir, set.file));
|
|
59
|
+
const { openVersioned, closeVersioned } = await import("../versioned/engine.js");
|
|
60
|
+
const venv = await openVersioned(project, resolveEnvironment(project, env));
|
|
61
|
+
try {
|
|
62
|
+
let rows;
|
|
63
|
+
try {
|
|
64
|
+
rows = await venv.driver.readCheck(set.query, {});
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
throw new YodelError(`${env}'s tenant query failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
68
|
+
}
|
|
69
|
+
return checked(rows.map((r) => { const v = Object.values(r)[0]; return typeof v === "string" ? v : JSON.stringify(v ?? ""); }), `${env}'s tenant query`);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
await closeVersioned(venv);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Throws unless `env`'s tenant set names the tenant `env` is. */
|
|
76
|
+
export async function checkTenant(project, env) {
|
|
77
|
+
if (!env.tenant)
|
|
78
|
+
return;
|
|
79
|
+
const set = tenantSetOf(project, env.tenant.env);
|
|
80
|
+
if (Array.isArray(set))
|
|
81
|
+
return; // resolveEnvironment checked it.
|
|
82
|
+
const names = (await listTenants(project, env.tenant.env)) ?? [];
|
|
83
|
+
if (!names.includes(env.tenant.name)) {
|
|
84
|
+
throw new YodelError(`no tenant "${env.tenant.name}" in ${env.tenant.env}'s tenant set (${set && "file" in set ? set.file : "its query"} lists ${names.length > 0 ? names.join(", ") : "none"})`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The targets `names` stand for: an environment with a tenant set is each
|
|
89
|
+
* of its tenants, `<env>/<tenant>`; any other name is itself.
|
|
90
|
+
*/
|
|
91
|
+
export async function expandTargets(project, names) {
|
|
92
|
+
const out = [];
|
|
93
|
+
for (const name of names) {
|
|
94
|
+
const tenants = splitTarget(name).tenant === undefined ? await listTenants(project, name) : undefined;
|
|
95
|
+
if (tenants)
|
|
96
|
+
out.push(...tenants.map((t) => tenantTarget(name, t)));
|
|
97
|
+
else
|
|
98
|
+
out.push(name);
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A tenant's driver: the environment's, with the template's name replaced
|
|
104
|
+
* by the tenant's in every statement and check it sends. An Op step (a
|
|
105
|
+
* rebuild, a backfill) gets the tenant in its context, and its runner
|
|
106
|
+
* renames what the step names (`../steps/index.ts`).
|
|
107
|
+
*/
|
|
108
|
+
export function tenantDriver(driver, tenant) {
|
|
109
|
+
const rename = (sql) => renameIdentifier(sql, tenant.template, tenant.name);
|
|
110
|
+
const where = (w) => ({
|
|
111
|
+
...(w.defaultDatabase !== undefined ? { defaultDatabase: rename(w.defaultDatabase) } : {}),
|
|
112
|
+
...(w.defaultSchema !== undefined ? { defaultSchema: rename(w.defaultSchema) } : {}),
|
|
113
|
+
});
|
|
114
|
+
return {
|
|
115
|
+
...driver,
|
|
116
|
+
readCheck: (sql, w) => driver.readCheck(rename(sql), where(w)),
|
|
117
|
+
runStatement: (step, run) => driver.runStatement({ ...step, sql: rename(step.sql) }, run),
|
|
118
|
+
stepContext: () => ({ ...driver.stepContext(), tenant }),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tenants/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tenant targets (#56), the parts every module can import: a tenant of
|
|
3
|
+
* environment `prod` is the target `prod/<tenant>`, and its migrations are
|
|
4
|
+
* the environment's with the template database or schema renamed.
|
|
5
|
+
*/
|
|
6
|
+
/** Between an environment and a tenant in a target's name. */
|
|
7
|
+
export declare const TENANT_SEPARATOR = "/";
|
|
8
|
+
/** A tenant's name: a database or schema name, and part of a target's name and of a file's. */
|
|
9
|
+
export declare const TENANT_NAME: RegExp;
|
|
10
|
+
/** `prod/acme` is environment `prod`, tenant `acme`; `prod` is `prod` alone. */
|
|
11
|
+
export declare function splitTarget(name: string): {
|
|
12
|
+
env: string;
|
|
13
|
+
tenant?: string;
|
|
14
|
+
};
|
|
15
|
+
/** The environment a target belongs to: `prod` for `prod/acme` and for `prod`. */
|
|
16
|
+
export declare const baseEnvironment: (name: string) => string;
|
|
17
|
+
export declare const tenantTarget: (env: string, tenant: string) => string;
|
|
18
|
+
/**
|
|
19
|
+
* `sql` with every identifier `from` replaced by `to`: the name standing
|
|
20
|
+
* alone, bare or quoted (`from.orders`, `"from"`, `` `from` ``), never a
|
|
21
|
+
* longer name that contains it (`from_archive`).
|
|
22
|
+
*/
|
|
23
|
+
export declare function renameIdentifier(sql: string, from: string, to: string): string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tenant targets (#56), the parts every module can import: a tenant of
|
|
3
|
+
* environment `prod` is the target `prod/<tenant>`, and its migrations are
|
|
4
|
+
* the environment's with the template database or schema renamed.
|
|
5
|
+
*/
|
|
6
|
+
/** Between an environment and a tenant in a target's name. */
|
|
7
|
+
export const TENANT_SEPARATOR = "/";
|
|
8
|
+
/** A tenant's name: a database or schema name, and part of a target's name and of a file's. */
|
|
9
|
+
export const TENANT_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
10
|
+
/** `prod/acme` is environment `prod`, tenant `acme`; `prod` is `prod` alone. */
|
|
11
|
+
export function splitTarget(name) {
|
|
12
|
+
const i = name.indexOf(TENANT_SEPARATOR);
|
|
13
|
+
return i < 0 ? { env: name } : { env: name.slice(0, i), tenant: name.slice(i + 1) };
|
|
14
|
+
}
|
|
15
|
+
/** The environment a target belongs to: `prod` for `prod/acme` and for `prod`. */
|
|
16
|
+
export const baseEnvironment = (name) => splitTarget(name).env;
|
|
17
|
+
export const tenantTarget = (env, tenant) => `${env}${TENANT_SEPARATOR}${tenant}`;
|
|
18
|
+
const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
19
|
+
/**
|
|
20
|
+
* `sql` with every identifier `from` replaced by `to`: the name standing
|
|
21
|
+
* alone, bare or quoted (`from.orders`, `"from"`, `` `from` ``), never a
|
|
22
|
+
* longer name that contains it (`from_archive`).
|
|
23
|
+
*/
|
|
24
|
+
export function renameIdentifier(sql, from, to) {
|
|
25
|
+
if (from === to)
|
|
26
|
+
return sql;
|
|
27
|
+
return sql.replace(new RegExp(`(?<![A-Za-z0-9_$])${escapeRegExp(from)}(?![A-Za-z0-9_$])`, "g"), to);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.js","sourceRoot":"","sources":["../../src/tenants/target.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAEpC,+FAA+F;AAC/F,MAAM,CAAC,MAAM,WAAW,GAAG,0BAA0B,CAAC;AAEtD,gFAAgF;AAChF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;AACtF,CAAC;AAED,kFAAkF;AAClF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC;AAE/E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAE,MAAc,EAAU,EAAE,CAAC,GAAG,GAAG,GAAG,gBAAgB,GAAG,MAAM,EAAE,CAAC;AAE1G,MAAM,YAAY,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAErF;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,IAAY,EAAE,EAAU;IACpE,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,GAAG,CAAC;IAC5B,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,qBAAqB,YAAY,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;AACtG,CAAC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tenant set's wave (#56): how the apply pipeline runs it, and what
|
|
3
|
+
* `yodel plan` and `yodel approve` show of it.
|
|
4
|
+
*
|
|
5
|
+
* A set given as a list or a file is a run per tenant, `<env>/<tenant>`,
|
|
6
|
+
* written into the rendered pipeline. A set given by a query is read when
|
|
7
|
+
* the wave runs, never when the pipeline is rendered: its wave is `shares`
|
|
8
|
+
* slots (one without `shares`), `<env>/@<i>of<n>`, and a slot is every
|
|
9
|
+
* tenant the query lists at that moment whose name hashes to it
|
|
10
|
+
* ({@link slotIndex}). Tenants come and go without a change to the
|
|
11
|
+
* pipeline, and a tenant always lands in the same slot.
|
|
12
|
+
*
|
|
13
|
+
* A slot's plan (`yodel apply <env>/@<i>of<n> --wave-plan`) is each of its
|
|
14
|
+
* tenants' wave plans and a digest over them, so the wave's one gate binds
|
|
15
|
+
* every tenant's plan whichever way the set is given. `--wave-apply` applies
|
|
16
|
+
* each tenant under its own lock, and refuses (exit 4) a tenant whose plan
|
|
17
|
+
* moved since the decision, naming it, after applying the others.
|
|
18
|
+
*/
|
|
19
|
+
import type { TenantSet, WaveGate } from "../config/define.js";
|
|
20
|
+
import type { Migration } from "../migrations/index.js";
|
|
21
|
+
import { type Project } from "../project.js";
|
|
22
|
+
import { type StatusReport } from "../versioned/index.js";
|
|
23
|
+
import { viewWavePlan, type PlanWaveOptions, type WavePlanFile } from "../waves/index.js";
|
|
24
|
+
import { type ApprovalMode } from "../approval-mode/index.js";
|
|
25
|
+
/** Which slot of which set's wave a target is, when it is one: `prod/@2of4`. */
|
|
26
|
+
export declare function splitSlot(target: string): {
|
|
27
|
+
env: string;
|
|
28
|
+
index: number;
|
|
29
|
+
count: number;
|
|
30
|
+
} | undefined;
|
|
31
|
+
export declare const slotTarget: (env: string, index: number, count: number) => string;
|
|
32
|
+
/** The slot, 1 to `count`, a tenant's name hashes to: the same whatever else the set lists. */
|
|
33
|
+
export declare function slotIndex(tenant: string, count: number): number;
|
|
34
|
+
/** A set given by a query is read when its wave runs. */
|
|
35
|
+
export declare const readAtRunTime: (set: TenantSet | undefined) => boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The runs of `env`'s wave, when it has a tenant set: a run per tenant, or
|
|
38
|
+
* for a set given by a query, `shares` slots (one without), with no server
|
|
39
|
+
* read. Undefined for an environment without a tenant set.
|
|
40
|
+
*/
|
|
41
|
+
export declare function waveTargets(project: Project, env: string, shares?: number): Promise<string[] | undefined>;
|
|
42
|
+
/** The digest of a slot's plan: over each of its tenants' wave plan digests. */
|
|
43
|
+
export declare function slotDigest(environment: string, tenants: ReadonlyArray<{
|
|
44
|
+
target: string;
|
|
45
|
+
planDigest: string;
|
|
46
|
+
}>): Promise<string>;
|
|
47
|
+
/** What `--wave-plan` writes for a slot: chant's fields over the slot, and each tenant's own plan. */
|
|
48
|
+
export interface SlotPlanFile {
|
|
49
|
+
planDigest: string;
|
|
50
|
+
destructive: boolean;
|
|
51
|
+
empty: boolean;
|
|
52
|
+
/** The slot, `<env>/@<i>of<n>`. */
|
|
53
|
+
environment: string;
|
|
54
|
+
tenants: Array<{
|
|
55
|
+
target: string;
|
|
56
|
+
plan: WavePlanFile;
|
|
57
|
+
}>;
|
|
58
|
+
/** Every tenant's held `before` steps, as `<tenant>: <step>`. */
|
|
59
|
+
held?: string[];
|
|
60
|
+
}
|
|
61
|
+
/** `yodel apply <env>/@<i>of<n> --wave-plan <file>`: plans every tenant of the slot, as the query lists them now. */
|
|
62
|
+
export declare function writeSlotPlan(project: Project, target: string, ordered: readonly Migration[], file: string, options: PlanWaveOptions, log: (line: string) => void): Promise<SlotPlanFile>;
|
|
63
|
+
/** Reads a slot's plan file. */
|
|
64
|
+
export declare function readSlotPlan(file: string): SlotPlanFile;
|
|
65
|
+
/**
|
|
66
|
+
* `yodel apply <env>/@<i>of<n> --wave-apply <file>`: each tenant the slot's
|
|
67
|
+
* plan names, through `applyTenant` (the tenant's own `--wave-apply`, with
|
|
68
|
+
* the decision checked for the slot). The exit code is 1 when a tenant
|
|
69
|
+
* failed, else 4 when a tenant's plan moved since the decision, else 0.
|
|
70
|
+
*/
|
|
71
|
+
export declare function applySlot(target: string, file: string, applyTenant: (tenant: string, planFile: string, decidedAs: {
|
|
72
|
+
target: string;
|
|
73
|
+
planDigest: string;
|
|
74
|
+
}) => Promise<number>, log: (line: string) => void): Promise<number>;
|
|
75
|
+
/** One tenant, as `yodel approve` reads it: its status, and the wave plan its run would write. */
|
|
76
|
+
export interface TenantView {
|
|
77
|
+
target: string;
|
|
78
|
+
report: StatusReport;
|
|
79
|
+
/** Absent when apply would refuse the tenant (`report.refusal`). */
|
|
80
|
+
plan?: Awaited<ReturnType<typeof viewWavePlan>> | undefined;
|
|
81
|
+
}
|
|
82
|
+
/** Every tenant of `set` now, each against its own history. */
|
|
83
|
+
export declare function viewTenants(project: Project, set: string, ordered: readonly Migration[], options?: {
|
|
84
|
+
allowOutOfOrder?: boolean;
|
|
85
|
+
}): Promise<TenantView[]>;
|
|
86
|
+
/** A tenant set's wave as the deciding job will decide it. */
|
|
87
|
+
export interface TenantSetWaveView {
|
|
88
|
+
/** 1-based, in yodel.config.ts `waves`. */
|
|
89
|
+
wave: number;
|
|
90
|
+
gate: WaveGate;
|
|
91
|
+
base: string;
|
|
92
|
+
baseSource: string;
|
|
93
|
+
/** The wave's runs: a tenant each, or the slots of a set read at run time. */
|
|
94
|
+
runs: Array<{
|
|
95
|
+
target: string;
|
|
96
|
+
tenants: string[];
|
|
97
|
+
planDigest: string;
|
|
98
|
+
destructive: boolean;
|
|
99
|
+
empty: boolean;
|
|
100
|
+
}>;
|
|
101
|
+
/** The set digest the wave's gate binds; absent while a tenant is refused. */
|
|
102
|
+
digest?: string | undefined;
|
|
103
|
+
/** The tenants apply refuses: the wave fails until they are fixed. */
|
|
104
|
+
refused: string[];
|
|
105
|
+
/** A pending migration has not run where a tenant requires it first. */
|
|
106
|
+
blocked: string[];
|
|
107
|
+
/** Under the gate at the base, the wave waits for an approval of `digest`. */
|
|
108
|
+
waits: boolean;
|
|
109
|
+
/** `chant approve yodel-apply yodel-apply-wave-<k> --plan <digest>`, with `--sign` when the wave is sealed. */
|
|
110
|
+
approve?: string | undefined;
|
|
111
|
+
/** Which approvals count (#48), as the base commit has the wave; absent, `ledger`. */
|
|
112
|
+
approval?: ApprovalMode | undefined;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* `set`'s wave over `tenants`, when yodel.config.ts `waves` names it: the
|
|
116
|
+
* runs the deciding job plans, their digests, and the set digest over them,
|
|
117
|
+
* which is what one approval binds. The `before` steps are not run here.
|
|
118
|
+
*/
|
|
119
|
+
export declare function viewTenantSetWave(project: Project, set: string, tenants: ReadonlyArray<Pick<TenantView, "target" | "plan">>): Promise<TenantSetWaveView | undefined>;
|
|
120
|
+
/** The tenants of a set grouped by what is pending on them (the same migrations), in the order first seen. */
|
|
121
|
+
export declare function groupTenants<T>(tenants: readonly T[], key: (t: T) => string): Array<{
|
|
122
|
+
key: string;
|
|
123
|
+
members: T[];
|
|
124
|
+
}>;
|
|
125
|
+
/** Up to `max` names, then how many more. */
|
|
126
|
+
export declare function someNames(names: readonly string[], code?: (s: string) => string, max?: number): string;
|
|
127
|
+
/** One line on a tenant set's wave, for text and markdown. */
|
|
128
|
+
export declare function describeTenantSetWave(w: TenantSetWaveView, count: number, code?: (s: string) => string): string;
|