Express generator and Sequelize to AWS Elastic BeanStalk - node.js

I made a API express app using express generator and Sequelize ORM, it works great on my local machine using sqlite, I had it deployed on Heroku at one point, but not much for tutorials on how to deploy to AWS Elastic Beanstalk....
bin/www
...
const { sequelize } = require('../models');
...
(async() => {
try {
await sequelize.authenticate();
await sequelize.sync();
console.log(`Connection successful!! on port:${port}`)
}catch(err) {
console.log("Connection failed:", err)
}
}) ();
config/config.json- this worked with postgres on heroku at one point
{
"development": {
"username": "root",
"password": null,
"database": "database_development",
"storage" : "GetNailed",
"dialect": "sqlite"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"use_env_variable": "DATABASE_URL",
"dialect": "postgres",
"dialectOptions": {
"ssl": {
"require": true,
"rejectUnauthorized": false
}
}
}
}
app.js
...
const {sequelize} = require('./models')
async function main() {
await sequelize.sync()
}
main()
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
const adminRouter =require('./routes/admin');
const nailsRouter = require('./routes/nails')
...

Related

MangoDB Compass can not connect to my backend using TypeORM

I am trying to create a simple web application where I can diplay users from a MongoDB database on a React web application.
However I am stuck on a problem with TypeORM and my MongoDB database. Indeed, my backend repository can not access to the database.
Here is my package.json file :
{
"name": "backend",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"build": "tsc",
"dev": "nodemon index.ts",
"start": "node ./dist/index.js",
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/.bin/typeorm",
"migration:generate": "npm run typeorm -- migration:generate --config src/config/ormconfig.json --connection --name ",
"migration:run": "npm run typeorm -- migration:run"
},
"license": "UNLICENSED",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"mongodb": "^3.6.0",
"typeorm": "^0.3.11"
},
"devDependencies": {
"#types/cors": "^2.8.13",
"#types/express": "^4.17.14",
"#types/mongodb": "^4.0.7",
"#types/node": "^18.11.8",
"nodemon": "^2.0.20",
"ts-node": "^10.9.1",
"typescript": "^4.8.4"
}
}
Here is my connectionService.ts file, which is supposed to create the connection to the database :
import { DataSource, DataSourceOptions } from "typeorm"
import { Utilisateurs } from "../entities/utilisateurs";
class connectionServices{
public myDataSource:DataSource;
constructor(dbConfig: DataSourceOptions){
this.myDataSource = new DataSource(dbConfig)
}
public async getUsers (){
const myusers = this.myDataSource.getMongoRepository(Utilisateurs);
const data = await myusers.find({});
console.log (data);
return data;
}
}
export default (connectionServices);
Here is my index.ts file :
import express from 'express';
import cors from 'cors';
import connectionServices from "./service/connectionService";
function main() {
const app = express();
const service = new connectionServices({
type: "mongodb",
url: "mongodb://localhost:27017",
port: 27017,
database: "users",
synchronize: true,
entities: [
"src/entities/**/*.ts"
],
});
app.use(cors())
app.get('/users/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
app.get('/', (req, res) => {
res.send('Well done!');
})
app.listen(4321, () => {
console.log('The application is listening on port 4321!');
})
app.get('/users', (req,res) => {
res.send(service.getUsers());
})
}
main();
And finally here is my ormconfig.json file :
{
"type": "mongodb",
"host": "localhost",
"url": "mongodb://localhost:27017",
"port": 27017,
"database": "test",
"synchronize": true,
"logging": false,
"entities": [
"src/entity/**/*.ts"
],
"migrations": [ "src/migration/**/*.ts"
],
"subscribers": [ "src/subscriber/**/*.ts"
],
"cli": {
"entitiesDir": "src/entity", "migrationsDir": "src/migration", "subscribersDir": "src/subscriber"
}
}
The backend builds and launches properly :
However when I type in the url http://localhost:4321/users, I get this error in my terminal and the backend crashes :
I have tried to put the url of the data base, or put the parameter "host": "localhost" with the correct port but nothing worked.
I have looked on several tutorials, videos without success...
If someone sees the solution to my problem that would be great!
You didn't provide your entities. however, I think the problem occurred because typeorm couldn't find your entities.
try changing src/entity/**/*.ts to src/entity/**/*{.ts,.js}.
Do the same thing for migration and subscribers if needed.
In fact the problem was in the index.ts file and in the connectionService.ts file.
In the service, it was missing a function in order to connect to the data base :
import { createConnection, DataSource, DataSourceOptions } from "typeorm"
import { Utilisateurs } from "../entities/utilisateurs.entity";
class connectionServices{
public myDataSource:DataSource;
async connect(){
await this.myDataSource.connect();
}
constructor(dbConfig: DataSourceOptions){
this.myDataSource = new DataSource(dbConfig);
}
public async getUsers (){
const myusers = this.myDataSource.getMongoRepository(Utilisateurs);
const data = await myusers.find({});
console.log (data);
return data;
}
}
export default (connectionServices);
And in the index.ts file, I was calling the promise of a table containing the date, and not the data. Here is the working file :
import express from 'express';
import cors from 'cors';
import connectionServices from "./service/connectionService";
import { Utilisateurs } from './entities/utilisateurs.entity';
async function main() {
const app = express();
const service = new connectionServices({
type: "mongodb",
host: "localhost",
port: 27017,
database: "users",
synchronize: true,
entities: [
Utilisateurs
],
});
await service.connect();
app.use(cors())
app.get('/users/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
app.get('/', (req, res) => {
res.send('Well done!');
})
app.listen(4321, () => {
console.log('The application is listening on port 4321!');
})
app.get('/users', async(req,res) => {
res.send(await service.getUsers());
})
}
main();
With these modifications, everything works properly.

Trouble connecting express api to nuxt app and mongodb

It's been seriously 10 days since i'm trying to deploy my web app online. i've gone back and forth between heroku and digital ocean. nothing solved. i've asked questions here all i get is a long post with technical terms i' not able to understand. Here's my problem :
i have a nuxt app with express.js in the backend and mongodb as the database. At first i had trouble with configuring host and port for my nuxt app. once i fixed it, anoither problem appeared : i'm not receiving data from the database. i don't if it's something related to database connection or with the express api configuration.
here's my nuxt config
export default {
ssr: false,
head: {
titleTemplate: 'Lokazz',
title: 'Lokazz',
meta: [
{ charset: 'utf-8' },
{
name: 'viewport',
content: 'width=device-width, initial-scale=1'
},
{
hid: 'description',
name: 'description',
content:
'Lokazz'
}
],
link: [
{
rel: 'stylesheet',
href:
'https://fonts.googleapis.com/css?family=Work+Sans:300,400,500,600,700&subset=latin-ext'
}
]
},
css: [
'swiper/dist/css/swiper.css',
'~/static/fonts/Linearicons/Font/demo-files/demo.css',
'~/static/fonts/font-awesome/css/font-awesome.css',
'~/static/css/bootstrap.min.css',
'~/assets/scss/style.scss'
],
plugins: [
{ src: '~plugins/vueliate.js', ssr: false },
{ src: '~/plugins/swiper-plugin.js', ssr: false },
{ src: '~/plugins/vue-notification.js', ssr: false },
{ src: '~/plugins/axios.js'},
{ src: '~/plugins/lazyLoad.js', ssr: false },
{ src: '~/plugins/mask.js', ssr: false },
{ src: '~/plugins/toastr.js', ssr: false },
],
buildModules: [
'#nuxtjs/vuetify',
'#nuxtjs/style-resources',
'cookie-universal-nuxt'
],
styleResources: {
scss: './assets/scss/env.scss'
},
modules: ['#nuxtjs/axios', 'nuxt-i18n','vue-sweetalert2/nuxt', '#nuxtjs/auth-next', "bootstrap-vue/nuxt"],
bootstrapVue: {
bootstrapCSS: false, // here you can disable automatic bootstrapCSS in case you are loading it yourself using sass
bootstrapVueCSS: false, // CSS that is specific to bootstrapVue components can also be disabled. That way you won't load css for modules that you don't use
},
i18n: {
locales: [
{ code: 'en', file: 'en.json' },
],
strategy: 'no_prefix',
fallbackLocale: 'en',
lazy: true,
defaultLocale: 'en',
langDir: 'lang/locales/'
},
router: {
linkActiveClass: '',
linkExactActiveClass: 'active',
},
server: {
port: 8080, // default: 3000
host: '0.0.0.0' // default: localhost
},
auth: {
strategies: {
local: {
token: {
property: "token",
global: true,
},
redirect: {
"login": "/account/login",
"logout": "/",
"home": "/page/ajouter-produit",
"callback": false
},
endpoints: {
login: { url: "/login", method: "post" },
logout: false, // we don't have an endpoint for our logout in our API and we just remove the token from localstorage
user:false
}
}
}
},
};
here's my package.json
{
"name": "martfury_vue",
"version": "1.3.0",
"description": "Martfury - Multi-purpose Ecomerce template with vuejs",
"author": "nouthemes",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
},
"config": {
"nuxt": {
"host": "0.0.0.0",
"port": "8080"
}
},
}
here's my repository.js file
import Cookies from 'js-cookie';
import axios from 'axios';
const token = Cookies.get('id_token');
const baseDomain = 'https://lokazzfullapp-8t7ec.ondigitalocean.app';
export const customHeaders = {
'Content-Type': 'application/json',
Accept: 'application/json'
};
export const baseUrl = `${baseDomain}`;
export default axios.create({
baseUrl,
headers: customHeaders
});
export const serializeQuery = query => {
return Object.keys(query)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`)
.join('&');
};
an example of an api call i make locally that works without a problem :
import Repository, { serializeQuery } from '~/repositories/Repository.js';
import { baseUrl } from '~/repositories/Repository';
import axios from 'axios'
const url = baseUrl;
export const actions = {
async getProducts({ commit }, payload) {
const reponse = await axios.get(url)
.then(response => {
commit('setProducts', response.data);
return response.data;
})
.catch(error => ({ error: JSON.stringify(error) }));
return reponse;
},
}
here's my index.js (express file)
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose')
const cors = require('cors');
//const url = 'mongodb://localhost:27017/lokazz'
const url = 'mongodb+srv://lokazz:zaki123456#cluster0.hsd8d.mongodb.net/lokazz?retryWrites=true&w=majority'
const jwt = require('jsonwebtoken')
const con = mongoose.connection
mongoose.connect(url, {useNewUrlParser:true}).then(()=>{
const app = express();
// middlleware
app.use(express.json())
app.use(cors());
//products routes
const products = require('./product/product.router');
app.use('/', products)
//users routes
const users = require('./user/user.router');
app.use('/', users)
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server started on port ${port}`));
}).catch(error => console.log(error.reason));
con.on('open', () => {
console.log('connected...')
})
My directory structure
the error i get after the api request, meaning it's not receving any data.
ebd1ecd.js:2 TypeError: Cannot read properties of undefined (reading 'username')
at f.<anonymous> (c88240c.js:1)
at f.t._render (ebd1ecd.js:2)
at f.r (ebd1ecd.js:2)
at wn.get (ebd1ecd.js:2)
at new wn (ebd1ecd.js:2)
at t (ebd1ecd.js:2)
at f.In.$mount (ebd1ecd.js:2)
at init (ebd1ecd.js:2)
at ebd1ecd.js:2
at v (ebd1ecd.js:2)
idk if it's a problem with mongodb connection cluster or the api call.

