@warlock.js/cascade 4.9.1 → 4.10.0

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/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ All notable changes to `@warlock.js/cascade` are documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
6
6
 
7
+ ## 4.9.2
8
+
9
+ ### Fixed
10
+
11
+ - `migrate:rollback` and `migrate:rollback --all` ran `down()` migrations in **apply order** instead of reverse. `getMigrationsToRollback` reversed the executed list and then re-sorted it ascending, which put it straight back into forward order and made the reverse dead code — so a rollback would drop a table before dropping the column added to it, failing with `relation "…" does not exist`. Any batch containing more than one migration was affected; single-migration batches hid it because one item has no order to get wrong
12
+ - migration ordering now lives in `migration-order.ts` with an explicit `sortMigrationsForRollback`. The descending sort is required, not cosmetic: the executed list is read back ordered by `batch, name`, so it is alphabetical rather than chronological and simply *not* re-sorting after the reverse would have produced reverse-alphabetical order — a different wrong answer
13
+
7
14
  ## 4.9.1
8
15
 
9
16
  ### Fixed
package/cjs/index.cjs CHANGED
@@ -21639,6 +21639,37 @@ function compareCreatedAt(a, b) {
21639
21639
  if (dateB) return 1;
21640
21640
  }
21641
21641
 
21642
+ //#endregion
21643
+ //#region ../cascade/src/migration/migration-order.ts
21644
+ /**
21645
+ * Comparator for applying migrations — oldest first.
21646
+ *
21647
+ * Priority:
21648
+ * 1. `createdAt` timestamp (older = earlier)
21649
+ * 2. Alphabetical by migration name (last resort)
21650
+ */
21651
+ function sortMigrations(a, b) {
21652
+ const byCreatedAt = compareCreatedAt(a.createdAt, b.createdAt);
21653
+ if (byCreatedAt !== void 0) return byCreatedAt;
21654
+ return a.migrationName.localeCompare(b.migrationName);
21655
+ }
21656
+ /**
21657
+ * Comparator for rolling migrations back — newest first, the exact inverse of
21658
+ * {@link sortMigrations}.
21659
+ *
21660
+ * A rollback has to undo migrations in the reverse of the order they were
21661
+ * applied, or a `down()` will hit schema its predecessor already removed —
21662
+ * dropping a table before dropping the column that was added to it.
21663
+ *
21664
+ * This must be an explicit descending sort rather than a `.reverse()` of the
21665
+ * executed list: that list is read back ordered by `batch, name`, so it is
21666
+ * alphabetical rather than chronological, and reversing it merely produces
21667
+ * reverse-alphabetical order.
21668
+ */
21669
+ function sortMigrationsForRollback(a, b) {
21670
+ return sortMigrations(b, a);
21671
+ }
21672
+
21642
21673
  //#endregion
21643
21674
  //#region ../cascade/src/migration/sql-grammar.ts
21644
21675
  /**
@@ -21763,18 +21794,6 @@ var SQLGrammar = class {
21763
21794
  //#endregion
21764
21795
  //#region ../cascade/src/migration/migration-runner.ts
21765
21796
  /**
21766
- * Comparator for sorting migration classes.
21767
- *
21768
- * Priority:
21769
- * 1. `createdAt` timestamp (older = earlier)
21770
- * 2. Alphabetical by migration name (last resort)
21771
- */
21772
- function sortMigrations(a, b) {
21773
- const byCreatedAt = compareCreatedAt(a.createdAt, b.createdAt);
21774
- if (byCreatedAt !== void 0) return byCreatedAt;
21775
- return a.migrationName.localeCompare(b.migrationName);
21776
- }
21777
- /**
21778
21797
  * Migration runner that executes migrations.
21779
21798
  *
21780
21799
  * This is a pure executor - it doesn't discover migrations.
@@ -22348,13 +22367,24 @@ var MigrationRunner = class {
22348
22367
  return this.migrations.filter((m) => !executedNames.has(m.migrationName)).sort(sortMigrations);
22349
22368
  }
22350
22369
  /**
22351
- * Get migrations to rollback.
22370
+ * Get migrations to rollback, newest-first.
22371
+ *
22372
+ * A rollback must undo migrations in the exact inverse of the order `up`
22373
+ * applied them, or a `down()` will hit schema its predecessor already
22374
+ * removed — dropping a table before dropping the column added to it, say.
22375
+ *
22376
+ * The sort has to be explicitly **descending**. Reversing the executed list
22377
+ * is not enough: `getExecutedMigrations` orders by `batch, name`, so the
22378
+ * input is alphabetical rather than chronological, and reversing it only
22379
+ * yields reverse-alphabetical order. (Sorting *ascending* here — which is
22380
+ * what this method used to do after a `.reverse()` — silently restored the
22381
+ * forward `up` order and made the reverse dead code.)
22352
22382
  */
22353
22383
  async getMigrationsToRollback(batches) {
22354
22384
  const executed = await this.getExecutedMigrations();
22355
22385
  if (executed.length === 0) return [];
22356
22386
  const batchNumbers = [...new Set(executed.map((r) => r.batch))].sort((a, b) => b - a).slice(0, batches);
22357
- return executed.filter((r) => batchNumbers.includes(r.batch)).reverse().map((r) => this.migrations.find((m) => m.migrationName === r.name)).filter((m) => !!m).sort(sortMigrations);
22387
+ return executed.filter((r) => batchNumbers.includes(r.batch)).map((r) => this.migrations.find((m) => m.migrationName === r.name)).filter((m) => !!m).sort(sortMigrationsForRollback);
22358
22388
  }
22359
22389
  /**
22360
22390
  * Get executed migration records.