Newer
Older
client_dwatch / lib / api / query-result.ts
/**
 * 一覧APIのクエリパラメータをパースした結果を表す共通の型。
 *
 * ★パース失敗は「null」ではなく、この union の `ok: false` で返すこと★
 *   null だと「どのパラメータが不正か」を呼び出し側に渡せず、
 *   ルート側が `details: null` の 422 しか組み立てられない(CLAUDE.md §9.3 の
 *   `{ error: { code, message, details? } }` を活かせない)。
 *
 * `lib/api/` に置く理由: エラー形式は CLAUDE.md §9.3 が全API共通と定めており、
 * 共通の形は共通の場所に置く(`lib/api/client.ts` と同じ考え方)。
 * `lib/clean-logs/` に置くと prechecks / ds-alerts / ds-devices が
 * 「清掃ログ」という無関係なドメインに依存することになる。
 */
import type { ApiError, ErrorCode } from "@/lib/types";

/** パース失敗。`status` は呼び出し側がそのままHTTPステータスに使う */
export interface QueryParseFailure {
  ok: false;
  error: ApiError;
  status: number;
}

export type QueryParseResult<T> =
  | { ok: true; query: T }
  | QueryParseFailure;

/**
 * 失敗を組み立てる。
 * `details` は「どのパラメータがなぜ不正か」を `{ パラメータ名: [理由] }` で入れる。
 * 省略時は `null`(キー自体を落とさない。API契約上 details は常に存在する)。
 */
export function fail(
  status: number,
  code: ErrorCode,
  message: string,
  details?: Record<string, string[]>
): QueryParseFailure {
  return {
    ok: false,
    status,
    error: { error: { code, message, details: details ?? null } },
  };
}