pipework 0.17.1 → 0.19.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/CHANGELOG.md +31 -0
- package/dist/REFERENCE.md +1190 -0
- package/dist/cli/commands/migrate.d.ts +16 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -1
- package/dist/cli/commands/migrate.js +35 -4
- package/dist/cli/commands/migrate.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +0 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/data/migrate/apply.d.ts +5 -7
- package/dist/data/migrate/apply.d.ts.map +1 -1
- package/dist/data/migrate/apply.js +7 -95
- package/dist/data/migrate/apply.js.map +1 -1
- package/dist/data/migrate/check.d.ts +11 -4
- package/dist/data/migrate/check.d.ts.map +1 -1
- package/dist/data/migrate/check.js +40 -22
- package/dist/data/migrate/check.js.map +1 -1
- package/dist/data/migrate/index.d.ts +2 -1
- package/dist/data/migrate/index.d.ts.map +1 -1
- package/dist/data/migrate/index.js +1 -0
- package/dist/data/migrate/index.js.map +1 -1
- package/dist/data/migrate/post-process.d.ts.map +1 -1
- package/dist/data/migrate/post-process.js +15 -5
- package/dist/data/migrate/post-process.js.map +1 -1
- package/dist/data/migrate/pragma.d.ts +35 -0
- package/dist/data/migrate/pragma.d.ts.map +1 -0
- package/dist/data/migrate/pragma.js +47 -0
- package/dist/data/migrate/pragma.js.map +1 -0
- package/dist/data/migrate/run.d.ts +1 -3
- package/dist/data/migrate/run.d.ts.map +1 -1
- package/dist/data/migrate/run.js +9 -9
- package/dist/data/migrate/run.js.map +1 -1
- package/dist/data/migrate/safety.d.ts +1 -1
- package/dist/data/migrate/safety.d.ts.map +1 -1
- package/dist/data/migrate/safety.js +41 -20
- package/dist/data/migrate/safety.js.map +1 -1
- package/dist/data/migrate/statements.d.ts +65 -0
- package/dist/data/migrate/statements.d.ts.map +1 -0
- package/dist/data/migrate/statements.js +290 -0
- package/dist/data/migrate/statements.js.map +1 -0
- package/package.json +1 -1
|
@@ -6,4 +6,20 @@ export interface MigrateCommandOptions {
|
|
|
6
6
|
acknowledgeLock: boolean | undefined;
|
|
7
7
|
}
|
|
8
8
|
export declare function migrate(options: MigrateCommandOptions): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* `--allow-destructive` / `--acknowledge-lock` authorized an *invocation*, so
|
|
11
|
+
* the first destructive migration that had to ship put them into a deploy
|
|
12
|
+
* workflow permanently and every migration after that was pre-approved by a
|
|
13
|
+
* decision nobody revisits. Authorization is per-migration now, declared in
|
|
14
|
+
* the file that raises the hazard, where review can see it.
|
|
15
|
+
*
|
|
16
|
+
* Failing loudly rather than ignoring them is the point: a pipeline still
|
|
17
|
+
* passing these is a pipeline that has been running ungated.
|
|
18
|
+
*
|
|
19
|
+
* Returns the error text, or null when neither flag was passed.
|
|
20
|
+
*/
|
|
21
|
+
export declare function rejectRetiredFlags(options: {
|
|
22
|
+
allowDestructive: boolean | undefined;
|
|
23
|
+
acknowledgeLock: boolean | undefined;
|
|
24
|
+
}): string | null;
|
|
9
25
|
//# sourceMappingURL=migrate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/migrate.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAA;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5B,gBAAgB,EAAE,OAAO,GAAG,SAAS,CAAA;IACrC,eAAe,EAAE,OAAO,GAAG,SAAS,CAAA;CACrC;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/migrate.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAA;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5B,gBAAgB,EAAE,OAAO,GAAG,SAAS,CAAA;IACrC,eAAe,EAAE,OAAO,GAAG,SAAS,CAAA;CACrC;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0D3E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,gBAAgB,EAAE,OAAO,GAAG,SAAS,CAAA;IACrC,eAAe,EAAE,OAAO,GAAG,SAAS,CAAA;CACrC,GAAG,MAAM,GAAG,IAAI,CAmBhB"}
|
|
@@ -8,6 +8,11 @@ export async function migrate(options) {
|
|
|
8
8
|
' Run `pipework init` to create one.\n');
|
|
9
9
|
process.exit(1);
|
|
10
10
|
}
|
|
11
|
+
const rejection = rejectRetiredFlags(options);
|
|
12
|
+
if (rejection !== null) {
|
|
13
|
+
logError(rejection);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
11
16
|
const instance = await discoverInstance(options.cwd);
|
|
12
17
|
if (instance.config.environment === 'production' && options.confirm !== true) {
|
|
13
18
|
logError('Refusing to run migrations in production without --confirm.\n\n' +
|
|
@@ -18,10 +23,7 @@ export async function migrate(options) {
|
|
|
18
23
|
if (instance.config.environment === 'production') {
|
|
19
24
|
warn('Running migrations against PRODUCTION database.');
|
|
20
25
|
}
|
|
21
|
-
const migrateOptions = {
|
|
22
|
-
allowDestructive: options.allowDestructive === true,
|
|
23
|
-
acknowledgeLock: options.acknowledgeLock === true,
|
|
24
|
-
};
|
|
26
|
+
const migrateOptions = {};
|
|
25
27
|
try {
|
|
26
28
|
if (options.db !== undefined) {
|
|
27
29
|
info(`Migrating database: ${options.db}`);
|
|
@@ -48,4 +50,33 @@ export async function migrate(options) {
|
|
|
48
50
|
await instance.pool.closeAll();
|
|
49
51
|
}
|
|
50
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* `--allow-destructive` / `--acknowledge-lock` authorized an *invocation*, so
|
|
55
|
+
* the first destructive migration that had to ship put them into a deploy
|
|
56
|
+
* workflow permanently and every migration after that was pre-approved by a
|
|
57
|
+
* decision nobody revisits. Authorization is per-migration now, declared in
|
|
58
|
+
* the file that raises the hazard, where review can see it.
|
|
59
|
+
*
|
|
60
|
+
* Failing loudly rather than ignoring them is the point: a pipeline still
|
|
61
|
+
* passing these is a pipeline that has been running ungated.
|
|
62
|
+
*
|
|
63
|
+
* Returns the error text, or null when neither flag was passed.
|
|
64
|
+
*/
|
|
65
|
+
export function rejectRetiredFlags(options) {
|
|
66
|
+
const used = [
|
|
67
|
+
options.allowDestructive === true ? '--allow-destructive' : null,
|
|
68
|
+
options.acknowledgeLock === true ? '--acknowledge-lock' : null,
|
|
69
|
+
].filter((f) => f !== null);
|
|
70
|
+
if (used.length === 0)
|
|
71
|
+
return null;
|
|
72
|
+
return (`${used.join(' and ')} ${used.length > 1 ? 'are' : 'is'} no longer accepted.\n\n` +
|
|
73
|
+
' Authorization belongs in the migration, not the deploy command.\n' +
|
|
74
|
+
' A flag here approves every migration this pipeline will ever run;\n' +
|
|
75
|
+
' a pragma approves the one file it is written in, in the diff where\n' +
|
|
76
|
+
' it is reviewed.\n\n' +
|
|
77
|
+
' Run `pipework migrate` with no flags. It will name each migration\n' +
|
|
78
|
+
' that needs a declaration and the exact line to add, e.g.\n\n' +
|
|
79
|
+
' -- pipework:expect-destructive\n' +
|
|
80
|
+
' DROP TABLE "graph_co_change_edges";\n');
|
|
81
|
+
}
|
|
51
82
|
//# sourceMappingURL=migrate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../src/cli/commands/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,QAAQ,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAUrE,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAA8B;IAC1D,MAAM,EAAE,gBAAgB,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAA;IACtF,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAA;IAClG,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAA;IAEzE,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;QACrC,QAAQ,CACN,2DAA2D;YAC3D,wCAAwC,CACzC,CAAA;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAEpD,IAAI,QAAQ,CAAC,MAAM,CAAC,WAAW,KAAK,YAAY,IAAI,OAAO,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QAC7E,QAAQ,CACN,iEAAiE;YACjE,oFAAoF;YACpF,qCAAqC,CACtC,CAAA;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,CAAC,WAAW,KAAK,YAAY,EAAE,CAAC;QACjD,IAAI,CAAC,iDAAiD,CAAC,CAAA;IACzD,CAAC;IAED,MAAM,cAAc,GAAG
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../src/cli/commands/migrate.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAoEA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmLvD"}
|
package/dist/cli/index.js
CHANGED
|
@@ -27,8 +27,6 @@ ${bold('Options:')}
|
|
|
27
27
|
--version, -v Show version
|
|
28
28
|
--name Migration name (used with generate)
|
|
29
29
|
--confirm Required for production migrations
|
|
30
|
-
--allow-destructive Permit destructive DDL (DROP TABLE, DROP COLUMN, etc.)
|
|
31
|
-
--acknowledge-lock Permit operations that acquire heavy locks
|
|
32
30
|
--tenant Tenant ID for tenant-scoped scripts
|
|
33
31
|
--job-type Override job type (default: "script")
|
|
34
32
|
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzC,MAAM,KAAK,GAAG;EACZ,IAAI,CAAC,UAAU,CAAC;;EAEhB,IAAI,CAAC,WAAW,CAAC;;;;;;;;;;;;;;;;;EAiBjB,IAAI,CAAC,UAAU,CAAC
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,14 +20,12 @@ export interface Migration {
|
|
|
20
20
|
export declare function applyMigrations(options: ApplyOptions): Promise<number>;
|
|
21
21
|
export declare function readMigrations(options: ApplyOptions): Migration[];
|
|
22
22
|
/**
|
|
23
|
-
* Split migration SQL into individual statements
|
|
24
|
-
*
|
|
25
|
-
* stripped; `--> statement-breakpoint` is honored as an explicit separator.
|
|
23
|
+
* Split migration SQL into individual statements, honoring drizzle's
|
|
24
|
+
* `--> statement-breakpoint` as an explicit separator.
|
|
26
25
|
*
|
|
27
|
-
* The
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* definition into unrunnable fragments. Issue #317.
|
|
26
|
+
* The scanning rules live in `statements.ts`, shared with the safety gate so
|
|
27
|
+
* the runner and the gate cannot disagree about where a statement begins —
|
|
28
|
+
* they did, and the gate was the one that was wrong (#334).
|
|
31
29
|
*/
|
|
32
30
|
export declare function parseStatements(raw: string): string[];
|
|
33
31
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/data/migrate/apply.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,YAAY;IAC3B,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AASD,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CA2F5E;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,EAAE,CA4CjE;AAED
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/data/migrate/apply.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,YAAY;IAC3B,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AASD,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CA2F5E;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,EAAE,CA4CjE;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAErD;AAMD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { readFileSync, existsSync } from 'node:fs';
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
3
|
import postgres from 'postgres';
|
|
4
|
+
import { scanStatements } from './statements.js';
|
|
4
5
|
const NO_TRANSACTION_PRAGMA = '-- pipework:no-transaction';
|
|
5
|
-
const STATEMENT_BREAKPOINT = '--> statement-breakpoint';
|
|
6
6
|
export async function applyMigrations(options) {
|
|
7
7
|
const migrations = readMigrations(options);
|
|
8
8
|
if (migrations.length === 0)
|
|
@@ -107,103 +107,15 @@ export function readMigrations(options) {
|
|
|
107
107
|
return migrations;
|
|
108
108
|
}
|
|
109
109
|
/**
|
|
110
|
-
* Split migration SQL into individual statements
|
|
111
|
-
*
|
|
112
|
-
* stripped; `--> statement-breakpoint` is honored as an explicit separator.
|
|
110
|
+
* Split migration SQL into individual statements, honoring drizzle's
|
|
111
|
+
* `--> statement-breakpoint` as an explicit separator.
|
|
113
112
|
*
|
|
114
|
-
* The
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* definition into unrunnable fragments. Issue #317.
|
|
113
|
+
* The scanning rules live in `statements.ts`, shared with the safety gate so
|
|
114
|
+
* the runner and the gate cannot disagree about where a statement begins —
|
|
115
|
+
* they did, and the gate was the one that was wrong (#334).
|
|
118
116
|
*/
|
|
119
117
|
export function parseStatements(raw) {
|
|
120
|
-
|
|
121
|
-
let current = '';
|
|
122
|
-
const flush = () => {
|
|
123
|
-
if (current.trim().length > 0)
|
|
124
|
-
statements.push(current.trim());
|
|
125
|
-
current = '';
|
|
126
|
-
};
|
|
127
|
-
let i = 0;
|
|
128
|
-
while (i < raw.length) {
|
|
129
|
-
const ch = raw[i];
|
|
130
|
-
// `--` line comment: stripped to end of line. `--> statement-breakpoint` is
|
|
131
|
-
// the one comment that also terminates the current statement.
|
|
132
|
-
if (ch === '-' && raw[i + 1] === '-') {
|
|
133
|
-
const nl = raw.indexOf('\n', i);
|
|
134
|
-
const end = nl === -1 ? raw.length : nl;
|
|
135
|
-
if (raw.slice(i, end).trim() === STATEMENT_BREAKPOINT)
|
|
136
|
-
flush();
|
|
137
|
-
i = end;
|
|
138
|
-
continue;
|
|
139
|
-
}
|
|
140
|
-
// `'...'` literal — `''` is an escaped quote. Copied verbatim.
|
|
141
|
-
if (ch === "'") {
|
|
142
|
-
const end = scanSingleQuote(raw, i);
|
|
143
|
-
current += raw.slice(i, end);
|
|
144
|
-
i = end;
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
// `$tag$ ... $tag$` dollar-quoted block. Copied verbatim — inner `;`/`--`
|
|
148
|
-
// are body content, not separators.
|
|
149
|
-
if (ch === '$') {
|
|
150
|
-
const tag = dollarQuoteTag(raw, i);
|
|
151
|
-
if (tag !== null) {
|
|
152
|
-
const close = raw.indexOf(tag, i + tag.length);
|
|
153
|
-
const end = close === -1 ? raw.length : close + tag.length;
|
|
154
|
-
current += raw.slice(i, end);
|
|
155
|
-
i = end;
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
if (ch === ';') {
|
|
160
|
-
flush();
|
|
161
|
-
i += 1;
|
|
162
|
-
continue;
|
|
163
|
-
}
|
|
164
|
-
current += ch;
|
|
165
|
-
i += 1;
|
|
166
|
-
}
|
|
167
|
-
flush();
|
|
168
|
-
return statements;
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* `start` indexes the opening `'`. Returns the index just past the closing `'`,
|
|
172
|
-
* treating a doubled `''` as an escaped quote. An unterminated literal returns
|
|
173
|
-
* the end of input — the statement is emitted as-is so Postgres reports it.
|
|
174
|
-
*/
|
|
175
|
-
function scanSingleQuote(raw, start) {
|
|
176
|
-
let i = start + 1;
|
|
177
|
-
while (i < raw.length) {
|
|
178
|
-
if (raw[i] === "'") {
|
|
179
|
-
if (raw[i + 1] === "'") {
|
|
180
|
-
i += 2;
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
return i + 1;
|
|
184
|
-
}
|
|
185
|
-
i += 1;
|
|
186
|
-
}
|
|
187
|
-
return raw.length;
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* If `start` indexes the opening `$` of a dollar-quote tag (`$$` or `$label$`,
|
|
191
|
-
* where a label is a SQL identifier), returns the full tag text; otherwise
|
|
192
|
-
* `null`. A `$` followed by a digit (`$1`) or non-identifier character is not
|
|
193
|
-
* a tag.
|
|
194
|
-
*/
|
|
195
|
-
function dollarQuoteTag(raw, start) {
|
|
196
|
-
let i = start + 1;
|
|
197
|
-
while (i < raw.length) {
|
|
198
|
-
const c = raw[i];
|
|
199
|
-
if (c === '$')
|
|
200
|
-
return raw.slice(start, i + 1);
|
|
201
|
-
const valid = i === start + 1 ? /[A-Za-z_]/.test(c) : /[A-Za-z0-9_]/.test(c);
|
|
202
|
-
if (!valid)
|
|
203
|
-
return null;
|
|
204
|
-
i += 1;
|
|
205
|
-
}
|
|
206
|
-
return null;
|
|
118
|
+
return scanStatements(raw, { breakpointSeparator: true });
|
|
207
119
|
}
|
|
208
120
|
function quoteIdent(name) {
|
|
209
121
|
return `"${name.replace(/"/g, '""')}"`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/data/migrate/apply.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,QAAQ,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/data/migrate/apply.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import { type MigrationHazard, type Severity } from './safety.js';
|
|
2
|
+
import { type PragmaKind } from './pragma.js';
|
|
2
3
|
import type { AppliedState } from './applied.js';
|
|
4
|
+
export interface FileHazards {
|
|
5
|
+
file: string;
|
|
6
|
+
hazards: MigrationHazard[];
|
|
7
|
+
/** Hazard classes this file raises but does not declare a pragma for. */
|
|
8
|
+
undeclared: PragmaKind[];
|
|
9
|
+
}
|
|
3
10
|
export interface MigrationCheckResult {
|
|
4
11
|
safe: boolean;
|
|
5
12
|
hasDestructive: boolean;
|
|
6
13
|
hasLocking: boolean;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
hasDynamic: boolean;
|
|
15
|
+
/** True when every hazard raised is declared by its own migration. */
|
|
16
|
+
declared: boolean;
|
|
17
|
+
fileHazards: FileHazards[];
|
|
11
18
|
}
|
|
12
19
|
/**
|
|
13
20
|
* Scans pending migrations for destructive and locking operations.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/data/migrate/check.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC5F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhD,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,OAAO,CAAA;IACb,cAAc,EAAE,OAAO,CAAA;IACvB,UAAU,EAAE,OAAO,CAAA;IACnB,
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/data/migrate/check.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC5F,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,eAAe,EAAE,CAAA;IAC1B,yEAAyE;IACzE,UAAU,EAAE,UAAU,EAAE,CAAA;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,OAAO,CAAA;IACb,cAAc,EAAE,OAAO,CAAA;IACvB,UAAU,EAAE,OAAO,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;IACnB,sEAAsE;IACtE,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,EAAE,WAAW,EAAE,CAAA;CAC3B;AAYD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,GAAG,oBAAoB,CAuD7G;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CA6BtE;AAED,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFileSync, existsSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { analyzeSQL, formatHazards } from './safety.js';
|
|
4
|
+
import { hasPragma, PRAGMA_FOR } from './pragma.js';
|
|
4
5
|
/**
|
|
5
6
|
* Scans pending migrations for destructive and locking operations.
|
|
6
7
|
*
|
|
@@ -15,12 +16,14 @@ import { analyzeSQL, formatHazards } from './safety.js';
|
|
|
15
16
|
export function checkMigrations(migrationsFolder, applied) {
|
|
16
17
|
const journalPath = join(migrationsFolder, 'meta', '_journal.json');
|
|
17
18
|
if (!existsSync(journalPath)) {
|
|
18
|
-
return { safe: true, hasDestructive: false, hasLocking: false, fileHazards: [] };
|
|
19
|
+
return { safe: true, hasDestructive: false, hasLocking: false, hasDynamic: false, declared: true, fileHazards: [] };
|
|
19
20
|
}
|
|
20
21
|
const journal = JSON.parse(readFileSync(journalPath, 'utf-8'));
|
|
21
22
|
const fileHazards = [];
|
|
22
23
|
let hasDestructive = false;
|
|
23
24
|
let hasLocking = false;
|
|
25
|
+
let hasDynamic = false;
|
|
26
|
+
let declared = true;
|
|
24
27
|
const isApplied = (entry) => {
|
|
25
28
|
if (applied === undefined || applied === null)
|
|
26
29
|
return false;
|
|
@@ -37,41 +40,56 @@ export function checkMigrations(migrationsFolder, applied) {
|
|
|
37
40
|
const sql = readFileSync(sqlPath, 'utf-8');
|
|
38
41
|
const hazards = analyzeSQL(sql);
|
|
39
42
|
if (hazards.length > 0) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
// A hazard is authorized by a pragma in the migration that raises it —
|
|
44
|
+
// never by a flag on the deploy command, which would authorize this
|
|
45
|
+
// migration and every migration after it. Checked per file, per class.
|
|
46
|
+
const undeclared = [];
|
|
47
|
+
for (const kind of ['destructive', 'locking', 'dynamic']) {
|
|
48
|
+
if (!hazards.some(h => h.severity === kind))
|
|
49
|
+
continue;
|
|
50
|
+
if (kind === 'destructive')
|
|
51
|
+
hasDestructive = true;
|
|
52
|
+
if (kind === 'locking')
|
|
53
|
+
hasLocking = true;
|
|
54
|
+
if (kind === 'dynamic')
|
|
55
|
+
hasDynamic = true;
|
|
56
|
+
if (!hasPragma(sql, kind)) {
|
|
57
|
+
undeclared.push(kind);
|
|
58
|
+
declared = false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
fileHazards.push({ file: `${entry.tag}.sql`, hazards, undeclared });
|
|
45
62
|
}
|
|
46
63
|
}
|
|
47
64
|
return {
|
|
48
|
-
safe: !hasDestructive && !hasLocking,
|
|
65
|
+
safe: !hasDestructive && !hasLocking && !hasDynamic,
|
|
49
66
|
hasDestructive,
|
|
50
67
|
hasLocking,
|
|
68
|
+
hasDynamic,
|
|
69
|
+
declared,
|
|
51
70
|
fileHazards,
|
|
52
71
|
};
|
|
53
72
|
}
|
|
54
73
|
export function formatCheckResult(result) {
|
|
55
|
-
if (result.
|
|
74
|
+
if (result.declared)
|
|
56
75
|
return '';
|
|
57
76
|
const lines = [];
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (lCount > 0)
|
|
64
|
-
parts.push(`${lCount} locking`);
|
|
65
|
-
lines.push(`Migration safety check: ${parts.join(' and ')} operation${dCount + lCount > 1 ? 's' : ''} detected.\n`);
|
|
66
|
-
for (const { file, hazards } of result.fileHazards) {
|
|
77
|
+
const undeclaredFiles = result.fileHazards.filter(f => f.undeclared.length > 0);
|
|
78
|
+
const n = undeclaredFiles.length;
|
|
79
|
+
lines.push(`Migration safety check: ${n} migration${n > 1 ? 's' : ''} raise${n > 1 ? '' : 's'} ` +
|
|
80
|
+
`hazards that ${n > 1 ? 'their own files do' : 'its own file does'} not declare.\n`);
|
|
81
|
+
for (const { file, hazards } of undeclaredFiles) {
|
|
67
82
|
lines.push(formatHazards(hazards, file));
|
|
68
83
|
}
|
|
69
84
|
lines.push('');
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
85
|
+
lines.push('Authorization belongs in the migration, not the deploy command.');
|
|
86
|
+
lines.push('Add the matching line to the top of each file above and commit it,');
|
|
87
|
+
lines.push('so the approval is reviewed in the diff and recorded in history:');
|
|
88
|
+
lines.push('');
|
|
89
|
+
for (const { file, undeclared } of undeclaredFiles) {
|
|
90
|
+
for (const kind of undeclared) {
|
|
91
|
+
lines.push(` ${file}: -- ${PRAGMA_FOR[kind]}`);
|
|
92
|
+
}
|
|
75
93
|
}
|
|
76
94
|
return lines.join('\n');
|
|
77
95
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/data/migrate/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAuC,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/data/migrate/check.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { migrateAll, migrateOne, UnsafeMigrationError, type MigrateResult, type MigrateOptions } from './run.js';
|
|
2
|
-
export { checkMigrations, formatCheckResult, type MigrationCheckResult, type MigrationHazard, type Severity } from './check.js';
|
|
2
|
+
export { checkMigrations, formatCheckResult, type MigrationCheckResult, type FileHazards, type MigrationHazard, type Severity } from './check.js';
|
|
3
|
+
export { hasPragma, PRAGMA_FOR, type PragmaKind } from './pragma.js';
|
|
3
4
|
export { readAppliedState, type AppliedState } from './applied.js';
|
|
4
5
|
export { analyzeSQL } from './safety.js';
|
|
5
6
|
export { generateForDatabase, type GenerateResult } from './generate.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/data/migrate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AAChH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/data/migrate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AAChH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAA;AACjJ,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAA;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { migrateAll, migrateOne, UnsafeMigrationError } from './run.js';
|
|
2
2
|
export { checkMigrations, formatCheckResult } from './check.js';
|
|
3
|
+
export { hasPragma, PRAGMA_FOR } from './pragma.js';
|
|
3
4
|
export { readAppliedState } from './applied.js';
|
|
4
5
|
export { analyzeSQL } from './safety.js';
|
|
5
6
|
export { generateForDatabase } from './generate.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/data/migrate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAA2C,MAAM,UAAU,CAAA;AAChH,OAAO,EAAE,eAAe,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/data/migrate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAA2C,MAAM,UAAU,CAAA;AAChH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAoF,MAAM,YAAY,CAAA;AACjJ,OAAO,EAAE,SAAS,EAAE,UAAU,EAAmB,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,gBAAgB,EAAqB,MAAM,cAAc,CAAA;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAuB,MAAM,eAAe,CAAA;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-process.d.ts","sourceRoot":"","sources":["../../../src/data/migrate/post-process.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"post-process.d.ts","sourceRoot":"","sources":["../../../src/data/migrate/post-process.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAoDxD"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { stripComments, codeStartOffset } from './statements.js';
|
|
1
2
|
const CREATE_INDEX_RE = /\bCREATE\s+(UNIQUE\s+)?INDEX\b(?!\s+CONCURRENTLY)/i;
|
|
2
3
|
const CONCURRENTLY_RE = /\bCONCURRENTLY\b/i;
|
|
3
4
|
const NO_TRANSACTION_PRAGMA = '-- pipework:no-transaction';
|
|
@@ -21,18 +22,27 @@ export function postProcessMigration(sql) {
|
|
|
21
22
|
const outputStatements = [];
|
|
22
23
|
let hasConcurrently = false;
|
|
23
24
|
for (const raw of rawStatements) {
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
// Match against the SQL with comments removed, not against the raw
|
|
26
|
+
// fragment. A statement and the comment above it share a `;`-fragment, so
|
|
27
|
+
// skipping fragments that *start with* `--` skipped the statement too and
|
|
28
|
+
// a commented CREATE INDEX silently kept its exclusive lock (#334).
|
|
29
|
+
// Comment text is equally unable to fake a match it should not have.
|
|
30
|
+
const code = stripComments(raw);
|
|
31
|
+
if (code.trim().length === 0) {
|
|
26
32
|
outputStatements.push(raw);
|
|
27
33
|
continue;
|
|
28
34
|
}
|
|
29
|
-
if (CREATE_INDEX_RE.test(
|
|
30
|
-
|
|
35
|
+
if (CREATE_INDEX_RE.test(code)) {
|
|
36
|
+
// Rewrite only from where the SQL actually starts, so a leading comment
|
|
37
|
+
// that happens to say "CREATE INDEX" is not the thing rewritten.
|
|
38
|
+
const offset = codeStartOffset(raw);
|
|
39
|
+
const rewritten = raw.slice(0, offset) +
|
|
40
|
+
raw.slice(offset).replace(/\b(CREATE\s+(?:UNIQUE\s+)?)(INDEX)\b/i, '$1$2 CONCURRENTLY');
|
|
31
41
|
outputStatements.push(rewritten);
|
|
32
42
|
hasConcurrently = true;
|
|
33
43
|
continue;
|
|
34
44
|
}
|
|
35
|
-
if (CONCURRENTLY_RE.test(
|
|
45
|
+
if (CONCURRENTLY_RE.test(code)) {
|
|
36
46
|
hasConcurrently = true;
|
|
37
47
|
}
|
|
38
48
|
outputStatements.push(raw);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-process.js","sourceRoot":"","sources":["../../../src/data/migrate/post-process.ts"],"names":[],"mappings":"AAAA,MAAM,eAAe,GAAG,oDAAoD,CAAA;AAC5E,MAAM,eAAe,GAAG,mBAAmB,CAAA;AAE3C,MAAM,qBAAqB,GAAG,4BAA4B,CAAA;AAE1D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACxC,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAExC,MAAM,gBAAgB,GAAa,EAAE,CAAA;IACrC,IAAI,eAAe,GAAG,KAAK,CAAA;IAE3B,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAChC,MAAM,
|
|
1
|
+
{"version":3,"file":"post-process.js","sourceRoot":"","sources":["../../../src/data/migrate/post-process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEhE,MAAM,eAAe,GAAG,oDAAoD,CAAA;AAC5E,MAAM,eAAe,GAAG,mBAAmB,CAAA;AAE3C,MAAM,qBAAqB,GAAG,4BAA4B,CAAA;AAE1D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACxC,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAExC,MAAM,gBAAgB,GAAa,EAAE,CAAA;IACrC,IAAI,eAAe,GAAG,KAAK,CAAA;IAE3B,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAChC,mEAAmE;QACnE,0EAA0E;QAC1E,0EAA0E;QAC1E,oEAAoE;QACpE,qEAAqE;QACrE,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;QAC/B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAC1B,SAAQ;QACV,CAAC;QAED,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,wEAAwE;YACxE,iEAAiE;YACjE,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;YACnC,MAAM,SAAS,GACb,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC;gBACpB,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,uCAAuC,EAAE,mBAAmB,CAAC,CAAA;YACzF,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YAChC,eAAe,GAAG,IAAI,CAAA;YACtB,SAAQ;QACV,CAAC;QAED,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,eAAe,GAAG,IAAI,CAAA;QACxB,CAAC;QAED,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC5B,CAAC;IAED,IAAI,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAA;IAE7C,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,QAAQ,CAAA;IACpB,CAAC;IAED,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,qBAAqB,CAAC;YAC/C,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,GAAG,qBAAqB,KAAK,MAAM,EAAE,CAAA;IAC3C,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration pragmas — per-file declarations read from the migration's own
|
|
3
|
+
* comments.
|
|
4
|
+
*
|
|
5
|
+
* Authorization for a hazardous migration lives here rather than on the
|
|
6
|
+
* `pipework migrate` command line, and the distinction is the whole point.
|
|
7
|
+
* A CLI flag authorizes an *invocation*: it is written once, into a deploy
|
|
8
|
+
* workflow, by someone who cannot know what migration 0071 will contain nine
|
|
9
|
+
* months later. The first destructive migration that has to ship puts
|
|
10
|
+
* `--allow-destructive` in CI permanently, and from then on the gate is
|
|
11
|
+
* decorative — every later migration is pre-approved by a decision nobody
|
|
12
|
+
* revisits, and nothing about it shows up in review.
|
|
13
|
+
*
|
|
14
|
+
* A pragma authorizes a *file*. It is written by the person writing the
|
|
15
|
+
* destructive statement, at the moment they write it; it appears in the diff,
|
|
16
|
+
* so it is reviewed; it is versioned, so `git log` says who approved which
|
|
17
|
+
* drop; and it cannot go blanket — a pragma in 0065 says nothing about 0071.
|
|
18
|
+
* The deploy command stays a bare `pipework migrate` forever, which means
|
|
19
|
+
* there is no flag to erode.
|
|
20
|
+
*
|
|
21
|
+
* The migration tracker already records a content hash per applied migration
|
|
22
|
+
* and refuses edited-but-applied files, so a pragma cannot be quietly added
|
|
23
|
+
* after the fact.
|
|
24
|
+
*/
|
|
25
|
+
export declare const PRAGMA_PREFIX = "-- pipework:";
|
|
26
|
+
/** Hazard classes that require a per-migration declaration. */
|
|
27
|
+
export type PragmaKind = 'destructive' | 'locking' | 'dynamic';
|
|
28
|
+
export declare const PRAGMA_FOR: Record<PragmaKind, string>;
|
|
29
|
+
/**
|
|
30
|
+
* True when `sql` declares the given pragma. Pragmas are recognized only on
|
|
31
|
+
* their own comment line, so prose that happens to mention one does not
|
|
32
|
+
* authorize anything.
|
|
33
|
+
*/
|
|
34
|
+
export declare function hasPragma(sql: string, kind: PragmaKind): boolean;
|
|
35
|
+
//# sourceMappingURL=pragma.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pragma.d.ts","sourceRoot":"","sources":["../../../src/data/migrate/pragma.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,eAAO,MAAM,aAAa,iBAAiB,CAAA;AAE3C,+DAA+D;AAC/D,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,SAAS,GAAG,SAAS,CAAA;AAE9D,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAIjD,CAAA;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAQhE"}
|