Hono RPC + Superjson で厳密に型を共有する

はじめに

今回はHonoのRPCを利用する際に、フロント・バックエンドで厳密に型を共有する方法を紹介します。 SuperJSONで型情報をjsonに追加した上で、zod.parse()を利用して値を検証して型を付与します。

利用技術

  • Hono v4.7.11: Webフレームワーク
  • SuperJSON v2.2.2: jsonに型情報を付与する
  • Zod v3.25.56: バリデーション
  • TypeScript

背景

HonoのRPC機能では、フロントエンドから下記のようにAPIを呼び出すことができます。

// バックエンド側のレスポンス作成部分
export const getSampleHandler = async (c) => {
  return c.json({
    message: "test",
    date: new Date(),
  });
};

// フロントエンド側のAPIコール部分
const response = await client.api.sample.$get(); // 'GETメソッドで /api/sample を呼び出す'
const data = await response.json();

この時dataの型情報を見ると、dateがstring型になっています。

これはレスポンスに設定したobjectがjsonに変換される際にjsonで扱える形式にキャストされるため発生します。 せっかくRPCを使うのであれば、すべての型情報を共有したいのでSuperJSONを活用することにしました。

関連情報

下記の記事で、今回やろうとしていることが解説されていましたが、現在のHonoのバージョンではそのまま利用することができませんでした。

zenn.dev

またGitHubのissueでも同じことが議論されていましたが、具体的なコードは提示されないままクローズされています。 github.com

同issueの中でzod.parse()について言及があったため、これを利用して実装してみました。 github.com

実装

バックエンド側

SuperJSONを使ってレスポンスが返せるように、下記の関数を準備します。

export const jsonS = <T>(
  c: Context,
  object: T,
  status: StatusCode = 200,
  headers?: Record<string, string>
) => {
  const body = SuperJSON.stringify(object);

  const responseHeaders = {
    "content-type": "application/json; charset=UTF-8",
    "x-SuperJSON": "true", // SuperJSON形式でシリアライズしていることを表現
    ...headers,
  };

  return c.newResponse(body, status, responseHeaders);
};

ヘッダーを追加するので、CORSの設定を追加します。

const app = new Hono()
  .use(
    "*",
    cors({
      ・・・
      exposeHeaders: ["x-SuperJSON"], // 許可する
      ・・・
    })
  )

上記の関数を利用してAPIのレスポンスを作成します。

export const getSampleHandler = async (c: Context) => {
  const data = {
    message: "test",
    date: new Date(),
  };

  return jsonS(c, data);
};

合わせてレスポンスのスキーマをZodで定義します。

export const sampleResponseSchema = z.object({
  message: z.string().describe("サンプルメッセージ"),
  date: z.date().describe("日付"),
});

バックエンド側の実装はこれで終了です。

フロントエンド

こちらもヘルパー関数を用意して、SuperJSONとZodを使ってobjectを取得します。

export async function parseTypedResponse<T extends z.ZodSchema>(
  response: Response,
  schema: T
): Promise<z.infer<T>> {
  const text = await response.text();

  // SuperJSONパース
  let parsedData: any;
  if (response.headers.get("x-SuperJSON")) {
    parsedData = SuperJSON.parse(text);
  } else {
    parsedData = JSON.parse(text);
  }

  // Zodバリデーション
  return schema.parse(parsedData);
}

APIのコール部分は下記のイメージです。

const response = await client.api.sample.$get();
const data = await parseTypedResponse(response, sampleResponseSchema);

これでdate型の型情報が付与されました。

おわりに

今回はHono RPC + SuperJSON を使ってDate型も含めた型共有を実現してみました。 Zodのスキーマ情報をフロント・バックエンドで共有する必要が出てくるので、もう少しスマートに実現できると嬉しい気がします。

KtorでfatJarを作成する

はじめに

Ktorアプリケーションを起動するにあたり、少し詰まったので備忘録を残しておく。

背景

APIサーバをKotlin + Ktorで構築し、Dockerコンテナ上でフロントのサービスからAPIを呼び出せるようにしようとした。
単純に下記のコマンドで実行できるかな?と思ったがうまくいかなかった。

# ビルド
./gradlew build


# 実行
./gradlew run

対応方法

下記ページを参考にfatJarを作成することで、APIを呼び出せるようになる。 ktor.io

# ビルド
./gradlew buildFatJar


