rake-db 2.26.0 → 2.27.2

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,5 +1,5 @@
1
- import { singleQuote, isRawSQL, toSnakeCase, toCamelCase, toArray, snakeCaseKey, emptyObject, setCurrentColumnName, consumeColumnName, ColumnTypeBase, setDefaultLanguage, deepCompare, getImportPath, pathToLog, emptyArray, getStackTrace, codeToString, addCode, quoteObjectKey, backtickQuote } from 'orchid-core';
2
- import { escapeForMigration, ArrayColumn, DomainColumn, EnumColumn, defaultSchemaConfig, getColumnTypes, parseTableData, escapeString, tableDataMethods, ColumnType, parseTableDataInput, UnknownColumn, raw, TransactionAdapter, logParamToLogObject, createDb as createDb$1, Adapter, makeColumnTypes, makeColumnsByType, RawSQL, CustomTypeColumn, assignDbDataToColumn, PostgisGeographyPointColumn, pushTableDataCode, primaryKeyInnerToCode, indexInnerToCode, excludeInnerToCode, constraintInnerToCode, referencesArgsToCode, TimestampTZColumn, TimestampColumn } from 'pqb';
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';
3
3
  import path, { join } from 'path';
4
4
  import { pathToFileURL, fileURLToPath } from 'node:url';
5
5
  import fs, { mkdir, writeFile, readdir, stat, readFile } from 'fs/promises';
@@ -68,11 +68,8 @@ const makePopulateEnumQuery = (item) => {
68
68
  }
69
69
  };
70
70
  };
71
- const begin = {
72
- text: "BEGIN"
73
- };
74
71
  const transaction = (adapter, fn) => {
75
- return adapter.transaction(begin, fn);
72
+ return adapter.transaction(void 0, fn);
76
73
  };
77
74
  const queryLock = (trx) => trx.query(`SELECT pg_advisory_xact_lock('${RAKE_DB_LOCK_KEY}')`);
78
75
 
@@ -1366,22 +1363,28 @@ const astToQuery = (ast) => {
1366
1363
  };
1367
1364
 