Sequalize won't create table but server is running without errors

This is the first time I'm using sequelize and i ran into a problem with creating a table in PostgreSQL. Server is running without any errors but its seems that sequelize don't do anything. I post my code below in hope that you can help me with this problem.
This is my server.js file
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
var corsOptions = {
origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
// parse requests of content-type - application/json
app.use(bodyParser.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// database
const db = require("./app/models");
const Role = db.role;
// db.sequelize.sync();
// force: true will drop the table if it already exists
db.sequelize.sync({force: true}).then(() => {
console.log('Drop and Resync Database with { force: true }');
initial();
});
// simple route
app.get("/", (req, res) => {
res.json({ message: "Welcome to bezkoder application." });
});
// routes
require('./app/routes/auth.routes')(app);
require('./app/routes/user.routes')(app);
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
function initial() {
Role.create({
id: 1,
naziv: "user"
});
Role.create({
id: 2,
naziv: "moderator"
});
Role.create({
id: 3,
naziv: "admin"
});
}
my db.config
module.exports = {
HOST: "localhost",
USER: "postgres",
PASSWORD: "sarke",
DB: "elposlovanje",
dialect: "postgres",
port: 5432,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
};
my index.js from models
const config = require("../config/db.config.js");
const Sequelize = require("sequelize");
const sequelize = new Sequelize(
config.DB,
config.USER,
config.PASSWORD,
{
host: config.HOST,
dialect: config.dialect,
port: config.port,
pool: {
max: config.pool.max,
min: config.pool.min,
acquire: config.pool.acquire,
idle: config.pool.idle
}
}
);
const db = {};
db.Sequelize = Sequelize;
db.sequelize = sequelize;
db.user = require("../models/user.model.js")(sequelize, Sequelize);
db.role = require("../models/role.model.js")(sequelize, Sequelize);
db.role.belongsToMany(db.user, {
through: "user_roles",
foreignKey: "roleId",
otherKey: "userId"
});
db.user.belongsToMany(db.role, {
through: "user_roles",
foreignKey: "userId",
otherKey: "roleId"
});
db.ROLES = ["user", "admin", "moderator"];
module.exports = db;
role from models
module.exports = (sequelize, Sequelize) => {
const Role = sequelize.define("roles", {
id: {
type: Sequelize.INTEGER,
primaryKey: true
},
naziv: {
type: Sequelize.STRING
}
});
return Role;
};
and user from model
module.exports = (sequelize, Sequelize) => {
const User = sequelize.define("users", {
ime: {
type: Sequelize.STRING
},
prezime: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
lozinka: {
type: Sequelize.STRING
},
brojindexa: {
type: Sequelize.STRING
}
});
return User;
};
Output after running node server.js is
Server is running on port 8080.
my package.json
{
"name": "node-js-jwt-auth-postgresql",
"version": "1.0.0",
"description": "Node.js Demo for JWT Authentication with PostgreSQL",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"node js",
"express",
"jwt",
"authentication",
"postgresql"
],
"author": "bezkoder",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"pg": "^7.18.2",
"pg-hstore": "^2.3.3",
"sequelize": "^5.22.3"
},
"devDependencies": {
"sequelize-cli": "^6.2.0"
}
}
i found out the problem was in the version of pg

