Backend: Nodejs, Mongodb, Express Typescript

Back-end with Node.js & MongoDB

Overview
Express and Node make up the middle (application) tier. Express.js is a server-side web framework, and Node.js the popular and powerful JavaScript server platform.
Mern architecture

Express.js and Node.js Server Tier
Express.js bills itself as a “fast, unopinionated, minimalist web framework for Node.js,” and that is indeed exactly what it is. Express.js has powerful models for URL routing (matching an incoming URL with a server function), and handling HTTP requests and responses.

By making XML HTTP Requests (XHRs) or GETs or POSTs from your React.js front-end, you can connect to Express.js functions that power your application. Those functions in turn use MongoDB’s Node.js drivers, either via callbacks for using Promises, to access and update data in your MongoDB database.

Overview

Structure

  • Via Express routes, HTTP request that matches a route will be checked by CORS Middleware before coming to Security layer.

  • Security layer includes:

    1. JWT Authentication Middleware: verify SignUp, verify token
    2. Authorization Middleware: check User’s roles with record
      in MongoDB database
    3. An error message will be sent as HTTP response to Client
      when the middleware throw any error
  • Controllers interact with MongoDB Database via Mongoose library and send HTTP response to Client.

Packages

  • Express
  • bcryptjs
  • jsonwebtoken
  • mongoose
  • MongoDB
  • cors

Project

First create a ‘backend’ folder that we created previously and create the server. Then, we will initialize package.json using npm init.

 

mkdir

backend

cd

backend npm init- y

Enter fullscreen mode

Exit fullscreen mode

Project Structure

Install the required packages using npm or yarn. Since I am using Typescript the types are installed as dev dependencies. The package.json should look like this.

packages

"dependencies"

:

{

"bcryptjs"

:

"^2.4.3"

,

"body-parser"

:

"^1.19.2"

,

"cookie-parser"

:

"^1.4.6"

,

"cors"

:

"^2.8.5"

,

"dotenv"

:

"^16.0.0"

,

"express"

:

"^4.17.3"

,

"express-jwt"

:

"^6.1.1"

,

"jsonwebtoken"

:

"^8.5.1"

,

"mongodb"

:

"^4.4.1"

,

"mongoose"

:

"^6.2.4"

,

"morgan"

:

"^1.10.0"

}

,

"devDependencies"

:

{

"@types/bcryptjs"

:

"^2.4.2"

,

"@types/cookie-parser"

:

"^1.4.2"

,

"@types/cors"

:

"^2.8.12"

,

"@types/express"

:

"^4.17.13"

,

"@types/express-jwt"

:

"^6.0.4"

,

"@types/jsonwebtoken"

:

"^8.5.8"

,

"@types/mongoose"

:

"^5.11.97"

,

"@types/morgan"

:

"^1.9.3"

,

"@types/node"

:

"^17.0.21"

,

"nodemon"

:

"^2.0.15"

,

"ts-node"

:

"^10.6.0"

,

"typescript"

:

"^4.6.2"

}

Enter fullscreen mode

Exit fullscreen mode

  1. Folders
    Create the following folders

mkdir

controllers routes middleware utils models config

touch

server.ts config.env

Enter fullscreen mode

Exit fullscreen mode

controllers
auth.ts: handle signup & signin actions
user.ts: return public & protected content
routes
auth.ts: POST register & login
user.ts: GET public & protected resources
middlewares
auth.ts: Authentication middleware, check protected routes
error.ts: error handling middleware
models for Mongoose Models
user.ts: User schema and model in Db
config
configure MongoDB database connection
configure Auth Key
server.ts:
import and initialize necessary modules and routes, listen for connections.
config.env:
store environment variables

Here, we are requiring express and cors to be used. const port process.env.port will access the port variable from the config.env we required.

require

(

'

dotenv

'

).

config

({

path

:

'

./config.env

'

});

import

express

from

"

express

"

;

import

cors

from

"

cors

"

;

import

cookieParser

from

'

cookie-parser

'

;

import

morgan

from

'

morgan

'

;

import

{

json

}

from

'

body-parser

'

import

mongoose

from

'

mongoose

'

import

{

connectDB

}

from

"

./config/db

"

;

const

app

=

express

();

const

PORT

=

process

.

env

.

PORT

||

5000

;

const

errorHandler

=

require

(

'

./middleware/error

'

)

//connect to db

connectDB

()

app

.

use

(

express

.

json

());

app

.

use

(

"

/api/auth

"

,

require

(

"

./routes/auth

"

));

app

.

use

(

"

/api/private

"

,

require

(

"

./routes/private

"

));

//ErrorHandler (Should be last piece of middleware)

app

.

use

(

errorHandler

);

const

server

=

app

.

listen

(

PORT

,()

=>

{

console

.

log

(

`Server is running on port

${

PORT

}

`

)

}

)

process

.

on

(

"

unhandledRejection

"

,(

error

,

promise

)

=>

{

console

.

log

(

`Logged Error:

${

error

}

`

);

server

.

close

(()

=>

process

.

exit

(

1

))

})

Enter fullscreen mode

Exit fullscreen mode

PORT

=

5000

MONGO_URI

=

mongodb

:

//localhost:27017/<your db name>

JWT_SECRET

=<

JWT

secret

key

>

JWT_EXPIRE

=

10

min

EMAIL_HOST

=<

Email

config

>

EMAIL_PORT

=

<

Email

config

>

EMAIL_USER

=<

Email

config

>

EMAIL_PASS

=<

Email

config

>

EMAIL_FROM

=<

Email

config

>

Enter fullscreen mode

Exit fullscreen mode

Here we can add the following code to connect to our database. For this to work you should have mongodb installed and Mongodb Service started.
This function is used in backend/server.ts to connect to Mongodb

import

{

ConnectOptions

}

from

'

mongodb

'

;

import

mongoose

from

'

mongoose

'

;

const

connectDB

=

async

()

=>

{

await

mongoose

.

connect

(

process

.

env

.

MONGO_URI

!

);

console

.

log

(

'

MongoDb Connected

'

);

}

module

.

exports

=

connectDB

;

Enter fullscreen mode

Exit fullscreen mode

Upto now, we have a basic server that can connect to Mongodb. In the 3rd part of this series we will work on Server API endpoints and Error Handling