Brewing a Full-Stack Breakfast with ExpressoTS, Bun, and Elysia
Tags: expressots, typescript, bunjs, elysiajs
Published: 2023-09-11 17:34:08

> 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**](https://expresso-ts.com)

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](https://daniel-boll.me/posts/a-first-project-with-expressots)

### [**Bun**](https://bun.sh)

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**](https://elysiajs.com/)

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:

```bash
curl -fsSL https://bun.sh/install | bash
```

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:

```bash
bun create elysia breakfast-ts
```

You should see a message like this:

```bash
Created elysia project successfully

# To get started, run:

  cd breakfast-ts
  bun run src/index.ts
```

## 3. Run Your Application

Follow the instructions in the terminal message:

```bash
cd breakfast-ts
bun run src/index.ts
```

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

```bash
🦊 Elysia is running at localhost:3000
```

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](https://httpie.io/) for its straightforward API, you're welcome to use `curl` if you prefer.

```bash
http :3000
```
```http
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
```

# 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:

```bash
bun run --watch src/index.ts
```

## 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:

```typescript
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}`,
);
```

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](https://elysiajs.com/concept/state-decorate.html) and
[Dependency Injection](https://elysiajs.com/patterns/dependency-injection.html) 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**](https://daniel-boll.me/posts/a-breakfest-with-expressots-and-bun#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**

```bash
http :3001/user
```
```http
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
```

### **Get a Single User**

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

```bash
http :3001/user/42
```
```http
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
```

### **Create a User**

```bash
http POST :3001/user
```
```http
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
```

### **Update a User**

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

```bash
http PUT :3001/user/42
```
```http
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
```

### **Delete a User**

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

```bash
http DELETE :3001/user/42
```
```http
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
```

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](https://daniel-boll.me/posts/a-breakfest-with-expressots-and-bun#diving-into-the-heart-of-the-matter-reflection-and-decorators)

If you are interested in the stuff you can achieve with reflection make sure to check out the full blog at [daniel-boll.me](https://daniel-boll.me/posts/a-breakfest-with-expressots-and-bun#diving-into-the-heart-of-the-matter-reflection-and-decorators) for much more content.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g3rjunwbp6yun7gcgudz.png)