I am using sequelize orm in node.js. I have made models folders for all model like userModel.js, in userModel.js I have some class-based functions like login and getToken.
// some code of userModel.js
const jwt = require('jsonwebtoken');
module.exports = (sequelize, Sequelize) => {
const UserSchema = sequelize.define('User', {
first_name: {
type: Sequelize.STRING,
},
last_name: {
type: Sequelize.STRING,
},
});
// generate token
UserSchema.genToken = (id) => {
return jwt.sign({ id }, 'test');
}
// user login
UserSchema.login = function (body) {
const User = this;
return User.findOne({
where: { email: body.email}
})
.then((result) => {
return result;
})
.catch((err) => {
return Promise.reject(err);
})
}
return UserSchema;
}
when i import userModel.js in db.js
const Sequelize = require('sequelize');
const config = {};
var db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, {
host: config.host,
dialect: config.dialect,
operatorsAliases: false,
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.User = sequelize.import('./../models/userModel');
module.exports = db;
so my question is when I using db variable for userModel like
db.User
I am using VS code editor for coding. So now VS code is showing me all suggestion of sequelize models but it is not showing my functions for login and genToken
//suggest
db.User.find()
db.User.findOne()
//but not include these
db.User.login()
db.User.genToken()
Even when I use db.User.login() or db.User.genToken() it's working as I want but right now I will have to open userModel.js again and again for seeing the name of all functions. How can I import models in a better way?
Related
I am trying to mutate in GraphQL to create a new user but I get the error of
Cannot return null for non-nullable field Mutation.register.
Screenshot of operation, variable and response here.
graphql/schema/schema.js
const{ buildSchema } = require('graphql');
const schema = buildSchema(`
type User {
_id: ID!
email: String!
username: String!
token: String!
createdAt: String!
}
input RegisterInput{
username: String!
password: String!
confirmPassword: String!
email: String!
}
type Query {
user(id: ID!): User
}
type Mutation {
register(registerInput: RegisterInput): User!
}
schema {
query: Query
mutation: Mutation
}
`)
module.exports = schema;
graphql/resolvers/user.js
const User = require('../../models/user.js');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const SECRET_KEY = 'oPXA96op!u%,`:}eT^.!|hvXohA~fa';
module.exports = {
Mutation: {
async register(
_,
{
registerInput: { username, email, password, confirmPassword}
},
context,
info
) {
password = await bcrypt.hash(password, 12);
const newUser = new User({
email,
username,
password,
createdAt: new Date().toISOString
});
const res = await newUser.save();
const token = jwt.sign({
id: res.id,
email: res.email,
username: res.username
}, SECRET_KEY, { expiresIn: '1h'});
return{
...res._doc,
id: res._id,
token
};
}
}
};
graphql/resolvers/index.js
const postResolver = require('./post');
const userResolver = require('./user');
const resolvers = {
Mutation: {
...userResolver.Mutation
},
...postResolver
}
module.exports = resolvers;
server.js
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
const mongoose = require('mongoose');
const cors = require('cors');
const { graphqlHTTP } = require('express-graphql');
const MONGODB = '';
const schema = require('./graphql/schema');
const resolvers = require('./graphql/resolvers');
const PORT = 4000;
const server = new ApolloServer({ schema, resolvers });
mongoose.connect(MONGODB);
mongoose.connection.once('open', function() {
console.log('Connected to the Database.');
});
mongoose.connection.on('error', function(error) {
console.log('Mongoose Connection Error : ' + error);
});
const app = express();
app.use(cors());
let apolloServer = null;
async function startServer() {
apolloServer = new ApolloServer({
schema,
resolvers,
});
await apolloServer.start();
apolloServer.applyMiddleware({ app });
}
startServer();
app.use("/graphql", graphqlHTTP({
schema: schema,
rootValue: resolvers,
graphiql: true
}));
app.listen(PORT, function() {
console.log(`Server listening on port ${PORT}.`);
});
I have checked many previous posts about this mutation error but none have seen to be resolved, and also have done many modifications to the schema/resolver but has not worked. I have also posted on the GraphQL Discord for help, but have had no luck. I tried changing the server.js but it affected my queries from running so I reverted.
/graphql/resolvers/post.js
const Post = require('../../models/post.js');
const { GraphQLDateTime } = require ('graphql-iso-date');
const customScalarResolver = {
Date: GraphQLDateTime
};
function posts() {
return Post.find({});
}
function post(args) {
return Post.findById(args.id)
}
function createPost(args) {
let post = new Post(args.postInput);
return post.save();
}
function deletePost(args) {
return Post.findByIdAndRemove(args.id);
}
function updatePost(args) {
return Post.findByIdAndUpdate(args.id, args.postInput, { new: true });
}
module.exports = { posts, post, createPost, deletePost, updatePost, customScalarResolver}
I have 3 sequelize models that i have defined imported into a file called sequelize.js like so:
const { Sequelize } = require("sequelize");
const UserModel = require("./models/user");
const ItemModel = require("./models/item");
const ReservationModel = require("./models/reservation");
const config = require("./dbconfig");
const db = config.database;
const Item = ItemModel(sequelize, Sequelize);
const User = UserModel(sequelize, Sequelize);
const Reservation = ReservationModel(sequelize, Sequelize);
Reservation.hasMany(Item);
Item.belongsTo(Reservation);
Reservation.belongsTo(User);
I then try to export them:
module.exports = { Item, User, Reservation };
However, when I try to access one of them and use a model function, I get an error.
const Model = require("../../sequelize");
const passport = require("passport");
module.exports = (app) => {
app.post("/registerUser", (req, res, next) => {
passport.authenticate("register", (err, user, info) => {
if (err) {
console.log(err);
}
if (info !== undefined) {
console.log(info.message);
res.send(info.message);
} else {
req.logIn(user, (err) => {
const data = {
first_name: req.body.first_name,
last_name: req.body.last_name,
email: req.body.email,
username: user.email,
};
Model.User.findOne({
where: {
email: data.username,
},
}).then((user) => {
user
.update({
first_name: data.first_name,
last_name: data.last_name,
email: data.email,
})
.then(() => {
console.log("user created in db");
res.status(200).send({ message: "user created" });
});
});
});
}
})(req, res, next);
});
};
results in
TypeError: User.findOne is not a function
This is not an issue when I just export one of them.
module.exports = User;
const User = require("./sequelize");
...
User.findOne(...) //works
I've tried multiple ways of exporting, but none seem to work.
e.g
module.exports = {
Item: Item,
User: User,
Reservation: Reservation,
}
and
exports.Item = Item;
exports.User = User;
exports.Reservation = Reservation;
edit: Here is my user model for reference
module.exports = (sequelize, type) => {
return sequelize.define(
"user",
{
id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true,
},
first_name: type.STRING,
last_name: type.STRING,
credentials: type.STRING,
email: {
type: type.STRING,
allowNull: false,
},
password: {
type: type.STRING,
allowNull: false,
},
},
{
tableName: "Users",
}
);
};
Why cant I export these multiple objects?
I have the exact structure you're using by importing all sequelize models into one file then module.exporting them in an object and the only thing I see thats different is how you define your models. I might be out of date but I learned as such:
const Sequelize = require('sequelize');
const db = require('../db');
module.exports = db.define('users', {
id: {
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
unique: true
},
}, {
timestamps: true,
});
Db declaration
const Sequelize = require('sequelize');
const db = new Sequelize(
process.env.DATABASE_URL, {
logging: false
}
);
module.exports = db;
Then your central import
const User = require('./user');
const Order = require('./order');
Order.belongsTo(User)
User.hasMany(Order)
module.exports = {
User,
Order
};
Then using it
const models = require('./models');
const results = await models.User.destroy({
where: {
id: id
}
});
if(results){
return results;
}
Found what was wrong. In my passport.js file, where I defined my localStrategy, I was doing an incorrect import.
My export in sequelize.js was
modules.export = {Item, User, Reservation};
while my import in passport.js was just
const User = require("../sequelize");
when it should have been
const Model = require("../sequelize");
const User = Model.User;
looks like I had it imported correctly in my signUp route, but not in my passport config file!
I have an issue with the Authenticati onController used with sequelize and sqlite
When I test the POST request using postman, it always gives status 400 with the response
{
error: 'Something is wrong'
}
This is the log
::1 - - [21/Jul/2020:15:40:33 +0000] "POST /register HTTP/1.1" 400 30 "-" "PostmanRuntime/7.26.1"
Here is the code of AuthenticationController
const {User} = require('../models')
module.exports = {
async register(req, res){
try {
const user = await User.create(req.body)
res.send(user.toJSON())
} catch (error) {
console.log(error)
res.status(400).send({
error: 'Something is wrong'
})
}
}
}
User model code
module.exports = (sequelize, DataTypes) =>
sequelize.define('User', {
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
})
models index code
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.database,
config.db.user,
config.db.password,
config.db.options
)
fs
.readdirSync(__dirname)
.filter((file)=>{
file != 'index.js'
})
.forEach((file)=>{
const model = require(path.join(__dirname, file))(
sequelize,
Sequelize.DataTypes
);
// const model = sequelize.import(path.join(__dirname,file))
db[model.name] = model
})
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db
routes code
const AuthenticationController = require('./controllers/AuthenticationController');
module.exports = (app) => {
app.post('/register',
AuthenticationController.register)
}
Earlier, it was throwing an error of "TypeError: Cannot read property 'create' of undefined"
But when I restarted the server, that was fixed. But I have no clues as to why the try block fails.
Anyone could throw some light on this? Thank you
Here is the revised code for /models/index.js
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.database,
config.db.user,
config.db.password,
config.db.options
)
fs.readdirSync(__dirname)
// .filter((file) => {
// file != "index.js";
// })
.filter(
(file) =>
file.indexOf(".") !== 0 && file !== "index.js" && file.slice(-3) === ".js"
)
.forEach((file) => {
const model = require(path.join(__dirname, file))(
sequelize,
Sequelize.DataTypes
);
// const model = sequelize.import(path.join(__dirname,file))
db[model.name] = model;
});
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db
The filter block was updated as shown in the revised, with the help of the link
https://www.codota.com/code/javascript/functions/sequelize/Sequelize/import
The 2 things that were changed are
Replaced the 'sequelize.import' with 'require'
Updated the 'filter' block as shown.
Here is the result:
Thanks to crumkev for the insight which led me find the answer.
I'm building a project with Express, trying to use the Sequelize ORM to access a mySQL database.
The errors I'm getting waver between not having models defined and findAll of Orders being a function and not an object I can query.
Is there an obvious flaw in my setup? Thanks!
Order.js:The Model
'use strict';
module.exports = (sequelize, DataTypes) => {
var Order = sequelize.define('stores', {
index: DataTypes.INTEGER,
server: DataTypes.STRING,
gridName: DataTypes.STRING,
x: DataTypes.INTEGER,
y: DataTypes.INTEGER,
z: DataTypes.INTEGER,
owner: DataTypes.STRING,
item: DataTypes.STRING,
deal: DataTypes.STRING,
quantity: DataTypes.INTEGER,
price: DataTypes.INTEGER,
GPS: DataTypes.STRING
});
return Order;
};
index.js:The model aggregator
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(module.filename);
const env = process.env.NODE_ENV || 'development';
// const config = require(__dirname + '/..database.json')[env];
const db = {};
let sequelize;
// if (config.use_env_variable) {
// sequelize = new Sequelize(process.env[config.use_env_variable]);
// } else {
sequelize = new Sequelize('db', 'user', 'pw', {
host: 'ip',
dialect: 'mysql2'
});
// }
fs
.readdirSync(__dirname)
.filter(function(file) {
return file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js';
})
.forEach(function(file) {
var model = sequelize['import'](path.join(__dirname, file));
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;
marketRoutes.js:The query controller
const models = require('../models');
module.exports = (app) => {
app.get('/api/requestOrders', (req, res) => {
console.log('hitting route', models.Order);
models.Order
.findAll()
.then(function(orders) {
console.log(orders);
})
.catch(function(err) {
console.log(err);
});
});
};
I think marketRoutes.js is looking for models in the wrong place. Shouldn't you be require index.js, so you can access the models imported from the file system and stored in the db object?
(I use a models directory... but there are some advantages to using sequelize.import)
I need to connect to different databases depending on the Express route.
For example:
example.com/oneapp
This route must access a database called oneapp
example.com/secondapp
This route must access a database called secondapp
I have these settings in my Sequelize
index.js:
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const config = require('../../config/database.js');
const db = {};
const sequelize = new Sequelize(config.producao);
fs
.readdirSync(__dirname)
.filter(file => (file.indexOf('.') !== 0) && (file !== path.basename(__filename)) && (file.slice(-3) === '.js'))
.forEach((file) => {
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
console.log(db)
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
database.js
module.exports = {
"producao": {
username: 'sa',
password: 'mypass',
database: 'PRODUCAO',
host: 'SVRNAZ002',
dialect: 'mssql',
}
}
Run that code twice with different db settings and keep two sets of the sequelize connection object and array of models.
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const configs = [require('../../config/database.js'), require('../../config/database2.js')];
module.exports = configs.map(config => {
const db = {};
const sequelize = new Sequelize(config.producao);
// load stuff like normal
db.sequelize = sequelize;
db.Sequelize = Sequelize;
return db;
});
Now you can access both:
const models = require('index');
const firstdb = models[0];
const seconddb = models[1];
maybe this is not the right answer, but I use it and it works.
first I use it for databases usually, the second for images
db.js
const {Sequelize} = require('sequelize')
const config = [
{
dialect: 'sqlite',
storage: './db.sqlite'
},
{
dialect: 'sqlite',
storage: './db_gambar.sqlite'
}
]
const database = config.map( x => new Sequelize(x));
module.exports = { database }
./models/akun.js
const { DataTypes, Model } = require('sequelize');
const { database} = require('./../db');
const sequelize = database[0];
// Tambahan is extend Model
class Akun extends Tambahan{}
Akun.init({
name: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING,
allowNull: false,
}
},{ sequelize, underscored: true})
./models/gambar.js
const { DataTypes, Model } = require('sequelize');
const { database } = require('./../db');
const sequelize = database[1];
// Tambahan is extend Model
class Gambar extends Tambahan{}
Gambar.init({
name: {
type: DataTypes,
allowNull: false
},
user_id: {
type:DataTypes.INTEGER,
allowNull: false
},
data: {
type:DataTypes.BLOB,
allowNull: false
},
thumbnail: {
type: DataTypes.BLOB,
allowNull: false
}
},{ sequelize , underscored: true})