pg-boss 12.25.0 → 12.26.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/dist/adapters/knex.d.ts.map +1 -1
- package/dist/adapters/knex.js +6 -1
- package/dist/attorney.d.ts.map +1 -1
- package/dist/attorney.js +31 -9
- package/dist/bam.d.ts.map +1 -1
- package/dist/bam.js +23 -1
- package/dist/boss.d.ts.map +1 -1
- package/dist/boss.js +15 -20
- package/dist/cli.js +147 -3
- package/dist/contractor.d.ts +1 -0
- package/dist/contractor.d.ts.map +1 -1
- package/dist/contractor.js +97 -0
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +9 -1
- package/dist/drifter.d.ts +84 -0
- package/dist/drifter.d.ts.map +1 -0
- package/dist/drifter.js +423 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +98 -55
- package/dist/manager.d.ts.map +1 -1
- package/dist/manager.js +68 -22
- package/dist/migrationStore.d.ts +2 -1
- package/dist/migrationStore.d.ts.map +1 -1
- package/dist/migrationStore.js +77 -4
- package/dist/plans.d.ts +24 -2
- package/dist/plans.d.ts.map +1 -1
- package/dist/plans.js +375 -71
- package/dist/schema.json +2069 -0
- package/dist/timekeeper.d.ts.map +1 -1
- package/dist/timekeeper.js +10 -4
- package/dist/types.d.ts +139 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -7
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { ManagedIndex, ManagedFunction, TableColumnDrift, ConstraintDrift, SchemaDriftReport } from './types.ts';
|
|
2
|
+
export declare function indexKeys(ddl: string): string;
|
|
3
|
+
export declare function indexPredicate(ddl: string): string;
|
|
4
|
+
export declare function indexKeysRaw(ddl: string): string;
|
|
5
|
+
export declare function indexPredicateRaw(ddl: string): string;
|
|
6
|
+
export declare function displayIndexDefinition(def: string): string;
|
|
7
|
+
export declare function extractFunctionBody(def: string): string;
|
|
8
|
+
export declare function normalizeFunctionBody(body: string): string;
|
|
9
|
+
export declare function normalizeDefault(expr: string): string;
|
|
10
|
+
export declare function normalizeConstraintDef(def: string): string;
|
|
11
|
+
export declare function getSchemaIndexes(schema: string): string;
|
|
12
|
+
export declare function getSchemaFunctions(schema: string): string;
|
|
13
|
+
export declare function getEnumDefinition(schema: string, typeName?: string): string;
|
|
14
|
+
export declare function getSchemaColumns(schema: string): string;
|
|
15
|
+
export declare function getSchemaTables(schema: string): string;
|
|
16
|
+
export declare function getSchemaConstraints(schema: string): string;
|
|
17
|
+
export declare function functionName(def: string): string;
|
|
18
|
+
export interface LiveIndex {
|
|
19
|
+
name: string;
|
|
20
|
+
table: string;
|
|
21
|
+
valid: boolean;
|
|
22
|
+
def?: string;
|
|
23
|
+
/** True when the index backs a constraint (primary key / unique), so it is not a standalone index. */
|
|
24
|
+
constraintBacked?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface LiveFunction {
|
|
27
|
+
name: string;
|
|
28
|
+
def?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface LiveColumn {
|
|
31
|
+
table: string;
|
|
32
|
+
column: string;
|
|
33
|
+
default?: string | null;
|
|
34
|
+
type?: string;
|
|
35
|
+
notNull?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface ExpectedColumns {
|
|
38
|
+
table: string;
|
|
39
|
+
columns: string[];
|
|
40
|
+
defaults?: Record<string, string>;
|
|
41
|
+
types?: Record<string, {
|
|
42
|
+
type: string;
|
|
43
|
+
notNull: boolean;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
export interface LiveConstraint {
|
|
47
|
+
table: string;
|
|
48
|
+
def: string;
|
|
49
|
+
}
|
|
50
|
+
export interface ExpectedConstraints {
|
|
51
|
+
table: string;
|
|
52
|
+
constraints: string[];
|
|
53
|
+
}
|
|
54
|
+
export declare function computeColumnDrift(expected: ExpectedColumns[], live: LiveColumn[]): TableColumnDrift[];
|
|
55
|
+
export declare function computeConstraintDrift(expected: ExpectedConstraints[], live: LiveConstraint[]): ConstraintDrift[];
|
|
56
|
+
export declare function computeSchemaDrift(opts?: {
|
|
57
|
+
indexes?: {
|
|
58
|
+
expected: ManagedIndex[];
|
|
59
|
+
live: LiveIndex[];
|
|
60
|
+
building?: ReadonlySet<string>;
|
|
61
|
+
};
|
|
62
|
+
tables?: {
|
|
63
|
+
expected: string[];
|
|
64
|
+
live: string[];
|
|
65
|
+
};
|
|
66
|
+
functions?: {
|
|
67
|
+
expected: ManagedFunction[];
|
|
68
|
+
live: LiveFunction[];
|
|
69
|
+
};
|
|
70
|
+
columns?: {
|
|
71
|
+
expected: ExpectedColumns[];
|
|
72
|
+
live: LiveColumn[];
|
|
73
|
+
};
|
|
74
|
+
enum?: {
|
|
75
|
+
name: string;
|
|
76
|
+
expected: readonly string[];
|
|
77
|
+
actual: string[];
|
|
78
|
+
};
|
|
79
|
+
constraints?: {
|
|
80
|
+
expected: ExpectedConstraints[];
|
|
81
|
+
live: LiveConstraint[];
|
|
82
|
+
};
|
|
83
|
+
}): SchemaDriftReport;
|
|
84
|
+
//# sourceMappingURL=drifter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drifter.d.ts","sourceRoot":"","sources":["../src/drifter.ts"],"names":[],"mappings":"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"}
|
package/dist/drifter.js
ADDED
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
const SINGLE_QUOTE_REGEX = /'/g;
|
|
2
|
+
// Extracts the first balanced parenthesised group from a CREATE INDEX statement — the key-column
|
|
3
|
+
// list. Stops at the matching close paren, so a trailing INCLUDE(...) or WHERE(...) is excluded and
|
|
4
|
+
// an inner COALESCE(...) is kept. Works on both hand-written DDL and pg_get_indexdef output (whose
|
|
5
|
+
// leading `USING btree (` opens the same first group).
|
|
6
|
+
function extractIndexKeyList(ddl) {
|
|
7
|
+
const open = ddl.indexOf('(');
|
|
8
|
+
if (open === -1)
|
|
9
|
+
return null;
|
|
10
|
+
let depth = 0;
|
|
11
|
+
for (let i = open; i < ddl.length; i++) {
|
|
12
|
+
if (ddl[i] === '(')
|
|
13
|
+
depth++;
|
|
14
|
+
else if (ddl[i] === ')' && --depth === 0)
|
|
15
|
+
return ddl.slice(open + 1, i);
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
// Strips SQL type casts, including schema-qualified enum casts (Postgres renders a job_state literal
|
|
20
|
+
// as `'active'::pgboss.job_state` and a text literal as `''::text`). Run before whitespace removal is
|
|
21
|
+
// fine — casts never contain spaces.
|
|
22
|
+
const CAST_REGEX = /::(?:[a-z_][a-z0-9_$]*\.)?[a-z_][a-z0-9_$]*(?:\[\])?/g;
|
|
23
|
+
// Normalises a key-column list so an expected list and a pg_get_indexdef list compare equal when they
|
|
24
|
+
// mean the same thing: lower-cased, quotes and whitespace stripped, and type casts removed. Column
|
|
25
|
+
// ORDER is preserved — an index on (a, b) must not normalise equal to (b, a), which is exactly the
|
|
26
|
+
// index-ordinal significance the drift check needs. Parens are kept so COALESCE(...) survives.
|
|
27
|
+
function normalizeKeyList(keyList) {
|
|
28
|
+
return keyList
|
|
29
|
+
.toLowerCase()
|
|
30
|
+
.replace(/"/g, '')
|
|
31
|
+
.replace(/\s+/g, '')
|
|
32
|
+
.replace(CAST_REGEX, '');
|
|
33
|
+
}
|
|
34
|
+
export function indexKeys(ddl) {
|
|
35
|
+
const list = extractIndexKeyList(ddl);
|
|
36
|
+
return list === null ? '' : normalizeKeyList(list);
|
|
37
|
+
}
|
|
38
|
+
// Everything after the top-level WHERE — the partial-index predicate — or '' for a non-partial index.
|
|
39
|
+
function extractPredicate(ddl) {
|
|
40
|
+
const m = ddl.match(/\bWHERE\b/i);
|
|
41
|
+
return m ? ddl.slice(m.index + m[0].length) : '';
|
|
42
|
+
}
|
|
43
|
+
// Normalises a predicate for comparison. Both sides originate from pg_get_indexdef — expected from the
|
|
44
|
+
// manifest, live from the catalog — so both carry pg's canonical form; this only undoes the cosmetic
|
|
45
|
+
// differences pg can vary between two equal predicates:
|
|
46
|
+
// - casts added to every literal (`'active'::pgboss.job_state`, `'x'::text`) → stripped
|
|
47
|
+
// - `IN (a, b)` rendered as `= ANY (ARRAY[a, b])` → folded back to `IN (a, b)`
|
|
48
|
+
// - the redundant OUTER paren pair pg wraps the whole predicate in → removed
|
|
49
|
+
// - case/whitespace differences → normalised away
|
|
50
|
+
// INNER grouping parens are deliberately KEPT: pg parenthesises each sub-expression identically for two
|
|
51
|
+
// equal predicates, so keeping them is symmetric, and it lets a real regrouping (`(a OR b) AND c` vs
|
|
52
|
+
// `a OR (b AND c)`) be detected as drift instead of both collapsing to the same token soup. This is why
|
|
53
|
+
// the whole-predicate paren strip must be OUTER-only (stripOuterParens), not a blanket paren removal.
|
|
54
|
+
function normalizePredicate(predicate) {
|
|
55
|
+
const folded = predicate
|
|
56
|
+
.toLowerCase()
|
|
57
|
+
.replace(/"/g, '')
|
|
58
|
+
.replace(CAST_REGEX, '')
|
|
59
|
+
.replace(/=\s*any\s*\(\s*array\s*\[([^\]]*)\]\s*\)/g, 'in ($1)');
|
|
60
|
+
return stripOuterParens(folded).replace(/\s+/g, '');
|
|
61
|
+
}
|
|
62
|
+
export function indexPredicate(ddl) {
|
|
63
|
+
return normalizePredicate(extractPredicate(ddl));
|
|
64
|
+
}
|
|
65
|
+
// Readable (non-normalised) key-column list and predicate for a CREATE INDEX statement, with runs of
|
|
66
|
+
// whitespace collapsed to single spaces and type casts stripped (a live `'active'::pgboss.job_state`
|
|
67
|
+
// reads as `'active'`). These are the human-facing values surfaced in a drift report; the normalised
|
|
68
|
+
// forms above are only used for comparison. Returns '' when there is nothing to show (no key list /
|
|
69
|
+
// no WHERE).
|
|
70
|
+
export function indexKeysRaw(ddl) {
|
|
71
|
+
const list = extractIndexKeyList(ddl);
|
|
72
|
+
return list === null ? '' : list.replace(CAST_REGEX, '').replace(/\s+/g, ' ').trim();
|
|
73
|
+
}
|
|
74
|
+
export function indexPredicateRaw(ddl) {
|
|
75
|
+
return stripOuterParens(extractPredicate(ddl).replace(CAST_REGEX, '').replace(/\s+/g, ' ').trim());
|
|
76
|
+
}
|
|
77
|
+
// True when the whole string is wrapped in a single outer parenthesis pair (the opening `(` matches
|
|
78
|
+
// the final `)`), e.g. "(a AND (b))" but not "(a) AND (b)".
|
|
79
|
+
function outerParensWrapWhole(s) {
|
|
80
|
+
if (s[0] !== '(')
|
|
81
|
+
return false;
|
|
82
|
+
let depth = 0;
|
|
83
|
+
for (let i = 0; i < s.length; i++) {
|
|
84
|
+
if (s[i] === '(')
|
|
85
|
+
depth++;
|
|
86
|
+
else if (s[i] === ')' && --depth === 0)
|
|
87
|
+
return i === s.length - 1;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
// Removes the redundant outer parentheses pg_get_indexdef wraps a whole predicate in. Only the
|
|
92
|
+
// outermost pair is stripped — inner grouping (which may be meaningful) is left intact.
|
|
93
|
+
function stripOuterParens(s) {
|
|
94
|
+
let out = s.trim();
|
|
95
|
+
while (outerParensWrapWhole(out)) {
|
|
96
|
+
out = out.slice(1, -1).trim();
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
// Tidies a pg_get_indexdef statement for display: drops the `USING btree` clause (btree is the
|
|
101
|
+
// default access method and every pg-boss index uses it, so it is pure noise), strips type casts
|
|
102
|
+
// (`'active'::pgboss.job_state` reads as `'active'`), collapses whitespace, and removes the redundant
|
|
103
|
+
// outer parentheses around the WHERE predicate. Inner grouping is left as-is.
|
|
104
|
+
export function displayIndexDefinition(def) {
|
|
105
|
+
const cleaned = def.replace(/\s+USING\s+btree\s+/i, ' ').replace(CAST_REGEX, '').replace(/\s+/g, ' ').trim();
|
|
106
|
+
const m = cleaned.match(/\bWHERE\b/i);
|
|
107
|
+
if (!m)
|
|
108
|
+
return cleaned;
|
|
109
|
+
const head = cleaned.slice(0, m.index + m[0].length);
|
|
110
|
+
const predicate = stripOuterParens(cleaned.slice(m.index + m[0].length).trim());
|
|
111
|
+
return `${head} ${predicate}`;
|
|
112
|
+
}
|
|
113
|
+
// Extracts the body of a function definition — the text between the outer dollar-quote tags. Works on
|
|
114
|
+
// both pg-boss's own `CREATE FUNCTION ... AS $$ … $$` and Postgres's `pg_get_functiondef` output
|
|
115
|
+
// (which wraps the body in `$function$ … $function$`). Postgres stores prosrc verbatim, so the two
|
|
116
|
+
// bodies are byte-identical for an un-drifted function, modulo the dollar-quote tag name. Nested
|
|
117
|
+
// dollar quotes with a different tag (pg-boss uses `$cmd$`) live inside the body and are preserved.
|
|
118
|
+
// Returns '' when no dollar-quoted body is found — an un-diffable definition is skipped, not flagged.
|
|
119
|
+
export function extractFunctionBody(def) {
|
|
120
|
+
const open = def.match(/\$[A-Za-z0-9_]*\$/);
|
|
121
|
+
if (!open)
|
|
122
|
+
return '';
|
|
123
|
+
const tag = open[0];
|
|
124
|
+
const start = open.index + tag.length;
|
|
125
|
+
const end = def.indexOf(tag, start);
|
|
126
|
+
return end === -1 ? '' : def.slice(start, end);
|
|
127
|
+
}
|
|
128
|
+
// Normalises a function body so a hand-written definition and pg_get_functiondef's stored copy compare
|
|
129
|
+
// equal despite cosmetic reindentation: runs of whitespace collapse to a single space and the ends are
|
|
130
|
+
// trimmed. Case is preserved — a changed string literal or identifier is real drift.
|
|
131
|
+
export function normalizeFunctionBody(body) {
|
|
132
|
+
return body.replace(/\s+/g, ' ').trim();
|
|
133
|
+
}
|
|
134
|
+
// Normalises a default expression so a hand-written DDL default and information_schema.column_default
|
|
135
|
+
// compare equal: lower-cased, casts stripped ('pending'::text -> 'pending', '{}'::integer[] -> '{}'),
|
|
136
|
+
// whitespace collapsed, and any redundant outer parens removed.
|
|
137
|
+
export function normalizeDefault(expr) {
|
|
138
|
+
return stripOuterParens(expr.toLowerCase().replace(CAST_REGEX, '').replace(/\s+/g, ' ').trim());
|
|
139
|
+
}
|
|
140
|
+
// Normalises a pg_get_constraintdef string for set comparison: lower-cased, quotes and casts stripped,
|
|
141
|
+
// whitespace collapsed.
|
|
142
|
+
export function normalizeConstraintDef(def) {
|
|
143
|
+
return def.toLowerCase().replace(/"/g, '').replace(CAST_REGEX, '').replace(/\s+/g, ' ').trim();
|
|
144
|
+
}
|
|
145
|
+
// --- schema drift detection (presence level) ---
|
|
146
|
+
// Every index in the schema, with the table it belongs to and whether it is valid. indisvalid is
|
|
147
|
+
// false while an interrupted CREATE INDEX CONCURRENTLY leaves a stub behind. Catalog-only (pg_class/
|
|
148
|
+
// pg_index), so it works on CockroachDB/YugabyteDB too.
|
|
149
|
+
export function getSchemaIndexes(schema) {
|
|
150
|
+
return `
|
|
151
|
+
SELECT c.relname AS name, t.relname AS "table", i.indisvalid AS valid, pg_get_indexdef(i.indexrelid) AS def,
|
|
152
|
+
EXISTS (SELECT 1 FROM pg_constraint con WHERE con.conindid = i.indexrelid) AS "constraintBacked"
|
|
153
|
+
FROM pg_index i
|
|
154
|
+
JOIN pg_class c ON c.oid = i.indexrelid
|
|
155
|
+
JOIN pg_class t ON t.oid = i.indrelid
|
|
156
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
157
|
+
WHERE n.nspname = '${schema.replace(SINGLE_QUOTE_REGEX, "''")}'
|
|
158
|
+
`;
|
|
159
|
+
}
|
|
160
|
+
// Every function in the schema with its full definition, for the function-body diff. pg_get_functiondef
|
|
161
|
+
// returns the stored source verbatim (Postgres does not reformat a function body), so an un-drifted
|
|
162
|
+
// function's body is byte-identical to what pg-boss emits. Not supported on CockroachDB, so callers run
|
|
163
|
+
// this best-effort.
|
|
164
|
+
export function getSchemaFunctions(schema) {
|
|
165
|
+
return `
|
|
166
|
+
SELECT p.proname AS name, pg_get_functiondef(p.oid) AS def
|
|
167
|
+
FROM pg_proc p
|
|
168
|
+
JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
169
|
+
WHERE n.nspname = '${schema.replace(SINGLE_QUOTE_REGEX, "''")}'
|
|
170
|
+
`;
|
|
171
|
+
}
|
|
172
|
+
// The ordered value list of an enum type, for the enum-definition diff. ORDER BY enumsortorder
|
|
173
|
+
// preserves declaration order — reordering the enum is itself drift (the numeric base type makes
|
|
174
|
+
// created < retry < … < failed load-bearing for state comparisons).
|
|
175
|
+
export function getEnumDefinition(schema, typeName = 'job_state') {
|
|
176
|
+
return `
|
|
177
|
+
SELECT e.enumlabel AS label
|
|
178
|
+
FROM pg_enum e
|
|
179
|
+
JOIN pg_type t ON t.oid = e.enumtypid
|
|
180
|
+
JOIN pg_namespace n ON n.oid = t.typnamespace
|
|
181
|
+
WHERE n.nspname = '${schema.replace(SINGLE_QUOTE_REGEX, "''")}' AND t.typname = '${typeName}'
|
|
182
|
+
ORDER BY e.enumsortorder
|
|
183
|
+
`;
|
|
184
|
+
}
|
|
185
|
+
// Every column of every table in the schema, for the column presence / default / type / nullability
|
|
186
|
+
// diff. Uses pg_attribute + format_type so the type is the canonical SQL form (`integer`, `integer[]`,
|
|
187
|
+
// `timestamp with time zone`, `<schema>.job_state`) rather than information_schema's lossy `ARRAY` /
|
|
188
|
+
// `USER-DEFINED`; the default expression comes from pg_get_expr. relkind r/p covers ordinary and
|
|
189
|
+
// partitioned tables (partition leaves are r). Catalog-only, so it works across backends.
|
|
190
|
+
export function getSchemaColumns(schema) {
|
|
191
|
+
return `
|
|
192
|
+
SELECT c.relname AS "table", a.attname AS "column",
|
|
193
|
+
format_type(a.atttypid, a.atttypmod) AS "type",
|
|
194
|
+
a.attnotnull AS "notNull",
|
|
195
|
+
pg_get_expr(ad.adbin, ad.adrelid) AS "default"
|
|
196
|
+
FROM pg_attribute a
|
|
197
|
+
JOIN pg_class c ON c.oid = a.attrelid
|
|
198
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
199
|
+
LEFT JOIN pg_attrdef ad ON ad.adrelid = a.attrelid AND ad.adnum = a.attnum
|
|
200
|
+
WHERE n.nspname = '${schema.replace(SINGLE_QUOTE_REGEX, "''")}'
|
|
201
|
+
AND a.attnum > 0 AND NOT a.attisdropped AND c.relkind IN ('r', 'p')
|
|
202
|
+
`;
|
|
203
|
+
}
|
|
204
|
+
// Every ordinary ('r') or partitioned ('p') table in the schema, catalog-only (pg_class), for the
|
|
205
|
+
// table-presence check. Deliberately independent of getSchemaColumns: that query uses pg_get_expr,
|
|
206
|
+
// which is unsupported on some backends and is wrapped in a best-effort try/catch — deriving table
|
|
207
|
+
// presence from its (possibly empty-on-failure) result would false-report every managed table as
|
|
208
|
+
// missing whenever the column query throws. pg_class is available everywhere, so table presence stays
|
|
209
|
+
// reliable even when the column diff is skipped.
|
|
210
|
+
export function getSchemaTables(schema) {
|
|
211
|
+
return `
|
|
212
|
+
SELECT c.relname AS "table"
|
|
213
|
+
FROM pg_class c
|
|
214
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
215
|
+
WHERE n.nspname = '${schema.replace(SINGLE_QUOTE_REGEX, "''")}'
|
|
216
|
+
AND c.relkind IN ('r', 'p')
|
|
217
|
+
`;
|
|
218
|
+
}
|
|
219
|
+
// Every non-NOT-NULL constraint in the schema, with the table it belongs to and its canonical
|
|
220
|
+
// definition (pg_get_constraintdef), for the constraint-set diff. contype <> 'n' excludes NOT NULL
|
|
221
|
+
// constraints (checked at the column level instead). Catalog-only (pg_constraint), so it works across
|
|
222
|
+
// backends.
|
|
223
|
+
export function getSchemaConstraints(schema) {
|
|
224
|
+
return `
|
|
225
|
+
SELECT rel.relname AS "table", pg_get_constraintdef(con.oid) AS def
|
|
226
|
+
FROM pg_constraint con
|
|
227
|
+
JOIN pg_class rel ON rel.oid = con.conrelid
|
|
228
|
+
JOIN pg_namespace n ON n.oid = rel.relnamespace
|
|
229
|
+
WHERE n.nspname = '${schema.replace(SINGLE_QUOTE_REGEX, "''")}' AND con.contype <> 'n'
|
|
230
|
+
`;
|
|
231
|
+
}
|
|
232
|
+
// Pulls the unqualified function name out of a CREATE FUNCTION statement (schema-qualified or not).
|
|
233
|
+
export function functionName(def) {
|
|
234
|
+
const m = def.match(/CREATE\s+(?:OR\s+REPLACE\s+)?FUNCTION\s+(?:[a-z_][\w$]*\.)?"?([\w$]+)"?/i);
|
|
235
|
+
return m ? m[1] : '';
|
|
236
|
+
}
|
|
237
|
+
// Function-body diff: an expected function with no catalog entry is missing; a present one whose stored
|
|
238
|
+
// body (from pg_get_functiondef) differs from the code's emitted body is mismatched. A function whose
|
|
239
|
+
// body cannot be extracted (no dollar-quoted body found) is skipped, not flagged.
|
|
240
|
+
function computeFunctionDrift(expected, live) {
|
|
241
|
+
const liveByName = new Map(live.map(f => [f.name, f]));
|
|
242
|
+
const missingFunctions = [];
|
|
243
|
+
const mismatchedFunctions = [];
|
|
244
|
+
for (const fn of expected) {
|
|
245
|
+
const found = liveByName.get(fn.name);
|
|
246
|
+
if (!found?.def) {
|
|
247
|
+
missingFunctions.push(fn);
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
const actualBody = normalizeFunctionBody(extractFunctionBody(found.def));
|
|
251
|
+
if (actualBody && actualBody !== fn.expectedBody) {
|
|
252
|
+
mismatchedFunctions.push({ ...fn, actualBody, actualDefinition: found.def.replace(/\s+/g, ' ').trim() });
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return { missingFunctions, mismatchedFunctions };
|
|
256
|
+
}
|
|
257
|
+
// Column presence / default / type / nullability diff per managed table. A table with no live columns
|
|
258
|
+
// is skipped (it does not exist — table presence is reported separately), so a missing table never
|
|
259
|
+
// floods the report with every column. Default, type, and nullability drift are only checked for
|
|
260
|
+
// expected tables that carry the corresponding `defaults`/`types` maps (the fixed managed tables); the
|
|
261
|
+
// job/partition tables omit them and are name-only.
|
|
262
|
+
export function computeColumnDrift(expected, live) {
|
|
263
|
+
const liveByTable = new Map();
|
|
264
|
+
for (const col of live) {
|
|
265
|
+
let cols = liveByTable.get(col.table);
|
|
266
|
+
if (!cols)
|
|
267
|
+
liveByTable.set(col.table, cols = new Map());
|
|
268
|
+
cols.set(col.column.toLowerCase(), col);
|
|
269
|
+
}
|
|
270
|
+
const drift = [];
|
|
271
|
+
for (const { table, columns, defaults, types } of expected) {
|
|
272
|
+
const liveCols = liveByTable.get(table);
|
|
273
|
+
if (!liveCols || liveCols.size === 0)
|
|
274
|
+
continue;
|
|
275
|
+
const expectedSet = new Set(columns);
|
|
276
|
+
const missingColumns = columns.filter(c => !liveCols.has(c));
|
|
277
|
+
const unexpectedColumns = [...liveCols.keys()].filter(c => !expectedSet.has(c));
|
|
278
|
+
const defaultMismatches = [];
|
|
279
|
+
const typeMismatches = [];
|
|
280
|
+
const nullabilityMismatches = [];
|
|
281
|
+
for (const col of columns) {
|
|
282
|
+
const liveCol = liveCols.get(col);
|
|
283
|
+
if (!liveCol)
|
|
284
|
+
continue;
|
|
285
|
+
if (defaults && defaults[col] !== undefined) {
|
|
286
|
+
const actual = liveCol.default ?? '';
|
|
287
|
+
if (normalizeDefault(defaults[col]) !== normalizeDefault(actual)) {
|
|
288
|
+
defaultMismatches.push({ column: col, expected: defaults[col], actual });
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (types && types[col]) {
|
|
292
|
+
// Both sides are the canonical format_type() form (expected from the manifest, actual from the
|
|
293
|
+
// live catalog), so a direct comparison suffices — no alias folding needed.
|
|
294
|
+
const actualType = liveCol.type ?? '';
|
|
295
|
+
if (types[col].type !== actualType) {
|
|
296
|
+
typeMismatches.push({ column: col, expected: types[col].type, actual: actualType });
|
|
297
|
+
}
|
|
298
|
+
if (types[col].notNull !== !!liveCol.notNull) {
|
|
299
|
+
nullabilityMismatches.push({ column: col, expected: types[col].notNull, actual: !!liveCol.notNull });
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (missingColumns.length || unexpectedColumns.length || defaultMismatches.length || typeMismatches.length || nullabilityMismatches.length) {
|
|
304
|
+
drift.push({ table, missingColumns, unexpectedColumns, defaultMismatches, typeMismatches, nullabilityMismatches });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return drift;
|
|
308
|
+
}
|
|
309
|
+
// Constraint-set diff per managed table. Compares normalised pg_get_constraintdef strings as sets: an
|
|
310
|
+
// expected constraint whose normalised form is absent from the live set is missing; a live constraint
|
|
311
|
+
// whose normalised form is not expected is unexpected. A table with no live constraints at all (absent
|
|
312
|
+
// table) is skipped, so a not-yet-created table never floods the report.
|
|
313
|
+
export function computeConstraintDrift(expected, live) {
|
|
314
|
+
const liveByTable = new Map();
|
|
315
|
+
for (const { table, def } of live) {
|
|
316
|
+
let defs = liveByTable.get(table);
|
|
317
|
+
if (!defs)
|
|
318
|
+
liveByTable.set(table, defs = []);
|
|
319
|
+
defs.push(def);
|
|
320
|
+
}
|
|
321
|
+
const drift = [];
|
|
322
|
+
for (const { table, constraints } of expected) {
|
|
323
|
+
const liveDefs = liveByTable.get(table);
|
|
324
|
+
if (!liveDefs || liveDefs.length === 0)
|
|
325
|
+
continue;
|
|
326
|
+
const liveNormSet = new Set(liveDefs.map(normalizeConstraintDef));
|
|
327
|
+
const expectedNormSet = new Set(constraints.map(normalizeConstraintDef));
|
|
328
|
+
const missingConstraints = constraints.filter(c => !liveNormSet.has(normalizeConstraintDef(c)));
|
|
329
|
+
const unexpectedConstraints = liveDefs.filter(d => !expectedNormSet.has(normalizeConstraintDef(d)));
|
|
330
|
+
if (missingConstraints.length || unexpectedConstraints.length) {
|
|
331
|
+
drift.push({ table, missingConstraints, unexpectedConstraints });
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return drift;
|
|
335
|
+
}
|
|
336
|
+
// Enum diff: ordered value-set comparison. An absent enum (empty actual — pre-enum schema or a backend
|
|
337
|
+
// without enums) is not treated as drift. Order is significant; the numeric base type relies on it.
|
|
338
|
+
function computeEnumDrift(name, expected, actual) {
|
|
339
|
+
if (actual.length === 0)
|
|
340
|
+
return null;
|
|
341
|
+
const same = expected.length === actual.length && expected.every((v, i) => v === actual[i]);
|
|
342
|
+
return same ? null : { name, expectedValues: [...expected], actualValues: actual };
|
|
343
|
+
}
|
|
344
|
+
// Presence + index definition diff: which managed indexes exist, plus (for present, valid ones) a
|
|
345
|
+
// key-column-order and partial-predicate comparison. Ordinals are treated asymmetrically, the same
|
|
346
|
+
// convention test/pgSchemaHelper.ts encodes — index column ORDER is significant here (an index on
|
|
347
|
+
// (a, b) differs from (b, a)); the table-column diff instead normalises ordinal position away.
|
|
348
|
+
//
|
|
349
|
+
// Generic engine: it carries no pg-boss knowledge. Every dimension is one optional `{ expected, live }`
|
|
350
|
+
// entry — none is privileged. `indexes.building` names async builds still in progress (pulled out of
|
|
351
|
+
// "missing"); `tables.expected` is the managed table set that scopes the extra-index warning. Each
|
|
352
|
+
// dimension is best-effort — callers omit the ones a backend can't support.
|
|
353
|
+
export function computeSchemaDrift(opts = {}) {
|
|
354
|
+
const expectedIndexes = opts.indexes?.expected ?? [];
|
|
355
|
+
const liveIndexes = opts.indexes?.live ?? [];
|
|
356
|
+
const building = opts.indexes?.building ?? new Set();
|
|
357
|
+
const liveByName = new Map(liveIndexes.map(i => [i.name, i]));
|
|
358
|
+
const expectedNames = new Set(expectedIndexes.map(i => i.name));
|
|
359
|
+
const missing = [];
|
|
360
|
+
const stillBuilding = [];
|
|
361
|
+
const invalid = [];
|
|
362
|
+
const mismatched = [];
|
|
363
|
+
for (const idx of expectedIndexes) {
|
|
364
|
+
const found = liveByName.get(idx.name);
|
|
365
|
+
if (!found) {
|
|
366
|
+
(building.has(idx.name) ? stillBuilding : missing).push(idx);
|
|
367
|
+
}
|
|
368
|
+
else if (!found.valid) {
|
|
369
|
+
invalid.push({ ...idx, building: building.has(idx.name) });
|
|
370
|
+
}
|
|
371
|
+
else if (idx.keys && found.def) {
|
|
372
|
+
// Definition-diff: a present, valid index whose key columns/order or predicate differ from the
|
|
373
|
+
// expected shape. Comparison is on the normalised forms (order-significant, format-insensitive),
|
|
374
|
+
// but the report carries the readable raw text. Only when the key list parses — an unparseable
|
|
375
|
+
// def is skipped, not falsely flagged. (An empty normalised key list means we could not parse the
|
|
376
|
+
// def; '' is never a real key list, whereas an empty predicate is legitimate for a non-partial
|
|
377
|
+
// index.)
|
|
378
|
+
const actualKeys = indexKeysRaw(found.def);
|
|
379
|
+
if (normalizeKeyList(actualKeys)) {
|
|
380
|
+
const expectedPredicate = idx.predicate ?? '';
|
|
381
|
+
const actualPredicate = indexPredicateRaw(found.def);
|
|
382
|
+
const differs = [];
|
|
383
|
+
if (normalizeKeyList(idx.keys) !== normalizeKeyList(actualKeys))
|
|
384
|
+
differs.push('keys');
|
|
385
|
+
if (normalizePredicate(expectedPredicate) !== normalizePredicate(actualPredicate))
|
|
386
|
+
differs.push('predicate');
|
|
387
|
+
if (differs.length) {
|
|
388
|
+
mismatched.push({ ...idx, expectedKeys: idx.keys, actualKeys, expectedPredicate, actualPredicate, actualDefinition: displayIndexDefinition(found.def), differs });
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
// Extra indexes: standalone (non-constraint-backing) indexes on a managed table that the expected set
|
|
394
|
+
// does not account for — a stale pg-boss index or one a user added. These are informational (an extra
|
|
395
|
+
// index is harmless), so they are surfaced as a warning and do NOT flip `ok`. Scoped to managed tables
|
|
396
|
+
// so a user's indexes on their own tables in the schema are never reported.
|
|
397
|
+
const managedTables = new Set(opts.tables?.expected ?? expectedIndexes.map(i => i.table));
|
|
398
|
+
const extraIndexes = liveIndexes
|
|
399
|
+
.filter(i => managedTables.has(i.table) && !expectedNames.has(i.name) && !i.constraintBacked)
|
|
400
|
+
.map(i => ({ name: i.name, table: i.table }));
|
|
401
|
+
const liveTables = new Set(opts.tables?.live ?? []);
|
|
402
|
+
const missingTables = (opts.tables?.expected ?? []).filter(t => !liveTables.has(t));
|
|
403
|
+
const { missingFunctions, mismatchedFunctions } = computeFunctionDrift(opts.functions?.expected ?? [], opts.functions?.live ?? []);
|
|
404
|
+
const columnDrift = opts.columns ? computeColumnDrift(opts.columns.expected, opts.columns.live) : [];
|
|
405
|
+
const constraintDrift = opts.constraints ? computeConstraintDrift(opts.constraints.expected, opts.constraints.live) : [];
|
|
406
|
+
const enumDrift = opts.enum ? computeEnumDrift(opts.enum.name, opts.enum.expected, opts.enum.actual) : null;
|
|
407
|
+
return {
|
|
408
|
+
ok: missingTables.length === 0 && missing.length === 0 && invalid.length === 0 &&
|
|
409
|
+
mismatched.length === 0 && missingFunctions.length === 0 && mismatchedFunctions.length === 0 &&
|
|
410
|
+
columnDrift.length === 0 && constraintDrift.length === 0 && enumDrift === null,
|
|
411
|
+
missingTables,
|
|
412
|
+
missing,
|
|
413
|
+
building: stillBuilding,
|
|
414
|
+
invalid,
|
|
415
|
+
extraIndexes,
|
|
416
|
+
mismatched,
|
|
417
|
+
missingFunctions,
|
|
418
|
+
mismatchedFunctions,
|
|
419
|
+
columnDrift,
|
|
420
|
+
constraintDrift,
|
|
421
|
+
enumDrift
|
|
422
|
+
};
|
|
423
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -77,6 +77,7 @@ export declare class PgBoss extends EventEmitter<types.PgBossEventMap> {
|
|
|
77
77
|
clearSpies(): void;
|
|
78
78
|
isInstalled(): Promise<boolean>;
|
|
79
79
|
schemaVersion(): Promise<number | null>;
|
|
80
|
+
detectSchemaDrift(): Promise<types.SchemaDriftReport>;
|
|
80
81
|
schedule(name: string, cron: string, data?: object | null, options?: types.ScheduleOptions): Promise<void>;
|
|
81
82
|
unschedule(name: string, key?: string): Promise<void>;
|
|
82
83
|
getSchedules(name?: string, key?: string): Promise<types.Schedule[]>;
|
|
@@ -84,7 +85,7 @@ export declare class PgBoss extends EventEmitter<types.PgBossEventMap> {
|
|
|
84
85
|
getBamEntries(): Promise<types.BamEntry[]>;
|
|
85
86
|
getDb(): types.IDatabase;
|
|
86
87
|
}
|
|
87
|
-
export type { BackendProfile, BackendOptions, BamEntry, BamEvent, BamStatusSummary, CommandResponse, CompleteOptions, ConnectionOptions, ConstructorOptions, DatabaseOptions, FetchGroupConcurrencyOptions, DependencyRef, FetchOptions, FindJobsOptions, FlowJob, GroupConcurrencyConfig, GroupOptions, IDatabase as Db, InsertOptions, Job, JobFetchOptions, JobInsert, JobMatchStrategy, JobOptions, JobPollingOptions, JobResult, JobResultStatus, JobStates, Events, JobWithMetadata, MaintenanceOptions, OffWorkOptions, PgBossEventMap, Queue, QueueOptions, QueuePolicy, QueueResult, QueueStats, QueueStatsOptions, RedriveOptions, Request, Schedule, ScheduleOptions, SchedulingOptions, SendOptions, StopOptions, UpdateOptions, UpdateQueueOptions, UpdateRequest, UpdateResponse, UpsertResponse, Warning, WipData, WorkConcurrencyOptions, WorkerState, WorkHandler, WorkOptions, WorkWithMetadataHandler, WorkHandlerFor, PerJobWorkHandler, PerJobWorkWithMetadataHandler, } from './types.ts';
|
|
88
|
+
export type { BackendProfile, BackendOptions, BamEntry, BamEvent, BamStatusSummary, CommandResponse, CompleteOptions, ConnectionOptions, ConstructorOptions, DatabaseOptions, FetchGroupConcurrencyOptions, DependencyRef, FetchOptions, FindJobsOptions, FlowJob, GroupConcurrencyConfig, GroupOptions, IDatabase as Db, InsertOptions, InvalidIndex, Job, JobFetchOptions, JobInsert, JobMatchStrategy, JobOptions, JobPollingOptions, JobResult, JobResultStatus, JobStates, Events, JobWithMetadata, MaintenanceOptions, ManagedIndex, MismatchedIndex, ManagedFunction, MismatchedFunction, TableColumnDrift, ConstraintDrift, EnumDrift, OffWorkOptions, PgBossEventMap, Queue, QueueOptions, QueuePolicy, QueueResult, QueueStats, QueueStatsOptions, RedriveOptions, Request, Schedule, ScheduleOptions, SchedulingOptions, SchemaDriftReport, SendOptions, StopOptions, UpdateOptions, UpdateQueueOptions, UpdateRequest, UpdateResponse, UpsertResponse, Warning, WipData, WorkConcurrencyOptions, WorkerState, WorkHandler, WorkOptions, WorkWithMetadataHandler, WorkHandlerFor, PerJobWorkHandler, PerJobWorkWithMetadataHandler, } from './types.ts';
|
|
88
89
|
export type { JobSpyInterface, JobSpyState, JobDataSelector, JobSelector, SpyJob, } from './spy.ts';
|
|
89
90
|
export { fromKnex, fromKysely, fromDrizzle, fromPrisma, fromPglite, } from './adapters/index.ts';
|
|
90
91
|
export type { KnexTransactionLike, KyselyTransactionLike, DrizzleTransactionLike, DrizzleSqlTagLike, PrismaTransactionLike, PGliteLike, } from './adapters/index.ts';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,aAAa,CAAA;AAUtC,OAAO,KAAK,KAAK,KAAK,MAAM,YAAY,CAAA;AAGxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE/C,OAAO,EAAE,UAAU,IAAI,MAAM,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,EAAE,cAAc,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|