@owlmeans/postgres-resource 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +219 -0
- package/agent-meta/instructions/postgres-resource.instructions.md +60 -0
- package/agent-meta/manifest.json +23 -0
- package/agent-meta/skills/postgres-resource/SKILL.md +186 -0
- package/build/consts.d.ts +81 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +86 -0
- package/build/consts.js.map +1 -0
- package/build/declarations.d.ts +12 -0
- package/build/declarations.d.ts.map +1 -0
- package/build/declarations.js +28 -0
- package/build/declarations.js.map +1 -0
- package/build/errors.d.ts +70 -0
- package/build/errors.d.ts.map +1 -0
- package/build/errors.js +201 -0
- package/build/errors.js.map +1 -0
- package/build/helper.d.ts +4 -0
- package/build/helper.d.ts.map +1 -0
- package/build/helper.js +5 -0
- package/build/helper.js.map +1 -0
- package/build/index.d.ts +8 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +7 -0
- package/build/index.js.map +1 -0
- package/build/resource.d.ts +4 -0
- package/build/resource.d.ts.map +1 -0
- package/build/resource.js +395 -0
- package/build/resource.js.map +1 -0
- package/build/types.d.ts +273 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/build/utils/criteria.d.ts +24 -0
- package/build/utils/criteria.d.ts.map +1 -0
- package/build/utils/criteria.js +209 -0
- package/build/utils/criteria.js.map +1 -0
- package/build/utils/diff.d.ts +24 -0
- package/build/utils/diff.d.ts.map +1 -0
- package/build/utils/diff.js +330 -0
- package/build/utils/diff.js.map +1 -0
- package/build/utils/index.d.ts +12 -0
- package/build/utils/index.d.ts.map +1 -0
- package/build/utils/index.js +12 -0
- package/build/utils/index.js.map +1 -0
- package/build/utils/introspect.d.ts +7 -0
- package/build/utils/introspect.d.ts.map +1 -0
- package/build/utils/introspect.js +70 -0
- package/build/utils/introspect.js.map +1 -0
- package/build/utils/life-cycle.d.ts +39 -0
- package/build/utils/life-cycle.d.ts.map +1 -0
- package/build/utils/life-cycle.js +119 -0
- package/build/utils/life-cycle.js.map +1 -0
- package/build/utils/marshal.d.ts +36 -0
- package/build/utils/marshal.d.ts.map +1 -0
- package/build/utils/marshal.js +152 -0
- package/build/utils/marshal.js.map +1 -0
- package/build/utils/migrations.d.ts +16 -0
- package/build/utils/migrations.d.ts.map +1 -0
- package/build/utils/migrations.js +108 -0
- package/build/utils/migrations.js.map +1 -0
- package/build/utils/name.d.ts +39 -0
- package/build/utils/name.d.ts.map +1 -0
- package/build/utils/name.js +63 -0
- package/build/utils/name.js.map +1 -0
- package/build/utils/schema.d.ts +28 -0
- package/build/utils/schema.d.ts.map +1 -0
- package/build/utils/schema.js +356 -0
- package/build/utils/schema.js.map +1 -0
- package/build/utils/sql.d.ts +22 -0
- package/build/utils/sql.d.ts.map +1 -0
- package/build/utils/sql.js +0 -0
- package/build/utils/sql.js.map +1 -0
- package/build/utils/sync.d.ts +21 -0
- package/build/utils/sync.d.ts.map +1 -0
- package/build/utils/sync.js +93 -0
- package/build/utils/sync.js.map +1 -0
- package/build/utils/table.d.ts +8 -0
- package/build/utils/table.d.ts.map +1 -0
- package/build/utils/table.js +68 -0
- package/build/utils/table.js.map +1 -0
- package/package.json +50 -0
- package/src/consts.ts +95 -0
- package/src/declarations.ts +41 -0
- package/src/errors.ts +242 -0
- package/src/helper.ts +7 -0
- package/src/index.ts +7 -0
- package/src/resource.ts +524 -0
- package/src/types.ts +310 -0
- package/src/utils/criteria.ts +246 -0
- package/src/utils/diff.ts +363 -0
- package/src/utils/index.ts +11 -0
- package/src/utils/introspect.ts +87 -0
- package/src/utils/life-cycle.ts +155 -0
- package/src/utils/marshal.ts +175 -0
- package/src/utils/migrations.ts +135 -0
- package/src/utils/name.ts +79 -0
- package/src/utils/schema.ts +426 -0
- package/src/utils/sql.ts +0 -0
- package/src/utils/sync.ts +106 -0
- package/src/utils/table.ts +76 -0
- package/tests/errors.spec.ts +121 -0
- package/tests/name.spec.ts +75 -0
- package/tests/schema.spec.ts +258 -0
- package/tests/sql.spec.ts +104 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import { PgIndexMethod } from '../consts.js';
|
|
2
|
+
import { PostgresPlaceholderError } from '../errors.js';
|
|
3
|
+
import { qualify, quoteIdent } from './name.js';
|
|
4
|
+
const literal = (value) => {
|
|
5
|
+
if (value === null)
|
|
6
|
+
return 'NULL';
|
|
7
|
+
if (typeof value === 'number')
|
|
8
|
+
return `${value}`;
|
|
9
|
+
if (typeof value === 'boolean')
|
|
10
|
+
return value ? 'TRUE' : 'FALSE';
|
|
11
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
12
|
+
};
|
|
13
|
+
const defaultExpression = (column) => {
|
|
14
|
+
if (column.defaultRaw != null)
|
|
15
|
+
return column.defaultRaw;
|
|
16
|
+
if (column.defaultLiteral !== undefined)
|
|
17
|
+
return literal(column.defaultLiteral);
|
|
18
|
+
return undefined;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Postgres echoes defaults back with an explicit cast — a declared `'active'` comes back
|
|
22
|
+
* as `'active'::text`. Strip a trailing cast when the literal underneath still matches, so
|
|
23
|
+
* an unchanged default doesn't look like drift on every boot.
|
|
24
|
+
*/
|
|
25
|
+
const normalizeDefault = (expression) => {
|
|
26
|
+
if (expression == null)
|
|
27
|
+
return null;
|
|
28
|
+
return expression.trim().replace(/::[a-z0-9_ ."\[\]]+$/i, '').trim().toLowerCase();
|
|
29
|
+
};
|
|
30
|
+
const normalizeDefinition = (definition) => definition.replace(/\s+/g, ' ').replace(/ ?, ?/g, ',').trim().toLowerCase();
|
|
31
|
+
const columnList = (columns) => columns.map(quoteIdent).join(', ');
|
|
32
|
+
const indexStatement = (spec, entry) => {
|
|
33
|
+
const target = entry.expression != null
|
|
34
|
+
? `(${entry.expression})`
|
|
35
|
+
: `(${columnList(entry.columns)})`;
|
|
36
|
+
const where = entry.where != null ? ` WHERE ${entry.where}` : '';
|
|
37
|
+
return `CREATE ${entry.unique === true ? 'UNIQUE ' : ''}INDEX ${quoteIdent(entry.name)}`
|
|
38
|
+
+ ` ON ${spec.qualified} USING ${entry.method ?? PgIndexMethod.BTree} ${target}${where}`;
|
|
39
|
+
};
|
|
40
|
+
const columnDefinition = (column) => {
|
|
41
|
+
const parts = [quoteIdent(column.column), column.sqlType];
|
|
42
|
+
if (column.notNull)
|
|
43
|
+
parts.push('NOT NULL');
|
|
44
|
+
const expression = defaultExpression(column);
|
|
45
|
+
if (expression != null)
|
|
46
|
+
parts.push(`DEFAULT ${expression}`);
|
|
47
|
+
return parts.join(' ');
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Foreign keys are planned separately from the rest of the table, and applied only once
|
|
51
|
+
* every resource has initialized: a key points at a table another resource owns, and that
|
|
52
|
+
* resource's own `init()` may not have run yet.
|
|
53
|
+
*
|
|
54
|
+
* @throws {PostgresPlaceholderError} when a target can't be resolved.
|
|
55
|
+
*/
|
|
56
|
+
export const planForeignKeys = (spec, context) => spec.references.map(reference => {
|
|
57
|
+
const column = reference.property != null ? spec.byProperty[reference.property] : undefined;
|
|
58
|
+
if (column == null) {
|
|
59
|
+
throw new PostgresPlaceholderError(`fk-unknown-property:${reference.property}`);
|
|
60
|
+
}
|
|
61
|
+
let targetSchema = reference.schema ?? spec.schema;
|
|
62
|
+
let targetTable = reference.table;
|
|
63
|
+
if (reference.resource != null) {
|
|
64
|
+
if (context == null) {
|
|
65
|
+
throw new PostgresPlaceholderError(`fk-no-context:${reference.resource}`);
|
|
66
|
+
}
|
|
67
|
+
let target;
|
|
68
|
+
try {
|
|
69
|
+
target = context.resource(reference.resource);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
throw new PostgresPlaceholderError(`fk-unknown-resource:${reference.resource}`);
|
|
73
|
+
}
|
|
74
|
+
if (target.table == null) {
|
|
75
|
+
throw new PostgresPlaceholderError(`fk-uninitialized:${reference.resource}`);
|
|
76
|
+
}
|
|
77
|
+
targetSchema = target.table.schema;
|
|
78
|
+
targetTable = target.table.table;
|
|
79
|
+
}
|
|
80
|
+
if (targetTable == null) {
|
|
81
|
+
throw new PostgresPlaceholderError(`fk-no-target:${reference.property}`);
|
|
82
|
+
}
|
|
83
|
+
const actions = [
|
|
84
|
+
reference.onDelete != null ? ` ON DELETE ${reference.onDelete}` : '',
|
|
85
|
+
reference.onUpdate != null ? ` ON UPDATE ${reference.onUpdate}` : ''
|
|
86
|
+
].join('');
|
|
87
|
+
return {
|
|
88
|
+
kind: 'add-foreign-key',
|
|
89
|
+
target: reference.name,
|
|
90
|
+
sql: `ALTER TABLE ${spec.qualified} ADD CONSTRAINT ${quoteIdent(reference.name)}`
|
|
91
|
+
+ ` FOREIGN KEY (${quoteIdent(column.column)})`
|
|
92
|
+
+ ` REFERENCES ${qualify(targetSchema, targetTable)} (${quoteIdent(reference.column)})${actions}`
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
/**
|
|
96
|
+
* Compare the compiled specification against the live table and produce the ordered DDL
|
|
97
|
+
* that converges one onto the other.
|
|
98
|
+
*
|
|
99
|
+
* Statement order is load bearing:
|
|
100
|
+
* - `DROP COLUMN` is last, because a `USING` cast or a backfill may legitimately read a
|
|
101
|
+
* column that is about to disappear.
|
|
102
|
+
* - A primary key constraint is never dropped: it cascades into every referencing key and
|
|
103
|
+
* can't be undone inside the same transaction once dependents exist.
|
|
104
|
+
*
|
|
105
|
+
* Foreign keys are not part of the plan at all — see {@link planForeignKeys}.
|
|
106
|
+
*/
|
|
107
|
+
export const planSync = (spec, live, additive = false) => {
|
|
108
|
+
if (!live.exists) {
|
|
109
|
+
const constraints = [];
|
|
110
|
+
if (spec.primaryKey.length > 0) {
|
|
111
|
+
constraints.push(`CONSTRAINT ${quoteIdent(`${spec.table}_pkey`)} PRIMARY KEY (${columnList(spec.primaryKey)})`);
|
|
112
|
+
}
|
|
113
|
+
for (const unique of spec.uniques) {
|
|
114
|
+
constraints.push(`CONSTRAINT ${quoteIdent(unique.name)} UNIQUE (${columnList(unique.columns)})`);
|
|
115
|
+
}
|
|
116
|
+
for (const check of spec.checks) {
|
|
117
|
+
constraints.push(`CONSTRAINT ${quoteIdent(check.name)} CHECK (${check.expression})`);
|
|
118
|
+
}
|
|
119
|
+
const statements = [{
|
|
120
|
+
kind: 'create-table',
|
|
121
|
+
target: spec.table,
|
|
122
|
+
sql: `CREATE TABLE ${spec.qualified} (\n `
|
|
123
|
+
+ [...spec.columns.map(columnDefinition), ...constraints].join(',\n ')
|
|
124
|
+
+ '\n)'
|
|
125
|
+
}];
|
|
126
|
+
for (const entry of spec.indexes) {
|
|
127
|
+
statements.push({ kind: 'create-index', target: entry.name, sql: indexStatement(spec, entry) });
|
|
128
|
+
}
|
|
129
|
+
return { fresh: true, statements };
|
|
130
|
+
}
|
|
131
|
+
const statements = [];
|
|
132
|
+
const byName = {};
|
|
133
|
+
for (const column of live.columns) {
|
|
134
|
+
byName[column.name] = column;
|
|
135
|
+
}
|
|
136
|
+
const managed = spec.columns.filter(column => column.managed);
|
|
137
|
+
/** 1. Columns the table doesn't have yet — always added nullable so existing rows survive. */
|
|
138
|
+
for (const column of managed) {
|
|
139
|
+
if (byName[column.column] != null) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const expression = defaultExpression(column);
|
|
143
|
+
statements.push({
|
|
144
|
+
kind: 'add-column',
|
|
145
|
+
target: column.column,
|
|
146
|
+
sql: `ALTER TABLE ${spec.qualified} ADD COLUMN ${quoteIdent(column.column)} ${column.sqlType}`
|
|
147
|
+
+ (expression != null ? ` DEFAULT ${expression}` : '')
|
|
148
|
+
});
|
|
149
|
+
if (column.notNull) {
|
|
150
|
+
if (expression == null) {
|
|
151
|
+
statements.push({
|
|
152
|
+
kind: 'backfill',
|
|
153
|
+
target: column.column,
|
|
154
|
+
sql: `UPDATE ${spec.qualified} SET ${quoteIdent(column.column)} = ${fallback(column)}`
|
|
155
|
+
+ ` WHERE ${quoteIdent(column.column)} IS NULL`
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
statements.push({
|
|
159
|
+
kind: 'set-not-null',
|
|
160
|
+
target: column.column,
|
|
161
|
+
sql: `ALTER TABLE ${spec.qualified} ALTER COLUMN ${quoteIdent(column.column)} SET NOT NULL`
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/** 2-4. Type, nullability and default drift on columns that already exist. */
|
|
166
|
+
for (const column of managed) {
|
|
167
|
+
const existing = byName[column.column];
|
|
168
|
+
if (existing == null) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (!additive && existing.type !== column.sqlType) {
|
|
172
|
+
const using = column.using ?? `${quoteIdent(column.column)}::${column.sqlType}`;
|
|
173
|
+
statements.push({
|
|
174
|
+
kind: 'alter-type',
|
|
175
|
+
target: column.column,
|
|
176
|
+
sql: `ALTER TABLE ${spec.qualified} ALTER COLUMN ${quoteIdent(column.column)}`
|
|
177
|
+
+ ` TYPE ${column.sqlType} USING ${using}`
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
const expression = defaultExpression(column);
|
|
181
|
+
if (normalizeDefault(expression) !== normalizeDefault(existing.defaultExpr)) {
|
|
182
|
+
statements.push(expression != null
|
|
183
|
+
? {
|
|
184
|
+
kind: 'set-default',
|
|
185
|
+
target: column.column,
|
|
186
|
+
sql: `ALTER TABLE ${spec.qualified} ALTER COLUMN ${quoteIdent(column.column)}`
|
|
187
|
+
+ ` SET DEFAULT ${expression}`
|
|
188
|
+
}
|
|
189
|
+
: {
|
|
190
|
+
kind: 'set-default',
|
|
191
|
+
target: column.column,
|
|
192
|
+
sql: `ALTER TABLE ${spec.qualified} ALTER COLUMN ${quoteIdent(column.column)} DROP DEFAULT`
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
if (column.notNull !== existing.notNull) {
|
|
196
|
+
if (column.notNull) {
|
|
197
|
+
statements.push({
|
|
198
|
+
kind: 'backfill',
|
|
199
|
+
target: column.column,
|
|
200
|
+
sql: `UPDATE ${spec.qualified} SET ${quoteIdent(column.column)}`
|
|
201
|
+
+ ` = ${expression ?? fallback(column)} WHERE ${quoteIdent(column.column)} IS NULL`
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
statements.push({
|
|
205
|
+
kind: column.notNull ? 'set-not-null' : 'drop-not-null',
|
|
206
|
+
target: column.column,
|
|
207
|
+
sql: `ALTER TABLE ${spec.qualified} ALTER COLUMN ${quoteIdent(column.column)}`
|
|
208
|
+
+ ` ${column.notNull ? 'SET' : 'DROP'} NOT NULL`
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/** 5. Unique and check constraints. Primary keys are deliberately excluded. */
|
|
213
|
+
const desiredConstraints = {};
|
|
214
|
+
for (const unique of spec.uniques) {
|
|
215
|
+
desiredConstraints[unique.name] = `UNIQUE (${columnList(unique.columns)})`;
|
|
216
|
+
}
|
|
217
|
+
for (const check of spec.checks) {
|
|
218
|
+
desiredConstraints[check.name] = `CHECK ((${check.expression}))`;
|
|
219
|
+
}
|
|
220
|
+
const liveConstraints = {};
|
|
221
|
+
for (const constraint of live.constraints) {
|
|
222
|
+
if (constraint.type === 'p' || constraint.type === 'f') {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
liveConstraints[constraint.name] = constraint.definition;
|
|
226
|
+
}
|
|
227
|
+
for (const [name, definition] of Object.entries(liveConstraints)) {
|
|
228
|
+
const desired = desiredConstraints[name];
|
|
229
|
+
if (desired != null && normalizeDefinition(desired) === normalizeDefinition(definition)) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
if (desired == null && additive) {
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
if (desired == null && !isGenerated(name, spec)) {
|
|
236
|
+
/** A constraint nobody declared was added by hand — leave it alone. */
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
statements.push({
|
|
240
|
+
kind: 'drop-constraint',
|
|
241
|
+
target: name,
|
|
242
|
+
sql: `ALTER TABLE ${spec.qualified} DROP CONSTRAINT ${quoteIdent(name)}`
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
for (const [name, definition] of Object.entries(desiredConstraints)) {
|
|
246
|
+
const existing = liveConstraints[name];
|
|
247
|
+
if (existing != null && normalizeDefinition(existing) === normalizeDefinition(definition)) {
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
if (existing != null && additive) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
statements.push({
|
|
254
|
+
kind: 'add-constraint',
|
|
255
|
+
target: name,
|
|
256
|
+
sql: `ALTER TABLE ${spec.qualified} ADD CONSTRAINT ${quoteIdent(name)} ${definition}`
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
/** 6. Indexes. Constraint backed indexes are owned by their constraint, not by us. */
|
|
260
|
+
const constraintBacked = live.constraints.map(constraint => constraint.name);
|
|
261
|
+
const desiredIndexes = {};
|
|
262
|
+
for (const entry of spec.indexes) {
|
|
263
|
+
desiredIndexes[entry.name] = indexStatement(spec, entry);
|
|
264
|
+
}
|
|
265
|
+
for (const existing of live.indexes) {
|
|
266
|
+
if (constraintBacked.includes(existing.name)) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const desired = desiredIndexes[existing.name];
|
|
270
|
+
if (desired != null && normalizeDefinition(desired) === normalizeDefinition(existing.definition)) {
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
if (desired == null && (additive || !isGenerated(existing.name, spec))) {
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
statements.push({
|
|
277
|
+
kind: 'drop-index',
|
|
278
|
+
target: existing.name,
|
|
279
|
+
sql: `DROP INDEX ${qualify(spec.schema, existing.name)}`
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
for (const [name, statement] of Object.entries(desiredIndexes)) {
|
|
283
|
+
const existing = live.indexes.find(entry => entry.name === name);
|
|
284
|
+
if (existing != null && normalizeDefinition(existing.definition) === normalizeDefinition(statement)) {
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
if (constraintBacked.includes(name)) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
statements.push({ kind: 'create-index', target: name, sql: statement });
|
|
291
|
+
}
|
|
292
|
+
/** 7. Drops, last and only in full mode. */
|
|
293
|
+
if (!additive) {
|
|
294
|
+
const keep = [...managed.map(column => column.column), ...spec.unmanaged];
|
|
295
|
+
for (const existing of live.columns) {
|
|
296
|
+
if (keep.includes(existing.name) || existing.generated !== '') {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
statements.push({
|
|
300
|
+
kind: 'drop-column',
|
|
301
|
+
target: existing.name,
|
|
302
|
+
destructive: true,
|
|
303
|
+
sql: `ALTER TABLE ${spec.qualified} DROP COLUMN ${quoteIdent(existing.name)}`
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return { fresh: false, statements };
|
|
308
|
+
};
|
|
309
|
+
/** A name this package would have generated is a name this package may drop. */
|
|
310
|
+
const isGenerated = (name, spec) => name.startsWith(`${spec.table}_`);
|
|
311
|
+
/** Value used to fill an existing row before a column becomes `NOT NULL`. */
|
|
312
|
+
const fallback = (column) => {
|
|
313
|
+
if (column.array)
|
|
314
|
+
return `'{}'::${column.sqlType}`;
|
|
315
|
+
if (column.jsonb)
|
|
316
|
+
return `'{}'::jsonb`;
|
|
317
|
+
switch (column.jsonType) {
|
|
318
|
+
case 'number':
|
|
319
|
+
case 'integer':
|
|
320
|
+
case 'bigint':
|
|
321
|
+
return '0';
|
|
322
|
+
case 'boolean':
|
|
323
|
+
return 'FALSE';
|
|
324
|
+
case 'date':
|
|
325
|
+
return 'now()';
|
|
326
|
+
default:
|
|
327
|
+
return `''::${column.sqlType}`;
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/utils/diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './criteria.js';
|
|
2
|
+
export * from './diff.js';
|
|
3
|
+
export * from './introspect.js';
|
|
4
|
+
export * from './life-cycle.js';
|
|
5
|
+
export * from './marshal.js';
|
|
6
|
+
export * from './migrations.js';
|
|
7
|
+
export * from './name.js';
|
|
8
|
+
export * from './schema.js';
|
|
9
|
+
export * from './sql.js';
|
|
10
|
+
export * from './sync.js';
|
|
11
|
+
export * from './table.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './criteria.js';
|
|
2
|
+
export * from './diff.js';
|
|
3
|
+
export * from './introspect.js';
|
|
4
|
+
export * from './life-cycle.js';
|
|
5
|
+
export * from './marshal.js';
|
|
6
|
+
export * from './migrations.js';
|
|
7
|
+
export * from './name.js';
|
|
8
|
+
export * from './schema.js';
|
|
9
|
+
export * from './sql.js';
|
|
10
|
+
export * from './sync.js';
|
|
11
|
+
export * from './table.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PoolClient } from 'pg';
|
|
2
|
+
import type { LiveTable } from '../types.js';
|
|
3
|
+
/** Read the table exactly as Postgres currently holds it. */
|
|
4
|
+
export declare const introspectTable: (client: PoolClient, schema: string, table: string, qualified: string) => Promise<LiveTable>;
|
|
5
|
+
/** Count the rows a destructive step would lose, so the boot log can say how much. */
|
|
6
|
+
export declare const countNonNull: (client: PoolClient, qualified: string, column: string) => Promise<number>;
|
|
7
|
+
//# sourceMappingURL=introspect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"introspect.d.ts","sourceRoot":"","sources":["../../src/utils/introspect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,IAAI,CAAA;AAEpC,OAAO,KAAK,EAAyC,SAAS,EAAE,MAAM,aAAa,CAAA;AAkCnF,6DAA6D;AAC7D,eAAO,MAAM,eAAe,GAC1B,QAAQ,UAAU,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,EAAE,WAAW,MAAM,KACnE,OAAO,CAAC,SAAS,CA+BnB,CAAA;AAED,sFAAsF;AACtF,eAAO,MAAM,YAAY,GACvB,QAAQ,UAAU,EAAE,WAAW,MAAM,EAAE,QAAQ,MAAM,KACpD,OAAO,CAAC,MAAM,CAWhB,CAAA"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `pg_attribute` + `format_type` rather than `information_schema.columns`, because it
|
|
3
|
+
* returns one canonical type string with the typmod already baked in
|
|
4
|
+
* (`character varying(320)`). `information_schema` splits the same information across
|
|
5
|
+
* four columns and reports every array as `ARRAY`, which no comparison can use.
|
|
6
|
+
*/
|
|
7
|
+
const COLUMNS = `
|
|
8
|
+
SELECT a.attname AS name,
|
|
9
|
+
format_type(a.atttypid, a.atttypmod) AS type,
|
|
10
|
+
a.attnotnull AS not_null,
|
|
11
|
+
pg_get_expr(d.adbin, d.adrelid) AS default_expr,
|
|
12
|
+
a.attidentity AS identity,
|
|
13
|
+
a.attgenerated AS generated,
|
|
14
|
+
a.attnum AS ordinal
|
|
15
|
+
FROM pg_attribute a
|
|
16
|
+
LEFT JOIN pg_attrdef d ON d.adrelid = a.attrelid AND d.adnum = a.attnum
|
|
17
|
+
WHERE a.attrelid = to_regclass($1) AND a.attnum > 0 AND NOT a.attisdropped
|
|
18
|
+
ORDER BY a.attnum
|
|
19
|
+
`;
|
|
20
|
+
const INDEXES = `
|
|
21
|
+
SELECT indexname AS name, indexdef AS definition
|
|
22
|
+
FROM pg_indexes
|
|
23
|
+
WHERE schemaname = $1 AND tablename = $2
|
|
24
|
+
`;
|
|
25
|
+
const CONSTRAINTS = `
|
|
26
|
+
SELECT c.conname AS name, c.contype AS type, pg_get_constraintdef(c.oid) AS definition
|
|
27
|
+
FROM pg_constraint c
|
|
28
|
+
WHERE c.conrelid = to_regclass($1)
|
|
29
|
+
`;
|
|
30
|
+
/** Read the table exactly as Postgres currently holds it. */
|
|
31
|
+
export const introspectTable = async (client, schema, table, qualified) => {
|
|
32
|
+
const exists = await client.query('SELECT to_regclass($1) IS NOT NULL AS present', [qualified]);
|
|
33
|
+
if (exists.rows[0]?.present !== true) {
|
|
34
|
+
return { exists: false, columns: [], indexes: [], constraints: [] };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Sequential, not `Promise.all`: this is one checked out connection, and a connection
|
|
38
|
+
* runs one statement at a time. Overlapping them only queues them behind each other —
|
|
39
|
+
* and node-postgres deprecated tolerating it.
|
|
40
|
+
*/
|
|
41
|
+
const columns = await client.query(COLUMNS, [qualified]);
|
|
42
|
+
const indexes = await client.query(INDEXES, [schema, table]);
|
|
43
|
+
const constraints = await client.query(CONSTRAINTS, [qualified]);
|
|
44
|
+
return {
|
|
45
|
+
exists: true,
|
|
46
|
+
columns: columns.rows.map(row => ({
|
|
47
|
+
name: row.name,
|
|
48
|
+
type: row.type,
|
|
49
|
+
notNull: row.not_null,
|
|
50
|
+
defaultExpr: row.default_expr,
|
|
51
|
+
identity: row.identity ?? '',
|
|
52
|
+
generated: row.generated ?? '',
|
|
53
|
+
ordinal: row.ordinal
|
|
54
|
+
})),
|
|
55
|
+
indexes: indexes.rows,
|
|
56
|
+
constraints: constraints.rows
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
/** Count the rows a destructive step would lose, so the boot log can say how much. */
|
|
60
|
+
export const countNonNull = async (client, qualified, column) => {
|
|
61
|
+
try {
|
|
62
|
+
const result = await client.query(`SELECT count(*)::text AS count FROM ${qualified} WHERE "${column.replace(/"/g, '""')}" IS NOT NULL`);
|
|
63
|
+
return parseInt(result.rows[0]?.count ?? '0', 10);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
/** Never let a diagnostic read break reconciliation. */
|
|
67
|
+
return -1;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=introspect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"introspect.js","sourceRoot":"","sources":["../../src/utils/introspect.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,MAAM,OAAO,GAAG;;;;;;;;;;;;CAYf,CAAA;AAED,MAAM,OAAO,GAAG;;;;CAIf,CAAA;AAED,MAAM,WAAW,GAAG;;;;CAInB,CAAA;AAED,6DAA6D;AAC7D,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAClC,MAAkB,EAAE,MAAc,EAAE,KAAa,EAAE,SAAiB,EAChD,EAAE;IACtB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAC/B,+CAA+C,EAAE,CAAC,SAAS,CAAC,CAC7D,CAAA;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;QACrC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAA;IACrE,CAAC;IAED;;;;OAIG;IACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,CAAa,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC,CAAA;IACpE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,CAAY,OAAO,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAA;IACvE,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,KAAK,CAAiB,WAAW,EAAE,CAAC,SAAS,CAAC,CAAC,CAAA;IAEhF,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChC,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,OAAO,EAAG,GAAwC,CAAC,QAAQ;YAC3D,WAAW,EAAG,GAAkD,CAAC,YAAY;YAC7E,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE;YAC5B,SAAS,EAAE,GAAG,CAAC,SAAS,IAAI,EAAE;YAC9B,OAAO,EAAE,GAAG,CAAC,OAAO;SACrB,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,CAAC,IAAI;QACrB,WAAW,EAAE,WAAW,CAAC,IAAI;KAC9B,CAAA;AACH,CAAC,CAAA;AAED,sFAAsF;AACtF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,MAAkB,EAAE,SAAiB,EAAE,MAAc,EACpC,EAAE;IACnB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAC/B,uCAAuC,SAAS,WAAW,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,eAAe,CACrG,CAAA;QAED,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,GAAG,EAAE,EAAE,CAAC,CAAA;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,wDAAwD;QACxD,OAAO,CAAC,CAAC,CAAA;IACX,CAAC;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { BasicContext } from '@owlmeans/context';
|
|
2
|
+
import type { DbConfig, MigrationReport, ResourceRecord } from '@owlmeans/resource';
|
|
3
|
+
import type { PgRuntimeTable, PostgresDb, PostgresResource, TableSpec } from '../types.js';
|
|
4
|
+
export interface TableInit {
|
|
5
|
+
spec: TableSpec;
|
|
6
|
+
/** The Drizzle table CRUD is built against. */
|
|
7
|
+
entity: PgRuntimeTable;
|
|
8
|
+
reports: MigrationReport[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Bring a resource's table to the shape its schema declares, then hand back everything the
|
|
12
|
+
* resource needs to query it. The Postgres counterpart of mongo's `initializeCollection`.
|
|
13
|
+
*
|
|
14
|
+
* The whole sequence runs inside a session level advisory lock keyed on the qualified table
|
|
15
|
+
* name, so replicas booting simultaneously converge one at a time instead of racing each
|
|
16
|
+
* other's DDL — a race mongo's converge-on-boot leaves open.
|
|
17
|
+
*
|
|
18
|
+
* Order is deliberate:
|
|
19
|
+
*
|
|
20
|
+
* 1. probe for the table
|
|
21
|
+
* 2. absent → *baseline* every registered migration; present → run the `pre` ones
|
|
22
|
+
* 3. reconcile structure against the schema
|
|
23
|
+
* 4. present → run the `post` migrations
|
|
24
|
+
* 5. queue foreign keys for after every resource has initialized
|
|
25
|
+
*
|
|
26
|
+
* Step 2 is what stops the two mechanisms colliding. On a fresh deployment the table is
|
|
27
|
+
* created directly to its final shape, so migrations that would have produced that shape
|
|
28
|
+
* are recorded as satisfied rather than replayed against a table that already matches.
|
|
29
|
+
*/
|
|
30
|
+
export declare const initializeTable: (db: PostgresDb, config: DbConfig, resource: PostgresResource<ResourceRecord>, context: BasicContext<any>, defer: (task: () => Promise<void>) => void) => Promise<TableInit>;
|
|
31
|
+
/**
|
|
32
|
+
* Add the foreign keys the schema declares, skipping any Postgres already holds.
|
|
33
|
+
*
|
|
34
|
+
* Constraints are compared by name only. A key whose *definition* drifted has to be dropped
|
|
35
|
+
* by hand or in a migration: `ALTER TABLE ... DROP CONSTRAINT` on a foreign key is not a
|
|
36
|
+
* change worth making on a boot nobody is watching.
|
|
37
|
+
*/
|
|
38
|
+
export declare const applyForeignKeys: (db: PostgresDb, spec: TableSpec, context: BasicContext<any>) => Promise<void>;
|
|
39
|
+
//# sourceMappingURL=life-cycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"life-cycle.d.ts","sourceRoot":"","sources":["../../src/utils/life-cycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAMnF,OAAO,KAAK,EACV,cAAc,EAAE,UAAU,EAAgB,gBAAgB,EAAE,SAAS,EACtE,MAAM,aAAa,CAAA;AAUpB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,SAAS,CAAA;IACf,+CAA+C;IAC/C,MAAM,EAAE,cAAc,CAAA;IACtB,OAAO,EAAE,eAAe,EAAE,CAAA;CAC3B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,eAAe,GAC1B,IAAI,UAAU,EAAE,QAAQ,QAAQ,EAAE,UAAU,gBAAgB,CAAC,cAAc,CAAC,EAC5E,SAAS,YAAY,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,KACrE,OAAO,CAAC,SAAS,CA0DnB,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAC3B,IAAI,UAAU,EAAE,MAAM,SAAS,EAAE,SAAS,YAAY,CAAC,GAAG,CAAC,KAC1D,OAAO,CAAC,IAAI,CAmBd,CAAA"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { MigrationStage, runMigrations } from '@owlmeans/resource';
|
|
2
|
+
import { DEF_MIGRATIONS_TABLE, PgAutoSync } from '../consts.js';
|
|
3
|
+
import { getDeclaration } from '../declarations.js';
|
|
4
|
+
import { describePgError, pgErrorToResourceError } from '../errors.js';
|
|
5
|
+
import { planForeignKeys, planSync } from './diff.js';
|
|
6
|
+
import { introspectTable } from './introspect.js';
|
|
7
|
+
import { makeMigrationStore } from './migrations.js';
|
|
8
|
+
import { pgTableName } from './name.js';
|
|
9
|
+
import { schemaToTableSpec } from './schema.js';
|
|
10
|
+
import { refOf, resolvePlaceholders } from './sql.js';
|
|
11
|
+
import { acquireLock, applyPlan, ensureSchema, releaseLock } from './sync.js';
|
|
12
|
+
import { specToTable } from './table.js';
|
|
13
|
+
/**
|
|
14
|
+
* Bring a resource's table to the shape its schema declares, then hand back everything the
|
|
15
|
+
* resource needs to query it. The Postgres counterpart of mongo's `initializeCollection`.
|
|
16
|
+
*
|
|
17
|
+
* The whole sequence runs inside a session level advisory lock keyed on the qualified table
|
|
18
|
+
* name, so replicas booting simultaneously converge one at a time instead of racing each
|
|
19
|
+
* other's DDL — a race mongo's converge-on-boot leaves open.
|
|
20
|
+
*
|
|
21
|
+
* Order is deliberate:
|
|
22
|
+
*
|
|
23
|
+
* 1. probe for the table
|
|
24
|
+
* 2. absent → *baseline* every registered migration; present → run the `pre` ones
|
|
25
|
+
* 3. reconcile structure against the schema
|
|
26
|
+
* 4. present → run the `post` migrations
|
|
27
|
+
* 5. queue foreign keys for after every resource has initialized
|
|
28
|
+
*
|
|
29
|
+
* Step 2 is what stops the two mechanisms colliding. On a fresh deployment the table is
|
|
30
|
+
* created directly to its final shape, so migrations that would have produced that shape
|
|
31
|
+
* are recorded as satisfied rather than replayed against a table that already matches.
|
|
32
|
+
*/
|
|
33
|
+
export const initializeTable = async (db, config, resource, context, defer) => {
|
|
34
|
+
const declaration = getDeclaration(resource.alias);
|
|
35
|
+
const meta = (config.meta ?? {});
|
|
36
|
+
const mode = meta.autoSync ?? PgAutoSync.Full;
|
|
37
|
+
const spec = schemaToTableSpec(resource.alias, resource.schema ?? declaration.schema, db.schema, pgTableName(config, resource), mode !== PgAutoSync.Off, declaration.indexes);
|
|
38
|
+
const entity = specToTable(spec);
|
|
39
|
+
const reports = [];
|
|
40
|
+
const client = await db.pool.connect();
|
|
41
|
+
try {
|
|
42
|
+
await acquireLock(client, spec.qualified);
|
|
43
|
+
await ensureSchema(client, spec.schema);
|
|
44
|
+
const resolve = (text) => resolvePlaceholders(text, context, spec);
|
|
45
|
+
const ref = (alias) => refOf(context, spec, alias);
|
|
46
|
+
const store = makeMigrationStore(client, spec, DEF_MIGRATIONS_TABLE, resolve, ref);
|
|
47
|
+
const fresh = !(await introspectTable(client, spec.schema, spec.table, spec.qualified)).exists;
|
|
48
|
+
reports.push(await runMigrations(resource.alias, declaration.migrations, store, fresh
|
|
49
|
+
? { baseline: true }
|
|
50
|
+
: { stage: MigrationStage.Pre }));
|
|
51
|
+
if (spec.autoSync) {
|
|
52
|
+
/** Re-read: a `pre` migration may have reshaped exactly what the diff is about to compare. */
|
|
53
|
+
const live = await introspectTable(client, spec.schema, spec.table, spec.qualified);
|
|
54
|
+
const plan = planSync(spec, live, mode === PgAutoSync.Additive);
|
|
55
|
+
await applyPlan(client, spec, plan);
|
|
56
|
+
}
|
|
57
|
+
if (!fresh) {
|
|
58
|
+
reports.push(await runMigrations(resource.alias, declaration.migrations, store, { stage: MigrationStage.Post }));
|
|
59
|
+
}
|
|
60
|
+
for (const report of reports) {
|
|
61
|
+
if (report.applied.length > 0) {
|
|
62
|
+
console.log(`@owlmeans/postgres-resource: ${spec.qualified} applied ${report.stage} migrations —`
|
|
63
|
+
+ ` ${report.applied.join(', ')}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
await releaseLock(client, spec.qualified);
|
|
69
|
+
client.release();
|
|
70
|
+
}
|
|
71
|
+
if (spec.references.length > 0) {
|
|
72
|
+
defer(async () => { await applyForeignKeys(db, spec, context); });
|
|
73
|
+
}
|
|
74
|
+
return { spec, entity, reports };
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Add the foreign keys the schema declares, skipping any Postgres already holds.
|
|
78
|
+
*
|
|
79
|
+
* Constraints are compared by name only. A key whose *definition* drifted has to be dropped
|
|
80
|
+
* by hand or in a migration: `ALTER TABLE ... DROP CONSTRAINT` on a foreign key is not a
|
|
81
|
+
* change worth making on a boot nobody is watching.
|
|
82
|
+
*/
|
|
83
|
+
export const applyForeignKeys = async (db, spec, context) => {
|
|
84
|
+
const client = await db.pool.connect();
|
|
85
|
+
try {
|
|
86
|
+
const statements = planForeignKeys(spec, context);
|
|
87
|
+
const live = await introspectTable(client, spec.schema, spec.table, spec.qualified);
|
|
88
|
+
if (!live.exists) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const present = live.constraints.map(constraint => constraint.name);
|
|
92
|
+
for (const statement of statements) {
|
|
93
|
+
if (present.includes(statement.target)) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
await apply(client, spec, statement.sql);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
client.release();
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const apply = async (client, spec, statement) => {
|
|
104
|
+
try {
|
|
105
|
+
await client.query(statement);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
const translated = pgErrorToResourceError(error);
|
|
109
|
+
/**
|
|
110
|
+
* A foreign key failing means live rows point at nothing. That's a data problem the
|
|
111
|
+
* boot can't fix, and refusing to start is better than starting with the constraint
|
|
112
|
+
* quietly missing.
|
|
113
|
+
*/
|
|
114
|
+
throw Object.assign(translated, {
|
|
115
|
+
message: `${spec.qualified}: ${describePgError(error)} — statement: ${statement}`
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
//# sourceMappingURL=life-cycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"life-cycle.js","sourceRoot":"","sources":["../../src/utils/life-cycle.ts"],"names":[],"mappings":"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"}
|