repost: Building a Web API using Express.js, Bun and MongoDB | Tharaka Romesh | Bits and Pieces
Web APIs serve as the central components of modern software, seamlessly connecting applications across the expansive landscape of the internet.
If you’re working with Node.js, you’re most likely familiar with the MER(A)N stack:
- MongoDB
- Express
- React/Angular
- Node
But, ever since Bun has come to the picture, building high performing APIs haven’t been challenging. So, this article will aim on building an Express.js API backed with MongoDB, powered by Bun!
# Understanding the Tools
If you’re not familiar with any of these tools, don’t worry. Let’s dive into these one by one and understand what we’re going to be working with:
- Express.js: It is a sleek and straightforward web framework seamlessly integrated with Node.js. It lets users build APIs with ease.
- MongoDB: NoSQL database excels in versatility and effortlessly manages large data loads.
- Bun: Bun is a JavaScript runtime that serves to be the replacement for Node.js
# Step 01: Setting Up the Application and Building the API
# 1. Installing Bun
First and foremost, let’s install Bun! To do so, run the command:
1 | curl https://bun.sh/install | bash |
You can verify the installation by running bun --version
.
# 2. Creating a Bun Project
Let’s initialize our Bun project with:
1 | mkdir blog-api |
You can adopt a folder directry structure as below:
1 | /blog-api |
# 3. Installing the libraries: Express.js, MongoDB, and Typescript
Now that you have Bun, you can install all the required packages using the Bun Package Manager itself using the commands:
1 | bun install express mongoose |
These scripts will install Express.js for our server, MongoDB through Mongoose for the database, and Typescript to keep our code clean and safe.
# 4. Brewing the Basic Server Potion
Inside, src/app.ts
create an Express.js server:
1 | import express from "express"; |
This is your basic Express.js app definitition.
Now, let’s ensure that our API is spun up using Bun . We’ll do this by tweaking our npm start script in package.json
:
1 | { |
You can kickstart your application into action with this simple command
1 | bun dev |
The
--watch
mode in Bun offers an ultra-fast, native file-watching experience, sharply contrasting with Node.js, which requires external tools like Nodemon to achieve similar functionality for development convenience.
You can check if the server is up and responsive by making a GET request to the /ping
route, which will reply with a playful “🏓 pong!”.
# 5. Designing the Mongoose Schema
In the src/models
folder, let’s create Post.ts
:
1 | import { Schema, InferSchemaType, model } from "mongoose"; |
# 6. Controllers: Defining Business Logic
Each route needs a corresponding controller function.
For instance, in your controllers
folder, you could have postController.ts
:
1 | import { Request, Response } from "express"; |
Remember to manage errors with care. Encase your controllers in try-catch blocks and send informative responses to the client. Subsequently, import these functions into your routes and incorporate them as needed.
# 7. Adding Routes to the Business Functions
For a Blog API, you’ll want these CRUD-necessary routes:
- Create a post
- Read a post
- Update a post
- Delete a post
Inside your src/routes
directory, you’ll create blogRoutes.ts
with the following:
1 | import express from "express"; |
# 8. Configuring MongoDB
It’s time to bring to life the database connection. Add the following to your src/config/db.ts
:
1 | import mongoose from "mongoose"; |
Now, create a .env file in your project’s root and add your settings, like the MONGODB_URI
, right in there.
In this configuration, we access environment variables directly without depending on utilities like dotenv, a common choice for Node.js projects. This is achievable because Bun inherently supports the exposure of these variables through .env files by default.
# 9. Stitching all together
After preparing your Models, Routes, and Controllers, incorporate them into the index.ts
file. Following this integration, your application is primed for launch.
1 | import express from "express"; |
And just like that, your API powered by Bun is ready.
# Adding Monitoring to Express.js Applications
# Logging requests in Express
Logging is essential for monitoring, debugging, and keeping track of application activity. Morgan is versatile and customizable, making it a valuable tool for developers looking to gain insights into their Express applications.
First, you’ll need to install Morgan. You can do this through bun:
1 | bun add morganbun add @types/morgan -d |
You’ll want to add Morgan as middleware in your Express application. This is done using app.use()
. Morgan has various predefined logging formats like dev
, tiny
, combined
, common
, etc. You can also create your own format. Let’s add a custom format to the index.ts
file.
1 | app.use(morgan(":method :url :status :response-time ms")); |
Morgan is hooked up with your Express app, ready to log all those HTTP requests. Logging comes super handy for keeping an eye on things and squashing bugs. Morgan’s flexibility means you can tweak it to fit your needs perfectly.
# Data validation in Express
To guarantee that the incoming data for your application is clean and structured to your specifications, the express-validator is an essential tool. It’s an excellent middleware option that simplifies validating and sanitizing your request data. Explore how to implement an express validator within your project.
First off, you’d install it in your project like so:
1 | bun add express-validatorbun add -d @types/express-validator |
Then, in your route postRoute.ts
file, you’ll need to import and use it like this:
1 | const router = express.Router(); |
So, with the above code, before we ever hit the route handler /post
, the express-validator checks the username, email, and password fields to ensure they meet our criteria. To test the validation, you can make a POST request without passing the required author
key or by passing an empty string for one of the fields. This will trigger an error response indicating the missing or empty field.
Now that you’ve gained the skills to build an application using Bun, Express, and MongoDB, several additional considerations exist to elevate your project to a production-grade status. To guide you through this advancement, we have curated a collection of tutorials, authoritative documentation, and helpful community contributions.
# Wrapping Up
If you’re keen on exploring further, the official documentation for Express.js, MongoDB, and Bun is an excellent starting point.
But, this article should be enough to get you started with building a production ready application using Bun.
I hope you found this article helpful.
Thank you for reading.