Reputation: 1395
I am learning how to use Sequelize ORM in Nodejs and save data in Postgres Database.
My goal is to insert user data into Users table. I have created the table using migration, and it works. However, I am not able to save users data. I 've followed many resources for example Tut 1 Tut 2, etc.. , I still get the same error
C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\database\models\index.js:12
if (config.use_env_variable) {
^
TypeError: Cannot read property 'use_env_variable' of undefined
at Object.<anonymous> (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\database\models\index.js:12:12)
at Module._compile (internal/modules/cjs/loader.js:776:30)
at babelWatchLoader (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\node_modules\babel-watch\runner.js:51:13)
at Object.require.extensions.(anonymous function) [as .js] (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\node_modules\babel-watch\runner.js:62:7)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Module.require (internal/modules/cjs/loader.js:690:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object.<anonymous> (C:\Users\HP\Desktop\Andela\project\Tutorials\react-project\chat_app_api\server\server.js:1:1)
at Module._compile (internal/modules/cjs/loader.js:776:30)
at babelWatchLoader (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\node_modules\babel-watch\runner.js:51:13)
at Object.require.extensions.(anonymous function) [as .js] (C:\Users\HP\Desktop\path\project\Tutorials\react-project\chat_app_api\node_modules\babel-watch\runner.js:62:7)
config/config.js
require('dotenv').config();
module.exports = {
development: {
use_env_variable: 'DATABASE_URL_DEV',
dialect: 'postgres',
},
test: {
use_env_variable: 'DATABASE_URL_TEST',
dialect: 'postgres',
},
production: {
use_env_variable: 'DATABASE_URL',
dialect: 'postgres',
ssl: true,
dialectOptions: {
ssl: true,
},
},
};
migrations/20190927083519-create-user.js
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
},
fullname: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
username: {
type: Sequelize.STRING
},
telephone: {
type: Sequelize.STRING
},
image: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Users');
}
};
models/index.js
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.js')[env]; // why this return Undefined ?
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);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = sequelize['import'](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;
models/users
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
fullname: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING,
username: DataTypes.STRING,
telephone: DataTypes.STRING,
image: DataTypes.STRING
}, {});
User.associate = function (models) {
// associations can be defined here
};
return User;
};
app.js
import express from 'express';
import cors from 'cors';
import morgan from 'morgan';
import bodyParser from 'body-parser';
import { errors } from 'celebrate';
import routes from './Routes/index';
const app = express();
app.use(cors());
app.use(morgan('combined'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/api', routes);
app.use(errors());
app.use((req, res) => {
const error = new Error('Route not found');
error.status = 404;
return res.status(error.status).json({
status: error.status,
message: error.message,
});
});
// Server Error
app.use((error, req, res) => {
const status = error.status || 500;
return res.status(status).json({
status,
message: error.message || 'Server error',
});
});
export default app;
.env
DATABASE_URL_DEV=postgres://postgres:.@localhost:5432/db_dev
DATABASE_URL_TEST=postgres://postgres:.@localhost:5432/db_test
DATABASE_URL=postgres://user:password@host:5432/db_remote
controllers/userControllers.js
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';
import models from '../../database/models';
import uploadImage from '../Helpers/upload.Image';
dotenv.config();
class UserController {
static async signup(req, res) {
const { body: input } = req;
input.password = bcrypt.hashSync(input.password, 10);
try {
const image = await uploadImage(req, res);
const { secure_url: img } = await image;
input.image = img;
console.log('result before ########################', models.User); // Undefined
const result = await models.User.create(input);
console.log('result after ########################', result); // Error here
delete result.dataValues.password;
const token = jwt.sign(result.dataValues, process.env.SECRET_KEY, { expiresIn: '1W' });
result.dataValues.token = token;
const status = 201;
return res.status(status).json({
status,
message: 'User successfully created',
data: result.dataValues,
});
} catch (error) {
console.log('error########################', error);
let { message } = error.errors[0];
const status = 500;
message = message || 'Server error';
return res.status(status).json({
status,
message,
});
}
}
}
export default UserController;
I still don't know why in models/index.js my config variable return undefined.
require(__dirname + '/../config/config.js') // return object
env // return environment
const config = require(__dirname + '/../config/config.js')[env]; //return Undefined
I spent 3 days debugging but I can not solve the Error. any help, guidance is highly appreciated.
Thanks
Upvotes: 1
Views: 4977
Reputation: 1395
Guyz, I found an answer to my problem,
in models/index.js
I change process.env.NODE_ENV to process.env.NODE_ENV.trim()
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
// Before
const env = process.env.NODE_ENV || 'development';
// After
const env = process.env.NODE_ENV.trim() || 'development'; // add .trim()
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;
db.Sequelize = Sequelize;
module.exports = db;
Further Details
package.json
"scripts": {
"db:migrate:dev": "sequelize db:migrate --env development",
"db:migrate:test": "sequelize db:migrate --env test",
"db:migrate:production": "sequelize db:migrate --env production",
"db:reset": "sequelize db:migrate:undo",
"start": "SET NODE_ENV=production && babel-watch server/server.js",
"dev": "SET NODE_ENV=development && babel-watch server/server.js",
"test": "SET NODE_ENV=testing && babel-watch server/server.js"
}
Example, Let's say if I start the server by typing in the terminal
npm run dev
If i do console.log(process.env.NODE_ENV) // output is "development " with a space.
Hence,
process.env.NODE_ENV === "development" // return false
or
"development " === "development" // return false
Javascript Trim() remove whitespace from both sides of a string
You want more resource? please visit w3c
Upvotes: 2