/ shared / utils / src / url.ts
url.ts
 1  /**
 2   * Remove the scheme and separators from the given URL.
 3   *
 4   * @example
 5   * ```javascript
 6   * removeScheme('https://music.apple.com/browse') // => 'music.apple.com/browse'
 7   * removeScheme('apple-music://music.apple.com/browse') // => 'music.apple.com/browse'
 8   * removeScheme('music.apple.com/browse') // => 'music.apple.com/browse'
 9   * ```
10   */
11  export function removeScheme(
12      url: string | URL | null | undefined,
13  ): string | undefined {
14      if (url === null || url === undefined) {
15          return undefined;
16      }
17  
18      return String(url).replace(/^((?:[^:]*:[/]{0,2})|(?::?\/\/))/i, '');
19  }
20  
21  /**
22   * Strip scheme and host (hostname + port) from a URL, leaving just the path, query
23   * params, and hash.
24   *
25   * @param {string} url The URL possibly containing a host
26   * @returns {string} hostlessUrl The url without its host
27   */
28  export function removeHost(
29      url: string | URL | null | undefined,
30  ): string | undefined {
31      return removeScheme(url)?.replace(/^([^/]*)/i, '');
32  }
33  
34  /**
35   * Strip query params and fragment from a URL.
36   */
37  export function removeQueryParams(
38      url: string | URL | undefined,
39  ): string | undefined {
40      if (url === undefined) {
41          return undefined;
42      }
43  
44      const value = String(url);
45      const splitIndex = value.indexOf('?');
46      return splitIndex >= 0 ? value.slice(0, splitIndex) : value;
47  }
48  
49  export function getBaseUrl(): string {
50      const currentUrl = new URL(window.location.href);
51      return `${currentUrl.protocol}//${currentUrl.host}`;
52  }
53  
54  export function buildUrl(props: {
55      protocol?: string;
56      hostname: string;
57      pathname?: string | string[];
58      queryParams?: string | Record<string, string>;
59      hash?: string;
60  }): URL {
61      const {
62          hostname,
63          pathname = '/',
64          queryParams = {},
65          protocol = 'https',
66          hash = '',
67      } = props;
68  
69      // Base URL with domain
70      const url = new URL(protocol + '://' + removeScheme(hostname));
71  
72      // URL path
73      url.pathname = Array.isArray(pathname)
74          ? '/' + pathname.map(encodeURIComponent).join('/').replace(/[/]+/, '/')
75          : pathname;
76  
77      // URL search (a.k.a. queryParams)
78      if (typeof queryParams === 'string') {
79          url.search = queryParams;
80      } else {
81          for (const [key, value] of Object.entries(queryParams)) {
82              url.searchParams.set(key, value);
83          }
84      }
85  
86      // URL hash
87      url.hash = hash;
88  
89      return url;
90  }