rake-db 2.25.17 → 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,8 +1,10 @@
1
- import { DomainColumn, escapeForMigration, ArrayColumn, 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';
2
- import { singleQuote, toSnakeCase, isRawSQL, toCamelCase, toArray, snakeCaseKey, emptyObject, setCurrentColumnName, consumeColumnName, ColumnTypeBase, setDefaultLanguage, deepCompare, getImportPath, pathToLog, emptyArray, getStackTrace, codeToString, addCode, quoteObjectKey, backtickQuote } from 'orchid-core';
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';
6
+ import 'url';
7
+ import 'node:path';
6
8
 
7
9
  const getFirstWordAndRest = (input) => {
8
10
  const i = input.search(/(?=[A-Z])|[-_ ]/);
@@ -29,12 +31,6 @@ const getTextAfterTo = (input) => {
29
31
  const getTextAfterFrom = (input) => {
30
32
  return getTextAfterRegExp(input, /(From|-from|_from| from)[A-Z-_ ]/, 4);
31
33
  };
32
- const joinWords = (...words) => {
33
- return words.slice(1).reduce(
34
- (acc, word) => acc + word[0].toUpperCase() + word.slice(1),
35
- words[0]
36
- );
37
- };
38
34
  const joinColumns = (columns) => {
39
35
  return columns.map((column) => `"${column}"`).join(", ");
40
36
  };
@@ -72,26 +68,17 @@ const makePopulateEnumQuery = (item) => {
72
68
  }
73
69
  };
74
70
  };
75
- const begin = {
76
- text: "BEGIN"
77
- };
78
71
  const transaction = (adapter, fn) => {
79
- return adapter.transaction(begin, fn);
72
+ return adapter.transaction(void 0, fn);
80
73
  };
81
74
  const queryLock = (trx) => trx.query(`SELECT pg_advisory_xact_lock('${RAKE_DB_LOCK_KEY}')`);
82
- const exhaustive = (_) => {
83
- throw new Error("Condition was not exhaustive");
84
- };
85
- const pluralize = (w, count, append = "s") => {
86
- return count === 1 ? w : w + append;
87
- };
88
75
 
89
76
  let currentChanges = [];
90
77
  const clearChanges = () => {
91
78
  currentChanges = [];
92
79
  };
93
80
  const getCurrentChanges = () => currentChanges;
94
- const pushChange = (fn) => currentChanges.push(fn);
81
+ const pushChange = (change) => currentChanges.push(change);
95
82
 
96
83
  const versionToString = (config, version) => config.migrationId === "timestamp" ? `${version}` : `${version}`.padStart(config.migrationId.serial, "0");
97
84
  const columnTypeToSql = (item) => {
@@ -1376,22 +1363,28 @@ const astToQuery = (ast) => {
1376
1363
  };
1377
1364
 
1378
1365
  const createMigrationInterface = (tx, up, config) => {
1379
- const adapter = new TransactionAdapter(
1380
- tx,
1381
- tx.client,
1382
- tx.types
1383
- );
1384
- adapter.schema = adapter.adapter.schema ?? "public";
1366
+ const adapter = Object.create(tx);
1367
+ adapter.schema = adapter.getSchema() ?? "public";
1385
1368
  const { query, arrays } = adapter;
1386
1369
  const log = logParamToLogObject(config.logger || console, config.log);
1387
- adapter.query = (q, types) => {
1388
- 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
+ );
1389
1377
  };
1390
- adapter.arrays = (q, types) => {
1391
- 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
+ );
1392
1385
  };
1393
1386
  Object.assign(adapter, { silentQuery: query, silentArrays: arrays });
1394
- const db = createDb$1({
1387
+ const db = createDbWithAdapter({
1395
1388
  adapter,
1396
1389
  columnTypes: config.columnTypes
1397
1390
  });
@@ -2231,11 +2224,14 @@ class Migration {
2231
2224
  });
2232
2225
  }
2233
2226
  }
