rake-db 2.15.2 → 2.15.3

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
@@ -2235,7 +2235,7 @@ const saveMigratedVersion = async (db, version, name, config) => {
2235
2235
  values: [version, name]
2236
2236
  });
2237
2237
  };
2238
- const removeMigratedVersion = async (db, version, name, config) => {
2238
+ const deleteMigratedVersion = async (db, version, name, config) => {
2239
2239
  const res = await db.silentArrays({
2240
2240
  text: `DELETE FROM ${quoteWithSchema({
2241
2241
  name: config.migrationsTable
@@ -2248,13 +2248,13 @@ const removeMigratedVersion = async (db, version, name, config) => {
2248
2248
  };
2249
2249
  class NoMigrationsTableError extends Error {
2250
2250
  }
2251
- const getMigratedVersionsMap = async (ctx, adapter, config) => {
2251
+ const getMigratedVersionsMap = async (ctx, adapter, config, renameTo) => {
2252
2252
  try {
2253
2253
  const table = quoteWithSchema({
2254
2254
  name: config.migrationsTable
2255
2255
  });
2256
2256
  const result = await adapter.arrays(
2257
- `SELECT * FROM ${table}`
2257
+ `SELECT * FROM ${table} ORDER BY version`
2258
2258
  );
2259
2259
  if (!result.fields[1]) {
2260
2260
  const { migrations } = await getMigrations(ctx, config, true);
@@ -2286,7 +2286,11 @@ const getMigratedVersionsMap = async (ctx, adapter, config) => {
2286
2286
  `ALTER TABLE ${table} ALTER COLUMN name SET NOT NULL`
2287
2287
  );
2288
2288
  }
2289
- return Object.fromEntries(result.rows);
2289
+ let versions = Object.fromEntries(result.rows);
2290
+ if (renameTo) {
2291
+ versions = await renameMigrations(config, adapter, versions, renameTo);
2292
+ }
2293
+ return { map: versions, sequence: result.rows.map((row) => +row[0]) };
2290
2294
  } catch (err) {
2291
2295
  if (err.code === "42P01") {
2292
2296
  throw new NoMigrationsTableError();
@@ -2295,6 +2299,47 @@ const getMigratedVersionsMap = async (ctx, adapter, config) => {
2295
2299
  }
2296
2300
  }
2297
2301
  };
2302
+ async function renameMigrations(config, trx, versions, renameTo) {
2303
+ let first;
2304
+ for (const version in versions) {
2305
+ first = version;
2306
+ break;
2307
+ }
2308
+ if (!first || getMigrationVersion(config, first))
2309
+ return versions;
2310
+ const fileName = fileNamesToChangeMigrationId[renameTo];
2311
+ const filePath = path.join(config.migrationsPath, fileName);
2312
+ const json = await fs.readFile(filePath, "utf-8");
2313
+ let data;
2314
+ try {
2315
+ data = JSON.parse(json);
2316
+ if (typeof data !== "object")
2317
+ throw new Error("Config for renaming is not an object");
2318
+ } catch (err) {
2319
+ throw new Error(`Failed to read ${pathToFileURL(filePath)}`, {
2320
+ cause: err
2321
+ });
2322
+ }
2323
+ const values = [];
2324
+ const updatedVersions = {};
2325
+ for (const version in versions) {
2326
+ const name = versions[version];
2327
+ const key = `${version}_${name}`;
2328
+ let newVersion = data[key];
2329
+ if (!newVersion) {
2330
+ throw new Error(
2331
+ `Failed to find an entry for the migrated ${key} in the ${fileName} config`
2332
+ );
2333
+ }
2334
+ if (renameTo === "serial") {
2335
+ newVersion = String(newVersion).padStart(4, "0");
2336
+ }
2337
+ updatedVersions[newVersion] = name;
2338
+ values.push([version, name, newVersion]);
2339
+ }
2340
+ await renameMigrationVersionsInDb(config, trx, values);
2341
+ return updatedVersions;
2342
+ }
2298
2343
 
2299
2344
  const createMigrationsTable = async (db, config) => {
2300
2345
  var _a, _b, _c;
@@ -2345,8 +2390,17 @@ const RAKE_DB_LOCK_KEY = "8582141715823621641";
2345
2390
  function makeMigrateFn(defaultCount, up, fn) {
2346
2391
  return async (ctx, options, config, args = []) => {
2347
2392
  const set = await getMigrations(ctx, config, up);
2348
- const count = getCount(args);
2349
- const conf = prepareConfig(config, args, count);
2393
+ const arg = args[0];
2394
+ let force = arg === "force";
2395
+ let count;
2396
+ if (arg === "force") {
2397
+ force = true;
2398
+ } else {
2399
+ force = false;
2400
+ const num = arg === "all" ? Infinity : parseInt(arg);
2401
+ count = isNaN(num) ? void 0 : num;
2402
+ }
2403
+ const conf = prepareConfig(config, args, count === void 0 || force);
2350
2404
  const asts = [];
2351
2405
  const appCodeUpdaterCache = {};
2352
2406
  const { appCodeUpdater } = conf;
@@ -2356,13 +2410,20 @@ function makeMigrateFn(defaultCount, up, fn) {
2356
2410
  const adapter = new Adapter(opts);
2357
2411
  try {
2358
2412
  await transaction(adapter, async (trx) => {
2359
- await fn(
2413
+ const versions = await getMigratedVersionsMap(
2360
2414
  ctx,
2415
+ trx,
2416
+ config,
2417
+ set.renameTo
2418
+ );
2419
+ await fn(
2361
2420
  trx,
2362
2421
  conf,
2363
2422
  set,
2423
+ versions,
2364
2424
  count != null ? count : defaultCount,
2365
- localAsts
2425
+ localAsts,
2426
+ force
2366
2427
  );
2367
2428
  });
2368
2429
  } catch (err) {
@@ -2370,7 +2431,21 @@ function makeMigrateFn(defaultCount, up, fn) {
2370
2431
  await transaction(adapter, async (trx) => {
2371
2432
  const config2 = conf;
2372
2433
  await createMigrationsTable(trx, config2);
2373
- await fn(ctx, trx, config2, set, count != null ? count : defaultCount, localAsts);
2434
+ const versions = await getMigratedVersionsMap(
2435
+ ctx,
2436
+ trx,
2437
+ config2,
2438
+ set.renameTo
2439
+ );
2440
+ await fn(
2441
+ trx,
2442
+ config2,
2443
+ set,
2444
+ versions,
2445
+ count != null ? count : defaultCount,
2446
+ localAsts,
2447
+ force
2448
+ );
2374
2449
  });
2375
2450
  } else {
2376
2451
  throw err;
@@ -2392,31 +2467,37 @@ function makeMigrateFn(defaultCount, up, fn) {
2392
2467
  const migrate = makeMigrateFn(
2393
2468
  Infinity,
2394
2469
  true,
2395
- (ctx, trx, config, migrations, count, asts) => migrateOrRollback(ctx, trx, config, migrations, count, asts, true)
2470
+ (trx, config, set, versions, count, asts, force) => migrateOrRollback(trx, config, set, versions, count, asts, true, force)
2396
2471
  );
2397
2472
  const rollback = makeMigrateFn(
2398
2473
  1,
2399
2474
  false,
2400
- (ctx, trx, config, migrations, count, asts) => migrateOrRollback(ctx, trx, config, migrations, count, asts, false)
2475
+ (trx, config, set, versions, count, asts, force) => migrateOrRollback(trx, config, set, versions, count, asts, false, force)
2401
2476
  );
2402
2477
  const redo = makeMigrateFn(
2403
2478
  1,
2404
2479
  true,
2405
- async (ctx, trx, config, set, count, asts) => {
2480
+ async (trx, config, set, versions, count, asts, force) => {
2406
2481
  set.migrations.reverse();
2407
- await migrateOrRollback(ctx, trx, config, set, count, asts, false);
2482
+ await migrateOrRollback(trx, config, set, versions, count, asts, false);
2408
2483
  set.migrations.reverse();
2409
- await migrateOrRollback(ctx, trx, config, set, count, asts, true, true);
2484
+ await migrateOrRollback(
2485
+ trx,
2486
+ config,
2487
+ set,
2488
+ versions,
2489
+ count,
2490
+ asts,
2491
+ true,
2492
+ force,
2493
+ true
2494
+ );
2410
2495
  }
2411
2496
  );
2412
2497
  const getDb = (adapter) => createDb$1({ adapter });
2413
- const getCount = (args) => {
2414
- const num = args[0] === "all" ? Infinity : parseInt(args[0]);
2415
- return isNaN(num) ? void 0 : num;
2416
- };
2417
- function prepareConfig(config, args, count) {
2498
+ function prepareConfig(config, args, hasArg) {
2418
2499
  config = __spreadValues$5({}, config);
2419
- const i = count === void 0 ? 0 : 1;
2500
+ const i = hasArg ? 0 : 1;
2420
2501
  const arg = args[i];
2421
2502
  if (arg === "--code") {
2422
2503
  config.useCodeUpdater = args[i + 1] !== "false";
@@ -2425,75 +2506,79 @@ function prepareConfig(config, args, count) {
2425
2506
  delete config.appCodeUpdater;
2426
2507
  return config;
2427
2508
  }
2428
- const migrateOrRollback = async (ctx, trx, config, set, count, asts, up, skipLock) => {
2509
+ const migrateOrRollback = async (trx, config, set, versions, count, asts, up, force, skipLock) => {
2429
2510
  var _a, _b, _c;
2511
+ const { sequence, map: versionsMap } = versions;
2512
+ if (up) {
2513
+ const rollbackTo = checkMigrationOrder(set, versions, force);
2514
+ if (rollbackTo) {
2515
+ let i = sequence.length - 1;
2516
+ for (; i >= 0; i--) {
2517
+ if (rollbackTo >= sequence[i]) {
2518
+ i++;
2519
+ break;
2520
+ }
2521
+ }
2522
+ if (i < 0)
2523
+ i = 0;
2524
+ set.migrations.reverse();
2525
+ await migrateOrRollback(
2526
+ trx,
2527
+ config,
2528
+ set,
2529
+ versions,
2530
+ sequence.length - i,
2531
+ asts,
2532
+ false
2533
+ );
2534
+ set.migrations.reverse();
2535
+ }
2536
+ }
2430
2537
  if (!skipLock)
2431
2538
  await queryLock(trx);
2432
2539
  let db;
2433
2540
  await ((_a = config[up ? "beforeMigrate" : "beforeRollback"]) == null ? void 0 : _a.call(config, db != null ? db : db = getDb(trx)));
2434
- let migratedVersions = await getMigratedVersionsMap(ctx, trx, config);
2435
- if (set.renameTo) {
2436
- migratedVersions = await renameMigrations(
2437
- config,
2438
- trx,
2439
- migratedVersions,
2440
- set.renameTo
2441
- );
2442
- }
2443
2541
  for (const file of set.migrations) {
2444
- if (up && migratedVersions[file.version] || !up && !migratedVersions[file.version]) {
2542
+ if (up && versionsMap[file.version] || !up && !versionsMap[file.version]) {
2445
2543
  continue;
2446
2544
  }
2447
2545
  if (count-- <= 0)
2448
2546
  break;
2449
2547
  await runMigration(trx, up, file, config, asts);
2548
+ if (up) {
2549
+ const name = path.basename(file.path);
2550
+ versionsMap[file.version] = name;
2551
+ sequence.push(+file.version);
2552
+ } else {
2553
+ versionsMap[file.version] = void 0;
2554
+ sequence.pop();
2555
+ }
2450
2556
  (_b = config.logger) == null ? void 0 : _b.log(
2451
2557
  `${up ? "Migrated" : "Rolled back"} ${pathToLog(file.path)}`
2452
2558
  );
2453
2559
  }
2454
2560
  await ((_c = config[up ? "afterMigrate" : "afterRollback"]) == null ? void 0 : _c.call(config, db != null ? db : db = getDb(trx)));
2455
2561
  };
2456
- async function renameMigrations(config, trx, migratedVersions, renameTo) {
2457
- let first;
2458
- for (const version in migratedVersions) {
2459
- first = version;
2460
- break;
2461
- }
2462
- if (!first || getMigrationVersion(config, first))
2463
- return migratedVersions;
2464
- const fileName = fileNamesToChangeMigrationId[renameTo];
2465
- const filePath = path.join(config.migrationsPath, fileName);
2466
- const json = await fs.readFile(filePath, "utf-8");
2467
- let data;
2468
- try {
2469
- data = JSON.parse(json);
2470
- if (typeof data !== "object")
2471
- throw new Error("Config for renaming is not an object");
2472
- } catch (err) {
2473
- throw new Error(`Failed to read ${pathToFileURL(filePath)}`, {
2474
- cause: err
2475
- });
2476
- }
2477
- const values = [];
2478
- const updatedVersions = {};
2479
- for (const version in migratedVersions) {
2480
- const name = migratedVersions[version];
2481
- const key = `${version}_${name}`;
2482
- let newVersion = data[key];
2483
- if (!newVersion) {
2484
- throw new Error(
2485
- `Failed to find an entry for the migrated ${key} in the ${fileName} config`
2486
- );
2487
- }
2488
- if (renameTo === "serial") {
2489
- newVersion = String(newVersion).padStart(4, "0");
2562
+ const checkMigrationOrder = (set, { sequence, map }, force) => {
2563
+ const last = sequence[sequence.length - 1];
2564
+ if (last) {
2565
+ for (const file of set.migrations) {
2566
+ const version = +file.version;
2567
+ if (version > last || map[version])
2568
+ continue;
2569
+ if (!force) {
2570
+ throw new Error(
2571
+ `Cannot migrate ${path.basename(
2572
+ file.path
2573
+ )} because the higher position ${map[last]} was already migrated.
2574
+ Run \`**db command** up force\` to rollback the above migrations and migrate all`
2575
+ );
2576
+ }
2577
+ return version;
2490
2578
  }
2491
- updatedVersions[newVersion] = name;
2492
- values.push([version, name, newVersion]);
2493
2579
  }
