rake-db 2.27.10 → 2.27.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +14 -13
- package/dist/index.js +259 -271
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +262 -274
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,104 @@
|
|
|
1
|
-
import { escapeForMigration, ArrayColumn, DomainColumn, EnumColumn,
|
|
2
|
-
import { singleQuote, isRawSQL, toSnakeCase, toCamelCase, toArray, snakeCaseKey, emptyObject, setCurrentColumnName, consumeColumnName, ColumnTypeBase, setDefaultLanguage, deepCompare, getImportPath, pathToLog, emptyArray, codeToString, addCode, quoteObjectKey, backtickQuote
|
|
1
|
+
import { defaultSchemaConfig, makeColumnTypes, escapeForMigration, ArrayColumn, DomainColumn, EnumColumn, getColumnTypes, parseTableData, escapeString, tableDataMethods, ColumnType, parseTableDataInput, UnknownColumn, raw, logParamToLogObject, createDbWithAdapter, makeColumnsByType, RawSQL, CustomTypeColumn, assignDbDataToColumn, PostgisGeographyPointColumn, pushTableDataCode, primaryKeyInnerToCode, indexInnerToCode, excludeInnerToCode, constraintInnerToCode, referencesArgsToCode, TimestampTZColumn, TimestampColumn } from 'pqb';
|
|
2
|
+
import { getStackTrace, singleQuote, isRawSQL, toSnakeCase, toCamelCase, toArray, snakeCaseKey, emptyObject, setCurrentColumnName, consumeColumnName, ColumnTypeBase, setDefaultLanguage, deepCompare, getImportPath, pathToLog, emptyArray, codeToString, addCode, quoteObjectKey, backtickQuote } from 'orchid-core';
|
|
3
3
|
import path, { join } from 'path';
|
|
4
|
-
import {
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
5
5
|
import fs, { mkdir, writeFile, readdir, stat, readFile } from 'fs/promises';
|
|
6
6
|
import 'url';
|
|
7
7
|
import 'node:path';
|
|
8
8
|
|
|
9
|
+
class RakeDbError extends Error {
|
|
10
|
+
}
|
|
11
|
+
class NoPrimaryKey extends RakeDbError {
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let currentChanges = [];
|
|
15
|
+
const clearChanges = () => {
|
|
16
|
+
currentChanges = [];
|
|
17
|
+
};
|
|
18
|
+
const getCurrentChanges = () => currentChanges;
|
|
19
|
+
const pushChange = (change) => currentChanges.push(change);
|
|
20
|
+
|
|
21
|
+
const migrationConfigDefaults = {
|
|
22
|
+
schemaConfig: defaultSchemaConfig,
|
|
23
|
+
migrationsPath: path.join("src", "db", "migrations"),
|
|
24
|
+
migrationId: { serial: 4 },
|
|
25
|
+
migrationsTable: "schemaMigrations",
|
|
26
|
+
snakeCase: false,
|
|
27
|
+
commands: {},
|
|
28
|
+
log: true,
|
|
29
|
+
logger: console,
|
|
30
|
+
import() {
|
|
31
|
+
throw new Error(
|
|
32
|
+
"Add `import: (path) => import(path),` setting to `rakeDb` config"
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const ensureMigrationsPath = (config) => {
|
|
37
|
+
if (!config.migrationsPath) {
|
|
38
|
+
config.migrationsPath = migrationConfigDefaults.migrationsPath;
|
|
39
|
+
}
|
|
40
|
+
if (!path.isAbsolute(config.migrationsPath)) {
|
|
41
|
+
config.migrationsPath = path.resolve(
|
|
42
|
+
config.basePath,
|
|
43
|
+
config.migrationsPath
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return config;
|
|
47
|
+
};
|
|
48
|
+
const ensureBasePathAndDbScript = (config, intermediateCallers = 0) => {
|
|
49
|
+
if (config.basePath && config.dbScript) return config;
|
|
50
|
+
let filePath = getStackTrace()?.[3 + intermediateCallers].getFileName();
|
|
51
|
+
if (!filePath) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
"Failed to determine path to db script. Please set basePath option of rakeDb"
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
if (filePath.startsWith("file://")) {
|
|
57
|
+
filePath = fileURLToPath(filePath);
|
|
58
|
+
}
|
|
59
|
+
const ext = path.extname(filePath);
|
|
60
|
+
if (ext !== ".ts" && ext !== ".js" && ext !== ".mjs") {
|
|
61
|
+
throw new Error(
|
|
62
|
+
`Add a .ts suffix to the "${path.basename(filePath)}" when calling it`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
config.basePath = path.dirname(filePath);
|
|
66
|
+
config.dbScript = path.basename(filePath);
|
|
67
|
+
return config;
|
|
68
|
+
};
|
|
69
|
+
const processRakeDbConfig = (config) => {
|
|
70
|
+
const result = { ...migrationConfigDefaults, ...config };
|
|
71
|
+
if (!result.log) {
|
|
72
|
+
delete result.logger;
|
|
73
|
+
}
|
|
74
|
+
ensureBasePathAndDbScript(result, 1);
|
|
75
|
+
ensureMigrationsPath(result);
|
|
76
|
+
if (!result.recurrentPath) {
|
|
77
|
+
result.recurrentPath = path.join(
|
|
78
|
+
result.migrationsPath,
|
|
79
|
+
"recurrent"
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
if ("recurrentPath" in result && !path.isAbsolute(result.recurrentPath)) {
|
|
83
|
+
result.recurrentPath = path.resolve(result.basePath, result.recurrentPath);
|
|
84
|
+
}
|
|
85
|
+
if ("baseTable" in config && config.baseTable) {
|
|
86
|
+
const { types, snakeCase, language } = config.baseTable.prototype;
|
|
87
|
+
result.columnTypes = types || makeColumnTypes(defaultSchemaConfig);
|
|
88
|
+
if (snakeCase) result.snakeCase = true;
|
|
89
|
+
if (language) result.language = language;
|
|
90
|
+
} else {
|
|
91
|
+
const ct = "columnTypes" in config && config.columnTypes;
|
|
92
|
+
result.columnTypes = (typeof ct === "function" ? ct(
|
|
93
|
+
makeColumnTypes(defaultSchemaConfig)
|
|
94
|
+
) : ct) || makeColumnTypes(defaultSchemaConfig);
|
|
95
|
+
}
|
|
96
|
+
if (config.migrationId === "serial") {
|
|
97
|
+
result.migrationId = { serial: 4 };
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
};
|
|
101
|
+
|
|
9
102
|
const getFirstWordAndRest = (input) => {
|
|
10
103
|
const i = input.search(/(?=[A-Z])|[-_ ]/);
|
|
11
104
|
if (i !== -1) {
|
|
@@ -73,13 +166,6 @@ const transaction = (adapter, fn) => {
|
|
|
73
166
|
};
|
|
74
167
|
const queryLock = (trx) => trx.query(`SELECT pg_advisory_xact_lock('${RAKE_DB_LOCK_KEY}')`);
|
|
75
168
|
|
|
76
|
-
let currentChanges = [];
|
|
77
|
-
const clearChanges = () => {
|
|
78
|
-
currentChanges = [];
|
|
79
|
-
};
|
|
80
|
-
const getCurrentChanges = () => currentChanges;
|
|
81
|
-
const pushChange = (change) => currentChanges.push(change);
|
|
82
|
-
|
|
83
169
|
const versionToString = (config, version) => config.migrationId === "timestamp" ? `${version}` : `${version}`.padStart(config.migrationId.serial, "0");
|
|
84
170
|
const columnTypeToSql = (item) => {
|
|
85
171
|
return item.data.isOfCustomType ? item instanceof DomainColumn ? quoteNameFromString(item.dataType) : quoteCustomType(item.toSQL()) : item.toSQL();
|
|
@@ -463,11 +549,6 @@ const tableMethods = {
|
|
|
463
549
|
}
|
|
464
550
|
};
|
|
465
551
|
|
|
466
|
-
class RakeDbError extends Error {
|
|
467
|
-
}
|
|
468
|
-
class NoPrimaryKey extends RakeDbError {
|
|
469
|
-
}
|
|
470
|
-
|
|
471
552
|
const createTable = async (migration, up, tableName, first, second, third) => {
|
|
472
553
|
let options;
|
|
473
554
|
let fn;
|
|
@@ -3051,7 +3132,6 @@ const makeMigrateCommand = (migrateFn, defaultCount) => {
|
|
|
3051
3132
|
}
|
|
3052
3133
|
for (const adapter of adapters) {
|
|
3053
3134
|
await migrateFn({ ctx: {}, adapter, config, count, force });
|
|
3054
|
-
await adapter.close();
|
|
3055
3135
|
}
|
|
3056
3136
|
};
|
|
3057
3137
|
};
|
|
@@ -3521,7 +3601,7 @@ const resetDb = async (adapters, config) => {
|
|
|
3521
3601
|
await dropDb(adapters, config);
|
|
3522
3602
|
await createDb(adapters, config);
|
|
3523
3603
|
for (const adapter of adapters) {
|
|
3524
|
-
await
|
|
3604
|
+
await migrate({ adapter, config });
|
|
3525
3605
|
}
|
|
3526
3606
|
};
|
|
3527
3607
|
const askForAdminCredentials = async (create) => {
|
|
@@ -3546,6 +3626,44 @@ const askForAdminCredentials = async (create) => {
|
|
|
3546
3626
|
};
|
|
3547
3627
|
};
|
|
3548
3628
|
|
|
3629
|
+
const runRecurrentMigrations = async (adapters, config) => {
|
|
3630
|
+
let dbs;
|
|
3631
|
+
let files = 0;
|
|
3632
|
+
await readdirRecursive(config.recurrentPath, async (path) => {
|
|
3633
|
+
files++;
|
|
3634
|
+
dbs ?? (dbs = adapters.map((adapter) => createDbWithAdapter({ adapter })));
|
|
3635
|
+
const sql = await readFile(path, "utf-8");
|
|
3636
|
+
await Promise.all(
|
|
3637
|
+
dbs.map(async (db) => {
|
|
3638
|
+
await db.adapter.arrays(sql);
|
|
3639
|
+
})
|
|
3640
|
+
);
|
|
3641
|
+
});
|
|
3642
|
+
if (files > 0) {
|
|
3643
|
+
config.logger?.log(
|
|
3644
|
+
`Applied ${files} recurrent migration file${files > 1 ? "s" : ""}`
|
|
3645
|
+
);
|
|
3646
|
+
}
|
|
3647
|
+
};
|
|
3648
|
+
const readdirRecursive = async (dirPath, cb) => {
|
|
3649
|
+
const list = await readdir(dirPath).catch((err) => {
|
|
3650
|
+
if (err.code !== "ENOENT") throw err;
|
|
3651
|
+
return;
|
|
3652
|
+
});
|
|
3653
|
+
if (!list) return;
|
|
3654
|
+
await Promise.all(
|
|
3655
|
+
list.map(async (item) => {
|
|
3656
|
+
const path = join(dirPath, item);
|
|
3657
|
+
const info = await stat(path);
|
|
3658
|
+
if (info.isDirectory()) {
|
|
3659
|
+
await readdirRecursive(path, cb);
|
|
3660
|
+
} else if (info.isFile() && path.endsWith(".sql")) {
|
|
3661
|
+
await cb(path);
|
|
3662
|
+
}
|
|
3663
|
+
})
|
|
3664
|
+
);
|
|
3665
|
+
};
|
|
3666
|
+
|
|
3549
3667
|
const filterSchema = (table) => `${table} !~ '^pg_' AND ${table} != 'information_schema'`;
|
|
3550
3668
|
const jsonAgg = (sql2, as) => `(SELECT coalesce(json_agg(t.*), '[]') FROM (${sql2}) t) AS "${as}"`;
|
|
3551
3669
|
const columnsSql = ({
|
|
@@ -5257,7 +5375,6 @@ const pullDbStructure = async (adapter, config) => {
|
|
|
5257
5375
|
const currentSchema = adapter.schema || "public";
|
|
5258
5376
|
const ctx = makeStructureToAstCtx(config, currentSchema);
|
|
5259
5377
|
const ast = await structureToAst(ctx, adapter, config);
|
|
5260
|
-
await adapter.close();
|
|
5261
5378
|
const result = astToMigration(currentSchema, config, ast);
|
|
5262
5379
|
if (!result) return;
|
|
5263
5380
|
const version = await makeFileVersion({}, config);
|
|
@@ -5281,220 +5398,6 @@ Append \`as\` method manually to ${count > 1 ? "these" : "this"} column${count >
|
|
|
5281
5398
|
);
|
|
5282
5399
|
}
|
|
5283
5400
|
config.logger?.log("Database pulled successfully");
|
|
5284
|
-
adapter.close();
|
|
5285
|
-
};
|
|
5286
|
-
|
|
5287
|
-
const runRecurrentMigrations = async (adapters, config) => {
|
|
5288
|
-
let dbs;
|
|
5289
|
-
let files = 0;
|
|
5290
|
-
await readdirRecursive(config.recurrentPath, async (path) => {
|
|
5291
|
-
files++;
|
|
5292
|
-
dbs ?? (dbs = adapters.map((adapter) => createDbWithAdapter({ adapter })));
|
|
5293
|
-
const sql = await readFile(path, "utf-8");
|
|
5294
|
-
await Promise.all(
|
|
5295
|
-
dbs.map(async (db) => {
|
|
5296
|
-
await db.adapter.arrays(sql);
|
|
5297
|
-
})
|
|
5298
|
-
);
|
|
5299
|
-
});
|
|
5300
|
-
if (dbs) {
|
|
5301
|
-
await Promise.all(dbs.map((db) => db.close()));
|
|
5302
|
-
if (files > 0) {
|
|
5303
|
-
config.logger?.log(
|
|
5304
|
-
`Applied ${files} recurrent migration file${files > 1 ? "s" : ""}`
|
|
5305
|
-
);
|
|
5306
|
-
}
|
|
5307
|
-
}
|
|
5308
|
-
};
|
|
5309
|
-
const readdirRecursive = async (dirPath, cb) => {
|
|
5310
|
-
const list = await readdir(dirPath).catch((err) => {
|
|
5311
|
-
if (err.code !== "ENOENT") throw err;
|
|
5312
|
-
return;
|
|
5313
|
-
});
|
|
5314
|
-
if (!list) return;
|
|
5315
|
-
await Promise.all(
|
|
5316
|
-
list.map(async (item) => {
|
|
5317
|
-
const path = join(dirPath, item);
|
|
5318
|
-
const info = await stat(path);
|
|
5319
|
-
if (info.isDirectory()) {
|
|
5320
|
-
await readdirRecursive(path, cb);
|
|
5321
|
-
} else if (info.isFile() && path.endsWith(".sql")) {
|
|
5322
|
-
await cb(path);
|
|
5323
|
-
}
|
|
5324
|
-
})
|
|
5325
|
-
);
|
|
5326
|
-
};
|
|
5327
|
-
|
|
5328
|
-
const listMigrationsStatuses = async (adapters, config, args) => {
|
|
5329
|
-
const ctx = {};
|
|
5330
|
-
const [{ migrations }, ...migrated] = await Promise.all([
|
|
5331
|
-
getMigrations(ctx, config, true),
|
|
5332
|
-
...adapters.map((adapter) => getMigratedVersionsMap(ctx, adapter, config))
|
|
5333
|
-
]);
|
|
5334
|
-
const map = {};
|
|
5335
|
-
let maxVersionLength = 12;
|
|
5336
|
-
let maxNameLength = 4;
|
|
5337
|
-
for (let i = 0; i < adapters.length; i++) {
|
|
5338
|
-
const list = migrated[i];
|
|
5339
|
-
const key = Object.entries(list.map).map(([version, up]) => `${version}${up ? "t" : "f"}`).join("");
|
|
5340
|
-
const database = adapters[i].getDatabase();
|
|
5341
|
-
if (map[key]) {
|
|
5342
|
-
map[key].databases.push(database);
|
|
5343
|
-
continue;
|
|
5344
|
-
}
|
|
5345
|
-
map[key] = {
|
|
5346
|
-
databases: [database],
|
|
5347
|
-
migrations: migrations.map((item) => {
|
|
5348
|
-
if (item.version.length > maxVersionLength) {
|
|
5349
|
-
maxVersionLength = item.version.length;
|
|
5350
|
-
}
|
|
5351
|
-
const name = path.parse(item.path).name.slice(item.version.length + 1).replace(
|
|
5352
|
-
/([a-z])([A-Z])/g,
|
|
5353
|
-
(_, a, b) => `${a} ${b.toLocaleLowerCase()}`
|
|
5354
|
-
).replace(/[-_](.)/g, (_, char) => ` ${char.toLocaleLowerCase()}`).replace(/^\w/, (match) => match.toLocaleUpperCase());
|
|
5355
|
-
if (name.length > maxNameLength) {
|
|
5356
|
-
maxNameLength = name.length;
|
|
5357
|
-
}
|
|
5358
|
-
return {
|
|
5359
|
-
up: !!list.map[item.version],
|
|
5360
|
-
version: item.version,
|
|
5361
|
-
name,
|
|
5362
|
-
url: pathToFileURL(item.path)
|
|
5363
|
-
};
|
|
5364
|
-
})
|
|
5365
|
-
};
|
|
5366
|
-
}
|
|
5367
|
-
const showUrl = args.includes("p") || args.includes("path");
|
|
5368
|
-
const asIs = (s) => s;
|
|
5369
|
-
const c = typeof config.log === "object" && config.log.colors === false ? {
|
|
5370
|
-
yellow: asIs,
|
|
5371
|
-
green: asIs,
|
|
5372
|
-
red: asIs,
|
|
5373
|
-
blue: asIs
|
|
5374
|
-
} : colors;
|
|
5375
|
-
const log = Object.values(map).map(({ databases, migrations: migrations2 }) => {
|
|
5376
|
-
let log2 = ` ${c.yellow("Database:")} ${databases.join(", ")}`;
|
|
5377
|
-
if (migrations2.length === 0) {
|
|
5378
|
-
return log2 + `
|
|
5379
|
-
|
|
5380
|
-
No migrations available`;
|
|
5381
|
-
}
|
|
5382
|
-
const lineSeparator = c.yellow(
|
|
5383
|
-
makeChars(14 + maxVersionLength + maxNameLength, "-")
|
|
5384
|
-
);
|
|
5385
|
-
const columnSeparator = c.yellow("|");
|
|
5386
|
-
log2 += "\n\n " + c.yellow(
|
|
5387
|
-
`Status | Migration ID${makeChars(
|
|
5388
|
-
maxVersionLength - 12,
|
|
5389
|
-
" "
|
|
5390
|
-
)} | Name
|
|
5391
|
-
${lineSeparator}`
|
|
5392
|
-
);
|
|
5393
|
-
for (const migration of migrations2) {
|
|
5394
|
-
log2 += `
|
|
5395
|
-
${migration.up ? ` ${c.green("Up")} ` : c.red("Down")} ${columnSeparator} ${c.blue(migration.version)}${makeChars(
|
|
5396
|
-
maxVersionLength - migration.version.length,
|
|
5397
|
-
" "
|
|
5398
|
-
)} ${columnSeparator} ${migration.name}`;
|
|
5399
|
-
if (showUrl) {
|
|
5400
|
-
log2 += `
|
|
5401
|
-
${migration.url}
|
|
5402
|
-
`;
|
|
5403
|
-
}
|
|
5404
|
-
}
|
|
5405
|
-
return log2 += showUrl ? lineSeparator : `
|
|
5406
|
-
${lineSeparator}`;
|
|
5407
|
-
}).join("\n\n");
|
|
5408
|
-
(config.logger ?? console).log(log);
|
|
5409
|
-
await Promise.all(adapters.map((adapter) => adapter.close()));
|
|
5410
|
-
};
|
|
5411
|
-
const makeChars = (count, char) => {
|
|
5412
|
-
let chars = "";
|
|
5413
|
-
for (let i = 0; i < count; i++) {
|
|
5414
|
-
chars += char;
|
|
5415
|
-
}
|
|
5416
|
-
return chars;
|
|
5417
|
-
};
|
|
5418
|
-
|
|
5419
|
-
const migrationConfigDefaults = {
|
|
5420
|
-
schemaConfig: defaultSchemaConfig,
|
|
5421
|
-
migrationsPath: path.join("src", "db", "migrations"),
|
|
5422
|
-
migrationId: { serial: 4 },
|
|
5423
|
-
migrationsTable: "schemaMigrations",
|
|
5424
|
-
snakeCase: false,
|
|
5425
|
-
commands: {},
|
|
5426
|
-
log: true,
|
|
5427
|
-
logger: console,
|
|
5428
|
-
import() {
|
|
5429
|
-
throw new Error(
|
|
5430
|
-
"Add `import: (path) => import(path),` setting to `rakeDb` config"
|
|
5431
|
-
);
|
|
5432
|
-
}
|
|
5433
|
-
};
|
|
5434
|
-
const ensureMigrationsPath = (config) => {
|
|
5435
|
-
if (!config.migrationsPath) {
|
|
5436
|
-
config.migrationsPath = migrationConfigDefaults.migrationsPath;
|
|
5437
|
-
}
|
|
5438
|
-
if (!path.isAbsolute(config.migrationsPath)) {
|
|
5439
|
-
config.migrationsPath = path.resolve(
|
|
5440
|
-
config.basePath,
|
|
5441
|
-
config.migrationsPath
|
|
5442
|
-
);
|
|
5443
|
-
}
|
|
5444
|
-
return config;
|
|
5445
|
-
};
|
|
5446
|
-
const ensureBasePathAndDbScript = (config, intermediateCallers = 0) => {
|
|
5447
|
-
if (config.basePath && config.dbScript) return config;
|
|
5448
|
-
let filePath = getStackTrace()?.[3 + intermediateCallers].getFileName();
|
|
5449
|
-
if (!filePath) {
|
|
5450
|
-
throw new Error(
|
|
5451
|
-
"Failed to determine path to db script. Please set basePath option of rakeDb"
|
|
5452
|
-
);
|
|
5453
|
-
}
|
|
5454
|
-
if (filePath.startsWith("file://")) {
|
|
5455
|
-
filePath = fileURLToPath(filePath);
|
|
5456
|
-
}
|
|
5457
|
-
const ext = path.extname(filePath);
|
|
5458
|
-
if (ext !== ".ts" && ext !== ".js" && ext !== ".mjs") {
|
|
5459
|
-
throw new Error(
|
|
5460
|
-
`Add a .ts suffix to the "${path.basename(filePath)}" when calling it`
|
|
5461
|
-
);
|
|
5462
|
-
}
|
|
5463
|
-
config.basePath = path.dirname(filePath);
|
|
5464
|
-
config.dbScript = path.basename(filePath);
|
|
5465
|
-
return config;
|
|
5466
|
-
};
|
|
5467
|
-
const processRakeDbConfig = (config) => {
|
|
5468
|
-
const result = { ...migrationConfigDefaults, ...config };
|
|
5469
|
-
if (!result.log) {
|
|
5470
|
-
delete result.logger;
|
|
5471
|
-
}
|
|
5472
|
-
ensureBasePathAndDbScript(result, 1);
|
|
5473
|
-
ensureMigrationsPath(result);
|
|
5474
|
-
if (!result.recurrentPath) {
|
|
5475
|
-
result.recurrentPath = path.join(
|
|
5476
|
-
result.migrationsPath,
|
|
5477
|
-
"recurrent"
|
|
5478
|
-
);
|
|
5479
|
-
}
|
|
5480
|
-
if ("recurrentPath" in result && !path.isAbsolute(result.recurrentPath)) {
|
|
5481
|
-
result.recurrentPath = path.resolve(result.basePath, result.recurrentPath);
|
|
5482
|
-
}
|
|
5483
|
-
if ("baseTable" in config && config.baseTable) {
|
|
5484
|
-
const { types, snakeCase, language } = config.baseTable.prototype;
|
|
5485
|
-
result.columnTypes = types || makeColumnTypes(defaultSchemaConfig);
|
|
5486
|
-
if (snakeCase) result.snakeCase = true;
|
|
5487
|
-
if (language) result.language = language;
|
|
5488
|
-
} else {
|
|
5489
|
-
const ct = "columnTypes" in config && config.columnTypes;
|
|
5490
|
-
result.columnTypes = (typeof ct === "function" ? ct(
|
|
5491
|
-
makeColumnTypes(defaultSchemaConfig)
|
|
5492
|
-
) : ct) || makeColumnTypes(defaultSchemaConfig);
|
|
5493
|
-
}
|
|
5494
|
-
if (config.migrationId === "serial") {
|
|
5495
|
-
result.migrationId = { serial: 4 };
|
|
5496
|
-
}
|
|
5497
|
-
return result;
|
|
5498
5401
|
};
|
|
5499
5402
|
|
|
5500
5403
|
const rebase = async (adapters, config) => {
|
|
@@ -5511,7 +5414,6 @@ const rebase = async (adapters, config) => {
|
|
|
5511
5414
|
await getMigrations(ctx, config, true, true),
|
|
5512
5415
|
...adapters.map((adapter) => getMigratedVersionsMap(ctx, adapter, config))
|
|
5513
5416
|
]);
|
|
5514
|
-
await Promise.all(adapters.map((adapter) => adapter.close()));
|
|
5515
5417
|
const files = set.migrations.map((file) => ({
|
|
5516
5418
|
...file,
|
|
5517
5419
|
name: path.basename(file.path),
|
|
@@ -5641,7 +5543,6 @@ const rebase = async (adapters, config) => {
|
|
|
5641
5543
|
adapter,
|
|
5642
5544
|
config: redoConfig
|
|
5643
5545
|
});
|
|
5644
|
-
await adapter.close();
|
|
5645
5546
|
}
|
|
5646
5547
|
for (let i = renames.length - 1; i >= 0; i--) {
|
|
5647
5548
|
const [from, version] = renames[i];
|
|
@@ -5656,37 +5557,97 @@ const rebase = async (adapters, config) => {
|
|
|
5656
5557
|
}
|
|
5657
5558
|
};
|
|
5658
5559
|
|
|
5659
|
-
const
|
|
5660
|
-
const
|
|
5661
|
-
const
|
|
5662
|
-
|
|
5663
|
-
config
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5560
|
+
const listMigrationsStatuses = async (adapters, config, args) => {
|
|
5561
|
+
const ctx = {};
|
|
5562
|
+
const [{ migrations }, ...migrated] = await Promise.all([
|
|
5563
|
+
getMigrations(ctx, config, true),
|
|
5564
|
+
...adapters.map((adapter) => getMigratedVersionsMap(ctx, adapter, config))
|
|
5565
|
+
]);
|
|
5566
|
+
const map = {};
|
|
5567
|
+
let maxVersionLength = 12;
|
|
5568
|
+
let maxNameLength = 4;
|
|
5569
|
+
for (let i = 0; i < adapters.length; i++) {
|
|
5570
|
+
const list = migrated[i];
|
|
5571
|
+
const key = Object.entries(list.map).map(([version, up]) => `${version}${up ? "t" : "f"}`).join("");
|
|
5572
|
+
const database = adapters[i].getDatabase();
|
|
5573
|
+
if (map[key]) {
|
|
5574
|
+
map[key].databases.push(database);
|
|
5575
|
+
continue;
|
|
5669
5576
|
}
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
}
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5577
|
+
map[key] = {
|
|
5578
|
+
databases: [database],
|
|
5579
|
+
migrations: migrations.map((item) => {
|
|
5580
|
+
if (item.version.length > maxVersionLength) {
|
|
5581
|
+
maxVersionLength = item.version.length;
|
|
5582
|
+
}
|
|
5583
|
+
const name = path.parse(item.path).name.slice(item.version.length + 1).replace(
|
|
5584
|
+
/([a-z])([A-Z])/g,
|
|
5585
|
+
(_, a, b) => `${a} ${b.toLocaleLowerCase()}`
|
|
5586
|
+
).replace(/[-_](.)/g, (_, char) => ` ${char.toLocaleLowerCase()}`).replace(/^\w/, (match) => match.toLocaleUpperCase());
|
|
5587
|
+
if (name.length > maxNameLength) {
|
|
5588
|
+
maxNameLength = name.length;
|
|
5589
|
+
}
|
|
5590
|
+
return {
|
|
5591
|
+
up: !!list.map[item.version],
|
|
5592
|
+
version: item.version,
|
|
5593
|
+
name,
|
|
5594
|
+
url: pathToFileURL(item.path)
|
|
5595
|
+
};
|
|
5596
|
+
})
|
|
5597
|
+
};
|
|
5598
|
+
}
|
|
5599
|
+
const showUrl = args.includes("p") || args.includes("path");
|
|
5600
|
+
const asIs = (s) => s;
|
|
5601
|
+
const c = typeof config.log === "object" && config.log.colors === false ? {
|
|
5602
|
+
yellow: asIs,
|
|
5603
|
+
green: asIs,
|
|
5604
|
+
red: asIs,
|
|
5605
|
+
blue: asIs
|
|
5606
|
+
} : colors;
|
|
5607
|
+
const log = Object.values(map).map(({ databases, migrations: migrations2 }) => {
|
|
5608
|
+
let log2 = ` ${c.yellow("Database:")} ${databases.join(", ")}`;
|
|
5609
|
+
if (migrations2.length === 0) {
|
|
5610
|
+
return log2 + `
|
|
5611
|
+
|
|
5612
|
+
No migrations available`;
|
|
5682
5613
|
}
|
|
5683
|
-
|
|
5614
|
+
const lineSeparator = c.yellow(
|
|
5615
|
+
makeChars(14 + maxVersionLength + maxNameLength, "-")
|
|
5616
|
+
);
|
|
5617
|
+
const columnSeparator = c.yellow("|");
|
|
5618
|
+
log2 += "\n\n " + c.yellow(
|
|
5619
|
+
`Status | Migration ID${makeChars(
|
|
5620
|
+
maxVersionLength - 12,
|
|
5621
|
+
" "
|
|
5622
|
+
)} | Name
|
|
5623
|
+
${lineSeparator}`
|
|
5624
|
+
);
|
|
5625
|
+
for (const migration of migrations2) {
|
|
5626
|
+
log2 += `
|
|
5627
|
+
${migration.up ? ` ${c.green("Up")} ` : c.red("Down")} ${columnSeparator} ${c.blue(migration.version)}${makeChars(
|
|
5628
|
+
maxVersionLength - migration.version.length,
|
|
5629
|
+
" "
|
|
5630
|
+
)} ${columnSeparator} ${migration.name}`;
|
|
5631
|
+
if (showUrl) {
|
|
5632
|
+
log2 += `
|
|
5633
|
+
${migration.url}
|
|
5634
|
+
`;
|
|
5635
|
+
}
|
|
5636
|
+
}
|
|
5637
|
+
return log2 += showUrl ? lineSeparator : `
|
|
5638
|
+
${lineSeparator}`;
|
|
5639
|
+
}).join("\n\n");
|
|
5640
|
+
(config.logger ?? console).log(log);
|
|
5641
|
+
await Promise.all(adapters.map((adapter) => adapter.close()));
|
|
5684
5642
|
};
|
|
5685
|
-
const
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5643
|
+
const makeChars = (count, char) => {
|
|
5644
|
+
let chars = "";
|
|
5645
|
+
for (let i = 0; i < count; i++) {
|
|
5646
|
+
chars += char;
|
|
5647
|
+
}
|
|
5648
|
+
return chars;
|
|
5689
5649
|
};
|
|
5650
|
+
|
|
5690
5651
|
const rakeDbAliases = {
|
|
5691
5652
|
migrate: "up",
|
|
5692
5653
|
rollback: "down",
|
|
@@ -5762,10 +5723,9 @@ ${Object.entries(helpArguments).map(
|
|
|
5762
5723
|
args
|
|
5763
5724
|
};
|
|
5764
5725
|
};
|
|
5726
|
+
const close = (adapters) => Promise.all(adapters.map((adapter) => adapter.close()));
|
|
5765
5727
|
const upCommand = {
|
|
5766
|
-
run: (adapters, config, args) => migrateCommand(adapters, config, args).then(
|
|
5767
|
-
() => runRecurrentMigrations(adapters, config)
|
|
5768
|
-
),
|
|
5728
|
+
run: (adapters, config, args) => migrateCommand(adapters, config, args).then(() => runRecurrentMigrations(adapters, config)).then(() => close(adapters)),
|
|
5769
5729
|
help: "migrate pending migrations",
|
|
5770
5730
|
helpArguments: {
|
|
5771
5731
|
"no arguments": "migrate all pending",
|
|
@@ -5774,7 +5734,7 @@ const upCommand = {
|
|
|
5774
5734
|
}
|
|
5775
5735
|
};
|
|
5776
5736
|
const downCommand = {
|
|
5777
|
-
run: (adapters, config, args) => rollbackCommand(adapters, config, args),
|
|
5737
|
+
run: (adapters, config, args) => rollbackCommand(adapters, config, args).then(() => close(adapters)),
|
|
5778
5738
|
help: "rollback migrated migrations",
|
|
5779
5739
|
helpArguments: {
|
|
5780
5740
|
"no arguments": "rollback one last migration",
|
|
@@ -5791,7 +5751,7 @@ const statusCommand = {
|
|
|
5791
5751
|
}
|
|
5792
5752
|
};
|
|
5793
5753
|
const recurrentCommand = {
|
|
5794
|
-
run: runRecurrentMigrations,
|
|
5754
|
+
run: (adapters, config) => runRecurrentMigrations(adapters, config).then(() => close(adapters)),
|
|
5795
5755
|
help: "run recurrent migrations"
|
|
5796
5756
|
};
|
|
5797
5757
|
const rakeDbCommands = {
|
|
@@ -5804,9 +5764,7 @@ const rakeDbCommands = {
|
|
|
5804
5764
|
help: "drop databases"
|
|
5805
5765
|
},
|
|
5806
5766
|
reset: {
|
|
5807
|
-
run: (adapters, config) => resetDb(adapters, config).then(
|
|
5808
|
-
() => runRecurrentMigrations(adapters, config)
|
|
5809
|
-
),
|
|
5767
|
+
run: (adapters, config) => resetDb(adapters, config).then(() => runRecurrentMigrations(adapters, config)).then(() => close(adapters)),
|
|
5810
5768
|
help: "drop, create and migrate databases"
|
|
5811
5769
|
},
|
|
5812
5770
|
up: upCommand,
|
|
@@ -5814,13 +5772,11 @@ const rakeDbCommands = {
|
|
|
5814
5772
|
down: downCommand,
|
|
5815
5773
|
rollback: downCommand,
|
|
5816
5774
|
redo: {
|
|
5817
|
-
run: (adapters, config, args) => redoCommand(adapters, config, args).then(
|
|
5818
|
-
() => runRecurrentMigrations(adapters, config)
|
|
5819
|
-
),
|
|
5775
|
+
run: (adapters, config, args) => redoCommand(adapters, config, args).then(() => runRecurrentMigrations(adapters, config)).then(() => close(adapters)),
|
|
5820
5776
|
help: "rollback and migrate, run recurrent"
|
|
5821
5777
|
},
|
|
5822
5778
|
pull: {
|
|
5823
|
-
run: ([adapter], config) => pullDbStructure(adapter, config),
|
|
5779
|
+
run: ([adapter], config) => pullDbStructure(adapter, config).then(() => close([adapter])),
|
|
5824
5780
|
help: "generate a combined migration for an existing database"
|
|
5825
5781
|
},
|
|
5826
5782
|
new: {
|
|
@@ -5832,7 +5788,7 @@ const rakeDbCommands = {
|
|
|
5832
5788
|
rec: recurrentCommand,
|
|
5833
5789
|
recurrent: recurrentCommand,
|
|
5834
5790
|
rebase: {
|
|
5835
|
-
run: rebase,
|
|
5791
|
+
run: (adapters, config) => rebase(adapters, config).then(() => close(adapters)),
|
|
5836
5792
|
help: "move local migrations below the new ones from upstream"
|
|
5837
5793
|
},
|
|
5838
5794
|
"change-ids": {
|
|
@@ -5846,6 +5802,38 @@ const rakeDbCommands = {
|
|
|
5846
5802
|
}
|
|
5847
5803
|
};
|
|
5848
5804
|
|
|
5805
|
+
const rakeDbWithAdapters = (adapters, partialConfig, args = process.argv.slice(2)) => {
|
|
5806
|
+
const config = processRakeDbConfig(partialConfig);
|
|
5807
|
+
const promise = runCommand(
|
|
5808
|
+
adapters,
|
|
5809
|
+
config,
|
|
5810
|
+
args
|
|
5811
|
+
).catch((err) => {
|
|
5812
|
+
if (err instanceof RakeDbError) {
|
|
5813
|
+
config.logger?.error(err.message);
|
|
5814
|
+
process.exit(1);
|
|
5815
|
+
}
|
|
5816
|
+
throw err;
|
|
5817
|
+
});
|
|
5818
|
+
return Object.assign(makeChange(config), {
|
|
5819
|
+
promise
|
|
5820
|
+
});
|
|
5821
|
+
};
|
|
5822
|
+
rakeDbWithAdapters.lazy = (adapters, partialConfig) => {
|
|
5823
|
+
const config = processRakeDbConfig(partialConfig);
|
|
5824
|
+
return {
|
|
5825
|
+
change: makeChange(config),
|
|
5826
|
+
run(args, conf) {
|
|
5827
|
+
return runCommand(adapters, conf ? { ...config, ...conf } : config, args);
|
|
5828
|
+
}
|
|
5829
|
+
};
|
|
5830
|
+
};
|
|
5831
|
+
const makeChange = (config) => (fn) => {
|
|
5832
|
+
const change = { fn, config };
|
|
5833
|
+
pushChange(change);
|
|
5834
|
+
return change;
|
|
5835
|
+
};
|
|
5836
|
+
|
|
5849
5837
|
const migrateFiles = async (db, files) => {
|
|
5850
5838
|
const qb = db.$qb;
|
|
5851
5839
|
await qb.ensureTransaction(async () => {
|