17

I'm trying to set up the project using Node v14.3 and sequelize.

I don't want to use babel-register. Instead of this I set "type": "module" in my package.json and use all ES6 - ES11 features out of the box.

I also want to use sequelize-cli for setting up and applying migrations. Everything works except the following command:

& sequelize db:migrate

Sequelize CLI [Node: 14.3.0, CLI: 5.5.1, ORM: 5.21.11]

Loaded configuration file "config/config.json".
Using environment "development".
== 20200530214311-create-user: migrating =======

ERROR: Must use import to load ES Module: /home/kasheftin/work/tests/chai-http-publication/migrations/20200530214311-create-user.js
require() of ES modules is not supported.
require() of /home/kasheftin/work/tests/chai-http-publication/migrations/20200530214311-create-user.js from /home/kasheftin/.nvm/versions/node/v14.3.0/lib/node_modules/sequelize-cli/node_modules/umzug/lib/migration.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename 20200530214311-create-user.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/kasheftin/work/tests/chai-http-publication/package.json.

We see that under the hood sequelize-cli uses require(). That's not allowed for ES Module. It suggests 3 ways to solve this:

  • rename 20200530214311-create-user.js to end in .cjs - Can not be done, sequelize-cli does not find migrations that end with .cjs.

  • Change the requiring code to use import() - I don't want to touch sequelize-cli code.

  • Remove "type": "module" - I can not because everything stops working.

Is there any other way to make sequelize-cli work? I'm using tests heavily and I want the test database to be prepared automatically before running tests.

8
  • 1
    github.com/sequelize/cli/issues/861 is still open. Maybe you can use a workaround only? Commented Jun 1, 2020 at 15:11
  • Thanks, @Anatoly. Installing the babel-core package and adding require("babel-core/register"); to my config.cjs file did the trick for me, just like mentioned in the link. Besides that, I also needed to install babel-preset-env in order to get it working. Commented Jun 9, 2020 at 6:34
  • You're not a author of the original question. Can I copy my comment as an answer? Commented Jun 9, 2020 at 18:49
  • Yes. So the answer is it's not possible at the moment. Commented Jun 10, 2020 at 6:28
  • 1
    There is babel-register mentioned in the official documentation: sequelize.org/master/manual/migrations.html. It seems this is the official way to use es6 Commented Feb 17, 2021 at 18:41

3 Answers 3

8

A solution is to add a package.json in your migrations folder to override the type: "module" from your main package.json

This package.json would look like this:

{
  "type": "commonjs"
}

and your migration file have to look like this:

module.exports = {
  up: async (queryInterface, Sequelize) => {

  },

  down: async (queryInterface, Sequelize) => {

  }
};

It works well with nodeJS 14.16.1 & Sequelize 6.6.2 & sequelize-cli 6.2.0

Sign up to request clarification or add additional context in comments.

3 Comments

This works for me with NodeJS 18 and Sequelize 6.19.0
it works, but break other app functionalities
@mohammadJavadGhasemy if you create the package.json in a specific folder it's not supposed to break anything
3

I got this to work by creating a .sequelizerc file to let sequelize know that I am overriding the default paths:

// .sequelizerc
const path = require('path');

const db_path = './';

module.exports = {
  'config': path.resolve(db_path, 'config/config.cjs'),
  'models-path': path.resolve(db_path, 'models'),
  'seeders-path': path.resolve(db_path, 'seeders'),
  'migrations-path': path.resolve(db_path, 'migrations')
};

Notice that I am using a config.cjs file. Then just create a migration but change the extension to .cjs as well:

// 20211206164144-create_subjects_table.cjs
const tableName = 'subjects';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable(tableName, {
      id: {
        type: Sequelize.UUID,
        defaultValue: Sequelize.UUIDV4,
        allowNull: false,
        primaryKey: true,
      },
      title: {
        type: Sequelize.STRING,
        required: true,
      },
      created_at: {
        type: Sequelize.DATE,
      },
      updated_at: {
        type: Sequelize.DATE,
      },
      deleted_at: {
        type: Sequelize.DATE,
      },
    });
  },

  down: async (queryInterface) => {
    await queryInterface.dropTable('subjects');
  },
};

This is working with Node.js version v16.13.1 and the following package.json:

{
  "type": "module",
  "dependencies": {
    "pg": "^8.7.1",
    "pg-hstore": "^2.3.4",
    "sequelize": "^6.12.0-beta.1"
  },
  "devDependencies": {
    "sequelize-cli": "^6.3.0"
  }
}

1 Comment

your sequelizerc file is using commonjs, now change that to esm and see the errors it pops
1

I've had the same issue for months now. Babel register would just not work while using ES module imports and Sequelize cli.

Here's how I eventually got everything to work properly. I had to copy src to a dist directory. Then override the type in package json. Hopefully this helps out 🍻

.sequelizerc

require('@babel/register')({
  presets: [
    ['@babel/preset-env', { targets: { node: 'current' } }]
  ]
});
const path = require('path');

const DB_PATH = 'dist/db'; // use dist instead of src directory

module.exports = {
  'config': path.resolve(DB_PATH, 'config.json'),
  'models-path': path.resolve(DB_PATH, 'models'),
  'seeders-path': path.resolve(DB_PATH, 'seeders'),
  'migrations-path': path.resolve(DB_PATH, 'migrations')
};

package.json

{
  "type": "module",
  "engines": {
    "node": ">=14.18",
    "yarn": ">=1.22"
  },
  "scripts": {
    "start": "node --experimental-specifier-resolution=node src",
    "db": "sequelize db:migrate && sequelize db:seed:all",
    "predb": "yarn dist",
    "dist": "cp -r src dist",
    "predist": "rm -rf dist",
    "postdist": "node setup-dist.js"
  },
  "dependencies": {
    "@babel/core": "^7.16.0",
    "@babel/preset-env": "^7.16.0",
    "@babel/register": "^7.16.0",
    "sequelize": "^6.8.0",
    "sequelize-cli": "^6.2.0"
  }
}

setup-dist.js

import { writeFileSync } from 'fs';

const file = './dist/package.json';
const data = '{ "type": "" }'; // to override ESM in main package.json

writeFileSync(file, data);

Reference: https://gist.github.com/elawad/c0af86ea37629ad0538c2b974b4ea0c1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.