Bun overview
Tags: bunjs, typescript
Published: 2023-09-11 21:40:20

---
title: Bun overview
published: true
tags: ['bun', 'typescript']
canonical_url: https://sevic.dev/notes/bun-overview/
---

Bun is a JavaScript runtime environment that extends JavaScriptCore engine built for Safari. Bun is designed for speed and developer experience (DX), which includes many features out of the box.

Some of the features include
- Built-in bundler
- Built-in test runner
- Node.js-compatible package manager, compatible with existing npm packages
- Compatibility with Node.js native modules like `fs`, `path`, etc.
- TypeScript support, run TypeScript files with no extra configuration
- Built-in watch mode
- Support for both ES modules and CommonJS modules, both can be used in the same file
- Native SQLite driver

### Installation

Let's start by installing it with the following command

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

Update the current version with `bun upgrade` command and check the current version with `bun --version` command.

Run `bun --help` to see what CLI options are available.

Initialize empty project via the `bun init` command

The init command will bootstrap the "hello world" example with configured package.json, binary lock file (`bun.lockb`), and tsconfig.

### Bundler

Bundler can be used via CLI command (`bun build`) or `Bun.build()` API

```ts
await Bun.build({
  entrypoints: ['./index.ts'],
  outdir: './build',
});
```

Below is the example for CLI command usage. Run `bun build --help` to see all of the available options

```bash
bun build --target=bun ./index.ts --outdir=./build
```

### Package manager

Install packages from package.json via the `bun install` command.

Install additional npm packages via the `bun add` command (e.g., `bun add zod`). To install dev dependencies, run `bun add` with `--dev` option (e.g., `bun add zod --dev`)

Remove dependencies via the `bun remove` command (e.g., `bun remove zod`)

### Running scripts

- Run specific script via the `bun <SCRIPT PATH>.ts` command
- Auto-install and run packages locally via the `bunx` command (e.g., `bunx cowsay "Hello world"`)
- Run a custom npm script from package.json via the `bun run <SCRIPT NAME>` command

### Watch mode

- hot reloading mode via `bun --hot index.ts` command without restarting the process
- watch mode via `bun --watch index.ts` command with restarting the process

### File system

Write into the file using `Bun.write` method

```ts
await Bun.write('./output.txt', 'Lorem ipsum');
```

### Environment variables

- Access environment variables via `Bun.env` or `process.env` objects
- Store variables in `.env` files, like `.env`, `.env.production`, `.env.local`
- Print all current environment variables via `bun run env` command

### HTTP server

Create a server with the following code

```ts
const server = Bun.serve({
  port: Bun.env.PORT,
  fetch (request) {
    return new Response('Welcome to Bun!');
  },
});

console.log(`Listening to port ${server.port}`);
```

### Frameworks

#### Elysia (Bun framework)

Install packages via the `bun add elysia @elysiajs/swagger` command, write the initial server, and run it via the `bun server.ts` command.

```ts
// server.ts
import { Elysia } from 'elysia';
import swagger from '@elysiajs/swagger';

const port = Bun.env.PORT || 8081;

new Elysia()
  .use(swagger({
    path: '/api-docs',
  }))
  .get('/posts/:id', (({ params: { id }}) => id))
  .listen(port);
```

#### Express

Install the `express` package via the `bun add express` command, write the initial server, and run it via the `bun server.ts` command

```ts
// server.ts
import express from 'express';

const app = express();
const port = Bun.env.PORT || 3001;

app.get('/', (req, res) => {
  res.send('Hello world');
});

app.listen(port, () => {
  console.log(`Listening on port ${port}`);
});
```

### Debugging

Install the extension `Bun for Visual Studio Code` by Oven and Run the `Bun: Debug file` command from the command palette. Execution will pause at the breakpoint.

### Testing

Bun supports basic mocking and assertion functions. Run existing tests via the `bun run <TEST SCRIPT NAME>` (e.g., `bun run test:unit`) command.

Below is an example of a basic test assertion and mocking using `bun:test` module.

```ts
import { describe, expect, it, mock } from 'bun:test';
import { add } from './addition-service';
import { calculate } from './calculation-service';

describe('Calculation service', () => {
  it('should return calculated value', async () => {
    const result = calculate();

    expect(result).toEqual(5);
  });

  it('should return mocked value', async () => {
    mock.module('./addition-service', () => {
      return {
        add: () => 3,
      };
    });

    const result = add();

    expect(result).toEqual(3);
  });
});
```

Run unit tests via the `bun test` command. Re-run tests when files change via the `bun test --watch` command.

### SQLite database

Below is a basic example of SQLite driver usage.

```ts
import { Database } from 'bun:sqlite';

const database = new Database('database.sqlite');
const query = database.query("SELECT 'hello world' as message;");
console.log(query.get());
database.close();
```

### Boilerplate

Here is the [link](https://sevic.dev/nestjs-starter) to the boilerplate I use for the development.