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