Multiple Config in JSON for Node.js

I am not sure what to title my question.
Its been a adventure with node.js and a helpful person pointed me to ioredis. Currently I have:
var Redis = require("ioredis");
const DBConfig = require(__dirname+'/../Config.json');
var cluster = new Redis.Cluster([
{
port: 6001,
host: "10.0.0.6",
},
{
port: 6002,
host: "10.0.0.5",
},
{
port: 6003,
host: "10.0.0.4",
},
{
port: 6004,
host: "10.0.0.3",
},
{
port: 6005,
host: "10.0.0.2",
},
{
port: 6006,
host: "10.0.0.1",
},
]);
But to me this seems it would be better in a json config file like...
Config.json:
{
"configA" : "abc",
"someotherconfigB" : "Stuff",
"foo" : "bar"
}
{
"port": 6001,
"host": "10.0.0.6",
},
{
"port": 6002,
"host": "10.0.0.5",
},
{
"port": 6003,
"host": "10.0.0.4",
},
{
"port": 6004,
"host": "10.0.0.3",
},
{
"port": 6005,
"host": "10.0.0.2",
},
{
"port": 6006,
"host": "10.0.0.1",
},
}
I am so new and this I just not sure how to implement this without syntax errors.
var Redis = require("ioredis");
const DBConfig = require(__dirname+'/../Config.json');
var cluster = new Redis.Cluster([DBConfig.redis]);
I am not sure how to implement "var cluster = new Redis.Cluster([DBConfig.redis]);" properly
You should declare those settings in as an array under a key
{
"configA" : "abc",
"someotherconfigB" : "Stuff",
"foo" : "bar",
"redisCluster": [
{
"port": 6001,
"host": "10.0.0.6"
},
{
"port": 6002,
"host": "10.0.0.5"
},
{
"port": 6003,
"host": "10.0.0.4"
}
]
}
Then use that key to access that value inside the required config file.
const DBConfig = require('../Config.json');
const cluster = new Redis.Cluster(DBConfig.redisCluster);
First, you need to have a proper config file. Your file seems to contain some config information and node information. I would suggest:
Config.json file:
{
"configs": {
"configA": "abc",
"someotherconfigB": "Stuff",
"foo": "bar"
},
"nodes": [
{
"port": 6001,
"host": "10.0.0.6"
},
{
"port": 6002,
"host": "10.0.0.5"
},
{
"port": 6003,
"host": "10.0.0.4"
},
{
"port": 6004,
"host": "10.0.0.3"
},
{
"port": 6005,
"host": "10.0.0.2"
},
{
"port": 6006,
"host": "10.0.0.1"
}
]
}
Then your file should look like:
const Redis = require('ioredis');
const DBConfig = require(__dirname + '/Config.json');
const cluster = new Redis.Cluster(DBConfig.nodes);
Object.entries(DBConfig.configs).map(([key, value]) => {
cluster.set(key, value);
});
DBConfig.nodes it's already an array. No need to put brackets around it
Object.entries(DBConfig.configs) will give you an array of [key, value] pairs of your DBConfig.configs's properties
Resources:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries

