2

I am getting the below error whenever I tried to call any call from serverless framework lambda

[offline] _____ HANDLER RESOLVED _____
offline: Failure: product.hasMany called with something that's not a subclass of Sequelize.Model
Error: product.hasMany called with something that's not a subclass of Sequelize.Model
    at Function.hasMany (C:\Users\Kiran\Documents\Projects\Rentals-Backend\node_modules\sequelize\lib\associations\mixin.js:18:13)
    at Function.Product.associate (C:\Users\Kiran\Documents\Projects\Rentals-Backend\entity\product.js:21:17)

IMPORTANT

Below code is the answer for the above error. You might missed any steps. So you can refer and fix. Thanks Anatoly who helped me to solve the problem.

Product model:

const { STRING, BOOLEAN, INTEGER } = require("sequelize");

module.exports = (sequelize, DataTypes) => {
    const Product = sequelize.define("product", {
        id: { type: INTEGER, primaryKey: true, autoIncrement: true },
        name: { type: STRING },
        description: { type: STRING, allowNull: true },
        purchase_price: { type: STRING },
        tax: { type: STRING },
        sale_price: { type: STRING },
        categoryId: { type: STRING },
        status: { type: BOOLEAN, defaultValue: 0 },
        created_on: { type: INTEGER, allowNull: true },
        updated_on: { type: INTEGER, allowNull: true },
    }, {
        timestamps: false,
        freezeTableName: true,
    })
    Product.associate = function (models) {
        Product.hasMany(models.product_image, { as: "images" });
        Product.belongsTo(models.product_category, { as: "category", foreignKey: 'categoryId' });
    };
    return Product;

}

Image model:

const { STRING, BOOLEAN, INTEGER } = require("sequelize");

module.exports = (sequelize, DataTypes) => {
    const ProductImage = sequelize.define("product_image", {
        id: { type: INTEGER, primaryKey: true, autoIncrement: true },
        productId: { type: INTEGER },
        fileName: { type: STRING },
        url: { type: STRING },
        position: { type: INTEGER },
        isDefault: { type: BOOLEAN, defaultValue: 0 },
        shopId: { type: STRING },
        status: { type: BOOLEAN, defaultValue: 0 },
        created_on: { type: INTEGER, allowNull: true },
        updated_on: { type: INTEGER, allowNull: true },
    }, {
        timestamps: false,
        freezeTableName: true,
    })

    return ProductImage;
}

Category model:

const { STRING, BOOLEAN, INTEGER } = require("sequelize");


module.exports = (sequelize, DataTypes) => {
    const ProductCategory = sequelize.define("product_category", {
        id: { type: INTEGER, primaryKey: true, autoIncrement: true },
        name: { type: STRING },
        description: { type: STRING, allowNull: true },
        status: { type: BOOLEAN, defaultValue: 0 },
        created_on: { type: INTEGER, allowNull: true },
        updated_on: { type: INTEGER, allowNull: true },
    }, {
        timestamps: false,
        freezeTableName: true,
    });
    return ProductCategory;
}

This is the config file where we initialize sequelize

Config file

    const Sequelize = require('sequelize')
    const fs = require('fs')
    const path = require('path')
    const db = {}
    const models = path.join(__dirname, '..', 'entity')
    var basename = path.basename(module.filename)
    
    const sequelize = new Sequelize(
        process.env.DB_NAME,
        process.env.DB_USER,
        process.env.DB_PASSWORD,
        {
            dialect: 'mysql',
            host: process.env.DB_HOST,
            port: process.env.DB_PORT,
            logging: false
        }
    )
    
    fs
      .readdirSync(models)
      .filter(function (file) {
        return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js')
      })
      .forEach(function (file) {
        var model = require(path.join(models, file))(
          sequelize,
          Sequelize.DataTypes
        );
        db[model.name] = model;
        
      })
    
    Object.keys(db).forEach(function (modelName) {
      if (db[modelName].associate) {
        db[modelName].associate(db)
      }
    })
    
    db.Sequelize = Sequelize
    db.sequelize = sequelize
    
    module.exports = db

Here we are calling product details.

Calling function

    const db = require('../config/sequelize-config');
    exports.getProductById = (query, username, shopId) => {
        return new Promise((resolve, reject) => {
            db.product.findOne({
                where: {
                    id: query.id
                },
                attributes: ['id', 'name', 'description', ['purchase_price', 'purchasePrice'], 'tax', ['sale_price', 'salePrice']],
                include: [{
                    model: db.product_image,
                    as: 'images',
                    where: {
                        status: 1
                    },
                    required: false,
                    attributes: ['id', 'fileName', 'position', 'url']
                },
                {
                    model: db.product_category,
                    as: 'category',
                    required: false,
                    attributes: ['id', 'name']
                }]
            }).then(product => {
                if (product) {
                    resolve({ [KEY_STATUS]: 1, [KEY_MESSAGE]: "Product details fetched successfully", [KEY_DATA]: product });
                } else {
                    reject({ [KEY_STATUS]: 0, [KEY_MESSAGE]: "Product details fetch failed" });
                }
            }).catch(error => {
                reject({ [KEY_STATUS]: 0, [KEY_MESSAGE]: "Product details fetch failed", [KEY_ERROR]: error.message });
            });
        })
    }
KIRAN K J
  • 632
  • 5
  • 28
  • 57

1 Answers1

1

To avoid cross-reference errors and similar ones I recommend converting model definitions to functions and registering models and associations in the same one module, see this answer and the question

Anatoly
  • 20,799
  • 3
  • 28
  • 42
  • After trying several hours I am getting `TypeError: Cannot read property 'define' of undefined` – KIRAN K J Nov 30 '21 at 14:44
  • Can you please update your question above with modified model files and a module with registration where you got this error? – Anatoly Nov 30 '21 at 17:02
  • I added `Config file` and `calling funtion` at the bottom. But the error is getting from `category model` file `let categoryModel = db.sequelize.define("product_category", {` this line. – KIRAN K J Nov 30 '21 at 17:39
  • You didn't turn your model definitions into functions like it did here: https://stackoverflow.com/a/61710568/1376618 – Anatoly Nov 30 '21 at 17:42
  • Also, I referred to the documentation again and there will not be mentioned the issue or precaution. – KIRAN K J Nov 30 '21 at 17:42
  • You're trying to use a module where you register all models in a model module directly and that's not correct at all. That's why you need to define model registration functions and export them from model modules and then call them in a module where you're creating Sequelize instance – Anatoly Nov 30 '21 at 17:49
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/239708/discussion-between-kiran-k-j-and-anatoly). – KIRAN K J Nov 30 '21 at 17:56
  • @Antoly I updated the entire question with the solution given by you. I think we are ver nearer to the solution. Thank you – KIRAN K J Dec 01 '21 at 13:43
  • You registered `Image` model as `product_image` but you're trying to use in in `hasMany` as `ProductImage` – Anatoly Dec 01 '21 at 18:57
  • Finally I reached the solution. Thank you very much for your great support and guidance. – KIRAN K J Dec 03 '21 at 00:52
  • https://stackoverflow.com/questions/70036679/sequelize-randomly-throwing-error-while-select?noredirect=1#comment123865725_70036679 For this issue, should I replace all `Sequelize` usage with `db.Sequelize` – KIRAN K J Dec 04 '21 at 06:45