/**
* 一覧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 } },
};
}