Typeorm connect to multiple database

I use node.js , TS and typeorm for back-end project.
I need to connect to a different database in the middleware according to the parameter I send.
And I've got to send the query to the database.
ormconfig
[
{
"name": "default",
"type": "postgres",
"host": "localhost",
"port": 5432,
"username": "postgres",
"password": "12345",
"database": "dbOne"
},
{
"name": "second-connection",
"type": "postgres",
"host": "localhost",
"port": 5432,
"username": "postgres",
"password": "12345",
"database": "dbTwo"
}
]
That's my connection settings.
After I do that, I'm trying to connect to the middleware.
const connectionOptions = await getConnectionOptions("second-connection");
const conTwo = await createConnection(connectionOptions);
const managerTwo = getManager("second-connection");
const resultTwo = await managerTwo
.createQueryBuilder(SysCompany, "company")
.getOne();
console.log(resultTwo);
I think I can connect to the database, but I'm having trouble with the repository.
Error
EntityMetadataNotFound: No metadata for "SysCompany" was found.
#Entity()
export class SysCompany extends CoreEntityWithTimestamp {
#Column({ length: 100 })
name: string;
// FK
// SysPersonnel
#OneToMany(type => SysPersonnel, personnel => personnel.sysCompany)
sysPersonnels: SysPersonnel[];
}
Maybe typeORM cannot find your JavaScript entity. I had that problem some time ago. You can do the following:
Check your destination folder after you built the project. Is your SysCompany.js available?
Set the entities property in the configuration. It must contain the path to your JS entities. The typeORM docs state that "Each entity must be registered in your connection options".
{
"name": "second-connection",
"type": "postgres",
"host": "localhost",
"port": 5432,
"username": "postgres",
"password": "12345",
"database": "dbTwo"
"entities": ["<path to entities>/**/*.js"]
}
I would also recommend to use a JavaScript configuration file. Your ormconfig.js can then use __dirname (directory name of the current module) to set the path. So if your directories look like this:
project/ormconfig.js
project/dist/entity/SysCompany.js
project/dist/entity/OtherEntity.js
You can use a configuration like this:
import {join} from "path";
...
entities: [
join(__dirname, "dist/entity/**/*.js")
],
...
You could also prevent duplication by using a base configuration object.
import {join} from "path";
const baseOptions = {
type: "postgres",
host: "localhost",
port: 5432,
username: "postgres",
password: "12345",
entities: [
join(__dirname, "dist/entity/**/*.js")
]
}
const defaultConfig = Object.assign({
name: "default",
database: "dbOne",
}, baseOptions);
const secondConfig = Object.assign({
name: "second-connection",
database: "dbTwo",
}, baseOptions);
module.exports = [ defaultConfig, secondConfig ];
In the file where you open the connection you could use an import:
import { secondConfig } from "<path to file>/ormconfig";
const conTwo = await createConnection(secondConfig);
The simplest way to use multiple databases is to create different connections:
import {createConnections} from "typeorm";
const connections = await createConnections([{
name: "db1Connection",
type: "mysql",
host: "localhost",
port: 3306,
username: "root",
password: "admin",
database: "db1",
entities: [__dirname + "/entity/*{.js,.ts}"],
synchronize: true
}, {
name: "db2Connection",
type: "mysql",
host: "localhost",
port: 3306,
username: "root",
password: "admin",
database: "db2",
entities: [__dirname + "/entity/*{.js,.ts}"],
synchronize: true
}]);
This approach allows you to connect to any number of databases you have and each database will have its own configuration, own entities and overall ORM scope and settings.
For each connection a new Connection instance will be created. You must specify a unique name for each connection you create.
The connection options can also be loaded from an ormconfig file. You can load all connections from the ormconfig file:
import {createConnections} from "typeorm";
const connections = await createConnections();
or you can specify which connection to create by name:
import {createConnection} from "typeorm";
const connection = await createConnection("db2Connection");
When working with connections you must specify a connection name to get a specific connection:
import {getConnection} from "typeorm";
const db1Connection = getConnection("db1Connection");
// you can work with "db1" database now...
const db2Connection = getConnection("db2Connection");
// you can work with "db2" database now...
Benefit of using this approach is that you can configure multiple connections with different login credentials, host, port and even database type itself. Downside for might be that you'll need to manage and work with multiple connection instances.

Resources