My goal with this question is to achieve, in a safe and sustainable way, working VS Code intellisense with Sequelize model definitions in my node.js (not typescript) project.
Sequelize models can be constructed
- via hooks, or
- by extending the Model class.
Models created with hooks won't be understood by intellisense, so I'm focused on the latter below.
Sequelize model constructors require a configured Sequelize connection instance. There are at least two ways of accomodating this.
A - Instantiate sequelize next to every model (ie: many times)
One documented example of model definition:
const { Sequelize, DataTypes, Model } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory');
class User extends Model {}
User.init({
// Model attributes are defined here
firstName: {
type: DataTypes.STRING,
allowNull: false
},
lastName: {
type: DataTypes.STRING
// allowNull defaults to true
}
}, {
// Other model options go here
sequelize, // We need to pass the connection instance
modelName: 'User' // We need to choose the model name
});
In this example, sequelize
connection is instantiated in the same file alongside the model definition.
We can repeate exactly this in many Model definition files. Each file can then export a Model class which can be used directly by the caller.
Intellisense will understand this setup.
B - Instantiate sequelize once, and pass it around
Sequelize CLI facilitates the below project structure:
- Each model definition file exports a function which builds the
Model
class. The function accepts the sequelize
instance as an argument.
- The
models/index.js
file instantiates sequelize
-- the only place in the project where this occurs. Every model-definition-function is then called, to which this sequelize
instance is passed.
- The resulting models are all exported by
models/index.js
.
It seems intellisense does not understand this, and cannot trace the class methods from these created-by-function exports.
Below is the User.js
file that Sequelize CLI would create for exactly the same model as the above example:
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class User extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
}
User.init(
{
firstName: DataTypes.STRING,
lastName: DataTypes.STRING
},
{
sequelize,
modelName: "User"
}
);
return User;
};
For the sake of intellisense, I would prefer to (more or less) use the structure evidenced by the first example: export classes, not functions. I might instantiate sequelize
in some separate file, but then require()
that file many times throughout my various model definitions.
Is this a bad idea? Will I unwittingly create some cacophony of competing connections? Do I need to be concerned of any side effects?