Welcome folks today in this blog post we will be building a backend crud rest api in bun.js & Typescript and sqlite3 database. All the full source code of the application is shown below.
What is Bun.js?
Bun.js is a fast runtime environment similar to node.js and deno.js. But it claims to be faster then the rest of the two. It’s a new thing in the market. So in this tutorial we will try to build a simple crud backend api with the help of built in sqlite3 database.
Installing Bun.js
Bun.js is a Unix based javascript runtime environment. So for installing it on unix it’s very easy by using the below command of curl
1 |
curl https://bun.sh/install | bash |
Installing on Windows
For installing on windows you need to first of all enable the subsystem for Linux Windows feature as shown below
As you can see you need to go to windows features and turn on the windows subsystem for Linux. It’s enables you to build linux based applications in Windows.
Installing Ubuntu From Windows Store
After that you need to download and install ubuntu Operating System from the windows store as shown below
As you can see you need to install a specific version of Ubuntu which can be 20.04.5 LTS. Download it and install it. This will hardly take 15 to 20 minutes to complete. And after that click the open button to open the Ubuntu OS Console as shown below
Installing Unzip and Zip in Ubuntu
Now you will need the unzip and zip libraries inside ubuntu to install the bun.js runtime environment
sudo apt install zip
sudo apt install unzip
Installing Bun.js Using Curl Command
1 |
curl https://bun.sh/install | bash |
As you can see you can now use the same command to install the bun.js with the curl command and after that you need to set the path which is shown below
Setting the Path of Bun.js inside Nano Editor
Now we need to set the path of bun.js downloaded inside the nano editor of linux as shown below
nano ~/.bashrc
1 2 |
export BUN_INSTALL="$HOME/.bun" export PATH="$BUN_INSTALL/bin:$PATH" |
At the bottom of this file paste the path that you got of bun.js. This path will be different for you as directory structure of your OS differs from others.
And then press ctrl + x and then press y and then press enter to save the file successfully. Now your path of bun.js has been globally set. Now you can access bun.js from the command line from anywhere.
Setting Up Bun.js in Visual Studio Code
Now guys create a empty folder and open it inside visual studio code editor and now we need to create a sample bun.js hello world program as shown on the official website.
http.js
1 2 3 4 5 6 7 |
// http.js export default { port: 3000, fetch(request) { return new Response("Welcome to Bun!"); }, }; |
Running the Bun.js File
Now for running your very first bun.js http server you just need to write this command
bun run http.js
It will start the server on port number 3000
Get Started
Now first of all you need to create a new bun.js project by using the below command. This is very much similar npm init
in node.js. So this command will initialize the package.json and basically all the dependencies
bun init
In order to get started with the project just first of all see the directory structure of the overall project which is shown below. It contains all the files and folders which will be there
Running the Project
Now we will running the index.ts
file as shown below
bun run index.ts
As you can see we are printing the message on the console.
Creating the Schema and Database
Now for our bun.js project we need to create the schema and the database. For this we need to create the src
directory. Now inside this you need to create bun.service.ts and bun.database.ts files as shown below
src/bun.database.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
import { Database } from "bun:sqlite"; export enum BunType { PLAIN = "Plain", BUTTER = "Butter", PIZZA = "Pizza", CHEESE = "Cheese", } export interface Bun { id?: string; type: BunType; } export default class BunDatabase { db: Database; constructor() { this.db = new Database("bakerydb.sqlite"); this.db.run( "CREATE TABLE IF NOT EXISTS buns (id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT)" ); } getBuns(): Bun[] { return this.db.query("SELECT * FROM buns").all(); } getBun(id: string): Bun { return this.db.query("SELECT * FROM buns WHERE id = $id").get({ $id: id, }); } createBun(bunType: BunType) { this.db.run("INSERT INTO buns (type) VALUES (?)", bunType); } updateBun(bun: Bun) { this.db.run("UPDATE buns SET type = ? WHERE id = ?", [bun.type, bun.id]); } deleteBun(id: string) { this.db.run("DELETE FROM buns WHERE id = ?", id); } } |
As you can see we are importing the sqlite database at the very first line. And then we are initializing types enum where we define the different bun types. It contains four constants. And then we are initializing interface bun which contains id and bunType. And then we have defined the class BunDatabase in which we have declared various methods to interact with the data. Here in this class we have defined the various crud operations. We have get all the buns and get specific bun by using it’s id. We are creating the bun using the bun type. And we are updating the bun using it’s id and we are deleting the bun using it’s id.
src/bun.service.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import BunDatabase, { Bun, BunType } from "./bun.database"; export default class BunService { db: BunDatabase; constructor(db: BunDatabase) { this.db = db; } getBuns() { return this.db.getBuns(); } getBun(id: string) { return this.db.getBun(id); } createBun(type: BunType) { this.db.createBun(type); } updateBun(bun: Bun) { this.db.updateBun(bun); } deleteBun(id: string) { this.db.deleteBun(id); } } |
As you can see we have defined the service where we are importing the bun database. And then we have defined the methods to call the database crud operations. So in this service we have defined all the methods of crud operations in this service. In the constructor of this service we are initializing the database
And now we need to write the code inside the index.ts
file of your bun.js project as shown below.
index.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
import BunDatabase, { Bun } from "./src/bun.database"; import BunService from "./src/bun.service"; const db = new BunDatabase(); const bunService = new BunService(db); export default { port: 3000, async fetch(request: Request) { const { method, url } = request; const { pathname, searchParams } = new URL(url); console.log(`${method} ${pathname}`); // GET /buns if (method === "GET" && pathname === "/buns") { const buns = bunService.getBuns(); return new Response(JSON.stringify(buns)); } // GET /bun if (method === "GET" && pathname === "/bun") { const bun = bunService.getBun(searchParams.get("id")); return new Response(JSON.stringify(bun)); } // POST /bun if (method === "POST" && pathname === "/bun") { const data: Bun = await request.json(); bunService.createBun(data.type); return new Response(null, { status: 204 }); } // PUT /bun if (method === "PUT" && pathname === "/bun") { const data: Bun = await request.json(); bunService.updateBun(data); return new Response(null, { status: 204 }); } // DELETE /bun if (method === "DELETE" && pathname === "/bun") { bunService.deleteBun(searchParams.get("id")); return new Response(null, { status: 204 }); } // 404 return new Response("Not Found", { status: 404 }); }, }; |
As you can see we have defined all the routes which is GET,POST,PUT & DELETE. As you can see we are importing the service and the database files. And then inside this file we are initializing the db and the service. And then we are extracting the url and the method from the request object. And then we are extracting the pathname and searchParams from the url constructor. And then we are declaring the GET Routes to the /buns endpoint to return all the buns. And then we are converting response to JSON using JSON.stringify() method. And then we are creating the bun using POST Request with the endpoint /bun. And then we are updating the bun using the PUT request with the endpoint /bun and passing the ID. And then we are deleting the bun using the DELETE request with the endpoint /bun and passing the ID as well.
Running the Bun.ts Http Web Server & Testing API Using Postman
Now to run the bun.js http server you need to execute the below command as shown below
bun run index.ts
As you can see if you visit the localhost:3000/buns it will return all the buns in an array of objects each having two fields id which is primary key and then the type parameter which is of type string. It’s a simple GET Request to get all the records.
Creating a Brand new Bun Using Post Request
As you can see we are making a simple POST request to the route /bun and providing the raw json object which contains the type property and then the response which is received which says bun inserted successfully in database
Getting the Specific Details of a Bun Using it’s ID
Now guys we will be getting the details of a specific bun using it’s id. This id will be passed a search parameter in the url itself as shown below in postman
As you can see this is query string as we are searching for a particular bun details using it’s id parameter which is the primary key of the table and then we get the whole json object of the bun detail containing the id and the type parameter.
Updating the Bun Details Using it’s ID
Now we will be updating the bun details using it’s id in postman as shown below. For this operation we will be using the PUT Request
As you can see we are passing the raw json object alongside with the PUT Request to the route /bun and then we are receiving the response the bun updated successfully in database.
Deleting the Bun Using it’s Id
Now guys we will be deleting the bun using it’s id. For this we will be using the delete request as shown below in postman.
As you can see guys we are passing the query parameter bun in the url itself and then we get a response bun successfully deleted from the database.