# 実行
./gradlew runFatJar

※ fatJar: 依存ライブラリを全て含んだ単一で実行可能なjarファイル

パスワード入力フォームのコピペは許可した方が良い

概要

パスワード入力フォームのコピーアンドペーストは、許可した方がセキュリティ的なメリットが大きいと思った話。

背景

以前自分が携わっていたWebサイトでは、ログインフォームにパスワードとパスワードを再度入力させるフォームを用意していた。
これは誤ったパスワードを登録してログインできなくなるのを防ぐために設置したので、コピーアンドペーストはできないようにして手で入力を促す仕組みにしていた。

ただ先日、下記の本を読んでコピーアンドペーストを許可した方が良いと理解を改めたので、記事に残しておく。

フォームの想定

以下のような、ユーザー登録画面などでパスワードを2回入力させるフォームを想定。
「パスワード(確認)」の入力欄がペースト禁止になっている。

なぜコピーアンドペーストを許可した方が良いか

メリット

  • ブラウザやアプリのパスワードマネージャーを使って、堅牢なパスワードを設定してもらいやすくなる。
    • コピペができない場合、入力が簡単なパスワードにあえて変えられる可能性がある。

デメリット

  • パスワードマネージャーを利用せず手入力するユーザーは、想定したパスワードとは異なる状態で登録されるかもしれない。
    • 例:大文字小文字を間違えた状態で入力して、確認欄にペーストするとか
    • パスワードを可視化する機能をつけることで、入力誤りに気づく可能性を上げれる。
    • パスワードリセットの機能があれば、リトライできるので問題にはならない。

まとめ

パスワード入力フォームのコピーアンドペーストは許可した方が良いと思ったという話。
許可した場合のデメリットは、機能を提供することで軽減することができるので、セキュリティ向上を優先したい。

人生で使える時間って本当に少ない・・・

概要

勉強が全然できなくなったので、何が原因か振り返ってみる

思いついたこと

二人暮らしを始めた

二人暮らしを始めて、自分のためにだけに使える時間が明確に減った。

その分の時間は二人のために使うようになって、例えば

  • ちゃんとご飯を作る
  • 毎日お風呂掃除をする

とかでちょっとずつ時間が消化されている。

では元々何をやっていた時間かと考えると、友人ともくもく会や筋トレ会を行っていた。 毎日1時間半ほど、勉強と筋トレに当てていたと考えると頑張っていたと思う。

本業で学ぶことが多い

転職して1年ぐらいが経つが、まだまだ仕事から学ぶことが多い

  • 初めての言語での開発
    • 初めての設計思想
  • チームリーダーとしてマネジメント

仕事を楽にするために勉強するのが最初のモチベーションだったが、今はこの気持ちが少し薄れてきているのかもしれない。

副業を始めた

友人の会社で副業を始めて、本業以外でも開発をするようになった。 あまり新しい領域を広げることには繋がらないが、コードを書く時間にはなっている気がする。

振り返ってみて

一人暮らしのときは、もくもく会をほぼ毎日実施することで強制的に勉強時間を確保していた。 暮らしが変わるタイミングで休止してしまったので、毎日は無理でも定期的に開催するように計画するのが良さそうだ。 モチベーションがなくとも、定期で時間を取れば進捗するだろう。

ただ、率先的に学習する意欲は減ってきていると感じている。 これからまた生活スタイルが変わってくることを考えると、今後のキャリアの見直しも必要になるかもしれない。

プロダクトマネージャーのしごと を読んだ感想

概要

プロダクトマネージャーのしごと を読んだのでその感想を書いた。

プロダクト運営を成功させるための銀の弾丸は存在しないので、地道にコミュニケーションを取るのが大切だと感じた。

本について

読んだ理由

  • ◯◯マネージャーという役職がいくつか存在するが、それぞれがどんな役割か分からなかったので「プロダクトマネージャー」は何をする必要があるかを知るため
    • プロジェクトマネージャーとはどう違うかとかも気になりポイント

対象読者

  • プロダクトマネージャー、のような役職についたが、どんなことが求められているか分からない人
  • 将来的にマネジメント方面に進もうと考えている人
    • 今マネージャーがどんな仕事をしているかのイメージを掴めるはず

理解したこと

◯◯マネージャ毎に決まった役割はない

各組織によってそれぞれ責務は変わってくるので、自身の組織ではどういう働きを求められているか確認する必要がある。

