export type CertificateStatusFilter = "all" | "valid" | "expired" | "revoked" | "unknown" const statuses = ["valid", "expired", "revoked", "unknown"] export function readCertificatesUrl(params: URLSearchParams) { const server = params.get("server"), status = params.get("status"), search = params.get("q") ?? "" let error: string | null = null if (["server", "status", "q"].some(key => params.getAll(key).length > 1)) error = "Параметры контекста сертификатов повторяются." if (server !== null && !(/^[1-9][0-9]*$/.test(server) && Number.isSafeInteger(Number(server))) && !/^srv[1-9][0-9]*$/.test(server)) error = "В ссылке указан неверный сервер." if (status !== null && !statuses.includes(status)) error = "В ссылке указан неизвестный статус." if (search.length > 200) error = "Поиск в ссылке слишком длинный." return { server: server ?? "all", status: (status ?? "all") as CertificateStatusFilter, search, error } } export function patchCertificatesUrl(params: URLSearchParams, changes: Record) { const next = new URLSearchParams(params) for (const [key, value] of Object.entries(changes)) if (value === null || value === "") next.delete(key); else next.set(key, value) return "/certificates" + (next.size ? "?" + next.toString() : "") }