DEV Community

Cover image for Brewing a Full-Stack Breakfast with ExpressoTS, Bun, and Elysia
Daniel Boll for ExpressoTS

Posted on

Brewing a Full-Stack Breakfast with ExpressoTS, Bun, and Elysia

Combine the power of ExpressoTS with Bun's Elysia framework in TypeScript for a mouth-watering full-stack experience.

Introduction

Welcome to a hands-on guide focused on integrating ExpressoTS, Bun, and Elysia into a full-stack TypeScript application. Let's cut to the chase and see what ingredients we'll be working with.

Our Ingredients

ExpressoTS

This TypeScript framework is designed for server-side applications. It offers flexibility in project structure and supports multiple
architectural patterns, including MVC. If you like your applications like your coffee — robust and versatile — ExpressoTS is your go-to.

You can also check my guide on a first project with ExpressoTS

Bun

An all-in-one toolkit that brings speed and efficiency to your JavaScript and TypeScript projects.
Think of Bun as the wholesome bread holding all your stack's ingredients together.
It's an entire toolbox in one neat package, and it's faster than you can say "bun in the oven."

ElysiaJS

A Bun web framework that promises performance, simplicity, and flexibility. Designed with TypeScript in mind, Elysia is like that final
touch of seasoning that takes your project from good to great.

So, whether you're into French toast or a classic Eggs Benedict, the aim of this blog post is to show you how to whip up a dish that's not just full of flavor, but also robust and scalable.

Getting Started: Your First Bite of Elysia

Now that we've set the table with the ingredients, let's start cooking. We'll begin by setting up a basic Elysia application using Bun.

1. Install Bun

First, you'll need to download and install Bun. Open your terminal and run the following command:

curl -fsSL https://bun.sh/install | bash
Enter fullscreen mode Exit fullscreen mode

This will download and install Bun on your machine, equipping you with a fast and efficient JavaScript runtime.

2. Create Your Elysia Project

Once Bun is installed, it's time to create your Elysia project. Run:

bun create elysia breakfast-ts
Enter fullscreen mode Exit fullscreen mode

You should see a message like this:

Created elysia project successfully

# To get started, run:

  cd breakfast-ts
  bun run src/index.ts
Enter fullscreen mode Exit fullscreen mode

3. Run Your Application

Follow the instructions in the terminal message:

cd breakfast-ts
bun run src/index.ts
Enter fullscreen mode Exit fullscreen mode

And just like that, you should see the message, instantaneously 🌪:

🦊 Elysia is running at localhost:3000
Enter fullscreen mode Exit fullscreen mode

Voila! You've just whipped up your first Elysia app, hot and fresh.

4. Verify Your Application

To verify Elysia's functionality, you can perform a health check using the provided endpoint. While I'll be using httpie for its straightforward API, you're welcome to use curl if you prefer.

http :3000
Enter fullscreen mode Exit fullscreen mode
HTTP/1.1 200 OK
Content-Length: 12
Date: Sun, 10 Sep 2023 20:47:46 GMT
content-type: text/plain;charset=utf-8

Hello Elysia
Enter fullscreen mode Exit fullscreen mode

Extending Elysia: Crafting a Simple User CRUD

With the basic setup out of the way, let's extend our Elysia app by adding some CRUD functionality for users.
This will serve as a good starting point before we dive into more complex operations in future posts.

1. Run Your Application in Watch Mode

First, stop the server if it's running. Then leverage Bun's watch mode, which will automatically reload the application
when changes are made to the source code:

bun run --watch src/index.ts
Enter fullscreen mode Exit fullscreen mode

2. Add User CRUD Routes

Now, let's define some basic CRUD operations. Open src/index.ts and add to your existing code the following:

import { Elysia } from "elysia";

// Create a user route group
const user = new Elysia().group("user", (app) =>
  app
    .get("/", () => "All users")
    .get("/:id", (context) => `Hello, ${context.params.id}`)
    .post("/", () => "Create User")
    .put("/:id", (context) => `Update User ${context.params.id}`)
    .delete("/:id", (context) => `Delete User ${context.params.id}`)
);

// Main app
const app = new Elysia()
  .get("/", () => "Hello Elysia")
  .use(user)
  .listen(3000);

