javascriptnode.jsauthenticationsequelize.js

how to fix "message": "Cannot read properties of undefined (reading 'findOne')" Received when calling the API made in node.js and sequelize?


I'm already sorry for my poor english and this is my first question around here. Im trying make a login app using the api with 2 roles (admin, normal user) and everytime I call the API this message show up at the thunder client: "message": "Cannot read properties of undefined (reading 'findOne')"

Here is my code:

src/database/models/index.js

'use strict';

const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const process = require('process');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.js')[env];
const db = {}

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
  sequelize = new Sequelize(config.database, config.username, config.password, config);
}
db.sequelize = sequelize
fs
  .readdirSync(__dirname)
  .filter(file => {
    return (
      file.indexOf('.') !== 0 &&
      file !== basename &&
      file.slice(-3) === '.js' &&
      file.indexOf('.test.js') === -1
    );
  })
  .forEach((file) => {
    const model = require(path.join(__dirname, file));
    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;

src/database/models/User.js

'use strict';

const userModel = (sequelize, DataTypes) =\> {
    const User = sequelize.define('User', {
        id: {
            type: DataTypes.INTEGER,
            primaryKey: true,
            autoIncrement: true,
        },
        role: {
            type: DataTypes.STRING,
        },
        name: {
            type: DataTypes.STRING,
        },
        email: {
            type: DataTypes.STRING,
        },
        password: {
            type: DataTypes.STRING,
        },

    }, {
        tableName: 'users',
        underscored: true,
        timestamps: false,
    });

    return User
}

module.exports = { userModel };

src/service/login.service.js

const md5 = require('md5');
const { User } = require('../database/models');
const { generateToken } = require('../utils/JWT');
const errorThrower = require('../utils/errorThrower');

const login = async ({ email, password }) => {
  const encodedPassword = md5(password);
  console.log(User)
  const user = await User.findOne({ where: { email, password: encodedPassword } });

  if (!user) errorThrower(404, 'Incorrect email or password');

  const token = generateToken(user);
  const { name, email: emailUser, role } = user;

  return { name, email: emailUser, role, token };
};

module.exports = {
  login,
};

I'm gratefull for anyone that tries to help me, and sorry for my english again


Solution

  • You just need to export the model function itself instead of exporting ab object with a prop pointing to this function:

    module.exports = userModel;
    

    and then call it while importing it using require:

    .forEach((file) => {
        const model = require(path.join(__dirname, file))(
           sequelize,
           Sequelize.DataTypes
        );
        db[model.name] = model;
      });
    

    See my other answer here and compare model registration code