/** Helpers for reading Next.js searchParams (Promise>). */ export type SP = Record; export function sp1(sp: SP, key: string): string | undefined { const v = sp[key]; const s = Array.isArray(v) ? v[0] : v; return s && s.length ? s : undefined; } export function spNum(sp: SP, key: string): number | null { const s = sp1(sp, key); if (s === undefined) return null; const n = Number(s.replace(/[,$\s]/g, '')); return Number.isFinite(n) ? n : null; } export function spInt(sp: SP, key: string, fallback = 1): number { const n = spNum(sp, key); return n === null ? fallback : Math.max(1, Math.trunc(n)); } export function spEnum(sp: SP, key: string, allowed: readonly T[], fallback: T): T { const s = sp1(sp, key); return s && (allowed as readonly string[]).includes(s) ? (s as T) : fallback; } export function pick(sp: SP, keys: string[]): Record { const out: Record = {}; for (const k of keys) out[k] = sp1(sp, k); return out; } export function withParams(base: string, params: Record): string { const u = new URLSearchParams(); for (const [k, v] of Object.entries(params)) if (v !== undefined && v !== null && v !== '') u.set(k, String(v)); const qs = u.toString(); return qs ? `${base}?${qs}` : base; }