import type { Filters, Sort } from "./queries"; import { SORTS } from "./queries"; export type SP = Record; const arr = (v: string | string[] | undefined) => (v === undefined ? [] : Array.isArray(v) ? v : v.split(",")).map((s) => s.trim()).filter(Boolean).slice(0, 12); export function parseFilters(sp: SP): Filters { const sort = typeof sp.sort === "string" && (SORTS as readonly string[]).includes(sp.sort) ? (sp.sort as Sort) : undefined; const page = Math.min(500, Math.max(1, parseInt(String(sp.page ?? "1"), 10) || 1)); return { q: typeof sp.q === "string" ? sp.q : undefined, category: arr(sp.category), tag: arr(sp.tag), use: arr(sp.use), os: arr(sp.os), exec: arr(sp.exec), iface: arr(sp.iface), source: arr(sp.source), pricing: arr(sp.pricing), status: arr(sp.status), depth: arr(sp.depth), selfhost: sp.selfhost === "1", sort, page }; } export function toQuery(f: Filters, patch: Partial = {}): string { const m = { ...f, ...patch }; const p = new URLSearchParams(); if (m.q) p.set("q", m.q); for (const k of ["category", "tag", "use", "os", "exec", "iface", "source", "pricing", "status", "depth"] as const) for (const v of m[k] ?? []) p.append(k, v); if (m.selfhost) p.set("selfhost", "1"); if (m.sort) p.set("sort", m.sort); if (m.page && m.page > 1) p.set("page", String(m.page)); const s = p.toString(); return s ? `?${s}` : ""; } export function toggle(f: Filters, key: keyof Filters, value: string): string { const cur = (f[key] as string[] | undefined) ?? []; const next = cur.includes(value) ? cur.filter((v) => v !== value) : [...cur, value]; return toQuery(f, { [key]: next, page: 1 } as Partial); }