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
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
You should see a message like this:
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:
cd breakfast-ts
bun run src/index.ts
And just like that, you should see the message, instantaneously πͺ:
π¦ 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 for its straightforward API, you're welcome to use curl
if you prefer.
http :3000
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:
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:
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 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
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.
http :3001/user/42
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
http POST :3001/user
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.
http PUT :3001/user/42
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.
http DELETE :3001/user/42
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
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.
Top comments (3)
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.
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.
π₯π₯π₯π₯