@thor-commerce/app-bridge-react 0.7.3 → 0.9.0
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/README.md +48 -0
- package/dist/browser.cjs +1034 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.d.cts +16 -0
- package/dist/browser.d.ts +16 -0
- package/dist/browser.js +37 -0
- package/dist/browser.js.map +1 -0
- package/dist/{chunk-FGZGTJQS.js → chunk-GEBMO3KT.js} +359 -241
- package/dist/chunk-GEBMO3KT.js.map +1 -0
- package/dist/chunk-ORDG3T77.js +82 -0
- package/dist/chunk-ORDG3T77.js.map +1 -0
- package/dist/index.cjs +429 -228
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -128
- package/dist/index.d.ts +4 -128
- package/dist/index.js +14 -4
- package/dist/next.cjs +415 -227
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +1 -0
- package/dist/next.d.ts +1 -0
- package/dist/next.js +4 -2
- package/dist/next.js.map +1 -1
- package/dist/react-router.cjs +415 -227
- package/dist/react-router.cjs.map +1 -1
- package/dist/react-router.d.cts +1 -0
- package/dist/react-router.d.ts +1 -0
- package/dist/react-router.js +4 -2
- package/dist/react-router.js.map +1 -1
- package/dist/runtime-BsE3hxuZ.d.cts +163 -0
- package/dist/runtime-BsE3hxuZ.d.ts +163 -0
- package/dist/thor-app-bridge.js +2 -0
- package/dist/thor-app-bridge.js.map +1 -0
- package/package.json +9 -1
- package/dist/chunk-FGZGTJQS.js.map +0 -1
|
@@ -499,251 +499,217 @@ function createAppBridge(options = {}) {
|
|
|
499
499
|
return new AppBridge(options);
|
|
500
500
|
}
|
|
501
501
|
|
|
502
|
-
// src/
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
[navigationItems]
|
|
534
|
-
);
|
|
535
|
-
const sessionTokenCacheRef = useRef(null);
|
|
536
|
-
const projectRef = useRef(readInitialProject(selfWindow));
|
|
537
|
-
const pendingSessionTokenRef = useRef(null);
|
|
538
|
-
useEffect(() => {
|
|
539
|
-
onNavigateRef.current = onNavigate;
|
|
540
|
-
}, [onNavigate]);
|
|
541
|
-
useEffect(() => {
|
|
542
|
-
if (typeof window === "undefined" && !selfWindow) {
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
545
|
-
const resolvedTargetOrigin = targetOrigin ?? getReferrerOrigin(selfWindow);
|
|
546
|
-
const resolvedAllowedOrigins = resolvedTargetOrigin ? [resolvedTargetOrigin] : void 0;
|
|
547
|
-
const nextBridge = createAppBridge({
|
|
548
|
-
allowedOrigins: resolvedAllowedOrigins,
|
|
549
|
-
clientId,
|
|
550
|
-
namespace,
|
|
551
|
-
requestTimeoutMs,
|
|
552
|
-
selfWindow,
|
|
502
|
+
// src/runtime.ts
|
|
503
|
+
var GLOBAL_RUNTIME_KEY = "__thorEmbeddedAppRuntime__";
|
|
504
|
+
var THOR_NAVIGATE_EVENT = "thor:navigate";
|
|
505
|
+
var EmbeddedAppRuntime = class {
|
|
506
|
+
constructor(config) {
|
|
507
|
+
this.currentPath = null;
|
|
508
|
+
this.navigationItems = [];
|
|
509
|
+
this.navigationEventType = "navigation:go";
|
|
510
|
+
this.navigationUpdateEventType = "navigation:update";
|
|
511
|
+
this.readyEventType = "app:ready";
|
|
512
|
+
this.hasSentReady = false;
|
|
513
|
+
this.lastSentNavigationItemsKey = null;
|
|
514
|
+
this.lastReportedPath = null;
|
|
515
|
+
this.pendingHostNavigationPath = null;
|
|
516
|
+
this.sessionTokenCache = null;
|
|
517
|
+
this.pendingSessionToken = null;
|
|
518
|
+
const resolvedWindow = config.selfWindow ?? (typeof window !== "undefined" ? window : void 0);
|
|
519
|
+
if (!resolvedWindow) {
|
|
520
|
+
throw new Error("EmbeddedAppRuntime requires a browser window.");
|
|
521
|
+
}
|
|
522
|
+
this.selfWindow = resolvedWindow;
|
|
523
|
+
this.targetOrigin = config.targetOrigin ?? getReferrerOrigin(resolvedWindow);
|
|
524
|
+
this.clientId = config.clientId;
|
|
525
|
+
this.currentPath = readCurrentPath(resolvedWindow);
|
|
526
|
+
this.project = readInitialProject(resolvedWindow);
|
|
527
|
+
this.readyPayload = config.readyPayload ?? { clientId: config.clientId };
|
|
528
|
+
this.bridge = createAppBridge({
|
|
529
|
+
allowedOrigins: this.targetOrigin ? [this.targetOrigin] : void 0,
|
|
530
|
+
namespace: config.namespace,
|
|
531
|
+
requestTimeoutMs: config.requestTimeoutMs,
|
|
532
|
+
selfWindow: resolvedWindow,
|
|
553
533
|
source: "embedded-app",
|
|
554
534
|
target: "dashboard",
|
|
555
|
-
targetOrigin:
|
|
556
|
-
targetWindow
|
|
557
|
-
});
|
|
558
|
-
setBridge(nextBridge);
|
|
559
|
-
return () => {
|
|
560
|
-
setBridge((currentBridge) => currentBridge === nextBridge ? null : currentBridge);
|
|
561
|
-
nextBridge.destroy();
|
|
562
|
-
};
|
|
563
|
-
}, [
|
|
564
|
-
clientId,
|
|
565
|
-
namespace,
|
|
566
|
-
requestTimeoutMs,
|
|
567
|
-
selfWindow,
|
|
568
|
-
targetOrigin,
|
|
569
|
-
targetWindow
|
|
570
|
-
]);
|
|
571
|
-
useEffect(() => {
|
|
572
|
-
if (!bridge || !bridge.hasTargetWindow()) {
|
|
573
|
-
return;
|
|
574
|
-
}
|
|
575
|
-
bridge.send(
|
|
576
|
-
readyEventType,
|
|
577
|
-
readyPayload ?? {
|
|
578
|
-
clientId
|
|
579
|
-
}
|
|
580
|
-
);
|
|
581
|
-
}, [bridge, clientId, readyEventType, readyPayload]);
|
|
582
|
-
useEffect(() => {
|
|
583
|
-
if (!bridge || !bridge.hasTargetWindow()) {
|
|
584
|
-
return;
|
|
585
|
-
}
|
|
586
|
-
bridge.send("navigation:items:update", {
|
|
587
|
-
items: normalizedNavigationItems
|
|
535
|
+
targetOrigin: this.targetOrigin,
|
|
536
|
+
targetWindow: config.targetWindow
|
|
588
537
|
});
|
|
589
|
-
|
|
590
|
-
useEffect(() => {
|
|
591
|
-
if (!bridge || !bridge.hasTargetWindow() || !currentPath) {
|
|
592
|
-
return;
|
|
593
|
-
}
|
|
594
|
-
bridge.send(navigationUpdateEventType, buildNavigationUpdatePayload(currentPath));
|
|
595
|
-
}, [bridge, currentPath, navigationUpdateEventType]);
|
|
596
|
-
useEffect(() => {
|
|
597
|
-
if (!bridge || !onNavigate) {
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
return bridge.on(navigationEventType, (message) => {
|
|
538
|
+
this.removeNavigationRequestHandler = this.bridge.on(this.navigationEventType, (message) => {
|
|
601
539
|
const destination = resolveNavigationDestination(message.payload);
|
|
602
540
|
if (!destination) {
|
|
603
541
|
return;
|
|
604
542
|
}
|
|
543
|
+
this.pendingHostNavigationPath = sanitizeEmbeddedAppPath(destination) ?? destination;
|
|
605
544
|
const nextPath = preserveEmbeddedAppLaunchParams(
|
|
606
545
|
destination,
|
|
607
|
-
|
|
546
|
+
this.selfWindow.location.href
|
|
608
547
|
);
|
|
609
|
-
|
|
548
|
+
this.navigate(nextPath ?? destination, message);
|
|
610
549
|
});
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
const nextPath = preserveEmbeddedAppLaunchParams(
|
|
622
|
-
sanitizedPath,
|
|
623
|
-
window.location.href
|
|
624
|
-
);
|
|
625
|
-
onNavigateRef.current?.(nextPath ?? sanitizedPath);
|
|
626
|
-
};
|
|
627
|
-
const handleDocumentClick = (event) => {
|
|
628
|
-
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) {
|
|
629
|
-
return;
|
|
630
|
-
}
|
|
631
|
-
const target = event.target;
|
|
632
|
-
if (!(target instanceof Element)) {
|
|
633
|
-
return;
|
|
634
|
-
}
|
|
635
|
-
const anchor = target.closest("a[href]");
|
|
636
|
-
if (!(anchor instanceof HTMLAnchorElement)) {
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
639
|
-
if (anchor.hasAttribute("download")) {
|
|
640
|
-
return;
|
|
550
|
+
this.removeNavigationInterceptors = installNavigationInterceptors({
|
|
551
|
+
bridge: this.bridge,
|
|
552
|
+
selfWindow: this.selfWindow,
|
|
553
|
+
navigate: (path) => this.navigate(path)
|
|
554
|
+
});
|
|
555
|
+
this.removeHistoryObserver = installHistoryObserver({
|
|
556
|
+
selfWindow: this.selfWindow,
|
|
557
|
+
onChange: (path) => {
|
|
558
|
+
this.currentPath = path;
|
|
559
|
+
this.syncBridgeState();
|
|
641
560
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
561
|
+
});
|
|
562
|
+
this.restoreFetch = installFetchInterceptor({
|
|
563
|
+
bridge: this.bridge,
|
|
564
|
+
getClientId: () => this.clientId,
|
|
565
|
+
getProject: () => this.project,
|
|
566
|
+
setProject: (project) => {
|
|
567
|
+
this.project = project;
|
|
568
|
+
},
|
|
569
|
+
readCachedToken: () => this.sessionTokenCache,
|
|
570
|
+
writeCachedToken: (token) => {
|
|
571
|
+
this.sessionTokenCache = token;
|
|
572
|
+
},
|
|
573
|
+
readPendingToken: () => this.pendingSessionToken,
|
|
574
|
+
writePendingToken: (token) => {
|
|
575
|
+
this.pendingSessionToken = token;
|
|
646
576
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
577
|
+
});
|
|
578
|
+
this.update(config);
|
|
579
|
+
}
|
|
580
|
+
update(config) {
|
|
581
|
+
if (config.clientId) {
|
|
582
|
+
this.clientId = config.clientId;
|
|
583
|
+
if (!this.readyPayload || typeof this.readyPayload === "object" && this.readyPayload !== null && "clientId" in this.readyPayload) {
|
|
584
|
+
this.readyPayload = config.readyPayload ?? { clientId: config.clientId };
|
|
651
585
|
}
|
|
652
|
-
|
|
586
|
+
}
|
|
587
|
+
if (config.currentPath !== void 0) {
|
|
588
|
+
this.currentPath = config.currentPath;
|
|
589
|
+
}
|
|
590
|
+
if (config.navigationItems !== void 0) {
|
|
591
|
+
this.navigationItems = normalizeBridgeNavigationItems(config.navigationItems);
|
|
592
|
+
}
|
|
593
|
+
if (config.onNavigate !== void 0) {
|
|
594
|
+
this.onNavigate = config.onNavigate;
|
|
595
|
+
}
|
|
596
|
+
if (config.readyEventType) {
|
|
597
|
+
this.readyEventType = config.readyEventType;
|
|
598
|
+
}
|
|
599
|
+
if (config.readyPayload !== void 0) {
|
|
600
|
+
this.readyPayload = config.readyPayload;
|
|
601
|
+
}
|
|
602
|
+
if (config.targetWindow !== void 0) {
|
|
603
|
+
this.bridge.setTargetWindow(config.targetWindow ?? null);
|
|
604
|
+
}
|
|
605
|
+
this.syncBridgeState();
|
|
606
|
+
}
|
|
607
|
+
clearNavigationHandler() {
|
|
608
|
+
this.onNavigate = void 0;
|
|
609
|
+
}
|
|
610
|
+
destroy() {
|
|
611
|
+
this.removeNavigationRequestHandler?.();
|
|
612
|
+
this.removeNavigationInterceptors();
|
|
613
|
+
this.removeHistoryObserver();
|
|
614
|
+
this.restoreFetch();
|
|
615
|
+
this.bridge.destroy();
|
|
616
|
+
}
|
|
617
|
+
syncBridgeState() {
|
|
618
|
+
if (!this.bridge.hasTargetWindow()) {
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
if (!this.hasSentReady) {
|
|
622
|
+
this.bridge.send(this.readyEventType, this.readyPayload);
|
|
623
|
+
this.hasSentReady = true;
|
|
624
|
+
}
|
|
625
|
+
const navigationItemsKey = JSON.stringify(this.navigationItems);
|
|
626
|
+
if (navigationItemsKey !== this.lastSentNavigationItemsKey) {
|
|
627
|
+
this.bridge.send("navigation:items:update", {
|
|
628
|
+
items: this.navigationItems
|
|
629
|
+
});
|
|
630
|
+
this.lastSentNavigationItemsKey = navigationItemsKey;
|
|
631
|
+
}
|
|
632
|
+
if (this.currentPath) {
|
|
633
|
+
if (this.currentPath === this.pendingHostNavigationPath) {
|
|
634
|
+
this.pendingHostNavigationPath = null;
|
|
635
|
+
this.lastReportedPath = this.currentPath;
|
|
653
636
|
return;
|
|
654
637
|
}
|
|
655
|
-
|
|
656
|
-
if (!nextPath) {
|
|
638
|
+
if (this.currentPath === this.lastReportedPath) {
|
|
657
639
|
return;
|
|
658
640
|
}
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
if (targetName === "_top" || targetName === "_parent") {
|
|
670
|
-
bridge.redirectToRemote(new URL(href, window.location.href).toString());
|
|
671
|
-
return null;
|
|
672
|
-
}
|
|
673
|
-
if (!targetName || targetName === "_self") {
|
|
674
|
-
const nextPath = resolveLocalNavigationPath(href, window.location.origin);
|
|
675
|
-
if (nextPath) {
|
|
676
|
-
handleLocalNavigation(nextPath);
|
|
677
|
-
return window;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
return originalOpen(url, target, features);
|
|
681
|
-
};
|
|
682
|
-
document.addEventListener("click", handleDocumentClick, true);
|
|
683
|
-
return () => {
|
|
684
|
-
document.removeEventListener("click", handleDocumentClick, true);
|
|
685
|
-
window.open = originalOpen;
|
|
686
|
-
};
|
|
687
|
-
}, [bridge, onNavigate]);
|
|
688
|
-
useEffect(() => {
|
|
689
|
-
if (!bridge || typeof window === "undefined") {
|
|
641
|
+
this.bridge.send(
|
|
642
|
+
this.navigationUpdateEventType,
|
|
643
|
+
buildNavigationUpdatePayload(this.currentPath)
|
|
644
|
+
);
|
|
645
|
+
this.lastReportedPath = this.currentPath;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
navigate(path, message) {
|
|
649
|
+
if (this.onNavigate) {
|
|
650
|
+
this.onNavigate(path, message);
|
|
690
651
|
return;
|
|
691
652
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
const sessionToken = await getSessionToken({
|
|
709
|
-
bridge,
|
|
710
|
-
clientId,
|
|
711
|
-
pendingSessionTokenRef,
|
|
712
|
-
projectRef,
|
|
713
|
-
sessionTokenCacheRef
|
|
714
|
-
});
|
|
715
|
-
nextHeaders.set("Authorization", `Bearer ${sessionToken}`);
|
|
716
|
-
} catch {
|
|
717
|
-
if (!projectRef.current) {
|
|
718
|
-
throw new Error("Missing Thor embedded session token");
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
if (!nextHeaders.has("X-Requested-With")) {
|
|
722
|
-
nextHeaders.set("X-Requested-With", "XMLHttpRequest");
|
|
723
|
-
}
|
|
724
|
-
if (input instanceof Request) {
|
|
725
|
-
return originalFetch(
|
|
726
|
-
new Request(input, {
|
|
727
|
-
headers: nextHeaders
|
|
728
|
-
})
|
|
729
|
-
);
|
|
730
|
-
}
|
|
731
|
-
return originalFetch(input, {
|
|
732
|
-
...init,
|
|
733
|
-
headers: nextHeaders
|
|
734
|
-
});
|
|
735
|
-
};
|
|
736
|
-
globalThis.fetch = interceptedFetch;
|
|
737
|
-
window.fetch = interceptedFetch;
|
|
738
|
-
return () => {
|
|
739
|
-
globalThis.fetch = originalFetch;
|
|
740
|
-
window.fetch = originalFetch;
|
|
741
|
-
};
|
|
742
|
-
}, [bridge, clientId]);
|
|
743
|
-
return /* @__PURE__ */ jsx(AppBridgeContext.Provider, { value: bridge, children });
|
|
653
|
+
if (dispatchNavigateEvent(this.selfWindow.document, path)) {
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
this.selfWindow.location.assign(path);
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
function getOrCreateEmbeddedAppRuntime(config) {
|
|
660
|
+
const globalScope = globalThis;
|
|
661
|
+
const existingRuntime = globalScope[GLOBAL_RUNTIME_KEY];
|
|
662
|
+
if (existingRuntime) {
|
|
663
|
+
existingRuntime.update(config);
|
|
664
|
+
return existingRuntime;
|
|
665
|
+
}
|
|
666
|
+
const runtime = new EmbeddedAppRuntime(config);
|
|
667
|
+
globalScope[GLOBAL_RUNTIME_KEY] = runtime;
|
|
668
|
+
return runtime;
|
|
744
669
|
}
|
|
745
|
-
function
|
|
746
|
-
return
|
|
670
|
+
function getEmbeddedAppRuntime() {
|
|
671
|
+
return globalThis[GLOBAL_RUNTIME_KEY] ?? null;
|
|
672
|
+
}
|
|
673
|
+
function dispatchNavigateEvent(document, path) {
|
|
674
|
+
const event = new CustomEvent(THOR_NAVIGATE_EVENT, {
|
|
675
|
+
cancelable: true,
|
|
676
|
+
detail: { path }
|
|
677
|
+
});
|
|
678
|
+
document.dispatchEvent(event);
|
|
679
|
+
return event.defaultPrevented;
|
|
680
|
+
}
|
|
681
|
+
function readCurrentPath(selfWindow) {
|
|
682
|
+
return sanitizeEmbeddedAppPath(
|
|
683
|
+
`${selfWindow.location.pathname}${selfWindow.location.search}${selfWindow.location.hash}`
|
|
684
|
+
) ?? null;
|
|
685
|
+
}
|
|
686
|
+
function installHistoryObserver({
|
|
687
|
+
selfWindow,
|
|
688
|
+
onChange
|
|
689
|
+
}) {
|
|
690
|
+
const history = selfWindow.history;
|
|
691
|
+
const originalPushState = history.pushState;
|
|
692
|
+
const originalReplaceState = history.replaceState;
|
|
693
|
+
const notify = () => {
|
|
694
|
+
onChange(readCurrentPath(selfWindow));
|
|
695
|
+
};
|
|
696
|
+
history.pushState = function(...args) {
|
|
697
|
+
originalPushState.apply(history, args);
|
|
698
|
+
notify();
|
|
699
|
+
};
|
|
700
|
+
history.replaceState = function(...args) {
|
|
701
|
+
originalReplaceState.apply(history, args);
|
|
702
|
+
notify();
|
|
703
|
+
};
|
|
704
|
+
selfWindow.addEventListener("popstate", notify);
|
|
705
|
+
selfWindow.addEventListener("hashchange", notify);
|
|
706
|
+
notify();
|
|
707
|
+
return () => {
|
|
708
|
+
history.pushState = originalPushState;
|
|
709
|
+
history.replaceState = originalReplaceState;
|
|
710
|
+
selfWindow.removeEventListener("popstate", notify);
|
|
711
|
+
selfWindow.removeEventListener("hashchange", notify);
|
|
712
|
+
};
|
|
747
713
|
}
|
|
748
714
|
function getReferrerOrigin(explicitWindow) {
|
|
749
715
|
const resolvedWindow = explicitWindow ?? (typeof window !== "undefined" ? window : void 0);
|
|
@@ -757,40 +723,190 @@ function getReferrerOrigin(explicitWindow) {
|
|
|
757
723
|
return void 0;
|
|
758
724
|
}
|
|
759
725
|
}
|
|
726
|
+
function installNavigationInterceptors({
|
|
727
|
+
bridge,
|
|
728
|
+
selfWindow,
|
|
729
|
+
navigate
|
|
730
|
+
}) {
|
|
731
|
+
const document = selfWindow.document;
|
|
732
|
+
const handleLocalNavigation = (path) => {
|
|
733
|
+
const sanitizedPath = sanitizeEmbeddedAppPath(path);
|
|
734
|
+
if (!sanitizedPath) {
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
const nextPath = preserveEmbeddedAppLaunchParams(
|
|
738
|
+
sanitizedPath,
|
|
739
|
+
selfWindow.location.href
|
|
740
|
+
);
|
|
741
|
+
navigate(nextPath ?? sanitizedPath);
|
|
742
|
+
};
|
|
743
|
+
const handleDocumentClick = (event) => {
|
|
744
|
+
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) {
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
const target = event.target;
|
|
748
|
+
if (!(target instanceof Element)) {
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
const anchor = target.closest("a[href]");
|
|
752
|
+
if (!(anchor instanceof HTMLAnchorElement)) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
if (anchor.hasAttribute("download")) {
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
const targetWindow = anchor.target.toLowerCase();
|
|
759
|
+
const href = anchor.getAttribute("href");
|
|
760
|
+
if (!href) {
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
if (targetWindow === "_top" || targetWindow === "_parent") {
|
|
764
|
+
event.preventDefault();
|
|
765
|
+
bridge.redirectToRemote(anchor.href);
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
if (targetWindow && targetWindow !== "_self") {
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
const nextPath = resolveLocalNavigationPath(href, selfWindow.location.origin);
|
|
772
|
+
if (!nextPath) {
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
event.preventDefault();
|
|
776
|
+
handleLocalNavigation(nextPath);
|
|
777
|
+
};
|
|
778
|
+
const originalOpen = selfWindow.open.bind(selfWindow);
|
|
779
|
+
selfWindow.open = (url, target, features) => {
|
|
780
|
+
if (url == null) {
|
|
781
|
+
return originalOpen(url, target, features);
|
|
782
|
+
}
|
|
783
|
+
const href = typeof url === "string" ? url : url.toString();
|
|
784
|
+
const targetName = (target ?? "").toLowerCase();
|
|
785
|
+
if (targetName === "_top" || targetName === "_parent") {
|
|
786
|
+
bridge.redirectToRemote(new URL(href, selfWindow.location.href).toString());
|
|
787
|
+
return null;
|
|
788
|
+
}
|
|
789
|
+
if (!targetName || targetName === "_self") {
|
|
790
|
+
const nextPath = resolveLocalNavigationPath(
|
|
791
|
+
href,
|
|
792
|
+
selfWindow.location.origin
|
|
793
|
+
);
|
|
794
|
+
if (nextPath) {
|
|
795
|
+
handleLocalNavigation(nextPath);
|
|
796
|
+
return selfWindow;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
return originalOpen(url, target, features);
|
|
800
|
+
};
|
|
801
|
+
document.addEventListener("click", handleDocumentClick, true);
|
|
802
|
+
return () => {
|
|
803
|
+
document.removeEventListener("click", handleDocumentClick, true);
|
|
804
|
+
selfWindow.open = originalOpen;
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
function installFetchInterceptor({
|
|
808
|
+
bridge,
|
|
809
|
+
getClientId,
|
|
810
|
+
getProject,
|
|
811
|
+
setProject,
|
|
812
|
+
readCachedToken,
|
|
813
|
+
writeCachedToken,
|
|
814
|
+
readPendingToken,
|
|
815
|
+
writePendingToken
|
|
816
|
+
}) {
|
|
817
|
+
if (typeof window === "undefined") {
|
|
818
|
+
return () => {
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
const originalFetch = globalThis.fetch.bind(globalThis);
|
|
822
|
+
const interceptedFetch = async (input, init) => {
|
|
823
|
+
if (!shouldAttachSessionToken(input)) {
|
|
824
|
+
return originalFetch(input, init);
|
|
825
|
+
}
|
|
826
|
+
const existingAuthorization = getExistingAuthorization(input, init);
|
|
827
|
+
if (existingAuthorization) {
|
|
828
|
+
return originalFetch(input, init);
|
|
829
|
+
}
|
|
830
|
+
const nextHeaders = new Headers(
|
|
831
|
+
input instanceof Request ? input.headers : init?.headers
|
|
832
|
+
);
|
|
833
|
+
try {
|
|
834
|
+
const sessionToken = await getSessionToken({
|
|
835
|
+
bridge,
|
|
836
|
+
clientId: getClientId(),
|
|
837
|
+
project: getProject,
|
|
838
|
+
setProject,
|
|
839
|
+
readCachedToken,
|
|
840
|
+
writeCachedToken,
|
|
841
|
+
readPendingToken,
|
|
842
|
+
writePendingToken
|
|
843
|
+
});
|
|
844
|
+
nextHeaders.set("Authorization", `Bearer ${sessionToken}`);
|
|
845
|
+
} catch {
|
|
846
|
+
if (!getProject()) {
|
|
847
|
+
throw new Error("Missing Thor embedded session token");
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
if (!nextHeaders.has("X-Requested-With")) {
|
|
851
|
+
nextHeaders.set("X-Requested-With", "XMLHttpRequest");
|
|
852
|
+
}
|
|
853
|
+
if (input instanceof Request) {
|
|
854
|
+
return originalFetch(
|
|
855
|
+
new Request(input, {
|
|
856
|
+
headers: nextHeaders
|
|
857
|
+
})
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
return originalFetch(input, {
|
|
861
|
+
...init,
|
|
862
|
+
headers: nextHeaders
|
|
863
|
+
});
|
|
864
|
+
};
|
|
865
|
+
globalThis.fetch = interceptedFetch;
|
|
866
|
+
window.fetch = interceptedFetch;
|
|
867
|
+
return () => {
|
|
868
|
+
globalThis.fetch = originalFetch;
|
|
869
|
+
window.fetch = originalFetch;
|
|
870
|
+
};
|
|
871
|
+
}
|
|
760
872
|
async function getSessionToken({
|
|
761
873
|
bridge,
|
|
762
874
|
clientId,
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
875
|
+
project,
|
|
876
|
+
setProject,
|
|
877
|
+
readCachedToken,
|
|
878
|
+
writeCachedToken,
|
|
879
|
+
readPendingToken,
|
|
880
|
+
writePendingToken
|
|
766
881
|
}) {
|
|
767
|
-
const cachedToken =
|
|
882
|
+
const cachedToken = readCachedToken();
|
|
768
883
|
if (cachedToken && !isExpired(cachedToken.expiresAt)) {
|
|
769
884
|
return cachedToken.token;
|
|
770
885
|
}
|
|
771
|
-
|
|
772
|
-
|
|
886
|
+
const pendingToken = readPendingToken();
|
|
887
|
+
if (pendingToken) {
|
|
888
|
+
return pendingToken;
|
|
773
889
|
}
|
|
774
|
-
const
|
|
890
|
+
const nextPendingToken = bridge.getSessionToken({ clientId }).then((response) => {
|
|
775
891
|
const token = response.sessionToken ?? response.idToken;
|
|
776
892
|
if (!token) {
|
|
777
893
|
throw new Error("Missing Thor embedded session token");
|
|
778
894
|
}
|
|
779
895
|
if (response.project) {
|
|
780
|
-
|
|
896
|
+
setProject(response.project);
|
|
781
897
|
}
|
|
782
|
-
|
|
898
|
+
writeCachedToken({
|
|
783
899
|
token,
|
|
784
900
|
expiresAt: normalizeTokenExpiry(token, response.exp)
|
|
785
|
-
};
|
|
786
|
-
|
|
901
|
+
});
|
|
902
|
+
writePendingToken(null);
|
|
787
903
|
return token;
|
|
788
904
|
}).catch((error) => {
|
|
789
|
-
|
|
905
|
+
writePendingToken(null);
|
|
790
906
|
throw error;
|
|
791
907
|
});
|
|
792
|
-
|
|
793
|
-
return
|
|
908
|
+
writePendingToken(nextPendingToken);
|
|
909
|
+
return nextPendingToken;
|
|
794
910
|
}
|
|
795
911
|
function shouldAttachSessionToken(input) {
|
|
796
912
|
if (typeof window === "undefined") {
|
|
@@ -869,7 +985,9 @@ export {
|
|
|
869
985
|
isBridgeMessage,
|
|
870
986
|
AppBridge,
|
|
871
987
|
createAppBridge,
|
|
872
|
-
|
|
873
|
-
|
|
988
|
+
THOR_NAVIGATE_EVENT,
|
|
989
|
+
EmbeddedAppRuntime,
|
|
990
|
+
getOrCreateEmbeddedAppRuntime,
|
|
991
|
+
getEmbeddedAppRuntime
|
|
874
992
|
};
|
|
875
|
-
//# sourceMappingURL=chunk-
|
|
993
|
+
//# sourceMappingURL=chunk-GEBMO3KT.js.map
|