pg-boss 12.25.1 → 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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drifter.d.ts","sourceRoot":"","sources":["../src/drifter.ts"],"names":[],"mappings":"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"}
@@ -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';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}