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.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as orchid_core from 'orchid-core';
|
|
2
|
-
import { MaybeArray, RawSQLBase, ColumnDataCheckBase, RecordString, ColumnTypeBase, EmptyObject, ColumnSchemaConfig, QueryLogOptions, AdapterBase, MaybePromise, QueryLogObject, QueryBase } from 'orchid-core';
|
|
3
1
|
import * as pqb from 'pqb';
|
|
4
2
|
import { ColumnsShape, Db, TableData, NoPrimaryKeyOption, ColumnType, EnumColumn, DefaultColumnTypes, DefaultSchemaConfig, DbResult, TableDataFn, TableDataItem, DbDomainArg, raw, SearchWeight, ColumnsByType, DbStructureDomainsMap } from 'pqb';
|
|
3
|
+
import * as orchid_core from 'orchid-core';
|
|
4
|
+
import { MaybeArray, RawSQLBase, ColumnDataCheckBase, RecordString, ColumnTypeBase, EmptyObject, ColumnSchemaConfig, QueryLogOptions, AdapterBase, MaybePromise, QueryLogObject, QueryBase } from 'orchid-core';
|
|
5
5
|
|
|
6
6
|
interface CreateTableResult<Table extends string, Shape extends ColumnsShape> {
|
|
7
7
|
table: Db<Table, Shape>;
|
|
@@ -1495,17 +1495,6 @@ interface RakeDbChangeFnWithPromise<CT> extends RakeDbChangeFn<CT> {
|
|
|
1495
1495
|
*/
|
|
1496
1496
|
declare const rakeDbWithAdapters: RakeDbFn<AdapterBase[]>;
|
|
1497
1497
|
declare const makeChange: (config: RakeDbConfig<ColumnSchemaConfig, unknown>) => (fn: ChangeCallback<unknown>) => MigrationChange;
|
|
1498
|
-
declare const runCommand: <SchemaConfig extends ColumnSchemaConfig<orchid_core.ColumnTypeBase<orchid_core.ColumnTypeSchemaArg, unknown, any, any, unknown, unknown, any, unknown, any, orchid_core.ColumnDataBase>>, CT>(adapters: AdapterBase[], config: RakeDbConfig<SchemaConfig, CT>, args?: string[]) => Promise<RakeDbResult>;
|
|
1499
|
-
interface RakeDbCommand {
|
|
1500
|
-
run(adapters: AdapterBase[], config: AnyRakeDbConfig, args: string[]): MaybePromise<unknown>;
|
|
1501
|
-
help: string;
|
|
1502
|
-
helpArguments?: RecordString;
|
|
1503
|
-
helpAfter?: string;
|
|
1504
|
-
}
|
|
1505
|
-
interface RakeDbCommands {
|
|
1506
|
-
[K: string]: RakeDbCommand;
|
|
1507
|
-
}
|
|
1508
|
-
declare const rakeDbCommands: RakeDbCommands;
|
|
1509
1498
|
|
|
1510
1499
|
declare const encodeColumnDefault: (def: unknown, values: unknown[], column?: ColumnTypeBase) => string | null;
|
|
1511
1500
|
declare const getConstraintName: (table: string, constraint: {
|
|
@@ -1764,4 +1753,16 @@ declare const makeMigrateAdapter: (config?: Partial<MigrateFnConfig>) => ((adapt
|
|
|
1764
1753
|
declare class RakeDbError extends Error {
|
|
1765
1754
|
}
|
|
1766
1755
|
|
|
1756
|
+
declare const runCommand: <SchemaConfig extends ColumnSchemaConfig<orchid_core.ColumnTypeBase<orchid_core.ColumnTypeSchemaArg, unknown, any, any, unknown, unknown, any, unknown, any, orchid_core.ColumnDataBase>>, CT>(adapters: AdapterBase[], config: RakeDbConfig<SchemaConfig, CT>, args?: string[]) => Promise<RakeDbResult>;
|
|
1757
|
+
interface RakeDbCommand {
|
|
1758
|
+
run(adapters: AdapterBase[], config: AnyRakeDbConfig, args: string[]): MaybePromise<unknown>;
|
|
1759
|
+
help: string;
|
|
1760
|
+
helpArguments?: RecordString;
|
|
1761
|
+
helpAfter?: string;
|
|
1762
|
+
}
|
|
1763
|
+
interface RakeDbCommands {
|
|
1764
|
+
[K: string]: RakeDbCommand;
|
|
1765
|
+
}
|
|
1766
|
+
declare const rakeDbCommands: RakeDbCommands;
|
|
1767
|
+
|
|
1767
1768
|
export { type AnyRakeDbConfig, type ChangeCallback, type DbMigration, DbStructure, type InputRakeDbConfig, type InputRakeDbConfigBase, type IntrospectedStructure, type MigrateFnConfig, RakeDbAst, type RakeDbChangeFn, type RakeDbChangeFnWithPromise, type RakeDbConfig, RakeDbError, type RakeDbFn, type SilentQueries, type StructureToAstCtx, type StructureToAstTableData, astToMigration, concatSchemaAndName, createMigrationInterface, dbColumnToAst, encodeColumnDefault, getConstraintName, getDbStructureTableData, getDbTableColumnsChecks, getExcludeName, getIndexName, getSchemaAndTableFromName, instantiateDbColumn, introspectDbSchema, makeChange, makeDomainsMap, makeFileVersion, makeMigrateAdapter, makeStructureToAstCtx, migrate, migrateAndClose, migrateFiles, migrationConfigDefaults, processRakeDbConfig, promptSelect, rakeDbCommands, rakeDbWithAdapters, runCommand, saveMigratedVersion, structureToAst, tableToAst, writeMigrationFile };
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,99 @@ var fs = require('fs/promises');
|
|
|
8
8
|
require('url');
|
|
9
9
|
require('node:path');
|
|
10
10
|
|
|
11
|
+
class RakeDbError extends Error {
|
|
12
|
+
}
|
|
13
|
+
class NoPrimaryKey extends RakeDbError {
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let currentChanges = [];
|
|
17
|
+
const clearChanges = () => {
|
|
18
|
+
currentChanges = [];
|
|
19
|
+
};
|
|
20
|
+
const getCurrentChanges = () => currentChanges;
|
|
21
|
+
const pushChange = (change) => currentChanges.push(change);
|
|
22
|
+
|
|
23
|
+
const migrationConfigDefaults = {
|
|
24
|
+
schemaConfig: pqb.defaultSchemaConfig,
|
|
25
|
+
migrationsPath: path.join("src", "db", "migrations"),
|
|
26
|
+
migrationId: { serial: 4 },
|
|
27
|
+
migrationsTable: "schemaMigrations",
|
|
28
|
+
snakeCase: false,
|
|
29
|
+
commands: {},
|
|
30
|
+
log: true,
|
|
31
|
+
logger: console,
|
|
32
|
+
import() {
|
|
33
|
+
throw new Error(
|
|
34
|
+
"Add `import: (path) => import(path),` setting to `rakeDb` config"
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const ensureMigrationsPath = (config) => {
|
|
39
|
+
if (!config.migrationsPath) {
|
|
40
|
+
config.migrationsPath = migrationConfigDefaults.migrationsPath;
|
|
41
|
+
}
|
|
42
|
+
if (!path.isAbsolute(config.migrationsPath)) {
|
|
43
|
+
config.migrationsPath = path.resolve(
|
|
44
|
+
config.basePath,
|
|
45
|
+
config.migrationsPath
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return config;
|
|
49
|
+
};
|
|
50
|
+
const ensureBasePathAndDbScript = (config, intermediateCallers = 0) => {
|
|
51
|
+
if (config.basePath && config.dbScript) return config;
|
|
52
|
+
let filePath = orchidCore.getStackTrace()?.[3 + intermediateCallers].getFileName();
|
|
53
|
+
if (!filePath) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
"Failed to determine path to db script. Please set basePath option of rakeDb"
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
if (filePath.startsWith("file://")) {
|
|
59
|
+
filePath = node_url.fileURLToPath(filePath);
|
|
60
|
+
}
|
|
61
|
+
const ext = path.extname(filePath);
|
|
62
|
+
if (ext !== ".ts" && ext !== ".js" && ext !== ".mjs") {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Add a .ts suffix to the "${path.basename(filePath)}" when calling it`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
config.basePath = path.dirname(filePath);
|
|
68
|
+
config.dbScript = path.basename(filePath);
|
|
69
|
+
return config;
|
|
70
|
+
};
|
|
71
|
+
const processRakeDbConfig = (config) => {
|
|
72
|
+
const result = { ...migrationConfigDefaults, ...config };
|
|
73
|
+
if (!result.log) {
|
|
74
|
+
delete result.logger;
|
|
75
|
+
}
|
|
76
|
+
ensureBasePathAndDbScript(result, 1);
|
|
77
|
+
ensureMigrationsPath(result);
|
|
78
|
+
if (!result.recurrentPath) {
|
|
79
|
+
result.recurrentPath = path.join(
|
|
80
|
+
result.migrationsPath,
|
|
81
|
+
"recurrent"
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
if ("recurrentPath" in result && !path.isAbsolute(result.recurrentPath)) {
|
|
85
|
+
result.recurrentPath = path.resolve(result.basePath, result.recurrentPath);
|
|
86
|
+
}
|
|
87
|
+
if ("baseTable" in config && config.baseTable) {
|
|
88
|
+
const { types, snakeCase, language } = config.baseTable.prototype;
|
|
89
|
+
result.columnTypes = types || pqb.makeColumnTypes(pqb.defaultSchemaConfig);
|
|
90
|
+
if (snakeCase) result.snakeCase = true;
|
|
91
|
+
if (language) result.language = language;
|
|
92
|
+
} else {
|
|
93
|
+
const ct = "columnTypes" in config && config.columnTypes;
|
|
94
|
+
result.columnTypes = (typeof ct === "function" ? ct(
|
|
95
|
+
pqb.makeColumnTypes(pqb.defaultSchemaConfig)
|
|
96
|
+
) : ct) || pqb.makeColumnTypes(pqb.defaultSchemaConfig);
|
|
97
|
+
}
|
|
98
|
+
if (config.migrationId === "serial") {
|
|
99
|
+
result.migrationId = { serial: 4 };
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
};
|
|
103
|
+
|
|
11
104
|
const getFirstWordAndRest = (input) => {
|
|
12
105
|
const i = input.search(/(?=[A-Z])|[-_ ]/);
|
|
13
106
|
if (i !== -1) {
|
|
@@ -75,13 +168,6 @@ const transaction = (adapter, fn) => {
|
|
|
75
168
|
};
|
|
76
169
|
const queryLock = (trx) => trx.query(`SELECT pg_advisory_xact_lock('${RAKE_DB_LOCK_KEY}')`);
|
|
77
170
|
|
|
78
|
-
let currentChanges = [];
|
|
79
|
-
const clearChanges = () => {
|
|
80
|
-
currentChanges = [];
|
|
81
|
-
};
|
|
82
|
-
const getCurrentChanges = () => currentChanges;
|
|
83
|
-
const pushChange = (change) => currentChanges.push(change);
|
|
84
|
-
|
|
85
171
|
const versionToString = (config, version) => config.migrationId === "timestamp" ? `${version}` : `${version}`.padStart(config.migrationId.serial, "0");
|
|
86
172
|
const columnTypeToSql = (item) => {
|
|
87
173
|
return item.data.isOfCustomType ? item instanceof pqb.DomainColumn ? quoteNameFromString(item.dataType) : quoteCustomType(item.toSQL()) : item.toSQL();
|
|
@@ -465,11 +551,6 @@ const tableMethods = {
|
|
|
465
551
|
}
|
|
466
552
|
};
|
|
467
553
|
|
|
468
|
-
class RakeDbError extends Error {
|
|
469
|
-
}
|
|
470
|
-
class NoPrimaryKey extends RakeDbError {
|
|
471
|
-
}
|
|
472
|
-
|
|
473
554
|
const createTable = async (migration, up, tableName, first, second, third) => {
|
|
474
555
|
let options;
|
|
475
556
|
let fn;
|
|
@@ -3053,7 +3134,6 @@ const makeMigrateCommand = (migrateFn, defaultCount) => {
|
|
|
3053
3134
|
}
|
|
3054
3135
|
for (const adapter of adapters) {
|
|
3055
3136
|
await migrateFn({ ctx: {}, adapter, config, count, force });
|
|
3056
|
-
await adapter.close();
|
|
3057
3137
|
}
|
|
3058
3138
|
};
|
|
3059
3139
|
};
|
|
@@ -3523,7 +3603,7 @@ const resetDb = async (adapters, config) => {
|
|
|
3523
3603
|
await dropDb(adapters, config);
|
|
3524
3604
|
await createDb(adapters, config);
|
|
3525
3605
|
for (const adapter of adapters) {
|
|
3526
|
-
await
|
|
3606
|
+
await migrate({ adapter, config });
|
|
3527
3607
|
}
|
|
3528
3608
|
};
|
|
3529
3609
|
const askForAdminCredentials = async (create) => {
|
|
@@ -3548,6 +3628,44 @@ const askForAdminCredentials = async (create) => {
|
|
|
3548
3628
|
};
|
|
3549
3629
|
};
|
|
3550
3630
|
|
|
3631
|
+
const runRecurrentMigrations = async (adapters, config) => {
|
|
3632
|
+
let dbs;
|
|
3633
|
+
let files = 0;
|
|
3634
|
+
await readdirRecursive(config.recurrentPath, async (path) => {
|
|
3635
|
+
files++;
|
|
3636
|
+
dbs ?? (dbs = adapters.map((adapter) => pqb.createDbWithAdapter({ adapter })));
|
|
3637
|
+
const sql = await fs.readFile(path, "utf-8");
|
|
3638
|
+
await Promise.all(
|
|
3639
|
+
dbs.map(async (db) => {
|
|
3640
|
+
await db.adapter.arrays(sql);
|
|
3641
|
+
})
|
|
3642
|
+
);
|
|
3643
|
+
});
|
|
3644
|
+
if (files > 0) {
|
|
3645
|
+
config.logger?.log(
|
|
3646
|
+
`Applied ${files} recurrent migration file${files > 1 ? "s" : ""}`
|
|
3647
|
+
);
|
|
3648
|
+
}
|
|
3649
|
+
};
|
|
3650
|
+
const readdirRecursive = async (dirPath, cb) => {
|
|
3651
|
+
const list = await fs.readdir(dirPath).catch((err) => {
|
|
3652
|
+
if (err.code !== "ENOENT") throw err;
|
|
3653
|
+
return;
|
|
3654
|
+
});
|
|
3655
|
+
if (!list) return;
|
|
3656
|
+
await Promise.all(
|
|
3657
|
+
list.map(async (item) => {
|
|
3658
|
+
const path$1 = path.join(dirPath, item);
|
|
3659
|
+
const info = await fs.stat(path$1);
|
|
3660
|
+
if (info.isDirectory()) {
|
|
3661
|
+
await readdirRecursive(path$1, cb);
|
|
3662
|
+
} else if (info.isFile() && path$1.endsWith(".sql")) {
|
|
3663
|
+
await cb(path$1);
|
|
3664
|
+
}
|
|
3665
|
+
})
|
|
3666
|
+
);
|
|
3667
|
+
};
|
|
3668
|
+
|
|
3551
3669
|
const filterSchema = (table) => `${table} !~ '^pg_' AND ${table} != 'information_schema'`;
|
|
3552
3670
|
const jsonAgg = (sql2, as) => `(SELECT coalesce(json_agg(t.*), '[]') FROM (${sql2}) t) AS "${as}"`;
|
|
3553
3671
|
const columnsSql = ({
|
|
@@ -5259,7 +5377,6 @@ const pullDbStructure = async (adapter, config) => {
|
|
|
5259
5377
|
const currentSchema = adapter.schema || "public";
|
|
5260
5378
|
const ctx = makeStructureToAstCtx(config, currentSchema);
|
|
5261
5379
|
const ast = await structureToAst(ctx, adapter, config);
|
|
5262
|
-
await adapter.close();
|
|
5263
5380
|
const result = astToMigration(currentSchema, config, ast);
|
|
5264
5381
|
if (!result) return;
|
|
5265
5382
|
const version = await makeFileVersion({}, config);
|
|
@@ -5283,220 +5400,6 @@ Append \`as\` method manually to ${count > 1 ? "these" : "this"} column${count >
|
|
|
5283
5400
|
);
|
|
5284
5401
|
}
|
|
5285
5402
|
config.logger?.log("Database pulled successfully");
|
|
5286
|
-
adapter.close();
|
|
5287
|
-
};
|
|
5288
|
-
|
|
5289
|
-
const runRecurrentMigrations = async (adapters, config) => {
|
|
5290
|
-
let dbs;
|
|
5291
|
-
let files = 0;
|
|
5292
|
-
await readdirRecursive(config.recurrentPath, async (path) => {
|
|
5293
|
-
files++;
|
|
5294
|
-
dbs ?? (dbs = adapters.map((adapter) => pqb.createDbWithAdapter({ adapter })));
|
|
5295
|
-
const sql = await fs.readFile(path, "utf-8");
|
|
5296
|
-
await Promise.all(
|
|
5297
|
-
dbs.map(async (db) => {
|
|
5298
|
-
await db.adapter.arrays(sql);
|
|
5299
|
-
})
|
|
5300
|
-
);
|
|
5301
|
-
});
|
|
5302
|
-
if (dbs) {
|
|
5303
|
-
await Promise.all(dbs.map((db) => db.close()));
|
|
5304
|
-
if (files > 0) {
|
|
5305
|
-
config.logger?.log(
|
|
5306
|
-
`Applied ${files} recurrent migration file${files > 1 ? "s" : ""}`
|
|
5307
|
-
);
|
|
5308
|
-
}
|
|
5309
|
-
}
|
|
5310
|
-
};
|
|
5311
|
-
const readdirRecursive = async (dirPath, cb) => {
|
|
5312
|
-
const list = await fs.readdir(dirPath).catch((err) => {
|
|
5313
|
-
if (err.code !== "ENOENT") throw err;
|
|
5314
|
-
return;
|
|
5315
|
-
});
|
|
5316
|
-
if (!list) return;
|
|
5317
|
-
await Promise.all(
|
|
5318
|
-
list.map(async (item) => {
|
|
5319
|
-
const path$1 = path.join(dirPath, item);
|
|
5320
|
-
const info = await fs.stat(path$1);
|
|
5321
|
-
if (info.isDirectory()) {
|
|
5322
|
-
await readdirRecursive(path$1, cb);
|
|
5323
|
-
} else if (info.isFile() && path$1.endsWith(".sql")) {
|
|
5324
|
-
await cb(path$1);
|
|
5325
|
-
}
|
|
5326
|
-
})
|
|
5327
|
-
);
|
|
5328
|
-
};
|
|
5329
|
-
|
|
5330
|
-
const listMigrationsStatuses = async (adapters, config, args) => {
|
|
5331
|
-
const ctx = {};
|
|
5332
|
-
const [{ migrations }, ...migrated] = await Promise.all([
|
|
5333
|
-
getMigrations(ctx, config, true),
|
|
5334
|
-
...adapters.map((adapter) => getMigratedVersionsMap(ctx, adapter, config))
|
|
5335
|
-
]);
|
|
5336
|
-
const map = {};
|
|
5337
|
-
let maxVersionLength = 12;
|
|
5338
|
-
let maxNameLength = 4;
|
|
5339
|
-
for (let i = 0; i < adapters.length; i++) {
|
|
5340
|
-
const list = migrated[i];
|
|
5341
|
-
const key = Object.entries(list.map).map(([version, up]) => `${version}${up ? "t" : "f"}`).join("");
|
|
5342
|
-
const database = adapters[i].getDatabase();
|
|
5343
|
-
if (map[key]) {
|
|
5344
|
-
map[key].databases.push(database);
|
|
5345
|
-
continue;
|
|
5346
|
-
}
|
|
5347
|
-
map[key] = {
|
|
5348
|
-
databases: [database],
|
|
5349
|
-
migrations: migrations.map((item) => {
|
|
5350
|
-
if (item.version.length > maxVersionLength) {
|
|
5351
|
-
maxVersionLength = item.version.length;
|
|
5352
|
-
}
|
|
5353
|
-
const name = path.parse(item.path).name.slice(item.version.length + 1).replace(
|
|
5354
|
-
/([a-z])([A-Z])/g,
|
|
5355
|
-
(_, a, b) => `${a} ${b.toLocaleLowerCase()}`
|
|
5356
|
-
).replace(/[-_](.)/g, (_, char) => ` ${char.toLocaleLowerCase()}`).replace(/^\w/, (match) => match.toLocaleUpperCase());
|
|
5357
|
-
if (name.length > maxNameLength) {
|
|
5358
|
-
maxNameLength = name.length;
|
|
5359
|
-
}
|
|
5360
|
-
return {
|
|
5361
|
-
up: !!list.map[item.version],
|
|
5362
|
-
version: item.version,
|
|
5363
|
-
name,
|
|
5364
|
-
url: node_url.pathToFileURL(item.path)
|
|
5365
|
-
};
|
|
5366
|
-
})
|
|
5367
|
-
};
|
|
5368
|
-
}
|
|
5369
|
-
const showUrl = args.includes("p") || args.includes("path");
|
|
5370
|
-
const asIs = (s) => s;
|
|
5371
|
-
const c = typeof config.log === "object" && config.log.colors === false ? {
|
|
5372
|
-
yellow: asIs,
|
|
5373
|
-
green: asIs,
|
|
5374
|
-
red: asIs,
|
|
5375
|
-
blue: asIs
|
|
5376
|
-
} : colors;
|
|
5377
|
-
const log = Object.values(map).map(({ databases, migrations: migrations2 }) => {
|
|
5378
|
-
let log2 = ` ${c.yellow("Database:")} ${databases.join(", ")}`;
|
|
5379
|
-
if (migrations2.length === 0) {
|
|
5380
|
-
return log2 + `
|
|
5381
|
-
|
|
5382
|
-
No migrations available`;
|
|
5383
|
-
}
|
|
5384
|
-
const lineSeparator = c.yellow(
|
|
5385
|
-
makeChars(14 + maxVersionLength + maxNameLength, "-")
|
|
5386
|
-
);
|
|
5387
|
-
const columnSeparator = c.yellow("|");
|
|
5388
|
-
log2 += "\n\n " + c.yellow(
|
|
5389
|
-
`Status | Migration ID${makeChars(
|
|
5390
|
-
maxVersionLength - 12,
|
|
5391
|
-
" "
|
|
5392
|
-
)} | Name
|
|
5393
|
-
${lineSeparator}`
|
|
5394
|
-
);
|
|
5395
|
-
for (const migration of migrations2) {
|
|
5396
|
-
log2 += `
|
|
5397
|
-
${migration.up ? ` ${c.green("Up")} ` : c.red("Down")} ${columnSeparator} ${c.blue(migration.version)}${makeChars(
|
|
5398
|
-
maxVersionLength - migration.version.length,
|
|
5399
|
-
" "
|
|
5400
|
-
)} ${columnSeparator} ${migration.name}`;
|
|
5401
|
-
if (showUrl) {
|
|
5402
|
-
log2 += `
|
|
5403
|
-
${migration.url}
|
|
5404
|
-
`;
|
|
5405
|
-
}
|
|
5406
|
-
}
|
|
5407
|
-
return log2 += showUrl ? lineSeparator : `
|
|
5408
|
-
${lineSeparator}`;
|
|
5409
|
-
}).join("\n\n");
|
|
5410
|
-
(config.logger ?? console).log(log);
|
|
5411
|
-
await Promise.all(adapters.map((adapter) => adapter.close()));
|
|
5412
|
-
};
|
|
5413
|
-
const makeChars = (count, char) => {
|
|
5414
|
-
let chars = "";
|
|
5415
|
-
for (let i = 0; i < count; i++) {
|
|
5416
|
-
chars += char;
|
|
5417
|
-
}
|
|
5418
|
-
return chars;
|
|
5419
|
-
};
|
|
5420
|
-
|
|
5421
|
-
const migrationConfigDefaults = {
|
|
5422
|
-
schemaConfig: pqb.defaultSchemaConfig,
|
|
5423
|
-
migrationsPath: path.join("src", "db", "migrations"),
|
|
5424
|
-
migrationId: { serial: 4 },
|
|
5425
|
-
migrationsTable: "schemaMigrations",
|
|
5426
|
-
snakeCase: false,
|
|
5427
|
-
commands: {},
|
|
5428
|
-
log: true,
|
|
5429
|
-
logger: console,
|
|
5430
|
-
import() {
|
|
5431
|
-
throw new Error(
|
|
5432
|
-
"Add `import: (path) => import(path),` setting to `rakeDb` config"
|
|
5433
|
-
);
|
|
5434
|
-
}
|
|
5435
|
-
};
|
|
5436
|
-
const ensureMigrationsPath = (config) => {
|
|
5437
|
-
if (!config.migrationsPath) {
|
|
5438
|
-
config.migrationsPath = migrationConfigDefaults.migrationsPath;
|
|
5439
|
-
}
|
|
5440
|
-
if (!path.isAbsolute(config.migrationsPath)) {
|
|
5441
|
-
config.migrationsPath = path.resolve(
|
|
5442
|
-
config.basePath,
|
|
5443
|
-
config.migrationsPath
|
|
5444
|
-
);
|
|
5445
|
-
}
|
|
5446
|
-
return config;
|
|
5447
|
-
};
|
|
5448
|
-
const ensureBasePathAndDbScript = (config, intermediateCallers = 0) => {
|
|
5449
|
-
if (config.basePath && config.dbScript) return config;
|
|
5450
|
-
let filePath = orchidCore.getStackTrace()?.[3 + intermediateCallers].getFileName();
|
|
5451
|
-
if (!filePath) {
|
|
5452
|
-
throw new Error(
|
|
5453
|
-
"Failed to determine path to db script. Please set basePath option of rakeDb"
|
|
5454
|
-
);
|
|
5455
|
-
}
|
|
5456
|
-
if (filePath.startsWith("file://")) {
|
|
5457
|
-
filePath = node_url.fileURLToPath(filePath);
|
|
5458
|
-
}
|
|
5459
|
-
const ext = path.extname(filePath);
|
|
5460
|
-
if (ext !== ".ts" && ext !== ".js" && ext !== ".mjs") {
|
|
5461
|
-
throw new Error(
|
|
5462
|
-
`Add a .ts suffix to the "${path.basename(filePath)}" when calling it`
|
|
5463
|
-
);
|
|
5464
|
-
}
|
|
5465
|
-
config.basePath = path.dirname(filePath);
|
|
5466
|
-
config.dbScript = path.basename(filePath);
|
|
5467
|
-
return config;
|
|
5468
|
-
};
|
|
5469
|
-
const processRakeDbConfig = (config) => {
|
|
5470
|
-
const result = { ...migrationConfigDefaults, ...config };
|
|
5471
|
-
if (!result.log) {
|
|
5472
|
-
delete result.logger;
|
|
5473
|
-
}
|
|
5474
|
-
ensureBasePathAndDbScript(result, 1);
|
|
5475
|
-
ensureMigrationsPath(result);
|
|
5476
|
-
if (!result.recurrentPath) {
|
|
5477
|
-
result.recurrentPath = path.join(
|
|
5478
|
-
result.migrationsPath,
|
|
5479
|
-
"recurrent"
|
|
5480
|
-
);
|
|
5481
|
-
}
|
|
5482
|
-
if ("recurrentPath" in result && !path.isAbsolute(result.recurrentPath)) {
|
|
5483
|
-
result.recurrentPath = path.resolve(result.basePath, result.recurrentPath);
|
|
5484
|
-
}
|
|
5485
|
-
if ("baseTable" in config && config.baseTable) {
|
|
5486
|
-
const { types, snakeCase, language } = config.baseTable.prototype;
|
|
5487
|
-
result.columnTypes = types || pqb.makeColumnTypes(pqb.defaultSchemaConfig);
|
|
5488
|
-
if (snakeCase) result.snakeCase = true;
|
|
5489
|
-
if (language) result.language = language;
|
|
5490
|
-
} else {
|
|
5491
|
-
const ct = "columnTypes" in config && config.columnTypes;
|
|
5492
|
-
result.columnTypes = (typeof ct === "function" ? ct(
|
|
5493
|
-
pqb.makeColumnTypes(pqb.defaultSchemaConfig)
|
|
5494
|
-
) : ct) || pqb.makeColumnTypes(pqb.defaultSchemaConfig);
|
|
5495
|
-
}
|
|
5496
|
-
if (config.migrationId === "serial") {
|
|
5497
|
-
result.migrationId = { serial: 4 };
|
|
5498
|
-
}
|
|
5499
|
-
return result;
|
|
5500
5403
|
};
|
|
5501
5404
|
|
|
5502
5405
|
const rebase = async (adapters, config) => {
|
|
@@ -5513,7 +5416,6 @@ const rebase = async (adapters, config) => {
|
|
|
5513
5416
|
await getMigrations(ctx, config, true, true),
|
|
5514
5417
|
...adapters.map((adapter) => getMigratedVersionsMap(ctx, adapter, config))
|
|
5515
5418
|
]);
|
|
5516
|
-
await Promise.all(adapters.map((adapter) => adapter.close()));
|
|
5517
5419
|
const files = set.migrations.map((file) => ({
|
|
5518
5420
|
...file,
|
|
5519
5421
|
name: path.basename(file.path),
|
|
@@ -5643,7 +5545,6 @@ const rebase = async (adapters, config) => {
|
|
|
5643
5545
|
adapter,
|
|
5644
5546
|
config: redoConfig
|
|
5645
5547
|
});
|
|
5646
|
-
await adapter.close();
|
|
5647
5548
|
}
|
|
5648
5549
|
for (let i = renames.length - 1; i >= 0; i--) {
|
|
5649
5550
|
const [from, version] = renames[i];
|
|
@@ -5658,37 +5559,97 @@ const rebase = async (adapters, config) => {
|
|
|
5658
5559
|
}
|
|
5659
5560
|
};
|
|
5660
5561
|
|
|
5661
|
-
const
|
|
5662
|
-
const
|
|
5663
|
-
const
|
|
5664
|
-
|
|
5665
|
-
config
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5562
|
+
const listMigrationsStatuses = async (adapters, config, args) => {
|
|
5563
|
+
const ctx = {};
|
|
5564
|
+
const [{ migrations }, ...migrated] = await Promise.all([
|
|
5565
|
+
getMigrations(ctx, config, true),
|
|
5566
|
+
...adapters.map((adapter) => getMigratedVersionsMap(ctx, adapter, config))
|
|
5567
|
+
]);
|
|
5568
|
+
const map = {};
|
|
5569
|
+
let maxVersionLength = 12;
|
|
5570
|
+
let maxNameLength = 4;
|
|
5571
|
+
for (let i = 0; i < adapters.length; i++) {
|
|
5572
|
+
const list = migrated[i];
|
|
5573
|
+
const key = Object.entries(list.map).map(([version, up]) => `${version}${up ? "t" : "f"}`).join("");
|
|
5574
|
+
const database = adapters[i].getDatabase();
|
|
5575
|
+
if (map[key]) {
|
|
5576
|
+
map[key].databases.push(database);
|
|
5577
|
+
continue;
|
|
5671
5578
|
}
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
}
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5579
|
+
map[key] = {
|
|
5580
|
+
databases: [database],
|
|
5581
|
+
migrations: migrations.map((item) => {
|
|
5582
|
+
if (item.version.length > maxVersionLength) {
|
|
5583
|
+
maxVersionLength = item.version.length;
|
|
5584
|
+
}
|
|
5585
|
+
const name = path.parse(item.path).name.slice(item.version.length + 1).replace(
|
|
5586
|
+
/([a-z])([A-Z])/g,
|
|
5587
|
+
(_, a, b) => `${a} ${b.toLocaleLowerCase()}`
|
|
5588
|
+
).replace(/[-_](.)/g, (_, char) => ` ${char.toLocaleLowerCase()}`).replace(/^\w/, (match) => match.toLocaleUpperCase());
|
|
5589
|
+
if (name.length > maxNameLength) {
|
|
5590
|
+
maxNameLength = name.length;
|
|
5591
|
+
}
|
|
5592
|
+
return {
|
|
5593
|
+
up: !!list.map[item.version],
|
|
5594
|
+
version: item.version,
|
|
5595
|
+
name,
|
|
5596
|
+
url: node_url.pathToFileURL(item.path)
|
|
5597
|
+
};
|
|
5598
|
+
})
|
|
5599
|
+
};
|
|
5600
|
+
}
|
|
5601
|
+
const showUrl = args.includes("p") || args.includes("path");
|
|
5602
|
+
const asIs = (s) => s;
|
|
5603
|
+
const c = typeof config.log === "object" && config.log.colors === false ? {
|
|
5604
|
+
yellow: asIs,
|
|
5605
|
+
green: asIs,
|
|
5606
|
+
red: asIs,
|
|
5607
|
+
blue: asIs
|
|
5608
|
+
} : colors;
|
|
5609
|
+
const log = Object.values(map).map(({ databases, migrations: migrations2 }) => {
|
|
5610
|
+
let log2 = ` ${c.yellow("Database:")} ${databases.join(", ")}`;
|
|
5611
|
+
if (migrations2.length === 0) {
|
|
5612
|
+
return log2 + `
|
|
5613
|
+
|
|
5614
|
+
No migrations available`;
|
|
5684
5615
|
}
|
|
5685
|
-
|
|
5616
|
+
const lineSeparator = c.yellow(
|
|
5617
|
+
makeChars(14 + maxVersionLength + maxNameLength, "-")
|
|
5618
|
+
);
|
|
5619
|
+
const columnSeparator = c.yellow("|");
|
|
5620
|
+
log2 += "\n\n " + c.yellow(
|
|
5621
|
+
`Status | Migration ID${makeChars(
|
|
5622
|
+
maxVersionLength - 12,
|
|
5623
|
+
" "
|
|
5624
|
+
)} | Name
|
|
5625
|
+
${lineSeparator}`
|
|
5626
|
+
);
|
|
5627
|
+
for (const migration of migrations2) {
|
|
5628
|
+
log2 += `
|
|
5629
|
+
${migration.up ? ` ${c.green("Up")} ` : c.red("Down")} ${columnSeparator} ${c.blue(migration.version)}${makeChars(
|
|
5630
|
+
maxVersionLength - migration.version.length,
|
|
5631
|
+
" "
|
|
5632
|
+
)} ${columnSeparator} ${migration.name}`;
|
|
5633
|
+
if (showUrl) {
|
|
5634
|
+
log2 += `
|
|
5635
|
+
${migration.url}
|
|
5636
|
+
`;
|
|
5637
|
+
}
|
|
5638
|
+
}
|
|
5639
|
+
return log2 += showUrl ? lineSeparator : `
|
|
5640
|
+
${lineSeparator}`;
|
|
5641
|
+
}).join("\n\n");
|
|
5642
|
+
(config.logger ?? console).log(log);
|
|
5643
|
+
await Promise.all(adapters.map((adapter) => adapter.close()));
|
|
5686
5644
|
};
|
|
5687
|
-
const
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5645
|
+
const makeChars = (count, char) => {
|
|
5646
|
+
let chars = "";
|
|
5647
|
+
for (let i = 0; i < count; i++) {
|
|
5648
|
+
chars += char;
|
|
5649
|
+
}
|
|
5650
|
+
return chars;
|
|
5691
5651
|
};
|
|
5652
|
+
|
|
5692
5653
|
const rakeDbAliases = {
|
|
5693
5654
|
migrate: "up",
|
|
5694
5655
|
rollback: "down",
|
|
@@ -5764,10 +5725,9 @@ ${Object.entries(helpArguments).map(
|
|
|
5764
5725
|
args
|
|
5765
5726
|
};
|
|
5766
5727
|
};
|
|
5728
|
+
const close = (adapters) => Promise.all(adapters.map((adapter) => adapter.close()));
|
|
5767
5729
|
const upCommand = {
|
|
5768
|
-
run: (adapters, config, args) => migrateCommand(adapters, config, args).then(
|
|
5769
|
-
() => runRecurrentMigrations(adapters, config)
|
|
5770
|
-
),
|
|
5730
|
+
run: (adapters, config, args) => migrateCommand(adapters, config, args).then(() => runRecurrentMigrations(adapters, config)).then(() => close(adapters)),
|
|
5771
5731
|
help: "migrate pending migrations",
|
|
5772
5732
|
helpArguments: {
|
|
5773
5733
|
"no arguments": "migrate all pending",
|
|
@@ -5776,7 +5736,7 @@ const upCommand = {
|
|
|
5776
5736
|
}
|
|
5777
5737
|
};
|
|
5778
5738
|
const downCommand = {
|
|
5779
|
-
run: (adapters, config, args) => rollbackCommand(adapters, config, args),
|
|
5739
|
+
run: (adapters, config, args) => rollbackCommand(adapters, config, args).then(() => close(adapters)),
|
|
5780
5740
|
help: "rollback migrated migrations",
|
|
5781
5741
|
helpArguments: {
|
|
5782
5742
|
"no arguments": "rollback one last migration",
|
|
@@ -5793,7 +5753,7 @@ const statusCommand = {
|
|
|
5793
5753
|
}
|
|
5794
5754
|
};
|
|
5795
5755
|
const recurrentCommand = {
|
|
5796
|
-
run: runRecurrentMigrations,
|
|
5756
|
+
run: (adapters, config) => runRecurrentMigrations(adapters, config).then(() => close(adapters)),
|
|
5797
5757
|
help: "run recurrent migrations"
|
|
5798
5758
|
};
|
|
5799
5759
|
const rakeDbCommands = {
|
|
@@ -5806,9 +5766,7 @@ const rakeDbCommands = {
|
|
|
5806
5766
|
help: "drop databases"
|
|
5807
5767
|
},
|
|
5808
5768
|
reset: {
|
|
5809
|
-
run: (adapters, config) => resetDb(adapters, config).then(
|
|
5810
|
-
() => runRecurrentMigrations(adapters, config)
|
|
5811
|
-
),
|
|
5769
|
+
run: (adapters, config) => resetDb(adapters, config).then(() => runRecurrentMigrations(adapters, config)).then(() => close(adapters)),
|
|
5812
5770
|
help: "drop, create and migrate databases"
|
|
5813
5771
|
},
|
|
5814
5772
|
up: upCommand,
|
|
@@ -5816,13 +5774,11 @@ const rakeDbCommands = {
|
|
|
5816
5774
|
down: downCommand,
|
|
5817
5775
|
rollback: downCommand,
|
|
5818
5776
|
redo: {
|
|
5819
|
-
run: (adapters, config, args) => redoCommand(adapters, config, args).then(
|
|
5820
|
-
() => runRecurrentMigrations(adapters, config)
|
|
5821
|
-
),
|
|
5777
|
+
run: (adapters, config, args) => redoCommand(adapters, config, args).then(() => runRecurrentMigrations(adapters, config)).then(() => close(adapters)),
|
|
5822
5778
|
help: "rollback and migrate, run recurrent"
|
|
5823
5779
|
},
|
|
5824
5780
|
pull: {
|
|
5825
|
-
run: ([adapter], config) => pullDbStructure(adapter, config),
|
|
5781
|
+
run: ([adapter], config) => pullDbStructure(adapter, config).then(() => close([adapter])),
|
|
5826
5782
|
help: "generate a combined migration for an existing database"
|
|
5827
5783
|
},
|
|
5828
5784
|
new: {
|
|
@@ -5834,7 +5790,7 @@ const rakeDbCommands = {
|
|
|
5834
5790
|
rec: recurrentCommand,
|
|
5835
5791
|
recurrent: recurrentCommand,
|
|
5836
5792
|
rebase: {
|
|
5837
|
-
run: rebase,
|
|
5793
|
+
run: (adapters, config) => rebase(adapters, config).then(() => close(adapters)),
|
|
5838
5794
|
help: "move local migrations below the new ones from upstream"
|
|
5839
5795
|
},
|
|
5840
5796
|
"change-ids": {
|
|
@@ -5848,6 +5804,38 @@ const rakeDbCommands = {
|
|
|
5848
5804
|
}
|
|
5849
5805
|
};
|
|
5850
5806
|
|
|
5807
|
+
const rakeDbWithAdapters = (adapters, partialConfig, args = process.argv.slice(2)) => {
|
|
5808
|
+
const config = processRakeDbConfig(partialConfig);
|
|
5809
|
+
const promise = runCommand(
|
|
5810
|
+
adapters,
|
|
5811
|
+
config,
|
|
5812
|
+
args
|
|
5813
|
+
).catch((err) => {
|
|
5814
|
+
if (err instanceof RakeDbError) {
|
|
5815
|
+
config.logger?.error(err.message);
|
|
5816
|
+
process.exit(1);
|
|
5817
|
+
}
|
|
5818
|
+
throw err;
|
|
5819
|
+
});
|
|
5820
|
+
return Object.assign(makeChange(config), {
|
|
5821
|
+
promise
|
|
5822
|
+
});
|
|
5823
|
+
};
|
|
5824
|
+
rakeDbWithAdapters.lazy = (adapters, partialConfig) => {
|
|
5825
|
+
const config = processRakeDbConfig(partialConfig);
|
|
5826
|
+
return {
|
|
5827
|
+
change: makeChange(config),
|
|
5828
|
+
run(args, conf) {
|
|
5829
|
+
return runCommand(adapters, conf ? { ...config, ...conf } : config, args);
|
|
5830
|
+
}
|
|
5831
|
+
};
|
|
5832
|
+
};
|
|
5833
|
+
const makeChange = (config) => (fn) => {
|
|
5834
|
+
const change = { fn, config };
|
|
5835
|
+
pushChange(change);
|
|
5836
|
+
return change;
|
|
5837
|
+
};
|
|
5838
|
+
|
|
5851
5839
|
const migrateFiles = async (db, files) => {
|
|
5852
5840
|
const qb = db.$qb;
|
|
5853
5841
|
await qb.ensureTransaction(async () => {
|