Newer
Older
client_dwatch / lib / api / schedule-filter.ts
/**
 * GET /errors・GET /clean-logs・GET /clean-logs/export の `schedule` 絞り込みの検証と照合。
 *
 * ★`lib/api/master-id.ts` と同じ置き場・同じ書き方の純粋関数★(指示書BH §12-2)。
 */
import { fail, type QueryParseResult } from "@/lib/api/query-result";
import type { ScheduleFilter } from "@/lib/types";

/** 受け付ける値(★この順★ — details の文言に使う) */
export const SCHEDULE_FILTERS = ["scheduled", "unscheduled"] as const;

/**
 * `schedule` クエリパラメータを検証する。
 *
 * | 入力 | 結果 |
 * |---|---|
 * | 省略・空文字・空白だけ | `null`(すべて) |
 * | `scheduled` / `unscheduled` | その値 |
 * | それ以外 | 422(★入力値をエコーしない★) |
 */
export function parseScheduleFilter(
  searchParams: URLSearchParams
): QueryParseResult<ScheduleFilter | null> {
  const raw = searchParams.get("schedule")?.trim() || null;
  if (raw === null) {
    return { ok: true, query: null };
  }
  if (!SCHEDULE_FILTERS.includes(raw as ScheduleFilter)) {
    return fail(422, "validation_failed", "scheduleの値が不正です", {
      schedule: [`${SCHEDULE_FILTERS.join(" / ")} のいずれかを指定してください`],
    });
  }
  return { ok: true, query: raw as ScheduleFilter };
}

/**
 * 予定あり/予定外の絞り込みに行が一致するか。
 *
 * ★引数 `isScheduled` は「予定あり=true」で固定★ — エラー一覧は `key.scheduled`、
 *   清掃詳細ログは `!r.unscheduled` を渡す(指示書BH §12-5 罠9)。
 */
export function matchesScheduleFilter(
  isScheduled: boolean,
  filter: ScheduleFilter | null
): boolean {
  if (filter === null) return true;
  switch (filter) {
    case "scheduled":
      return isScheduled;
    case "unscheduled":
      return !isScheduled;
    default: {
      const _exhaustive: never = filter;
      return _exhaustive;
    }
  }
}