ERROR: Error parsing url: undefined when migrating database to heroku - javascript

I'm using Sequelize as an ORM and I'm trying to migrate my database to Heroku. When running heroku run sequelize db:migrate
I just get
Loaded configuration file "config/config.js".
Using environment "production".
ERROR: Error parsing url: undefined
Here's what my config file looks like:
module.exports = {
"development": {
"username": "root",
"password": "password",
"database": "vueapp",
"host": "127.0.0.1",
"dialect": "postgres"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"use_env_variable": process.env.DATABASE_URL,
"dialect": "postgres",
"ssl": true,
"dialectOptions": {
"ssl": true
}
}
}
And the index file
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')[env];
const User = require("./user")
const Hour = require('./hours');
const db = {
User,
Hour
};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(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;
Not entirely sure what the issue is. Going through the heroku logs, I see a throw new Error('Dialect needs to be explicitly supplied as of v4.0.0');
But I have added the dialect in the config.js file. Does it matter if the config file is a .js file or a .json file?
Just to clarify, the actual web app opens up and I can see the error handler that I set up. So I'm not actually getting an application error when opening up the route URL

production: {
use_env_variable: 'DATABASE_URL',
},
change your production to this and go to heroku to set environmental variable

Did you later solve the problem

This is a little confusing but Damilola is correctly. You need need to leave the value for use_env_variable to 'DATABASE_URL'. You will be tempted to change this to process.env.DATABASE_URL. This is incorrect.
Leaving it like this will allow Sequelize to inject the value that is saved to the Heroku env variable DATABASE_URL.
production: {
use_env_variable: 'DATABASE_URL',
dialect: "postgres",
protocol: "postgres"
}

Related

Linux - NodeJS, Express, PostgreSQL - ErrorHandler: password authentication failed for user "root"

Edit -
Success! I should have RTFM it seems. Using the environmental variables seems to be required to be EXACT to the manual.
Fixed code:
# PostgreSQL Database Infomation
PGDATABASE_TEST = user_db
PGDATABASE = user_db
PGUSER = postgres
PGPASSWORD = password
# PostgreSQL Host and Port Infomation
PGHOST = localhost
PGPORT = 5432
--
I'm using .env variables to connect to a Postgres Database.
When submitting data via Postman to a Express API I receive an error stating the following:
throw new ErrorHandler(error.statusCode, error.message)
^
ErrorHandler: password authentication failed for user "tito"
at UserService.createUserAccount (/home/tito/Documents/GitHub/***/server/services/user.service.js:11:19)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async createUserAccount (/home/tito/Documents/GitHub/***/server/controllers/user.controller.js:11:18) {
status: 'error',
statusCode: undefined
}
As you can see, its using my OS username rather than .env set one. When running node with sudo I get the auth error with root.
My db.js:
require("dotenv").config();
const { Pool } = require("pg");
// Check which Database to use. Live is safe.
const isProduction = process.env.NODE_ENV === 'PRODUCTION';
const database = process.env.NODE_ENV === 'TEST' ? process.env.PG_TEST_DATABASE : process.env.PG_DATABASE;
// Request to Database contructed
const connectionString = `postgresql://${process.env.PG_USER}:${process.env.PG_PASS}#${process.env.PG_HOST}:${process.env.PG_PORT}/${database}`;
// Setup Pool.
const pool = new Pool ({
connectionString: isProduction ? process.env.DATABASE_URL : connectionString,
ssl: isProduction ? { rejectUnauthorized: false } : false
});
console.log(`Ready at : ${connectionString}`)
module.exports = {
query: (text, params) => pool.query(text, params),
end: () => pool.end()
}
My .env:
# Express API Port.
PORT = 5000
# Enviroment - TEST for local. PRODUCTION for live.
NODE_ENV = PRODUCTION
# PostgreSQL Database Infomation
PG_TEST_DATABASE = user_db
PG_DATABASE = user_db
PG_USER = postgres
PG_PASS = password
# PostgreSQL Host and Port Infomation
PG_HOST = localhost
PG_PORT = 5432
My UserService:
const {
createUserAccount_DB
} = require("../db/user.db");
const { ErrorHandler } = require("../helpers/error")
class UserService {
createUserAccount = async (user) => {
try {
return await createUserAccount_DB(user);
} catch (error) {
throw new ErrorHandler(error.statusCode, error.message)
}
}
}
module.exports = new UserService();
And my createUserAccount:
const userService = require("../services/user.service");
const { ErrorHandler } = require("../helpers/error");
const createUserAccount = async (req, res) => {
console.log("Create Account API Triggered");
const { user_name, user_pass, user_email } = req.body;
// const hashedPassword = hashedPassword(password);
const user = await userService.createUserAccount({
user_name,
user_pass,
user_email
});
res.status(201).json({
status: "success",
user,
})
};
Success! I should have RTFM it seems. Using the environmental variables seems to be required to be EXACT to the manual.
Fixed code:
# PostgreSQL Database Infomation
PGDATABASE_TEST = user_db
PGDATABASE = user_db
PGUSER = postgres
PGPASSWORD = password
# PostgreSQL Host and Port Infomation
PGHOST = localhost
PGPORT = 5432

SyntaxError: Unexpected token * after importing sequelize model db object

I am working on an app where I have to connect and perform queries on an SQL server using Sequelize. I have created migrations, seeders, and models using sequelize init but now when I tried to create an object of models using const db = require("./models") it is throwing error like
D:\Code Practice\express-sequelize-demo\node_modules\tedious\lib\token\stream-parser.js:85
static async *parseTokens(iterable, debug, options, colMetadata = []){
SyntaxError: Unexpected token *
at createScript (vm.js:80:10)
at Object.runInThisContext (vm.js:139:10)
at Module._compile (module.js:616:28)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (D:\Code Practice\express-sequelize-demo\node_modules\tedious\lib\token\token-stream-parser.js:10:44)
Files I created
package.json
{
"name": "express-sequelize-demo",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"start": "nodemon app.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"mssql": "^7.1.0",
"sequelize": "^6.6.2",
"tedious": "^11.0.9"
},
"devDependencies": {
"nodemon": "^2.0.7"
}
}
app.js
const express = require("express");
const app = express();
const PORT = 8088;
// throwing error here after importing
const db = require("./models");
app.get("/users", (req, res) => {
res.send({
status: 1,
message: "Hello from User",
});
});
app.get("/", (req, res) => {
res.send({
status: 1,
message: "Welcome to Home Page",
});
});
app.listen(PORT, () => {
console.log(`App is running on ${PORT}`);
});
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.json")[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
);
console.log(sequelize);
}
fs.readdirSync(__dirname)
.filter((file) => {
return (
file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js"
);
})
.forEach((file) => {
const model = require(path.join(__dirname, file))(
sequelize,
Sequelize.DataTypes
);
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/user.js
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class User extends Model {
static associate(models) {
// define association here
}
};
User.init({
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
bio: DataTypes.TEXT
}, {
sequelize,
modelName: 'User',
});
return User;
};
5)config.json
{
"development": {
"username": "SA",
"password": "Password123",
"database": "database_development",
"host": "localhost",
"dialect": "mssql"
},
"test": {
"username": "root",
"password": "Password123",
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mssql"
},
"production": {
"username": "root",
"password": "Password123",
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mssql"
}
}
I have resolved this issue by updating the node version.
Here the issue was when I try to create sequelize instances using
const sequelize = new Sequelize(DB connection params); //pass the actual db config
it was throwing that error.
SyntaxError: Unexpected token *
But after some research, I updated my node version from 8.11.4 to 14.17.0 and it worked. Now without any error, I can run my application and it is working as expected.

