{"id":13683623,"url":"https://github.com/sequelize/umzug","last_synced_at":"2025-05-14T08:04:17.613Z","repository":{"id":22595956,"uuid":"25937956","full_name":"sequelize/umzug","owner":"sequelize","description":"Framework agnostic migration tool for Node.js","archived":false,"fork":false,"pushed_at":"2025-05-06T19:46:31.000Z","size":3460,"stargazers_count":2098,"open_issues_count":18,"forks_count":162,"subscribers_count":20,"default_branch":"main","last_synced_at":"2025-05-07T07:04:48.573Z","etag":null,"topics":["javascript","migrations","sequelize","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sequelize.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":null,"patreon":null,"open_collective":"sequelize","ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2014-10-29T19:36:59.000Z","updated_at":"2025-05-06T03:29:18.000Z","dependencies_parsed_at":"2024-02-02T23:30:41.757Z","dependency_job_id":"167ccd3a-f775-441d-9336-966a6385d9f8","html_url":"https://github.com/sequelize/umzug","commit_stats":{"total_commits":682,"total_committers":60,"mean_commits":"11.366666666666667","dds":0.7316715542521994,"last_synced_commit":"cc0d00b204b75623d3963b3faa8cf49634041238"},"previous_names":[],"tags_count":64,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequelize%2Fumzug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequelize%2Fumzug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequelize%2Fumzug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sequelize%2Fumzug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sequelize","download_url":"https://codeload.github.com/sequelize/umzug/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254101584,"owners_count":22014907,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","migrations","sequelize","typescript"],"created_at":"2024-08-02T13:02:19.485Z","updated_at":"2025-05-14T08:04:17.575Z","avatar_url":"https://github.com/sequelize.png","language":"TypeScript","readme":"# Umzug\n\n[![Build Status](https://github.com/sequelize/umzug/actions/workflows/ci.yml/badge.svg)](https://github.com/sequelize/umzug/actions/workflows/ci.yml/badge.svg)\n[![npm](https://badgen.net/npm/v/umzug)](https://www.npmjs.com/package/umzug)\n[![npm (downloads)](https://badgen.net/npm/dm/umzug)](https://npmjs.com/package/umzug)\n\nUmzug is a framework-agnostic migration tool for Node. It provides a clean API for running and rolling back tasks.\n\n## Highlights\n\n* Written in TypeScript\n\t* Built-in typings\n\t* Auto-completion right in your IDE\n\t* Documentation right in your IDE\n* Programmatic API for migrations\n* Built-in [CLI](#cli)\n* Database agnostic\n* Supports logging of migration process\n* Supports multiple storages for migration data\n* [Usage examples](./examples)\n\n## Documentation\n\n_Note: these are the docs for the latest version of umzug, which has several breaking changes from v2.x. See [the upgrading section](#upgrading-from-v2x) for a migration guide. For the previous stable version, please refer to the [v2.x branch](https://github.com/sequelize/umzug/tree/v2.x)._\n\n### Minimal Example\n\nThe following example uses a Sqlite database through sequelize and persists the migration data in the database itself through the sequelize storage. There are several more involved examples covering a few different scenarios in the [examples folder](./examples). Note that although this uses Sequelize, Umzug isn't coupled to Sequelize, it's just one of the (most commonly-used) supported storages.\n\n```js\n// index.js\nconst {Sequelize} = require('sequelize')\nconst {Umzug, SequelizeStorage} = require('umzug')\n\nconst sequelize = new Sequelize({dialect: 'sqlite', storage: './db.sqlite'})\n\nconst umzug = new Umzug({\n  migrations: {glob: 'migrations/*.js'},\n  context: sequelize.getQueryInterface(),\n  storage: new SequelizeStorage({sequelize}),\n  logger: console,\n})\n\n// Checks migrations and run them if they are not already applied. To keep\n// track of the executed migrations, a table (and sequelize model) called SequelizeMeta\n// will be automatically created (if it doesn't exist already) and parsed.\nawait umzug.up()\n```\n\n```js\n// migrations/00_initial.js\n\nconst {Sequelize} = require('sequelize')\n\nasync function up({context: queryInterface}) {\n  await queryInterface.createTable('users', {\n    id: {\n      type: Sequelize.INTEGER,\n      allowNull: false,\n      primaryKey: true,\n    },\n    name: {\n      type: Sequelize.STRING,\n      allowNull: false,\n    },\n    createdAt: {\n      type: Sequelize.DATE,\n      allowNull: false,\n    },\n    updatedAt: {\n      type: Sequelize.DATE,\n      allowNull: false,\n    },\n  })\n}\n\nasync function down({context: queryInterface}) {\n  await queryInterface.dropTable('users')\n}\n\nmodule.exports = {up, down}\n```\n\nNote that we renamed the `context` argument to `queryInterface` for clarity. The `context` is whatever we specified when creating the Umzug instance in `index.js`.\n\n\u003cdetails\u003e\n\u003csummary\u003eYou can also write your migrations in typescript by using `ts-node` in the entrypoint:\u003c/summary\u003e\n\n```typescript\n// index.ts\nrequire('ts-node/register')\n\nimport { Sequelize } from 'sequelize';\nimport { Umzug, SequelizeStorage } from 'umzug';\n\nconst sequelize = new Sequelize({ dialect: 'sqlite', storage: './db.sqlite' });\n\nconst umzug = new Umzug({\n  migrations: { glob: 'migrations/*.ts' },\n  context: sequelize.getQueryInterface(),\n  storage: new SequelizeStorage({ sequelize }),\n  logger: console,\n});\n\n// export the type helper exposed by umzug, which will have the `context` argument typed correctly\nexport type Migration = typeof umzug._types.migration;\n\n(async () =\u003e {\n  await umzug.up();\n})();\n```\n\n```typescript\n// migrations/00_initial.ts\nimport type { Migration } from '..';\n\n// types will now be available for `queryInterface`\nexport const up: Migration = ({ context: queryInterface }) =\u003e queryInterface.createTable(...)\nexport const down: Migration = ({ context: queryInterface }) =\u003e queryInterface.dropTable(...)\n```\n\u003c/details\u003e\n\nSee [these tests](./test/umzug.test.ts) for more examples of Umzug usage, including:\n\n- passing `ignore` and `cwd` parameters to the glob instructions\n- customising migrations ordering\n- finding migrations from multiple different directories\n- using non-js file extensions via a custom resolver, e.g. `.sql`\n\n### Usage\n\n#### Installation\n\nUmzug is available on npm by specifying the correct tag:\n\n```bash\nnpm install umzug\n```\n\n#### Umzug instance\n\nIt is possible to configure an Umzug instance by passing an object to the constructor.\n\n```js\nconst {Umzug} = require('umzug')\n\nconst umzug = new Umzug({\n  /* ... options ... */\n})\n```\n\nDetailed documentation for these options are in the `UmzugOptions` TypeScript interface, which can be found in [src/types.ts](./src/types.ts).\n\n#### Getting all pending migrations\n\nYou can get a list of pending (i.e. not yet executed) migrations with the `pending()` method:\n\n```js\nconst migrations = await umzug.pending()\n// returns an array of all pending migrations.\n```\n\n#### Getting all executed migrations\n\nYou can get a list of already executed migrations with the `executed()` method:\n\n```js\nconst migrations = await umzug.executed()\n// returns an array of all already executed migrations\n```\n\n#### Executing pending migrations\n\nThe `up` method can be used to execute all pending migrations.\n\n```js\nconst migrations = await umzug.up()\n// returns an array of all executed migrations\n```\n\nIt is also possible to pass the name of a migration in order to just run the migrations from the current state to the passed migration name (inclusive).\n\n```js\nawait umzug.up({to: '20141101203500-task'})\n```\n\nTo limit the number of migrations that are run, `step` can be used:\n\n```js\n// This will run the next two migrations\nawait umzug.up({step: 2})\n```\n\nRunning specific migrations while ignoring the right order, can be done like this:\n\n```js\nawait umzug.up({migrations: ['20141101203500-task', '20141101203501-task-2']})\n```\n\n#### Reverting executed migration\n\nThe `down` method can be used to revert the last executed migration.\n\n```js\nconst migration = await umzug.down()\n// reverts the last migration and returns it.\n```\n\nTo revert more than one migration, you can use `step`:\n\n```js\n// This will revert the last two migrations\nawait umzug.down({step: 2})\n```\n\nIt is possible to pass the name of a migration until which (inclusive) the migrations should be reverted. This allows the reverting of multiple migrations at once.\n\n```js\nconst migrations = await umzug.down({to: '20141031080000-task'})\n// returns an array of all reverted migrations.\n```\n\nTo revert all migrations, you can pass 0 as the `to` parameter:\n\n```js\nawait umzug.down({to: 0})\n```\n\nReverting specific migrations while ignoring the right order, can be done like this:\n\n```js\nawait umzug.down({migrations: ['20141101203500-task', '20141101203501-task-2']})\n```\n\n### Migrations\n\nThere are two ways to specify migrations: via files or directly via an array of migrations.\n\n#### Migration files\n\nA migration file ideally exposes an `up` and a `down` async functions. They will perform the task of upgrading or downgrading the database.\n\n```js\nmodule.exports = {\n  async up() {\n    /* ... */\n  },\n  async down() {\n    /* ... */\n  },\n}\n```\n\nMigration files can be located anywhere - they will typically be loaded according to a glob pattern provided to the `Umzug` constructor.\n\n#### Direct migrations list\n\nYou can also specify directly a list of migrations to the `Umzug` constructor:\n\n```js\nconst {Umzug} = require('umzug')\n\nconst umzug = new Umzug({\n  migrations: [\n    {\n      // the name of the migration is mandatory\n      name: '00-first-migration',\n      async up({context}) {\n        /* ... */\n      },\n      async down({context}) {\n        /* ... */\n      },\n    },\n    {\n      name: '01-foo-bar-migration',\n      async up({context}) {\n        /* ... */\n      },\n      async down({context}) {\n        /* ... */\n      },\n    },\n  ],\n  context: sequelize.getQueryInterface(),\n  logger: console,\n})\n```\n\n#### Modifying the parameters passed to your migration methods\n\nSometimes it's necessary to modify the parameters `umzug` will pass to your migration methods when the library calls the `up` and `down` methods for each migration. This is the case when using migrations currently generated using `sequelize-cli`. In this case you can use the `resolve` fuction during migration configuration to determine which parameters will be passed to the relevant method\n\n```js\nimport {Sequelize} from 'sequelize'\nimport {Umzug, SequelizeStorage} from 'umzug'\n\nconst sequelize = new Sequelize(/* ... */)\n\nconst umzug = new Umzug({\n  migrations: {\n    glob: 'migrations/*.js',\n    resolve: ({name, path, context}) =\u003e {\n      const migration = require(path)\n      return {\n        // adjust the parameters Umzug will\n        // pass to migration methods when called\n        name,\n        up: async () =\u003e migration.up(context, Sequelize),\n        down: async () =\u003e migration.down(context, Sequelize),\n      }\n    },\n  },\n  context: sequelize.getQueryInterface(),\n  storage: new SequelizeStorage({sequelize}),\n  logger: console,\n})\n```\n\n#### Additional migration configuration options\n\nTo load migrations in another format, you can use the `resolve` function:\n\n```js\nconst fs = require('fs')\nconst {Sequelize} = require('sequelize')\nconst {Umzug} = require('umzug')\n\nconst umzug = new Umzug({\n  migrations: {\n    glob: 'migrations/*.up.sql',\n    resolve: ({name, path, context: sequelize}) =\u003e ({\n      name,\n      up: async () =\u003e {\n        const sql = fs.readFileSync(path).toString()\n        return sequelize.query(sql)\n      },\n      down: async () =\u003e {\n        // Get the corresponding `.down.sql` file to undo this migration\n        const sql = fs\n          .readFileSync(path.replace('.up.sql', '.down.sql'))\n          .toString()\n        return sequelize.query(sql)\n      },\n    }),\n  },\n  context: new Sequelize(/* ... */),\n  logger: console,\n})\n```\n\nYou can support mixed migration file types, and use umzug's default resolver for javascript/typescript:\n\n```js\nconst fs = require('fs')\nconst {Sequelize} = require('sequelize')\nconst {Umzug} = require('umzug')\n\nconst umzug = new Umzug({\n  migrations: {\n    glob: 'migrations/*.{js,ts,up.sql}',\n    resolve: params =\u003e {\n      if (!params.path.endsWith('.sql')) {\n        return Umzug.defaultResolver(params)\n      }\n      const {context: sequelize} = params\n      return {\n        name: params.name,\n        up: async () =\u003e {\n          const sql = fs.readFileSync(params.path).toString()\n          return sequelize.query(sql)\n        },\n        down: async () =\u003e {\n          // Get the corresponding `.down.sql` file to undo this migration\n          const sql = fs\n            .readFileSync(params.path.replace('.up.sql', '.down.sql'))\n            .toString()\n          return sequelize.query(sql)\n        },\n      }\n    },\n  },\n  logger: console,\n  context: new Sequelize(/* ... */),\n})\n```\n\nThe glob syntax allows loading migrations from multiple locations:\n\n```js\nconst {Sequelize} = require('sequelize')\nconst {Umzug} = require('umzug')\n\nconst umzug = new Umzug({\n  migrations: {\n    glob: '{first-folder/*.js,second-folder-with-different-naming-convention/*.js}',\n  },\n  context: new Sequelize(/* ... */),\n  logger: console,\n})\n```\n\nNote on migration file sorting:\n\n- file matches, found using [fast-glob](https://npmjs.com/package/fast-glob), will be lexicographically sorted based on their paths\n  - so if your migrations are `one/m1.js`, `two/m2.js`, `three/m3.js`, the resultant order will be `one/m1.js`, `three/m3.js`, `two/m2.js`\n  - similarly, if your migrations are called `m1.js`, `m2.js`, ... `m10.js`, `m11.js`, the resultant ordering will be `m1.js`, `m10.js`, `m11.js`, ... `m2.js`\n- The easiest way to deal with this is to ensure your migrations appear in a single folder, and their paths match lexicographically with the order they should run in\n- If this isn't possible, the ordering can be customised using a new instance (previously, in the beta release for v3, this could be done with `.extend(...)` - see below for example using a new instance)\n\n### Upgrading from v2.x\n\nThe Umzug class should be imported as a named import, i.e. `import { Umzug } from 'umzug'`.\n\nThe `MigrationMeta` type, which is returned by `umzug.executed()` and `umzug.pending()`, no longer has a `file` property - it has a `name` and *optional* `path` - since migrations are not necessarily bound to files on the file system.\n\nThe `migrations.glob` parameter replaces `path`, `pattern` and `traverseDirectories`. It can be used, in combination with `cwd` and `ignore` to do much more flexible file lookups. See https://npmjs.com/package/fast-glob for more information on the syntax.\n\nThe `migrations.resolve` parameter replaces `customResolver`. Explicit support for `wrap` and `nameFormatter` has been removed - these can be easily implemented in a `resolve` function.\n\nThe constructor option `logging` is replaced by `logger` to allow for `warn` and `error` messages in future. NodeJS's global `console` object can be passed to this. To disable logging, replace `logging: false` with `logger: undefined`.\n\nEvents have moved from the default nodejs `EventEmitter` to [emittery](https://www.npmjs.com/package/emittery). It has better design for async code, a less bloated API surface and strong types. But, it doesn't allow passing multiple arguments to callbacks, so listeners have to change slightly, as well as `.addListener(...)` and `.removeListener(...)` no longer being supported (`.on(...)` and `.off(...)` should now be used):\n\nBefore:\n\n```js\numzug.on('migrating', (name, m) =\u003e console.log({name, path: m.path}))\n```\n\nAfter:\n\n```js\numzug.on('migrating', ev =\u003e console.log({name: ev.name, path: ev.path}))\n```\n\nThe `Umzug#execute` method is removed. Use `Umzug#up` or `Umzug#down`.\n\nThe options for `Umguz#up` and `Umzug#down` have changed:\n- `umzug.up({ to: 'some-name' })` and `umzug.down({ to: 'some-name' })` are still valid.\n- `umzug.up({ from: '...' })` and `umzug.down({ from: '...' })` are no longer supported. To run migrations out-of-order (which is not generally recommended), you can explicitly use `umzug.up({ migrations: ['...'] })` and `umzug.down({ migrations: ['...'] })`.\n- name matches must be exact. `umzug.up({ to: 'some-n' })` will no longer match a migration called `some-name`.\n- `umzug.down({ to: 0 })` is still valid but `umzug.up({ to: 0 })` is not.\n- `umzug.up({ migrations: ['m1', 'm2'] })` is still valid but the shorthand `umzug.up(['m1', 'm2'])` has been removed.\n- `umzug.down({ migrations: ['m1', 'm2'] })` is still valid but the shorthand `umzug.down(['m1', 'm2'])` has been removed.\n- `umzug.up({ migrations: ['m1', 'already-run'] })` will throw an error, if `already-run` is not found in the list of pending migrations.\n- `umzug.down({ migrations: ['m1', 'has-not-been-run'] })` will throw an error, if `has-not-been-run` is not found in the list of executed migrations.\n- `umzug.up({ migrations: ['m1', 'm2'], rerun: 'ALLOW' })` will re-apply migrations `m1` and `m2` even if they've already been run.\n- `umzug.up({ migrations: ['m1', 'm2'], rerun: 'SKIP' })` will skip migrations `m1` and `m2` if they've already been run.\n- `umzug.down({ migrations: ['m1', 'm2'], rerun: 'ALLOW' })` will \"revert\" migrations `m1` and `m2` even if they've never been run.\n- `umzug.down({ migrations: ['m1', 'm2'], rerun: 'SKIP' })` will skip reverting migrations `m1` and `m2` if they haven't been run or are already reverted.\n- `umzug.up({ migrations: ['m1', 'does-not-exist', 'm2'] })` will throw an error if the migration name is not found. Note that the error will be thrown and no migrations run unless _all_ migration names are found - whether or not `rerun: 'ALLOW'` is added.\n\nThe `context` parameter replaces `params`, and is passed in as a property to migration functions as an options object, alongs side `name` and `path`. This means the signature for migrations, which in v2 was `(context) =\u003e Promise\u003cvoid\u003e`, has changed slightly in v3, to `({ name, path, context }) =\u003e Promise\u003cvoid\u003e`.\n\n#### Handling existing v2-format migrations\n\nThe `resolve` function can also be used to upgrade your umzug version to v3 when you have existing v2-compatible migrations:\n\n```js\nconst {Umzug} = require('umzug')\n\nconst umzug = new Umzug({\n  migrations: {\n    glob: 'migrations/umzug-v2-format/*.js',\n    resolve: ({name, path, context}) =\u003e {\n      // Adjust the migration from the new signature to the v2 signature, making easier to upgrade to v3\n      const migration = require(path)\n      return {\n        name,\n        up: async () =\u003e migration.up(context),\n        down: async () =\u003e migration.down(context),\n      }\n    },\n  },\n  context: sequelize.getQueryInterface(),\n  logger: console,\n})\n```\n\nSimilarly, you no longer need `migrationSorting`, you can instantiate a new `Umzug` instance to manipulate migration lists directly:\n\n```js\nconst {Umzug} = require('umzug')\n\nconst parent = new Umzug({\n  migrations: {glob: 'migrations/**/*.js'},\n  context: sequelize.getQueryInterface(),\n})\n\nconst umzug = new Umzug({\n  ...parent.options,\n  migrations: async ctx =\u003e\n    (await parent.migrations()).sort((a, b) =\u003e b.path.localeCompare(a.path)),\n})\n```\n\n### Storages\n\nStorages define where the migration data is stored.\n\n#### JSON Storage\n\nUsing `JSONStorage` will create a JSON file which will contain an array with all the executed migrations. You can specify the path to the file. The default for that is `umzug.json` in the working directory of the process.\n\nDetailed documentation for the options it can take are in the `JSONStorageConstructorOptions` TypeScript interface, which can be found in [src/storage/json.ts](./src/storage/json.ts).\n\n#### Memory Storage\n\nUsing `memoryStorage` will store migrations with an in-memory array. This can be useful for proof-of-concepts or tests, since it doesn't interact with databases or filesystems.\n\nIt doesn't take any options, just import the `memoryStorage` function and call it to return a storage instance:\n\n```typescript\nimport { Umzug, memoryStorage } from 'umzug'\n\nconst umzug = new Umzug({\n  migrations: ...,\n  storage: memoryStorage(),\n  logger: console,\n})\n```\n\n#### Sequelize Storage\n\nUsing `SequelizeStorage` will create a table in your SQL database called `SequelizeMeta` containing an entry for each executed migration. You will have to pass a configured instance of Sequelize or an existing Sequelize model. Optionally you can specify the model name, table name, or column name. All major Sequelize versions are supported.\n\nDetailed documentation for the options it can take are in the `_SequelizeStorageConstructorOptions` TypeScript interface, which can be found in [src/storage/sequelize.ts](./src/storage/sequelize.ts).\n\nThis library has been tested with sequelize v6. It may or may not work with lower versions - use at your own risk.\n\n#### MongoDB Storage\n\nUsing `MongoDBStorage` will create a collection in your MongoDB database called `migrations` containing an entry for each executed migration. You will have either to pass a MongoDB Driver Collection as `collection` property. Alternatively you can pass a established MongoDB Driver connection and a collection name.\n\nDetailed documentation for the options it can take are in the `MongoDBStorageConstructorOptions` TypeScript interface, which can be found in [src/storage/mongodb.ts](./src/storage/mongodb.ts).\n\n#### Custom\n\nIn order to use a custom storage, you can pass your storage instance to Umzug constructor.\n\n```js\nclass CustomStorage {\n  constructor() {}\n  logMigration() {}\n  unlogMigration() {}\n  executed() {}\n}\n\nconst umzug = new Umzug({\n  storage: new CustomStorage(/* ... */),\n  logger: console,\n})\n```\n\nYour instance must adhere to the [UmzugStorage](./src/storage/contract.ts) interface. If you're using TypeScript you can ensure this at compile time, and get IDE type hints by importing it:\n\n```typescript\nimport { UmzugStorage } from 'umzug'\n\nclass CustomStorage implements UmzugStorage {\n  /* ... */\n}\n```\n\n### Events\n\nUmzug is an [emittery event emitter](https://www.npmjs.com/package/emittery). Each of the following events will be called with migration parameters as its payload (with `context`, `name`, and nullable `path` properties). Events are a convenient place to implement application-specific logic that must run around each migration:\n\n* `migrating` - A migration is about to be executed.\n* `migrated` - A migration has successfully been executed.\n* `reverting` - A migration is about to be reverted.\n* `reverted` - A migration has successfully been reverted.\n\nThese events run at the beginning and end of `up` and `down` calls. They'll receive an object containing a `context` property:\n\n- `beforeCommand` - Before any command (`'up' | 'down' | 'executed' | 'pending'`) is run.\n- `afterCommand` - After any command (`'up' | 'down' | 'executed' | 'pending'`) is run. Note: this will always run, even if the command throws an error.\n\nThe [`FileLocker` class](./src/file-locker.ts) uses `beforeAll` and `afterAll` to implement a simple filesystem-based locking mechanism.\n\nAll events are type-safe, so IDEs will prevent typos and supply strong types for the event payloads.\n\n### Errors\n\nWhen a migration throws an error, it will be wrapped in a `MigrationError` which captures the migration metadata (name, path etc.) as well as the original error message, and _will be rethrown_. In most cases, this is expected behaviour, and doesn't require any special handling beyond standard error logging setups.\n\nIf you expect failures and want to try to recover from them, you will need to try-catch the call to `umzug.up()`. You can access the original error from the `.cause` property if necessary:\n\n```js\ntry {\n  await umzug.up()\n} catch (e) {\n  if (e instanceof MigrationError) {\n    const original = e.cause\n    // do something with the original error here\n  }\n  throw e\n}\n```\n\nUnder the hood, [verror](https://npmjs.com/package/verror) is used to wrap errors.\n\n### CLI\n\n🚧🚧🚧 The CLI is new to Umzug v3. Feedback on it is welcome in [discussions](https://github.com/sequelize/umzug/discussions) 🚧🚧🚧\n\nUmzug instances provide a `.runAsCLI()` method. When called, this method will automatically cause your program to become a complete CLI, with help text and such:\n\n```js\n// migrator.js\nconst {Umzug} = require('umzug')\n\nconst umzug = new Umzug({\n  /* ... */\n})\n\nexports.umzug = umzug\n\nif (require.main === module) {\n  umzug.runAsCLI()\n}\n```\n\nNote that this uses the [@rushstack/ts-command-line](https://www.npmjs.com/package/@rushstack/ts-command-line) package, which shows only the top-level message of any errors throw by default. See [here](https://github.com/sequelize/umzug/issues/619#issuecomment-1793297576) for how you can see a full stack trace.\n\n#### CLI Usage\n\nA script like the one above is now a runnable CLI program. You can run `node migrator.js --help` to see how to use it. It will print something like:\n\n\u003c!-- codegen:start {preset: custom, source: ./codegen.js, export: cliHelp} --\u003e\n```\nusage: \u003cscript\u003e [-h] \u003ccommand\u003e ...\n\nUmzug migrator\n\nPositional arguments:\n  \u003ccommand\u003e\n    up        Applies pending migrations\n    down      Revert migrations\n    pending   Lists pending migrations\n    executed  Lists executed migrations\n    create    Create a migration file\n\nOptional arguments:\n  -h, --help  Show this help message and exit.\n\nFor detailed help about a specific command, use: \u003cscript\u003e \u003ccommand\u003e -h\n```\n\u003c!-- codegen:end --\u003e\n\n#### Running migrations\n\n`node migrator up` and `node migrator down` apply and revert migrations respectively. They're the equivalent of the `.up()` and `.down()` methods.\n\nUse `node migrator up --help` and `node migrator down --help` for options (running \"to\" a specific migration, passing migration names to be run explicitly, and specifying the rerun behavior):\n\nUp:\n\u003c!-- codegen:start {preset: custom, source: ./codegen.js, export: cliHelp, action: up} --\u003e\n```\nusage: \u003cscript\u003e up [-h] [--to NAME] [--step COUNT] [--name MIGRATION]\n                   [--rerun {THROW,SKIP,ALLOW}]\n                   \n\nPerforms all migrations. See --help for more options\n\nOptional arguments:\n  -h, --help            Show this help message and exit.\n  --to NAME             All migrations up to and including this one should be \n                        applied\n  --step COUNT          Apply this many migrations. If not specified, all \n                        will be applied.\n  --name MIGRATION      Explicity declare migration name(s) to be applied. \n                        Only these migrations will be applied.\n  --rerun {THROW,SKIP,ALLOW}\n                        Specify what action should be taken when a migration \n                        that has already been applied is passed to --name. \n                        The default value is \"THROW\".\n```\n\u003c!-- codegen:end --\u003e\n\nDown:\n\u003c!-- codegen:start {preset: custom, source: ./codegen.js, export: cliHelp, action: down} --\u003e\n```\nusage: \u003cscript\u003e down [-h] [--to NAME] [--step COUNT] [--name MIGRATION]\n                     [--rerun {THROW,SKIP,ALLOW}]\n                     \n\nUndoes previously-applied migrations. By default, undoes the most recent \nmigration only. Use --help for more options. Useful in development to start \nfrom a clean slate. Use with care in production!\n\nOptional arguments:\n  -h, --help            Show this help message and exit.\n  --to NAME             All migrations up to and including this one should be \n                        reverted. Pass '0' to revert all.\n  --step COUNT          Revert this many migrations. If not specified, only \n                        the most recent migration will be reverted.\n  --name MIGRATION      Explicity declare migration name(s) to be reverted. \n                        Only these migrations will be reverted.\n  --rerun {THROW,SKIP,ALLOW}\n                        Specify what action should be taken when a migration \n                        that has already been applied is passed to --name. \n                        The default value is \"THROW\".\n```\n\u003c!-- codegen:end --\u003e\n\n\n#### Listing migrations\n\n```bash\nnode migrator pending # list migrations yet to be run\nnode migrator executed # list migrations that have already run\n\nnode migrator pending --json # list pending migrations including names and paths, in a json array format\nnode migrator executed --json # list executed migrations including names and paths, in a json array format\n\nnode migrator pending --help # show help/options\nnode migrator executed --help # show help/options\n```\n\n\u003c!-- codegen:start {preset: custom, source: ./codegen.js, export: cliHelp, action: pending} --\u003e\n```\nusage: \u003cscript\u003e pending [-h] [--json]\n\nPrints migrations returned by `umzug.pending()`. By default, prints migration \nnames one per line.\n\nOptional arguments:\n  -h, --help  Show this help message and exit.\n  --json      Print pending migrations in a json format including names and \n              paths. This allows piping output to tools like jq. Without this \n              flag, the migration names will be printed one per line.\n```\n\u003c!-- codegen:end --\u003e\n\n\u003c!-- codegen:start {preset: custom, source: ./codegen.js, export: cliHelp, action: executed} --\u003e\n```\nusage: \u003cscript\u003e executed [-h] [--json]\n\nPrints migrations returned by `umzug.executed()`. By default, prints \nmigration names one per line.\n\nOptional arguments:\n  -h, --help  Show this help message and exit.\n  --json      Print executed migrations in a json format including names and \n              paths. This allows piping output to tools like jq. Without this \n              flag, the migration names will be printed one per line.\n```\n\u003c!-- codegen:end --\u003e\n\n#### Creating migrations - CLI\n\nUsually, migrations correspond to files on the filesystem. The CLI exposes a way to create migration files easily:\n\n```bash\nnode migrator create --name my-migration.js\n```\n\nThis will create a file with a name like `2000.12.25T12.34.56.my-migration.js` in the same directory as the most recent migration file. If it's the very first migration file, you need to specify the folder explicitly:\n\n```bash\nnode migrator create --name my-migration.js --folder path/to/directory\n```\n\nThe timestamp prefix can be customized to be date-only or omitted, but be aware that it's strongly recommended to ensure your migrations are lexicographically sortable so it's easy for humans and tools to determine what order they should run in - so the default prefix is recommended.\n\nThis will generate a migration file called `\u003c\u003ctimestamp\u003e\u003e.my-migration.js` with the default migration template for `.js` files that ships with Umzug.\n\nUmzug also ships with default templates for [`.ts`, `.cjs`, `.mjs` and `.sql` files](./src/templates.ts). Umzug will choose the template based on the extension you provide in `name`.\n\nYou can specify a custom template for your project when constructing an umzug instance via the `template` option. It should be a function which receives a filepath string, and returns an array of `[filepath, content]` pairs. Usually, just one pair is needed, but a second could be used to include a \"down\" migration in a separate file:\n\n```js\nconst umzug = new Umzug({\n  migrations: {\n    /*...*/\n  },\n  create: {\n    template: filepath =\u003e [\n      [filepath, fs.readFileSync('path/to/your/template/file').toString()],\n    ],\n  },\n})\n```\n\nThe create command includes some safety checks to make sure migrations aren't created with ambiguous ordering, and that they will be picked up by umzug when applying migrations. The first pair is expected to be the \"up\" migration file, and to be picked up by the `pending` command.\n\nUse `node migrator create --help` for more options:\n\n\u003c!-- codegen:start {preset: custom, source: ./codegen.js, export: cliHelp, action: create} --\u003e\n```\nusage: \u003cscript\u003e create [-h] --name NAME [--prefix {TIMESTAMP,DATE,NONE}]\n                       [--folder PATH] [--allow-extension EXTENSION]\n                       [--skip-verify] [--allow-confusing-ordering]\n                       \n\nGenerates a placeholder migration file using a timestamp as a prefix. By \ndefault, mimics the last existing migration, or guesses where to generate the \nfile if no migration exists yet.\n\nOptional arguments:\n  -h, --help            Show this help message and exit.\n  --name NAME           The name of the migration file. e.g. my-migration.js, \n                        my-migration.ts or my-migration.sql. Note - a prefix \n                        will be added to this name, usually based on a \n                        timestamp. See --prefix\n  --prefix {TIMESTAMP,DATE,NONE}\n                        The prefix format for generated files. TIMESTAMP uses \n                        a second-resolution timestamp, DATE uses a \n                        day-resolution timestamp, and NONE removes the prefix \n                        completely. The default value is \"TIMESTAMP\".\n  --folder PATH         Path on the filesystem where the file should be \n                        created. The new migration will be created as a \n                        sibling of the last existing one if this is omitted.\n  --allow-extension EXTENSION\n                        Allowable extension for created files. By default .js,\n                         .ts and .sql files can be created. To create txt \n                        file migrations, for example, you could use '--name \n                        my-migration.txt --allow-extension .txt' This \n                        parameter may alternatively be specified via the \n                        UMZUG_ALLOW_EXTENSION environment variable.\n  --skip-verify         By default, the generated file will be checked after \n                        creation to make sure it is detected as a pending \n                        migration. This catches problems like creation in the \n                        wrong folder, or invalid naming conventions. This \n                        flag bypasses that verification step.\n  --allow-confusing-ordering\n                        By default, an error will be thrown if you try to \n                        create a migration that will run before a migration \n                        that already exists. This catches errors which can \n                        cause problems if you change file naming conventions. \n                        If you use a custom ordering system, you can disable \n                        this behavior, but it's strongly recommended that you \n                        don't! If you're unsure, just ignore this option.\n```\n\u003c!-- codegen:end --\u003e\n\n### Creating migrations - API\n\nUmzug includes an optional helper for generating migration files. It's often most convenient to create files using the [CLI helper](#creating-migrations---cli), but the equivalent API also exists on an umzug instance:\n\n```js\nawait umzug.create({name: 'my-new-migration.js'})\n```\n\n## License\n\nSee the [LICENSE file](./LICENSE)\n","funding_links":["https://opencollective.com/sequelize"],"categories":["TypeScript","\u003ca name=\"TypeScript\"\u003e\u003c/a\u003eTypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsequelize%2Fumzug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsequelize%2Fumzug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsequelize%2Fumzug/lists"}