console.log(
  `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`,
);
Enter fullscreen mode Exit fullscreen mode

Here, we've used Elysia's group<Prefix extends string = string>(prefix: Prefix, run: (group: Elysia<...>)) method to bundle all user-related routes together. We've defined routes for getting all users, getting a single user by ID, creating a user, updating a user, and deleting a user.

3. More Advanced Features

Note: You can extend this basic setup in various ways. Elysia supports both simple state management within the server and more advanced
dependency injection techniques for robust applications. Check out Elysia's documentation on
State Decorate and
Dependency Injection if you're interested.

For the sake of this blog post, we're keeping it simple. If you are willing to expand your horizons, however, you are encouraged to check out the
Call to Action section at the end of this post, where you may help the ExpressoTS community in the bun integration.

4. Test Your User CRUD Endpoints

After running your server, you can test each endpoint to make sure they're working as intended.

Get All Users

http :3001/user
Enter fullscreen mode Exit fullscreen mode
HTTP/1.1 200 OK
Content-Length: 9
Date: Sun, 10 Sep 2023 20:47:46 GMT
content-type: text/plain;charset=utf-8

All users
Enter fullscreen mode Exit fullscreen mode

Get a Single User

Replace {id} with the ID of the user you're interested in.

http :3001/user/42
Enter fullscreen mode Exit fullscreen mode
HTTP/1.1 200 OK
Content-Length: 11
Date: Sun, 10 Sep 2023 20:47:46 GMT
content-type: text/plain;charset=utf-8

Hello, 42
Enter fullscreen mode Exit fullscreen mode

Create a User

http POST :3001/user
Enter fullscreen mode Exit fullscreen mode
HTTP/1.1 200 OK
Content-Length: 11
Date: Sun, 10 Sep 2023 20:47:46 GMT
content-type: text/plain;charset=utf-8

Create User
Enter fullscreen mode Exit fullscreen mode

Update a User

Again, replace {id} with the ID of the user you want to update.

http PUT :3001/user/42
Enter fullscreen mode Exit fullscreen mode
HTTP/1.1 200 OK
Content-Length: 16
Date: Sun, 10 Sep 2023 20:47:46 GMT
content-type: text/plain;charset=utf-8

Update User 42
Enter fullscreen mode Exit fullscreen mode

Delete a User

And one last time, replace {id} with the ID of the user you want to delete.

http DELETE :3001/user/42
Enter fullscreen mode Exit fullscreen mode
HTTP/1.1 200 OK
Content-Length: 16
Date: Sun, 10 Sep 2023 20:47:46 GMT
content-type: text/plain;charset=utf-8

Delete User 42
Enter fullscreen mode Exit fullscreen mode

Now you've successfully tested all of your user CRUD operations. It's like a full-course breakfast — everything is present and accounted for!

Diving into the Heart of the Matter: Reflection and Decorators

In programming, reflection is a mechanism that allows you to inspect and manipulate program elements like classes and objects at runtime. In other words, reflection enables a program to observe its own structure, similar to how you can observe your own reflection in the mirror. This allows for greater dynamic behavior, enabling more powerful and flexible constructs like decorators.

Dive deeper @ daniel-boll.me

If you are interested in the stuff you can achieve with reflection make sure to check out the full blog at daniel-boll.me for much more content.

Image description

Top comments (3)

Collapse
 
rsaz profile image
Richard Zampieri

Great article, good job!

Despite I love performance, without having functionalities such as DI, decorators, providers that increase developers productivity, doesn't mean much when I consider to adopt a new tech just by the performance perspective. Really depends on the type of product I am assigned to build.

Let's see if we can migrate a whole fully fledge solution such as ExpressoTS to use Bun's runtime.

Collapse
 
danielboll profile image
Daniel Boll

Absolutely, performance alone isn't a deal-breaker. Features that boost developer productivity are equally important. Migrating a solution like ExpressoTS to Bun would be a great test of its full capabilities. We aim to offer Bun users a seamless experience, just like with Express. Looking forward to exploring this further.

Collapse
 
arielbetti profile image
Ariel Betti

🔥🔥🔥🔥