{"id":15573268,"url":"https://github.com/okv/east","last_synced_at":"2025-05-15T23:04:33.924Z","repository":{"id":8026959,"uuid":"9436249","full_name":"okv/east","owner":"okv","description":"Node.js database migration tool","archived":false,"fork":false,"pushed_at":"2024-10-27T19:39:53.000Z","size":1532,"stargazers_count":82,"open_issues_count":4,"forks_count":13,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-05-09T21:06:40.337Z","etag":null,"topics":["couchbase","database","dynamodb","javascript","migration","mongodb","mysql","nodejs","postgres","sqlite","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/okv.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","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}},"created_at":"2013-04-14T22:17:57.000Z","updated_at":"2025-04-03T15:45:09.000Z","dependencies_parsed_at":"2024-06-18T15:21:05.259Z","dependency_job_id":"8d314b56-6a80-4d20-b782-305cd4751332","html_url":"https://github.com/okv/east","commit_stats":{"total_commits":655,"total_committers":14,"mean_commits":"46.785714285714285","dds":0.1923664122137405,"last_synced_commit":"484bfe1188fe382f8f328c11c01e3053469e6941"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okv%2Feast","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okv%2Feast/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okv%2Feast/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okv%2Feast/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/okv","download_url":"https://codeload.github.com/okv/east/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254436944,"owners_count":22070946,"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":["couchbase","database","dynamodb","javascript","migration","mongodb","mysql","nodejs","postgres","sqlite","typescript"],"created_at":"2024-10-02T18:11:37.067Z","updated_at":"2025-05-15T23:04:33.895Z","avatar_url":"https://github.com/okv.png","language":"JavaScript","readme":"# east\n\neast - node.js database migration tool for different databases (extensible via\n[adapters](#adapters)) with [transpiled languages support (e.g. TypeScript)](#typescript-and-other-transpiled-languages-support).\n\neast connects to the db using particular adapter (mongodb, sqlite, postgres,\nmysql, couchbase, couchdb), keeps track of executed migrations by storing their names\ninside db and makes connect to the db available inside `migrate` and `rollback`\nfunctions. east encourages you to use for migrations driver/syntax with which\nyou are already familiar with (apparently you use it for work with db at your\napplication) and doesn't provide universal api for working with any kind of\ndatabase.\n\n[![Npm version](https://img.shields.io/npm/v/east.svg)](https://www.npmjs.org/package/east)\n[![Build Status](https://github.com/okv/east/actions/workflows/nodejs-main.yml/badge.svg?branch=master)](https://github.com/okv/east/actions/workflows/nodejs-main.yml?query=branch%3Amaster)\n[![Coverage Status](https://coveralls.io/repos/github/okv/east/badge.svg)](https://coveralls.io/github/okv/east)\n[![Known Vulnerabilities](https://snyk.io/test/npm/east/badge.svg)](https://snyk.io/test/npm/east)\n\n\nFollowing subjects described below:\n\n* [Node.js compatibility](#nodejs-compatibility)\n* [Installation](#installation)\n* [Changelog](#changelog)\n* [Cli usage](#cli-usage)\n* [Library usage](#library-usage)\n* [Adapters](#adapters)\n* [Plugins](#plugins)\n* [Creating own adapter](#creating-own-adapter)\n* [TypeScript and other transpiled languages support](#typescript-and-other-transpiled-languages-support)\n* [ECMAScript Modules support](#ecmascript-modules-support)\n* [License](#license)\n\n\n## Node.js compatibility\n\neast itself requires node.js \u003e= 10.17.0 to work.\n\nPlease note that particular adapter may have other requirements (see\ndocumentation for specific adapter).\n\n\n## Installation\n\n```sh\nnpm install east -g\n```\n\nalternatively you could install it locally\n\n\n## Changelog\n\nAll notable changes to this project documented in [CHANGELOG.md](CHANGELOG.md).\n\n\n## Cli usage\n\nAt your project dir run\n\n```sh\neast init\n```\n\nafter that you can `create`, `migrate`, `rollback` your migrations.\n\nRun `east -h` to see all commands:\n\n```sh\n\nUsage: east [options] [command]\n\nOptions:\n  -V, --version                       output the version number\n  --adapter \u003cname\u003e                    which db adapter to use\n  --config \u003cpath\u003e                     config file to use\n  --timeout \u003ctimeout\u003e                 timeout for migrate/rollback\n  --template \u003cpath\u003e                   path to template for new migrations\n  --dir \u003cdir\u003e                         dir where migration executable files are stored (default: \"./migrations\")\n  --source-dir \u003cdir\u003e                  dir where migration source files are stored, equal to --dir by default\n  --migration-extension \u003cext\u003e         migration executable files extension name (default: \"js\")\n  --source-migration-extension \u003cext\u003e  migration source files extension name, equal to --migration-extension by default\n  --url \u003curl\u003e                         db connect url\n  --trace                             verbose mode (includes error stack trace)\n  --silent                            prevent output of detailed log\n  --es-modules                        config, migrations, adapter and plugins could be provided as ES Modules with this flag\n  --no-exit                           require a clean shutdown of the event loop: process.exit will not be called at the end\n  -h, --help                          display help for command\n\nCommands:\n  init                                initialize migration system\n  create \u003cbasename\u003e                   create new migration based on template\n  migrate [options] [migrations...]   run all or selected migrations\n  rollback [options] [migrations...]  rollback all or selected migrations\n  list [options] [status]             list migration with selected status (\"new\", \"executed\" or \"all\"), \"new\" by default\n  *\n  help [command]                      display help for command\n\n```\n\nrun `east \u003ccommand\u003e -h` to see detailed command help.\n\nAll options described above can be set via command line or at `.eastrc` file\nlocated at current directory, e.g.:\n\n```js\n\n{\n\t\"dir\": \"./dbmigration\",\n\t\"template\": \"./lib/node/utils/customMigrationTemplate.js\"\n}\n\n```\n\n`.eastrc` also can be a regular commonjs module (instead of json file):\n\n```js\n\nvar path = require('path');\n\nmodule.exports = {\n    dir: path.join(__dirname, 'dbmigration'),\n    template: './lib/node/utils/customMigrationTemplate.js'\n};\n\n```\n\neast also supports config as ECMAScript module, config could be:\n\n```js\nimport path from 'path';\n\nexport const dir = path.resolve('dbmigration');\nexport const template = path.resolve('./lib/node/utils/customMigrationTemplate.js');\n````\n\nSee [ECMAScript Modules support](#ecmascript-modules-support) for details.\n\n\n### create\n\n```sh\neast create doSomething\n```\n\nproduces something like this\n\n```sh\nNew migration \"1_doSomething\" created at \"migrations/1_doSomething.js\"\n```\n\nthe created file will contain\n\n```js\nexports.tags = [];\n\nexports.migrate = async (client) =\u003e {\n\n};\n\nexports.rollback = async (client) =\u003e {\n\n};\n```\n\n* `client` represents a connection to the current db and it's determined by the\nadapter (see [adapters](#adapters) section)\n* `done` callback may be defined as second argument - should be called at the\nend of the migration (if any error occures you can pass it as the first argument)\n* `rollback` function is optional and may be omitted\n\nMigration file is a regular node.js module and allows migrating any database e.g.\n\n```js\n// include your database wrapper which you already use in app\nconst db = require('./db');\n\nexports.migrate = async (client) =\u003e {\n    await db.connect();\n    await db.things.insert({_id: 1, name: 'apple', color: 'red'});\n};\n\nexports.rollback = async (client) =\u003e {\n    await db.connect();\n    await db.things.remove({_id: 1});\n};\n```\n\nor you can use a special adapter for database (see [adapters](#adapters) section).\n\n\n#### Migration file number format\n\nThe default format for migration file names is to prepend a number to the\nfilename which is incremented with every new file. This creates migration files\nsuch as \"migrations/1_doSomething.js\", \"migrations/2_doSomethingElse.js\".\n\nIf you prefer your files to be created with a date-time instead of sequential\nnumbers, you can set the `migrationNumberFormat` configuration parameter in\nyour `.eastrc` to \"dateTime\":\n\n```json\n{\n    \"migrationNumberFormat\": \"dateTime\"\n}\n```\n\nThis will create migration files with date-time prefix in `YYYYMMDDhhmmss`\nformat (e.g. \"migrations/20190720172730_doSomething.js\").\n\nFor the default behavior, you can omit the `migrationNumberFormat`\nconfiguration option or set it to:\n\n```json\n{\n    \"migrationNumberFormat\": \"sequentialNumber\"\n}\n```\n\n\n### migrate\n\nlet's create one more migration\n\n```sh\neast create doSomethingElse\n```\n\nthen executes both of them\n\n```sh\neast migrate\n```\n\nit sequentially executes all new migrations and produces\n\n```sh\ntarget migrations:\n    1_doSomething\n    2_doSomethingElse\nmigrate \"1_doSomething\"\nmigration done\nmigrate \"2_doSomethingElse\"\nmigration done\n```\n\nselected migrations can be executed by passing their names (or numbers or\nbasenames or paths) as an argument\n\n```sh\neast migrate 1_doSomething 2\n```\n\nin our case this command will skip all of them\n\n```sh\nskip \"1_doSomething\" because it's already executed\nskip \"2_doSomethingElse\" because it's already executed\nnothing to migrate\n```\n\nyou can pass `--force` option to execute already executed migrations.\nThis is useful while you develop and test your migration.\n\nYou also can export `tags` array from migration and then run only\nmigrations that satisfy the expression specified by `--tag` option. The expression\nconsists of tag names and boolean operators `\u0026`, `|` and `!`. For example,\nthe following command will run all migrations that have \"tag1\" tag and do not have \"tag2\" tag:\n\n```sh\neast migrate --tag 'tag1 \u0026 !tag2'\n```\n\n\n### rollback\n\n`rollback` has similar to `migrate` command syntax but executes `rollback`\nfunction from the migration file\n\n```sh\neast rollback\n```\n\nwill produce\n\n```sh\ntarget migrations:\n    2_doSomethingElse\n    1_doSomething\nrollback \"2_doSomethingElse\"\nmigration successfully rolled back\nrollback \"1_doSomething\"\nmigration successfully rolled back\n```\n\n\n### list\n\n```sh\neast list\n```\n\nshows new migrations e.g.\n\n```sh\nnew migrations:\n     1_doSomething\n     2_doSomethingElse\n```\n\ntarget status could be specified as an argument e.g.\n\n```sh\neast list executed\n```\n\n\n## Library usage\n\neast exposes `MigrationManager` class (descendant of `EventEmitter`) which for\nexample can be used to migrate your database from node.js app without using\neast cli:\n\n```js\nconst {MigrationManager} = require('east');\n\nconst main = async () =\u003e {\n    const migrationManager = new MigrationManager();\n\n    // log target migrations before execution\n    migrationManager.once('beforeMigrateMany', (migrationNames) =\u003e {\n        console.log('Target migrations: ', migrationNames);\n    });\n\n    await migrationManager.configure();\n\n    try {\n        await migrationManager.connect();\n        // select for migration all not executed migrations\n        await migrationManager.migrate({status: 'new'});\n    }\n    finally {\n        await migrationManager.disconnect();\n    }\n}\n\nmain().catch((err) =\u003e {\n    console.error('Some error occurred: ', err.stack || err);\n});\n````\n\n`MigrationManager` methods:\n\n* **configure(params)** - configures migration process, accepts object with\nparameters (`dir`, `adapter`, etc) and merges it with loaded config (when\n`loadConfig` param is truthy - true by default). Returns *Promise\u003cvoid\u003e*. **This\nmethod should be called before any other methods.**\n\n* **getParams()** - returns *Promise* with parameters used by migration\nprocess after configuration(`configure` method).\n\n* **init()** - initiates migration process for a project. Should be called once\nper project. Returns *Promise\u003cvoid\u003e*.\n\n* **isInitialized()** - checks whether `init` was made or not.\nReturns *Promise\u003cBoolean\u003e*.\n\n* **create(basename)** - creates migration, returns *Promise* with migration\nobject.\n\n* **getMigrationPath(name, migrationFileType)** - returns an absolute path of the migration\nfile on disk by the name of the migration, `migrationFileType` can be one of\n\"executable\" or \"source\" (\"executable\" by default). Returns *Promise\u003cString\u003e*.\n\n* **connect()** - connects to database management system (if supposed by\nadapter). Returns *Promise\u003cvoid\u003e*.\n\n* **getMigrationNames({migrations, status, tag, reverseOrderResult})** -\nreturns migrations names, following options are provided:\n\n  * **migrations** - array of target migrations, each migration could be\n  defined by basename, full name, path or number.\n  * **status** - status to filter migrations, supported statuses are:\n  \"new\", \"executed\" and \"all\".\n  * **tag** - tag expression to filter migrations e.g. \"tag1 \u0026 !tag2\"\n  * **reverseOrderResult** - if true then result array will be reversed.\n\n`migrations` and `status` are mutually exclusive.\nIf `migrations`, `status` not provided then all migrations will be processed\n(e.g. filtered by tag and returned).\n\n* **migrate({migrations, status, tag, force})** - executes target migrations.\nTarget migration could be defined by `migrations`, `status`, `tag` options\n(see it's description at `getMigrationNames` method). *By default*\nmigrations with status \"new\" are chosen. Returns *Promise\u003cvoid\u003e*. `force`\nflag allows to execute already executed migrations.\n\n* **rollback({migrations, status, tag, force})** - rollbacks target migrations.\nTarget migration could be defined by `migrations`, `status`, `tag` options\n(see it's description at `getMigrationNames` method). *By default*\nmigrations with status \"executed\" are chosen. Returns *Promise\u003cvoid\u003e*. `force`\nflag allows to rollback not executed migrations.\n\n* **disconnect()** - disconnects from database management system (if supposed\nby adapter). Returns *Promise\u003cvoid\u003e*.\n\n\n`MigrationManager` events:\n\n* **beforeMigrateOne({migration})**\n* **afterMigrateOne({migration})**\n* **beforeMigrateMany({migrationNames})**\n* **afterMigrateMany({migrationNames})**\n* **beforeRollbackOne({migration})**\n* **afterRollbackOne({migration})**\n* **beforeRollbackMany({migrationNames})**\n* **afterRollbackMany({migrationNames})**\n* **onSkipMigration({migration, reason})**\n\n\n## Adapters\n\nadapter determines where executed migration names will be stored and what will be\npassed to `migrate` and `rollback` function as `client`.\nDefault adapter stores executed migration names at file `.migrations` which is\nlocated at migrations executables directory and passes `null` as `client`.\n\nOther adapters:\n* [mongodb](https://github.com/okv/east-mongo)\n* [sqlite](https://github.com/2do2go/east-sqlite)\n* [postgres](https://github.com/2do2go/east-postgres)\n* [mysql](https://github.com/riggerthegeek/east-mysql)\n* [couchbase](https://github.com/ramiel/east-couchbase)\n* [couchdb](https://github.com/schipiga/east-couchdb)\n* [dynamodb](https://github.com/cstar-industries/east-dynamodb)\n\n\n## Plugins\n\nEast functionality could be extended by using plugins, for usage instructions\nsee plugin page:\n\n* [migration duration logger](https://github.com/okv/east-migration-duration-logger)\n* [migration progress indicator helper](https://github.com/okv/east-migration-progress-indicator-helper)\n\n\n## Creating own adapter\n\nFor writing your own adapter you should implement methods for connection,\nmark transaction as executed, etc see details inside\n[built-in adapter](lib/adapter.js) and [other adapters](#adapters).\nSee [TypeScript support](#typescript-and-other-transpiled-languages-support) for the details on the required\nadapter interface.\n\nYou also can run migrator tests from current repository against your adapter:\n\n* Clone current repository\n* Change current directory to it\n* Create file `.eastrc` with path and parameters for\nyour adapter e.g.\n\n```js\n{\n    \"adapter\": \"../../east-mysql/lib/adapter\",\n    \"url\": \"mysql://user:password@localhost/east_test_db\",\n    \"createDbOnConnect\": true\n}\n```\n\n* Run `NODE_EAST_TEST_LOAD_CONFIG=1 npm run testSpecified test/01-migrator -- --jobs=1` at\nroot of the cloned repository.\n\n\n## TypeScript and other transpiled languages support\n\n`east` allows you to opt-in writing and executing your migrations with any transpiled languages,\nwhile by default it uses a single dir called \"migrations\" and looks for \".js\" files in it.\n\nYou can configure separate executable and source files directories as well as\nseparate executable and source files extensions with `--dir`, `--source-dir`,\n`--migration-extension`, `--source-migration-extension` respectively.\n\nBy default if you specify only `--dir` and/or `--migration-extension`, then\n`--source-dir` and/or `--source-migration-extension` will be equal to it, however\nit doesn't work on the other way around, e.g. if you specify\n\n```\n--source-dir mySourceDir --source-migration-extension ts\n```\n\nthen `--dir` and `--migration-extension` will have `migrations` and `js` values by default,\nso it is recommended to specify at least `--dir`, `--source-dir` and `--source-migration-extension`\nwhen you are building a transpiled language.\n\nIf you use TypeScript you can run `east` with [`ts-node`](https://github.com/TypeStrong/ts-node)\nif you don't want to transpile you migration scripts before running them:\n\n```sh\nts-node $(which east) migrate\n```\n\nJust be sure to specify `--migration-extension ts` so that `east` does look for\nTypeScript files when `require()`-ing the migration scripts.\n\n\n### TypeScript typings\n\n`east` exposes TypeScript declarations of the `Adapter`, `MigrationManager`\nand other related interfaces.\n\nYou can access it by importing the interfaces from `east` module itself:\n\n```ts\nimport { DbClient } from 'some-mainstream-db';\nimport type { Adapter, AdapterConstructor } from 'east';\n\nclass MyAdapter implements Adapter\u003cDbClient\u003e {\n\t// go to definition of Adapter interface for documentation on required methods\n\t// you can also leverage your ide features to generate\n\t// stub method impementations here\n}\n\n// type-check the class static type (i.e. its constructor)\nconst _: AdpaterConstructor\u003cDbClient\u003e = MyAdapter;\n\nexport = MyAdapter;\n```\n\n\n## ECMAScript Modules support\n\neast provides support for es modules by `--es-modules` cli flag.\nWith this flag config, migrations, adapter and plugins will be loaded using\n[import expression](https://nodejs.org/dist/latest-v12.x/docs/api/esm.html#esm_import_expressions).\nIt allows to provide those entities like commonjs or es modules, e.g.\n`.eastrc.mjs`:\n\n```js\nimport path from 'path';\nexport const dir = path.resolve('dbmigration');\nexport const template = path.resolve('./lib/node/utils/customMigrationTemplate.js');\n````\n\nPlease note, that you need to enable nodejs es modules support (use `mjs`\nextension for module or package.json with type \"module\", etc - see\n[nodejs esm docs](https://nodejs.org/dist/latest-v12.x/docs/api/esm.html) for\ndetails).\n\nConfig presented above could be used like this:\n\n```sh\neast --config .eastrc.mjs --es-modules list\n```\n\nWhen migration files as es module are desired `--migration-extension` and\n`--source-migration-extension` set to \"mjs\" could be used.\n\n\n\n## License\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokv%2Feast","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fokv%2Feast","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokv%2Feast/lists"}