🐺 REST APIs with Elysia.js 🌿
Tags: elysia, bunjs, api, webdev
Published: 2024-03-25 12:56:53

<Intro>
Hey API Dev, tired of building express apps that don't perform well under high loads? Want something that feels a bit cleaner and modern to build your next multi-million dollar project? 

You may have heard of [Bun](https://dev.to/lundjrl/bun-a-faster-javascript-runtime-jph), the newest JS runtime before, but have you heard of an ergonomic developer-friendly API framework that uses Bun?

If not, this article is for you 🎉

There's a few contenders out there but the one that really stood out to me is Elysia.

&nbsp;

## What is Elysia? 

Elysia is a HTTP API framework written on Bun with developer experience being the main motivation of the framework. 

Essentially, a faster Express.js replacement.

Elysia is set up for you to write functions and returns for your API. Need to send a response to the client? Just return your data in the callback function. No need to rely on req/res explicitly. 

A basic Elysia endpoint could look like this:

![Code snippet of a simple Elysia endpoint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aafy9w37qwhi2ocrj600.png)

Which will return a 200 and the string `Test` inside the response body.

The implementation syntax looks similar to express but cleaner, in my opinion.

&nbsp;

### Elysia Paths

You can leverage all the regular HTTP Methods and also add your own:

![Code snippet showing API paths in Elysia](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hrpazldbdfcziktcjojj.png)

Or if you don't care about the method, you can use `.all` instead of `.get .post` etc.

You can also handle 404 errors like so:

![Code snippet showing how to handle 404 errors in Elysia](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yfgqkjbjwzq0sp3aefyz.png)

Need dynamic paths? No worries:

![Code snippet describing how to use dynamic paths in Elysia](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eujo0w4jylt0bklqv4nc.png)

Need multiple dynamic variables on an endpoint? They got you:

![Code snippet of how to use dynamic variables in an endpoint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m3e98w2r4unucftpspk3.png)

What about wildcards? Don't worry about it:

![Code snippet showing how to use wildcards in Elysia](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ub9cfamrkcz1gqc852jk.png)

As you can see, Elysia has a lot of power baked in. But what about returning data? 

&nbsp;

### Elysia's Handler Function

Those callbacks you saw in the code-snippets are the "handler". A handler is a callback function as the second argument in an endpoint. As you saw, we can extract params, path, and the request context by destructuring the request object:

![Code snippet on how to descructure the request object in HTTP requests](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kbm7kynsrd9je7nv2kxs.png)

The request object isn't lost to us tho. To alter request headers or redirects, we can leverage `set` like so:

![Code snippet showing how to use the request object in Elysia](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hw6ck9c4rm7yfjelw9kn.png)

More info on request context [here](https://elysiajs.com/essential/context.html).

&nbsp;

### Elysia Responses

Elysia will automatically create the response object for you from whatever you return in your handler function.

If you want, you can also return a `new Response()` object and Elysia will handle it.

Want to move your routes to different files? Leverage Elysia's [plugin system](https://elysiajs.com/essential/plugin.html).

Need some additional functionality? Checkout the [community](https://elysiajs.com/plugins/overview.html).

&nbsp;

### Life Cycle Events

I won't go into too much detail here but this is an illustration of what's going on under the hood.

![Elysia Life cycle diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h0hq86jbz0s81pw7zjvn.png)

When a request is made and accepted, the system will transform the request to the object we receive in our handler function. 

If we have validation in place, that occurs next. The handler function is executed and returns data in form of a HTTP Response.

If this all makes sense, let's move on to a demo!
&nbsp;

<img width="100%" style="width:100%" alt="Makes sense meme" src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lmjo7m893pwf5ovz6ka1.gif">

&nbsp;

## API Demo

💻 **Completed code [here](https://github.com/lundjrl/elysia-article)**

Let's start by creating a new Elysia app!

You can easily create a new Elysia app by running `bun create elysia app` in your terminal where "app" is the name of your new application. If you don't have Bun installed, you can install it via curl `curl -fsSL https://bun.sh/install | bash`.

Next, cd into the new directory and run the app with `bun run dev`. A dev server should start up at `localhost:3000`.

&nbsp;

### Building Our Endpoints

For this demo, we're going to be connecting to the Trefle plant API. This API contains a very wide variety of plants and we'll be performing get requests for the purpose of this demo.

We're going to make a few endpoints to get our plant data.

    1. Get 30 plants
    2. Search by query
    3. Search by plant genus
    4. Search by plant species

First off, we'll add those endpoints to `index.ts`

![Code snippet showing endpoints in our API application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rp4ujsqpugec1xonnqgm.png)

Don't worry about the handler function for now, we'll add those later after we complete the next step.

Next, let's create the file that'll contain these functions in `src/api.ts`. Add these functions below:

![Code snippet showing basic functions for handlers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yf0t081w4lfxa2z04k73.png)

But before we can attach these functions to the plant API, we need to get a token to authenticate. If you create an account [here](https://trefle.io/profile), you'll be granted with an API token to use their API.

Once you get your token, add it to `.env` inside our project as `API_TOKEN`. We'll leverage Bun to securely access our secrets. No dotenv package needed! Env variables are available via Bun with `Bun.env.${YOUR_ENV}`.

After your token has been added, let's kill the current server and restart with `bun run dev`. Now our value for the env variable should be accessible.

Next we will connect our API to Trefle with a generate URL function. This function will construct a new URL object and dynamically append any query params to the string. 

![Code snippet of generateUrl function to construct Trefle fetch url](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z5ysew4fk0a3hnst00nm.png)

Now that we have a way to construct our url to the Trefle API, let's start getting some data. We'll need to complete those handler functions I mentioned earlier. 

For each handler, call the generateUrl function we created. For the specifics on getting plants, refer to the screenshot below. The purpose of this article isn't to use the Trefle API, just to demonstrate how to setup an Elysia instance. 

![Code snippet of finished code in src/api.ts file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wits2kpbx4e36h9rmz5v.png)

Cool, if your code looks similar to the snippet above, let's move on to wrapping up the endpoints in`index.ts`.

We just need to import the handler functions and assign them to the proper endpoints. 

![Code snippet of finished endpoints](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rylw2qn6kzbqt38fc6z5.png)

After that's done, if we go to `localhost:3000/plants` in our browser, we should see a JSON object returned with 30 plants :tada: :herb:

Test out the other endpoints to get specific genus or species data! That about sums up the demo.

&nbsp;

### Additional Things About Elysia

There's still a lot about the framework that we couldn't cover in this article. Here are some quick links if anything catches your eye.

[Cookies in Elysia](https://elysiajs.com/patterns/cookie.html)
[Swagger docs](https://elysiajs.com/patterns/documentation.html)
[Websockets](https://elysiajs.com/patterns/websocket.html)
[Lazy loading](https://elysiajs.com/patterns/lazy-loading-module.html)
[Dos and donts](https://elysiajs.com/patterns/mvc.html)
[E2E type safety](https://elysiajs.com/eden/overview.html)

&nbsp;

### Resources / Thank you

Thanks for taking the time to read! What did you think? Are you going to be trying Elysia anytime soon? Let me know in the comments! 

If you want to know more about the API framework, checkout these links below. 

[Elysia Docs](https://elysiajs.com/)
[Elysia Github](https://github.com/elysiajs/elysia)
[Official Plugins](https://elysiajs.com/plugins/overview.html)
[Demo Repo](https://github.com/lundjrl/Elysia-API)


<Credits to banner image>

**Image credits go to the Elysia repository image author. I did not create the banner image on this post**