TypeScript 製のフレームワーク FoalTS を使ってみる

# FoalTS とは

https://foalts.org/

TypeScript で作られている Express ベースのウェブアプリケーションフレームワークです。
多くの Node 向けフレームワークはマイクロフレームワークで、気軽に始めるのはいいのですが、ちょっと込み入ったアプリにしようと思った時にあまりに自由度が高いので意外と開発が難しくなる傾向がありますよね。

その点、FoalTS は軽量なスタートから、堅牢なアプリケーションを開発するために必要な基本的な機能を提供してくれるフルスタックフレームワークとしても使える (とドキュメントには書いてある) ということなので、サーバーサイドを Node で運用したいときに Express に代表されるようなマイクロフレームワーク以外の選択肢として結構良いかもしれないと思い、少し試してみることにしました。

# プロジェクトを作る

多くのフレームワークと同じく、プロジェクトを作成したりできる CLI ツールが提供されています。

```bash
npm install -g @foal/cli
```

インストールすると次のようにプロジェクトを作れます。今回は `try-foal` という名前にしてみました。

```bash
foal createapp try-foal
```

うん。この辺りはよくある感じですね。

```:ディレクトリ構成はこんな感じ
try-foal/
  config/
  node_modules/
  public/
  src/
    app/
    e2e/
    scripts/
  ormconfig.js
  package.json
  tsconfig.*.json
  .eslintrc.js
```

そしてこの時点で `npm run develop` することで開発サーバーを起動できるようになっています。

<img width="1091" alt="開発サーバーを起動したスクリーンショット" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/765/31d22cc7-3b84-56af-2b4f-6835d711d108.png">

また、ここで `npm run test` とするとユニットテストが、 `npm run e2e` とすると E2E テストが起動します。この辺り含まれているのは個人的には嬉しいところです。

# コントローラの定義

ジェネレートしたプロジェクトのファイルを見てみます。
NestJS ほど　Decorators がごてごてしていなくて、コードの見やすさも良いですね。

```typescript:src/app/controllers/api.controller.ts
import { Context, Get, HttpResponseOK } from '@foal/core';

export class ApiController {
  @Get('/')
  index(ctx: Context) {
    return new HttpResponseOK('Hello world!');
  }
}
```

メソッドは非同期でも書けるので、DB 操作など外部通信が走るようなメソッドもシンプルに書けそう。
バリデーションなどもデコレータで書けるみたいですね。これはまあ、好み分かれそうな印象ですね〜。

```typescript:公式ドキュメントから
import {
  ...
  ValidateBody, ValidatePathParam
} from '@foal/core';

export class ApiController {

  ...

  @Post('/todos')
  @ValidateBody({
    // The body request should be an object once parsed by the framework.
    // Every additional properties that are not defined in the "properties"
    // object should be removed.
    additionalProperties: false,
    properties: {
      // The "text" property of ctx.request.body should be a string if it exists.
      text: { type: 'string' }
    },
    // The property "text" is required.
    required: [ 'text' ],
    type: 'object',
  })
  async postTodo(ctx: Context) {
    const todo = new Todo();
    todo.text = ctx.request.body.text;

    await getRepository(Todo).save(todo);

    return new HttpResponseCreated(todo);
  }

  ...
}
```

ここについては、定義を分けて書いたり、Validation Class (class-validator) を使って書くこともできるので、大きなアプリケーションでは外に出した方が見通し良さそうです。

# データベースを操作する

FoalTS では ORM として [TypeORM](http://typeorm.io/) を使用しています。そして、そのエンティティをジェネレートするコマンドもあります。

```bash
foal generate entity news
```

こうすると `src/app/entities` に `news.entity.ts` のようなファイルが生成されるのでこれを編集していく感じですね。

ここは特に変わったことはなくただただ普通に使いやすそうかなというところ。

# フロントエンドライブラリとの連携 (React, Vue, Angular)

最近のアプリケーションではビューライブラリを使うこともとても多いので、この辺り気になるところです。
FoalTS の `connect` コマンドを使うことで、例えば `create-react-app` したフロントエンド実装と連携させることができます。

```bash:これはドキュメントに書かれているものです
mkdir my-app
cd my-app

foal createapp backend
npx create-react-app frontend --template typescript

cd backend
foal connect react ../frontend
```

React の場合は frontend アプリケーションの `package.json` に `proxy` の設定が追加されました。
これは開発時に、FoalTS と React の開発サーバーのポートが異なる時に Origin (CORS) の問題を回避するためですね。

ドキュメントには React の SSR についても書かれていますが、この辺りはまだ最低限なサポートに見えました。

# Shell Script (コマンド) の定義

フルスタックフレームワークらしく、コマンドを定義することもできます。
`foal generate script create-news` で `src/scripts/create-news.ts` が作られます。
ここに定義した操作を `foal run create-news` で実行することができます。

# ひとまずまとめ

少しずつ試しているのですが、全て 1 記事にするとすごく長くなりそうだったので一旦この辺りで切り上げることにします。(そうしたら、ただドキュメントのチュートリアルをなぞっただけみたいなことになってしまったのですが)

ちゃんとしたアプリケーションを作る時に必要なものは一通り入っていて、その割に Node / Express の手軽さも残しているのでライトな使い方から業務レベルでのアプリケーションまで一通りこなせそうな印象でした。
最近の流行からはちょっと外れているかもしれませんが、TypeScript でアプリを作りたい時には選択肢に入れてもいいかもですね。

ここまで書いておいてあれですが、こんなものより公式のドキュメントが読みやすいので、興味がある方は是非。