Heroku with Strapi, Application is not using production database

I've deployed my app to Heroku. It gives an Application Error message upon visit.
The logs gave me this:
[2021-02-15T01:04:05.882Z] debug ⛔️ Server wasn't able to start properly.
[2021-02-15T01:04:05.883Z] error Error: connect ECONNREFUSED 127.0.0.1:5432
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1146:16)
Which according to my guess, is that its trying to use local database. I think the app is not using the database.js located in config/env/production. The application runs fine with heroku local.
Below is the database.js I set for production env:
const parse = require("pg-connection-string").parse;
const config = parse(process.env.DATABASE_URL);
module.exports = ({ env }) => ({
defaultConnection: "default",
connections: {
default: {
connector: "bookshelf",
settings: {
client: "postgres",
host: config.host,
port: config.port,
database: config.database,
username: config.user,
password: config.password,
ssl: {
rejectUnauthorized: false,
},
},
options: {
ssl: true,
},
},
},
});
Creating and printing the config var on heroku console results in expected values.
For some reason the deployment method in the strapi docs to heroku does not seem to work when you initially have set up your local database as Postgres.
I had the same problem as you and I fixed it using the NODE_ENV env variable.
Instead of creating a new production database config file in ./config/production/database.js you can simply extend the config file in ./config/database.js with the prod config and decide based on what NODE_ENV is set which one to return.
As example:
module.exports = ({ env }) => {
const parse = require("pg-connection-string").parse;
const config = parse(env("DATABASE_URL", "127.0.0.1"));
const devConfig = {
client: "postgres",
connection: {
host: env("DATABASE_HOST", "127.0.0.1"),
port: env.int("DATABASE_PORT", 5432),
database: env("DATABASE_NAME", "db_name"),
user: env("DATABASE_USERNAME", "root"),
password: env("LOCAL_DB_PASSWORD"),
ssl: env.bool("DATABASE_SSL", false),
},
};
const prodConfig = {
client: "postgres",
connection: {
host: config.host,
port: config.port,
database: config.database,
user: config.user,
password: config.password,
ssl: {
rejectUnauthorized: false,
},
},
debug: false,
};
return
env("NODE_ENV", "development") === "production" ? prodConfig : devConfig
};

