1 | import {ExtendedWindow} from '@shopify/useful-types';
|
2 |
|
3 | const cache = new Map<string, Promise<any>>();
|
4 |
|
5 | export default function load<
|
6 | Imported = any,
|
7 | CustomWindow extends Window = Window
|
8 | >(
|
9 | source: string,
|
10 | getImport: (window: CustomWindow) => Imported,
|
11 | nonce: string,
|
12 | ): Promise<Imported> {
|
13 | if (typeof window === 'undefined') {
|
14 | return Promise.reject(
|
15 | new Error('You can’t import a remote module from the server'),
|
16 | );
|
17 | }
|
18 |
|
19 | const cachedModule = cache.get(source);
|
20 |
|
21 | if (cachedModule != null) {
|
22 | return cachedModule;
|
23 | }
|
24 |
|
25 | const scriptTag = scriptTagFor(source, nonce);
|
26 | appendScriptTag(scriptTag);
|
27 |
|
28 | const promise = new Promise<Imported>((resolve, reject) => {
|
29 | function scriptTagOnLoad() {
|
30 | scriptTag.removeEventListener('load', scriptTagOnLoad);
|
31 | scriptTag.removeEventListener('error', scriptTagOnError);
|
32 | resolve(getImport(window as ExtendedWindow<CustomWindow>));
|
33 | }
|
34 |
|
35 | function scriptTagOnError() {
|
36 | scriptTag.removeEventListener('load', scriptTagOnLoad);
|
37 | scriptTag.removeEventListener('error', scriptTagOnError);
|
38 | reject(new Error('Script tag failed to load remote source'));
|
39 | }
|
40 |
|
41 | scriptTag.addEventListener('load', scriptTagOnLoad);
|
42 | scriptTag.addEventListener('error', scriptTagOnError);
|
43 | });
|
44 |
|
45 | cache.set(source, promise);
|
46 | return promise;
|
47 | }
|
48 |
|
49 | export function clearCache() {
|
50 | cache.clear();
|
51 | }
|
52 |
|
53 | function scriptTagFor(source: string, nonce: string) {
|
54 | const node = document.createElement('script');
|
55 | node.setAttribute('type', 'text/javascript');
|
56 | node.setAttribute('src', source);
|
57 |
|
58 | if (nonce.length > 0) {
|
59 | node.setAttribute('nonce', nonce);
|
60 | }
|
61 |
|
62 | return node;
|
63 | }
|
64 |
|
65 | function appendScriptTag(scriptTag: HTMLScriptElement) {
|
66 | document.head.appendChild(scriptTag);
|
67 | }
|
68 |
|
\ | No newline at end of file |