@klauswuestefeld/jux-web 2026.1.24 → 2026.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/captcha/turnstyle.d.ts +11 -0
- package/dist/jux/language.d.ts +1 -1
- package/dist/jux-web.js +129 -15
- package/dist/local-storage/utils.d.ts +1 -1
- package/dist/login/session.d.ts +1 -2
- package/dist/main.d.ts +1 -0
- package/dist/main.esm.js +127 -13
- package/dist/main.js +129 -15
- package/package.json +1 -1
package/dist/jux/language.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare
|
|
1
|
+
export declare let chosenLanguage: any;
|
|
2
2
|
export declare const reloadWithLanguageOverride: (lang: string) => void;
|
|
3
3
|
export declare const getTranslation: (k: string) => string;
|
|
4
4
|
export declare const initLanguage: (translations_: any, defaultLanguage?: string) => void;
|
package/dist/jux-web.js
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
var juxWeb = (function (exports) {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
let
|
|
5
|
-
const
|
|
6
|
-
|
|
4
|
+
let prefix;
|
|
5
|
+
const setLocalStoragePrefix = (s) => {
|
|
6
|
+
if (prefix !== undefined) {
|
|
7
|
+
throw 'prefix was already set to ' + prefix;
|
|
8
|
+
}
|
|
9
|
+
if (!s) {
|
|
10
|
+
throw 'prefix argument is ' + s + ', use empty string if you want no prefix.';
|
|
11
|
+
}
|
|
12
|
+
prefix = s;
|
|
13
|
+
};
|
|
14
|
+
const getLocalStorageKey = (k) => {
|
|
15
|
+
if (prefix === undefined)
|
|
16
|
+
setLocalStoragePrefix('');
|
|
17
|
+
return prefix.length === 0 ? k : `${prefix}_${k}`;
|
|
18
|
+
};
|
|
19
|
+
// TODO: export this to the frontEnd and use it.
|
|
7
20
|
const getLocalStorageItem = (k) => localStorage.getItem(getLocalStorageKey(k));
|
|
8
21
|
const setLocalStorageItem = (k, v) => localStorage.setItem(getLocalStorageKey(k), v);
|
|
9
22
|
const removeLocalStorageItem = (k) => localStorage.removeItem(getLocalStorageKey(k));
|
|
@@ -16,7 +29,7 @@ var juxWeb = (function (exports) {
|
|
|
16
29
|
};
|
|
17
30
|
const OVERRIDE_KEY = 'jux.language.override';
|
|
18
31
|
let translations = {};
|
|
19
|
-
|
|
32
|
+
exports.chosenLanguage = getBrowserLanguage();
|
|
20
33
|
const reloadWithLanguageOverride = (lang) => {
|
|
21
34
|
setLocalStorageItem(OVERRIDE_KEY, lang);
|
|
22
35
|
location.reload();
|
|
@@ -24,9 +37,10 @@ var juxWeb = (function (exports) {
|
|
|
24
37
|
// @ts-ignore
|
|
25
38
|
const getTranslation = (k) => translations[k] || k;
|
|
26
39
|
const initLanguage = (translations_, defaultLanguage = 'en') => {
|
|
27
|
-
|
|
40
|
+
exports.chosenLanguage = getLocalStorageItem(OVERRIDE_KEY) || getBrowserLanguage();
|
|
41
|
+
translations = translations_[exports.chosenLanguage] || translations_[defaultLanguage];
|
|
28
42
|
document.title = getTranslation('title');
|
|
29
|
-
document.documentElement.lang = translations_[chosenLanguage] ? chosenLanguage : defaultLanguage;
|
|
43
|
+
document.documentElement.lang = translations_[exports.chosenLanguage] ? exports.chosenLanguage : defaultLanguage;
|
|
30
44
|
};
|
|
31
45
|
|
|
32
46
|
const THRESHOLD_WIDTH = 640;
|
|
@@ -443,6 +457,97 @@ var juxWeb = (function (exports) {
|
|
|
443
457
|
return token;
|
|
444
458
|
};
|
|
445
459
|
|
|
460
|
+
const createDisableBackground = () => {
|
|
461
|
+
const disableBackground = document.createElement('disable-background');
|
|
462
|
+
document.body.appendChild(disableBackground);
|
|
463
|
+
return disableBackground;
|
|
464
|
+
};
|
|
465
|
+
const reenableBela = (disableBackground) => {
|
|
466
|
+
disableBackground.remove();
|
|
467
|
+
};
|
|
468
|
+
const ensureTurnstileScript = () => new Promise((resolve, reject) => {
|
|
469
|
+
const existing = document.querySelector('script[data-turnstile-script]');
|
|
470
|
+
const onReady = () => (typeof window.turnstile !== 'undefined') ? resolve() : reject(new Error('Turnstile not available'));
|
|
471
|
+
if (existing) {
|
|
472
|
+
if (typeof window.turnstile !== 'undefined')
|
|
473
|
+
return resolve();
|
|
474
|
+
existing.addEventListener('load', onReady, { once: true });
|
|
475
|
+
existing.addEventListener('error', () => reject(new Error('Failed to load Turnstile')), { once: true });
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
const script = document.createElement('script');
|
|
479
|
+
script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';
|
|
480
|
+
script.async = true;
|
|
481
|
+
script.defer = true;
|
|
482
|
+
script.dataset.turnstileScript = 'true';
|
|
483
|
+
script.addEventListener('load', onReady, { once: true });
|
|
484
|
+
script.addEventListener('error', () => reject(new Error('Failed to load Turnstile')), { once: true });
|
|
485
|
+
document.head.appendChild(script);
|
|
486
|
+
setTimeout(() => reject(new Error('Turnstile load timeout')), 15000);
|
|
487
|
+
});
|
|
488
|
+
let challengeInFlight = null;
|
|
489
|
+
const captchaChallenge = () => {
|
|
490
|
+
console.log('challange');
|
|
491
|
+
if (challengeInFlight)
|
|
492
|
+
return challengeInFlight;
|
|
493
|
+
challengeInFlight = new Promise((resolve, reject) => __awaiter$2(void 0, void 0, void 0, function* () {
|
|
494
|
+
const disableBackground = createDisableBackground();
|
|
495
|
+
let overlay = null;
|
|
496
|
+
const cleanup = () => {
|
|
497
|
+
try {
|
|
498
|
+
overlay === null || overlay === void 0 ? void 0 : overlay.remove();
|
|
499
|
+
}
|
|
500
|
+
catch (_a) { }
|
|
501
|
+
try {
|
|
502
|
+
reenableBela(disableBackground);
|
|
503
|
+
}
|
|
504
|
+
catch (_b) { }
|
|
505
|
+
challengeInFlight = null;
|
|
506
|
+
};
|
|
507
|
+
try {
|
|
508
|
+
yield ensureTurnstileScript();
|
|
509
|
+
overlay = document.createElement('captcha-overlay');
|
|
510
|
+
const container = document.createElement('turnstile-container');
|
|
511
|
+
container.id = 'cf-turnstile-container';
|
|
512
|
+
overlay.appendChild(container);
|
|
513
|
+
document.body.appendChild(overlay);
|
|
514
|
+
overlay.style.zIndex = '100';
|
|
515
|
+
overlay.style.width = '100%';
|
|
516
|
+
overlay.style.display = 'flex';
|
|
517
|
+
overlay.style.alignItems = 'center';
|
|
518
|
+
overlay.style.justifyContent = 'center';
|
|
519
|
+
window.turnstile.render(container, {
|
|
520
|
+
sitekey: '0x4AAAAAAB1GW9W6TaEdd7vi',
|
|
521
|
+
callback: (token) => {
|
|
522
|
+
console.log("turnstile token", token);
|
|
523
|
+
backendGet('validate-turnstile', { 'turnstile-token': token }, (res) => {
|
|
524
|
+
console.log(res);
|
|
525
|
+
const sessionToken = res === null || res === void 0 ? void 0 : res['session-token'];
|
|
526
|
+
if (sessionToken) {
|
|
527
|
+
try {
|
|
528
|
+
localStorage.setItem('session-token', String(sessionToken));
|
|
529
|
+
}
|
|
530
|
+
catch (_a) { }
|
|
531
|
+
}
|
|
532
|
+
cleanup();
|
|
533
|
+
resolve(token);
|
|
534
|
+
}, (err) => {
|
|
535
|
+
cleanup();
|
|
536
|
+
reject(err);
|
|
537
|
+
});
|
|
538
|
+
console.log("backendGet called");
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
catch (e) {
|
|
543
|
+
cleanup();
|
|
544
|
+
reject(e);
|
|
545
|
+
console.error("backendGet threw", e);
|
|
546
|
+
}
|
|
547
|
+
}));
|
|
548
|
+
return challengeInFlight;
|
|
549
|
+
};
|
|
550
|
+
|
|
446
551
|
const setBackendUrl = (backendUrl) => setLocalStorageItem('backend-url', backendUrl);
|
|
447
552
|
//@ts-ignore
|
|
448
553
|
const getBackendUrl = () => process.env.BACKEND_URL || getLocalStorageItem('backend-url');
|
|
@@ -549,7 +654,7 @@ var juxWeb = (function (exports) {
|
|
|
549
654
|
}
|
|
550
655
|
};
|
|
551
656
|
const backendRequest = (url_2, ...args_2) => __awaiter$2(void 0, [url_2, ...args_2], void 0, function* (url, options = {}, onSuccess, onError, onRedirect, requestType = 'query', handleUnauthorized = defaultHandleUnauthorized, retrial = false, retrialNum = 0, extras) {
|
|
552
|
-
var _a;
|
|
657
|
+
var _a, _b;
|
|
553
658
|
if (requestRunning && !retrial) { // only allow one request at a time
|
|
554
659
|
setTimeout(() => backendRequest(url, options, onSuccess, onError, onRedirect, requestType, handleUnauthorized, false, retrialNum), 300);
|
|
555
660
|
return;
|
|
@@ -630,6 +735,17 @@ var juxWeb = (function (exports) {
|
|
|
630
735
|
handleUnauthorized(response);
|
|
631
736
|
return;
|
|
632
737
|
}
|
|
738
|
+
if (response.status === 429) {
|
|
739
|
+
try {
|
|
740
|
+
const token = yield captchaChallenge(); // shows overlay, disables background, validates, cleans up
|
|
741
|
+
return backendRequest(url, Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, options.headers), { 'cf-turnstile-token': token, 'cf-session-token': (_b = localStorage.getItem('session-token')) !== null && _b !== void 0 ? _b : '' }) }), onSuccess, onError, onRedirect, requestType, handleUnauthorized, true, retrialNum, extras);
|
|
742
|
+
}
|
|
743
|
+
catch (e) {
|
|
744
|
+
onError === null || onError === void 0 ? void 0 : onError({ error: 'Captcha challenge failed', detail: e });
|
|
745
|
+
requestRunning = false;
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
633
749
|
try {
|
|
634
750
|
let jsonResponse = {};
|
|
635
751
|
try {
|
|
@@ -1063,7 +1179,7 @@ var juxWeb = (function (exports) {
|
|
|
1063
1179
|
btnsContainer.appendChild(loginButton('EMAIL-PASSWORD', () => appendLoginTypes(loginPage, btnsContainer, clientApp, onUserLogin, onLoginError, upperLoginTypes, backgroundImg, explanation, handleSSOLogin, handlers)));
|
|
1064
1180
|
}
|
|
1065
1181
|
if (upperLoginTypes.includes('ANONYMOUS')) {
|
|
1066
|
-
btnsContainer.appendChild(loginButton('guest', () => onUserLogin('
|
|
1182
|
+
btnsContainer.appendChild(loginButton('guest', () => onUserLogin('anonymous')));
|
|
1067
1183
|
}
|
|
1068
1184
|
};
|
|
1069
1185
|
const loginPage = (clientApp, backgroundImg, onUserLogin, onLoginError, loginTypes, handleSSOLogin, handlers) => {
|
|
@@ -14825,7 +14941,7 @@ var juxWeb = (function (exports) {
|
|
|
14825
14941
|
const onError = () => onAuthenticationFailure('login-failed');
|
|
14826
14942
|
getSSOAuthorizationEndpoint(onSuccess, onError);
|
|
14827
14943
|
};
|
|
14828
|
-
const initSession = ({ clientApp, supportedLoginTypes, onUserLogin, onLoginError, backgroundImage, fetchUserBackendUrl, magicLinkRequestEndpoint, magicLinkAuthEndpoint,
|
|
14944
|
+
const initSession = ({ clientApp, supportedLoginTypes, onUserLogin, onLoginError, backgroundImage, fetchUserBackendUrl, magicLinkRequestEndpoint, magicLinkAuthEndpoint, }) => {
|
|
14829
14945
|
// if (startNewDemo()) {
|
|
14830
14946
|
// initDemo(setBackendToken, onAuthentication);
|
|
14831
14947
|
// return;
|
|
@@ -14835,8 +14951,9 @@ var juxWeb = (function (exports) {
|
|
|
14835
14951
|
window.juxWebGlobal.fetchUserBackendUrl = fetchUserBackendUrl;
|
|
14836
14952
|
window.juxWebGlobal.magicLinkRequestEndpoint = magicLinkRequestEndpoint;
|
|
14837
14953
|
window.juxWebGlobal.magicLinkAuthEndpoint = magicLinkAuthEndpoint;
|
|
14838
|
-
|
|
14839
|
-
|
|
14954
|
+
const supportedLoginTypesArray = Array.isArray(supportedLoginTypes)
|
|
14955
|
+
? supportedLoginTypes
|
|
14956
|
+
: [supportedLoginTypes];
|
|
14840
14957
|
const signInToken = extractTokenFromWindowLocation('sign-in') || extractTokenFromWindowLocation('magic-link');
|
|
14841
14958
|
if (signInToken) {
|
|
14842
14959
|
const onOpenMagicLink = () => {
|
|
@@ -14870,9 +14987,6 @@ var juxWeb = (function (exports) {
|
|
|
14870
14987
|
}));
|
|
14871
14988
|
return;
|
|
14872
14989
|
}
|
|
14873
|
-
const supportedLoginTypesArray = Array.isArray(supportedLoginTypes)
|
|
14874
|
-
? supportedLoginTypes
|
|
14875
|
-
: [supportedLoginTypes];
|
|
14876
14990
|
displayPage(clientApp, loginPage(clientApp, backgroundImage, onUserLogin, onLoginError, supportedLoginTypesArray, handleSSOLogin, { onAuthPasswordLogin, onGoogleSignIn, onMicrosoftSignIn, handleMagicLinkRequest }));
|
|
14877
14991
|
// validateThirdPartyCookies(initGapi, () => displayPage(Page.LOGIN));
|
|
14878
14992
|
// checkMixpanel(() => mixpanel.track('View Login Page'));
|
|
@@ -14986,7 +15100,6 @@ var juxWeb = (function (exports) {
|
|
|
14986
15100
|
element.dispatchEvent(new JuxEvent('command', 'POST', endpoint, onResult, params, onError, onRedirect));
|
|
14987
15101
|
};
|
|
14988
15102
|
|
|
14989
|
-
exports.chosenLanguage = chosenLanguage;
|
|
14990
15103
|
exports.clearSession = clearSession;
|
|
14991
15104
|
exports.command = command;
|
|
14992
15105
|
exports.getCurrentUser = getCurrentUser;
|
|
@@ -15003,6 +15116,7 @@ var juxWeb = (function (exports) {
|
|
|
15003
15116
|
exports.reloadWithLanguageOverride = reloadWithLanguageOverride;
|
|
15004
15117
|
exports.requestMagicLink = requestMagicLink;
|
|
15005
15118
|
exports.resetJuxWebGlobal = resetJuxWebGlobal;
|
|
15119
|
+
exports.setLocalStoragePrefix = setLocalStoragePrefix;
|
|
15006
15120
|
exports.upload = upload;
|
|
15007
15121
|
|
|
15008
15122
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const setLocalStoragePrefix: (s: string) => void;
|
|
2
2
|
export declare const getLocalStorageItem: (k: string) => string | null;
|
|
3
3
|
export declare const setLocalStorageItem: (k: string, v: string) => void;
|
|
4
4
|
export declare const removeLocalStorageItem: (k: string) => void;
|
package/dist/login/session.d.ts
CHANGED
|
@@ -7,9 +7,8 @@ interface InitSessionParams {
|
|
|
7
7
|
fetchUserBackendUrl: any;
|
|
8
8
|
magicLinkRequestEndpoint?: string;
|
|
9
9
|
magicLinkAuthEndpoint?: string;
|
|
10
|
-
urlPrefix: string;
|
|
11
10
|
}
|
|
12
|
-
export declare const initSession: ({ clientApp, supportedLoginTypes, onUserLogin, onLoginError, backgroundImage, fetchUserBackendUrl, magicLinkRequestEndpoint, magicLinkAuthEndpoint,
|
|
11
|
+
export declare const initSession: ({ clientApp, supportedLoginTypes, onUserLogin, onLoginError, backgroundImage, fetchUserBackendUrl, magicLinkRequestEndpoint, magicLinkAuthEndpoint, }: InitSessionParams) => void;
|
|
13
12
|
export declare const onMicrosoftSignIn: (onUserLogin: any) => Promise<void>;
|
|
14
13
|
export declare const onGoogleSignIn: (onUserLogin: any) => void;
|
|
15
14
|
export declare const onAuthPasswordLogin: (credentials: any, onUserLogin: any, onLoginError: any, onReturn: any, clientApp: HTMLElement, backgroundImg: string) => void;
|
package/dist/main.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { magicLinkModal } from './login/magic-link-modal';
|
|
|
7
7
|
export { clearSession } from './login/session-actions';
|
|
8
8
|
export { command, query } from './jux/jux-event';
|
|
9
9
|
export { getCurrentUser, resetJuxWebGlobal } from './jux/jux-web-global/utils';
|
|
10
|
+
export { setLocalStoragePrefix } from './local-storage/utils';
|
|
10
11
|
declare global {
|
|
11
12
|
interface Window {
|
|
12
13
|
submitCaptcha: any;
|
package/dist/main.esm.js
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import * as msal from '@azure/msal-browser';
|
|
2
2
|
|
|
3
|
-
let
|
|
4
|
-
const
|
|
5
|
-
|
|
3
|
+
let prefix;
|
|
4
|
+
const setLocalStoragePrefix = (s) => {
|
|
5
|
+
if (prefix !== undefined) {
|
|
6
|
+
throw 'prefix was already set to ' + prefix;
|
|
7
|
+
}
|
|
8
|
+
if (!s) {
|
|
9
|
+
throw 'prefix argument is ' + s + ', use empty string if you want no prefix.';
|
|
10
|
+
}
|
|
11
|
+
prefix = s;
|
|
12
|
+
};
|
|
13
|
+
const getLocalStorageKey = (k) => {
|
|
14
|
+
if (prefix === undefined)
|
|
15
|
+
setLocalStoragePrefix('');
|
|
16
|
+
return prefix.length === 0 ? k : `${prefix}_${k}`;
|
|
17
|
+
};
|
|
18
|
+
// TODO: export this to the frontEnd and use it.
|
|
6
19
|
const getLocalStorageItem = (k) => localStorage.getItem(getLocalStorageKey(k));
|
|
7
20
|
const setLocalStorageItem = (k, v) => localStorage.setItem(getLocalStorageKey(k), v);
|
|
8
21
|
const removeLocalStorageItem = (k) => localStorage.removeItem(getLocalStorageKey(k));
|
|
@@ -15,7 +28,7 @@ const getBrowserLanguage = () => {
|
|
|
15
28
|
};
|
|
16
29
|
const OVERRIDE_KEY = 'jux.language.override';
|
|
17
30
|
let translations = {};
|
|
18
|
-
|
|
31
|
+
let chosenLanguage = getBrowserLanguage();
|
|
19
32
|
const reloadWithLanguageOverride = (lang) => {
|
|
20
33
|
setLocalStorageItem(OVERRIDE_KEY, lang);
|
|
21
34
|
location.reload();
|
|
@@ -23,6 +36,7 @@ const reloadWithLanguageOverride = (lang) => {
|
|
|
23
36
|
// @ts-ignore
|
|
24
37
|
const getTranslation = (k) => translations[k] || k;
|
|
25
38
|
const initLanguage = (translations_, defaultLanguage = 'en') => {
|
|
39
|
+
chosenLanguage = getLocalStorageItem(OVERRIDE_KEY) || getBrowserLanguage();
|
|
26
40
|
translations = translations_[chosenLanguage] || translations_[defaultLanguage];
|
|
27
41
|
document.title = getTranslation('title');
|
|
28
42
|
document.documentElement.lang = translations_[chosenLanguage] ? chosenLanguage : defaultLanguage;
|
|
@@ -442,6 +456,97 @@ const extractTokenFromWindowLocation = (tokenParam, additionalParam = '') => {
|
|
|
442
456
|
return token;
|
|
443
457
|
};
|
|
444
458
|
|
|
459
|
+
const createDisableBackground = () => {
|
|
460
|
+
const disableBackground = document.createElement('disable-background');
|
|
461
|
+
document.body.appendChild(disableBackground);
|
|
462
|
+
return disableBackground;
|
|
463
|
+
};
|
|
464
|
+
const reenableBela = (disableBackground) => {
|
|
465
|
+
disableBackground.remove();
|
|
466
|
+
};
|
|
467
|
+
const ensureTurnstileScript = () => new Promise((resolve, reject) => {
|
|
468
|
+
const existing = document.querySelector('script[data-turnstile-script]');
|
|
469
|
+
const onReady = () => (typeof window.turnstile !== 'undefined') ? resolve() : reject(new Error('Turnstile not available'));
|
|
470
|
+
if (existing) {
|
|
471
|
+
if (typeof window.turnstile !== 'undefined')
|
|
472
|
+
return resolve();
|
|
473
|
+
existing.addEventListener('load', onReady, { once: true });
|
|
474
|
+
existing.addEventListener('error', () => reject(new Error('Failed to load Turnstile')), { once: true });
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
const script = document.createElement('script');
|
|
478
|
+
script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';
|
|
479
|
+
script.async = true;
|
|
480
|
+
script.defer = true;
|
|
481
|
+
script.dataset.turnstileScript = 'true';
|
|
482
|
+
script.addEventListener('load', onReady, { once: true });
|
|
483
|
+
script.addEventListener('error', () => reject(new Error('Failed to load Turnstile')), { once: true });
|
|
484
|
+
document.head.appendChild(script);
|
|
485
|
+
setTimeout(() => reject(new Error('Turnstile load timeout')), 15000);
|
|
486
|
+
});
|
|
487
|
+
let challengeInFlight = null;
|
|
488
|
+
const captchaChallenge = () => {
|
|
489
|
+
console.log('challange');
|
|
490
|
+
if (challengeInFlight)
|
|
491
|
+
return challengeInFlight;
|
|
492
|
+
challengeInFlight = new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
|
|
493
|
+
const disableBackground = createDisableBackground();
|
|
494
|
+
let overlay = null;
|
|
495
|
+
const cleanup = () => {
|
|
496
|
+
try {
|
|
497
|
+
overlay === null || overlay === void 0 ? void 0 : overlay.remove();
|
|
498
|
+
}
|
|
499
|
+
catch (_a) { }
|
|
500
|
+
try {
|
|
501
|
+
reenableBela(disableBackground);
|
|
502
|
+
}
|
|
503
|
+
catch (_b) { }
|
|
504
|
+
challengeInFlight = null;
|
|
505
|
+
};
|
|
506
|
+
try {
|
|
507
|
+
yield ensureTurnstileScript();
|
|
508
|
+
overlay = document.createElement('captcha-overlay');
|
|
509
|
+
const container = document.createElement('turnstile-container');
|
|
510
|
+
container.id = 'cf-turnstile-container';
|
|
511
|
+
overlay.appendChild(container);
|
|
512
|
+
document.body.appendChild(overlay);
|
|
513
|
+
overlay.style.zIndex = '100';
|
|
514
|
+
overlay.style.width = '100%';
|
|
515
|
+
overlay.style.display = 'flex';
|
|
516
|
+
overlay.style.alignItems = 'center';
|
|
517
|
+
overlay.style.justifyContent = 'center';
|
|
518
|
+
window.turnstile.render(container, {
|
|
519
|
+
sitekey: '0x4AAAAAAB1GW9W6TaEdd7vi',
|
|
520
|
+
callback: (token) => {
|
|
521
|
+
console.log("turnstile token", token);
|
|
522
|
+
backendGet('validate-turnstile', { 'turnstile-token': token }, (res) => {
|
|
523
|
+
console.log(res);
|
|
524
|
+
const sessionToken = res === null || res === void 0 ? void 0 : res['session-token'];
|
|
525
|
+
if (sessionToken) {
|
|
526
|
+
try {
|
|
527
|
+
localStorage.setItem('session-token', String(sessionToken));
|
|
528
|
+
}
|
|
529
|
+
catch (_a) { }
|
|
530
|
+
}
|
|
531
|
+
cleanup();
|
|
532
|
+
resolve(token);
|
|
533
|
+
}, (err) => {
|
|
534
|
+
cleanup();
|
|
535
|
+
reject(err);
|
|
536
|
+
});
|
|
537
|
+
console.log("backendGet called");
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
catch (e) {
|
|
542
|
+
cleanup();
|
|
543
|
+
reject(e);
|
|
544
|
+
console.error("backendGet threw", e);
|
|
545
|
+
}
|
|
546
|
+
}));
|
|
547
|
+
return challengeInFlight;
|
|
548
|
+
};
|
|
549
|
+
|
|
445
550
|
const setBackendUrl = (backendUrl) => setLocalStorageItem('backend-url', backendUrl);
|
|
446
551
|
//@ts-ignore
|
|
447
552
|
const getBackendUrl = () => process.env.BACKEND_URL || getLocalStorageItem('backend-url');
|
|
@@ -548,7 +653,7 @@ const uploadRequest = (url, file, onSuccess, onError, extras) => {
|
|
|
548
653
|
}
|
|
549
654
|
};
|
|
550
655
|
const backendRequest = (url_2, ...args_2) => __awaiter(void 0, [url_2, ...args_2], void 0, function* (url, options = {}, onSuccess, onError, onRedirect, requestType = 'query', handleUnauthorized = defaultHandleUnauthorized, retrial = false, retrialNum = 0, extras) {
|
|
551
|
-
var _a;
|
|
656
|
+
var _a, _b;
|
|
552
657
|
if (requestRunning && !retrial) { // only allow one request at a time
|
|
553
658
|
setTimeout(() => backendRequest(url, options, onSuccess, onError, onRedirect, requestType, handleUnauthorized, false, retrialNum), 300);
|
|
554
659
|
return;
|
|
@@ -629,6 +734,17 @@ const backendRequest = (url_2, ...args_2) => __awaiter(void 0, [url_2, ...args_2
|
|
|
629
734
|
handleUnauthorized(response);
|
|
630
735
|
return;
|
|
631
736
|
}
|
|
737
|
+
if (response.status === 429) {
|
|
738
|
+
try {
|
|
739
|
+
const token = yield captchaChallenge(); // shows overlay, disables background, validates, cleans up
|
|
740
|
+
return backendRequest(url, Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, options.headers), { 'cf-turnstile-token': token, 'cf-session-token': (_b = localStorage.getItem('session-token')) !== null && _b !== void 0 ? _b : '' }) }), onSuccess, onError, onRedirect, requestType, handleUnauthorized, true, retrialNum, extras);
|
|
741
|
+
}
|
|
742
|
+
catch (e) {
|
|
743
|
+
onError === null || onError === void 0 ? void 0 : onError({ error: 'Captcha challenge failed', detail: e });
|
|
744
|
+
requestRunning = false;
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
632
748
|
try {
|
|
633
749
|
let jsonResponse = {};
|
|
634
750
|
try {
|
|
@@ -1062,7 +1178,7 @@ const appendLoginTypes = (loginPage, btnsContainer, clientApp, onUserLogin, onLo
|
|
|
1062
1178
|
btnsContainer.appendChild(loginButton('EMAIL-PASSWORD', () => appendLoginTypes(loginPage, btnsContainer, clientApp, onUserLogin, onLoginError, upperLoginTypes, backgroundImg, explanation, handleSSOLogin, handlers)));
|
|
1063
1179
|
}
|
|
1064
1180
|
if (upperLoginTypes.includes('ANONYMOUS')) {
|
|
1065
|
-
btnsContainer.appendChild(loginButton('guest', () => onUserLogin('
|
|
1181
|
+
btnsContainer.appendChild(loginButton('guest', () => onUserLogin('anonymous')));
|
|
1066
1182
|
}
|
|
1067
1183
|
};
|
|
1068
1184
|
const loginPage = (clientApp, backgroundImg, onUserLogin, onLoginError, loginTypes, handleSSOLogin, handlers) => {
|
|
@@ -1505,7 +1621,7 @@ const handleSSOLogin = () => {
|
|
|
1505
1621
|
const onError = () => onAuthenticationFailure('login-failed');
|
|
1506
1622
|
getSSOAuthorizationEndpoint(onSuccess, onError);
|
|
1507
1623
|
};
|
|
1508
|
-
const initSession = ({ clientApp, supportedLoginTypes, onUserLogin, onLoginError, backgroundImage, fetchUserBackendUrl, magicLinkRequestEndpoint, magicLinkAuthEndpoint,
|
|
1624
|
+
const initSession = ({ clientApp, supportedLoginTypes, onUserLogin, onLoginError, backgroundImage, fetchUserBackendUrl, magicLinkRequestEndpoint, magicLinkAuthEndpoint, }) => {
|
|
1509
1625
|
// if (startNewDemo()) {
|
|
1510
1626
|
// initDemo(setBackendToken, onAuthentication);
|
|
1511
1627
|
// return;
|
|
@@ -1515,8 +1631,9 @@ const initSession = ({ clientApp, supportedLoginTypes, onUserLogin, onLoginError
|
|
|
1515
1631
|
window.juxWebGlobal.fetchUserBackendUrl = fetchUserBackendUrl;
|
|
1516
1632
|
window.juxWebGlobal.magicLinkRequestEndpoint = magicLinkRequestEndpoint;
|
|
1517
1633
|
window.juxWebGlobal.magicLinkAuthEndpoint = magicLinkAuthEndpoint;
|
|
1518
|
-
|
|
1519
|
-
|
|
1634
|
+
const supportedLoginTypesArray = Array.isArray(supportedLoginTypes)
|
|
1635
|
+
? supportedLoginTypes
|
|
1636
|
+
: [supportedLoginTypes];
|
|
1520
1637
|
const signInToken = extractTokenFromWindowLocation('sign-in') || extractTokenFromWindowLocation('magic-link');
|
|
1521
1638
|
if (signInToken) {
|
|
1522
1639
|
const onOpenMagicLink = () => {
|
|
@@ -1550,9 +1667,6 @@ const initSession = ({ clientApp, supportedLoginTypes, onUserLogin, onLoginError
|
|
|
1550
1667
|
}));
|
|
1551
1668
|
return;
|
|
1552
1669
|
}
|
|
1553
|
-
const supportedLoginTypesArray = Array.isArray(supportedLoginTypes)
|
|
1554
|
-
? supportedLoginTypes
|
|
1555
|
-
: [supportedLoginTypes];
|
|
1556
1670
|
displayPage(clientApp, loginPage(clientApp, backgroundImage, onUserLogin, onLoginError, supportedLoginTypesArray, handleSSOLogin, { onAuthPasswordLogin, onGoogleSignIn, onMicrosoftSignIn, handleMagicLinkRequest }));
|
|
1557
1671
|
// validateThirdPartyCookies(initGapi, () => displayPage(Page.LOGIN));
|
|
1558
1672
|
// checkMixpanel(() => mixpanel.track('View Login Page'));
|
|
@@ -1666,4 +1780,4 @@ const command = (element, endpoint, onResult, params, onError, onRedirect) => {
|
|
|
1666
1780
|
element.dispatchEvent(new JuxEvent('command', 'POST', endpoint, onResult, params, onError, onRedirect));
|
|
1667
1781
|
};
|
|
1668
1782
|
|
|
1669
|
-
export { chosenLanguage, clearSession, command, getCurrentUser, getTranslation, handleJuxEvent, handleMagicLinkRequest, initLanguage, initSession, loginButton, loginPage, magicLinkModal, onMicrosoftSignIn, query, reloadWithLanguageOverride, requestMagicLink, resetJuxWebGlobal, upload };
|
|
1783
|
+
export { chosenLanguage, clearSession, command, getCurrentUser, getTranslation, handleJuxEvent, handleMagicLinkRequest, initLanguage, initSession, loginButton, loginPage, magicLinkModal, onMicrosoftSignIn, query, reloadWithLanguageOverride, requestMagicLink, resetJuxWebGlobal, setLocalStoragePrefix, upload };
|
package/dist/main.js
CHANGED
|
@@ -24,9 +24,22 @@ function _interopNamespace(e) {
|
|
|
24
24
|
|
|
25
25
|
var msal__namespace = /*#__PURE__*/_interopNamespace(msal);
|
|
26
26
|
|
|
27
|
-
let
|
|
28
|
-
const
|
|
29
|
-
|
|
27
|
+
let prefix;
|
|
28
|
+
const setLocalStoragePrefix = (s) => {
|
|
29
|
+
if (prefix !== undefined) {
|
|
30
|
+
throw 'prefix was already set to ' + prefix;
|
|
31
|
+
}
|
|
32
|
+
if (!s) {
|
|
33
|
+
throw 'prefix argument is ' + s + ', use empty string if you want no prefix.';
|
|
34
|
+
}
|
|
35
|
+
prefix = s;
|
|
36
|
+
};
|
|
37
|
+
const getLocalStorageKey = (k) => {
|
|
38
|
+
if (prefix === undefined)
|
|
39
|
+
setLocalStoragePrefix('');
|
|
40
|
+
return prefix.length === 0 ? k : `${prefix}_${k}`;
|
|
41
|
+
};
|
|
42
|
+
// TODO: export this to the frontEnd and use it.
|
|
30
43
|
const getLocalStorageItem = (k) => localStorage.getItem(getLocalStorageKey(k));
|
|
31
44
|
const setLocalStorageItem = (k, v) => localStorage.setItem(getLocalStorageKey(k), v);
|
|
32
45
|
const removeLocalStorageItem = (k) => localStorage.removeItem(getLocalStorageKey(k));
|
|
@@ -39,7 +52,7 @@ const getBrowserLanguage = () => {
|
|
|
39
52
|
};
|
|
40
53
|
const OVERRIDE_KEY = 'jux.language.override';
|
|
41
54
|
let translations = {};
|
|
42
|
-
|
|
55
|
+
exports.chosenLanguage = getBrowserLanguage();
|
|
43
56
|
const reloadWithLanguageOverride = (lang) => {
|
|
44
57
|
setLocalStorageItem(OVERRIDE_KEY, lang);
|
|
45
58
|
location.reload();
|
|
@@ -47,9 +60,10 @@ const reloadWithLanguageOverride = (lang) => {
|
|
|
47
60
|
// @ts-ignore
|
|
48
61
|
const getTranslation = (k) => translations[k] || k;
|
|
49
62
|
const initLanguage = (translations_, defaultLanguage = 'en') => {
|
|
50
|
-
|
|
63
|
+
exports.chosenLanguage = getLocalStorageItem(OVERRIDE_KEY) || getBrowserLanguage();
|
|
64
|
+
translations = translations_[exports.chosenLanguage] || translations_[defaultLanguage];
|
|
51
65
|
document.title = getTranslation('title');
|
|
52
|
-
document.documentElement.lang = translations_[chosenLanguage] ? chosenLanguage : defaultLanguage;
|
|
66
|
+
document.documentElement.lang = translations_[exports.chosenLanguage] ? exports.chosenLanguage : defaultLanguage;
|
|
53
67
|
};
|
|
54
68
|
|
|
55
69
|
const THRESHOLD_WIDTH = 640;
|
|
@@ -466,6 +480,97 @@ const extractTokenFromWindowLocation = (tokenParam, additionalParam = '') => {
|
|
|
466
480
|
return token;
|
|
467
481
|
};
|
|
468
482
|
|
|
483
|
+
const createDisableBackground = () => {
|
|
484
|
+
const disableBackground = document.createElement('disable-background');
|
|
485
|
+
document.body.appendChild(disableBackground);
|
|
486
|
+
return disableBackground;
|
|
487
|
+
};
|
|
488
|
+
const reenableBela = (disableBackground) => {
|
|
489
|
+
disableBackground.remove();
|
|
490
|
+
};
|
|
491
|
+
const ensureTurnstileScript = () => new Promise((resolve, reject) => {
|
|
492
|
+
const existing = document.querySelector('script[data-turnstile-script]');
|
|
493
|
+
const onReady = () => (typeof window.turnstile !== 'undefined') ? resolve() : reject(new Error('Turnstile not available'));
|
|
494
|
+
if (existing) {
|
|
495
|
+
if (typeof window.turnstile !== 'undefined')
|
|
496
|
+
return resolve();
|
|
497
|
+
existing.addEventListener('load', onReady, { once: true });
|
|
498
|
+
existing.addEventListener('error', () => reject(new Error('Failed to load Turnstile')), { once: true });
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
const script = document.createElement('script');
|
|
502
|
+
script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';
|
|
503
|
+
script.async = true;
|
|
504
|
+
script.defer = true;
|
|
505
|
+
script.dataset.turnstileScript = 'true';
|
|
506
|
+
script.addEventListener('load', onReady, { once: true });
|
|
507
|
+
script.addEventListener('error', () => reject(new Error('Failed to load Turnstile')), { once: true });
|
|
508
|
+
document.head.appendChild(script);
|
|
509
|
+
setTimeout(() => reject(new Error('Turnstile load timeout')), 15000);
|
|
510
|
+
});
|
|
511
|
+
let challengeInFlight = null;
|
|
512
|
+
const captchaChallenge = () => {
|
|
513
|
+
console.log('challange');
|
|
514
|
+
if (challengeInFlight)
|
|
515
|
+
return challengeInFlight;
|
|
516
|
+
challengeInFlight = new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
|
|
517
|
+
const disableBackground = createDisableBackground();
|
|
518
|
+
let overlay = null;
|
|
519
|
+
const cleanup = () => {
|
|
520
|
+
try {
|
|
521
|
+
overlay === null || overlay === void 0 ? void 0 : overlay.remove();
|
|
522
|
+
}
|
|
523
|
+
catch (_a) { }
|
|
524
|
+
try {
|
|
525
|
+
reenableBela(disableBackground);
|
|
526
|
+
}
|
|
527
|
+
catch (_b) { }
|
|
528
|
+
challengeInFlight = null;
|
|
529
|
+
};
|
|
530
|
+
try {
|
|
531
|
+
yield ensureTurnstileScript();
|
|
532
|
+
overlay = document.createElement('captcha-overlay');
|
|
533
|
+
const container = document.createElement('turnstile-container');
|
|
534
|
+
container.id = 'cf-turnstile-container';
|
|
535
|
+
overlay.appendChild(container);
|
|
536
|
+
document.body.appendChild(overlay);
|
|
537
|
+
overlay.style.zIndex = '100';
|
|
538
|
+
overlay.style.width = '100%';
|
|
539
|
+
overlay.style.display = 'flex';
|
|
540
|
+
overlay.style.alignItems = 'center';
|
|
541
|
+
overlay.style.justifyContent = 'center';
|
|
542
|
+
window.turnstile.render(container, {
|
|
543
|
+
sitekey: '0x4AAAAAAB1GW9W6TaEdd7vi',
|
|
544
|
+
callback: (token) => {
|
|
545
|
+
console.log("turnstile token", token);
|
|
546
|
+
backendGet('validate-turnstile', { 'turnstile-token': token }, (res) => {
|
|
547
|
+
console.log(res);
|
|
548
|
+
const sessionToken = res === null || res === void 0 ? void 0 : res['session-token'];
|
|
549
|
+
if (sessionToken) {
|
|
550
|
+
try {
|
|
551
|
+
localStorage.setItem('session-token', String(sessionToken));
|
|
552
|
+
}
|
|
553
|
+
catch (_a) { }
|
|
554
|
+
}
|
|
555
|
+
cleanup();
|
|
556
|
+
resolve(token);
|
|
557
|
+
}, (err) => {
|
|
558
|
+
cleanup();
|
|
559
|
+
reject(err);
|
|
560
|
+
});
|
|
561
|
+
console.log("backendGet called");
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
catch (e) {
|
|
566
|
+
cleanup();
|
|
567
|
+
reject(e);
|
|
568
|
+
console.error("backendGet threw", e);
|
|
569
|
+
}
|
|
570
|
+
}));
|
|
571
|
+
return challengeInFlight;
|
|
572
|
+
};
|
|
573
|
+
|
|
469
574
|
const setBackendUrl = (backendUrl) => setLocalStorageItem('backend-url', backendUrl);
|
|
470
575
|
//@ts-ignore
|
|
471
576
|
const getBackendUrl = () => process.env.BACKEND_URL || getLocalStorageItem('backend-url');
|
|
@@ -572,7 +677,7 @@ const uploadRequest = (url, file, onSuccess, onError, extras) => {
|
|
|
572
677
|
}
|
|
573
678
|
};
|
|
574
679
|
const backendRequest = (url_2, ...args_2) => __awaiter(void 0, [url_2, ...args_2], void 0, function* (url, options = {}, onSuccess, onError, onRedirect, requestType = 'query', handleUnauthorized = defaultHandleUnauthorized, retrial = false, retrialNum = 0, extras) {
|
|
575
|
-
var _a;
|
|
680
|
+
var _a, _b;
|
|
576
681
|
if (requestRunning && !retrial) { // only allow one request at a time
|
|
577
682
|
setTimeout(() => backendRequest(url, options, onSuccess, onError, onRedirect, requestType, handleUnauthorized, false, retrialNum), 300);
|
|
578
683
|
return;
|
|
@@ -653,6 +758,17 @@ const backendRequest = (url_2, ...args_2) => __awaiter(void 0, [url_2, ...args_2
|
|
|
653
758
|
handleUnauthorized(response);
|
|
654
759
|
return;
|
|
655
760
|
}
|
|
761
|
+
if (response.status === 429) {
|
|
762
|
+
try {
|
|
763
|
+
const token = yield captchaChallenge(); // shows overlay, disables background, validates, cleans up
|
|
764
|
+
return backendRequest(url, Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, options.headers), { 'cf-turnstile-token': token, 'cf-session-token': (_b = localStorage.getItem('session-token')) !== null && _b !== void 0 ? _b : '' }) }), onSuccess, onError, onRedirect, requestType, handleUnauthorized, true, retrialNum, extras);
|
|
765
|
+
}
|
|
766
|
+
catch (e) {
|
|
767
|
+
onError === null || onError === void 0 ? void 0 : onError({ error: 'Captcha challenge failed', detail: e });
|
|
768
|
+
requestRunning = false;
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
656
772
|
try {
|
|
657
773
|
let jsonResponse = {};
|
|
658
774
|
try {
|
|
@@ -1086,7 +1202,7 @@ const appendLoginTypes = (loginPage, btnsContainer, clientApp, onUserLogin, onLo
|
|
|
1086
1202
|
btnsContainer.appendChild(loginButton('EMAIL-PASSWORD', () => appendLoginTypes(loginPage, btnsContainer, clientApp, onUserLogin, onLoginError, upperLoginTypes, backgroundImg, explanation, handleSSOLogin, handlers)));
|
|
1087
1203
|
}
|
|
1088
1204
|
if (upperLoginTypes.includes('ANONYMOUS')) {
|
|
1089
|
-
btnsContainer.appendChild(loginButton('guest', () => onUserLogin('
|
|
1205
|
+
btnsContainer.appendChild(loginButton('guest', () => onUserLogin('anonymous')));
|
|
1090
1206
|
}
|
|
1091
1207
|
};
|
|
1092
1208
|
const loginPage = (clientApp, backgroundImg, onUserLogin, onLoginError, loginTypes, handleSSOLogin, handlers) => {
|
|
@@ -1529,7 +1645,7 @@ const handleSSOLogin = () => {
|
|
|
1529
1645
|
const onError = () => onAuthenticationFailure('login-failed');
|
|
1530
1646
|
getSSOAuthorizationEndpoint(onSuccess, onError);
|
|
1531
1647
|
};
|
|
1532
|
-
const initSession = ({ clientApp, supportedLoginTypes, onUserLogin, onLoginError, backgroundImage, fetchUserBackendUrl, magicLinkRequestEndpoint, magicLinkAuthEndpoint,
|
|
1648
|
+
const initSession = ({ clientApp, supportedLoginTypes, onUserLogin, onLoginError, backgroundImage, fetchUserBackendUrl, magicLinkRequestEndpoint, magicLinkAuthEndpoint, }) => {
|
|
1533
1649
|
// if (startNewDemo()) {
|
|
1534
1650
|
// initDemo(setBackendToken, onAuthentication);
|
|
1535
1651
|
// return;
|
|
@@ -1539,8 +1655,9 @@ const initSession = ({ clientApp, supportedLoginTypes, onUserLogin, onLoginError
|
|
|
1539
1655
|
window.juxWebGlobal.fetchUserBackendUrl = fetchUserBackendUrl;
|
|
1540
1656
|
window.juxWebGlobal.magicLinkRequestEndpoint = magicLinkRequestEndpoint;
|
|
1541
1657
|
window.juxWebGlobal.magicLinkAuthEndpoint = magicLinkAuthEndpoint;
|
|
1542
|
-
|
|
1543
|
-
|
|
1658
|
+
const supportedLoginTypesArray = Array.isArray(supportedLoginTypes)
|
|
1659
|
+
? supportedLoginTypes
|
|
1660
|
+
: [supportedLoginTypes];
|
|
1544
1661
|
const signInToken = extractTokenFromWindowLocation('sign-in') || extractTokenFromWindowLocation('magic-link');
|
|
1545
1662
|
if (signInToken) {
|
|
1546
1663
|
const onOpenMagicLink = () => {
|
|
@@ -1574,9 +1691,6 @@ const initSession = ({ clientApp, supportedLoginTypes, onUserLogin, onLoginError
|
|
|
1574
1691
|
}));
|
|
1575
1692
|
return;
|
|
1576
1693
|
}
|
|
1577
|
-
const supportedLoginTypesArray = Array.isArray(supportedLoginTypes)
|
|
1578
|
-
? supportedLoginTypes
|
|
1579
|
-
: [supportedLoginTypes];
|
|
1580
1694
|
displayPage(clientApp, loginPage(clientApp, backgroundImage, onUserLogin, onLoginError, supportedLoginTypesArray, handleSSOLogin, { onAuthPasswordLogin, onGoogleSignIn, onMicrosoftSignIn, handleMagicLinkRequest }));
|
|
1581
1695
|
// validateThirdPartyCookies(initGapi, () => displayPage(Page.LOGIN));
|
|
1582
1696
|
// checkMixpanel(() => mixpanel.track('View Login Page'));
|
|
@@ -1690,7 +1804,6 @@ const command = (element, endpoint, onResult, params, onError, onRedirect) => {
|
|
|
1690
1804
|
element.dispatchEvent(new JuxEvent('command', 'POST', endpoint, onResult, params, onError, onRedirect));
|
|
1691
1805
|
};
|
|
1692
1806
|
|
|
1693
|
-
exports.chosenLanguage = chosenLanguage;
|
|
1694
1807
|
exports.clearSession = clearSession;
|
|
1695
1808
|
exports.command = command;
|
|
1696
1809
|
exports.getCurrentUser = getCurrentUser;
|
|
@@ -1707,4 +1820,5 @@ exports.query = query;
|
|
|
1707
1820
|
exports.reloadWithLanguageOverride = reloadWithLanguageOverride;
|
|
1708
1821
|
exports.requestMagicLink = requestMagicLink;
|
|
1709
1822
|
exports.resetJuxWebGlobal = resetJuxWebGlobal;
|
|
1823
|
+
exports.setLocalStoragePrefix = setLocalStoragePrefix;
|
|
1710
1824
|
exports.upload = upload;
|