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.
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
-
Via Express routes, HTTP request that matches a route will be checked by CORS Middleware before coming to Security layer.
-
Security layer includes:
- JWT Authentication Middleware: verify SignUp, verify token
- Authorization Middleware: check User’s roles with record
in MongoDB database - 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
-
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