1import { CreateURLOptions, ParsedURL } from './Linking.types'; 2 3export function createURL(path: string, { queryParams = {} }: CreateURLOptions = {}): string { 4 if (typeof window === 'undefined') return ''; 5 const url = new URL(path, window.location.origin); 6 Object.entries(queryParams).forEach(([key, value]) => { 7 if (typeof value === 'string') { 8 url.searchParams.set(key, encodeURIComponent(value)); 9 } else if (value != null) { 10 // @ts-expect-error 11 url.searchParams.set(key, value); 12 } 13 }); 14 return url.toString().replace(/\/$/, ''); 15} 16 17export function parse(url: string): ParsedURL { 18 let parsed: URL; 19 try { 20 parsed = new URL(url); 21 } catch { 22 if (typeof window === 'undefined') { 23 return { 24 hostname: null, 25 path: url, 26 queryParams: {}, 27 scheme: null, 28 }; 29 } 30 return { 31 hostname: 'localhost', 32 path: url, 33 queryParams: {}, 34 scheme: 'http', 35 }; 36 } 37 const queryParams: Record<string, string> = {}; 38 parsed.searchParams.forEach((value, key) => { 39 queryParams[key] = decodeURIComponent(value); 40 }); 41 return { 42 hostname: parsed.hostname || null, 43 // TODO: We should probably update native to follow the default URL behavior closer. 44 path: 45 !parsed.hostname && !parsed.pathname 46 ? null 47 : parsed.pathname === '' 48 ? null 49 : parsed.pathname.replace(/^\//, ''), 50 queryParams, 51 scheme: parsed.protocol.replace(/:$/, ''), 52 }; 53} 54