プロダクトマネージャとして何をする必要があるか

終わらせる必要があることをすべて行う必要がある。 もちろん、自分ひとりですべてをやる必要はなく、各専門家やステークホルダー同士の橋渡しをして終わらせるための段取りを組めばOK

やるべきことを外野が言ってくれるまで待っているのはNG

後手に回れば回るほど、つらい思いをする可能性が高くなるので、何事も先回りして解決しておくような行動が求められる。 これは関係者間の認識相違などにも同じことが言える。言わなくても大丈夫だろう・・・と思うことは、気まずい雰囲気になろうが発信することで後々大きな問題になることを防ぐことができる。 本書では「過剰なコミュニケーション」と表現しているが、これが一番大切なことだと感じた。

メンバーが今何をするべきか自分で判断できない状態はNG

自分が1ヶ月休んでも仕事が進む体制を作れるように仕組み作りを行うことが大切。 案件の優先度やなぜこの案件を対応するかをメンバーが判断できない状態は、組織化が進んでいないと言える。 組織化が進むと各メンバー間のコミュニケーションに自身が不要になり、必要な対応を各々が判断できるようになる。

アウトプットだけを意識するのはNG

最小の労力で最大の収益を上げることを意識することが大切。 多くの仕事をして多くのアウトプットをアピールしたくなるが、無駄な仕事をチームにさせている可能性があるので注意する。

また、ユーザーのニーズを知ることができるようにインタビューやツールの導入をすると良い。 ヒートマップツールなどを導入すると、ユーザーニーズにあったUI/UX改善のヒントになる。

感想・まとめ

今回はプロダクトマネージャーのしごとを読んだ感想を書いた。 自分から積極的に関係者とコミュニケーションを取り、プロダクトを良くするためのタスクを進めていくことが大切だと感じた。 本書では他にもアンチパターンやリモートワークでの働き方などについても記載があるので、興味があれば手にとってほしい。

「読み手につたわる文章 テクニカルライティング」を読んだ感想

概要

先日から開催されている技術書典 16で購入した表題の本について、感想を書きました。

この記事は誰向けの内容か

  • 本書に興味を持っているが、購入を悩んでいる人
  • 本書を購入して他人の感想が気になった人

この記事は誰向けの内容ではないか

  • 本書について興味がない人

この記事を読んだ後にどんな状態になるか

  • 本書で学べることが分かるはず

この本を読もうと思ったきっかけ

技術書典 16 のおすすめ本をツイッターなどで探していて、目についたのがきっかけになります。 普段の業務はリモートワークのため、以下のように文章を書く機会がとても多いです。

  • slackでの報告・連絡・相談
  • 社内Wikiに手順書やナレッジを書く
  • チケットに調査内容や実装方針を書く

これらの文章を分かりやすく記述するために、役立つことがあればと購入を決意しました。

本の概要

techbookfest.org

良かったこと、理解したこと

そもそもテクニカルライティングとは

テクニカルライティングとは実用文を分かりやすく書くための技術です。

そして実用文とは以下のような文章のことです。

対象となる「何か」について論理的かつ簡潔に説明してをしていてそれを読むことで何をどうすればいいのかが分かるような文章

業務で書く文章の大半は、この定義に当てはまると思うので、社会人には必須な技術だと感じました。

文章を書くにあたって

ある対象について文章を書くためには、対象を深く理解する必要があると理解しました。 確かに対象への理解が浅いと、解像度の低い情報しか伝えることができません。

例えば、「りんごは赤い果物です。」としか説明できないのと、「りんごはバラ科リンゴ属に属する果物で、寒冷地帯で栽培が盛んです。」だと得られる情報は変わってきます。 もし曖昧な言葉しか出てこないなら、もう少しインプットすることを心がけようと思います。

レビューに関する心構え

文章のレビューについて書かれていましたが、他のレビューにも応用できる考え方を知れて良かったと感じています。

指摘は素直に受け入れる

「好みかもですが―」みたいな指摘を受けたときは、やらない理由を考えてしまうことがありますよね。 より良くする視点で指摘をしてくれているので、基本的には修正することで品質は向上して後悔することは少ない、というのは確かにと思いました。 時間がないとか言い訳をせずに、手を動かすことを心がけたいです。

レビュアーが気づいたことに、書いたとき気付けなかったのは当然

