diff --git a/docs/cli.md b/docs/cli.md index 3082acc00..d67819e35 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -3,650 +3,529 @@ title: Sequelize CLI sidebar_position: 9 --- -:::warning +Just like you use [version control](https://en.wikipedia.org/wiki/Version_control) systems such as [Git](https://en.wikipedia.org/wiki/Git) to manage changes in your source code, you can use **migrations** to keep track of changes to the database. With migrations you can transfer your existing database into another state and vice versa: those state transitions are saved in migration files, which describe how to get to the new state and how to revert the changes in order to get back to the old state. -Neither the Sequelize CLI nor its documentation is ready for use in Sequelize 7. If you rely on the CLI, please stay on Sequelize 6 for now. +The Sequelize CLI (`@sequelize/cli`) ships support for running and managing migrations. It is built on top of [umzug](https://github.com/sequelize/umzug) for migration execution and [oclif](https://oclif.io) for the command-line interface. -Considering the main purpose of the CLI is to run migrations, you can also try using [umzug](https://github.com/sequelize/umzug), or any -other database migration tool instead. +## Installing the CLI -::: +```bash npm2yarn +npm install --save-dev @sequelize/cli +``` -Just like you use [version control](https://en.wikipedia.org/wiki/Version_control) systems such as [Git](https://en.wikipedia.org/wiki/Git) to manage changes in your source code, you can use **migrations** to keep track of changes to the database. With migrations, you can transfer your existing database into another state and vice versa: Those state transitions are saved in migration files, which describe how to get to the new state and how to revert the changes to get back to the old state. +The CLI binary is named `sequelize`: -You will need the [Sequelize Command-Line Interface (CLI)](https://github.com/sequelize/cli). The CLI ships support for migrations and project bootstrapping. +```bash +# npm +npx sequelize --help -A Migration in Sequelize is a JavaScript file that exports two functions, `up` and `down`, that dictate how to perform the migration and undo it. You define those functions manually, but you don't call them manually; the CLI will call them automatically. In these functions, you should perform whatever queries you need, with the help of `sequelize.query` and whichever other methods Sequelize provides to you. There is no extra magic beyond that. +# yarn +yarn sequelize --help +``` -## Installing the CLI +## Configuration -To install the Sequelize CLI: +The CLI is configured using [cosmiconfig](https://github.com/cosmiconfig/cosmiconfig). +It searches for a `sequelize` configuration in the following places: -```bash -# using npm -npm install --save-dev sequelize-cli -# using yarn -yarn add sequelize-cli --dev -``` +- A `sequelize` key in `package.json`. +- A `.sequelizerc.json` or `.config/sequelizerc.json` file (can also be yml, js, mjs, cjs). +- A `sequelize.config.js`, `sequelize.config.cjs`, or `sequelize.config.mjs` file (recommended). -For details see the [CLI GitHub repository](https://github.com/sequelize/cli). +The configuration file must export (or contain) an object with the following properties: -## Project bootstrapping +| Option | Type | Default | Description | +| ----------------- | -------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `migrationFolder` | `string` | `"/migrations"` | Path to the migrations folder, relative to the config file's directory. | +| `seedFolder` | `string` | `"/seeds"` | Path to the seeds folder, relative to the config file's directory. | +| `database` | `object` | — | [Sequelize constructor options](./getting-started.mdx#connecting-to-a-database), including a `dialect`. Required for commands that connect to the database. | -To create an empty project you will need to execute `init` command +The `dialect` field inside `database` can be either a dialect class (e.g. `PostgresDialect`) or an import-path string (e.g. `"@sequelize/postgres#PostgresDialect"`). -```bash -# using npm -npx sequelize-cli init -# using yarn -yarn sequelize-cli init +### Example configuration + +When using a JavaScript or TypeScript config file, you can pass the dialect class directly: + +```js title="sequelize.config.mjs" +import { loadEnvFile } from 'node:process'; +import { PostgresDialect } from '@sequelize/postgres'; + +// load the ".env" file (if it exists) so we can use environment variables in the config +loadEnvFile(); + +export default { + migrationFolder: '/db/migrations', + seedFolder: '/db/seeds', + + // Commands that only generate files (e.g. `migration generate`, `seed generate`) + // do not require a `database` entry in the config. + database: { + dialect: PostgresDialect, + + // These options depend on the dialect, see the "Getting started" docs for details + database: 'my_database', + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + host: 'localhost', + port: 5432, + }, +}; ``` -This will create the following folders +:::tip -- `config`, contains the config file, which tells CLI how to connect with the database -- `models`, contains all models for your project -- `migrations`, contains all migration files -- `seeders`, contains all seed files +Keep secrets (passwords, API keys) out of source code. Use environment variables as shown above. -### Configuration +::: -Before continuing further we will need to tell the CLI how to connect to the database. To do that let's open the default config file `config/config.json`. It looks something like this: +When using a JSON config file (e.g. `.sequelizerc` or a `sequelize` key in `package.json`), +specify the dialect as an import-path string in the form `"#"`. +The CLI will import the package and resolve the named export at startup: -```json +```json title=".sequelizerc" { - "development": { - "username": "root", - "password": null, - "database": "database_development", - "host": "127.0.0.1", - "dialect": "mysql" - }, - "test": { - "username": "root", - "password": null, - "database": "database_test", - "host": "127.0.0.1", - "dialect": "mysql" - }, - "production": { - "username": "root", - "password": null, - "database": "database_production", - "host": "127.0.0.1", - "dialect": "mysql" + "migrationFolder": "/db/migrations", + "seedFolder": "/db/seeds", + "database": { + "dialect": "@sequelize/postgres#PostgresDialect", + "database": "my_database", + "host": "localhost", + "port": 5432 } } ``` -Note that the Sequelize CLI assumes MySQL by default. If you're using another dialect, you need to change the content of the `"dialect"` option. - -Now edit this file and set correct database credentials and dialect. The keys of the objects (e.g. "development") are used on `model/index.js` for matching `process.env.NODE_ENV` (When undefined, "development" is a default value). +Examples of import-path strings (not exhaustive): -Sequelize will use the default connection port for each dialect (for example, for Postgres, it is port 5432). If you need to specify a different port, use the `"port"` field (it is not present by default in `config/config.js` but you can simply add it). +| Dialect | Import-path string | +| ---------- | ----------------------------------------- | +| PostgreSQL | `"@sequelize/postgres#PostgresDialect"` | +| MySQL | `"@sequelize/mysql#MySqlDialect"` | +| MariaDB | `"@sequelize/mariadb#MariaDbDialect"` | +| SQLite | `"@sequelize/sqlite3#SqliteDialect"` | +| MSSQL | `"@sequelize/mssql#MsSqlDialect"` | +| DB2 | `"@sequelize/db2#Db2Dialect"` | +| Snowflake | `"@sequelize/snowflake#SnowflakeDialect"` | -**Note:** _If your database doesn't exist yet, you can just call `db:create` command. With proper access, it will create that database for you._ +:::warning -## Creating the first Model (and Migration) +Using JSON is discouraged, as it cannot access environment variables or other dynamic values. +Make sure to keep secrets out of source code. -Once you have properly configured the CLI config file you are ready to create your first migration. It's as simple as executing a simple command. +::: -We will use `model:generate` command. This command requires two options: +## Migration commands -- `name`: the name of the model; -- `attributes`: the list of model attributes. +### `migration generate` -Let's create a model named `User`. +Generates a new migration file in the configured `migrationFolder`. ```bash -# using npm -npx sequelize-cli model:generate --name User --attributes firstName:string,lastName:string,email:string -# using yarn -yarn sequelize-cli model:generate --name User --attributes firstName:string,lastName:string,email:string +npx sequelize migration generate --format= [--name=] ``` -This will: +**Flags:** -- Create a model file `user` in `models` folder; -- Create a migration file with a name like `XXXXXXXXXXXXXX-create-user.js` in the `migrations` folder. +| Flag | Required | Default | Description | +| ---------- | -------- | ----------- | ------------------------------------------------------- | +| `--format` | Yes | — | File format: `sql`, `typescript`, `cjs`, or `esm`. | +| `--name` | No | `"unnamed"` | A short descriptive name, used as part of the filename. | -**Note:** _Sequelize will only use Model files, it's the table representation. On the other hand, the migration file is a change in that model or more specifically that table, used by CLI. Treat migrations like a commit or a log for some change in the database._ +The generated filename is prefixed with a UTC timestamp in `YYYY-MM-DDThh-mm-ss` format (e.g. `2026-04-12t14-30-00-create-users.ts`). Files are sorted alphabetically when run, so the timestamp ensures correct ordering. -## Writing a migration +**SQL format** creates a directory with two files: -The following skeleton shows a typical migration file. - -```js -module.exports = { - up: (queryInterface, Sequelize) => { - // logic for transforming into the new state - }, - down: (queryInterface, Sequelize) => { - // logic for reverting the changes - }, -}; +``` +migrations/ + 2026-04-12t14-30-00-create-users/ + up.sql ← forward migration + down.sql ← rollback migration ``` -We can generate this file using `migration:generate`. This will create `xxx-migration-example.js` in your migration folder. +**All other formats** create a single file: -```bash -# using npm -npx sequelize-cli migration:generate --name migration-example -# using yarn -yarn sequelize-cli migration:generate --name migration-example +``` +migrations/ + 2026-04-12t14-30-00-create-users.ts ← TypeScript + 2026-04-12t14-30-00-create-users.mjs ← ESM + 2026-04-12t14-30-00-create-users.cjs ← CommonJS ``` -The passed `queryInterface` object can be used to modify the database. The `Sequelize` object stores the available data types such as `STRING` or `INTEGER`. The function `up` or `down` should return a `Promise`. Let's look at an example: +If you run the command in interactive mode without providing `--name`, you will be prompted for one. -```js -const { DataTypes } = require('@sequelize/core'); +#### JSON output -module.exports = { - up: (queryInterface, Sequelize) => { - return queryInterface.createTable('Person', { - name: DataTypes.STRING, - isBetaMember: { - type: DataTypes.BOOLEAN, - defaultValue: false, - allowNull: false, - }, - }); - }, - down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Person'); - }, -}; +```bash +npx sequelize migration generate --format=typescript --name=create-users --json +# { "path": "/path/to/migrations/2026-04-12t14-30-00-create-users.ts" } ``` -The following is an example of a migration that performs two changes in the database, -using an automatically managed transaction to ensure that all instructions are successfully executed or rolled back in case of failure: +--- -```js -const { DataTypes } = require('@sequelize/core'); +### `migration run` -module.exports = { - up: (queryInterface, Sequelize) => { - return queryInterface.sequelize.transaction(transaction => { - return Promise.all([ - queryInterface.addColumn( - 'Person', - 'petName', - { - type: DataTypes.STRING, - }, - { transaction }, - ), - queryInterface.addColumn( - 'Person', - 'favoriteColor', - { - type: DataTypes.STRING, - }, - { transaction }, - ), - ]); - }); - }, - down: (queryInterface, Sequelize) => { - return queryInterface.sequelize.transaction(transaction => { - return Promise.all([ - queryInterface.removeColumn('Person', 'petName', { transaction }), - queryInterface.removeColumn('Person', 'favoriteColor', { transaction }), - ]); - }); - }, -}; +Runs all pending migrations (or a subset). + +```bash +npx sequelize migration run [--to=] [--step=] ``` -The next example is of a migration that has a foreign key. You can use references to specify a foreign key: +**Flags:** -```js -const { DataTypes } = require('@sequelize/core'); +| Flag | Default | Description | +| -------- | ------- | ---------------------------------------------------------- | +| `--to` | — | Run migrations up to and including the one with this name. | +| `--step` | — | Run only this many pending migrations. | -module.exports = { - up: queryInterface => { - return queryInterface.createTable('Person', { - name: DataTypes.STRING, - isBetaMember: { - type: DataTypes.BOOLEAN, - defaultValue: false, - allowNull: false, - }, - userId: { - type: DataTypes.INTEGER, - references: { - model: { - tableName: 'users', - schema: 'schema', - }, - key: 'id', - }, - allowNull: false, - }, - }); - }, - down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Person'); - }, -}; -``` +Migration history is tracked in a `SequelizeMeta` table that the CLI creates automatically in your database. -The next example is of a migration that uses async/await where you create a unique index on a new column, with a manually-managed transaction: +**Examples:** -```js -const { DataTypes } = require('@sequelize/core'); +```bash +# Run all pending migrations +npx sequelize migration run -module.exports = { - async up(queryInterface) { - const transaction = await queryInterface.sequelize.startUnmanagedTransaction(); - try { - await queryInterface.addColumn( - 'Person', - 'petName', - { - type: DataTypes.STRING, - }, - { transaction }, - ); - await queryInterface.addIndex('Person', 'petName', { - fields: 'petName', - unique: true, - transaction, - }); - await transaction.commit(); - } catch (err) { - await transaction.rollback(); - throw err; - } - }, - async down(queryInterface) { - const transaction = await queryInterface.sequelize.startUnmanagedTransaction(); - try { - await queryInterface.removeColumn('Person', 'petName', { transaction }); - await transaction.commit(); - } catch (err) { - await transaction.rollback(); - throw err; - } - }, -}; -``` +# Run only the next 2 pending migrations +npx sequelize migration run --step=2 -The next example is of a migration that creates a unique index composed of multiple fields with a condition, which allows a relation to exist multiple times but only one can satisfy the condition: +# Run all pending migrations up to (and including) a specific one +npx sequelize migration run --to=2026-01-02-create-posts +``` -```js -const { DataTypes } = require('@sequelize/core'); +#### JSON output -module.exports = { - up: queryInterface => { - queryInterface - .createTable('Person', { - name: DataTypes.STRING, - bool: { - type: DataTypes.BOOLEAN, - defaultValue: false, - }, - }) - .then((queryInterface, Sequelize) => { - queryInterface.addIndex('Person', ['name', 'bool'], { - type: 'UNIQUE', - where: { bool: 'true' }, - }); - }); - }, - down: queryInterface => { - return queryInterface.dropTable('Person'); - }, -}; +```bash +npx sequelize migration run --json +# { "migrated": ["2026-01-01-create-users", "2026-01-02-create-posts"] } ``` -## Running Migrations +--- + +### `migration undo` -Until this step, we haven't inserted anything into the database. We have just created the required model and migration files for our first model, `User`. Now to actually create that table in the database you need to run `db:migrate` command. +Reverts executed migrations. ```bash -# using npm -npx sequelize-cli db:migrate -# using yarn -yarn sequelize-cli db:migrate +npx sequelize migration undo [--step=] [--all] [--to=] ``` -This command will execute these steps: +**Flags:** -- Will ensure a table called `SequelizeMeta` in the database. This table is used to record which migrations have run on the current database -- Start looking for any migration files that haven't run yet. This is possible by checking `SequelizeMeta` table. In this case, it will run `XXXXXXXXXXXXXX-create-user.js` migration, which we created in the last step. -- Creates a table called `Users` with all columns as specified in its migration file. +| Flag | Default | Description | +| -------- | ------- | ----------------------------------------------------------------------------------------- | +| `--step` | `1` | Number of migrations to revert. Cannot be combined with `--all` or `--to`. | +| `--all` | `false` | Revert all executed migrations. | +| `--to` | — | Revert migrations down to and including this migration. Cannot be combined with `--step`. | -## Undoing Migrations +**Examples:** -Now our table has been created and saved in the database. With migration, you can revert to the old state by just running a command. +```bash +# Revert the last executed migration +npx sequelize migration undo -You can use `db:migrate:undo`, this command will revert the most recent migration. +# Revert the last 3 executed migrations +npx sequelize migration undo --step=3 -```bash -# using npm -npx sequelize-cli db:migrate:undo -# using yarn -yarn sequelize-cli db:migrate:undo +# Revert all executed migrations +npx sequelize migration undo --all + +# Revert down to (and including) a specific migration +npx sequelize migration undo --to=2026-01-02-create-posts ``` -You can revert to the initial state by undoing all migrations with the `db:migrate:undo:all` command. You can also revert to a specific migration by passing its name with the `--to` option. +#### JSON output ```bash -# using npm -npx sequelize-cli db:migrate:undo:all --to XXXXXXXXXXXXXX-create-posts.js -# using yarn -yarn sequelize-cli db:migrate:undo:all --to XXXXXXXXXXXXXX-create-posts.js +npx sequelize migration undo --json +# { "reverted": ["2026-01-03-create-comments"] } ``` -### Creating the first Seed - -Suppose we want to insert some data into a few tables by default. If we follow up on the previous example we can consider creating a demo user for the `User` table. +--- -To manage all data migrations you can use seeders. Seed files are some changes in data that can be used to populate database tables with sample or test data. +### `migration status` -Let's create a seed file that will add a demo user to our `User` table. +Shows which migrations have been executed and which are pending. ```bash -# using npm -npx sequelize-cli seed:generate --name demo-user -# using yarn -yarn sequelize-cli seed:generate --name demo-user +npx sequelize migration status ``` -This command will create a seed file in `seeders` folder. The file name will look something like `XXXXXXXXXXXXXX-demo-user.js`. It follows the same `up / down` semantics as the migration files. +**Example output:** -Now we should edit this file to insert the demo user to `User` table. - -```js -module.exports = { - up: (queryInterface, Sequelize) => { - return queryInterface.bulkInsert('Users', [ - { - firstName: 'John', - lastName: 'Doe', - email: 'example@example.com', - createdAt: new Date(), - updatedAt: new Date(), - }, - ]); - }, - down: (queryInterface, Sequelize) => { - return queryInterface.bulkDelete('Users', null, {}); - }, -}; ``` +Executed migrations: + ✔ 2026-01-01-create-users + ✔ 2026-01-02-create-posts -## Running Seeds +Pending migrations: + ○ 2026-01-03-create-comments +``` -In last step you created a seed file; however, it has not been committed to the database. To do that we run a simple command. +#### JSON output ```bash -# using npm -npx sequelize-cli db:seed:all -# using yarn -yarn sequelize-cli db:seed:all +npx sequelize migration status --json +# { "migrated": ["2026-01-01-create-users", "2026-01-02-create-posts"], "pending": ["2026-01-03-create-comments"] } ``` -This will execute that seed file and a demo user will be inserted into the `User` table. - -**Note:** _Seeder execution history is not stored anywhere, unlike migrations, which use the `SequelizeMeta` table. If you wish to change this behavior, please read the `Storage` section._ - -## Undoing Seeds +--- -Seeders can be undone if they are using any storage. There are two commands available for that: +## Writing migrations -If you wish to undo the most recent seed: +Each migration must export an `up` function (to apply the change) and an optional `down` function (to revert it). The `down` function is only required if you use `migration undo`. -```bash -# using npm -npx sequelize-cli db:seed:undo -# using yarn -yarn sequelize-cli db:seed:undo -``` +JavaScript migration functions receive a context object containing a `sequelize` instance. -If you wish to undo a specific seed: +The main tools for writing JavaScript migrations are the methods available on [`sequelize.queryInterface`](./other-topics/query-interface.md), +which provides a dialect-agnostic API for modifying the database schema and data. +You can also execute raw SQL queries with [`sequelize.query`](./querying/raw-queries.mdx). -```bash -# using npm -npx sequelize-cli db:seed:undo --seed name-of-seed-as-in-data -# using yarn -yarn sequelize-cli db:seed:undo --seed name-of-seed-as-in-data -``` +:::danger -If you wish to undo all seeds: +Never use Models inside migrations, as they do not reflect the current state of the database. -```bash -# using npm -npx sequelize-cli db:seed:undo:all -# using yarn -yarn sequelize-cli db:seed:undo:all -``` +::: -### The `.sequelizerc` file +### TypeScript -This is a special configuration file. It lets you specify the following options that you would usually pass as arguments to CLI: +```ts title="migrations/2026-01-01t00-00-00-create-users.ts" +import type { UmzugContext } from '@sequelize/cli'; -- `env`: The environment to run the command in -- `config`: The path to the config file -- `options-path`: The path to a JSON file with additional options -- `migrations-path`: The path to the migrations folder -- `seeders-path`: The path to the seeders folder -- `models-path`: The path to the models folder -- `url`: The database connection string to use. Alternative to using --config files -- `debug`: When available show various debug information +export async function up({ sequelize }: UmzugContext): Promise { + await sequelize.queryInterface.createTable('users', { + id: { type: 'INTEGER', primaryKey: true, autoIncrement: true }, + name: { type: 'VARCHAR(255)', allowNull: false }, + email: { type: 'VARCHAR(255)', allowNull: false, unique: true }, + }); +} -Some scenarios where you can use it: +export async function down({ sequelize }: UmzugContext): Promise { + await sequelize.queryInterface.dropTable('users'); +} +``` -- You want to override default path to `migrations`, `models`, `seeders` or `config` folder. -- You want to rename `config.json` to something else like `database.json` +### ESM (`.mjs`) -And a whole lot more. Let's see how you can use this file for custom configuration. +```js title="migrations/2026-01-01t00-00-00-create-users.mjs" +/** @type {import('@sequelize/cli').MigrationFunction} */ +export async function up({ sequelize }) { + await sequelize.queryInterface.createTable('users', { + id: { type: 'INTEGER', primaryKey: true, autoIncrement: true }, + name: { type: 'VARCHAR(255)', allowNull: false }, + email: { type: 'VARCHAR(255)', allowNull: false, unique: true }, + }); +} -To begin, let's create the `.sequelizerc` file in the root directory of your project, with the following content: +/** @type {import('@sequelize/cli').MigrationFunction} */ +export async function down({ sequelize }) { + await sequelize.queryInterface.dropTable('users'); +} +``` -```js -// .sequelizerc +### CommonJS (`.cjs`) -const path = require('path'); +```js title="migrations/2026-01-01t00-00-00-create-users.cjs" +'use strict'; module.exports = { - config: path.resolve('config', 'database.json'), - 'models-path': path.resolve('db', 'models'), - 'seeders-path': path.resolve('db', 'seeders'), - 'migrations-path': path.resolve('db', 'migrations'), + /** @type {import('@sequelize/cli').MigrationFunction} */ + async up({ sequelize }) { + await sequelize.queryInterface.createTable('users', { + id: { type: 'INTEGER', primaryKey: true, autoIncrement: true }, + name: { type: 'VARCHAR(255)', allowNull: false }, + email: { type: 'VARCHAR(255)', allowNull: false, unique: true }, + }); + }, + + /** @type {import('@sequelize/cli').MigrationFunction} */ + async down({ sequelize }) { + await sequelize.queryInterface.dropTable('users'); + }, }; ``` -With this config, you are telling the CLI to: +### SQL -- Use `config/database.json` file for config settings; -- Use `db/models` as models folder; -- Use `db/seeders` as seeders folder; -- Use `db/migrations` as the migrations folder. +SQL migrations are directories containing an `up.sql` file and optionally a `down.sql` file. Both files contain raw SQL that is executed directly against the database. -### Dynamic configuration +```sql title="migrations/2026-01-01t00-00-00-create-users/up.sql" +CREATE TABLE users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL UNIQUE +); +``` -The configuration file is by default a JSON file called `config.json`. But sometimes you need a dynamic configuration, for example, to access environment variables or execute some other code to determine the configuration. +```sql title="migrations/2026-01-01t00-00-00-create-users/down.sql" +DROP TABLE users; +``` -Thankfully, the Sequelize CLI can read from both `.json` and `.js` files. This can be set up with `.sequelizerc` file. You just have to provide the path to your `.js` file as the `config` option of your exported object: +If there is no `down.sql` file, `migration undo` will throw an error for that migration. -```js -const path = require('path'); +:::tip -module.exports = { - config: path.resolve('config', 'config.js'), -}; -``` +The CLI also supports flat `.sql` files (e.g. `migrations/2026-01-01t00-00-00-create-users.sql`) as up-only migrations. These cannot be reverted. -Now the Sequelize CLI will load `config/config.js` for getting configuration options. +::: -An example of `config/config.js` file: +--- -```js -const fs = require('fs'); +## Seed commands -module.exports = { - development: { - username: 'database_dev', - password: 'database_dev', - database: 'database_dev', - host: '127.0.0.1', - port: 3306, - dialect: 'mysql', - dialectOptions: { - bigNumberStrings: true, - }, - }, - test: { - username: process.env.CI_DB_USERNAME, - password: process.env.CI_DB_PASSWORD, - database: process.env.CI_DB_NAME, - host: '127.0.0.1', - port: 3306, - dialect: 'mysql', - dialectOptions: { - bigNumberStrings: true, - }, - }, - production: { - username: process.env.PROD_DB_USERNAME, - password: process.env.PROD_DB_PASSWORD, - database: process.env.PROD_DB_NAME, - host: process.env.PROD_DB_HOSTNAME, - port: process.env.PROD_DB_PORT, - dialect: 'mysql', - dialectOptions: { - bigNumberStrings: true, - ssl: { - ca: fs.readFileSync(__dirname + '/mysql-ca-main.crt'), - }, - }, - }, -}; -``` +Seeds are files used to populate your database with sample or test data. The CLI can generate seed file scaffolds in the same formats as migrations. -The example above also shows how to add custom dialect options to the configuration. +:::note -### Using Babel +The CLI currently only provides a `seed generate` command. Running and reverting seeds is not yet built into the CLI. -To enable more modern constructions in your migrations and seeders, you can simply install `babel-register` and require it at the beginning of `.sequelizerc`: +::: + +### `seed generate` + +Generates a new seed file in the configured `seedFolder`. ```bash -# using npm -npm i --save-dev babel-register -# using yarn -yarn add babel-register --dev +npx sequelize seed generate --format= [--name=] ``` -```js -// .sequelizerc +**Flags:** -require('babel-register'); +| Flag | Required | Default | Description | +| ---------- | -------- | ----------- | ------------------------------------------------------- | +| `--format` | Yes | — | File format: `sql`, `typescript`, `cjs`, or `esm`. | +| `--name` | No | `"unnamed"` | A short descriptive name, used as part of the filename. | -const path = require('path'); +**Examples:** -module.exports = { - config: path.resolve('config', 'config.json'), - 'models-path': path.resolve('models'), - 'seeders-path': path.resolve('seeders'), - 'migrations-path': path.resolve('migrations'), -}; +```bash +npx sequelize seed generate --format=typescript --name=demo-users +npx sequelize seed generate --format=sql --name=demo-users ``` -Of course, the outcome will depend upon your babel configuration (such as in a `.babelrc` file). Learn more at [babeljs.io](https://babeljs.io). - -### Security tip +#### JSON output -Use environment variables for config settings. This is because secrets such as passwords should never be part of the source code (and especially not committed to version control). +```bash +npx sequelize seed generate --format=typescript --name=demo-users --json +# { "path": "/path/to/seeds/2026-04-12t14-30-00-demo-users.ts" } +``` -### Storage +--- -There are three types of storage that you can use: `sequelize`, `json`, and `none`. +## Writing seeds -- `sequelize` : stores migrations and seeds in a table on the sequelize database -- `json` : stores migrations and seeds on a json file -- `none` : does not store any migration/seed +Seed files follow the same structure as migration files: they export `up` and `down` functions. -#### Migration Storage +### TypeScript -By default, the CLI will create a table in your database called `SequelizeMeta` containing an entry for each executed migration. To change this behavior, there are three options you can add to the configuration file. Using `migrationStorage`, you can choose the type of storage to be used for migrations. If you choose `json`, you can specify the path of the file using `migrationStoragePath` or the CLI will write to the file `sequelize-meta.json`. If you want to keep the information in the database, using `sequelize`, but want to use a different table, you can change the table name using `migrationStorageTableName`. Also, you can define a different schema for the `SequelizeMeta` table by providing the `migrationStorageTableSchema` property. +```ts title="seeds/2026-01-01t00-00-00-demo-users.ts" +import type { UmzugContext } from '@sequelize/cli'; -```json -{ - "development": { - "username": "root", - "password": null, - "database": "database_development", - "host": "127.0.0.1", - "dialect": "mysql", +export async function up({ sequelize }: UmzugContext): Promise { + await sequelize.queryInterface.bulkInsert('users', [ + { name: 'Alice', email: 'alice@example.com' }, + { name: 'Bob', email: 'bob@example.com' }, + ]); +} - // Use a different storage type. Default: sequelize - "migrationStorage": "json", +export async function down({ sequelize }: UmzugContext): Promise { + await sequelize.queryInterface.bulkDelete('users', {}); +} +``` - // Use a different file name. Default: sequelize-meta.json - "migrationStoragePath": "sequelizeMeta.json", +### SQL - // Use a different table name. Default: SequelizeMeta - "migrationStorageTableName": "sequelize_meta", +```sql title="seeds/2026-01-01t00-00-00-demo-users/up.sql" +INSERT INTO users (name, email) VALUES + ('Alice', 'alice@example.com'), + ('Bob', 'bob@example.com'); +``` - // Use a different schema for the SequelizeMeta table - "migrationStorageTableSchema": "custom_schema" - } -} +```sql title="seeds/2026-01-01t00-00-00-demo-users/down.sql" +DELETE FROM users WHERE email IN ('alice@example.com', 'bob@example.com'); ``` -**Note:** _The `none` storage is not recommended as a migration storage. If you decide to use it, be aware of the implications of having no record of what migrations did or didn't run._ +--- -#### Seed Storage +## Interactive mode -By default, the CLI will not save any seed that is executed. If you choose to change this behavior (!), you can use `seederStorage` in the configuration file to change the storage type. If you choose `json`, you can specify the path of the file using `seederStoragePath` or the CLI will write to the file `sequelize-data.json`. If you want to keep the information in the database, using `sequelize`, you can specify the table name using `seederStorageTableName`, or it will default to `SequelizeData`. +By default, the CLI runs in interactive mode. When a required flag is not provided on the command line, you will be prompted to enter it. -```json -{ - "development": { - "username": "root", - "password": null, - "database": "database_development", - "host": "127.0.0.1", - "dialect": "mysql", - // Use a different storage. Default: none - "seederStorage": "json", - // Use a different file name. Default: sequelize-data.json - "seederStoragePath": "sequelizeData.json", - // Use a different table name. Default: SequelizeData - "seederStorageTableName": "sequelize_data" - } -} +To disable interactive prompts (e.g. in CI), pass `--no-interactive`: + +```bash +npx sequelize migration generate --format=typescript --name=create-users --no-interactive ``` -### Configuration Connection String +--- -As an alternative to the `--config` option with configuration files defining your database, you can use the `--url` option to pass in a connection string. For example: +## JSON output + +All commands support a `--json` flag that outputs the result as machine-readable JSON instead of human-readable text. This is useful for scripting or programmatic integration. ```bash -# using npm -npx sequelize-cli db:migrate --url 'mysql://root:password@mysql_host.com/database_name' -# using yarn -yarn sequelize-cli db:migrate --url 'mysql://root:password@mysql_host.com/database_name' +npx sequelize migration run --json +npx sequelize migration undo --json +npx sequelize migration status --json +npx sequelize migration generate --format=sql --name=create-users --json +npx sequelize seed generate --format=typescript --name=demo-users --json ``` -If utilizing `package.json` scripts with npm, make sure to use the extra `--` in your command when using flags. -For example: +When a command fails, the JSON output will contain an `error` object: ```json -// package.json - -... - "scripts": { - "migrate:up": "npx sequelize-cli db:migrate", - "migrate:undo": "npx sequelize-cli db:migrate:undo" - }, -... +{ "error": { "message": "Migration folder not found at path \"/app/migrations\"" } } ``` -Use the command like so: `npm run migrate:up -- --url ` +--- + +## Programmatic API + +All CLI functionality is also available as a Node.js API exported from `@sequelize/cli`. This allows you to integrate Sequelize migrations directly into your application code or custom scripts. + +```ts +import { + runMigrations, + undoMigrations, + getMigrationStatus, + generateMigration, + generateSeed, +} from '@sequelize/cli'; -### Programmatic usage +// Run all pending migrations +const applied = await runMigrations(); -Sequelize has a sister library called [umzug](https://github.com/sequelize/umzug) for programmatically handling execution and logging of migration tasks. +// Run up to a specific migration +await runMigrations({ to: '2026-01-02-create-posts' }); + +// Run only 1 pending migration +await runMigrations({ step: 1 }); + +// Undo the last migration (default) +await undoMigrations(); + +// Undo the last 3 migrations +await undoMigrations({ step: 3 }); + +// Undo all migrations +await undoMigrations({ to: 0 }); + +// Undo down to (and including) a specific migration +await undoMigrations({ to: '2026-01-02-create-posts' }); + +// Check migration status +const { executed, pending } = await getMigrationStatus(); + +// Generate a new migration file +const migrationPath = await generateMigration({ + format: 'typescript', + migrationName: 'create-users', + migrationFolder: '/app/migrations', +}); + +// Generate a new seed file +const seedPath = await generateSeed({ + format: 'typescript', + seedName: 'demo-users', + seedFolder: '/app/seeds', +}); +``` diff --git a/docs/models/migrations.md b/docs/models/migrations.md index 3797bd321..aac9c7594 100644 --- a/docs/models/migrations.md +++ b/docs/models/migrations.md @@ -25,7 +25,7 @@ Of course, you are free to use any other migration tool: - [Atlas](https://github.com/ariga/atlas) provides built-in integration for Sequelize, including automatic migration planning, migration linting, schema diffing, and more. Read more in [Atlas/Sequelize portal](https://atlasgo.io/guides/orms/sequelize). - [Umzug](https://github.com/sequelize/umzug) is a great alternative that the Sequelize CLI uses under the hood. -- Third-party tools that can be used to help with migrations are also listed on the [Third-Party Resources](../other-topics/resources.md#migrations) page. +- Third-party tools that can be used to help with migrations are also listed on the [Third Party Resources](../other-topics/resources.md) page. ## Using a Database Diff Tool diff --git a/docs/other-topics/query-interface.md b/docs/other-topics/query-interface.md index 80d441c88..8b946e67a 100644 --- a/docs/other-topics/query-interface.md +++ b/docs/other-topics/query-interface.md @@ -2,26 +2,96 @@ title: Query Interface --- -An instance of Sequelize uses something called **Query Interface** to communicate to the database in a dialect-agnostic way. Most of the methods you've learned in this manual are implemented with the help of several methods from the query interface. +The **Query Interface** is a low-level API that Sequelize uses internally to communicate with the database in a dialect-agnostic way. +It is primarily useful in contexts where models are not available, such as database migrations. -The methods from the query interface are therefore lower-level methods; you should use them only if you do not find another way to do it with higher-level APIs from Sequelize. They are, of course, still higher-level than running raw queries directly (i.e., writing SQL by hand). +The Query Interface can be considered as the step between model methods and raw SQL queries. -This guide shows a few examples, but for the full list of what it can do, and for detailed usage of each method, check the [QueryInterface API](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html). +:::note + +Only APIs that are considered stable and well-designed for end users are documented here. +Other APIs are being progressively redesigned and will be documented as they become ready. + +::: ## Obtaining the query interface -From now on, we will call `queryInterface` the singleton instance of the [QueryInterface](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html) class, which is available on your Sequelize instance: +The query interface is available on your Sequelize instance: ```js -import { Sequelize, DataTypes } from '@sequelize/core'; +import { Sequelize } from '@sequelize/core'; + const sequelize = new Sequelize(/* ... */); -const queryInterface = sequelize.getQueryInterface(); +const queryInterface = sequelize.queryInterface; +``` + +For the full API reference, see the [QueryInterface API](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html). + +## Database management + +These methods let you create and manage databases. +They are dialect-specific and not all methods are supported by every dialect. + +Relevant API: +[`createDatabase`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#createdatabase), +[`dropDatabase`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#dropdatabase), +[`listDatabases`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#listdatabases), + +```js +// Create a database +await queryInterface.createDatabase('mydb', { charset: 'utf8mb4' }); + +// Drop a database +await queryInterface.dropDatabase('mydb'); + +// List all databases +const databases = await queryInterface.listDatabases(); +// => [{ name: 'mydb' }, ...] ``` -## Creating a table +## Schema management + +Schemas are namespaces that can contain tables (what MySQL/MariaDB call "databases"). + +Relevant API: +[`createSchema`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#createschema), +[`dropSchema`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#dropschema), +[`listSchemas`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#listschemas), +[`dropAllSchemas`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#dropallschemas) ```js -queryInterface.createTable('Person', { +// Create a schema +await queryInterface.createSchema('myschema'); + +// Drop a schema +await queryInterface.dropSchema('myschema'); + +// List all schemas +const schemas = await queryInterface.listSchemas(); +// => ['public', 'myschema'] + +// Drop all schemas (use with care!) +await queryInterface.dropAllSchemas({ + // optionally skip certain schemas + skip: ['public'], +}); +``` + +## Table management + +### Creating a table + +Relevant API: [`createTable`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#createtable) + +```js +import { DataTypes } from '@sequelize/core'; + +await queryInterface.createTable('people', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, name: DataTypes.STRING, isBetaMember: { type: DataTypes.BOOLEAN, @@ -33,33 +103,139 @@ queryInterface.createTable('Person', { Generated SQL (using SQLite): -```SQL -CREATE TABLE IF NOT EXISTS `Person` ( +```sql +CREATE TABLE IF NOT EXISTS `people` ( + `id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` VARCHAR(255), `isBetaMember` TINYINT(1) NOT NULL DEFAULT 0 ); ``` -**Note:** Consider defining a Model instead and calling `YourModel.sync()` instead, which is a higher-level approach. +### Listing and checking tables -## Adding a column to a table +Relevant API: +[`listTables`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#listtables), +[`tableExists`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#tableexists) ```js -queryInterface.addColumn('Person', 'petName', { type: DataTypes.STRING }); +// List all tables in the current schema +const tables = await queryInterface.listTables(); +// => [{ tableName: 'people', schema: 'public' }, ...] + +// Check whether a table exists +const exists = await queryInterface.tableExists('people'); +// => true +``` + +### Describing a table + +Relevant API: [`describeTable`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#describetable) + +Returns the full column definitions for a table: + +```js +const columns = await queryInterface.describeTable('people'); +``` + +Example output: + +```js +{ + id: { + type: 'INTEGER', + allowNull: false, + defaultValue: null, + primaryKey: true, + autoIncrement: true, + comment: null, + }, + name: { + type: 'VARCHAR(255)', + allowNull: true, + defaultValue: null, + primaryKey: false, + autoIncrement: false, + comment: null, + }, +} +``` + +### Renaming a table + +Relevant API: [`renameTable`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#renametable) + +```js +await queryInterface.renameTable('people', 'User'); +``` + +### Dropping tables + +Relevant API: +[`dropTable`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#droptable), +[`dropAllTables`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#dropalltables) + +```js +// Drop a single table +await queryInterface.dropTable('people'); + +// Drop all tables in the current schema (use with care!) +await queryInterface.dropAllTables({ + // optionally skip certain tables + skip: ['migrations'], +}); +``` + +### Truncating a table + +Relevant API: [`truncate`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#truncate) + +Deletes all rows but keeps the table structure: + +```js +await queryInterface.truncate('people'); +``` + +## Column management + +### Adding a column + +Relevant API: [`addColumn`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#addcolumn) + +```js +await queryInterface.addColumn('people', 'petName', { + type: DataTypes.STRING, + allowNull: true, +}); ``` Generated SQL (using SQLite): ```sql -ALTER TABLE `Person` ADD `petName` VARCHAR(255); +ALTER TABLE `people` ADD `petName` VARCHAR(255); ``` -## Changing the datatype of a column +### Removing a column + +Relevant API: [`removeColumn`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#removecolumn) + +```js +await queryInterface.removeColumn('people', 'petName'); +``` + +Generated SQL (using PostgreSQL): + +```sql +ALTER TABLE "public"."people" DROP COLUMN "petName"; +``` + +### Changing a column + +Relevant API: [`changeColumn`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#changecolumn) ```js -queryInterface.changeColumn('Person', 'foo', { +await queryInterface.changeColumn('people', 'age', { type: DataTypes.FLOAT, - defaultValue: 3.14, + defaultValue: 0, allowNull: false, }); ``` @@ -67,90 +243,217 @@ queryInterface.changeColumn('Person', 'foo', { Generated SQL (using MySQL): ```sql -ALTER TABLE `Person` CHANGE `foo` `foo` FLOAT NOT NULL DEFAULT 3.14; +ALTER TABLE `people` CHANGE `age` `age` FLOAT NOT NULL DEFAULT 0; ``` -## Removing a column +### Renaming a column + +Relevant API: [`renameColumn`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#renamecolumn) + +```js +await queryInterface.renameColumn('people', 'petName', 'animalName'); +``` + +:::note SQLite limitations + +SQLite does not natively support altering or removing columns. Sequelize works around this by recreating the whole table using a temporary backup table, inspired by [the SQLite documentation](https://www.sqlite.org/lang_altertable.html#otheralter). + +::: + +## Index management + +### Adding an index + +Relevant API: [`addIndex`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#addindex) ```js -queryInterface.removeColumn('Person', 'petName', { - /* query options */ +// Simple index +await queryInterface.addIndex('people', ['name']); + +// Unique index with a custom name +await queryInterface.addIndex('people', { + fields: ['email'], + unique: true, + name: 'people_email_unique', +}); + +// Partial index (PostgreSQL) +await queryInterface.addIndex('people', { + fields: ['email'], + unique: true, + where: { active: true }, }); ``` -Generated SQL (using PostgreSQL): +### Removing an index + +Relevant API: [`removeIndex`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#removeindex) + +```js +// By index name +await queryInterface.removeIndex('people', 'people_email_unique'); -```SQL -ALTER TABLE "public"."Person" DROP COLUMN "petName"; +// By column list (Sequelize will infer the index name) +await queryInterface.removeIndex('people', ['email']); ``` -## Changing and removing columns in SQLite +### Listing indexes -SQLite does not support directly altering and removing columns. However, Sequelize will try to work around this by recreating the whole table with the help of a backup table, inspired by [these instructions](https://www.sqlite.org/lang_altertable.html#otheralter). +Relevant API: [`showIndex`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#showindex) -For example: +```js +const indexes = await queryInterface.showIndex('people'); +``` + +Example output: ```js -// Assuming we have a table in SQLite created as follows: -queryInterface.createTable('Person', { - name: DataTypes.STRING, - isBetaMember: { - type: DataTypes.BOOLEAN, - defaultValue: false, - allowNull: false, +[ + { + name: 'people_email_unique', + unique: true, + primary: false, + fields: [{ attribute: 'email', order: 'ASC', length: undefined, collate: undefined }], + includes: undefined, + tableName: 'people', + type: undefined, }, - petName: DataTypes.STRING, - foo: DataTypes.INTEGER, +]; +``` + +## Constraint management + +### Adding a constraint + +Relevant API: [`addConstraint`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#addconstraint) + +```js +// UNIQUE constraint +await queryInterface.addConstraint('people', { + fields: ['email'], + type: 'UNIQUE', + name: 'people_email_unique', }); -// And we change a column: -queryInterface.changeColumn('Person', 'foo', { - type: DataTypes.FLOAT, - defaultValue: 3.14, - allowNull: false, +// CHECK constraint (not supported by MySQL) +await queryInterface.addConstraint('people', { + fields: ['age'], + type: 'CHECK', + where: { age: { [Op.gte]: 0 } }, + name: 'people_age_positive', +}); + +// PRIMARY KEY constraint +await queryInterface.addConstraint('people', { + fields: ['id'], + type: 'PRIMARY KEY', + name: 'people_pk', +}); + +// FOREIGN KEY constraint +await queryInterface.addConstraint('posts', { + fields: ['userId'], + type: 'FOREIGN KEY', + name: 'post_user_fkey', + references: { + table: 'people', + field: 'id', + }, + onDelete: 'CASCADE', + onUpdate: 'CASCADE', }); ``` -The following SQL calls are generated for SQLite: +### Listing constraints -```sql -PRAGMA TABLE_INFO(`Person`); +Relevant API: [`showConstraints`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#showconstraints) -CREATE TABLE IF NOT EXISTS `Person_backup` ( - `name` VARCHAR(255), - `isBetaMember` TINYINT(1) NOT NULL DEFAULT 0, - `foo` FLOAT NOT NULL DEFAULT '3.14', - `petName` VARCHAR(255) -); +```js +const constraints = await queryInterface.showConstraints('people'); +``` -INSERT INTO `Person_backup` - SELECT - `name`, - `isBetaMember`, - `foo`, - `petName` - FROM `Person`; +Example output: + +```js +[ + { + constraintName: 'people_email_unique', + constraintType: 'UNIQUE', + tableName: 'people', + tableSchema: 'public', + constraintSchema: 'public', + columnNames: ['email'], + }, +]; +``` -DROP TABLE `Person`; +You can filter by constraint type or column: -CREATE TABLE IF NOT EXISTS `Person` ( - `name` VARCHAR(255), - `isBetaMember` TINYINT(1) NOT NULL DEFAULT 0, - `foo` FLOAT NOT NULL DEFAULT '3.14', - `petName` VARCHAR(255) -); +```js +// Only foreign key constraints +const fks = await queryInterface.showConstraints('posts', { + constraintType: 'FOREIGN KEY', +}); + +// Constraints on a specific column +const colConstraints = await queryInterface.showConstraints('people', { + columnName: 'email', +}); +``` + +### Removing a constraint + +Relevant API: [`removeConstraint`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#removeconstraint) + +```js +await queryInterface.removeConstraint('people', 'people_email_unique'); +``` -INSERT INTO `Person` - SELECT - `name`, - `isBetaMember`, - `foo`, - `petName` - FROM `Person_backup`; +### Deferring constraints -DROP TABLE `Person_backup`; +Relevant API: [`deferConstraints`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#deferconstraints) + +For dialects that support deferrable constraints, you can defer constraint checking within a transaction: + +```js +import { ConstraintChecking } from '@sequelize/core'; + +// Defer all constraints until the end of the transaction +await sequelize.transaction(async () => { + await queryInterface.deferConstraints(ConstraintChecking.DEFERRED()); + + // ... perform operations that would temporarily violate constraints +}); + +// Or defer only specific named constraints: +await sequelize.transaction(async () => { + await queryInterface.deferConstraints(ConstraintChecking.DEFERRED(['post_user_fkey'])); +}); ``` -## Other +## Miscellaneous + +### Disabling foreign key checks + +Relevant API: [`withoutForeignKeyChecks`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#withoutforeignkeychecks) -As mentioned in the beginning of this guide, there is a lot more to the Query Interface available in Sequelize! Check the [QueryInterface API](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html) for a full list of what can be done. +Use `withoutForeignKeyChecks` to safely perform bulk operations (such as truncating tables) that would otherwise violate foreign key constraints. Sequelize will automatically re-enable foreign key checks after the callback completes, even if it throws. + +```js +await queryInterface.withoutForeignKeyChecks(async connection => { + await queryInterface.truncate('posts', { connection }); + await queryInterface.truncate('people', { connection }); +}); +``` + +You must use the provided `connection` for all queries inside the callback to ensure they run on the same database connection (foreign key checks are connection-scoped in most databases). + +### Getting the server version + +Relevant API: [`fetchDatabaseVersion`](pathname:///api/v7/classes/_sequelize_core.index.AbstractQueryInterface.html#fetchdatabaseversion) + +```ts +// Get the database server version +const version = await queryInterface.fetchDatabaseVersion(); +// => '8.0.32' +``` diff --git a/docs/other-topics/resources.md b/docs/other-topics/resources.md index cdc84ffd1..a85d741b3 100644 --- a/docs/other-topics/resources.md +++ b/docs/other-topics/resources.md @@ -6,52 +6,31 @@ A curated list of awesome projects surrounding Sequelize. ## Integrations -- [sequelize-typescript](https://www.npmjs.com/package/sequelize-typescript) - Decorators and some other features for sequelize (built-in as of Sequelize 7). - [Sequelize-Nest](https://docs.nestjs.com/recipes/sql-sequelize) - Sequelize integration in [nest](https://github.com/nestjs/nest). -- [sequelizejs-decorators](https://www.npmjs.com/package/sequelizejs-decorators) decorators for composing sequelize models. - [kysely-sequelize](https://www.npmjs.com/package/kysely-sequelize) - A toolkit (dialect, type translators, etc.) that allows using your existing Sequelize instance with [Kysely](https://www.kysely.dev). ## Code generation & visualisers - [sequelize-ui](https://github.com/tomjschuster/sequelize-ui) - Online tool for building models, relations and more. - [sequelizer](https://github.com/andyforever/sequelizer) - A GUI Desktop App for generating Sequelize models. Support for Mysql, Mariadb, Postgres, Sqlite, Mssql. -- [sequelize-auto](https://github.com/sequelize/sequelize-auto) Generating models for SequelizeJS via the command line is another choice. - [pg-generator](https://pg-generator.com/v4/builtin-templates--nc,d1/sequelize.html) - Auto generate/scaffold Sequelize models for PostgreSQL database. - [meteor modeler](https://www.datensen.com/) - Desktop tool for visual definition of Sequelize models and associations. -- [sequel-ace-typescript-bundles](https://github.com/binlabs/sequel-ace-typescript-bundles) - A plugin for Sequel Ace that allows generation of Sequelize models from selected database tables. - [hatchify](https://github.com/bitovi/hatchify) - Schema driven Node CRUD API and React Web UI including Sequelize based ORM. -## Performance - -- [dataloader-sequelize](https://www.npmjs.com/package/dataloader-sequelize) - Batching, caching and simplification of Sequelize with facebook/dataloader -- [sequelize-transparent-cache](https://github.com/DanielHreben/sequelize-transparent-cache) - -## Migrations - -- [umzug](https://github.com/sequelize/umzug) - framework-agnostic migration tool for Node. -- [sequelize-cli](https://github.com/sequelize/cli) - The Sequelize Command Line Interface. Includes umzug-based migrations. -- [sequelize-mig](https://github.com/MRVMV/sequelize-mig) - Sequelize migration generator -- [sequelizemm](https://github.com/hasinoorit/sequelizemm) - CLI tool to generate a migration script from models - ## Miscellaneous -- [sequelize-pg-utilities](https://github.com/davesag/sequelize-pg-utilities) - Opinionated set of database utilities. -- [sequelize-test-helpers](https://github.com/davesag/sequelize-test-helpers) - A collection of utilities to help with unit-testing Sequelize models and code that needs those models. -- [Sequelize-fixtures](https://github.com/domasx2/sequelize-fixtures) - Simple lib to load data to database using sequelize. +- [sequelize-cursor-pagination](https://github.com/ephys/sequelize-cursor-pagination) - Cursor based pagination for Sequelize. - [SequelizeGuard](https://github.com/lotivo/sequelize-acl) - Role, Permission based Authorization for Sequelize. -- [sequelize-bcrypt](https://github.com/mattiamalonni/sequelize-bcrypt) - Utility to integrate bcrypt into sequelize models -- [sequelize-temporal](https://github.com/bonaval/sequelize-temporal) - Temporal tables (aka historical records) -- [sequelize-joi](https://github.com/mattiamalonni/sequelize-joi) - Allows specifying [Joi](https://github.com/sideway/joi) validation schema for model attributes in Sequelize. -- [sequelize-slugify](https://www.npmjs.com/package/sequelize-slugify) - Add slugs to sequelize models -- [sequelize-tokenify](https://github.com/pipll/sequelize-tokenify) - Add unique tokens to sequelize models -- [sqlcommenter-sequelize](https://github.com/google/sqlcommenter/tree/master/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-sequelize) A [sqlcommenter](https://google.github.io/sqlcommenter/) plugin with [support for Sequelize](https://google.github.io/sqlcommenter/node/sequelize/) to augment SQL statements with comments that can be used later to correlate application code with SQL statements. -- [@rematter/sequelize-paranoid-delete](https://www.npmjs.com/package/@rematter/sequelize-paranoid-delete) - Enables onDelete when using paranoid mode. -- [@hatchifyjs/sequelize-create-with-associations](https://github.com/bitovi/sequelize-create-with-associations) - Automatically creates, bulkCreates and updates records that have relationships to each other without extra code. +- [umzug](https://github.com/sequelize/umzug) - framework-agnostic migration tool for Node. +- [dataloader-sequelize](https://www.npmjs.com/package/dataloader-sequelize) - Batching, caching and simplification of Sequelize with facebook/dataloader ## Outdated These libraries haven't been updated in a long time, and may not work with newer versions of Sequelize +- [sequelizejs-decorators](https://www.npmjs.com/package/sequelizejs-decorators) decorators for composing sequelize models (built-in as of Sequelize 7). +- [sequelize-typescript](https://www.npmjs.com/package/sequelize-typescript) - Decorators and some other features for sequelize (built-in as of Sequelize 7). +- [sequelize-cli](https://github.com/sequelize/cli) - The Sequelize Command Line Interface. Includes umzug-based migrations (replaced with `@sequelize/cli`). - [sequelize-transforms](https://www.npmjs.com/package/sequelize-transforms) - Add configurable attribute transforms. - [Sequelize-fixture](https://github.com/xudejian/sequelize-fixture) - [Fixer](https://github.com/olalonde/fixer) @@ -61,3 +40,18 @@ These libraries haven't been updated in a long time, and may not work with newer - [sequelize-autoload](https://github.com/boxsnake-nodejs/sequelize-autoload) - An autoloader for Sequelize, inspired by [PSR-0](https://www.php-fig.org/psr/psr-0/) and [PSR-4](https://www.php-fig.org/psr/psr-4/). - [sequelize-deep-update](https://www.npmjs.com/package/sequelize-deep-update) - Update a sequelize instance and its included associated instances with new properties. - [sequelize-noupdate-attributes](https://www.npmjs.com/package/sequelize-noupdate-attributes) - Adds no update/readonly attributes support to models. +- [sequelize-pg-utilities](https://github.com/davesag/sequelize-pg-utilities) - Opinionated set of database utilities. +- [sequelize-test-helpers](https://github.com/davesag/sequelize-test-helpers) - A collection of utilities to help with unit-testing Sequelize models and code that needs those models. +- [Sequelize-fixtures](https://github.com/domasx2/sequelize-fixtures) - Simple lib to load data to database using sequelize. +- [sequelize-bcrypt](https://github.com/mattiamalonni/sequelize-bcrypt) - Utility to integrate bcrypt into sequelize models +- [sequelize-temporal](https://github.com/bonaval/sequelize-temporal) - Temporal tables (aka historical records) +- [sequelize-joi](https://github.com/mattiamalonni/sequelize-joi) - Allows specifying [Joi](https://github.com/sideway/joi) validation schema for model attributes in Sequelize. +- [sequelize-slugify](https://www.npmjs.com/package/sequelize-slugify) - Add slugs to sequelize models +- [sequelize-tokenify](https://github.com/pipll/sequelize-tokenify) - Add unique tokens to sequelize models +- [sqlcommenter-sequelize](https://github.com/google/sqlcommenter/tree/master/nodejs/sqlcommenter-nodejs/packages/sqlcommenter-sequelize) A [sqlcommenter](https://google.github.io/sqlcommenter/) plugin with [support for Sequelize](https://google.github.io/sqlcommenter/node/sequelize/) to augment SQL statements with comments that can be used later to correlate application code with SQL statements. +- [sequelize-mig](https://github.com/MRVMV/sequelize-mig) - Sequelize migration generator +- [@hatchifyjs/sequelize-create-with-associations](https://github.com/bitovi/sequelize-create-with-associations) - Automatically creates, bulkCreates and updates records that have relationships to each other without extra code. +- [sequelizemm](https://github.com/hasinoorit/sequelizemm) - CLI tool to generate a migration script from models +- [sequelize-transparent-cache](https://github.com/DanielHreben/sequelize-transparent-cache) +- [sequelize-auto](https://github.com/sequelize/sequelize-auto) Generating models for SequelizeJS via the command line is another choice. +- [sequel-ace-typescript-bundles](https://github.com/binlabs/sequel-ace-typescript-bundles) - A plugin for Sequel Ace that allows generation of Sequelize models from selected database tables. diff --git a/docs/other-topics/upgrade.md b/docs/other-topics/upgrade.md index b1f7bc759..e4546cf27 100644 --- a/docs/other-topics/upgrade.md +++ b/docs/other-topics/upgrade.md @@ -752,6 +752,38 @@ Because generated foreign key names are inferred from the association name, this means that foreign keys are now in camelCase by default too. For instance, the association `Project.belongsTo(User)` now has the name `user` and the generated foreign key is `userId`. +### The CLI has been completely rewritten + +The Sequelize CLI has been completely rewritten from scratch for v7 and is now published as `@sequelize/cli` (replacing the old `sequelize-cli` package). + +Key changes at a glance: + +- **New package name:** `@sequelize/cli` (install with `npm install --save-dev @sequelize/cli`) +- **New binary name:** `sequelize` (was `sequelize-cli`) +- **New commands:** command names have changed — see the table below +- **New config format:** replaces `config/config.json` with a `sequelize.config.js` (or `.sequelizerc`) file discovered via [cosmiconfig](https://github.com/cosmiconfig/cosmiconfig) +- **New migration signature:** migration functions now receive `{ sequelize }` instead of `(queryInterface, Sequelize)` +- **Multiple file formats:** migrations and seeds can be written in TypeScript (`.ts`), ESM (`.mjs`), CommonJS (`.cjs`), or raw SQL (directory with `up.sql` / `down.sql`) +- **`--json` flag:** all commands support structured JSON output for scripting +- **Programmatic API:** all commands are exposed as importable functions from `@sequelize/cli` + +**Command mapping from v6 to v7:** + +| v6 (`sequelize-cli`) | v7 (`@sequelize/cli`) | +| ----------------------------------- | ------------------------------------------------ | +| `sequelize-cli db:migrate` | `sequelize migration run` | +| `sequelize-cli db:migrate:undo` | `sequelize migration undo` | +| `sequelize-cli db:migrate:undo:all` | `sequelize migration undo --all` | +| `sequelize-cli migration:generate` | `sequelize migration generate --format=` | +| `sequelize-cli seed:generate` | `sequelize seed generate --format=` | +| `sequelize-cli db:seed:all` | _(not yet available)_ | +| `sequelize-cli db:seed:undo` | _(not yet available)_ | +| `sequelize-cli init` | _(removed)_ | +| `sequelize-cli model:generate` | _(removed)_ | +| `sequelize-cli db:create` | _(removed)_ | + +See the [CLI documentation](../cli.md) for full details. + ## Minor Breaking changes These are less likely to impact you, but you should still be aware of them.