Open6

[WIP] T3 Stackで作ったWebシステムにおいて Type SafeなCLIツールを作成できるか?

TakashiAiharaTakashiAihara

動機

T3 Stackについて勉強中です。まだフワフワ。

バックエンド - フロントエンドで型定義を共有し、APIの静的型付けを実現する。
いまのところ T3 Stack最強だと思っているんですが、一つ疑問が。
「APIの汎用性はどこまで担保できる?」

大きな B to C 向け Webシステムは、SDKやらCLIの提供が一般的です。
IaaS、PaaS、SaaSと幅広く。
それによる利用促進の効果も期待できます。
これは REST APIによる恩恵の一つだと思います。

果たして T3 Stackを使ったWebシステムでも、それらの提供が可能なのか?
とそれらしいことを書きましたが、つまり「バック・フロント密結合すぎない?」って感覚を打破したいのです。*1

その他の動機「ブックマークマネージャ自炊したい欲」

ブックマークマネージャーとして buku を使っています。
CLIベースでブックマークを管理するプロダクト。
これ、シンプルかつ便利でコンセプトも良い。
ただ自分の積ん読グセがひどすぎるので、もっと自分を戒める機能が欲しいなぁと。

CLIで利用可なブックマークマネージャとしつつ、

  • 複数デバイス (Windows / Mac / Android / iPhone etc)
  • 複数ブラウザ (Chrome / Firefox / Edge etc)

これらからアクセスできる環境を作り、一元管理してしまいたい。*2

元はといえば、数万の単位でブックマークをしてしまう自分が全て悪いんですが、この積ん読グセは治ることはない。

注釈

*1 tRPCを利用するCLIが作れるか?のほうが正しいかもしれない。あと、gRPCを間にかませれば割と簡単に出来そうですね。
*2 buku自体は bukuserver というもので Web UI があるようです。少し前の記憶ですが Basic 認証しか使えなかったはず。。。

TakashiAiharaTakashiAihara

tRPCのドキュメントからすると、 Client側の Type AppRouter が切り分けられれば出来そう。

import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from '../path/to/server/trpc'; // <- ここの切り分け
const client = createTRPCProxyClient<AppRouter>({
  links: [
    httpBatchLink({
      url: 'http://localhost:3000/trpc',
      // You can pass any HTTP headers you wish here
      async headers() {
        return {
          authorization: getAuthCookie(),
        };
      },
    }),
  ],
});

割とさっくり出来るのかな。。。
Webpackをいじったりとかだとしんどそうだな

TakashiAiharaTakashiAihara

暫定解決策「フロント・バックを別RepoにしてLinkする」

ここに記述が。

https://trpc.io/docs/faq#is-a-monorepo-mandatory
https://github.com/trpc/trpc/discussions/1860

別リポジトリとしてしまって、フロントエンドのRepoでバックエンドを npm install してLinkする。
Router の型定義をimportして使う形。

ただ、この解決策の場合、参照しているバックエンドのパッケージが最新でなければ、型定義の乖離が生まれることになります。
暫定。

最も理想的な形は

  • バックエンド / フロントエンド / CLI の monorepo
  • CLIから参照するのは型定義のみ(バックエンドのセキュリティ担保)
  • 一回のBuildですべて Buildされる( CLIもそのまま配布するだけ)

なかなか厳しそうだ

TakashiAiharaTakashiAihara

いや、結合点は 型定義の import だけだから、実は全然難しくないんじゃないか?

TakashiAiharaTakashiAihara

ヒントを見つけた。

https://github.com/t3-oss/create-t3-turbo

Create T3 Turbo

こちら、フロントエンドに React / React Native (Expo) を構成した monorepo で、これを基盤とすればもう殆ど何でもできる最強テンプレートです。

  • └ packages ( ワークスペース )
    • └ api (tRPCの実装)
  • └ apps ( フロント実装 )
    • └ nextjs ( for Web )
    • └ expo ( for Mobile )

こんな構成なんですが、実装は上記の nextjs とか expo の構成をパクれば良さそうだった。

  • ワークスペースで trpc定義を実装
  • apps でフロント実装をして、trpc の型定義を見させる

ざっくり書くとこんな感じで、それほど難しくなかった。

ただ、Buildでどれだけセパレートできるかが課題で、まだフワフワしている部分があるので引き続き調査。