2234
- const wrapWithLog = async (log, query, fn) => {
2227
+ const wrapWithLog = async (log, text, values, fn) => {
2235
2228
  if (!log) {
2236
2229
  return fn();
2237
2230
  } else {
2238
- const sql = typeof query === "string" ? { text: query, values: [] } : query.values ? query : { ...query, values: [] };
2231
+ const sql = {
2232
+ text,
2233
+ values: values || []
2234
+ };
2239
2235
  const logData = log.beforeQuery(sql);
2240
2236
  try {
2241
2237
  const result = await fn();
@@ -2382,7 +2378,7 @@ const createCollation = async (migration, up, name, options) => {
2382
2378
  await migration.adapter.query(query);
2383
2379
  };
2384
2380
  const queryExists = (db, sql) => {
2385
- return db.adapter.query(sql).then(({ rowCount }) => rowCount > 0);
2381
+ return db.adapter.query(sql.text, sql.values).then(({ rowCount }) => rowCount > 0);
2386
2382
  };
2387
2383
  const renameType = async (migration, from, to, kind) => {
2388
2384
  const [fromSchema, f] = getSchemaAndTableFromName(migration.up ? from : to);
@@ -2605,7 +2601,7 @@ const fileNamesToChangeMigrationId = {
2605
2601
  const fileNamesToChangeMigrationIdMap = Object.fromEntries(
2606
2602
  Object.entries(fileNamesToChangeMigrationId).map(([_, name]) => [name, true])
2607
2603
  );
2608
- const changeIds = async (options, config, [arg, digitsArg]) => {
2604
+ const changeIds = async (adapters, config, [arg, digitsArg]) => {
2609
2605
  if (arg !== "serial" && arg !== "timestamp") {
2610
2606
  throw new Error(
2611
2607
  `Pass "serial" or "timestamp" argument to the "change-ids" command`
@@ -2692,12 +2688,13 @@ After setting \`renameMigrations\` (see above) and renaming the files, run the d
2692
2688
  );
2693
2689
  })
2694
2690
  );
2695
- await options.map((opts) => {
2696
- const adapter = new Adapter(opts);
2697
- renameMigrationVersionsInDb(config, adapter, values).then(
2698
- () => adapter.close()
2699
- );
2700
- });
2691
+ await Promise.all(
2692
+ adapters.map((adapter) => {
2693
+ renameMigrationVersionsInDb(config, adapter, values).then(
2694
+ () => adapter.close()
2695
+ );
2696
+ })
2697
+ );
2701
2698
  config.logger?.log(
2702
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.
2703
2700
 
@@ -2705,14 +2702,14 @@ ${arg === "timestamp" || digits !== 4 ? `Set \`migrationId\`: ${arg === "timesta
2705
2702
  );
2706
2703
  };
2707
2704
  const renameMigrationVersionsInDb = async (config, adapter, values) => {
2708
- await adapter.arrays({
2709
- 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(
2710
2707
  ([oldVersion, , newVersion], i) => `('${oldVersion}', $${i + 1}, '${newVersion}')`
2711
2708
  ).join(
2712
2709
  ", "
2713
2710
  )}) v(oldVersion, name, version) WHERE t.version = v.oldVersion`,
2714
- values: values.map(([, name]) => name)
2715
- });
2711
+ values.map(([, name]) => name)
2712
+ );
2716
2713
  };
2717
2714
 
2718
2715
  const getMigrations = async (ctx, config, up, allowDuplicates, getVersion = getMigrationVersionOrThrow) => {
@@ -2870,16 +2867,16 @@ function getDigitsPrefix(name) {
2870
2867
  }
2871
2868
 
2872
2869
  const saveMigratedVersion = async (db, version, name, config) => {
2873
- await db.silentArrays({
2874
- text: `INSERT INTO "${config.migrationsTable}"(version, name) VALUES ($1, $2)`,
2875
- values: [version, name]
2876
- });
2870
+ await db.silentArrays(
2871
+ `INSERT INTO "${config.migrationsTable}"(version, name) VALUES ($1, $2)`,
2872
+ [version, name]
2873
+ );
2877
2874
  };
2878
2875
  const deleteMigratedVersion = async (db, version, name, config) => {
2879
- const res = await db.silentArrays({
2880
- text: `DELETE FROM "${config.migrationsTable}" WHERE version = $1 AND name = $2`,
2881
- values: [version, name]
2882
- });
2876
+ const res = await db.silentArrays(
2877
+ `DELETE FROM "${config.migrationsTable}" WHERE version = $1 AND name = $2`,
2878
+ [version, name]
2879
+ );
2883
2880
  if (res.rowCount === 0) {
2884
2881
  throw new Error(`Migration ${version}_${name} was not found in db`);
2885
2882
  }
@@ -2912,10 +2909,10 @@ const getMigratedVersionsMap = async (ctx, adapter, config, renameTo) => {
2912
2909
  await adapter.arrays(`ALTER TABLE ${table} ADD COLUMN name TEXT`);
2913
2910
  await Promise.all(
2914
2911
  result.rows.map(
2915
- ([version, name]) => adapter.arrays({
2916
- text: `UPDATE ${table} SET name = $2 WHERE version = $1`,
2917
- values: [version, name]
2918
- })
2912
+ ([version, name]) => adapter.arrays(`UPDATE ${table} SET name = $2 WHERE version = $1`, [
2913
+ version,
2914
+ name
2915
+ ])
2919
2916
  )
2920
2917
  );
2921
2918
  await adapter.arrays(
@@ -2991,89 +2988,88 @@ const createMigrationsTable = async (db, config) => {
2991
2988
  };
2992
2989
 
2993
2990
  const RAKE_DB_LOCK_KEY = "8582141715823621641";
2994
- function makeMigrateFn(defaultCount, up, fn) {
2995
- return async (ctx, options, config, args = [], adapters = options.map((opts) => new Adapter(opts)), dontClose) => {
2996
- const set = await getMigrations(ctx, config, up);
2997
- const arg = args[0];
2998
- let force = arg === "force";
2999
- let count;
3000
- if (arg === "force") {
3001
- force = true;
3002
- } else {
3003
- force = false;
3004
- const num = arg === "all" ? Infinity : parseInt(arg);
3005
- count = isNaN(num) ? void 0 : num;
3006
- }
3007
- const conf = config;
3008
- const length = options.length;
3009
- for (let i = 0; i < length; i++) {
3010
- const opts = options[i];
3011
- const adapter = adapters[i];
3012
- let migrations;
3013
- try {
3014
- 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);
3015
3012
  const versions = await getMigratedVersionsMap(
3016
3013
  ctx,
3017
3014
  trx,
3018
- config,
3015
+ params.config,
3019
3016
  set.renameTo
3020
3017
  );
3021
3018
  migrations = await fn(
3022
3019
  trx,
3023
- conf,
3020
+ params.config,
3024
3021
  set,
3025
3022
  versions,
3026
- count ?? defaultCount,
3023
+ count,
3027
3024
  force
3028
3025
  );
3029
3026
  });
3030
- } catch (err) {
3031
- if (err instanceof NoMigrationsTableError) {
3032
- await transaction(adapter, async (trx) => {
3033
- const config2 = conf;
3034
- await createMigrationsTable(trx, config2);
3035
- const versions = await getMigratedVersionsMap(
3036
- ctx,
3037
- trx,
3038
- config2,
3039
- set.renameTo
3040
- );
3041
- migrations = await fn(
3042
- trx,
3043
- config2,
3044
- set,
3045
- versions,
3046
- count ?? defaultCount,
3047
- force
3048
- );
3049
- });
3050
- } else {
3051
- throw err;
3052
- }
3053
- } finally {
3054
- if (!dontClose) await adapter.close();
3027
+ } else {
3028
+ throw err;
3055
3029
  }
3056
- config.afterChangeCommit?.({
3057
- options: opts,
3058
- up,
3059
- migrations
3060
- });
3061
3030
  }
3062
- return adapters;
3031
+ params.config.afterChangeCommit?.({
3032
+ adapter: params.adapter,
3033
+ up,
3034
+ migrations
3035
+ });
3063
3036
  };
3064
3037
  }
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
+ };
3065
3058
  const migrate = makeMigrateFn(
3066
- Infinity,
3067
3059
  true,
3068
3060
  (trx, config, set, versions, count, force) => migrateOrRollback(trx, config, set, versions, count, true, false, force)
3069
3061
  );
3062
+ const migrateAndClose = async (params) => {
3063
+ await migrate(params);
3064
+ await params.adapter.close();
3065
+ };
3066
+ const migrateCommand = makeMigrateCommand(migrate, Infinity);
3070
3067
  const rollback = makeMigrateFn(
3071
- 1,
3072
3068
  false,
3073
3069
  (trx, config, set, versions, count, force) => migrateOrRollback(trx, config, set, versions, count, false, false, force)
3074
3070
  );
3071
+ const rollbackCommand = makeMigrateCommand(rollback, 1);
3075
3072
  const redo = makeMigrateFn(
3076
- 1,
3077
3073
  true,
3078
3074
  async (trx, config, set, versions, count, force) => {
3079
3075
  set.migrations.reverse();
@@ -3092,7 +3088,8 @@ const redo = makeMigrateFn(
3092
3088
  );
3093
3089
  }
3094
3090
  );
3095
- const getDb = (adapter) => createDb$1({ adapter });
3091
+ const redoCommand = makeMigrateCommand(redo, 1);
3092
+ const getDb = (adapter) => createDbWithAdapter({ adapter });
3096
3093
  const migrateOrRollback = async (trx, config, set, versions, count, up, redo2, force, skipLock) => {
3097
3094
  const { sequence, map: versionsMap } = versions;
3098
3095
  if (up) {
@@ -3138,11 +3135,13 @@ const migrateOrRollback = async (trx, config, set, versions, count, up, redo2, f
3138
3135
  if (!loggedAboutStarting && (!redo2 || !up)) {
3139
3136
  loggedAboutStarting = true;
3140
3137
  config.logger?.log(
3141
- `${redo2 ? "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()}
3142
3139
  `
3143
3140
  );
3144
3141
  }
3145
- await runMigration(trx, up, file, config);
3142
+ const changes = await getChanges(file, config);
3143
+ const adapter = await runMigration(trx, up, changes, config);
3144
+ await changeMigratedVersion(adapter, up, file, config);
3146
3145
  (migrations ?? (migrations = [])).push(file);
3147
3146
  if (up) {
3148
3147
  const name = path.basename(file.path);
@@ -3204,117 +3203,43 @@ Run \`**db command** up force\` to rollback the above migrations and migrate all
3204
3203
  return;
3205
3204
  };
3206
3205
  const changeCache = {};
3207
- const runMigration = async (trx, up, file, config) => {
3206
+ const getChanges = async (file, config) => {
3208
3207
  clearChanges();
3209
- let changes = changeCache[file.path];
3208
+ let changes = file.path ? changeCache[file.path] : void 0;
3210
3209
  if (!changes) {
3211
3210
  const module = await file.load();
3212
3211
  const exported = module?.default && toArray(module.default);
3213
- if (config.forceDefaultExports && !exported) {
3212
+ if (config?.forceDefaultExports && !exported) {
3214
3213
  throw new RakeDbError(
3215
3214
  `Missing a default export in ${file.path} migration`
3216
3215
  );
3217
3216
  }
3218
3217
  changes = exported || getCurrentChanges();
3219
- changeCache[file.path] = changes;
3218
+ if (file.path) changeCache[file.path] = changes;
3220
3219
  }
3220
+ return changes;
3221
+ };
3222
+ const runMigration = async (trx, up, changes, config) => {
3221
3223
  const db = createMigrationInterface(trx, up, config);
3222
3224
  if (changes.length) {
3223
3225
  const from = up ? 0 : changes.length - 1;
3224
3226
  const to = up ? changes.length : -1;
3225
3227
  const step = up ? 1 : -1;
3226
3228
  for (let i = from; i !== to; i += step) {
3227
- await changes[i](db, up);
3229
+ await changes[i].fn(db, up);
3228
3230
  }
3229
3231
  }
3232
+ return db.adapter;
3233
+ };
3234
+ const changeMigratedVersion = async (adapter, up, file, config) => {
3230
3235
  await (up ? saveMigratedVersion : deleteMigratedVersion)(
3231
- db.adapter,
3236
+ adapter,
3232
3237
  file.version,
3233
3238
  path.basename(file.path).slice(file.version.length + 1),
3234
3239
  config
3235
3240
  );
3236
3241
  };
3237
3242
 
3238
- const migrationConfigDefaults = {
3239
- schemaConfig: defaultSchemaConfig,
3240
- migrationsPath: path.join("src", "db", "migrations"),
3241
- migrationId: { serial: 4 },
3242
- migrationsTable: "schemaMigrations",
3243
- snakeCase: false,
3244
- commands: {},
3245
- log: true,
3246
- logger: console,
3247
- import() {
3248
- throw new Error("Please define the `import` setting in `rakeDb` config");
3249
- }
3250
- };
3251
- const processRakeDbConfig = (config) => {
3252
- const result = { ...migrationConfigDefaults, ...config };
3253
- if (!result.recurrentPath) {
3254
- result.recurrentPath = path.join(result.migrationsPath, "recurrent");
3255
- }
3256
- if (!result.log) {
3257
- delete result.logger;
3258
- }
3259
- if (!result.basePath || !result.dbScript) {
3260
- let filePath = getStackTrace()?.[3].getFileName();
3261
- if (!filePath) {
3262
- throw new Error(
3263
- "Failed to determine path to db script. Please set basePath option of rakeDb"
3264
- );
3265
- }
3266
- if (filePath.startsWith("file://")) {
3267
- filePath = fileURLToPath(filePath);
3268
- }
3269
- const ext = path.extname(filePath);
3270
- if (ext !== ".ts" && ext !== ".js" && ext !== ".mjs") {
3271
- throw new Error(
3272
- `Add a .ts suffix to the "${path.basename(filePath)}" when calling it`
3273
- );
3274
- }
3275
- result.basePath = path.dirname(filePath);
3276
- result.dbScript = path.basename(filePath);
3277
- }
3278
- if ("migrationsPath" in result && !path.isAbsolute(result.migrationsPath)) {
3279
- result.migrationsPath = path.resolve(
3280
- result.basePath,
3281
- result.migrationsPath
3282
- );
3283
- }
3284
- if ("recurrentPath" in result && !path.isAbsolute(result.recurrentPath)) {
3285
- result.recurrentPath = path.resolve(result.basePath, result.recurrentPath);
3286
- }
3287
- if ("baseTable" in config && config.baseTable) {
3288
- const { types, snakeCase, language } = config.baseTable.prototype;
3289
- result.columnTypes = types || makeColumnTypes(defaultSchemaConfig);
3290
- if (snakeCase) result.snakeCase = true;
3291
- if (language) result.language = language;
3292
- } else {
3293
- const ct = "columnTypes" in config && config.columnTypes;
3294
- result.columnTypes = (typeof ct === "function" ? ct(
3295
- makeColumnTypes(defaultSchemaConfig)
3296
- ) : ct) || makeColumnTypes(defaultSchemaConfig);
3297
- }
3298
- if (config.migrationId === "serial") {
3299
- result.migrationId = { serial: 4 };
3300
- }
3301
- return result;
3302
- };
3303
- const getDatabaseAndUserFromOptions = (options) => {
3304
- if (options.databaseURL) {
3305
- const url = new URL(options.databaseURL);
3306
- return {
3307
- database: url.pathname.slice(1),
3308
- user: url.username
3309
- };
3310
- } else {
3311
- return {
3312
- database: options.database,
3313
- user: options.user
3314
- };
3315
- }
3316
- };
3317
-
3318
3243
  const colors = {
3319
3244
  yellow: (s) => `\x1B[33m${s}\x1B[0m`,
3320
3245
  green: (s) => `\x1B[32m${s}\x1B[0m`,
@@ -3502,52 +3427,9 @@ const promptText = ({
3502
3427
  });
3503
3428
  };
3504
3429
 
3505
- const setAdapterOptions = (options, set) => {
3506
- if (options.databaseURL) {
3507
- const url = new URL(options.databaseURL);
3508
- if ("database" in set) {
3509
- url.pathname = `/${set.database}`;
3510
- }
3511
- if (set.user !== void 0) {
3512
- url.username = set.user;
3513
- }
3514
- if (set.password !== void 0) {
3515
- url.password = set.password;
3516
- }
3517
- return { ...options, databaseURL: url.toString() };
3518
- } else {
3519
- return {
3520
- ...options,
3521
- ...set
3522
- };
3523
- }
3524
- };
3525
- const setAdminCredentialsToOptions = async (options, create) => {
3526
- const ok = await promptConfirm({
3527
- message: `Would you like to share admin credentials to ${create ? "create" : "drop"} a database?`
3528
- });
3529
- if (!ok) {
3530
- return;
3531
- }
3532
- const user = await promptText({
3533
- message: "Enter admin user:",
3534
- default: "postgres",
3535
- min: 1
3536
- });
3537
- const password = await promptText({
3538
- message: "Enter admin password:",
3539
- password: true
3540
- });
3541
- return setAdapterOptions(options, {
3542
- user,
3543
- password: password || void 0
3544
- });
3545
- };
3546
-
3547
- const execute = async (options, sql) => {
3548
- const db = new Adapter(options);
3430
+ const execute = async (adapter, sql) => {
3549
3431
  try {
3550
- await db.query(sql);
3432
+ await adapter.query(sql);
3551
3433
  return "ok";
3552
3434
  } catch (error) {
3553
3435
  const err = error;
@@ -3562,13 +3444,16 @@ const execute = async (options, sql) => {
3562
3444
  return { error };
3563
3445
  }
3564
3446
  } finally {
3565
- await db.close();
3447
+ await adapter.close();
3566
3448
  }
3567
3449
  };
3568
- const createOrDrop = async (options, adminOptions, config, args) => {
3569
- const params = getDatabaseAndUserFromOptions(options);
3450
+ const createOrDrop = async (adapter, adminAdapter, config, args) => {
3451
+ const params = {
3452
+ database: adapter.getDatabase(),
3453
+ user: adapter.getUser()
3454
+ };
3570
3455
  const result = await execute(
3571
- setAdapterOptions(adminOptions, { database: "postgres" }),
3456
+ adminAdapter.reconfigure({ database: "postgres" }),
3572
3457
  args.sql(params)
3573
3458
  );
3574
3459
  if (result === "ok") {
@@ -3582,31 +3467,28 @@ const createOrDrop = async (options, adminOptions, config, args) => {
3582
3467
  return;
3583
3468
  } else if (result === "forbidden") {
3584
3469
  let message = `Permission denied to ${args.create ? "create" : "drop"} database.`;
3585
- const host = adminOptions.databaseURL ? new URL(adminOptions.databaseURL).hostname : adminOptions.host;
3470
+ const host = adminAdapter.getHost();
3586
3471
  const isLocal = host === "localhost";
3587
3472
  if (!isLocal) {
3588
3473
  message += `
3589
3474
  Don't use this command for database service providers, only for a local db.`;
3590
3475
  }
3591
3476
  config.logger?.log(message);
3592
- const updatedOptions = await setAdminCredentialsToOptions(
3593
- options,
3594
- args.create
3595
- );
3596
- if (!updatedOptions) return;
3597
- 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);
3598
3480
  return;
3599
3481
  } else {
3600
3482
  throw result.error;
3601
3483
  }
3602
3484
  if (!args.create) return;
3603
- const db = new Adapter(options);
3604
- await createMigrationsTable(db, config);
3605
- await db.close();
3485
+ const newlyConnectedAdapter = adapter.reconfigure({});
3486
+ await createMigrationsTable(newlyConnectedAdapter, config);
3487
+ await newlyConnectedAdapter.close();
3606
3488
  };
3607
- const createDb = async (options, config) => {
3608
- for (const opts of options) {
3609
- await createOrDrop(opts, opts, config, {
3489
+ const createDb = async (adapters, config) => {
3490
+ for (const adapter of adapters) {
3491
+ await createOrDrop(adapter, adapter, config, {
3610
3492
  sql({ database, user }) {
3611
3493
  return `CREATE DATABASE "${database}"${user ? ` OWNER "${user}"` : ""}`;
3612
3494
  },
@@ -3620,9 +3502,9 @@ const createDb = async (options, config) => {
3620
3502
  });
3621
3503
  }
3622
3504
  };
3623
- const dropDb = async (options, config) => {
3624
- for (const opts of options) {
3625
- await createOrDrop(opts, opts, config, {
3505
+ const dropDb = async (adapters, config) => {
3506
+ for (const adapter of adapters) {
3507
+ await createOrDrop(adapter, adapter, config, {
3626
3508
  sql({ database }) {
3627
3509
  return `DROP DATABASE "${database}"`;
3628
3510
  },
@@ -3635,10 +3517,33 @@ const dropDb = async (options, config) => {
3635
3517
  });
3636
3518
  }
3637
3519
  };
3638
- const resetDb = async (options, config) => {
3639
- await dropDb(options, config);
3640
- await createDb(options, config);
3641
- await migrate({}, 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
+ };
3642
3547
  };
3643
3548
 
3644
3549
  const filterSchema = (table) => `${table} !~ '^pg_' AND ${table} != 'information_schema'`;
@@ -4602,6 +4507,10 @@ const checkIfIsOuterRecursiveFkey = (data, table, references) => {
4602
4507
  return false;
4603
4508
  };
4604
4509
 
4510
+ const exhaustive = (_) => {
4511
+ throw new Error("Condition was not exhaustive");
4512
+ };
4513
+
4605
4514
  const astToGenerateItems = (config, asts, currentSchema) => {
4606
4515
  return asts.map((ast) => astToGenerateItem(config, ast, currentSchema));
4607
4516
  };
@@ -5347,8 +5256,7 @@ const timestampsToCode = ({ hasTZTimestamps }) => {
5347
5256
  return `t.${key}()`;
5348
5257
  };
5349
5258
 
5350
- const pullDbStructure = async (options, config) => {
5351
- const adapter = new Adapter(options);
5259
+ const pullDbStructure = async (adapter, config) => {
5352
5260
  const currentSchema = adapter.schema || "public";
5353
5261
  const ctx = makeStructureToAstCtx(config, currentSchema);
5354
5262
  const ast = await structureToAst(ctx, adapter, config);
@@ -5379,12 +5287,12 @@ Append \`as\` method manually to ${count > 1 ? "these" : "this"} column${count >
5379
5287
  adapter.close();
5380
5288
  };
5381
5289
 
5382
- const runRecurrentMigrations = async (options, config) => {
5290
+ const runRecurrentMigrations = async (adapters, config) => {
5383
5291
  let dbs;
5384
5292
  let files = 0;
5385
5293
  await readdirRecursive(config.recurrentPath, async (path) => {
5386
5294
  files++;
5387
- dbs ?? (dbs = options.map((opts) => createDb$1({ adapter: new Adapter(opts) })));
5295
+ dbs ?? (dbs = adapters.map((adapter) => createDbWithAdapter({ adapter })));
5388
5296
  const sql = await readFile(path, "utf-8");
5389
5297
  await Promise.all(
5390
5298
  dbs.map(async (db) => {
@@ -5420,8 +5328,7 @@ const readdirRecursive = async (dirPath, cb) => {
5420
5328
  );
5421
5329
  };
5422
5330
 
5423
- const listMigrationsStatuses = async (options, config, args) => {
5424
- const adapters = options.map((opts) => new Adapter(opts));
5331
+ const listMigrationsStatuses = async (adapters, config, args) => {
5425
5332
  const ctx = {};
5426
5333
  const [{ migrations }, ...migrated] = await Promise.all([
5427
5334
  getMigrations(ctx, config, true),
@@ -5430,10 +5337,10 @@ const listMigrationsStatuses = async (options, config, args) => {
5430
5337
  const map = {};
5431
5338
  let maxVersionLength = 12;
5432
5339
  let maxNameLength = 4;
5433
- for (let i = 0; i < options.length; i++) {
5340
+ for (let i = 0; i < adapters.length; i++) {
5434
5341
  const list = migrated[i];
5435
5342
  const key = Object.entries(list.map).map(([version, up]) => `${version}${up ? "t" : "f"}`).join("");
5436
- const database = options[i].database || new URL(options[i].databaseURL).pathname.slice(1);
5343
+ const database = adapters[i].getDatabase();
5437
5344
  if (map[key]) {
5438
5345
  map[key].databases.push(database);
5439
5346
  continue;
@@ -5512,7 +5419,88 @@ const makeChars = (count, char) => {
5512
5419
  return chars;
5513
5420
  };
5514
5421
 
5515
- 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) => {
5516
5504
  if (config.migrations) {
5517
5505
  throw new Error("Cannot rebase migrations defined in the config");
5518
5506
  }
@@ -5521,7 +5509,6 @@ const rebase = async (options, config) => {
5521
5509
  `Cannot rebase when the 'migrationId' is set to 'timestamp' in the config`
5522
5510
  );
5523
5511
  }
5524
- const adapters = options.map((opts) => new Adapter(opts));
5525
5512
  const ctx = {};
5526
5513
  const [set, ...versionMaps] = await Promise.all([
5527
5514
  await getMigrations(ctx, config, true, true),
@@ -5642,20 +5629,23 @@ const rebase = async (options, config) => {
5642
5629
  return files2;
5643
5630
  }, []).sort((a, b) => +b.version - +a.version);
5644
5631
  set.migrations = migrationsDown;
5645
- await redo(
5646
- ctx,
5647
- options,
5648
- {
5649
- ...config,
5650
- async afterRollback() {
5651
- set.migrations = migrationsUp;
5652
- },
5653
- async afterMigrate() {
5654
- set.migrations = migrationsDown;
5655
- }
5632
+ const redoConfig = {
5633
+ ...config,
5634
+ async afterRollback() {
5635
+ set.migrations = migrationsUp;
5656
5636
  },
5657
- ["all"]
5658
- );
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
+ }
5659
5649
  for (let i = renames.length - 1; i >= 0; i--) {
5660
5650
  const [from, version] = renames[i];
5661
5651
  const prefix = String(version).padStart(4, "0");
@@ -5669,10 +5659,10 @@ const rebase = async (options, config) => {
5669
5659
  }
5670
5660
  };
5671
5661
 
5672
- const rakeDb = (options, partialConfig, args = process.argv.slice(2)) => {
5662
+ const rakeDbWithAdapters = (adapters, partialConfig, args = process.argv.slice(2)) => {
5673
5663
  const config = processRakeDbConfig(partialConfig);
5674
5664
  const promise = runCommand(
5675
- options,
5665
+ adapters,
5676
5666
  config,
5677
5667
  args
5678
5668
  ).catch((err) => {
@@ -5682,40 +5672,40 @@ const rakeDb = (options, partialConfig, args = process.argv.slice(2)) => {
5682
5672
  }
5683
5673
  throw err;
5684
5674
  });
5685
- return Object.assign(change, {
5675
+ return Object.assign(makeChange(config), {
5686
5676
  promise
5687
5677
  });
5688
5678
  };
5689
- rakeDb.lazy = (options, partialConfig) => {
5679
+ rakeDbWithAdapters.lazy = (adapters, partialConfig) => {
5690
5680
  const config = processRakeDbConfig(partialConfig);
5691
5681
  return {
5692
- change,
5682
+ change: makeChange(config),
5693
5683
  run(args, conf) {
5694
- return runCommand(options, conf ? { ...config, ...conf } : config, args);
5684
+ return runCommand(adapters, conf ? { ...config, ...conf } : config, args);
5695
5685
  }
5696
5686
  };
5697
5687
  };
5698
- function change(fn) {
5699
- pushChange(fn);
5700
- return fn;
5701
- }
5688
+ const makeChange = (config) => (fn) => {
5689
+ const change = { fn, config };
5690
+ pushChange(change);
5691
+ return change;
5692
+ };
5702
5693
  const rakeDbAliases = {
5703
5694
  migrate: "up",
5704
5695
  rollback: "down",
5705
5696
  s: "status",
5706
5697
  rec: "recurrent"
5707
5698
  };
5708
- const runCommand = async (opts, config, args = process.argv.slice(2)) => {
5699
+ const runCommand = async (adapters, config, args = process.argv.slice(2)) => {
5709
5700
  let arg = args[0]?.split(":")[0];
5710
5701
  if (rakeDbAliases[arg]) {
5711
5702
  args = [...args];
5712
5703
  arg = args[0] = rakeDbAliases[arg];
5713
5704
  }
5714
- const options = toArray(opts);
5715
5705
  args.shift();
5716
5706
  const command = rakeDbCommands[arg]?.run ?? config.commands[arg];
5717
5707
  if (command) {
5718
- await command(options, config, args);
5708
+ await command(adapters, config, args);
5719
5709
  } else if (config.logger) {
5720
5710
  const commandsHelp = [];
5721
5711
  let max = 0;
@@ -5770,14 +5760,14 @@ ${Object.entries(helpArguments).map(
5770
5760
  `);
5771
5761
  }
5772
5762
  return {
5773
- options,
5763
+ adapters,
5774
5764
  config,
5775
5765
  args
5776
5766
  };
5777
5767
  };
5778
5768
  const upCommand = {
5779
- run: (options, config, args) => migrate({}, options, config, args).then(
5780
- () => runRecurrentMigrations(options, config)
5769
+ run: (adapters, config, args) => migrateCommand(adapters, config, args).then(
5770
+ () => runRecurrentMigrations(adapters, config)
5781
5771
  ),
5782
5772
  help: "migrate pending migrations",
5783
5773
  helpArguments: {
@@ -5787,7 +5777,7 @@ const upCommand = {
5787
5777
  }
5788
5778
  };
5789
5779
  const downCommand = {
5790
- run: (options, config, args) => rollback({}, options, config, args),
5780
+ run: (adapters, config, args) => rollbackCommand(adapters, config, args),
5791
5781
  help: "rollback migrated migrations",
5792
5782
  helpArguments: {
5793
5783
  "no arguments": "rollback one last migration",
@@ -5817,8 +5807,8 @@ const rakeDbCommands = {
5817
5807
  help: "drop databases"
5818
5808
  },
5819
5809
  reset: {
5820
- run: (options, config) => resetDb(options, config).then(
5821
- () => runRecurrentMigrations(options, config)
5810
+ run: (adapters, config) => resetDb(adapters, config).then(
5811
+ () => runRecurrentMigrations(adapters, config)
5822
5812
  ),
5823
5813
  help: "drop, create and migrate databases"
5824
5814
  },
@@ -5827,13 +5817,13 @@ const rakeDbCommands = {
5827
5817
  down: downCommand,
5828
5818
  rollback: downCommand,
5829
5819
  redo: {
5830
- run: (options, config, args) => redo({}, options, config, args).then(
5831
- () => runRecurrentMigrations(options, config)
5820
+ run: (adapters, config, args) => redoCommand(adapters, config, args).then(
5821
+ () => runRecurrentMigrations(adapters, config)
5832
5822
  ),
5833
5823
  help: "rollback and migrate, run recurrent"
5834
5824
  },
5835
5825
  pull: {
5836
- run: ([options], config) => pullDbStructure(options, config),
5826
+ run: ([adapter], config) => pullDbStructure(adapter, config),
5837
5827
  help: "generate a combined migration for an existing database"
5838
5828
  },
5839
5829
  new: {
@@ -5859,5 +5849,18 @@ const rakeDbCommands = {
5859
5849
  }
5860
5850
  };
5861
5851
 
5862
- export { Migration, NoMigrationsTableError, RAKE_DB_LOCK_KEY, addColumnComment, addColumnExclude, addColumnIndex, addOrDropEnumValues, astToMigration, changeCache, changeEnumValues, clearChanges, cmpRawSql, colors, columnToSql, columnTypeToSql, commentsToQuery, concatSchemaAndName, constraintToSql, createDb, createMigrationInterface, dbColumnToAst, deleteMigratedVersion, dropDb, encodeColumnDefault, excludesToQuery, exhaustive, generateTimeStamp, getColumnName, getConstraintName, getCurrentChanges, getDatabaseAndUserFromOptions, getDbStructureTableData, getDbTableColumnsChecks, getExcludeName, getFirstWordAndRest, getForeignKeyTable, getIndexName, getMigratedVersionsMap, getSchemaAndTableFromName, getTextAfterFrom, getTextAfterTo, identityToSql, indexesToQuery, instantiateDbColumn, interpolateSqlValues, introspectDbSchema, joinColumns, joinWords, makeDbStructureColumnsShape, makeDomainsMap, makeFileVersion, makePopulateEnumQuery, makeStructureToAstCtx, migrate, migrateOrRollback, migrationConfigDefaults, nameColumnChecks, newMigration, pluralize, primaryKeyToSql, processRakeDbConfig, promptConfirm, promptSelect, promptText, pushChange, queryLock, quoteCustomType, quoteNameFromString, quoteSchemaTable, quoteTable, quoteWithSchema, rakeDb, rakeDbAliases, rakeDbCommands, redo, referencesToSql, renameType, resetDb, rollback, saveMigratedVersion, structureToAst, tableToAst, transaction, versionToString, writeMigrationFile };
5852
+ const migrateFiles = async (db, files) => {
5853
+ const qb = db.$qb;
5854
+ await qb.ensureTransaction(async () => {
5855
+ const adapter = qb.internal.transactionStorage.getStore()?.adapter;
5856
+ for (const load of files) {
5857
+ clearChanges();
5858
+ const changes = await getChanges({ load });
5859
+ const config = changes[0]?.config;
5860
+ await runMigration(adapter, true, changes, config);
5861
+ }
5862
+ });
5863
+ };
5864
+
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 };
5863
5866
  //# sourceMappingURL=index.mjs.map