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.mjs CHANGED
@@ -1,11 +1,104 @@
1
- import { escapeForMigration, ArrayColumn, DomainColumn, EnumColumn, defaultSchemaConfig, getColumnTypes, parseTableData, escapeString, tableDataMethods, ColumnType, parseTableDataInput, UnknownColumn, raw, logParamToLogObject, createDbWithAdapter, makeColumnsByType, RawSQL, CustomTypeColumn, assignDbDataToColumn, PostgisGeographyPointColumn, pushTableDataCode, primaryKeyInnerToCode, indexInnerToCode, excludeInnerToCode, constraintInnerToCode, referencesArgsToCode, TimestampTZColumn, TimestampColumn, makeColumnTypes } from 'pqb';
2
- import { singleQuote, isRawSQL, toSnakeCase, toCamelCase, toArray, snakeCaseKey, emptyObject, setCurrentColumnName, consumeColumnName, ColumnTypeBase, setDefaultLanguage, deepCompare, getImportPath, pathToLog, emptyArray, codeToString, addCode, quoteObjectKey, backtickQuote, getStackTrace } from 'orchid-core';
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 { pathToFileURL, fileURLToPath } from 'node:url';
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 migrateAndClose({ adapter, config });
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 rakeDbWithAdapters = (adapters, partialConfig, args = process.argv.slice(2)) => {
5660
- const config = processRakeDbConfig(partialConfig);
5661
- const promise = runCommand(
5662
- adapters,
5663
- config,
5664
- args
5665
- ).catch((err) => {
5666
- if (err instanceof RakeDbError) {
5667
- config.logger?.error(err.message);
5668
- process.exit(1);
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
- throw err;
5671
- });
5672
- return Object.assign(makeChange(config), {
5673
- promise
5674
- });
5675
- };
5676
- rakeDbWithAdapters.lazy = (adapters, partialConfig) => {
5677
- const config = processRakeDbConfig(partialConfig);
5678
- return {
5679
- change: makeChange(config),
5680
- run(args, conf) {
5681
- return runCommand(adapters, conf ? { ...config, ...conf } : config, args);
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 makeChange = (config) => (fn) => {
5686
- const change = { fn, config };
5687
- pushChange(change);
5688
- return change;
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 () => {