トラス構造が幾何学的に組まれた建築物のファサード
現場の実践

@cyia/opentui-angular でAngularのTUI開発が変わる理由

目次を見る

CLIツールの内部管理画面やデプロイウィザードをターミナル上で動かしたい、という要件は業務システムの現場でも珍しくない。そうした場面で登場するのが TUI(Text User Interface)、つまりターミナル上に描画するテキストベースのUIだ。今回取り上げる @cyia/opentui-angular は、Angularのコンポーネント設計をそのままTUI開発に持ち込める実験的ライブラリで、業務ツール開発者にとって注目すべき技術的試みといえる。

TUI開発がこれまで難しかった理由

TUIアプリを1から作ろうとすると、開発者はまず低レベルの描画処理と格闘することになる。具体的には、ANSI エスケープシーケンス(ターミナル上で文字色やカーソル位置を制御するための特殊文字列)の手書き、文字バッファの管理、ターミナルのリサイズイベントの検知といった作業が発生する。これらはアプリ本体のビジネスロジックとはほぼ無関係な処理であり、コードベースに占める割合が膨らみやすい。

Node.js のエコシステムにはこの問題を緩和するライブラリがいくつか存在する。たとえば blessedink がその代表格で、ink は React のコンポーネントモデルをターミナルUIに適用するアプローチをとっている。OpenTUI はその後継的存在に近く、textboxinputscrollboxdiff など豊富なコンポーネントセットと、キーボードイベントやフォーカス管理を扱う Hooks API を備えている。ただし OpenTUI の設計は React のレンダリング基盤(react-server-dom-flight)に強く依存しており、Angular チームがそのまま採用するには障壁があった。

Angularのプラットフォーム抽象化をTUIに転用する仕組み

@cyia/opentui-angular が実現していることの核心は、Angularのレンダリング基盤を「ブラウザのDOM」から「ターミナルの文字バッファ」へ差し替える点にある。

Angularは内部に RendererFactory2Sanitizer という抽象レイヤーを持っており、描画の具体的な実装をプラットフォームごとに切り替えられる設計になっている。Angular Universal(サーバーサイドレンダリング用の実装)がこの仕組みを使ってNode.js上でHTMLを生成するのと同じ要領で、@cyia/opentui-angularTDomAdapter と呼ばれるカスタム実装を差し込み、DOM操作の呼び出しをOpenTUIのレンダラーへ橋渡しする。ブラウザのAPIが存在しない環境では、大半のDOM関連メソッドをno-op(何もしない空実装)として定義し、エラーを回避する構造だ。

コンポーネントのテンプレート側では、NO_ERRORS_SCHEMA(Angularが未知のタグ名に対してエラーを出さないようにする設定)を利用することで、<box><text> といったOpenTUI独自のタグをそのままAngularテンプレートで記述できる。

@Component({
  selector: 'app-root',
  schemas: [NO_ERRORS_SCHEMA],
  template: `
    <box>
      <text [content]="message()" fg="cyan" />
    </box>
  `,
})
export class App {
  protected message = signal('Hello from Angular + OpenTUI');
}

Signal(Angularの状態管理プリミティブ)がそのまま使えるため、既存のAngularコードベースに慣れた開発者であれば学習コストを抑えられる。

業務システム開発者が評価すべきポイント

このライブラリが業務ツール開発の文脈で特に意味を持つのは、既存のAngularスキルセットを再利用できる点だ。チーム内にAngularの知識があれば、TUI固有の学習コストを最小化しつつ内部CLIツールを実装できる可能性がある。

具体的な活用シナリオを整理すると、次のようなケースが想定される。

    <li>デプロイ前の確認ウィザード(環境変数の表示・選択・確定)</li>
    <li>マイクロサービス構成でのヘルスチェックダッシュボード</li>
    <li>DBマイグレーションの進捗をインタラクティブに表示する管理ツール</li>
    <li>CI/CDパイプラインの手動承認インターフェース</li>

キーボードショートカットの宣言的な定義(useKeymapuseBindings)やスロット(プラグイン的にUIを差し込む仕組み)の仕組みも備えており、画面を複数のコンポーネントに分割してチームで並行開発するスタイルも取れる。

一方で注意点もある。このライブラリは2024年7月時点で公開されたばかりの実験段階のプロジェクトであり、プロダクションでの採用実績は限られている。AngularのプライベートAPI(ɵinternalCreateApplication のように頭に ɵ がついているAPIはAngularの内部実装を指し、バージョン間の互換性が保証されない)を使用しているため、Angularのメジャーアップデート時に追随コストが生じるリスクは織り込んでおく必要がある。

対照となる選択肢として ink(React ベース)も挙げておく。ink はすでに多くのCLIツール(gatsbycreate-react-app など)で採用実績があり、安定性を優先する場面では依然として有力な選択肢だ。Angularチームが技術的な一貫性を保ちつつTUIを作りたい場合に、@cyia/opentui-angular は一考に値するという位置づけになる。

AngularのDI(依存性注入)システムをターミナルアプリに持ち込むというアプローチは、フレームワークの抽象レイヤーがどこまで汎用化できるかを示す事例としても技術的な価値がある。実用前には、対象のAngularバージョンとの互換性検証を必ず行ってほしい。

参考

Writing TUI in the Terminal with Angular: Introducing @cyia/opentui-angular

この記事について: 本記事は AI を活用して作成し、forva AI 編集部が内容を確認・監修しています。

AI 駆動開発のご相談は forva AI へ。まずはお気軽にどうぞ。