A first project with ExpressoTS
Tags: javascript, typescript, expressots, restapi
Published: 2023-08-27 17:35:21


## Introduction

[ExpressoTS](https://expresso-ts.com/) is a new developer-friendly TypeScript framework for Server-Side Applications. It's currently built on top of [Express](https://expressjs.com/), easy to get a new developer on board, light and easy project structure, two different project structure supported (opinionated and non opinionated version), supports MVC, non MVC, architecture. The opinionated template was built on top of clean architecture, you will see concepts embedded in the opinionated template such as entities, useCases, repositories and providers.

## Setting Up Your First ExpressoTS Project

Ah, the first step to any great journey in the world of coding—a proper setup. Trust me, nobody wants to get lost before even starting the adventure. So, let's cut the chit-chat and dive right in.

### Installation of ExpressoTS CLI

You've got two routes here, and the destination is the same, a functional ExpressoTS environment. Your first option is to install the ExpressoTS CLI globally:

```bash
pnpm i -g @expressots/cli
```

Got limited commitment issues? No worries, you can also use `dlx` to run the CLI without installing it globally. Ah, the wonders of a one-night stand with a CLI!

```bash
pnpx @expressots/cli new expressots-first-project
```

### Configuration Wizard

After running the command, you're greeted by a friendly (albeit text-based) wizard 🧙‍♂️. 

```bash
[🐎 Expressots]

? Project name expressots-first-project
? Package manager pnpm
? Select a template Non-Opinionated :: A simple ExpressoTS project.
? Do you want to create this project? Yes
```

Fill out the form wisely but don't overthink it. For this tutorial, I'm going with the "Non-Opinionated" template because, it will give us a shallower learning curve in the start.

## Getting Comfy in Your New ExpressoTS Home 🏡

### Navigating to Your Project

So you've set up your new ExpressoTS project. Awesome! Time to get inside the engine room and take a look under the hood.

```bash
cd expressots-first-project
```

You're now in the root folder, and if you're curious about what comes packed by default, run a quick `tree` command.

```bash
@expressots/tests/expressots-first-project via  v16.19.0
❯ tree -I node_modules -a
.
├── .eslintrc.js
├── expressots.config.ts
├── .gitignore
├── jest.config.ts
├── package.json
├── pnpm-lock.yaml
├── .prettierrc
├── README.md
├── src
│   ├── app.container.ts
│   ├── app.controller.ts
│   ├── app.module.ts
│   ├── app.usecase.ts
│   └── main.ts
├── test
│   └── app.usecase.spec.ts
├── tsconfig.build.json
└── tsconfig.json

3 directories, 16 files
```

There you go! These are the files you'll be living with.

### Customizing Your Prettier Preferences

You've got your own coding style—don't we all? You can tweak the `.prettierrc` file to your heart's content.

```json
{
  "singleQuote": false,
  "trailingComma": "all",
  "endOfLine": "auto",
  "tabWidth": 2
}
```

### Let's Take a Quick Tour of **package.json**

A glance at the `scripts` section in `package.json` tells you all you need to know to get things up and running.

```bash
❯ cat package.json | jq ".scripts"
{
  "prebuild": "rm -rf ./dist",
  "build": "tsc -p tsconfig.build.json",
  "dev": "tsnd ./src/main.ts",
  "prod": "node ./dist/main.js",
  "test": "jest",
  "test:watch": "jest --watchAll",
  "test:cov": "jest --coverage",
  "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
  "lint": "eslint \"src/**/*.ts\" --fix"
}
```

Here, you've got your usual suspects: build, dev, test, and more.

### Format All The Things!

Before diving into development, let's keep it neat. The `format` script will handle that.

```bash
pnpm format
```

### Running in Dev Mode

And finally, the moment you've been waiting for—fire up the dev server and see your app come to life!

```bash
@expressots/tests/expressots-first-project via  v16.19.0
❯ pnpm dev

[INFO] ts-node-dev ver. 2.0.0 (using ts-node ver. 10.9.1, typescript ver. 4.9.5)
Application version not provided is running on port 3000 - Environment: development
```

## Making Your First Request in ExpressoTS 🌐

### Time for a Little Hello!

You've been through the house tour, you've feng shui'd your `.prettierrc` and got your scripts all figured out. Now what? Well, how about actually seeing your app in action?

### Using HTTPie for Your First GET Request

For this demonstration, we're going to use [HTTPie](https://httpie.io/) — the `cURL` for the 21st century. But like, way more readable. Here's how to send your first GET request to `http://localhost:3000`.

```bash
@expressots/tests/expressots-first-project via  v16.19.0
❯ http :3000
```

*Bam!* You should see a response like:

```bash
HTTP/1.1 200 OK
...
Hello Expresso TS!
```

**Congrats!** You just made your server say hello.

## Anatomy of the "Hello Expresso TS!" 🦴

Alright, let's dissect that `"Hello Expresso TS!"` message. How does this simple string pass through layers of TypeScript files to make it to your browser? Spoiler: _It's not magic; it's just well-structured code._

### The Starting Point: **src/main.ts**

This is where the baton is picked up. Here, we import the essential parts from ExpressoTS and set up the initial application instance. Simple enough.

```ts
import "reflect-metadata";
import { AppInstance, ServerEnvironment } from "@expressots/core";
import { container } from "./app.container";

async function bootstrap() {
  AppInstance.create(container);
  AppInstance.listen(3000, ServerEnvironment.Development);
}

bootstrap();
```

### The Container: **src/app.container.ts**

Think of this as the backstage, where everyone gets ready for the show. It's where the application container is configured with your custom modules.

```ts
import { AppContainer } from "@expressots/core";
import { AppModule } from "./app.module";

const appContainer = new AppContainer();
const container = appContainer.create([AppModule]);

export { container };
```

### The Module: **src/app.module.ts**

Modules in ExpressoTS group related functionalities. Here, it's as simple as importing the `AppController`.

```ts
import { CreateModule } from "@expressots/core";
import { AppController } from "./app.controller";

const AppModule = CreateModule([AppController]);

export { AppModule };
```

### The Controller: **src/app.controller.ts**

This is the conductor of our orchestra. It's responsible for handling HTTP requests and directing traffic. In this case, it's just saying, `"Hello Expresso TS!"`.

```ts
import { BaseController, controller, httpGet, response } from "inversify-express-utils";
import { Response } from "express";
import { AppUseCase } from "./app.usecase";

@controller("/")
class AppController extends BaseController {
  constructor(private appUseCase: AppUseCase) {
    super("app-controller");
  }

  @httpGet("/")
  execute(@response() res: Response) {
    return res.send(this.appUseCase.execute());
  }
}
```

### The Use Case: **src/app.usecase.ts**

Here's where the actual `"Hello Expresso TS!"` lives.

```ts
import { provide } from "inversify-binding-decorators";

@provide(AppUseCase)
class AppUseCase {
  execute() {
    return "Hello Expresso TS!";
  }
}
```

## "Hello, Who?" Changing the Default Response 🖊️

Got bored of the usual `"Hello Expresso TS!"`? Let's give it a personal touch. To do that, we only need to venture into the `src/app.usecase.ts` file. See, this is the beauty of a well-structured codebase; you don't have to jump through hoops to make a simple change.

### The Tweak: **src/app.usecase.ts**

One line change. That's it. Here we just swap out the text to `"Hello from <Daniel::Boll>"`.

```ts
@provide(AppUseCase)
class AppUseCase {
  execute() {
    return "Hello from <Daniel::Boll>";
  }
}
```

### The Reload: Auto-refresh FTW

As soon as you save that change, the development server detects this update and reloads itself. No manual effort required. Ah, the joys of modern development.

```bash
[INFO] Restarting: /../@expressots/tests/expressots-first-project/src/app.usecase.ts has been modified
Application version not provided is running on port 3000 - Environment: development
```

### The Result: Let's Talk to the Server Again

Run the command, and voila! The updated greeting is now served hot, right from your server.

```bash
Hello from <Daniel::Boll>
```

## Dive deeper

If you are interested in more stuff you can do in this simple ExpressoTS project make sure to check out the full blog at [daniel-boll.me](https://daniel-boll.me/posts/a-first-project-with-expressots).