New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
models/index.js doesn't work with ES6 modules #960
Comments
Hi, |
For now, I created this temporary solution. |
As a matter of fact, i occured this error since i didn't delete a model i created manually before using sequelize-cli... Thanks anyway for your answer, i'll keep it in mind ! |
This is my solution for the moment import { readdirSync } from "fs";
import { basename, dirname } from "path";
import { Sequelize, DataTypes } from "sequelize";
import { fileURLToPath } from 'url';
import database from "../config/database.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const db = {};
const sequelize = new Sequelize(database.development);
export default (async () => {
const files = readdirSync(__dirname)
.filter(
(file) => file.indexOf('.') !== 0
&& file !== basename(__filename)
&& file.slice(-3) === '.js',
);
for await (const file of files) {
const model = await import(`./${file}`);
const namedModel = model.default(sequelize, DataTypes);
db[namedModel.name] = namedModel;
}
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
return db;
})(); |
@ephys can you look into this? |
I'm not sure how to go about fixing this. If we generate CJS code, it's not going to work for users that use ESM. I suppose we could prompt during generation which module system to use |
I guess it's possible to use *.mjs, since it's a standard, just to differentiate. Then, at generation time, only copy those with the corresponding extension. |
If we were to generate .mjs, users using commonjs would not be able to require those files |
That's what I meant by "differentiate" and "corresponding extension". It's the easiest way to go. |
Well (The CLI code is also in dire need of an update and I'd like to migrate it to ESM before doing anything else too) |
This comment was marked as off-topic.
This comment was marked as off-topic.
This works, you just have to check if the file were imported before you call "model.default(sequelize,DataTypes) because you are awaiting for the files to be read other than that you are good to go" Also if the "const model = await import('./${file}') does not work just use const model = await import(path.resolve("src", "models", |
I write like this but it is'nt load the models and then give my the error: how can i fix it? |
I had the same issue. In my case models/index.js was loaded (which is the model loader and not a model. So the error message was correct). I wrote an additional .filter line to get it out of my file list. If this does not help you have to make sure that you are only importing models. I have a different problem. Following the solution of @NixonAzeredo I am trying to load models in my controller files: |
This works, what changes was to include path to the models. import { readdirSync } from "fs";
// import path here
import path from "path";
import { basename, dirname } from "path";
import { Sequelize, DataTypes } from "sequelize";
import { fileURLToPath } from "url";
import sequelize from "../config/connection.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const db = {};
export default (async () => {
const files = readdirSync(__dirname).filter(
(file) =>
file.indexOf(".") !== 0 &&
file !== basename(__filename) &&
file.slice(-3) === ".js"
);
for await (const file of files) {
// use path here to access your models from models directory then await for it @
const model = await import(path.resolve("models", `${file}`));
if (model.default) {
const namedModel = await model.default(sequelize, DataTypes);
db[namedModel.name] = namedModel;
}
}
Object.keys(db).forEach((modelName) => {
if (modelName) {
if (db[modelName].associate) {
db[modelName].associate(db);
}
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
return db;
})();
|
This comment was marked as duplicate.
This comment was marked as duplicate.
Thanks a lot for your effort. I tried it out and can confirm that it works. Unfortunately I ran into another issue: migrations seem not to work with ES6 modules out of the box. Possible solutions seem quite hacky. I decided to keep using CommonJS syntax and wait until there is better support for ES6. |
This comment was marked as off-topic.
This comment was marked as off-topic.
This works on my Nextjs 14.1.0, Node 19 and Sequelize 6.35 'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const process = require('process');
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.js')[env];
const db = {};
const models = process.cwd() + '/db/models/' || __dirname;
const basename = path.basename(models + "index.js");
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize({database: config.database, username: config.username,
password: config.password, config: config, dialect: "mysql", host: config.host,
dialectModule: require("mysql2")});
}
fs
.readdirSync(models)
.filter(file => {
return (
file.indexOf('.') !== 0 &&
file !== basename &&
file.slice(-3) === '.js' &&
file.indexOf('.test.js') === -1
);
})
.forEach(file => {
const model = require(`./${file}`)(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db; |
I just started learning node.js/express/Sequelize, I ran into this issue and spent hours trying to figure it out. I'm not very experienced and not sure if my solution is the best.. But what worked for me was to add a package.json file that just has the line {"type": "commonjs"} in each folder generated by Sequelize CLI (config, migrations, models). So I ended up with 3 of those files, one in each folder. This fixed the running migrate issue and importing the db and models in the rest of my files that use ES6. |
If you want to use this file in ESM, here is what you need to do:
import { fileURLToPath } from 'node:url';
import path from 'node:path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(fileURLToPath(import.meta.url)); Basically #960 (comment), with a small tweak, is the solution you should use if you want an equivalent to the CJS file for ESM. This is what we would generate if we were to update the CLI to support generating it as ESM. import { readdirSync } from "fs";
import { basename, dirname } from "path";
import { Sequelize, DataTypes } from "sequelize";
import { fileURLToPath } from 'url';
import database from "../config/database.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const db = {};
const sequelize = new Sequelize(database.development);
const files = readdirSync(__dirname)
.filter(
(file) => file.indexOf('.') !== 0
&& file !== basename(__filename)
&& file.slice(-3) === '.js',
);
await Promise.all(files.map(async file => {
const model = await import(`./${file}`);
if (!model.default) {
return;
}
const namedModel = model.default(sequelize, DataTypes);
db[namedModel.name] = namedModel;
}))
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
return db; |
What you are doing?
Trying to load models with models/index.js doesn't work with ES6 modules activated with
"type": "module"
Variables like
__filename
and__dirname
don't work anymore with modules.What do you expect to happen?
There should be an option to choose between Modules or CommonJS.
What is actually happening?
There's only CommonJS support.
The text was updated successfully, but these errors were encountered: