{"id":13780204,"url":"https://github.com/feathersjs-ecosystem/feathers-sequelize","last_synced_at":"2025-05-16T07:05:14.917Z","repository":{"id":2495429,"uuid":"45963279","full_name":"feathersjs-ecosystem/feathers-sequelize","owner":"feathersjs-ecosystem","description":"A Feathers service adapter for the Sequelize ORM. Supporting MySQL, MariaDB, Postgres, SQLite, and SQL Server","archived":false,"fork":false,"pushed_at":"2025-05-04T13:30:32.000Z","size":1889,"stargazers_count":208,"open_issues_count":14,"forks_count":75,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-05-04T14:22:11.428Z","etag":null,"topics":["feathers-service-adapter","feathersjs","sequelize"],"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/feathersjs-ecosystem.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/contributing.md","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":"2015-11-11T06:10:07.000Z","updated_at":"2025-05-04T13:17:04.000Z","dependencies_parsed_at":"2023-07-06T15:16:41.968Z","dependency_job_id":"2e5e7e5f-5e92-4299-b058-61e0ad0f13d0","html_url":"https://github.com/feathersjs-ecosystem/feathers-sequelize","commit_stats":{"total_commits":364,"total_committers":46,"mean_commits":7.913043478260869,"dds":"0.43956043956043955","last_synced_commit":"cca3cc7694592a5e9bdfb5d67c873cb8a0b8f740"},"previous_names":[],"tags_count":87,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feathersjs-ecosystem%2Ffeathers-sequelize","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feathersjs-ecosystem%2Ffeathers-sequelize/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feathersjs-ecosystem%2Ffeathers-sequelize/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feathersjs-ecosystem%2Ffeathers-sequelize/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/feathersjs-ecosystem","download_url":"https://codeload.github.com/feathersjs-ecosystem/feathers-sequelize/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254485057,"owners_count":22078767,"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":["feathers-service-adapter","feathersjs","sequelize"],"created_at":"2024-08-03T18:01:13.331Z","updated_at":"2025-05-16T07:05:09.895Z","avatar_url":"https://github.com/feathersjs-ecosystem.png","language":"TypeScript","readme":"# feathers-sequelize\n\n[![CI](https://github.com/feathersjs-ecosystem/feathers-sequelize/workflows/CI/badge.svg)](https://github.com/feathersjs-ecosystem/feathers-sequelize/actions?query=workflow%3ACI)\n[![Download Status](https://img.shields.io/npm/dm/feathers-sequelize.svg)](https://www.npmjs.com/package/feathers-sequelize)\n[![Discord](https://badgen.net/badge/icon/discord?icon=discord\u0026label)](https://discord.gg/qa8kez8QBx)\n\n\u003e **Caution:** When you're using feathers v4 and want to upgrade to feathers v5, please make sure to read the [migration guide](#migrate-to-feathers-v5-dove).\n\n\u003e NOTE: This is the version for Feathers v5. For Feathers v4 use [feathers-sequelize v6](https://github.com/feathersjs-ecosystem/feathers-sequelize/tree/crow)\n\nA [Feathers](https://feathersjs.com) database adapter for [Sequelize](https://sequelize.org/), an ORM for Node.js. It supports PostgreSQL, MySQL, MariaDB, SQLite and MSSQL and features transaction support, relations, read replication and more.\n\n\u003c!-- TOC --\u003e\n\n- [API](#api)\n  - [`service(options)`](#serviceoptions)\n  - [params.sequelize](#paramssequelize)\n  - [operators](#operatormap)\n  - [Modifying the model](#modifyModel)\n- [Caveats](#caveats)\n  - [Sequelize `raw` queries](#sequelize-raw-queries)\n  - [Working with MSSQL](#working-with-mssql)\n- [Example](#example)\n- [Associations](#associations)\n  - [Embrace the ORM](#embrace-the-orm)\n  - [Setting `params.sequelize.include`](#setting-paramssequelizeinclude)\n- [Querying](#querying)\n  - [Querying a nested column](#querying-a-nested-column)\n- [Working with Sequelize Model instances](#working-with-sequelize-model-instances)\n- [Validation](#validation)\n- [Errors](#errors)\n- [Testing sequelize queries in isolation](#testing-sequelize-queries-in-isolation)\n  - [1. Build a test file](#1-build-a-test-file)\n  - [2. Integrate the query using a \"before\" hook](#2-integrate-the-query-using-a-before-hook)\n- [Migrations](#migrations)\n  - [Initial Setup: one-time tasks](#initial-setup-one-time-tasks)\n  - [Migrations workflow](#migrations-workflow)\n  - [Create a new migration](#create-a-new-migration)\n    - [Add the up/down scripts:](#add-the-updown-scripts)\n    - [Keeping your app code in sync with migrations](#keeping-your-app-code-in-sync-with-migrations)\n  - [Apply a migration](#apply-a-migration)\n  - [Undo the previous migration](#undo-the-previous-migration)\n  - [Reverting your app to a previous state](#reverting-your-app-to-a-previous-state)\n  - [Migrating](#migrating)\n- [License](#license)\n- [Migrating to feathers v5](#migrate-to-feathers-v5-dove)\n\n\u003c!-- /TOC --\u003e\n\n\u003e __Very Important:__ Before using this adapter you have to be familiar with both, the [Feathers Basics](https://docs.feathersjs.com/guides/basics/setup.html) and general use of [Sequelize](https://sequelize.org/docs/v6/). For associations and relations see the [associations](#associations) section. This adapter may not cover all use cases but they can still be implemented using Sequelize models directly in a [Custom Feathers service](https://docs.feathersjs.com/guides/basics/services.html).\n\n```bash\nnpm install --save feathers-sequelize@pre\n```\n\nAnd [one of the following](https://sequelize.org/docs/v6/getting-started/):\n\n```bash\nnpm install --save pg pg-hstore\nnpm install --save mysql2 // For both mysql and mariadb dialects\nnpm install --save sqlite3\nnpm install --save tedious // MSSQL\n```\n\n\u003e __Important:__ `feathers-sequelize` implements the [Feathers Common database adapter API](https://docs.feathersjs.com/api/databases/common.html) and [querying syntax](https://docs.feathersjs.com/api/databases/querying.html).\n\u003e For more information about models and general Sequelize usage, follow up in the [Sequelize documentation](https://sequelize.org/docs/v6/).\n\n## API\n\n### `new SequelizeService(options)`\n\nReturns a new service instance initialized with the given options.\n\n```js\nconst Model = require('./models/mymodel');\nconst { SequelizeService } = require('feathers-sequelize');\n\napp.use('/messages', new SequelizeService({ Model }));\napp.use('/messages', new SequelizeService({ Model, id, events, paginate }));\n```\n\n__Options:__\n\n- `Model` (**required**) - The Sequelize model definition\n- `id` (*optional*, default: primary key of the model) - The name of the id field property. Will use the first property with `primaryKey: true` by default.\n- `raw` (*optional*, default: `true`) - Runs queries faster by returning plain objects instead of Sequelize models.\n- `Sequelize` (*optional*, default: `Model.sequelize.Sequelize`) - The Sequelize instance\n- `events` (*optional*) - A list of [custom service events](https://docs.feathersjs.com/api/events.html#custom-events) sent by this service\n- `paginate` (*optional*) - A [pagination object](https://docs.feathersjs.com/api/databases/common.html#pagination) containing a `default` and `max` page size\n- `multi` (*optional*) - Allow `create` with arrays and `update` and `remove` with `id` `null` to change multiple items. Can be `true` for all methods or an array of allowed methods (e.g. `[ 'remove', 'create' ]`)\n- `operatorMap` (*optional*) - A mapping from query syntax property names to to [Sequelize secure operators](https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#operators)\n- `operators` (*optional*) - An array of additional query operators to allow (e..g `[ '$regex', '$geoNear' ]`). Default is the supported `operators`\n- `filters` (*optional*) - An object of additional query parameters to allow (e..g `{ '$post.id$': true }`).`\n\n### params.sequelize\n\nWhen making a [service method](https://docs.feathersjs.com/api/services.html) call, `params` can contain an `sequelize` property which allows to pass additional Sequelize options. This can e.g. be used to **retrieve associations**. Normally this wil be set in a before [hook](https://docs.feathersjs.com/api/hooks.html):\n\n```js\napp.service('messages').hooks({\n  before: {\n    find(context) {\n      // Get the Sequelize instance. In the generated application via:\n      const sequelize = context.app.get('sequelizeClient');\n      const { User } = sequelize.models;\n\n      context.params.sequelize = {\n        include: [ User ]\n      }\n\n      return context;\n    }\n  }\n});\n```\n\nOther options that `params.sequelize` allows you to pass can be found in [Sequelize querying docs](https://sequelize.org/master/manual/model-querying-basics.html).\nBeware that when setting a [top-level `where` property](https://sequelize.org/master/manual/eager-loading.html#complex-where-clauses-at-the-top-level) (usually for querying based on a column on an associated model), the `where` in `params.sequelize` will overwrite your `query`.\n\nThis library offers some additional functionality when using `sequelize.returning` in services that support `multi`. The `multi` option allows you to create, patch, and remove multiple records at once. When using `sequelize.returning` with `multi`, the `sequelize.returning` is used to indicate if the method should return any results. This is helpful when updating large numbers of records and you do not need the API (or events) to be bogged down with results.\n\n### operatorMap\n\nSequelize deprecated string based operators a while ago for security reasons. Starting at version 4.0.0 `feathers-sequelize` converts queries securely, so you can still use string based operators listed below. If you want to support additional Sequelize operators, the `operatorMap` service option can contain a mapping from query parameter name to Sequelize operator. By default supported are:\n\n```\n'$eq',\n'$ne',\n'$gte',\n'$gt',\n'$lte',\n'$lt',\n'$in',\n'$nin',\n'$like',\n'$notLike',\n'$iLike',\n'$notILike',\n'$or',\n'$and'\n```\n\n```js\n// Find all users with name similar to Dav\napp.service('users').find({\n  query: {\n    name: {\n      $like: 'Dav%'\n    }\n  }\n});\n```\n\n```\nGET /users?name[$like]=Dav%\n```\n\n## Modifying the Model\n\nSequelize allows you to call methods like `Model.scope()`, `Model.schema()`, and others. To use these methods, extend the class to overwrite the `getModel` method.\n\n```js\nconst { SequelizeService } = require('feathers-sequelize');\n\nclass Service extends SequelizeService {\n  getModel(params) {\n    let Model = this.options.Model;\n    if (params?.sequelize?.scope) {\n      Model = Model.scope(params.sequelize.scope);\n    }\n    if (params?.sequelize?.schema) {\n      Model = Model.schema(params.sequelize.schema);\n    }\n    return Model;\n  }\n}\n```\n\n## Caveats\n\n### Sequelize `raw` queries\n\nBy default, all `feathers-sequelize` operations will return `raw` data (using `raw: true` when querying the database). This results in faster execution and allows feathers-sequelize to interoperate with feathers-common hooks and other 3rd party integrations. However, this will bypass some of the \"goodness\" you get when using Sequelize as an ORM:\n\n - custom getters/setters will be bypassed\n - model-level validations are bypassed\n - associated data loads a bit differently\n - ...and several other issues that one might not expect\n\nDon't worry! The solution is easy. Please read the guides about [working with model instances](#working-with-sequelize-model-instances). You can also pass `{ raw: true/false}` in `params.sequelize` to change the behavior per service call.\n\n### Working with MSSQL\n\nWhen using MSSQL as the database, a default sort order always has to be applied, otherwise the adapter will throw an `Invalid usage of the option NEXT in the FETCH statement.` error. This can be done in your model with:\n\n```js\nmodel.beforeFind(model =\u003e model.order.push(['id', 'ASC']))\n```\n\nOr in a hook like this:\n\n```js\nexport default function (options = {}) {\n  return async context =\u003e {\n    const { query = {} } = context.params;\n    // Sort by id field ascending (or any other property you want)\n    // See https://docs.feathersjs.com/api/databases/querying.html#sort\n    const $sort = { id: 1 };\n\n    context.params.query = {\n      $sort: {\n\n      },\n      ...query\n    }\n\n    return context;\n  }\n}\n```\n\n### Primary keys\nAll tables used by a feathers-sequelize service require a primary key. Although it is common practice for many-to-many tables to not have a primary key, this service will break if the table does not have a primary key. This is because most service methods require an ID and because of how feathers maps services to URLs.\n\n## Example\n\nHere is an example of a Feathers server with a `messages` SQLite Sequelize Model:\n\n```\n$ npm install @feathersjs/feathers @feathersjs/errors @feathersjs/express @feathersjs/socketio sequelize feathers-sequelize sqlite3\n```\n\nIn `app.js`:\n\n```ts\nimport path from 'path';\nimport { feathers } from '@feathersjs/feathers';\nimport express from '@feathersjs/express';\nimport socketio from '@feathersjs/socketio';\n\nimport Sequelize from 'sequelize';\nimport SequelizeService from 'feathers-sequelize';\n\nconst sequelize = new Sequelize('sequelize', '', '', {\n  dialect: 'sqlite',\n  storage: path.join(__dirname, 'db.sqlite'),\n  logging: false\n});\n\nconst Message = sequelize.define('message', {\n  text: {\n    type: Sequelize.STRING,\n    allowNull: false\n  }\n}, {\n  freezeTableName: true\n});\n\n// Create an Express compatible Feathers application instance.\nconst app = express(feathers());\n\n// Turn on JSON parser for REST services\napp.use(express.json());\n// Turn on URL-encoded parser for REST services\napp.use(express.urlencoded({ extended: true }));\n// Enable REST services\napp.configure(express.rest());\n// Enable Socket.io services\napp.configure(socketio());\n// Create an in-memory Feathers service with a default page size of 2 items\n// and a maximum size of 4\napp.use('/messages', new SequelizeService({\n  Model: Message,\n  paginate: {\n    default: 2,\n    max: 4\n  }\n}));\napp.use(express.errorHandler());\n\nMessage.sync({ force: true }).then(() =\u003e {\n  // Create a dummy Message\n  app.service('messages').create({\n    text: 'Message created on server'\n  }).then(message =\u003e console.log('Created message', message));\n});\n\n// Start the server\nconst port = 3030;\n\napp.listen(port, () =\u003e {\n  console.log(`Feathers server listening on port ${port}`);\n});\n```\n\nRun the example with `node app` and go to [localhost:3030/messages](http://localhost:3030/messages).\n\n\n## Associations\n\n### Embrace the ORM\n\nThe documentation on [Sequelize associations and relations](https://sequelize.org/docs/v6/core-concepts/assocs/) is essential to implementing associations with this adapter and one of the steepest parts of the Sequelize learning curve. If you have never used an ORM, let it do a lot of the heavy lifting for you!\n\n### Setting `params.sequelize.include`\n\nOnce you understand how the `include` option works with Sequelize, you will want to set that option from a [before hook](https://docs.feathersjs.com/guides/basics/hooks.html) in Feathers. Feathers will pass the value of `context.params.sequelize` as the options parameter for all Sequelize method calls. This is what your hook might look like:\n\n```js\n// GET /my-service?name=John\u0026include=1\nfunction (context) {\n  const { include, ...query } = context.params.query;\n\n   if (include) {\n      const AssociatedModel = context.app.services.fooservice.Model;\n      context.params.sequelize = {\n        include: [{ model: AssociatedModel }]\n      };\n      // Update the query to not include `include`\n      context.params.query = query;\n   }\n\n   return context;\n}\n```\n\nUnderneath the hood, feathers will call your models find method sort of like this:\n\n```js\n// YourModel is a sequelize model\nconst options = Object.assign({ where: { name: 'John' }}, context.params.sequelize);\nYourModel.findAndCount(options);\n```\n\nFor more information, follow up up in the [Sequelize documentation for associations](https://sequelize.org/docs/v6/core-concepts/assocs/) and [this issue](https://github.com/feathersjs-ecosystem/feathers-sequelize/issues/20).\n\n## Querying\n\nAdditionally to the [common querying mechanism](https://docs.feathersjs.com/api/databases/querying.html) this adapter also supports all [Sequelize query operators](https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#operators).\n\n### Querying a nested column\n\nTo query based on a column in an associated model, you can use Sequelize's [nested column syntax](https://sequelize.org/master/manual/eager-loading.html#complex-where-clauses-at-the-top-level) in a query. The nested column syntax is considered a `filter` by Feathers, and so each such usage has to be [whitelisted](#whitelist).\n\nExample:\n```js\n// Find a user with post.id == 120\napp.service('users').find({\n  query: {\n    '$post.id$': 120,\n    include: {\n      model: posts\n    }\n  }\n});\n```\n\nFor this case to work, you'll need to add '$post.id$' to the service options' ['filters' property](#whitelist).\n\n## Working with Sequelize Model instances\n\nIt is highly recommended to use `raw` queries, which is the default. However, there are times when you will want to take advantage of [Sequelize Instance](https://sequelize.org/docs/v6/core-concepts/model-instances/) methods. There are two ways to tell feathers to return Sequelize instances:\n\n1. Set `{ raw: false }` in a \"before\" hook:\n    ```js\n    const rawFalse = () =\u003e (context) =\u003e {\n      if (!context.params.sequelize) context.params.sequelize = {};\n      Object.assign(context.params.sequelize, { raw: false });\n      return context;\n    }\n\n    export default {\n      after: {\n        // ...\n        find: [rawFalse()]\n        // ...\n      },\n      // ...\n    };\n\n    ```\n1. Use the `hydrate` hook in the \"after\" phase:\n\n    ```js\n    import { hydrate } from 'feathers-sequelize';\n\n    export default {\n      after: {\n        // ...\n        find: [hydrate()]\n        // ...\n      },\n      // ...\n    };\n\n    // Or, if you need to include associated models, you can do the following:\n    const includeAssociated = () =\u003e (context) =\u003e hydrate({\n      include: [{ model: context.app.services.fooservice.Model }]\n    });\n\n    export default {\n      after: {\n        // ...\n        find: [includeAssociated()]\n        // ...\n      },\n      // ...\n    };\n    ```\n\n  For a more complete example see this [gist](https://gist.github.com/sicruse/bfaa17008990bab2fd1d76a670c3923f).\n\n\u003e **Important:** When working with Sequelize Instances, most of the feathers-hooks-common will no longer work. If you need to use a common hook or other 3rd party hooks, you should use the \"dehydrate\" hook to convert data back to a plain object:\n\u003e ```js\n\u003e import { dehydrate, hydrate } from 'feathers-sequelize';\n\u003e import { populate } = from 'feathers-hooks-common';\n\u003e\n\u003e export default {\n\u003e   after: {\n\u003e     // ...\n\u003e     find: [hydrate(), doSomethingCustom(), dehydrate(), populate()]\n\u003e     // ...\n\u003e   },\n\u003e   // ...\n\u003e };\n\u003e ```\n\n## Validation\n\nSequelize by default gives you the ability to [add validations at the model level](https://sequelize.org/docs/v6/core-concepts/validations-and-constraints/). Using an error handler like the one that [comes with Feathers](https://github.com/feathersjs/feathers-errors/blob/master/src/error-handler.js) your validation errors will be formatted nicely right out of the box!\n\n## Errors\n\nErrors do not contain Sequelize specific information. The original Sequelize error can be retrieved on the server via:\n\n```js\nimport { ERROR } = from 'feathers-sequelize';\n\ntry {\n  await sequelizeService.doSomething();\n} catch(error) {\n  // error is a FeathersError\n  // Safely retrieve the Sequelize error\n  const sequelizeError = error[ERROR];\n}\n```\n\n## Testing sequelize queries in isolation\n\nIf you wish to use some of the more advanced features of sequelize, you should first test your queries in isolation (without feathers). Once your query is working, you can integrate it into your feathers app.\n\n### 1. Build a test file\n\nCreate a temporary file in your project root like this:\n\n```js\n// test.js\nimport app from from './src/app';\n// run setup to initialize relations\napp.setup();\n\nconst seqClient = app.get('sequelizeClient');\nconst SomeModel = seqClient.models['some-model'];\nconst log = console.log.bind(console);\n\nSomeModel.findAll({\n  /*\n  * Build your custom query here. We will use this object later.\n  */\n}).then(log).catch(log);\n```\n\nAnd then run this file like this:\n\n```\nnode test.js\n```\nContinue updating the file and running it until you are satisfied with the results.\n\n### 2. Integrate the query using a \"before\" hook\n\nOnce your have your custom query working to your satisfaction, you will want to integrate it into your feathers app. Take the guts of the `findAll` operation above and create a \"before\" hook:\n\n```js\nfunction buildCustomQuery(context) {\n\tcontext.params.sequelize = {\n       /*\n        * This is the same object you passed to \"findAll\" above.\n        * This object is *shallow merged* onto the underlying query object\n        * generated by feathers-sequelize (it is *not* a deep merge!).\n        * The underlying data will already contain the following:\n        *   - \"where\" condition based on query paramters\n        *   - \"limit\" and \"offset\" based on pagination settings\n        *   - \"order\" based $sort query parameter\n        * You can override any/all of the underlying data by setting it here.\n        * This gives you full control over the query object passed to sequelize!\n        */\n\t};\n}\n\nsomeService.hooks({\n\tbefore: {\n\t\tfind: [buildCustomQuery]\n\t}\n});\n```\n\n\n## Migrations\n\nMigrations with feathers and sequelize are quite simple. This guide will walk you through creating the recommended file structure, but you are free to rearrange things as you see fit. The following assumes you have a `migrations` folder in the root of your app.\n\n### Initial Setup: one-time tasks\n\n- Install the [sequelize CLI](https://github.com/sequelize/cli):\n\n```\nnpm install sequelize-cli --save -g\n```\n\n- Create a `.sequelizerc` file in your project root with the following content:\n\n```js\nconst path = require('path');\n\nmodule.exports = {\n  'config': path.resolve('migrations/config.js'),\n  'migrations-path': path.resolve('migrations/scripts'),\n  'seeders-path': path.resolve('migrations/seeders'),\n  'models-path': path.resolve('migrations/models.js')\n};\n```\n\n- Create the migrations config in `migrations/config.js`:\n\n```js\nconst app = require('../src/app');\nconst env = process.env.NODE_ENV || 'development';\nconst dialect = 'postgres'; // Or your dialect name\n\nmodule.exports = {\n  [env]: {\n    dialect,\n    url: app.get(dialect),\n    migrationStorageTableName: '_migrations'\n  }\n};\n```\n\n- Define your models config in `migrations/models.js`:\n\n```js\nconst Sequelize = require('sequelize');\nconst app = require('../src/app');\nconst sequelize = app.get('sequelizeClient');\nconst models = sequelize.models;\n\n// The export object must be a dictionary of model names -\u003e models\n// It must also include sequelize (instance) and Sequelize (constructor) properties\nmodule.exports = Object.assign({\n  Sequelize,\n  sequelize\n}, models);\n```\n\n### Migrations workflow\n\nThe migration commands will load your application and it is therefore required that you define the same environment variables as when running your application. For example, many applications will define the database connection string in the startup command:\n\n```\nDATABASE_URL=postgres://user:pass@host:port/dbname npm start\n```\nAll of the following commands assume that you have defined the same environment variables used by your application.\n\n\u003e **ProTip:** To save typing, you can export environment variables for your current bash/terminal session:\n\n```\nexport DATABASE_URL=postgres://user:pass@host:port/db\n```\n\n### Create a new migration\n\nTo create a new migration file, run the following command and provide a meaningful name:\n\n```\nsequelize migration:create --name=\"meaningful-name\"\n```\n\nThis will create a new file in the `migrations/scripts` folder. All migration file names will be prefixed with a sortable data/time string: `20160421135254-meaningful-name.js`. This prefix is crucial for making sure your migrations are executed in the proper order.\n\n\u003e **NOTE:** The order of your migrations is determined by the alphabetical order of the migration scripts in the file system. The file names generated by the CLI tools will always ensure that the most recent migration comes last.\n\n#### Add the up/down scripts:\n\nOpen the newly created migration file and write the code to both apply and undo the migration. Please refer to the [sequelize migration functions](https://sequelize.org/docs/v6/other-topics/migrations/) for available operations. **Do not be lazy - write the down script too and test!** Here is an example of converting a `NOT NULL` column accept null values:\n\n```js\n'use strict';\n\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.changeColumn('tableName', 'columnName', {\n      type: Sequelize.STRING,\n      allowNull: true\n    });\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.changeColumn('tableName', 'columnName', {\n      type: Sequelize.STRING,\n      allowNull: false\n    });\n  }\n};\n```\n\n\u003e **ProTip:** As of this writing, if you use the `changeColumn` method you must **always** specify the `type`, even if the type is not changing.\n\n\u003e **ProTip:** Down scripts are typically easy to create and should be nearly identical to the up script except with inverted logic and inverse method calls.\n\n#### Keeping your app code in sync with migrations\n\nThe application code should always be up to date with the migrations. This allows the app to be freshly installed with everything up-to-date without running the migration scripts. Your migrations should also never break a freshly installed app. This often times requires that you perform any necessary checks before executing a task. For example, if you update a model to include a new field, your migration should first check to make sure that new field does not exist:\n\n```js\n'use strict';\n\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.describeTable('tableName').then(attributes =\u003e {\n      if ( !attributes.columnName ) {\n        return queryInterface.addColumn('tableName', 'columnName', {\n          type: Sequelize.INTEGER,\n          defaultValue: 0\n        });\n      }\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.describeTable('tableName').then(attributes =\u003e {\n      if ( attributes.columnName ) {\n        return queryInterface.removeColumn('tableName', 'columnName');\n      }\n    });\n  }\n};\n```\n\n### Apply a migration\n\nThe CLI tools will always run your migrations in the correct order and will keep track of which migrations have been applied and which have not. This data is stored in the database under the `_migrations` table. To ensure you are up to date, simply run the following:\n\n```\nsequelize db:migrate\n```\n\n\u003e **ProTip:** You can add the migrations script to your application startup command to ensure that all migrations have run every time your app is started. Try updating your package.json `scripts` attribute and run `npm start`:\n\n```\nscripts: {\n    start: \"sequelize db:migrate \u0026\u0026 node src/\"\n}\n```\n\n### Undo the previous migration\n\nTo undo the last migration, run the following command:\n\n```\nsequelize db:migrate:undo\n```\n\nContinue running the command to undo each migration one at a time - the migrations will be undone in the proper order.\n\n\u003e **Note:** - You shouldn't really have to undo a migration unless you are the one developing a new migration and you want to test that it works. Applications rarely have to revert to a previous state, but when they do you will be glad you took the time to write and test your `down` scripts!\n\n### Reverting your app to a previous state\n\nIn the unfortunate case where you must revert your app to a previous state, it is important to take your time and plan your method of attack. Every application is different and there is no one-size-fits-all strategy for rewinding an application. However, most applications should be able to follow these steps (order is important):\n\n1. Stop your application (kill the process)\n1. Find the last stable version of your app\n1. Count the number of migrations which have been added since that version\n1. Undo your migrations one at a time until the db is in the correct state\n1. Revert your code back to the previous state\n1. Start your app\n\n## License\n\nCopyright (c) 2024\n\nLicensed under the [MIT license](LICENSE).\n\n### whitelist\n\nThe `whitelist` property is no longer, you should use `filters` instead. Checkout the migration guide below.\n\n\u003e Feathers v5 introduces a convention for `options.operators` and `options.filters`. The way feathers-sequelize worked in previous version is not compatible with these conventions. Please read https://dove.feathersjs.com/guides/migrating.html#custom-filters-operators.\n\n## Migrate to Feathers v5 (dove)\n\nThere are several breaking changes for feathers-sequelize in Feathers v5. This guide will help you to migrate your existing Feathers v4 application to Feathers v5.\n\n### Named export\n\nThe default export of `feathers-sequelize` has been removed. You now have to import the `SequelizeService` class directly:\n```js\nimport { SequelizeService } from 'feathers-sequelize';\n\napp.use('/messages', new SequelizeService({ ... }));\n```\nThis follows conventions from feathers v5.\n\n### operators / operatorMap\n\n\u003e Feathers v5 introduces a convention for `options.operators` and `options.filters`. The way feathers-sequelize worked in previous version is not compatible with these conventions. Please read https://dove.feathersjs.com/guides/migrating.html#custom-filters-operators first.\n\nThe old `options.operators` object is renamed to `options.operatorMap`:\n\n```js\nimport { SequelizeService } from 'feathers-sequelize';\nimport { Op } from 'sequelize';\n\napp.use('/messages', new SequelizeService({\n  Model,\n  // operators is now operatorMap:\n  operatorMap: {\n    $between: Op.between\n  }\n}));\n```\n\n### filters\n\n\u003e Feathers v5 introduces a convention for `options.operators` and `options.filters`. The way feathers-sequelize worked in previous version is not compatible with these conventions. Please read https://dove.feathersjs.com/guides/migrating.html#custom-filters-operators first.\n\nFeathers v5 introduces a new `filters` option. It is an object to verify filters. Here you need to add `$dollar.notation$` operators, if you have some.\n\n```js\nimport { SequelizeService } from 'feathers-sequelize';\n\napp.use('/messages', new SequelizeService({\n  Model,\n  filters: {\n    '$and': true,\n    '$person.name$': true\n  }\n}));\n```\n","funding_links":[],"categories":["Plugins"],"sub_categories":["Database"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeathersjs-ecosystem%2Ffeathers-sequelize","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffeathersjs-ecosystem%2Ffeathers-sequelize","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeathersjs-ecosystem%2Ffeathers-sequelize/lists"}