diff --git a/site/docs/migrations.mdx b/site/docs/migrations.mdx index 11d96f12a..263b96add 100644 --- a/site/docs/migrations.mdx +++ b/site/docs/migrations.mdx @@ -26,19 +26,19 @@ Migrations can use the `Kysely.schema` module to modify the schema. Migrations c ## Execution order -There are two options for ordering migrations in Kysely: strict and permissive. Both options are based on the alphanumeric ordering of the migration name. In either case, an excellent way to name your migrations is to prefix them with an ISO 8601 date string. +Migrations will be run in the alpha-numeric order of your migration names. An excellent way to name your migrations is to prefix them with an ISO 8601 date string. -Strict ordering (the default) will give an error if the alphanumeric order of your migration files does not match the execution order of them in the database. This adds safety by always executing your migrations in the correct, alphanumeric order. +By default, Kysely will also ensure this order matches the execution order of any previously executed migrations in your database. If the orders do not match (for example, a new migration was added alphabetically before a previously executed one), an error will be returned. This adds safety by always executing your migrations in the correct, alphanumeric order. -Permissive ordering will allow new migrations to be run even if they are added alphabetically before ones that have already executed. Permissive ordering works well in large teams where multiple team members may add migrations at the same time in parallel commits without knowing about the other migrations. Permissive ordering will run pending (unexecuted) migrations in order when migrating up. When migrating down, migrations will be undone in the opposite order in which they were executed (reverse sorted by execution timestamp). +There is also an `allowUnorderedMigrations` option. This option will allow new migrations to be run even if they are added alphabetically before ones that have already executed. Allowing unordered migrations works well in large teams where multiple team members may add migrations at the same time in parallel commits without knowing about the other migrations. Pending (unexecuted) migrations will be run in alpha-numeric order when migrating up. When migrating down, migrations will be undone in the opposite order in which they were executed (reverse sorted by execution timestamp). -To use permissive ordering, pass the `migrationOrder` option to Migrator: +To allow unordered migrations, pass the `allowUnorderedMigrations` option to Migrator: ```ts const migrator = new Migrator({ db, provider: new FileMigrationProvider(...), - migrationOrder: 'permissive' + allowUnorderedMigrations: true }) ``` diff --git a/src/migration/migrator.ts b/src/migration/migrator.ts index 609aa63d7..435f393ac 100644 --- a/src/migration/migrator.ts +++ b/src/migration/migrator.ts @@ -9,7 +9,7 @@ import { freeze, getLast } from '../util/object-utils.js' export const DEFAULT_MIGRATION_TABLE = 'kysely_migration' export const DEFAULT_MIGRATION_LOCK_TABLE = 'kysely_migration_lock' -export const DEFAULT_MIGRATION_ORDER = 'strict' +export const DEFAULT_ALLOW_UNORDERED_MIGRATIONS = false export const MIGRATION_LOCK_ID = 'migration_lock' export const NO_MIGRATIONS: NoMigrations = freeze({ __noMigrations__: true }) @@ -268,8 +268,10 @@ export class Migrator { return this.#props.migrationLockTableName ?? DEFAULT_MIGRATION_LOCK_TABLE } - get #migrationOrder(): 'strict' | 'permissive' | undefined { - return this.#props.migrationOrder ?? DEFAULT_MIGRATION_ORDER + get #allowUnorderedMigrations(): boolean { + return ( + this.#props.allowUnorderedMigrations ?? DEFAULT_ALLOW_UNORDERED_MIGRATIONS + ) } get #schemaPlugin(): KyselyPlugin { @@ -464,7 +466,7 @@ export class Migrator { const executedMigrations = await this.#getExecutedMigrations(db) this.#ensureNoMissingMigrations(migrations, executedMigrations) - if (this.#migrationOrder !== 'permissive') { + if (!this.#allowUnorderedMigrations) { this.#ensureMigrationsInOrder(migrations, executedMigrations) } @@ -716,17 +718,17 @@ export interface MigratorProps { /** * Enforces whether or not migrations must be run in alpha-numeric order. * - * In strict mode, migrations must be run in their exact alpha-numeric order. + * When false, migrations must be run in their exact alpha-numeric order. * This is checked against the migrations already run in the database * (`migrationTableName'). This ensures your migrations are always run in * the same order and is the safest option. * - * In permissive mode, migrations are still run in alpha-numeric order, but + * When true, migrations are still run in alpha-numeric order, but * the order is not checked against already-run migrations in the database. * Kysely will simply run all migrations that haven't run yet, in alpha-numeric * order. */ - readonly migrationOrder?: 'strict' | 'permissive' + readonly allowUnorderedMigrations?: boolean } /** diff --git a/test/node/src/migration.test.ts b/test/node/src/migration.test.ts index 93f3de58e..7556edd8b 100644 --- a/test/node/src/migration.test.ts +++ b/test/node/src/migration.test.ts @@ -130,17 +130,17 @@ for (const dialect of DIALECTS) { expect(executedUpMethods2).to.eql([]) }) - it('should run a new migration added before the last executed one with permissive ordering enabled', async () => { + it('should run a new migration added before the last executed one with allowUnorderedMigrations enabled', async () => { const [migrator1, executedUpMethods1] = createMigrations( ['migration1', 'migration3'], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const { results: results1 } = await migrator1.migrateToLatest() const [migrator2, executedUpMethods2] = createMigrations( ['migration1', 'migration2', 'migration3', 'migration4'], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const { results: results2 } = await migrator2.migrateToLatest() @@ -218,18 +218,18 @@ for (const dialect of DIALECTS) { expect(executedUpMethods2).to.eql([]) }) - describe('with permissive ordering', () => { + describe('with allowUnorderedMigrations', () => { it('should return an error if a previously executed migration is missing', async () => { const [migrator1, executedUpMethods1] = createMigrations( ['migration1', 'migration2', 'migration3'], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) await migrator1.migrateToLatest() const [migrator2, executedUpMethods2] = createMigrations( ['migration2', 'migration3', 'migration4'], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const { error } = await migrator2.migrateToLatest() @@ -250,12 +250,12 @@ for (const dialect of DIALECTS) { it('should return an error if a the last executed migration is not found', async () => { const [migrator1, executedUpMethods1] = createMigrations( ['migration1', 'migration2', 'migration3'], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const [migrator2, executedUpMethods2] = createMigrations( ['migration1', 'migration2', 'migration4'], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) await migrator1.migrateToLatest() @@ -456,11 +456,11 @@ for (const dialect of DIALECTS) { expect(executedDownMethods2).to.eql(['migration4', 'migration3']) }) - describe('with permissive ordering enabled', () => { + describe('with allowUnorderedMigrations enabled', () => { it('should migrate up to a specific migration', async () => { const [migrator1, executedUpMethods1] = createMigrations( ['migration1', 'migration3', 'migration4', 'migration5'], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const { results: results1 } = await migrator1.migrateTo('migration3') @@ -473,7 +473,7 @@ for (const dialect of DIALECTS) { 'migration4', 'migration5', ], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const { results: results2 } = await migrator2.migrateTo('migration4') @@ -495,7 +495,7 @@ for (const dialect of DIALECTS) { it('should migrate all the way down', async () => { const [migrator1, executedUpMethods1] = createMigrations( ['migration1', 'migration2', 'migration4'], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const { results: results1 } = await migrator1.migrateToLatest() @@ -503,7 +503,7 @@ for (const dialect of DIALECTS) { const [migrator2, executedUpMethods2, executedDownMethods2] = createMigrations( ['migration1', 'migration2', 'migration3', 'migration4'], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const { results: results2 } = await migrator2.migrateTo(NO_MIGRATIONS) @@ -548,7 +548,7 @@ for (const dialect of DIALECTS) { it('should migrate down to a specific migration', async () => { const [migrator1, executedUpMethods1] = createMigrations( ['migration1', 'migration2', 'migration3', 'migration5'], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const { results: results1 } = await migrator1.migrateTo('migration5') @@ -562,7 +562,7 @@ for (const dialect of DIALECTS) { 'migration4', 'migration5', ], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const { results: results2 } = await migrator2.migrateTo('migration2') @@ -655,17 +655,17 @@ for (const dialect of DIALECTS) { expect(executedUpMethods2).to.eql([]) }) - it('should migrate up one step with permissive ordering enabled', async () => { + it('should migrate up one step with allowUnorderedMigrations enabled', async () => { const [migrator1, executedUpMethods1] = createMigrations( ['migration1', 'migration3'], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const { results: results1 } = await migrator1.migrateToLatest() const [migrator2, executedUpMethods2] = createMigrations( ['migration1', 'migration2', 'migration3', 'migration4'], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const { results: results2 } = await migrator2.migrateUp() @@ -742,10 +742,10 @@ for (const dialect of DIALECTS) { expect(executedDownMethods2).to.eql([]) }) - it('should migrate down one step with permissive ordering enabled', async () => { + it('should migrate down one step with allowUnorderedMigrations enabled', async () => { const [migrator1, executedUpMethods1, _executedDownMethods1] = createMigrations(['migration1', 'migration2', 'migration4'], { - migrationOrder: 'permissive', + allowUnorderedMigrations: true, }) await migrator1.migrateToLatest() @@ -759,7 +759,7 @@ for (const dialect of DIALECTS) { 'migration4', 'migration5', ], - { migrationOrder: 'permissive' } + { allowUnorderedMigrations: true } ) const { results: results1 } = await migrator2.migrateDown()