export const networkMapFilters=["all","online","degraded","offline","unknown","jump-host","exit-node","home-router"] as const export type NetworkMapFilter=typeof networkMapFilters[number] export function readNetworkMapUrl(params:URLSearchParams){ const server=params.get("server"),search=params.get("q")??"",filter=params.get("filter")??"all",dest=params.get("dest")??"services",wan=params.get("wan") let error:string|null=null if(["server","q","filter","dest","wan"].some(key=>params.getAll(key).length>1))error="В ссылке повторяется контекст карты." else if(server!==null&&!/^[a-zA-Z0-9_.:-]{1,64}$/.test(server))error="В ссылке указан некорректный сервер карты." else if(search.length>256)error="Поиск карты в ссылке слишком длинный." else if(!(networkMapFilters as readonly string[]).includes(filter))error="В ссылке указан неизвестный фильтр карты." else if(!["services","countries"].includes(dest))error="В ссылке указан неизвестный режим назначений." else if(wan!==null&&(!server||!/^\d{1,4}$/.test(wan)))error="В ссылке указан некорректный аплинк карты." return {server,search,filter:filter as NetworkMapFilter,dest:dest as "services"|"countries",wan:wan===null?null:Number(wan),error} } export function patchNetworkMapUrl(params:URLSearchParams,values:Record){ const next=new URLSearchParams(params) for(const[key,value]of Object.entries(values)){if(value===null||value==="")next.delete(key);else next.set(key,value)} return "/network-map"+(next.size?"?"+next.toString():"") }