tempest-db-js 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/bin.cjs +429 -42
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +2 -2
- package/dist/{chunk-QMW4NKMH.js → chunk-43XL66JG.js} +546 -43
- package/dist/chunk-43XL66JG.js.map +1 -0
- package/dist/{chunk-AGDD7K3F.js → chunk-JR4MLFQN.js} +217 -22
- package/dist/chunk-JR4MLFQN.js.map +1 -0
- package/dist/index.cjs +217 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +129 -8
- package/dist/index.d.ts +129 -8
- package/dist/index.js +1 -1
- package/dist/migrations/index.cjs +597 -44
- package/dist/migrations/index.cjs.map +1 -1
- package/dist/migrations/index.d.cts +91 -15
- package/dist/migrations/index.d.ts +91 -15
- package/dist/migrations/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-AGDD7K3F.js.map +0 -1
- package/dist/chunk-QMW4NKMH.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { columnsOf } from './chunk-
|
|
1
|
+
import { columnsOf } from './chunk-JR4MLFQN.js';
|
|
2
2
|
|
|
3
3
|
// src/migrations/operations.ts
|
|
4
4
|
var IrreversibleMigration = class extends Error {
|
|
@@ -31,6 +31,10 @@ function invert(op) {
|
|
|
31
31
|
return { kind: "rename_column", table: op.table, from: op.to, to: op.from };
|
|
32
32
|
case "recreate_table":
|
|
33
33
|
return { kind: "recreate_table", from: op.to, to: op.from };
|
|
34
|
+
case "add_constraint":
|
|
35
|
+
return { kind: "drop_constraint", table: op.table, constraint: op.constraint };
|
|
36
|
+
case "drop_constraint":
|
|
37
|
+
return { kind: "add_constraint", table: op.table, constraint: op.constraint };
|
|
34
38
|
case "execute":
|
|
35
39
|
if (op.down === null) {
|
|
36
40
|
throw new IrreversibleMigration("execute() operation has no down SQL");
|
|
@@ -90,8 +94,8 @@ function makeRevisionId(label, parents) {
|
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
// src/migrations/ddl.ts
|
|
93
|
-
function quoteId(name) {
|
|
94
|
-
return `"${name.replace(/"/g, '""')}"`;
|
|
97
|
+
function quoteId(name, dialect) {
|
|
98
|
+
return dialect === "mysql" ? `\`${name.replace(/`/g, "``")}\`` : `"${name.replace(/"/g, '""')}"`;
|
|
95
99
|
}
|
|
96
100
|
function quoteLiteral(value) {
|
|
97
101
|
return `'${value.replace(/'/g, "''")}'`;
|
|
@@ -116,6 +120,45 @@ function renderColumnType(type, dialect) {
|
|
|
116
120
|
return "TEXT";
|
|
117
121
|
}
|
|
118
122
|
}
|
|
123
|
+
if (dialect === "mysql") {
|
|
124
|
+
switch (kind) {
|
|
125
|
+
case "smallint":
|
|
126
|
+
return "SMALLINT";
|
|
127
|
+
case "integer":
|
|
128
|
+
return "INT";
|
|
129
|
+
case "bigint":
|
|
130
|
+
return "BIGINT";
|
|
131
|
+
case "numeric":
|
|
132
|
+
return meta.precision !== void 0 ? `DECIMAL(${meta.precision}${meta.scale !== void 0 ? `, ${meta.scale}` : ""})` : "DECIMAL";
|
|
133
|
+
case "real":
|
|
134
|
+
return "FLOAT";
|
|
135
|
+
case "double":
|
|
136
|
+
return "DOUBLE";
|
|
137
|
+
case "varchar":
|
|
138
|
+
return `VARCHAR(${meta.length ?? 255})`;
|
|
139
|
+
case "char":
|
|
140
|
+
return `CHAR(${meta.length ?? 255})`;
|
|
141
|
+
case "text":
|
|
142
|
+
return "TEXT";
|
|
143
|
+
case "boolean":
|
|
144
|
+
return "TINYINT(1)";
|
|
145
|
+
case "date":
|
|
146
|
+
return "DATE";
|
|
147
|
+
case "time":
|
|
148
|
+
return "TIME";
|
|
149
|
+
case "datetime":
|
|
150
|
+
case "timestamp":
|
|
151
|
+
return "DATETIME";
|
|
152
|
+
case "blob":
|
|
153
|
+
return "BLOB";
|
|
154
|
+
case "json":
|
|
155
|
+
return "JSON";
|
|
156
|
+
case "uuid":
|
|
157
|
+
return "CHAR(36)";
|
|
158
|
+
case "enum":
|
|
159
|
+
return `ENUM(${(meta.values ?? []).map(quoteLiteral).join(", ")})`;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
119
162
|
switch (kind) {
|
|
120
163
|
case "smallint":
|
|
121
164
|
return "SMALLINT";
|
|
@@ -160,29 +203,66 @@ function renderDefault(def, dialect) {
|
|
|
160
203
|
if (typeof expr === "object") return expr.raw;
|
|
161
204
|
switch (expr) {
|
|
162
205
|
case "now":
|
|
163
|
-
return dialect === "
|
|
206
|
+
return dialect === "postgresql" ? "now()" : "CURRENT_TIMESTAMP";
|
|
164
207
|
case "current_date":
|
|
165
208
|
return "CURRENT_DATE";
|
|
166
209
|
case "current_time":
|
|
167
210
|
return "CURRENT_TIME";
|
|
168
211
|
case "uuidv4":
|
|
169
|
-
|
|
212
|
+
if (dialect === "postgresql") return "gen_random_uuid()";
|
|
213
|
+
if (dialect === "mysql") return "(UUID())";
|
|
214
|
+
return "(lower(hex(randomblob(16))))";
|
|
170
215
|
}
|
|
171
216
|
}
|
|
172
217
|
const value = def.value;
|
|
173
218
|
if (value === null) return "NULL";
|
|
174
219
|
if (typeof value === "boolean") {
|
|
175
|
-
return dialect === "
|
|
220
|
+
return dialect === "postgresql" ? value ? "TRUE" : "FALSE" : value ? "1" : "0";
|
|
176
221
|
}
|
|
177
222
|
if (typeof value === "number" || typeof value === "bigint") return String(value);
|
|
178
223
|
if (value instanceof Date) return quoteLiteral(value.toISOString());
|
|
179
224
|
if (typeof value === "object") return quoteLiteral(JSON.stringify(value));
|
|
180
225
|
return quoteLiteral(String(value));
|
|
181
226
|
}
|
|
227
|
+
function renderFkAction(action) {
|
|
228
|
+
return action.toUpperCase();
|
|
229
|
+
}
|
|
230
|
+
function renderFkActions(fk) {
|
|
231
|
+
let sql = "";
|
|
232
|
+
if (fk.onDelete) sql += ` ON DELETE ${renderFkAction(fk.onDelete)}`;
|
|
233
|
+
if (fk.onUpdate) sql += ` ON UPDATE ${renderFkAction(fk.onUpdate)}`;
|
|
234
|
+
return sql;
|
|
235
|
+
}
|
|
236
|
+
function columnConstraintSuffix(col, dialect) {
|
|
237
|
+
let sql = "";
|
|
238
|
+
if (col.unique) sql += " UNIQUE";
|
|
239
|
+
if (col.references) {
|
|
240
|
+
const ref = col.references;
|
|
241
|
+
sql += ` REFERENCES ${quoteId(ref.table, dialect)} (${quoteId(ref.column, dialect)})`;
|
|
242
|
+
sql += renderFkActions(ref);
|
|
243
|
+
}
|
|
244
|
+
return sql;
|
|
245
|
+
}
|
|
246
|
+
function renderUniqueConstraint(uc, dialect) {
|
|
247
|
+
const cols = uc.columns.map((c) => quoteId(c, dialect)).join(", ");
|
|
248
|
+
return `CONSTRAINT ${quoteId(uc.name, dialect)} UNIQUE (${cols})`;
|
|
249
|
+
}
|
|
250
|
+
function renderForeignKeyConstraint(fk, dialect) {
|
|
251
|
+
const cols = fk.columns.map((c) => quoteId(c, dialect)).join(", ");
|
|
252
|
+
const refCols = fk.refColumns.map((c) => quoteId(c, dialect)).join(", ");
|
|
253
|
+
return `CONSTRAINT ${quoteId(fk.name, dialect)} FOREIGN KEY (${cols}) REFERENCES ${quoteId(fk.refTable, dialect)} (${refCols})${renderFkActions(fk)}`;
|
|
254
|
+
}
|
|
255
|
+
function tableConstraintClauses(table, dialect) {
|
|
256
|
+
return [
|
|
257
|
+
...table.uniqueConstraints.map((uc) => renderUniqueConstraint(uc, dialect)),
|
|
258
|
+
...table.foreignKeys.map((fk) => renderForeignKeyConstraint(fk, dialect))
|
|
259
|
+
];
|
|
260
|
+
}
|
|
182
261
|
function renderColumnDef(col, dialect) {
|
|
183
|
-
let sql = `${quoteId(col.name)} ${renderColumnType(col.type, dialect)}`;
|
|
262
|
+
let sql = `${quoteId(col.name, dialect)} ${renderColumnType(col.type, dialect)}`;
|
|
184
263
|
if (col.notNull) sql += " NOT NULL";
|
|
185
264
|
if (col.default !== null) sql += ` DEFAULT ${renderDefault(col.default, dialect)}`;
|
|
265
|
+
sql += columnConstraintSuffix(col, dialect);
|
|
186
266
|
return sql;
|
|
187
267
|
}
|
|
188
268
|
function enumTypeName(table, column) {
|
|
@@ -202,23 +282,29 @@ function renderCreateTable(table, dialect) {
|
|
|
202
282
|
if (dialect === "postgresql" && c.type.kind === "enum") {
|
|
203
283
|
const typeName = enumTypeName(table.name, c.name);
|
|
204
284
|
const values = (c.type.meta.values ?? []).map(quoteLiteral).join(", ");
|
|
205
|
-
typeStmts.push(`CREATE TYPE ${quoteId(typeName)} AS ENUM (${values})`);
|
|
206
|
-
let def = `${quoteId(c.name)} ${quoteId(typeName)}`;
|
|
285
|
+
typeStmts.push(`CREATE TYPE ${quoteId(typeName, dialect)} AS ENUM (${values})`);
|
|
286
|
+
let def = `${quoteId(c.name, dialect)} ${quoteId(typeName, dialect)}`;
|
|
207
287
|
if (c.notNull) def += " NOT NULL";
|
|
208
288
|
if (c.default !== null) def += ` DEFAULT ${renderDefault(c.default, dialect)}`;
|
|
209
|
-
return def;
|
|
289
|
+
return def + columnConstraintSuffix(c, dialect);
|
|
210
290
|
}
|
|
211
291
|
if (dialect === "postgresql" && isAutoIncrementPk(table, c)) {
|
|
212
|
-
return `${quoteId(c.name)} ${postgresSerialType(c.type.kind)}`;
|
|
292
|
+
return `${quoteId(c.name, dialect)} ${postgresSerialType(c.type.kind)}${columnConstraintSuffix(c, dialect)}`;
|
|
293
|
+
}
|
|
294
|
+
if (dialect === "mysql" && isAutoIncrementPk(table, c)) {
|
|
295
|
+
return `${quoteId(c.name, dialect)} ${renderColumnType(c.type, dialect)} NOT NULL AUTO_INCREMENT${columnConstraintSuffix(c, dialect)}`;
|
|
213
296
|
}
|
|
214
297
|
return renderColumnDef(c, dialect);
|
|
215
298
|
});
|
|
216
299
|
if (table.primaryKey.length > 0) {
|
|
217
|
-
cols.push(
|
|
300
|
+
cols.push(
|
|
301
|
+
`PRIMARY KEY (${table.primaryKey.map((c) => quoteId(c, dialect)).join(", ")})`
|
|
302
|
+
);
|
|
218
303
|
}
|
|
304
|
+
cols.push(...tableConstraintClauses(table, dialect));
|
|
219
305
|
return [
|
|
220
306
|
...typeStmts,
|
|
221
|
-
`CREATE TABLE ${quoteId(table.name)} (
|
|
307
|
+
`CREATE TABLE ${quoteId(table.name, dialect)} (
|
|
222
308
|
${cols.join(",\n ")}
|
|
223
309
|
)`
|
|
224
310
|
];
|
|
@@ -228,60 +314,97 @@ function renderOperation(op, dialect) {
|
|
|
228
314
|
case "create_table":
|
|
229
315
|
return renderCreateTable(op.table, dialect);
|
|
230
316
|
case "drop_table":
|
|
231
|
-
return [`DROP TABLE ${quoteId(op.table.name)}`];
|
|
317
|
+
return [`DROP TABLE ${quoteId(op.table.name, dialect)}`];
|
|
232
318
|
case "rename_table":
|
|
233
|
-
return [`
|
|
319
|
+
return dialect === "mysql" ? [`RENAME TABLE ${quoteId(op.from, dialect)} TO ${quoteId(op.to, dialect)}`] : [
|
|
320
|
+
`ALTER TABLE ${quoteId(op.from, dialect)} RENAME TO ${quoteId(op.to, dialect)}`
|
|
321
|
+
];
|
|
234
322
|
case "add_column":
|
|
235
323
|
return [
|
|
236
|
-
`ALTER TABLE ${quoteId(op.table)} ADD COLUMN ${renderColumnDef(op.column, dialect)}`
|
|
324
|
+
`ALTER TABLE ${quoteId(op.table, dialect)} ADD COLUMN ${renderColumnDef(op.column, dialect)}`
|
|
237
325
|
];
|
|
238
326
|
case "drop_column":
|
|
239
|
-
return [
|
|
327
|
+
return [
|
|
328
|
+
`ALTER TABLE ${quoteId(op.table, dialect)} DROP COLUMN ${quoteId(op.column.name, dialect)}`
|
|
329
|
+
];
|
|
240
330
|
case "rename_column":
|
|
241
331
|
return [
|
|
242
|
-
`ALTER TABLE ${quoteId(op.table)} RENAME COLUMN ${quoteId(op.from)} TO ${quoteId(op.to)}`
|
|
332
|
+
`ALTER TABLE ${quoteId(op.table, dialect)} RENAME COLUMN ${quoteId(op.from, dialect)} TO ${quoteId(op.to, dialect)}`
|
|
243
333
|
];
|
|
244
334
|
case "alter_column":
|
|
245
335
|
return renderAlterColumn(op.table, op.to, dialect);
|
|
246
336
|
case "recreate_table":
|
|
247
|
-
return dialect === "sqlite" ? renderSqliteRebuild(op.from, op.to) :
|
|
337
|
+
return dialect === "sqlite" ? renderSqliteRebuild(op.from, op.to) : renderTableDiff(op.from, op.to, dialect);
|
|
338
|
+
case "add_constraint":
|
|
339
|
+
return renderAddConstraint(op.table, op.constraint, dialect);
|
|
340
|
+
case "drop_constraint":
|
|
341
|
+
return renderDropConstraint(op.table, op.constraint, dialect);
|
|
248
342
|
case "execute":
|
|
249
343
|
return [op.up];
|
|
250
344
|
}
|
|
251
345
|
}
|
|
346
|
+
function renderAddConstraint(table, constraint, dialect) {
|
|
347
|
+
if (dialect === "sqlite") {
|
|
348
|
+
throw new Error(
|
|
349
|
+
`add_constraint on SQLite needs a table-rebuild (recreate_table); constraint ${constraint.constraint.name} on ${table}`
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
const clause = constraint.type === "unique" ? renderUniqueConstraint(constraint.constraint, dialect) : renderForeignKeyConstraint(constraint.constraint, dialect);
|
|
353
|
+
return [`ALTER TABLE ${quoteId(table, dialect)} ADD ${clause}`];
|
|
354
|
+
}
|
|
355
|
+
function renderDropConstraint(table, constraint, dialect) {
|
|
356
|
+
if (dialect === "sqlite") {
|
|
357
|
+
throw new Error(
|
|
358
|
+
`drop_constraint on SQLite needs a table-rebuild (recreate_table); constraint ${constraint.constraint.name} on ${table}`
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
const t = quoteId(table, dialect);
|
|
362
|
+
const name = quoteId(constraint.constraint.name, dialect);
|
|
363
|
+
if (dialect === "mysql") {
|
|
364
|
+
return [
|
|
365
|
+
constraint.type === "unique" ? `ALTER TABLE ${t} DROP INDEX ${name}` : `ALTER TABLE ${t} DROP FOREIGN KEY ${name}`
|
|
366
|
+
];
|
|
367
|
+
}
|
|
368
|
+
return [`ALTER TABLE ${t} DROP CONSTRAINT ${name}`];
|
|
369
|
+
}
|
|
252
370
|
function renderSqliteRebuild(from, to) {
|
|
253
371
|
const tmp = `__new_${to.name}`;
|
|
254
372
|
const common = Object.keys(to.columns).filter((c) => c in from.columns);
|
|
255
373
|
const cols = Object.values(to.columns).map((c) => renderColumnDef(c, "sqlite"));
|
|
256
374
|
if (to.primaryKey.length > 0) {
|
|
257
|
-
cols.push(
|
|
375
|
+
cols.push(
|
|
376
|
+
`PRIMARY KEY (${to.primaryKey.map((c) => quoteId(c, "sqlite")).join(", ")})`
|
|
377
|
+
);
|
|
258
378
|
}
|
|
259
|
-
|
|
379
|
+
cols.push(...tableConstraintClauses(to, "sqlite"));
|
|
380
|
+
const commonSql = common.map((c) => quoteId(c, "sqlite")).join(", ");
|
|
260
381
|
return [
|
|
261
382
|
"PRAGMA foreign_keys=off",
|
|
262
|
-
`CREATE TABLE ${quoteId(tmp)} (
|
|
383
|
+
`CREATE TABLE ${quoteId(tmp, "sqlite")} (
|
|
263
384
|
${cols.join(",\n ")}
|
|
264
385
|
)`,
|
|
265
|
-
common.length > 0 ? `INSERT INTO ${quoteId(tmp)} (${commonSql}) SELECT ${commonSql} FROM ${quoteId(from.name)}` : `-- no common columns to copy from ${from.name}`,
|
|
266
|
-
`DROP TABLE ${quoteId(from.name)}`,
|
|
267
|
-
`ALTER TABLE ${quoteId(tmp)} RENAME TO ${quoteId(to.name)}`,
|
|
386
|
+
common.length > 0 ? `INSERT INTO ${quoteId(tmp, "sqlite")} (${commonSql}) SELECT ${commonSql} FROM ${quoteId(from.name, "sqlite")}` : `-- no common columns to copy from ${from.name}`,
|
|
387
|
+
`DROP TABLE ${quoteId(from.name, "sqlite")}`,
|
|
388
|
+
`ALTER TABLE ${quoteId(tmp, "sqlite")} RENAME TO ${quoteId(to.name, "sqlite")}`,
|
|
268
389
|
"PRAGMA foreign_keys=on"
|
|
269
390
|
];
|
|
270
391
|
}
|
|
271
|
-
function
|
|
392
|
+
function renderTableDiff(from, to, dialect) {
|
|
272
393
|
const stmts = [];
|
|
273
394
|
for (const [name, col] of Object.entries(to.columns)) {
|
|
274
395
|
if (!(name in from.columns)) {
|
|
275
396
|
stmts.push(
|
|
276
|
-
`ALTER TABLE ${quoteId(to.name)} ADD COLUMN ${renderColumnDef(col,
|
|
397
|
+
`ALTER TABLE ${quoteId(to.name, dialect)} ADD COLUMN ${renderColumnDef(col, dialect)}`
|
|
277
398
|
);
|
|
278
399
|
} else {
|
|
279
|
-
stmts.push(...renderAlterColumn(to.name, col,
|
|
400
|
+
stmts.push(...renderAlterColumn(to.name, col, dialect));
|
|
280
401
|
}
|
|
281
402
|
}
|
|
282
403
|
for (const name of Object.keys(from.columns)) {
|
|
283
404
|
if (!(name in to.columns)) {
|
|
284
|
-
stmts.push(
|
|
405
|
+
stmts.push(
|
|
406
|
+
`ALTER TABLE ${quoteId(to.name, dialect)} DROP COLUMN ${quoteId(name, dialect)}`
|
|
407
|
+
);
|
|
285
408
|
}
|
|
286
409
|
}
|
|
287
410
|
return stmts;
|
|
@@ -289,11 +412,16 @@ function renderPostgresTableDiff(from, to) {
|
|
|
289
412
|
function renderAlterColumn(table, to, dialect) {
|
|
290
413
|
if (dialect === "sqlite") {
|
|
291
414
|
throw new Error(
|
|
292
|
-
`alter_column on SQLite needs
|
|
415
|
+
`alter_column on SQLite needs a table-rebuild (recreate_table); column ${table}.${to.name}`
|
|
293
416
|
);
|
|
294
417
|
}
|
|
295
|
-
|
|
296
|
-
|
|
418
|
+
if (dialect === "mysql") {
|
|
419
|
+
return [
|
|
420
|
+
`ALTER TABLE ${quoteId(table, dialect)} MODIFY COLUMN ${renderColumnDef(to, dialect)}`
|
|
421
|
+
];
|
|
422
|
+
}
|
|
423
|
+
const t = quoteId(table, dialect);
|
|
424
|
+
const c = quoteId(to.name, dialect);
|
|
297
425
|
const stmts = [
|
|
298
426
|
`ALTER TABLE ${t} ALTER COLUMN ${c} TYPE ${renderColumnType(to.type, dialect)}`
|
|
299
427
|
];
|
|
@@ -312,9 +440,74 @@ function columnSignature(col) {
|
|
|
312
440
|
type: col.type,
|
|
313
441
|
notNull: col.notNull,
|
|
314
442
|
primaryKey: col.primaryKey,
|
|
315
|
-
default: col.default
|
|
443
|
+
default: col.default,
|
|
444
|
+
unique: col.unique,
|
|
445
|
+
references: col.references
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
function uniqueSignature(uc) {
|
|
449
|
+
return JSON.stringify({ columns: uc.columns });
|
|
450
|
+
}
|
|
451
|
+
function foreignKeySignature(fk) {
|
|
452
|
+
return JSON.stringify({
|
|
453
|
+
columns: fk.columns,
|
|
454
|
+
refTable: fk.refTable,
|
|
455
|
+
refColumns: fk.refColumns,
|
|
456
|
+
onDelete: fk.onDelete ?? null,
|
|
457
|
+
onUpdate: fk.onUpdate ?? null
|
|
316
458
|
});
|
|
317
459
|
}
|
|
460
|
+
function diffConstraints(current, target) {
|
|
461
|
+
const ops = [];
|
|
462
|
+
const table = target.name;
|
|
463
|
+
const currentUq = new Map(current.uniqueConstraints.map((u) => [u.name, u]));
|
|
464
|
+
const targetUq = new Map(target.uniqueConstraints.map((u) => [u.name, u]));
|
|
465
|
+
for (const [name, cur] of currentUq) {
|
|
466
|
+
const tgt = targetUq.get(name);
|
|
467
|
+
if (!tgt || uniqueSignature(cur) !== uniqueSignature(tgt)) {
|
|
468
|
+
ops.push(dropUnique(table, cur));
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
for (const [name, tgt] of targetUq) {
|
|
472
|
+
const cur = currentUq.get(name);
|
|
473
|
+
if (!cur || uniqueSignature(cur) !== uniqueSignature(tgt)) {
|
|
474
|
+
ops.push(addUnique(table, tgt));
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
const currentFk = new Map(current.foreignKeys.map((f) => [f.name, f]));
|
|
478
|
+
const targetFk = new Map(target.foreignKeys.map((f) => [f.name, f]));
|
|
479
|
+
for (const [name, cur] of currentFk) {
|
|
480
|
+
const tgt = targetFk.get(name);
|
|
481
|
+
if (!tgt || foreignKeySignature(cur) !== foreignKeySignature(tgt)) {
|
|
482
|
+
ops.push(dropForeignKey(table, cur));
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
for (const [name, tgt] of targetFk) {
|
|
486
|
+
const cur = currentFk.get(name);
|
|
487
|
+
if (!cur || foreignKeySignature(cur) !== foreignKeySignature(tgt)) {
|
|
488
|
+
ops.push(addForeignKey(table, tgt));
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return ops;
|
|
492
|
+
}
|
|
493
|
+
function uniqueNamed(uc) {
|
|
494
|
+
return { type: "unique", constraint: uc };
|
|
495
|
+
}
|
|
496
|
+
function foreignKeyNamed(fk) {
|
|
497
|
+
return { type: "foreignKey", constraint: fk };
|
|
498
|
+
}
|
|
499
|
+
function addUnique(table, uc) {
|
|
500
|
+
return { kind: "add_constraint", table, constraint: uniqueNamed(uc) };
|
|
501
|
+
}
|
|
502
|
+
function dropUnique(table, uc) {
|
|
503
|
+
return { kind: "drop_constraint", table, constraint: uniqueNamed(uc) };
|
|
504
|
+
}
|
|
505
|
+
function addForeignKey(table, fk) {
|
|
506
|
+
return { kind: "add_constraint", table, constraint: foreignKeyNamed(fk) };
|
|
507
|
+
}
|
|
508
|
+
function dropForeignKey(table, fk) {
|
|
509
|
+
return { kind: "drop_constraint", table, constraint: foreignKeyNamed(fk) };
|
|
510
|
+
}
|
|
318
511
|
function diffSchema(current, target) {
|
|
319
512
|
const ops = [];
|
|
320
513
|
const drops = [];
|
|
@@ -343,6 +536,7 @@ function diffSchema(current, target) {
|
|
|
343
536
|
ops.push({ kind: "drop_column", table: name, column: currentCol });
|
|
344
537
|
}
|
|
345
538
|
}
|
|
539
|
+
ops.push(...diffConstraints(currentTable, targetTable));
|
|
346
540
|
}
|
|
347
541
|
for (const [name, currentTable] of Object.entries(current.tables)) {
|
|
348
542
|
if (!target.tables[name]) {
|
|
@@ -407,6 +601,9 @@ function heads(migrations) {
|
|
|
407
601
|
}
|
|
408
602
|
|
|
409
603
|
// src/migrations/ir.ts
|
|
604
|
+
function constraintName(prefix, table, columns) {
|
|
605
|
+
return `${prefix}_${table}_${columns.join("_")}`;
|
|
606
|
+
}
|
|
410
607
|
function reflectTable(model) {
|
|
411
608
|
const columns = {};
|
|
412
609
|
const primaryKey = [];
|
|
@@ -417,11 +614,32 @@ function reflectTable(model) {
|
|
|
417
614
|
type: col.type,
|
|
418
615
|
notNull: col.flags.notNull || isPk,
|
|
419
616
|
primaryKey: isPk,
|
|
420
|
-
default: col.defaultValue
|
|
617
|
+
default: col.defaultValue,
|
|
618
|
+
unique: col.flags.unique,
|
|
619
|
+
references: col.reference
|
|
421
620
|
};
|
|
422
621
|
if (isPk) primaryKey.push(name);
|
|
423
622
|
}
|
|
424
|
-
|
|
623
|
+
const uniqueConstraints = [];
|
|
624
|
+
const foreignKeys = [];
|
|
625
|
+
for (const c of model.tableArgs?.() ?? []) {
|
|
626
|
+
if (c.kind === "unique") {
|
|
627
|
+
uniqueConstraints.push({
|
|
628
|
+
name: c.name ?? constraintName("uq", model.tablename, c.columns),
|
|
629
|
+
columns: c.columns
|
|
630
|
+
});
|
|
631
|
+
} else {
|
|
632
|
+
foreignKeys.push({
|
|
633
|
+
name: c.name ?? constraintName("fk", model.tablename, c.columns),
|
|
634
|
+
columns: c.columns,
|
|
635
|
+
refTable: c.refTable,
|
|
636
|
+
refColumns: c.refColumns,
|
|
637
|
+
onDelete: c.onDelete,
|
|
638
|
+
onUpdate: c.onUpdate
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
return { name: model.tablename, columns, primaryKey, uniqueConstraints, foreignKeys };
|
|
425
643
|
}
|
|
426
644
|
function reflectSchema(models) {
|
|
427
645
|
const tables = {};
|
|
@@ -458,6 +676,39 @@ function affinityToKind(affinity) {
|
|
|
458
676
|
return "text";
|
|
459
677
|
}
|
|
460
678
|
}
|
|
679
|
+
function sqliteForeignKeys(driver, table) {
|
|
680
|
+
const rows = driver.execute(`PRAGMA foreign_key_list(${JSON.stringify(table)})`, []).rows;
|
|
681
|
+
const byId = /* @__PURE__ */ new Map();
|
|
682
|
+
for (const r of rows) {
|
|
683
|
+
const list = byId.get(r.id) ?? [];
|
|
684
|
+
list.push(r);
|
|
685
|
+
byId.set(r.id, list);
|
|
686
|
+
}
|
|
687
|
+
const fks = [];
|
|
688
|
+
for (const group of byId.values()) {
|
|
689
|
+
const ordered = [...group].sort((a, b) => a.seq - b.seq);
|
|
690
|
+
const columns = ordered.map((r) => r.from);
|
|
691
|
+
fks.push({
|
|
692
|
+
name: `fk_${table}_${columns.join("_")}`,
|
|
693
|
+
columns,
|
|
694
|
+
refTable: ordered[0]?.table ?? "",
|
|
695
|
+
refColumns: ordered.map((r) => r.to)
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
return fks;
|
|
699
|
+
}
|
|
700
|
+
function sqliteUniques(driver, table) {
|
|
701
|
+
const indexes = driver.execute(`PRAGMA index_list(${JSON.stringify(table)})`, []).rows;
|
|
702
|
+
const uniques = [];
|
|
703
|
+
for (const idx of indexes) {
|
|
704
|
+
if (Number(idx.unique) !== 1 || idx.origin === "pk") continue;
|
|
705
|
+
const cols = driver.execute(`PRAGMA index_info(${JSON.stringify(idx.name)})`, []).rows.sort((a, b) => a.seqno - b.seqno).map((c) => c.name);
|
|
706
|
+
if (cols.length > 0) {
|
|
707
|
+
uniques.push({ name: `uq_${table}_${cols.join("_")}`, columns: cols });
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
return uniques;
|
|
711
|
+
}
|
|
461
712
|
function introspectSqlite(driver) {
|
|
462
713
|
const tablesRows = driver.execute(
|
|
463
714
|
"SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' AND name != 'tempest_db_js_migrations'",
|
|
@@ -477,14 +728,39 @@ function introspectSqlite(driver) {
|
|
|
477
728
|
type: { kind: affinityToKind(affinity), meta: {} },
|
|
478
729
|
notNull: Number(col.notnull) === 1 || isPk,
|
|
479
730
|
primaryKey: isPk,
|
|
480
|
-
default: null
|
|
731
|
+
default: null,
|
|
732
|
+
unique: false,
|
|
733
|
+
references: null
|
|
481
734
|
};
|
|
482
735
|
if (isPk) primaryKey.push(col.name);
|
|
483
736
|
}
|
|
484
|
-
tables[tableName] = {
|
|
737
|
+
tables[tableName] = {
|
|
738
|
+
name: tableName,
|
|
739
|
+
columns,
|
|
740
|
+
primaryKey,
|
|
741
|
+
uniqueConstraints: sqliteUniques(driver, tableName),
|
|
742
|
+
foreignKeys: sqliteForeignKeys(driver, tableName)
|
|
743
|
+
};
|
|
485
744
|
}
|
|
486
745
|
return { tables };
|
|
487
746
|
}
|
|
747
|
+
function constraintKeys(table) {
|
|
748
|
+
const fks = /* @__PURE__ */ new Set();
|
|
749
|
+
const uniques = /* @__PURE__ */ new Set();
|
|
750
|
+
for (const col of Object.values(table.columns)) {
|
|
751
|
+
if (col.unique) uniques.add(col.name);
|
|
752
|
+
if (col.references) {
|
|
753
|
+
fks.add(`${col.name}=>${col.references.table}(${col.references.column})`);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
for (const uc of table.uniqueConstraints) {
|
|
757
|
+
uniques.add([...uc.columns].sort().join(","));
|
|
758
|
+
}
|
|
759
|
+
for (const fk of table.foreignKeys) {
|
|
760
|
+
fks.add(`${fk.columns.join(",")}=>${fk.refTable}(${fk.refColumns.join(",")})`);
|
|
761
|
+
}
|
|
762
|
+
return { fks, uniques };
|
|
763
|
+
}
|
|
488
764
|
function checkDrift(driver, models) {
|
|
489
765
|
const actual = introspectSqlite(driver);
|
|
490
766
|
const expected = reflectSchema(models);
|
|
@@ -522,6 +798,34 @@ function checkDrift(driver, models) {
|
|
|
522
798
|
);
|
|
523
799
|
}
|
|
524
800
|
}
|
|
801
|
+
const expectedKeys = constraintKeys(expectedTable);
|
|
802
|
+
const actualKeys = constraintKeys(actualTable);
|
|
803
|
+
for (const fk of expectedKeys.fks) {
|
|
804
|
+
if (!actualKeys.fks.has(fk)) {
|
|
805
|
+
issues.push(`foreign key "${tableName}: ${fk}" is missing from the database`);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
for (const fk of actualKeys.fks) {
|
|
809
|
+
if (!expectedKeys.fks.has(fk)) {
|
|
810
|
+
issues.push(
|
|
811
|
+
`foreign key "${tableName}: ${fk}" exists in the database but not in the model`
|
|
812
|
+
);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
for (const uq of expectedKeys.uniques) {
|
|
816
|
+
if (!actualKeys.uniques.has(uq)) {
|
|
817
|
+
issues.push(
|
|
818
|
+
`unique constraint "${tableName}: (${uq})" is missing from the database`
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
for (const uq of actualKeys.uniques) {
|
|
823
|
+
if (!expectedKeys.uniques.has(uq)) {
|
|
824
|
+
issues.push(
|
|
825
|
+
`unique constraint "${tableName}: (${uq})" exists in the database but not in the model`
|
|
826
|
+
);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
525
829
|
}
|
|
526
830
|
for (const tableName of Object.keys(actual.tables)) {
|
|
527
831
|
if (!expected.tables[tableName]) {
|
|
@@ -583,14 +887,59 @@ async function introspectPostgres(driver) {
|
|
|
583
887
|
},
|
|
584
888
|
notNull: col.is_nullable === "NO" || isPk,
|
|
585
889
|
primaryKey: isPk,
|
|
586
|
-
default: null
|
|
890
|
+
default: null,
|
|
891
|
+
unique: false,
|
|
892
|
+
references: null
|
|
587
893
|
};
|
|
588
894
|
if (isPk) primaryKey.push(name);
|
|
589
895
|
}
|
|
590
|
-
tables[tableName] = {
|
|
896
|
+
tables[tableName] = {
|
|
897
|
+
name: tableName,
|
|
898
|
+
columns,
|
|
899
|
+
primaryKey,
|
|
900
|
+
uniqueConstraints: await postgresUniques(driver, tableName),
|
|
901
|
+
foreignKeys: await postgresForeignKeys(driver, tableName)
|
|
902
|
+
};
|
|
591
903
|
}
|
|
592
904
|
return { tables };
|
|
593
905
|
}
|
|
906
|
+
async function postgresForeignKeys(driver, table) {
|
|
907
|
+
const result = await driver.execute(
|
|
908
|
+
`SELECT c.conname AS name,
|
|
909
|
+
(SELECT array_agg(a.attname ORDER BY k.ord)
|
|
910
|
+
FROM unnest(c.conkey) WITH ORDINALITY AS k(attnum, ord)
|
|
911
|
+
JOIN pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = k.attnum) AS cols,
|
|
912
|
+
cf.relname AS ref_table,
|
|
913
|
+
(SELECT array_agg(a.attname ORDER BY k.ord)
|
|
914
|
+
FROM unnest(c.confkey) WITH ORDINALITY AS k(attnum, ord)
|
|
915
|
+
JOIN pg_attribute a ON a.attrelid = c.confrelid AND a.attnum = k.attnum) AS ref_cols
|
|
916
|
+
FROM pg_constraint c
|
|
917
|
+
JOIN pg_class cf ON cf.oid = c.confrelid
|
|
918
|
+
WHERE c.contype = 'f' AND c.conrelid = $1::regclass`,
|
|
919
|
+
[table]
|
|
920
|
+
);
|
|
921
|
+
return result.rows.map((r) => ({
|
|
922
|
+
name: String(r.name),
|
|
923
|
+
columns: r.cols ?? [],
|
|
924
|
+
refTable: String(r.ref_table),
|
|
925
|
+
refColumns: r.ref_cols ?? []
|
|
926
|
+
}));
|
|
927
|
+
}
|
|
928
|
+
async function postgresUniques(driver, table) {
|
|
929
|
+
const result = await driver.execute(
|
|
930
|
+
`SELECT c.conname AS name,
|
|
931
|
+
(SELECT array_agg(a.attname ORDER BY k.ord)
|
|
932
|
+
FROM unnest(c.conkey) WITH ORDINALITY AS k(attnum, ord)
|
|
933
|
+
JOIN pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = k.attnum) AS cols
|
|
934
|
+
FROM pg_constraint c
|
|
935
|
+
WHERE c.contype = 'u' AND c.conrelid = $1::regclass`,
|
|
936
|
+
[table]
|
|
937
|
+
);
|
|
938
|
+
return result.rows.map((r) => ({
|
|
939
|
+
name: String(r.name),
|
|
940
|
+
columns: r.cols ?? []
|
|
941
|
+
}));
|
|
942
|
+
}
|
|
594
943
|
async function checkDriftPostgres(driver, models) {
|
|
595
944
|
const actual = await introspectPostgres(driver);
|
|
596
945
|
const expected = reflectSchema(models);
|
|
@@ -623,6 +972,20 @@ async function checkDriftPostgres(driver, models) {
|
|
|
623
972
|
);
|
|
624
973
|
}
|
|
625
974
|
}
|
|
975
|
+
const expectedKeys = constraintKeys(expectedTable);
|
|
976
|
+
const actualKeys = constraintKeys(actualTable);
|
|
977
|
+
for (const fk of expectedKeys.fks) {
|
|
978
|
+
if (!actualKeys.fks.has(fk)) {
|
|
979
|
+
issues.push(`foreign key "${tableName}: ${fk}" is missing from the database`);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
for (const uq of expectedKeys.uniques) {
|
|
983
|
+
if (!actualKeys.uniques.has(uq)) {
|
|
984
|
+
issues.push(
|
|
985
|
+
`unique constraint "${tableName}: (${uq})" is missing from the database`
|
|
986
|
+
);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
626
989
|
}
|
|
627
990
|
for (const tableName of Object.keys(actual.tables)) {
|
|
628
991
|
if (!expected.tables[tableName]) {
|
|
@@ -638,7 +1001,9 @@ function columnShape(col) {
|
|
|
638
1001
|
type: col.type,
|
|
639
1002
|
notNull: col.notNull,
|
|
640
1003
|
primaryKey: col.primaryKey,
|
|
641
|
-
default: col.default
|
|
1004
|
+
default: col.default,
|
|
1005
|
+
unique: col.unique,
|
|
1006
|
+
references: col.references
|
|
642
1007
|
});
|
|
643
1008
|
}
|
|
644
1009
|
function tableShape(columns) {
|
|
@@ -757,6 +1122,14 @@ var Op = class {
|
|
|
757
1122
|
recreateTable(from, to) {
|
|
758
1123
|
this.run({ kind: "recreate_table", from, to });
|
|
759
1124
|
}
|
|
1125
|
+
/** Add a table-level unique / foreign-key constraint. */
|
|
1126
|
+
addConstraint(table, constraint) {
|
|
1127
|
+
this.run({ kind: "add_constraint", table, constraint });
|
|
1128
|
+
}
|
|
1129
|
+
/** Drop a table-level unique / foreign-key constraint. */
|
|
1130
|
+
dropConstraint(table, constraint) {
|
|
1131
|
+
this.run({ kind: "drop_constraint", table, constraint });
|
|
1132
|
+
}
|
|
760
1133
|
/** Raw SQL escape hatch (e.g. a data migration). `down` may be `null`. */
|
|
761
1134
|
execute(up, down = null) {
|
|
762
1135
|
this.run({ kind: "execute", up, down });
|
|
@@ -856,6 +1229,112 @@ var MigrationRunner = class {
|
|
|
856
1229
|
return reverted;
|
|
857
1230
|
}
|
|
858
1231
|
};
|
|
1232
|
+
function quoteIdent(name, dialect) {
|
|
1233
|
+
return dialect === "mysql" ? `\`${name.replace(/`/g, "``")}\`` : `"${name.replace(/"/g, '""')}"`;
|
|
1234
|
+
}
|
|
1235
|
+
function placeholder(index, dialect) {
|
|
1236
|
+
return dialect === "postgresql" ? `$${index}` : "?";
|
|
1237
|
+
}
|
|
1238
|
+
var AsyncMigrationRunner = class {
|
|
1239
|
+
constructor(driver, dialect) {
|
|
1240
|
+
this.driver = driver;
|
|
1241
|
+
this.dialect = dialect;
|
|
1242
|
+
this.vt = quoteIdent(VERSION_TABLE, dialect);
|
|
1243
|
+
}
|
|
1244
|
+
driver;
|
|
1245
|
+
dialect;
|
|
1246
|
+
vt;
|
|
1247
|
+
/** Create the version-tracking table if it does not exist. */
|
|
1248
|
+
async ensureVersionTable() {
|
|
1249
|
+
await this.driver.execute(
|
|
1250
|
+
`CREATE TABLE IF NOT EXISTS ${this.vt} (revision ${this.textType()} PRIMARY KEY, applied_at ${this.textType()} NOT NULL, down_revision ${this.textType()} NOT NULL)`,
|
|
1251
|
+
[]
|
|
1252
|
+
);
|
|
1253
|
+
}
|
|
1254
|
+
/** A portable "text" column type for the version table. */
|
|
1255
|
+
textType() {
|
|
1256
|
+
return this.dialect === "mysql" ? "VARCHAR(255)" : "TEXT";
|
|
1257
|
+
}
|
|
1258
|
+
/** The set of applied revision ids. */
|
|
1259
|
+
async applied() {
|
|
1260
|
+
await this.ensureVersionTable();
|
|
1261
|
+
const { rows } = await this.driver.execute(`SELECT revision FROM ${this.vt}`, []);
|
|
1262
|
+
return new Set(rows.map((r) => String(r.revision)));
|
|
1263
|
+
}
|
|
1264
|
+
async runOps(ops) {
|
|
1265
|
+
for (const op of ops) {
|
|
1266
|
+
for (const stmt of renderOperation(op, this.dialect)) {
|
|
1267
|
+
const trimmed = stmt.trim();
|
|
1268
|
+
if (trimmed.length === 0 || trimmed.startsWith("--")) continue;
|
|
1269
|
+
await this.driver.execute(stmt, []);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
async record(migration, appliedAt) {
|
|
1274
|
+
const p = (i) => placeholder(i, this.dialect);
|
|
1275
|
+
await this.driver.execute(
|
|
1276
|
+
`INSERT INTO ${this.vt} (revision, applied_at, down_revision) VALUES (${p(1)}, ${p(2)}, ${p(3)})`,
|
|
1277
|
+
[migration.revision, appliedAt, migration.downRevision.join(",")]
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1280
|
+
async forget(revision) {
|
|
1281
|
+
await this.driver.execute(
|
|
1282
|
+
`DELETE FROM ${this.vt} WHERE revision = ${placeholder(1, this.dialect)}`,
|
|
1283
|
+
[revision]
|
|
1284
|
+
);
|
|
1285
|
+
}
|
|
1286
|
+
/**
|
|
1287
|
+
* Apply all pending migrations up to the head(s), in DAG order.
|
|
1288
|
+
*
|
|
1289
|
+
* @param migrations All known migrations.
|
|
1290
|
+
* @param appliedAt Timestamp string to stamp on each applied revision.
|
|
1291
|
+
* @returns The revision ids that were applied this run.
|
|
1292
|
+
*/
|
|
1293
|
+
async upgrade(migrations, appliedAt) {
|
|
1294
|
+
const done = await this.applied();
|
|
1295
|
+
const ordered = topoOrder(migrations);
|
|
1296
|
+
const ran = [];
|
|
1297
|
+
for (const migration of ordered) {
|
|
1298
|
+
if (done.has(migration.revision)) continue;
|
|
1299
|
+
const op = new Op();
|
|
1300
|
+
migration.up(op);
|
|
1301
|
+
await this.runOps(op.operations);
|
|
1302
|
+
await this.record(migration, appliedAt);
|
|
1303
|
+
ran.push(migration.revision);
|
|
1304
|
+
}
|
|
1305
|
+
return ran;
|
|
1306
|
+
}
|
|
1307
|
+
/**
|
|
1308
|
+
* Revert the last `steps` applied migrations (default 1), newest first.
|
|
1309
|
+
*
|
|
1310
|
+
* @param migrations All known migrations.
|
|
1311
|
+
* @param steps How many applied revisions to roll back.
|
|
1312
|
+
* @returns The revision ids that were reverted.
|
|
1313
|
+
*/
|
|
1314
|
+
async downgrade(migrations, steps = 1) {
|
|
1315
|
+
const done = await this.applied();
|
|
1316
|
+
const ordered = topoOrder(migrations).filter((m) => done.has(m.revision));
|
|
1317
|
+
const toRevert = ordered.slice(-steps).reverse();
|
|
1318
|
+
const reverted = [];
|
|
1319
|
+
for (const migration of toRevert) {
|
|
1320
|
+
const op = new Op();
|
|
1321
|
+
try {
|
|
1322
|
+
migration.down(op);
|
|
1323
|
+
} catch {
|
|
1324
|
+
op.operations.length = 0;
|
|
1325
|
+
}
|
|
1326
|
+
if (op.operations.length === 0) {
|
|
1327
|
+
const upOp = new Op();
|
|
1328
|
+
migration.up(upOp);
|
|
1329
|
+
op.operations.push(...invertAll(upOp.operations));
|
|
1330
|
+
}
|
|
1331
|
+
await this.runOps(op.operations);
|
|
1332
|
+
await this.forget(migration.revision);
|
|
1333
|
+
reverted.push(migration.revision);
|
|
1334
|
+
}
|
|
1335
|
+
return reverted;
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
859
1338
|
|
|
860
1339
|
// src/migrations/replay.ts
|
|
861
1340
|
function applyOperation(schema, op) {
|
|
@@ -919,6 +1398,30 @@ function applyOperation(schema, op) {
|
|
|
919
1398
|
}
|
|
920
1399
|
break;
|
|
921
1400
|
}
|
|
1401
|
+
case "add_constraint": {
|
|
1402
|
+
const t = tables[op.table];
|
|
1403
|
+
if (t) {
|
|
1404
|
+
tables[op.table] = op.constraint.type === "unique" ? {
|
|
1405
|
+
...t,
|
|
1406
|
+
uniqueConstraints: [...t.uniqueConstraints, op.constraint.constraint]
|
|
1407
|
+
} : { ...t, foreignKeys: [...t.foreignKeys, op.constraint.constraint] };
|
|
1408
|
+
}
|
|
1409
|
+
break;
|
|
1410
|
+
}
|
|
1411
|
+
case "drop_constraint": {
|
|
1412
|
+
const t = tables[op.table];
|
|
1413
|
+
if (t) {
|
|
1414
|
+
const dropName = op.constraint.constraint.name;
|
|
1415
|
+
tables[op.table] = op.constraint.type === "unique" ? {
|
|
1416
|
+
...t,
|
|
1417
|
+
uniqueConstraints: t.uniqueConstraints.filter((u) => u.name !== dropName)
|
|
1418
|
+
} : {
|
|
1419
|
+
...t,
|
|
1420
|
+
foreignKeys: t.foreignKeys.filter((f) => f.name !== dropName)
|
|
1421
|
+
};
|
|
1422
|
+
}
|
|
1423
|
+
break;
|
|
1424
|
+
}
|
|
922
1425
|
}
|
|
923
1426
|
return { tables };
|
|
924
1427
|
}
|
|
@@ -1055,6 +1558,6 @@ function runMigrationCli(argv, config) {
|
|
|
1055
1558
|
}
|
|
1056
1559
|
}
|
|
1057
1560
|
|
|
1058
|
-
export { CyclicMigrationGraph, IrreversibleMigration, MigrationRunner, Op, UnknownRevision, applyOperation, applyRenames, checkDrift, checkDriftPostgres, defineMigrationConfig, detectRenames, diffSchema, emptySchema, generateMigration, heads, introspectPostgres, introspectSqlite, invert, invertAll, makeRevisionId, reflectSchema, reflectTable, renderColumnDef, renderColumnType, renderDefault, renderOperation, replaySchema, runMigrationCli, sqliteAffinity, topoOrder };
|
|
1059
|
-
//# sourceMappingURL=chunk-
|
|
1060
|
-
//# sourceMappingURL=chunk-
|
|
1561
|
+
export { AsyncMigrationRunner, CyclicMigrationGraph, IrreversibleMigration, MigrationRunner, Op, UnknownRevision, applyOperation, applyRenames, checkDrift, checkDriftPostgres, defineMigrationConfig, detectRenames, diffSchema, emptySchema, generateMigration, heads, introspectPostgres, introspectSqlite, invert, invertAll, makeRevisionId, reflectSchema, reflectTable, renderColumnDef, renderColumnType, renderDefault, renderOperation, replaySchema, runMigrationCli, sqliteAffinity, topoOrder };
|
|
1562
|
+
//# sourceMappingURL=chunk-43XL66JG.js.map
|
|
1563
|
+
//# sourceMappingURL=chunk-43XL66JG.js.map
|