1368
1365
  const createMigrationInterface = (tx, up, config) => {
1369
- const adapter = new TransactionAdapter(
1370
- tx,
1371
- tx.client,
1372
- tx.types
1373
- );
1374
- adapter.schema = adapter.adapter.schema ?? "public";
1366
+ const adapter = Object.create(tx);
1367
+ adapter.schema = adapter.getSchema() ?? "public";
1375
1368
  const { query, arrays } = adapter;
1376
1369
  const log = logParamToLogObject(config.logger || console, config.log);
1377
- adapter.query = (q, types) => {
1378
- return wrapWithLog(log, q, () => query.call(adapter, q, types));
1370
+ adapter.query = (text, values) => {
1371
+ return wrapWithLog(
1372
+ log,
1373
+ text,
1374
+ values,
1375
+ () => query.call(adapter, text, values)
1376
+ );
1379
1377
  };
1380
- adapter.arrays = (q, types) => {
1381
- return wrapWithLog(log, q, () => arrays.call(adapter, q, types));
1378
+ adapter.arrays = (text, values) => {
1379
+ return wrapWithLog(
1380
+ log,
1381
+ text,
1382
+ values,
1383
+ () => arrays.call(adapter, text, values)
1384
+ );
1382
1385
  };
1383
1386
  Object.assign(adapter, { silentQuery: query, silentArrays: arrays });
1384
- const db = createDb$1({
1387
+ const db = createDbWithAdapter({
1385
1388
  adapter,
1386
1389
  columnTypes: config.columnTypes
1387
1390
  });
@@ -2221,11 +2224,14 @@ class Migration {
2221
2224
  });
2222
2225
  }
2223
2226
  }
2224
- const wrapWithLog = async (log, query, fn) => {
2227
+ const wrapWithLog = async (log, text, values, fn) => {
2225
2228
  if (!log) {
2226
2229
  return fn();
2227
2230
  } else {
2228
- const sql = typeof query === "string" ? { text: query, values: [] } : query.values ? query : { ...query, values: [] };
2231
+ const sql = {
2232
+ text,
2233
+ values: values || []
2234
+ };
2229
2235
  const logData = log.beforeQuery(sql);
2230
2236
  try {
2231
2237
  const result = await fn();
@@ -2372,7 +2378,7 @@ const createCollation = async (migration, up, name, options) => {
2372
2378
  await migration.adapter.query(query);
2373
2379
  };
2374
2380
  const queryExists = (db, sql) => {
2375
- return db.adapter.query(sql).then(({ rowCount }) => rowCount > 0);
2381
+ return db.adapter.query(sql.text, sql.values).then(({ rowCount }) => rowCount > 0);
2376
2382
  };
2377
2383
  const renameType = async (migration, from, to, kind) => {
2378
2384
  const [fromSchema, f] = getSchemaAndTableFromName(migration.up ? from : to);
@@ -2595,7 +2601,7 @@ const fileNamesToChangeMigrationId = {
2595
2601
  const fileNamesToChangeMigrationIdMap = Object.fromEntries(
2596
2602
  Object.entries(fileNamesToChangeMigrationId).map(([_, name]) => [name, true])
2597
2603
  );
2598
- const changeIds = async (options, config, [arg, digitsArg]) => {
2604
+ const changeIds = async (adapters, config, [arg, digitsArg]) => {
2599
2605
  if (arg !== "serial" && arg !== "timestamp") {
2600
2606
  throw new Error(
2601
2607
  `Pass "serial" or "timestamp" argument to the "change-ids" command`
@@ -2682,12 +2688,13 @@ After setting \`renameMigrations\` (see above) and renaming the files, run the d
2682
2688
  );
2683
2689
  })
2684
2690
  );
2685
- await options.map((opts) => {
2686
- const adapter = new Adapter(opts);
2687
- renameMigrationVersionsInDb(config, adapter, values).then(
2688
- () => adapter.close()
2689
- );
2690
- });
2691
+ await Promise.all(
2692
+ adapters.map((adapter) => {
2693
+ renameMigrationVersionsInDb(config, adapter, values).then(
2694
+ () => adapter.close()
2695
+ );
2696
+ })
2697
+ );
2691
2698
  config.logger?.log(
2692
2699
  `Migration files were renamed, a config file ${fileNamesToChangeMigrationId[arg]} for renaming migrations after deploy was created, and migrations in local db were renamed successfully.
2693
2700
 
@@ -2695,14 +2702,14 @@ ${arg === "timestamp" || digits !== 4 ? `Set \`migrationId\`: ${arg === "timesta
2695
2702
  );
2696
2703
  };
2697
2704
  const renameMigrationVersionsInDb = async (config, adapter, values) => {
2698
- await adapter.arrays({
2699
- text: `UPDATE "${config.migrationsTable}" AS t SET version = v.version FROM (VALUES ${values.map(
2705
+ await adapter.arrays(
2706
+ `UPDATE "${config.migrationsTable}" AS t SET version = v.version FROM (VALUES ${values.map(
2700
2707
  ([oldVersion, , newVersion], i) => `('${oldVersion}', $${i + 1}, '${newVersion}')`
2701
2708
  ).join(
2702
2709
  ", "
2703
2710
  )}) v(oldVersion, name, version) WHERE t.version = v.oldVersion`,
2704
- values: values.map(([, name]) => name)
2705
- });
2711
+ values.map(([, name]) => name)
2712
+ );
2706
2713
  };
2707
2714
 
2708
2715
  const getMigrations = async (ctx, config, up, allowDuplicates, getVersion = getMigrationVersionOrThrow) => {
@@ -2860,16 +2867,16 @@ function getDigitsPrefix(name) {
2860
2867
  }
2861
2868
 
2862
2869
  const saveMigratedVersion = async (db, version, name, config) => {
2863
- await db.silentArrays({
2864
- text: `INSERT INTO "${config.migrationsTable}"(version, name) VALUES ($1, $2)`,
2865
- values: [version, name]
2866
- });
2870
+ await db.silentArrays(
2871
+ `INSERT INTO "${config.migrationsTable}"(version, name) VALUES ($1, $2)`,
2872
+ [version, name]
2873
+ );
2867
2874
  };
2868
2875
  const deleteMigratedVersion = async (db, version, name, config) => {
2869
- const res = await db.silentArrays({
2870
- text: `DELETE FROM "${config.migrationsTable}" WHERE version = $1 AND name = $2`,
2871
- values: [version, name]
2872
- });
2876
+ const res = await db.silentArrays(
2877
+ `DELETE FROM "${config.migrationsTable}" WHERE version = $1 AND name = $2`,
2878
+ [version, name]
2879
+ );
2873
2880
  if (res.rowCount === 0) {
2874
2881
  throw new Error(`Migration ${version}_${name} was not found in db`);
2875
2882
  }
@@ -2902,10 +2909,10 @@ const getMigratedVersionsMap = async (ctx, adapter, config, renameTo) => {
2902
2909
  await adapter.arrays(`ALTER TABLE ${table} ADD COLUMN name TEXT`);
2903
2910
  await Promise.all(
2904
2911
  result.rows.map(
2905
- ([version, name]) => adapter.arrays({
2906
- text: `UPDATE ${table} SET name = $2 WHERE version = $1`,
2907
- values: [version, name]
2908
- })
2912
+ ([version, name]) => adapter.arrays(`UPDATE ${table} SET name = $2 WHERE version = $1`, [
2913
+ version,
2914
+ name
2915
+ ])
2909
2916
  )
2910
2917
  );
2911
2918
  await adapter.arrays(
@@ -2981,89 +2988,88 @@ const createMigrationsTable = async (db, config) => {
2981
2988
  };
2982
2989
 
2983
2990
  const RAKE_DB_LOCK_KEY = "8582141715823621641";
2984
- function makeMigrateFn(defaultCount, up, fn) {
2985
- return async (ctx, options, config, args = [], adapters = options.map((opts) => new Adapter(opts)), dontClose) => {
2986
- const set = await getMigrations(ctx, config, up);
2987
- const arg = args[0];
2988
- let force = arg === "force";
2989
- let count;
2990
- if (arg === "force") {
2991
- force = true;
2992
- } else {
2993
- force = false;
2994
- const num = arg === "all" ? Infinity : parseInt(arg);
2995
- count = isNaN(num) ? void 0 : num;
2996
- }
2997
- const conf = config;
2998
- const length = options.length;
2999
- for (let i = 0; i < length; i++) {
3000
- const opts = options[i];
3001
- const adapter = adapters[i];
3002
- let migrations;
3003
- try {
3004
- await transaction(adapter, async (trx) => {
2991
+ function makeMigrateFn(up, fn) {
2992
+ return async (params) => {
2993
+ const ctx = params.ctx || {};
2994
+ const set = await getMigrations(ctx, params.config, up);
2995
+ const count = params.count ?? Infinity;
2996
+ const force = params.force ?? false;
2997
+ let migrations;
2998
+ try {
2999
+ await transaction(params.adapter, async (trx) => {
3000
+ const versions = await getMigratedVersionsMap(
3001
+ ctx,
3002
+ trx,
3003
+ params.config,
3004
+ set.renameTo
3005
+ );
3006
+ migrations = await fn(trx, params.config, set, versions, count, force);
3007
+ });
3008
+ } catch (err) {
3009
+ if (err instanceof NoMigrationsTableError) {
3010
+ await transaction(params.adapter, async (trx) => {
3011
+ await createMigrationsTable(trx, params.config);
3005
3012
  const versions = await getMigratedVersionsMap(
3006
3013
  ctx,
3007
3014
  trx,
3008
- config,
3015
+ params.config,
3009
3016
  set.renameTo
3010
3017
  );
3011
3018
  migrations = await fn(
3012
3019
  trx,
3013
- conf,
3020
+ params.config,
3014
3021
  set,
3015
3022
  versions,
3016
- count ?? defaultCount,
3023
+ count,
3017
3024
  force
3018
3025
  );
3019
3026
  });
3020
- } catch (err) {
3021
- if (err instanceof NoMigrationsTableError) {
3022
- await transaction(adapter, async (trx) => {
3023
- const config2 = conf;
3024
- await createMigrationsTable(trx, config2);
3025
- const versions = await getMigratedVersionsMap(
3026
- ctx,
3027
- trx,
3028
- config2,
3029
- set.renameTo
3030
- );
3031
- migrations = await fn(
3032
- trx,
3033
- config2,
3034
- set,
3035
- versions,
3036
- count ?? defaultCount,
3037
- force
3038
- );
3039
- });
3040
- } else {
3041
- throw err;
3042
- }
3043
- } finally {
3044
- if (!dontClose) await adapter.close();
3027
+ } else {
3028
+ throw err;
3045
3029
  }
3046
- config.afterChangeCommit?.({
3047
- options: opts,
3048
- up,
3049
- migrations
3050
- });
3051
3030
  }
3052
- return adapters;
3031
+ params.config.afterChangeCommit?.({
3032
+ adapter: params.adapter,
3033
+ up,
3034
+ migrations
3035
+ });
3053
3036
  };
3054
3037
  }
3055
- const fullMigrate = makeMigrateFn(
3056
- Infinity,
3038
+ const makeMigrateCommand = (migrateFn, defaultCount) => {
3039
+ return async (adapters, config, args) => {
3040
+ const arg = args[0];
3041
+ let force = arg === "force";
3042
+ let count = defaultCount;
3043
+ if (arg === "force") {
3044
+ force = true;
3045
+ } else {
3046
+ force = false;
3047
+ const num = arg === "all" ? Infinity : parseInt(arg || "");
3048
+ if (!isNaN(num)) {
3049
+ count = num;
3050
+ }
3051
+ }
3052
+ for (const adapter of adapters) {
3053
+ await migrateFn({ ctx: {}, adapter, config, count, force });
3054
+ await adapter.close();
3055
+ }
3056
+ };
3057
+ };
3058
+ const migrate = makeMigrateFn(
3057
3059
  true,
3058
3060
  (trx, config, set, versions, count, force) => migrateOrRollback(trx, config, set, versions, count, true, false, force)
3059
3061
  );
3060
- const fullRollback = makeMigrateFn(
3061
- 1,
3062
+ const migrateAndClose = async (params) => {
3063
+ await migrate(params);
3064
+ await params.adapter.close();
3065
+ };
3066
+ const migrateCommand = makeMigrateCommand(migrate, Infinity);
3067
+ const rollback = makeMigrateFn(
3062
3068
  false,
3063
3069
  (trx, config, set, versions, count, force) => migrateOrRollback(trx, config, set, versions, count, false, false, force)
3064
3070
  );
3065
- const fullRedo = makeMigrateFn(
3066
- 1,
3071
+ const rollbackCommand = makeMigrateCommand(rollback, 1);
3072
+ const redo = makeMigrateFn(
3067
3073
  true,
3068
3074
  async (trx, config, set, versions, count, force) => {
3069
3075
  set.migrations.reverse();
@@ -3082,8 +3088,9 @@ const fullRedo = makeMigrateFn(
3082
3088
  );
3083
3089
  }
3084
3090
  );
3085
- const getDb = (adapter) => createDb$1({ adapter });
3086
- const migrateOrRollback = async (trx, config, set, versions, count, up, redo, force, skipLock) => {
3091
+ const redoCommand = makeMigrateCommand(redo, 1);
3092
+ const getDb = (adapter) => createDbWithAdapter({ adapter });
3093
+ const migrateOrRollback = async (trx, config, set, versions, count, up, redo2, force, skipLock) => {
3087
3094
  const { sequence, map: versionsMap } = versions;
3088
3095
  if (up) {
3089
3096
  const rollbackTo = checkMigrationOrder(config, set, versions, force);
@@ -3104,7 +3111,7 @@ const migrateOrRollback = async (trx, config, set, versions, count, up, redo, fo
3104
3111
  versions,
3105
3112
  sequence.length - i,
3106
3113
  false,
3107
- redo
3114
+ redo2
3108
3115
  );
3109
3116
  set.migrations.reverse();
3110
3117
  }
@@ -3116,7 +3123,7 @@ const migrateOrRollback = async (trx, config, set, versions, count, up, redo, fo
3116
3123
  db ?? (db = getDb(trx));
3117
3124
  const { migrations: migrations2 } = set;
3118
3125
  await beforeMigrate?.({ db, migrations: migrations2 });
3119
- await config.beforeChange?.({ db, migrations: migrations2, up, redo });
3126
+ await config.beforeChange?.({ db, migrations: migrations2, up, redo: redo2 });
3120
3127
  }
3121
3128
  let loggedAboutStarting = false;
3122
3129
  let migrations;
@@ -3125,10 +3132,10 @@ const migrateOrRollback = async (trx, config, set, versions, count, up, redo, fo
3125
3132
  continue;
3126
3133
  }
3127
3134
  if (count-- <= 0) break;
3128
- if (!loggedAboutStarting && (!redo || !up)) {
3135
+ if (!loggedAboutStarting && (!redo2 || !up)) {
3129
3136
  loggedAboutStarting = true;
3130
3137
  config.logger?.log(
3131
- `${redo ? "Reapplying migrations for" : up ? "Migrating" : "Rolling back"} database ${trx.config.connectionString ? new URL(trx.config.connectionString).pathname.slice(1) : trx.config.database}
3138
+ `${redo2 ? "Reapplying migrations for" : up ? "Migrating" : "Rolling back"} database ${trx.getDatabase()}
3132
3139
  `
3133
3140
  );
3134
3141
  }
@@ -3153,7 +3160,7 @@ const migrateOrRollback = async (trx, config, set, versions, count, up, redo, fo
3153
3160
  const afterMigrate = config[up ? "afterMigrate" : "afterRollback"];
3154
3161
  if (config.afterChange || afterMigrate) {
3155
3162
  db ?? (db = getDb(trx));
3156
- await config.afterChange?.({ db, up, redo, migrations });
3163
+ await config.afterChange?.({ db, up, redo: redo2, migrations });
3157
3164
  await afterMigrate?.({ db, migrations });
3158
3165
  }
3159
3166
  return migrations;
@@ -3233,86 +3240,6 @@ const changeMigratedVersion = async (adapter, up, file, config) => {
3233
3240
  );
3234
3241
  };
3235
3242
 
3236
- const migrationConfigDefaults = {
3237
- schemaConfig: defaultSchemaConfig,
3238
- migrationsPath: path.join("src", "db", "migrations"),
3239
- migrationId: { serial: 4 },
3240
- migrationsTable: "schemaMigrations",
3241
- snakeCase: false,
3242
- commands: {},
3243
- log: true,
3244
- logger: console,
3245
- import() {
3246
- throw new Error("Please define the `import` setting in `rakeDb` config");
3247
- }
3248
- };
3249
- const processRakeDbConfig = (config) => {
3250
- const result = { ...migrationConfigDefaults, ...config };
3251
- if (!result.recurrentPath) {
3252
- result.recurrentPath = path.join(result.migrationsPath, "recurrent");
3253
- }
3254
- if (!result.log) {
3255
- delete result.logger;
3256
- }
3257
- if (!result.basePath || !result.dbScript) {
3258
- let filePath = getStackTrace()?.[3].getFileName();
3259
- if (!filePath) {
3260
- throw new Error(
3261
- "Failed to determine path to db script. Please set basePath option of rakeDb"
3262
- );
3263
- }
3264
- if (filePath.startsWith("file://")) {
3265
- filePath = fileURLToPath(filePath);
3266
- }
3267
- const ext = path.extname(filePath);
3268
- if (ext !== ".ts" && ext !== ".js" && ext !== ".mjs") {
3269
- throw new Error(
3270
- `Add a .ts suffix to the "${path.basename(filePath)}" when calling it`
3271
- );
3272
- }
3273
- result.basePath = path.dirname(filePath);
3274
- result.dbScript = path.basename(filePath);
3275
- }
3276
- if ("migrationsPath" in result && !path.isAbsolute(result.migrationsPath)) {
3277
- result.migrationsPath = path.resolve(
3278
- result.basePath,
3279
- result.migrationsPath
3280
- );
3281
- }
3282
- if ("recurrentPath" in result && !path.isAbsolute(result.recurrentPath)) {
3283
- result.recurrentPath = path.resolve(result.basePath, result.recurrentPath);
3284
- }
3285
- if ("baseTable" in config && config.baseTable) {
3286
- const { types, snakeCase, language } = config.baseTable.prototype;
3287
- result.columnTypes = types || makeColumnTypes(defaultSchemaConfig);
3288
- if (snakeCase) result.snakeCase = true;
3289
- if (language) result.language = language;
3290
- } else {
3291
- const ct = "columnTypes" in config && config.columnTypes;
3292
- result.columnTypes = (typeof ct === "function" ? ct(
3293
- makeColumnTypes(defaultSchemaConfig)
3294
- ) : ct) || makeColumnTypes(defaultSchemaConfig);
3295
- }
3296
- if (config.migrationId === "serial") {
3297
- result.migrationId = { serial: 4 };
3298
- }
3299
- return result;
3300
- };
3301
- const getDatabaseAndUserFromOptions = (options) => {
3302
- if (options.databaseURL) {
3303
- const url = new URL(options.databaseURL);
3304
- return {
3305
- database: url.pathname.slice(1),
3306
- user: url.username
3307
- };
3308
- } else {
3309
- return {
3310
- database: options.database,
3311
- user: options.user
3312
- };
3313
- }
3314
- };
3315
-
3316
3243
  const colors = {
3317
3244
  yellow: (s) => `\x1B[33m${s}\x1B[0m`,
3318
3245
  green: (s) => `\x1B[32m${s}\x1B[0m`,
@@ -3500,52 +3427,9 @@ const promptText = ({
3500
3427
  });
3501
3428
  };
3502
3429
 
3503
- const setAdapterOptions = (options, set) => {
3504
- if (options.databaseURL) {
3505
- const url = new URL(options.databaseURL);
3506
- if ("database" in set) {
3507
- url.pathname = `/${set.database}`;
3508
- }
3509
- if (set.user !== void 0) {
3510
- url.username = set.user;
3511
- }
3512
- if (set.password !== void 0) {
3513
- url.password = set.password;
3514
- }
3515
- return { ...options, databaseURL: url.toString() };
3516
- } else {
3517
- return {
3518
- ...options,
3519
- ...set
3520
- };
3521
- }
3522
- };
3523
- const setAdminCredentialsToOptions = async (options, create) => {
3524
- const ok = await promptConfirm({
3525
- message: `Would you like to share admin credentials to ${create ? "create" : "drop"} a database?`
3526
- });
3527
- if (!ok) {
3528
- return;
3529
- }
3530
- const user = await promptText({
3531
- message: "Enter admin user:",
3532
- default: "postgres",
3533
- min: 1
3534
- });
3535
- const password = await promptText({
3536
- message: "Enter admin password:",
3537
- password: true
3538
- });
3539
- return setAdapterOptions(options, {
3540
- user,
3541
- password: password || void 0
3542
- });
3543
- };
3544
-
3545
- const execute = async (options, sql) => {
3546
- const db = new Adapter(options);
3430
+ const execute = async (adapter, sql) => {
3547
3431
  try {
3548
- await db.query(sql);
3432
+ await adapter.query(sql);
3549
3433
  return "ok";
3550
3434
  } catch (error) {
3551
3435
  const err = error;
@@ -3560,13 +3444,16 @@ const execute = async (options, sql) => {
3560
3444
  return { error };
3561
3445
  }
3562
3446
  } finally {
3563
- await db.close();
3447
+ await adapter.close();
3564
3448
  }
3565
3449
  };
3566
- const createOrDrop = async (options, adminOptions, config, args) => {
3567
- const params = getDatabaseAndUserFromOptions(options);
3450
+ const createOrDrop = async (adapter, adminAdapter, config, args) => {
3451
+ const params = {
3452
+ database: adapter.getDatabase(),
3453
+ user: adapter.getUser()
3454
+ };
3568
3455
  const result = await execute(
3569
- setAdapterOptions(adminOptions, { database: "postgres" }),
3456
+ adminAdapter.reconfigure({ database: "postgres" }),
3570
3457
  args.sql(params)
3571
3458
  );
3572
3459
  if (result === "ok") {
@@ -3580,31 +3467,28 @@ const createOrDrop = async (options, adminOptions, config, args) => {
3580
3467
  return;
3581
3468
  } else if (result === "forbidden") {
3582
3469
  let message = `Permission denied to ${args.create ? "create" : "drop"} database.`;
3583
- const host = adminOptions.databaseURL ? new URL(adminOptions.databaseURL).hostname : adminOptions.host;
3470
+ const host = adminAdapter.getHost();
3584
3471
  const isLocal = host === "localhost";
3585
3472
  if (!isLocal) {
3586
3473
  message += `
3587
3474
  Don't use this command for database service providers, only for a local db.`;
3588
3475
  }
3589
3476
  config.logger?.log(message);
3590
- const updatedOptions = await setAdminCredentialsToOptions(
3591
- options,
3592
- args.create
3593
- );
3594
- if (!updatedOptions) return;
3595
- await createOrDrop(options, updatedOptions, config, args);
3477
+ const params2 = await askForAdminCredentials(args.create);
3478
+ if (!params2) return;
3479
+ await createOrDrop(adapter, adminAdapter.reconfigure(params2), config, args);
3596
3480
  return;
3597
3481
  } else {
3598
3482
  throw result.error;
3599
3483
  }
3600
3484
  if (!args.create) return;
3601
- const db = new Adapter(options);
3602
- await createMigrationsTable(db, config);
3603
- await db.close();
3485
+ const newlyConnectedAdapter = adapter.reconfigure({});
3486
+ await createMigrationsTable(newlyConnectedAdapter, config);
3487
+ await newlyConnectedAdapter.close();
3604
3488
  };
3605
- const createDb = async (options, config) => {
3606
- for (const opts of options) {
3607
- await createOrDrop(opts, opts, config, {
3489
+ const createDb = async (adapters, config) => {
3490
+ for (const adapter of adapters) {
3491
+ await createOrDrop(adapter, adapter, config, {
3608
3492
  sql({ database, user }) {
3609
3493
  return `CREATE DATABASE "${database}"${user ? ` OWNER "${user}"` : ""}`;
3610
3494
  },
@@ -3618,9 +3502,9 @@ const createDb = async (options, config) => {
3618
3502
  });
3619
3503
  }
3620
3504
  };
3621
- const dropDb = async (options, config) => {
3622
- for (const opts of options) {
3623
- await createOrDrop(opts, opts, config, {
3505
+ const dropDb = async (adapters, config) => {
3506
+ for (const adapter of adapters) {
3507
+ await createOrDrop(adapter, adapter, config, {
3624
3508
  sql({ database }) {
3625
3509
  return `DROP DATABASE "${database}"`;
3626
3510
  },
@@ -3633,10 +3517,33 @@ const dropDb = async (options, config) => {
3633
3517
  });
3634
3518
  }
3635
3519
  };
3636
- const resetDb = async (options, config) => {
3637
- await dropDb(options, config);
3638
- await createDb(options, config);
3639
- await fullMigrate({}, options, config);
3520
+ const resetDb = async (adapters, config) => {
3521
+ await dropDb(adapters, config);
3522
+ await createDb(adapters, config);
3523
+ for (const adapter of adapters) {
3524
+ await migrateAndClose({ adapter, config });
3525
+ }
3526
+ };
3527
+ const askForAdminCredentials = async (create) => {
3528
+ const ok = await promptConfirm({
3529
+ message: `Would you like to share admin credentials to ${create ? "create" : "drop"} a database?`
3530
+ });
3531
+ if (!ok) {
3532
+ return;
3533
+ }
3534
+ const user = await promptText({
3535
+ message: "Enter admin user:",
3536
+ default: "postgres",
3537
+ min: 1
3538
+ });
3539
+ const password = await promptText({
3540
+ message: "Enter admin password:",
3541
+ password: true
3542
+ });
3543
+ return {
3544
+ user,
3545
+ password: password || void 0
3546
+ };
3640
3547
  };
3641
3548
 
3642
3549
  const filterSchema = (table) => `${table} !~ '^pg_' AND ${table} != 'information_schema'`;
@@ -5349,8 +5256,7 @@ const timestampsToCode = ({ hasTZTimestamps }) => {
5349
5256
  return `t.${key}()`;
5350
5257
  };
5351
5258
 
5352
- const pullDbStructure = async (options, config) => {
5353
- const adapter = new Adapter(options);
5259
+ const pullDbStructure = async (adapter, config) => {
5354
5260
  const currentSchema = adapter.schema || "public";
5355
5261
  const ctx = makeStructureToAstCtx(config, currentSchema);
5356
5262
  const ast = await structureToAst(ctx, adapter, config);
@@ -5381,12 +5287,12 @@ Append \`as\` method manually to ${count > 1 ? "these" : "this"} column${count >
5381
5287
  adapter.close();
5382
5288
  };
5383
5289
 
5384
- const runRecurrentMigrations = async (options, config) => {
5290
+ const runRecurrentMigrations = async (adapters, config) => {
5385
5291
  let dbs;
5386
5292
  let files = 0;
5387
5293
  await readdirRecursive(config.recurrentPath, async (path) => {
5388
5294
  files++;
5389
- dbs ?? (dbs = options.map((opts) => createDb$1({ adapter: new Adapter(opts) })));
5295
+ dbs ?? (dbs = adapters.map((adapter) => createDbWithAdapter({ adapter })));
5390
5296
  const sql = await readFile(path, "utf-8");
5391
5297
  await Promise.all(
5392
5298
  dbs.map(async (db) => {
@@ -5422,8 +5328,7 @@ const readdirRecursive = async (dirPath, cb) => {
5422
5328
  );
5423
5329
  };
5424
5330
 
5425
- const listMigrationsStatuses = async (options, config, args) => {
5426
- const adapters = options.map((opts) => new Adapter(opts));
5331
+ const listMigrationsStatuses = async (adapters, config, args) => {
5427
5332
  const ctx = {};
5428
5333
  const [{ migrations }, ...migrated] = await Promise.all([
5429
5334
  getMigrations(ctx, config, true),
@@ -5432,10 +5337,10 @@ const listMigrationsStatuses = async (options, config, args) => {
5432
5337
  const map = {};
5433
5338
  let maxVersionLength = 12;
5434
5339
  let maxNameLength = 4;
5435
- for (let i = 0; i < options.length; i++) {
5340
+ for (let i = 0; i < adapters.length; i++) {
5436
5341
  const list = migrated[i];
5437
5342
  const key = Object.entries(list.map).map(([version, up]) => `${version}${up ? "t" : "f"}`).join("");
5438
- const database = options[i].database || new URL(options[i].databaseURL).pathname.slice(1);
5343
+ const database = adapters[i].getDatabase();
5439
5344
  if (map[key]) {
5440
5345
  map[key].databases.push(database);
5441
5346
  continue;
@@ -5514,7 +5419,88 @@ const makeChars = (count, char) => {
5514
5419
  return chars;
5515
5420
  };
5516
5421
 
5517
- const rebase = async (options, config) => {
5422
+ const migrationConfigDefaults = {
5423
+ schemaConfig: defaultSchemaConfig,
5424
+ migrationsPath: path.join("src", "db", "migrations"),
5425
+ migrationId: { serial: 4 },
5426
+ migrationsTable: "schemaMigrations",
5427
+ snakeCase: false,
5428
+ commands: {},
5429
+ log: true,
5430
+ logger: console,
5431
+ import() {
5432
+ throw new Error(
5433
+ "Add `import: (path) => import(path),` setting to `rakeDb` config"
5434
+ );
5435
+ }
5436
+ };
5437
+ const ensureMigrationsPath = (config) => {
5438
+ if (!config.migrationsPath) {
5439
+ config.migrationsPath = migrationConfigDefaults.migrationsPath;
5440
+ }
5441
+ if (!path.isAbsolute(config.migrationsPath)) {
5442
+ config.migrationsPath = path.resolve(
5443
+ config.basePath,
5444
+ config.migrationsPath
5445
+ );
5446
+ }
5447
+ return config;
5448
+ };
5449
+ const ensureBasePathAndDbScript = (config, intermediateCallers = 0) => {
5450
+ if (config.basePath && config.dbScript) return config;
5451
+ let filePath = getStackTrace()?.[3 + intermediateCallers].getFileName();
5452
+ if (!filePath) {
5453
+ throw new Error(
5454
+ "Failed to determine path to db script. Please set basePath option of rakeDb"
5455
+ );
5456
+ }
5457
+ if (filePath.startsWith("file://")) {
5458
+ filePath = fileURLToPath(filePath);
5459
+ }
5460
+ const ext = path.extname(filePath);
5461
+ if (ext !== ".ts" && ext !== ".js" && ext !== ".mjs") {
5462
+ throw new Error(
5463
+ `Add a .ts suffix to the "${path.basename(filePath)}" when calling it`
5464
+ );
5465
+ }
5466
+ config.basePath = path.dirname(filePath);
5467
+ config.dbScript = path.basename(filePath);
5468
+ return config;
5469
+ };
5470
+ const processRakeDbConfig = (config) => {
5471
+ const result = { ...migrationConfigDefaults, ...config };
5472
+ if (!result.log) {
5473
+ delete result.logger;
5474
+ }
5475
+ ensureBasePathAndDbScript(result, 1);
5476
+ ensureMigrationsPath(result);
5477
+ if (!result.recurrentPath) {
5478
+ result.recurrentPath = path.join(
5479
+ result.migrationsPath,
5480
+ "recurrent"
5481
+ );
5482
+ }
5483
+ if ("recurrentPath" in result && !path.isAbsolute(result.recurrentPath)) {
5484
+ result.recurrentPath = path.resolve(result.basePath, result.recurrentPath);
5485
+ }
5486
+ if ("baseTable" in config && config.baseTable) {
5487
+ const { types, snakeCase, language } = config.baseTable.prototype;
5488
+ result.columnTypes = types || makeColumnTypes(defaultSchemaConfig);
5489
+ if (snakeCase) result.snakeCase = true;
5490
+ if (language) result.language = language;
5491
+ } else {
5492
+ const ct = "columnTypes" in config && config.columnTypes;
5493
+ result.columnTypes = (typeof ct === "function" ? ct(
5494
+ makeColumnTypes(defaultSchemaConfig)
5495
+ ) : ct) || makeColumnTypes(defaultSchemaConfig);
5496
+ }
5497
+ if (config.migrationId === "serial") {
5498
+ result.migrationId = { serial: 4 };
5499
+ }
5500
+ return result;
5501
+ };
5502
+
5503
+ const rebase = async (adapters, config) => {
5518
5504
  if (config.migrations) {
5519
5505
  throw new Error("Cannot rebase migrations defined in the config");
5520
5506
  }
@@ -5523,7 +5509,6 @@ const rebase = async (options, config) => {
5523
5509
  `Cannot rebase when the 'migrationId' is set to 'timestamp' in the config`
5524
5510
  );
5525
5511
  }
5526
- const adapters = options.map((opts) => new Adapter(opts));
5527
5512
  const ctx = {};
5528
5513
  const [set, ...versionMaps] = await Promise.all([
5529
5514
  await getMigrations(ctx, config, true, true),
@@ -5644,20 +5629,23 @@ const rebase = async (options, config) => {
5644
5629
  return files2;
5645
5630
  }, []).sort((a, b) => +b.version - +a.version);
5646
5631
  set.migrations = migrationsDown;
5647
- await fullRedo(
5648
- ctx,
5649
- options,
5650
- {
5651
- ...config,
5652
- async afterRollback() {
5653
- set.migrations = migrationsUp;
5654
- },
5655
- async afterMigrate() {
5656
- set.migrations = migrationsDown;
5657
- }
5632
+ const redoConfig = {
5633
+ ...config,
5634
+ async afterRollback() {
5635
+ set.migrations = migrationsUp;
5658
5636
  },
5659
- ["all"]
5660
- );
5637
+ async afterMigrate() {
5638
+ set.migrations = migrationsDown;
5639
+ }
5640
+ };
5641
+ for (const adapter of adapters) {
5642
+ await redo({
5643
+ ctx,
5644
+ adapter,
5645
+ config: redoConfig
5646
+ });
5647
+ await adapter.close();
5648
+ }
5661
5649
  for (let i = renames.length - 1; i >= 0; i--) {
5662
5650
  const [from, version] = renames[i];
5663
5651
  const prefix = String(version).padStart(4, "0");
@@ -5671,10 +5659,10 @@ const rebase = async (options, config) => {
5671
5659
  }
5672
5660
  };
5673
5661
 
5674
- const rakeDb = (options, partialConfig, args = process.argv.slice(2)) => {
5662
+ const rakeDbWithAdapters = (adapters, partialConfig, args = process.argv.slice(2)) => {
5675
5663
  const config = processRakeDbConfig(partialConfig);
5676
5664
  const promise = runCommand(
5677
- options,
5665
+ adapters,
5678
5666
  config,
5679
5667
  args
5680
5668
  ).catch((err) => {
@@ -5688,12 +5676,12 @@ const rakeDb = (options, partialConfig, args = process.argv.slice(2)) => {
5688
5676
  promise
5689
5677
  });
5690
5678
  };
5691
- rakeDb.lazy = (options, partialConfig) => {
5679
+ rakeDbWithAdapters.lazy = (adapters, partialConfig) => {
5692
5680
  const config = processRakeDbConfig(partialConfig);
5693
5681
  return {
5694
5682
  change: makeChange(config),
5695
5683
  run(args, conf) {
5696
- return runCommand(options, conf ? { ...config, ...conf } : config, args);
5684
+ return runCommand(adapters, conf ? { ...config, ...conf } : config, args);
5697
5685
  }
5698
5686
  };
5699
5687
  };
@@ -5703,22 +5691,21 @@ const makeChange = (config) => (fn) => {
5703
5691
  return change;
5704
5692
  };
5705
5693
  const rakeDbAliases = {
5706
- fullMigrate: "up",
5694
+ migrate: "up",
5707
5695
  rollback: "down",
5708
5696
  s: "status",
5709
5697
  rec: "recurrent"
5710
5698
  };
5711
- const runCommand = async (opts, config, args = process.argv.slice(2)) => {
5699
+ const runCommand = async (adapters, config, args = process.argv.slice(2)) => {
5712
5700
  let arg = args[0]?.split(":")[0];
5713
5701
  if (rakeDbAliases[arg]) {
5714
5702
  args = [...args];
5715
5703
  arg = args[0] = rakeDbAliases[arg];
5716
5704
  }
5717
- const options = toArray(opts);
5718
5705
  args.shift();
5719
5706
  const command = rakeDbCommands[arg]?.run ?? config.commands[arg];
5720
5707
  if (command) {
5721
- await command(options, config, args);
5708
+ await command(adapters, config, args);
5722
5709
  } else if (config.logger) {
5723
5710
  const commandsHelp = [];
5724
5711
  let max = 0;
@@ -5773,14 +5760,14 @@ ${Object.entries(helpArguments).map(
5773
5760
  `);
5774
5761
  }
5775
5762
  return {
5776
- options,
5763
+ adapters,
5777
5764
  config,
5778
5765
  args
5779
5766
  };
5780
5767
  };
5781
5768
  const upCommand = {
5782
- run: (options, config, args) => fullMigrate({}, options, config, args).then(
5783
- () => runRecurrentMigrations(options, config)
5769
+ run: (adapters, config, args) => migrateCommand(adapters, config, args).then(
5770
+ () => runRecurrentMigrations(adapters, config)
5784
5771
  ),
5785
5772
  help: "migrate pending migrations",
5786
5773
  helpArguments: {
@@ -5790,7 +5777,7 @@ const upCommand = {
5790
5777
  }
5791
5778
  };
5792
5779
  const downCommand = {
5793
- run: (options, config, args) => fullRollback({}, options, config, args),
5780
+ run: (adapters, config, args) => rollbackCommand(adapters, config, args),
5794
5781
  help: "rollback migrated migrations",
5795
5782
  helpArguments: {
5796
5783
  "no arguments": "rollback one last migration",
@@ -5820,8 +5807,8 @@ const rakeDbCommands = {
5820
5807
  help: "drop databases"
5821
5808
  },
5822
5809
  reset: {
5823
- run: (options, config) => resetDb(options, config).then(
5824
- () => runRecurrentMigrations(options, config)
5810
+ run: (adapters, config) => resetDb(adapters, config).then(
5811
+ () => runRecurrentMigrations(adapters, config)
5825
5812
  ),
5826
5813
  help: "drop, create and migrate databases"
5827
5814
  },
@@ -5830,13 +5817,13 @@ const rakeDbCommands = {
5830
5817
  down: downCommand,
5831
5818
  rollback: downCommand,
5832
5819
  redo: {
5833
- run: (options, config, args) => fullRedo({}, options, config, args).then(
5834
- () => runRecurrentMigrations(options, config)
5820
+ run: (adapters, config, args) => redoCommand(adapters, config, args).then(
5821
+ () => runRecurrentMigrations(adapters, config)
5835
5822
  ),
5836
5823
  help: "rollback and migrate, run recurrent"
5837
5824
  },
5838
5825
  pull: {
5839
- run: ([options], config) => pullDbStructure(options, config),
5826
+ run: ([adapter], config) => pullDbStructure(adapter, config),
5840
5827
  help: "generate a combined migration for an existing database"
5841
5828
  },
5842
5829
  new: {
@@ -5875,5 +5862,5 @@ const migrateFiles = async (db, files) => {
5875
5862
  });
5876
5863
  };
5877
5864
 
5878
- export { astToMigration, concatSchemaAndName, createMigrationInterface, dbColumnToAst, encodeColumnDefault, fullMigrate, getConstraintName, getDbStructureTableData, getDbTableColumnsChecks, getExcludeName, getIndexName, getSchemaAndTableFromName, instantiateDbColumn, introspectDbSchema, makeDomainsMap, makeFileVersion, makeStructureToAstCtx, migrateFiles, migrationConfigDefaults, promptSelect, rakeDb, rakeDbCommands, saveMigratedVersion, structureToAst, tableToAst, writeMigrationFile };
5865
+ export { astToMigration, concatSchemaAndName, createMigrationInterface, dbColumnToAst, encodeColumnDefault, getConstraintName, getDbStructureTableData, getDbTableColumnsChecks, getExcludeName, getIndexName, getSchemaAndTableFromName, instantiateDbColumn, introspectDbSchema, makeDomainsMap, makeFileVersion, makeStructureToAstCtx, migrate, migrateAndClose, migrateFiles, migrationConfigDefaults, promptSelect, rakeDbCommands, rakeDbWithAdapters, saveMigratedVersion, structureToAst, tableToAst, writeMigrationFile };
5879
5866
  //# sourceMappingURL=index.mjs.map