この視点が自分にはなくて、「こんな簡単なことも気付けなかった……」と落ち込むことがありました。 しかし、レビュアーはレビューに100%のリソースを使っている一方、レビューイは成果物を作る際に多くのことにリソースを使っています。そのため、気付けることに差が出るのは当然ということです。 必要以上に落ち込むことなく、指摘に感謝して修正するようにしたいと思いました。

まとめ

今回は「読み手につたわる文章 テクニカルライティング」を読んでの感想を書きました。 心構えにフォーカスした感想になってしまいましたが、本書では実際にどう書けば良いのかも解説されています。 この文章もそのルールに従って作成をしてみました!

気になった方はぜひ読んでみてください!

「移動する人はうまくいく」を読んだ感想

「移動する人はうまくいく」という本を読んだので、その感想記事です。

本について

  • タイトル:移動する人はうまくいく
  • 著者:長倉 顕太

手に取った理由

私はリモートワークをメインにしていて、趣味もインドア派なので、ほとんど外に出ない生活を送っています。 また、最近転職をしたのですが、思っていたよりも仕事がうまく進められておらず、改善の必要性を感じていました。 そんなときにこの本に出会い、自分の生活とは真逆だけれど、何かヒントになることがあるかもしれないと思い、手に取りました。

わかったこと・感じたこと

行動を変えるならまずは環境を変える

自分の行動を変えるためには、環境を変えるのが効果的だと理解しました。

私は、「筋トレをするぞ!」とか「この勉強をするぞ!」と決心しても、すぐに三日坊主になってしまうことが多く、自己啓発系の本を読んでモチベーションを保っていても、それが習慣になるまで続いたことはほとんどありません。

一方、転職に伴って東京に引っ越したことで、東京に住む友人たちと「もくもく会」を始めることができました。 環境が変わったことで、結果的に勉強する時間を持つことができたのです。

確かに、環境を変えることは行動を変えるきっかけになりそうなので、今後も移動して新しい環境にチャレンジするようにしたいと思いました。 リモートワークができる企業に勤めているので、仕事が移動の障壁にならないのは助かっています。

一つの場所に居続けると自分のキャラクターが固定される

これは特に共感した内容です。

一つの場所に居続けると、周囲からずっと同じキャラクターとして扱われることになります。

例えば、私は実家にいた頃、子供として甘える振る舞いをよくしていたように思います。 親が与えてくれるのを待つような態度で、何かを頼むときも察してもらうのを待っていました。典型的な甘えん坊だったと思います。

しかし、一人暮らしを始めると、自分で家事をする必要があったり、何かが欲しいときには自分から行動しなければなりません。これにより、自然と振る舞いが変わっていきました。それでも、人生の半分以上を実家で過ごしていたので、性格面ではまだ甘えが残っていると感じています。これは、できれば改善したい部分です。

さらに、場所を変えることの利点として、この本にも書かれていましたが、新しい土地ではまったく違うキャラクターとして振る舞っても、違和感を持つ人がいないことが挙げられます。 私の場合、大学デビューみたいなことはありませんでしたが、一人暮らしを始めてから、アニメやゲームのグッズを部屋に飾るようになりました。実家ではなんとなく恥ずかしくてできませんでしたが、今では平気になっています。

このように、自分がなりたい自分像と現実とのギャップを埋めるためには、場所や環境を変えて新たなチャレンジをするのが有効だと理解しました。

好きな人のルーツを辿る

好きな作家、クリエイターなど自分がリスペクトしている人が

  • どんな本を読んできたのか
  • どんな人生を送ってきたのか
  • 何が好きか
  • 何が嫌いか

といった、その人のルーツを辿ることで、少しメタ的な思考ができるようになることが分かりました。 ただその人の本を読んでいるだけでは、作品についての感想しか浮かびませんが、ルーツを知ることで、その背景が見えてくるということだと思います。

これは人間関係にも応用できる話だと感じていて、相手に興味を持ち、そのルーツを知ろうとすれば、良い関係を築けるようになる気がします。

まとめ

今回は、「移動する人はうまくいく」を読んだ感想を書いてみました。

今はなんでも家からインターネットで解決できる時代ですが、意図的に色んなところに移動して行動を変えるきっかけを作っていきたいなと思いました。

本書の中には、実際に移動できる体質を作るプランもいくつか紹介されていたので、気になった方は読んでみてください。