Cannot read property 'create' of undefined in expressjs - node.js

Please am new to Nodejs but am trying to insert a data into my database using sequelize but am getting Cannot read property .create of undefined.
This is my index.js file
const fs = require('fs')
const path = require('path')
const Sequelize = require('sequelize')
const config = require('../config/config')
const db = {}
const sequelize = new Sequelize(
config.DB,
config.USER,
config.PASSWORD,
{
host: config.HOST,
dialect: config.dialect,
operatorsAliases: false,
pool: {
max: config.pool.max,
min: config.pool.min,
acquire: config.pool.acquire,
idle: config.pool.idle
}
});
fs
.readdirSync(__dirname)
.filter((file) =>
file !== 'index.js'
)
.forEach((file) => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes)
// db[model] = model
db.User = model
})
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db;
This is my Model/User.js File
module.exports = (sequelize, DataTypes) => {
sequelize.define('User', {
hmtec_email: {
type: DataTypes.STRING,
unique: true
},
hmtec_password: DataTypes.STRING
})
This is my Controllers/AuthController.js File
const {User} = require ('../models/User')
module.exports = {
async register (req, res) {
try {
const user = await User.create(req.body)
res.send(user.toJSON())
} catch (err) {
console.log(err);
res.status(400).send({
error: 'Email already in Use'
})
}
}
I don't know what wrong with the code, I dont know why am getting that error of .create is undefined

I think your problem is in the last file .. AuthController.js
const {User} = require ('../models/User')
You are using the Es6 new destruction assignment
More Info here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
Normally you should define your variable without the brackets
That mean you got all of the variable available.
But adding the brackets means that you want to get the child of the object, this child is named user .. and then name the variable also as user
and search these info
From the require file after the equal.
But in your user file .. you are exporting a function .. that does not have any child named user
Thus undefined
Better alternative is to use Classes
More info here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
So in user model
// Inside your function you need to use sequalize module , iam not familar with it but you must require it to use it
const Sequelize = require('sequelize');
// Define the Class
class user {
// add the name you want to use for the function - here I used create so the other code also work - also I inserted async because this is asynchronous and also I removed the sequalize from parameters because you don't need it now after it is required above.
async create (DataTypes) => {
await Sequelize.define('User', {
hmtec_email: {
type: DataTypes.STRING,
unique: true
},
hmtec_password: DataTypes.STRING
})
}
module.exports = user;
Now when you require the file in Authcontroller , remove the brackets
const User = require ('../models/User')
and now you can use User.create(YOUR_DATA_VARIABLE);in your authController.js
and if there is any other functions inside this class you also can use them in the same manner.
I hope this fix your problem.

Related

Sequelize 'no such table:' despite table and database clearly existing and correctly configured

Good evening.
I'm building an Express REST API using SQLite, with Sequelize being my ORM of choice.
I was working with an existing database, so I used a package called sequelize-auto in order
to generate my models.
Problem is, Sequelize for some reason won't see my database, a .db file, or won't detect the table, despite being clearly defined. The problem occurs in this block of code:
const Sequelize = require('sequelize');
const sequelize = new Sequelize('expenserdb', 'user', 'pass', {
dialect: 'sqlite',
host: '../database/expenserdb.db'
});
const initModels = require('../models/init-models');
const models = initModels(sequelize);
module.exports = class dbService {
editUserName(newName) {
models.User.update({Name: newName}, {
where: {
UserId: 1
}
})
.catch((err) => {console.log(err)});
}
}
This is my dbService.js file, and as you can see, the database is clearly defined, with the name, location and everything being correct. Despite all of this, I'm still getting:
Error: SQLITE_ERROR: no such table: User {errno: 1, code: 'SQLITE_ERROR', sql: 'UPDATE `User` SET `Name`=$1 WHERE `UserId` = $2'
This service is being injected into my controller via awilix, and the method is called inside the controller:
const container = require("../containerConfig");
const dbService = container.resolve("dbService");
exports.runNameChange = async (req) => {
const newName = JSON.stringify(req.body.name);
const result = await dbService.editUserName(newName);
return result;
};
And in turn, the controller method is ran when this endpoint is hit:
app.post('/updateuser', async function(req, res) {
const result = await userController.runNameChange(req);
res.status(200).send(String(result));
});
Also, the dboptions.json file:
{
"storage":"./database/expenserdb.db"
}
I'm new to Node, Express, and Sequelize in general. I might have missed something crucial, but I can't seem to realize what. Help is greatly appreciated.
Update: just figured it out, you need the FULL path and not the relative path in the
verbose constructor, as such:
const sequelize = new Sequelize('expenserdb', 'user', 'pass', {
dialect: 'sqlite',
storage: 'E:/desktopshortcuts/yahalom/expenser/expenser-server/database/expenserdb.db'
});

Why is sequelize Intellisense not working?

How I can turn on Intellisense of node.js sequelize?
There is no model method:
What I can do?
i solved the problem related to sequelize intellisense by changing my general require syntax to
const {Sequelize}=require('sequelize');
What I found is that The previous versions of Intellisense is working, but not stable ( or 6.x) version.
So you can try this:
const {Sequelize} = require("sequelize");
or
const Sequelize = require("sequelize").Sequelize
Either of this following works.
follow this you will get Intellisense works properly.
/models/index.js
'use strict';
const Sequelize = require('sequelize');
const db = {};
/**
* #type {Sequelize.Sequelize}=con
*/
let con = new Sequelize(process.env.db_database, process.env.db_username, process.env.db_password, {
host: process.env.db_host,
dialect: "mysql"
});
(async function () {
try {
//ck connection
await con.authenticate()
//attach models
db.User = require('./User')
db.Test = require('./Test')
//associate
Object.keys(db).forEach(modelName => {
// if (db[modelName].associate) {
// db[modelName].associate(db);
// }
});
//sync
await con.sync({
logging: true,
force: false
})
} catch (e) {
console.log("error db con: ", e.name)
}
}())
db.con = con
module.exports = db;
/models/User.js
const { DataTypes } = require('sequelize');
const { con } = require('.');
const User = con.define("User", {
name: {
type: DataTypes.STRING,
allowNull: false
},
password: {
type: DataTypes.STRING,
allowNull: false
}
})
module.exports = User
according to:
https://github.com/sequelize/sequelize/issues/11103
const Sequelize = require('sequelize').Sequelize;
Here is an ES6 way to get IntelliSense working on your models (instead of just the instantiated class).
First - declare the sequelize instance which can be imported into many files.
// sequelize.js
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize(...);
export default sequelize;
Second - follow the suggested setup by sequelize-cli. Note you need to reimport the model. I know this might seem annoying to continually add export declarations here but when you add this 1 line, you get all the benefit :)
// models/index.js
import Sequelize from 'sequelize';
import sequelize from '../config/sequelize';
export * from './user';
export * from './another-model';
// ... etc
let db = {};
const basename = path.basename(__filename);
fs.readdirSync(__dirname)
.filter((file) => file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js')
.forEach((file) => {
const module = require(path.join(__dirname, file));
Object.values(module).forEach((model) => {
db[model.name] = model;
});
});
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
export {
sequelize,
Sequelize,
migrations
};
Third - update model file like so.
Note: adding export keyword here and importing your base sequelize instance.
//models/MyModel.js
import Sequelize from 'sequelize';
import sequelize from '../sequelize';
const { DataTypes } = Sequelize;
export const User = sequelize.define('User', {
userId: DataTypes.UUID,
...
}, {});
User.associate = function (models) {
User.belongsTo(models.Admin, {
foreignKey: 'adminId',
});
};
Sharing this since I struggled to find a working example since if you follow the official docs, you don't get IntelliSense on the models.
example showing models on db object
example showing sequelize intellisense
The reason you are not getting the Intellisense might be because you are not importing your models through sequelize correctly. Assuming you are defining your models in separate files and then importing them. I would recommend doing the following:
Create an index.js file in your models folder
Use sequelize.import to import all your models and associate them as well.
Then export them all from index.js along with seqeulize db instance and Sequelize module.
Wherever in your project you need your models just require db from /models.
models/index.js
const sequelize = new Sequelize(DB_NAME, DB_USERNAME, DB_PASSWORD)
const db = {
Sequelize: Sequelize,
sequelize,
User: sequelize.import("./user"),
Message: sequelize.import("./message")
}
Object.keys(db).forEach(model => {
if ("associate" in db[model]) {
db[model].associate(db)
}
})
module.exports = db

Sequelize build is not a function when model is created from migration

This is my model which is create from sequelize cli: (it describes an user in User.js)
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
username: DataTypes.STRING
}, {});
User.associate = function(models) {
// associations can be defined here
};
return User;
};
When I try to create it in my script file, I get this following error:
User.build is not a function
Here's how I call the build method:
const User = require('../models/User');
User.build({
username: message["name"],
}).save();
In your case it returns a function not constructor
you have to pass sequelize and DataTypes while importing it
const User= require('../models/User')(sequelize, DataTypes);
Hope it'll work for you
You need to require model from "model/index"
so change this
const User = require('../models/User');
to this
const {User} = require('../models/index');
refer to this answer

sequelize .create is not a function error

I'm getting Unhandled rejection TypeError: feed.create is not a function error and I can't understand why it occurs. What's the problem here?
Here's my code. I'm probably not doing something very fundamental here since I can't reach feed variable in routes/index.js.
If I add module.exports = feed; to my models file, I can reach it, but I have more than one models, so if I add additional models below the feed, they override it.
db.js
var Sequelize = require('sequelize');
var sequelize = new Sequelize('mydatabase', 'root', 'root', {
host: 'localhost',
dialect: 'mysql',
port: 8889,
pool: {
max: 5,
min: 0,
idle: 10000
},
define: {
timestamps: false
}
});
var db = {};
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
models.js
var db = require('./db'),
sequelize = db.sequelize,
Sequelize = db.Sequelize;
var feed = sequelize.define('feeds', {
subscriber_id: Sequelize.INTEGER,
activity_id: Sequelize.INTEGER
},
{
tableName: 'feeds',
freezeTableName: true
});
routes/index.js
var express = require('express');
var router = express.Router();
var models = require('../models');
router.get('/addfeed', function(req,res) {
sequelize.sync().then(function () {
return feed.create({
subscriber_id: 5008,
activity_id : 116
});
}).then(function (jane) {
res.sendStatus(jane);
});
});
You cannot reach a variable from a file, by only requiring it in another one. You need to either define an object literal to hold all your variables in one place and assign it to module.exports, or you need to import them from different files separately.
In your case, I would create separate files to hold table schemas, and then import them by sequelize.import under one file, then require that file.
Like this:
models/index.js:
var sequelize = new Sequelize('DBNAME', 'root', 'root', {
host: "localhost",
dialect: 'sqlite',
pool:{
max: 5,
min: 0,
idle: 10000
},
storage: "SOME_DB_PATH"
});
// load models
var models = [
'Users',
];
models.forEach(function(model) {
module.exports[model] = sequelize.import(__dirname + '/' + model);
});
models/Users.js
var Sequelize = require("sequelize");
module.exports=function(sequelize, DataTypes){
return Users = sequelize.define("Users", {
id: {
type: DataTypes.INTEGER,
field: "id",
autoIncrement: !0,
primaryKey: !0
},
firstName: {
type: DataTypes.STRING,
field: "first_name"
},
lastName: {
type: DataTypes.STRING,
field: "last_name"
},
}, {
freezeTableName: true, // Model tableName will be the same as the model name
classMethods:{
}
},
instanceMethods:{
}
}
});
};
Then import each model like this:
var Users = require("MODELS_FOLDER_PATH").Users;
Hope this helps.
Just use
const { User } = require("../models");
Update :
in newer version of sequelize v6 and beyond sequelize.import is deprecated
sequelize docs recommend using require now
If you have generated models using migrations
this is how your model file will look like
models/user.js
'use strict'
module.exports = (sequelize, DataTypes, Model) => {
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({
name: {
type: DataTypes.STRING,
allowNull: false
},
phone_number: {
type: DataTypes.STRING(20)
},
otp: {
type: DataTypes.INTEGER(4).UNSIGNED
},{
sequelize,
modelName: 'User',
});
return User;
};
as you can see your model export function has sequelize DataTypes & Model parameters.
so when you import this model you should send above arguments.
Example
I am importing user model in controllers/user.js file, it could be any file
controllers/controller.js
const Sequelize = require('sequelize');
const sequelize = require('../config/db').sequelize;
// Bring in Model
const User = require('../models/user')(sequelize, Sequelize.DataTypes,
Sequelize.Model);
// your code...
// User.create(), User.find() whatever
Notice that sequelize(with small 's') and Sequelize(with capital 'S') are different things, first one represent instance of Sequelize created using new Sequelize, second one is just package you installed & imported
first one (sequelize) can be found wherever you started a connection to database using const sequelize = new Sequelize() usually from app.js or db.js file, make sure to export it from there and import it into where you want to use Model i.e controller
export sequelize instance
db.js Or app.js
const sequelize = new Sequelize();
... //your code
...
module.exports = {
sequelize: sequelize
}
You may want to check the answer given on the link below tackling the same issue, I was able to resolve mine using const User = sequelize.import('../models/users');, instead of just import User from '../models/users';
Sequelize create not a function?
I came with the same issue when I used something like:
const { Feed } = require("../models/Feed.js");
So, just using the code down below solved it
const { Feed } = require("../models");

Sequelize: Require vs Import

In the documentation for sequlize they use the import function like so
// in your server file - e.g. app.js
var Project = sequelize.import(__dirname + "/path/to/models/project")
// The model definition is done in /path/to/models/project.js
// As you might notice, the DataTypes are the very same as explained above
module.exports = function(sequelize, DataTypes) {
return sequelize.define("Project", {
name: DataTypes.STRING,
description: DataTypes.TEXT
})
}
However, what would be so wrong with this?
// in your server file - e.g. app.js
var Project = require(__dirname + "/path/to/models/project")
// The model definition is done in /path/to/models/project.js
var Project = sequelize.define("Project", {
name: Sequelize.STRING,
description: Sequelize.TEXT
});
module.exports = Project
Well, as you can see your model definition needs two things:
Sequelize or DataTypes
sequelize
In your first example when using sequelize.import('something'); it is similar to use require('something')(this, Sequelize); (this being the sequelize instance)
Both are necessary to initialize your model, but the important thing to understand is: One of these is a classtype so it's global, the other one is an instance and has to be created with your connection parameters.
So if you do this:
var Project = sequelize.define("Project", {
name: Sequelize.STRING,
description: Sequelize.TEXT
});
module.exports = Project
Where does sequelize come from? It has to be instantiated and passed somehow.
Here is an example with require instead of import:
// /path/to/app.js
var Sequelize = require('sequelize');
var sequelize = new Sequelize(/* ... */);
var Project = require('/path/to/models/project')(sequelize, Sequelize);
// /path/to/models/project.js
module.exports = function (sequelize, DataTypes) {
sequelize.define("Project", {
name: DataTypes.STRING,
description: DataTypes.TEXT
});
};
module.exports = Project
You could even change it so you wouldn't have to pass Sequelize by requiring it in the model itself, but you would still need to create a sequelize instance prior to define the model.
sequelize.import is deprecated as of sequelize 6
As mentioned at https://sequelize.org/master/manual/models-definition.html
Deprecated: sequelize.import
Note: You should not use sequelize.import. Please just use require instead.
So you should just port:
// index.js
const sequelize = new Sequelize(...)
const User = sequelize.import('./user')
// user.js
module.exports = (sequelize, DataTypes) => {
// Define User.
return User;
}
to:
// index.js
const sequelize = new Sequelize(...)
const User = require('./user')(sequelize)
// user.js
const { DataTypes } = require('sequelize')
module.exports = (sequelize) => {
// Define User.
return User;
}

Resources