Hono with MongoDB
Intro
Hono is a web framework that works on a number of javascript frameworks. It is used primarily used for running web applications on the edge (like Cloudflare Workers). We can Hono with Bun to create our web applications and then we can host them on Linux or containers.
Note: Hono has a excellent getting-started guide at https://hono.dev/getting-started/bun. A some of content in this post is going to be a repeat of their guide
Hono
We will use hono-create
package to setup the basic project structure for our application. When prompted select bun
as the template.
% bun create hono api
create-hono version 0.3.2
✔ Using target directory … api
✔ Which template do you want to use? › bun
Change directory to the newly created project and install dependencies
% cd api
% bun install
The autogenerated index.ts file already has code to import Hono, initialize it and serve a text response at base URL.
Since we are using Bun, we can change the scripts in the package.json file to
{
"scripts": {
"dev": "NODE_ENV=development bun run --hot src/index.ts",
"prod": "NODE_ENV=production bun run src/index.ts"
},
}
Let’s add a HTTP request logger and CORS policy to the application using Hono’s built in middleware. After initializing but before adding routes to the app, we can add the following
app.use('*', logger())
app.use('*', cors({
origin: (origin) => {
if(process.env.NODE_ENV == 'development')
return '*'
else {
let url = new URL(origin)
return url.hostname.endsWith('projects.yasakdogra.com') ? origin : ''
}
}
}))
The CORS middleware will allow all origins in development environment but only allow origins ending with projects.yasakdogra.com
in other environments (like production)
Check out some of my project posts to see how to add additional routes and return different types of responses. A example is also given further down in this post
MongoDB
NOTE: This step requires a working MongoDB installation. If you do not have one, you can sign up for the free tier of MongoDB Atlas
We will use Mongoose, object model tool, for working with MongoDB. We will also add Dotenv to load the database connection string
% bun add dotenv mongoose
NOTE: Only use the .env file method for development, testing and hosting non essential applications. For production applications store sensitive information in encrypted password stores. I will write more about that in a separate post
Create a .env file in project root. Add MongoDB connection string to it
MONGO_URI=mongodb+srv://<user>:<pass>@<instance>.mongodb.net/quotes?retryWrites=true&w=majority
NOTE: Since this file contains sensitive information, do not check in this file with version control. Keep sensitive information out of .env file if its used in version control
Now we can access the connection string inside our source code with
import 'dotenv/config'
const MONGO_URI = process.env.MONGO_URI
We can connect using Mongoose and the connection string with
import 'dotenv/config'
import mongoose from "mongoose";
if (process.env.MONGO_URI)
mongoose.connect(process.env.MONGO_URI)
else
throw new Error('MONGO_URI not found')
Putting it together
Now we will create a sample application that pulls a random quote from quotes database
The quotes are stored in the format
{
"quote": "A house divided against itself cannot stand.",
"author": "Abraham Lincoln"
}
Create a schema and model using mongoose in index.ts file
const quoteSchema = new mongoose.Schema({
quote: String,
author: String
});
const Quote = mongoose.model('Quote', quoteSchema);
To get a random quote we can use MongoDB’s aggregate and sample functions using similar mongoose functions: aggregate and sample. To send the response we can use json
function from Hono context
We can modify the GET request at base URL
app.get('/', async (c) => {
const tmp = await Quote.aggregate().sample(1).exec()
return c.json({text: tmp[0]['quote'], author: tmp[0]['author']})
})
Now we can run the application with bun run dev
and visit http://localhost:3000
or run curl localhost:3000
we will get a random quote
{"text":"Kind words do not cost much. Yet they accomplish much.","author":"Blaise Pascal"}