Why Sequelize migration create table but models can not connect to a database

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
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

Sequelize sqlite3 connects to database but throw error when fetching data

I'm using sequelize with sqlite3 inside nodejs.
The connection to database file runs fine with no error, but when trying to access it for the first time I'm getting the following error (no matter what table or query I try to do):
TypeError: Cannot read property 'findOne' of undefined
at l.a.sequelize.authenticate.then (/usr/local/bin/aeirtu/node/webpack:/server.js:55:1)
at tryCatcher (/usr/local/bin/aeirtu/node/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/usr/local/bin/aeirtu/node/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/usr/local/bin/aeirtu/node/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/usr/local/bin/aeirtu/node/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/usr/local/bin/aeirtu/node/node_modules/bluebird/js/release/promise.js:693:18)
at Async._drainQueue (/usr/local/bin/aeirtu/node/node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (/usr/local/bin/aeirtu/node/node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues [as _onImmediate] (/usr/local/bin/aeirtu/node/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:763:18)
at tryOnImmediate (timers.js:734:5)
at processImmediate (timers.js:716:5)
Here is my connection code:
My node.js code:
import express from "express";
import models from "./models";
const app = express();
models.sequelize
.authenticate()
.then(() => {
console.log("Connected to repository");
})
.catch(err => {
console.log("ERROR connecting to repository.");
console.log(err);
});
let port = 3001;
app.listen(port, () => {
console.log("Server listening on port " + port);
});
My models.js:
import Sequelize from "sequelize";
import fs from "fs";
import path from "path";
const DATABASE_FILENAME = "test.db";
const fileWithPath = path.join(process.env.TEST_HOME, 'data', DATABASE_FILENAME);
let basename = path.basename(__filename);
let env = process.env.NODE_ENV || "development";
let db = {};
console.log("Connecting to repository at " + fileWithPath);
// database wide options
let opts = {
dialect: "sqlite",
storage: fileWithPath,
define: {
//prevent sequelize from pluralizing table names
freezeTableName: true,
// don't add the timestamp attributes (updatedAt, createdAt)
timestamps: false
},
operatorsAliases: Sequelize.Op, // use Sequelize.Op https://github.com/sequelize/sequelize/issues/8417#issuecomment-334056048
};
let sequelize = new Sequelize(DATABASE_FILENAME, null, null, opts);
fs
.readdirSync(__dirname)
.filter(file => {
return (
file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js"
);
})
.forEach(file => {
let 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;
export default db;
And a simple test code:
import db from "./models";
db.TestTable.findOne().then(data => {
if (!data) console.log("ERROR FETCHING DATA");
console.log(data.name);
});
I've triple checked: the sqlite3 file is in the correct location and the tables are there with data. For some reason I'm not being able to access then. I've also changed chmod a+rwx at the database file.
you forgot to import the *TestTable model`
db.TestTable = require('./TestTable')(sequelize, Sequelize);
your model.js should be a connection
but there are no define model yet like
module.exports = (sequelize, DataTypes) => {
const testTable = sequelize.define('model', {
states: {
type: Sequelize.ENUM,
values: ['active', 'pending', 'deleted']
}
});
return testTable;
};
Sample

Categories

Resources