Skip to content

fix(frontend): unknown JSON の型キャストを zod safeParse に置き換え (#114) - #130

Merged
f0reachARR merged 8 commits into
mainfrom
feat/114-zod-parse-refactor
May 15, 2026
Merged

fix(frontend): unknown JSON の型キャストを zod safeParse に置き換え (#114)#130
f0reachARR merged 8 commits into
mainfrom
feat/114-zod-parse-refactor

Conversation

@f0reachARR

Copy link
Copy Markdown
Owner

概要

OpenAPI schema 上で unknown として扱われる diff.summary フィールドや API エラーのパースに使われていた危険な as 型キャストを、zod safeParse ベースの実装へ置き換えるリファクタリングです。

Closes #114


背景・要件

  • run-detail-content.tsxdiffError as Record<string, unknown> / diffError as Record<string, { message?: string }> のキャストが使われていた
  • create-token-dialog.tsxerr as { error?: { message?: string } } のキャストが使われていた
  • guards.ts の手動 type guard 4関数 (isFileChanges, isBomChanges, isCheckEntry, isArtifactChanges) を宣言的な zod schema に置き換える
  • runtime parse 失敗時の表示を明確にする("Data format not recognized" fallback)
  • 既存の正常系表示を維持する

調査結果

  • diff.summary as DiffSummary のキャストは実装前から既にゼロ件(parseDiffSummary(raw: unknown) に移行済み)
  • 残存 as キャストは API error の2箇所のみ
  • guards.ts の type guard 4関数は diff-summary.ts からのみ呼ばれていた(isRecord は3コンポーネントで使用中のため残存)
  • DiffSummary interface は import 0件で未使用

実装概要

変更ファイル一覧(9件)

ファイル 操作 内容
boardflow/src/lib/domain/diff-summary-schema.ts 新規 FileChangesSchema / BomChangesSchema / CheckEntrySchema / ArtifactChangesSchema の zod schema
boardflow/src/lib/domain/diff-summary.ts 編集 parseDiffSummarysafeParse ベースに書き換え。checks の全 entry 不正時に null 返却
boardflow/src/lib/domain/guards.ts 編集 type guard 4関数削除、isRecord のみ残存
boardflow/src/lib/api/error.ts 新規 parseApiErrorMessage(err: unknown): string | null helper
boardflow/src/components/run-detail/run-detail-content.tsx 編集 as Record<...>parseApiErrorMessage に置換
boardflow/src/components/tokens/create-token-dialog.tsx 編集 as { error?: ... }parseApiErrorMessage に置換
boardflow/src/lib/api/schema-types.ts 編集 未使用 DiffSummary interface 削除
boardflow/src/lib/domain/__tests__/diff-summary.test.ts 新規 vitest ユニットテスト 18件
boardflow/src/components/run-detail/run-diff-summary-card.tsx 編集 checks null 時の "Checks: data format not recognized" fallback 追加

設計方針

  • parseDiffSummary のシグネチャ (raw: unknown → ParsedDiffSummary) は不変 → 消費側コンポーネントの変更不要
  • フィールド単位 safeParse: 1フィールド不正でも他は正常に返る既存挙動を維持
  • parseApiErrorMessage は zod ではなく軽量 typeof チェック helper として実装(API error の構造が OpenAPI に未定義のため、zod import のコスト増を避けた)
  • checks 全 entry 不正時: null を返して "Data format not recognized" fallback を表示(silent drop を防止)

テスト結果

チェック 結果
vitest (18 tests) ✅ パス
pnpm lint ✅ パス (Checked 89 files, No errors)
pnpm typecheck ✅ パス
pnpm build ✅ パス (production build 成功)

更新ドキュメント

  • docs/logs/114/worklog.md — 作業ログ(research / plan / impl / review 2ラウンド / docs 確認)
  • docs/external/zod-v4-safeparse-unknown-json.md — zod v4 safeParse の外部調査メモ

外部調査メモ

  • zod v4 の safeParse API は v3 と互換。result.success / result.data / result.error の構造は変更なし
  • フィールド単位で safeParse を適用して部分的 fallback を維持する方針は妥当と確認

残リスク

  1. schema と interface の二重管理: diff-summary-schema.ts の zod schema と diff-summary.ts の TypeScript interface が並存。将来 z.infer<typeof Schema> に統一可能
  2. API error 構造の backend 依存: { error: { message: string } } は OpenAPI schema に未定義。backend 変更時は parseApiErrorMessagenull を返し fallback メッセージが表示される(安全側に倒れる)
  3. isRecord の将来移動: guards.tsisRecord のみが残っている状態。必要に応じて utils.ts 等に移動検討可能
  4. README.md の lint 記述不整合: pnpm lint の説明が「ESLint 実行」だが実装は biome check(今回の変更起因ではない既存不整合)

review / docs OK 判定

  • review agent: pr_ready: true(2ラウンドの指摘を修正後)
  • docs agent: docs_ready: true

…114)

- Add diff-summary-schema.ts with zod schemas for FileChanges, BomChanges,
  CheckEntry, ArtifactChanges
- Rewrite parseDiffSummary to use field-level safeParse instead of type guards
- Add parseApiErrorMessage helper for API error extraction
- Replace as casts in run-detail-content.tsx and create-token-dialog.tsx
- Remove unused DiffSummary interface from schema-types.ts
- Strip replaced type guards from guards.ts (keep isRecord for other consumers)
- Return null when checks object has entries but all fail safeParse
- Use result.data from safeParse for type-safe parsed values
- Add vitest and comprehensive test suite for parseDiffSummary
When parseDiffSummary returns null for checks (malformed data),
the summary card now shows 'data format not recognized' instead
of silently dropping the section.

Refs #114
@f0reachARR
f0reachARR merged commit bcf0003 into main May 15, 2026
2 checks passed
@f0reachARR
f0reachARR deleted the feat/114-zod-parse-refactor branch May 15, 2026 10:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

frontend: unknown JSON への型キャストを zod parse に置き換える

1 participant