{"id":15663329,"url":"https://github.com/nflaig/loopback4-migration","last_synced_at":"2025-04-14T00:42:59.076Z","repository":{"id":38418635,"uuid":"275350805","full_name":"nflaig/loopback4-migration","owner":"nflaig","description":"LoopBack 4 Migration Component","archived":false,"fork":false,"pushed_at":"2025-02-18T00:37:21.000Z","size":1475,"stargazers_count":17,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-10T17:13:40.051Z","etag":null,"topics":["database-migrations","downgrade","loopback-4","loopback-extension","migration","upgrade"],"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/nflaig.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"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}},"created_at":"2020-06-27T10:40:54.000Z","updated_at":"2024-06-24T15:38:44.000Z","dependencies_parsed_at":"2024-06-24T17:21:47.142Z","dependency_job_id":"eb7c6f38-302b-4c30-b238-c37f6d41097c","html_url":"https://github.com/nflaig/loopback4-migration","commit_stats":{"total_commits":74,"total_committers":2,"mean_commits":37.0,"dds":0.08108108108108103,"last_synced_commit":"03f330c8d7512408eb54cbbbb535b960581cc1de"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nflaig%2Floopback4-migration","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nflaig%2Floopback4-migration/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nflaig%2Floopback4-migration/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nflaig%2Floopback4-migration/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nflaig","download_url":"https://codeload.github.com/nflaig/loopback4-migration/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248804721,"owners_count":21164127,"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":["database-migrations","downgrade","loopback-4","loopback-extension","migration","upgrade"],"created_at":"2024-10-03T13:36:41.104Z","updated_at":"2025-04-14T00:42:59.047Z","avatar_url":"https://github.com/nflaig.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- omit in toc --\u003e\n# loopback4-migration\n\n[![Actions Status][build-badge]][actions]\n[![Coverage Status][coveralls-badge]][coveralls]\n\n[![Latest version][npm-version-badge]][npm-package]\n[![License][license-badge]][license]\n[![Downloads][npm-downloads-badge]][npm-package]\n[![Total Downloads][npm-total-downloads-badge]][npm-package]\n\nMigration component that can be used by all applications build with LoopBack 4 to manage migration tasks\nsuch as database updates.\n\nIt provides a common interface to implement custom migration scripts and automatically handles\nthe versioning of the database and the execution of the scripts based on the application version\ncompared to the database version.\n\n\u003c!-- omit in toc --\u003e\n## Contents\n\n- [Prerequisites](#prerequisites)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Example](#example)\n- [Configuration](#configuration)\n- [Debug](#debug)\n- [Related resources](#related-resources)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Prerequisites\n\nSome dependencies need to be installed as peer dependencies\n\n```sh\n@loopback/boot\n@loopback/context\n@loopback/core\n@loopback/repository\n```\n\nand the application needs to have the `RepositoryMixin` applied and to automatically discover the\napplication version and the migration scripts the `BootMixin` is required although there is the option\nof [manual configuration](#configuration).\n\n ```ts\n class MyApplication extends BootMixin(RepositoryMixin(Application)) {}\n ```\n\n## Installation\n\n```sh\nnpm install loopback4-migration\n```\n\n\u003c!-- omit in toc --\u003e\n### Bind the component in `application.ts`\n\nThis will add the required model, repository and further artifacts to the application. By default,\nthe module will use the existing data source of the application to create and keep track of the\napplied migrations. It will also automatically discover the version of the application based on the\n`package.json` file. The data source and the version of application can also be manually configured,\nsee [Configuration](#update-default-values).\n\n```ts\nimport { MigrationComponent } from \"loopback4-migration\";\n\nexport class MyApplication extends BootMixin(\n    ServiceMixin(RepositoryMixin(RestApplication))\n) {\n    constructor(options?: ApplicationConfig) {\n        super(options);\n\n        // ...\n\n        // Bind migration component related elements\n        this.component(MigrationComponent);\n\n        // ...\n    }\n}\n```\n\n## Usage\n\nThe custom migration scripts need to implement the `MigrationScript` interface. The `version` and the\n`up()` method to handle database upgrades always need to be specified. Optionally, a `scriptName` and\na `description` can be set. In addition, if required and technically possible the `down()` method can\nbe implemented which will be used to handle downgrades of the database.\n\n**Note:** downgrading the database to an earlier version might not be possible in all cases and should\nbe considered as an edge case. Sometimes it is just impossible to revert the upgrade logic or in other\ncases it might not even be required because the upgrade changes are backwards compatible. In any case,\nit is recommended to create a database backup before updating the database.\n\nMigration scripts added to `src/migrations` with the file naming convention `\u003cscriptName\u003e.migration.ts`\nare automatically discovered and registered when the application is booted.\nIt is also possible to [manually add migration scripts](#update-default-values) from different locations\nor change the default directory and naming convention, see [Configuration](#update-directory-and-naming-convention).\n\nAnother option is to use the `@migrationScript` decorator to add the binding tag to the migration script class and\nbind it to the application.\nThe decorator also allows to [configure the scope][lb4-binding-scope]\nand add additional [tags][lb4-binding-tags].\n\n**Note:** Each migration script needs to have a unique class name else it will be discarded as a duplicate.\n\n```ts\nexport interface MigrationScript {\n    version: string;\n    scriptName?: string;\n    description?: string;\n\n    up(): ValueOrPromise\u003cany\u003e;\n\n    down?(): ValueOrPromise\u003cany\u003e;\n}\n```\n\n## Example\n\nThis is an example of a migration script which adds the `fullName` property to all existing users\nwithout the property.\n\nIt utilizes [Dependency Injection][lb4-dependency-injection] to retrieve the required dependencies\nsuch as [repositories][lb4-repositories].\n\n**Note:** The `@migrationScript` decorator would not be required here since the script follows\nthe naming convention and would be automatically discovered. This is just to show how the decorator\nwould be used.\n\n\u003e src/migrations/1.0.1.migration.ts\n\n```ts\nimport { repository } from \"@loopback/repository\";\nimport { MigrationScript, migrationScript } from \"loopback4-migration\";\nimport { UserRepository } from \"../repositories\";\n\n@migrationScript()\nexport class AddUserFullName implements MigrationScript {\n    version = \"1.0.1\";\n    scriptName = AddUserFullName.name;\n    description = \"add full name to users by combining first and last name\";\n\n    constructor(\n        @repository(UserRepository)\n        private userRepository: UserRepository\n    ) {}\n\n    async up(): Promise\u003cvoid\u003e {\n        // retrieve all users without fullName property\n        const users = await this.userRepository.find({\n            where: { fullName: { exists: false } }\n        });\n\n        // add fullName property to each user\n        const updateUsers = users.map(user =\u003e\n            this.userRepository.updateById(user.id, {\n                fullName: `${user.firstName} ${user.lastName}`\n            })\n        );\n\n        await Promise.all(updateUsers);\n    }\n\n    async down(): Promise\u003cvoid\u003e {\n        // remove fullName property from all users\n        await this.userRepository.updateAll(\u003cany\u003e{\n            $unset: { fullName: 0 }\n        });\n    }\n}\n```\n\n## Configuration\n\nThe component can be configured in `application.ts` to overwrite the default values.\n\n\u003c!-- omit in toc --\u003e\n### Update default values\n\n- `appVersion` - The application version retrieved from `package.json` can either be overwritten with\n  this property or by setting the `APPLICATION_VERSION` environment variable. Note that the module\n  currently only supports [Semantic Versioning][semantic-versioning].\n- `dataSourceName` - The name of the data source which should be used to track the applied migrations.\n  This is mostly relevant if the application uses more than one data source.\n- `modelName` - The name of the model which will be used as table or collection name to store the applied migrations.\n- `migrationScripts` - An array of migration script classes that implement the `MigrationScript` interface.\n  Setting the scripts manually is usually not required since they are automatically discovered and bound\n  to the application. Duplicate scripts will be removed and not bound to the application.\n\n```ts\nimport { MigrationBindings } from \"loopback4-migration\";\nimport { MongodbDataSource } from \"./datasources\";\nimport { MigrationScript101, MigrationScript102, MigrationScript103 } from \"./anyfolder\";\n\nexport class MyApplication extends BootMixin(\n    ServiceMixin(RepositoryMixin(RestApplication))\n) {\n    constructor(options?: ApplicationConfig) {\n        super(options);\n\n        // ...\n\n        // Configure migration component\n        this.bind(MigrationBindings.CONFIG).to({\n            appVersion: \"1.0.0\",\n            dataSourceName: MongodbDataSource.dataSourceName,\n            modelName: \"AnyName\",\n            migrationScripts: [MigrationScript101, MigrationScript102, MigrationScript103]\n        });\n\n        // ...\n    }\n}\n```\n\n\u003c!-- omit in toc --\u003e\n### Update directory and naming convention\n\nIt is also possible to update the default directory and file extension by changing the `bootOptions`\nof the application.\n\n```ts\nthis.bootOptions = {\n    migrations: {\n        dirs: [\"anyfolder\"],\n        extensions: [\".any.extension\"],\n        nested: true\n    }\n};\n```\n\n## Debug\n\nTo enable debug logs set the `DEBUG` environment variable to `loopback:migration:*`, see\n[Setting debug strings][lb4-debug-strings] for further details.\n\n## Related resources\n\n- [Evolutionary Database Design][evolutionary-database-design]\n\n## Contributing\n\n[![contributions welcome][contributions-welcome-badge]][issues]\n\n## License\n\nThis project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info.\n\n[actions]: https://github.com/nflaig/loopback4-migration/actions\n[license]: https://github.com/nflaig/loopback4-migration/blob/master/LICENSE\n[issues]: https://github.com/nflaig/loopback4-migration/issues\n[coveralls]: https://coveralls.io/github/nflaig/loopback4-migration?branch=master\n[npm-package]: https://www.npmjs.com/package/loopback4-migration\n\n[build-badge]: https://github.com/nflaig/loopback4-migration/workflows/build/badge.svg\n[coveralls-badge]: https://coveralls.io/repos/github/nflaig/loopback4-migration/badge.svg?branch=master\n[npm-version-badge]: https://img.shields.io/npm/v/loopback4-migration.svg?style=flat-square\n[npm-downloads-badge]: https://img.shields.io/npm/dw/loopback4-migration.svg?label=Downloads\u0026style=flat-square\u0026color=blue\n[npm-total-downloads-badge]: https://img.shields.io/npm/dt/loopback4-migration.svg?label=Total%20Downloads\u0026style=flat-square\u0026color=blue\n[license-badge]: https://img.shields.io/github/license/nflaig/loopback4-migration.svg?color=blue\u0026label=License\u0026style=flat-square\n[contributions-welcome-badge]: https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat\n\n[lb4-binding-scope]: https://loopback.io/doc/en/lb4/Binding.html#configure-the-scope\n[lb4-binding-tags]: https://loopback.io/doc/en/lb4/Binding.html#describe-tags\n[lb4-repositories]: https://loopback.io/doc/en/lb4/Repositories.html\n[lb4-dependency-injection]: https://loopback.io/doc/en/lb4/Dependency-injection.html\n[lb4-debug-strings]: https://loopback.io/doc/en/lb4/Setting-debug-strings.html\n[evolutionary-database-design]: https://www.martinfowler.com/articles/evodb.html\n[semantic-versioning]: https://semver.org/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnflaig%2Floopback4-migration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnflaig%2Floopback4-migration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnflaig%2Floopback4-migration/lists"}