forked from clerk/javascript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathloadClerkJsScript.ts
More file actions
95 lines (75 loc) · 2.99 KB
/
Copy pathloadClerkJsScript.ts
File metadata and controls
95 lines (75 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { parsePublishableKey } from '@clerk/shared/keys';
import { loadScript } from '@clerk/shared/loadScript';
import { isValidProxyUrl, proxyUrlToAbsoluteURL } from '@clerk/shared/proxy';
import { addClerkPrefix } from '@clerk/shared/url';
import { errorThrower } from '../errors/errorThrower';
import type { IsomorphicClerkOptions } from '../types';
import { isDevOrStagingUrl } from './isDevOrStageUrl';
import { versionSelector } from './versionSelector';
const FAILED_TO_LOAD_ERROR = 'Clerk: Failed to load Clerk';
type LoadClerkJsScriptOptions = Omit<IsomorphicClerkOptions, 'proxyUrl' | 'domain'> & {
proxyUrl?: string;
domain?: string;
};
const loadClerkJsScript = (opts: LoadClerkJsScriptOptions) => {
const { publishableKey } = opts;
if (!publishableKey) {
errorThrower.throwMissingPublishableKeyError();
}
const existingScript = document.querySelector<HTMLScriptElement>('script[data-clerk-js-script]');
if (existingScript) {
return new Promise((resolve, reject) => {
existingScript.addEventListener('load', () => {
resolve(existingScript);
});
existingScript.addEventListener('error', () => {
reject(FAILED_TO_LOAD_ERROR);
});
});
}
return loadScript(clerkJsScriptUrl(opts), {
async: true,
crossOrigin: 'anonymous',
beforeLoad: applyClerkJsScriptAttributes(opts),
}).catch(() => {
throw new Error(FAILED_TO_LOAD_ERROR);
});
};
const clerkJsScriptUrl = (opts: LoadClerkJsScriptOptions) => {
const { clerkJSUrl, clerkJSVariant, clerkJSVersion, proxyUrl, domain, publishableKey } = opts;
if (clerkJSUrl) {
return clerkJSUrl;
}
let scriptHost = '';
if (!!proxyUrl && isValidProxyUrl(proxyUrl)) {
scriptHost = proxyUrlToAbsoluteURL(proxyUrl).replace(/http(s)?:\/\//, '');
} else if (domain && !isDevOrStagingUrl(parsePublishableKey(publishableKey)?.frontendApi || '')) {
scriptHost = addClerkPrefix(domain);
} else {
scriptHost = parsePublishableKey(publishableKey)?.frontendApi || '';
}
const variant = clerkJSVariant ? `${clerkJSVariant.replace(/\.+$/, '')}.` : '';
const version = versionSelector(clerkJSVersion);
return `https://${scriptHost}/npm/@clerk/clerk-js@${version}/dist/clerk.${variant}browser.js`;
};
const buildClerkJsScriptAttributes = (options: LoadClerkJsScriptOptions) => {
const obj: Record<string, string> = {};
if (options.publishableKey) {
obj['data-clerk-publishable-key'] = options.publishableKey;
}
if (options.proxyUrl) {
obj['data-clerk-proxy-url'] = options.proxyUrl;
}
if (options.domain) {
obj['data-clerk-domain'] = options.domain;
}
return obj;
};
const applyClerkJsScriptAttributes = (options: LoadClerkJsScriptOptions) => (script: HTMLScriptElement) => {
const attributes = buildClerkJsScriptAttributes(options);
for (const attribute in attributes) {
script.setAttribute(attribute, attributes[attribute]);
}
};
export { loadClerkJsScript, buildClerkJsScriptAttributes, clerkJsScriptUrl };
export type { LoadClerkJsScriptOptions };