2494
- await renameMigrationVersionsInDb(config, trx, values);
2495
- return updatedVersions;
2496
- }
2580
+ return;
2581
+ };
2497
2582
  async function runCodeUpdaterAfterAll(options, config, appCodeUpdater, asts, cache) {
2498
2583
  for (const ast of asts) {
2499
2584
  await (appCodeUpdater == null ? void 0 : appCodeUpdater.process({
@@ -2541,7 +2626,7 @@ const runMigration = async (trx, up, file, config, asts) => {
2541
2626
  await changes[i](db, up);
2542
2627
  }
2543
2628
  }
2544
- await (up ? saveMigratedVersion : removeMigratedVersion)(
2629
+ await (up ? saveMigratedVersion : deleteMigratedVersion)(
2545
2630
  db.adapter,
2546
2631
  file.version,
2547
2632
  path.basename(file.path).slice(file.version.length + 1),
@@ -4033,7 +4118,7 @@ const listMigrationsStatuses = async (options, config, args) => {
4033
4118
  let maxNameLength = 4;
4034
4119
  for (let i = 0; i < options.length; i++) {
4035
4120
  const list = migrated[i];
4036
- const key = Object.entries(list).map(([version, up]) => `${version}${up ? "t" : "f"}`).join("");
4121
+ const key = Object.entries(list.map).map(([version, up]) => `${version}${up ? "t" : "f"}`).join("");
4037
4122
  const database = options[i].database || new URL(options[i].databaseURL).pathname.slice(1);
4038
4123
  if (map[key]) {
4039
4124
  map[key].databases.push(database);
@@ -4053,7 +4138,7 @@ const listMigrationsStatuses = async (options, config, args) => {
4053
4138
  maxNameLength = name.length;
4054
4139
  }
4055
4140
  return {
4056
- up: !!list[item.version],
4141
+ up: !!list.map[item.version],
4057
4142
  version: item.version,
4058
4143
  name,
4059
4144
  url: pathToFileURL(item.path)
@@ -4159,8 +4244,8 @@ const rebase = async (options, config) => {
4159
4244
  if (start === -1)
4160
4245
  return;
4161
4246
  const combinedVersionsMap = {};
4162
- for (const map of versionMaps) {
4163
- Object.assign(combinedVersionsMap, map);
4247
+ for (const versions of versionMaps) {
4248
+ Object.assign(combinedVersionsMap, versions.map);
4164
4249
  }
4165
4250
  const renames = [];
4166
4251
  const renamesMap = {};
@@ -4396,13 +4481,15 @@ Commands:
4396
4481
  reset drop, create and migrate databases
4397
4482
  pull generate a combined migration for an existing database
4398
4483
  new create new migration file, see below
4399
- migrate migrate pending migrations, run recurrent
4400
- up migrate pending migrations, don't run recurrent
4484
+ up migrate pending migrations
4485
+ migrate migrate pending migrations, also run recurrent
4486
+ up|migrate force resolve the case of a non-migrated file in the middle
4401
4487
  rollback or down rollback the last migrated
4402
4488
  redo rollback and migrate, run recurrent
4403
4489
  status or s list migrations statuses
4404
4490
  status path or s p list migrations statuses and paths to files
4405
4491
  rec or recurrent run recurrent migrations
4492
+ rebase move local migrations below the new ones from upstream
4406
4493
  change-ids serial change migrations ids to 4 digit serial
4407
4494
  change-ids serial 42 change migrations ids to custom digits serial
4408
4495
  change-ids timestamp change migrations ids to timestamps
@@ -4422,5 +4509,5 @@ Migrate and rollback common arguments:
4422
4509
  --code false do not run code updater
4423
4510
  `;
4424
4511
 
4425
- export { Migration, NoMigrationsTableError, RAKE_DB_LOCK_KEY, changeCache, createDb, createMigrationInterface, dropDb, generate, generateTimeStamp, getDatabaseAndUserFromOptions, getMigratedVersionsMap, makeFileVersion, migrate, migrateOrRollback, migrationConfigDefaults, processRakeDbConfig, rakeDb, redo, removeMigratedVersion, resetDb, rollback, saveMigratedVersion, writeMigrationFile };
4512
+ export { Migration, NoMigrationsTableError, RAKE_DB_LOCK_KEY, changeCache, createDb, createMigrationInterface, deleteMigratedVersion, dropDb, generate, generateTimeStamp, getDatabaseAndUserFromOptions, getMigratedVersionsMap, makeFileVersion, migrate, migrateOrRollback, migrationConfigDefaults, processRakeDbConfig, rakeDb, redo, resetDb, rollback, saveMigratedVersion, writeMigrationFile };
4426
4513
  //# sourceMappingURL=index.mjs.map