@thor-commerce/app-bridge-react 0.7.3 → 0.8.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 +971 -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-GX5V7AK7.js +82 -0
- package/dist/chunk-GX5V7AK7.js.map +1 -0
- package/dist/{chunk-FGZGTJQS.js → chunk-IRTDLWEQ.js} +300 -245
- package/dist/chunk-IRTDLWEQ.js.map +1 -0
- package/dist/index.cjs +370 -232
- 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 +356 -231
- 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 +356 -231
- 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-mEVvh6Rv.d.cts +158 -0
- package/dist/runtime-mEVvh6Rv.d.ts +158 -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
package/dist/react-router.cjs
CHANGED
|
@@ -530,240 +530,151 @@ function createAppBridge(options = {}) {
|
|
|
530
530
|
return new AppBridge(options);
|
|
531
531
|
}
|
|
532
532
|
|
|
533
|
-
// src/
|
|
534
|
-
var
|
|
535
|
-
var
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
selfWindow,
|
|
549
|
-
targetOrigin,
|
|
550
|
-
targetWindow
|
|
551
|
-
}) {
|
|
552
|
-
const [bridge, setBridge] = (0, import_react.useState)(null);
|
|
553
|
-
const onNavigateRef = (0, import_react.useRef)(onNavigate);
|
|
554
|
-
const normalizedNavigationItems = (0, import_react.useMemo)(
|
|
555
|
-
() => normalizeBridgeNavigationItems(navigationItems),
|
|
556
|
-
[navigationItems]
|
|
557
|
-
);
|
|
558
|
-
const sessionTokenCacheRef = (0, import_react.useRef)(null);
|
|
559
|
-
const projectRef = (0, import_react.useRef)(readInitialProject(selfWindow));
|
|
560
|
-
const pendingSessionTokenRef = (0, import_react.useRef)(null);
|
|
561
|
-
(0, import_react.useEffect)(() => {
|
|
562
|
-
onNavigateRef.current = onNavigate;
|
|
563
|
-
}, [onNavigate]);
|
|
564
|
-
(0, import_react.useEffect)(() => {
|
|
565
|
-
if (typeof window === "undefined" && !selfWindow) {
|
|
566
|
-
return;
|
|
533
|
+
// src/runtime.ts
|
|
534
|
+
var GLOBAL_RUNTIME_KEY = "__thorEmbeddedAppRuntime__";
|
|
535
|
+
var THOR_NAVIGATE_EVENT = "thor:navigate";
|
|
536
|
+
var EmbeddedAppRuntime = class {
|
|
537
|
+
constructor(config) {
|
|
538
|
+
this.currentPath = null;
|
|
539
|
+
this.navigationItems = [];
|
|
540
|
+
this.navigationEventType = "navigation:go";
|
|
541
|
+
this.navigationUpdateEventType = "navigation:update";
|
|
542
|
+
this.readyEventType = "app:ready";
|
|
543
|
+
this.sessionTokenCache = null;
|
|
544
|
+
this.pendingSessionToken = null;
|
|
545
|
+
const resolvedWindow = config.selfWindow ?? (typeof window !== "undefined" ? window : void 0);
|
|
546
|
+
if (!resolvedWindow) {
|
|
547
|
+
throw new Error("EmbeddedAppRuntime requires a browser window.");
|
|
567
548
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
549
|
+
this.selfWindow = resolvedWindow;
|
|
550
|
+
this.targetOrigin = config.targetOrigin ?? getReferrerOrigin(resolvedWindow);
|
|
551
|
+
this.clientId = config.clientId;
|
|
552
|
+
this.project = readInitialProject(resolvedWindow);
|
|
553
|
+
this.readyPayload = config.readyPayload ?? { clientId: config.clientId };
|
|
554
|
+
this.bridge = createAppBridge({
|
|
555
|
+
allowedOrigins: this.targetOrigin ? [this.targetOrigin] : void 0,
|
|
556
|
+
namespace: config.namespace,
|
|
557
|
+
requestTimeoutMs: config.requestTimeoutMs,
|
|
558
|
+
selfWindow: resolvedWindow,
|
|
576
559
|
source: "embedded-app",
|
|
577
560
|
target: "dashboard",
|
|
578
|
-
targetOrigin:
|
|
579
|
-
targetWindow
|
|
561
|
+
targetOrigin: this.targetOrigin,
|
|
562
|
+
targetWindow: config.targetWindow
|
|
580
563
|
});
|
|
581
|
-
|
|
582
|
-
return () => {
|
|
583
|
-
setBridge((currentBridge) => currentBridge === nextBridge ? null : currentBridge);
|
|
584
|
-
nextBridge.destroy();
|
|
585
|
-
};
|
|
586
|
-
}, [
|
|
587
|
-
clientId,
|
|
588
|
-
namespace,
|
|
589
|
-
requestTimeoutMs,
|
|
590
|
-
selfWindow,
|
|
591
|
-
targetOrigin,
|
|
592
|
-
targetWindow
|
|
593
|
-
]);
|
|
594
|
-
(0, import_react.useEffect)(() => {
|
|
595
|
-
if (!bridge || !bridge.hasTargetWindow()) {
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
bridge.send(
|
|
599
|
-
readyEventType,
|
|
600
|
-
readyPayload ?? {
|
|
601
|
-
clientId
|
|
602
|
-
}
|
|
603
|
-
);
|
|
604
|
-
}, [bridge, clientId, readyEventType, readyPayload]);
|
|
605
|
-
(0, import_react.useEffect)(() => {
|
|
606
|
-
if (!bridge || !bridge.hasTargetWindow()) {
|
|
607
|
-
return;
|
|
608
|
-
}
|
|
609
|
-
bridge.send("navigation:items:update", {
|
|
610
|
-
items: normalizedNavigationItems
|
|
611
|
-
});
|
|
612
|
-
}, [bridge, normalizedNavigationItems]);
|
|
613
|
-
(0, import_react.useEffect)(() => {
|
|
614
|
-
if (!bridge || !bridge.hasTargetWindow() || !currentPath) {
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
617
|
-
bridge.send(navigationUpdateEventType, buildNavigationUpdatePayload(currentPath));
|
|
618
|
-
}, [bridge, currentPath, navigationUpdateEventType]);
|
|
619
|
-
(0, import_react.useEffect)(() => {
|
|
620
|
-
if (!bridge || !onNavigate) {
|
|
621
|
-
return;
|
|
622
|
-
}
|
|
623
|
-
return bridge.on(navigationEventType, (message) => {
|
|
564
|
+
this.removeNavigationRequestHandler = this.bridge.on(this.navigationEventType, (message) => {
|
|
624
565
|
const destination = resolveNavigationDestination(message.payload);
|
|
625
566
|
if (!destination) {
|
|
626
567
|
return;
|
|
627
568
|
}
|
|
628
569
|
const nextPath = preserveEmbeddedAppLaunchParams(
|
|
629
570
|
destination,
|
|
630
|
-
|
|
571
|
+
this.selfWindow.location.href
|
|
631
572
|
);
|
|
632
|
-
|
|
573
|
+
this.navigate(nextPath ?? destination, message);
|
|
633
574
|
});
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
)
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
}
|
|
654
|
-
const target = event.target;
|
|
655
|
-
if (!(target instanceof Element)) {
|
|
656
|
-
return;
|
|
657
|
-
}
|
|
658
|
-
const anchor = target.closest("a[href]");
|
|
659
|
-
if (!(anchor instanceof HTMLAnchorElement)) {
|
|
660
|
-
return;
|
|
661
|
-
}
|
|
662
|
-
if (anchor.hasAttribute("download")) {
|
|
663
|
-
return;
|
|
664
|
-
}
|
|
665
|
-
const targetWindow2 = anchor.target.toLowerCase();
|
|
666
|
-
const href = anchor.getAttribute("href");
|
|
667
|
-
if (!href) {
|
|
668
|
-
return;
|
|
669
|
-
}
|
|
670
|
-
if (targetWindow2 === "_top" || targetWindow2 === "_parent") {
|
|
671
|
-
event.preventDefault();
|
|
672
|
-
bridge.redirectToRemote(anchor.href);
|
|
673
|
-
return;
|
|
674
|
-
}
|
|
675
|
-
if (targetWindow2 && targetWindow2 !== "_self") {
|
|
676
|
-
return;
|
|
677
|
-
}
|
|
678
|
-
const nextPath = resolveLocalNavigationPath(href, window.location.origin);
|
|
679
|
-
if (!nextPath) {
|
|
680
|
-
return;
|
|
681
|
-
}
|
|
682
|
-
event.preventDefault();
|
|
683
|
-
handleLocalNavigation(nextPath);
|
|
684
|
-
};
|
|
685
|
-
const originalOpen = window.open.bind(window);
|
|
686
|
-
window.open = (url, target, features) => {
|
|
687
|
-
if (url == null) {
|
|
688
|
-
return originalOpen(url, target, features);
|
|
689
|
-
}
|
|
690
|
-
const href = typeof url === "string" ? url : url.toString();
|
|
691
|
-
const targetName = (target ?? "").toLowerCase();
|
|
692
|
-
if (targetName === "_top" || targetName === "_parent") {
|
|
693
|
-
bridge.redirectToRemote(new URL(href, window.location.href).toString());
|
|
694
|
-
return null;
|
|
575
|
+
this.removeNavigationInterceptors = installNavigationInterceptors({
|
|
576
|
+
bridge: this.bridge,
|
|
577
|
+
selfWindow: this.selfWindow,
|
|
578
|
+
navigate: (path) => this.navigate(path)
|
|
579
|
+
});
|
|
580
|
+
this.restoreFetch = installFetchInterceptor({
|
|
581
|
+
bridge: this.bridge,
|
|
582
|
+
getClientId: () => this.clientId,
|
|
583
|
+
getProject: () => this.project,
|
|
584
|
+
setProject: (project) => {
|
|
585
|
+
this.project = project;
|
|
586
|
+
},
|
|
587
|
+
readCachedToken: () => this.sessionTokenCache,
|
|
588
|
+
writeCachedToken: (token) => {
|
|
589
|
+
this.sessionTokenCache = token;
|
|
590
|
+
},
|
|
591
|
+
readPendingToken: () => this.pendingSessionToken,
|
|
592
|
+
writePendingToken: (token) => {
|
|
593
|
+
this.pendingSessionToken = token;
|
|
695
594
|
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
595
|
+
});
|
|
596
|
+
this.update(config);
|
|
597
|
+
}
|
|
598
|
+
update(config) {
|
|
599
|
+
if (config.clientId) {
|
|
600
|
+
this.clientId = config.clientId;
|
|
601
|
+
if (!this.readyPayload || typeof this.readyPayload === "object" && this.readyPayload !== null && "clientId" in this.readyPayload) {
|
|
602
|
+
this.readyPayload = config.readyPayload ?? { clientId: config.clientId };
|
|
702
603
|
}
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
604
|
+
}
|
|
605
|
+
if (config.currentPath !== void 0) {
|
|
606
|
+
this.currentPath = config.currentPath;
|
|
607
|
+
}
|
|
608
|
+
if (config.navigationItems !== void 0) {
|
|
609
|
+
this.navigationItems = normalizeBridgeNavigationItems(config.navigationItems);
|
|
610
|
+
}
|
|
611
|
+
if (config.onNavigate !== void 0) {
|
|
612
|
+
this.onNavigate = config.onNavigate;
|
|
613
|
+
}
|
|
614
|
+
if (config.readyEventType) {
|
|
615
|
+
this.readyEventType = config.readyEventType;
|
|
616
|
+
}
|
|
617
|
+
if (config.readyPayload !== void 0) {
|
|
618
|
+
this.readyPayload = config.readyPayload;
|
|
619
|
+
}
|
|
620
|
+
if (config.targetWindow !== void 0) {
|
|
621
|
+
this.bridge.setTargetWindow(config.targetWindow ?? null);
|
|
622
|
+
}
|
|
623
|
+
this.syncBridgeState();
|
|
624
|
+
}
|
|
625
|
+
clearNavigationHandler() {
|
|
626
|
+
this.onNavigate = void 0;
|
|
627
|
+
}
|
|
628
|
+
destroy() {
|
|
629
|
+
this.removeNavigationRequestHandler?.();
|
|
630
|
+
this.removeNavigationInterceptors();
|
|
631
|
+
this.restoreFetch();
|
|
632
|
+
this.bridge.destroy();
|
|
633
|
+
}
|
|
634
|
+
syncBridgeState() {
|
|
635
|
+
if (!this.bridge.hasTargetWindow()) {
|
|
713
636
|
return;
|
|
714
637
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
}
|
|
724
|
-
const nextHeaders = new Headers(
|
|
725
|
-
input instanceof Request ? input.headers : init?.headers
|
|
638
|
+
this.bridge.send(this.readyEventType, this.readyPayload);
|
|
639
|
+
this.bridge.send("navigation:items:update", {
|
|
640
|
+
items: this.navigationItems
|
|
641
|
+
});
|
|
642
|
+
if (this.currentPath) {
|
|
643
|
+
this.bridge.send(
|
|
644
|
+
this.navigationUpdateEventType,
|
|
645
|
+
buildNavigationUpdatePayload(this.currentPath)
|
|
726
646
|
);
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
};
|
|
759
|
-
globalThis.fetch = interceptedFetch;
|
|
760
|
-
window.fetch = interceptedFetch;
|
|
761
|
-
return () => {
|
|
762
|
-
globalThis.fetch = originalFetch;
|
|
763
|
-
window.fetch = originalFetch;
|
|
764
|
-
};
|
|
765
|
-
}, [bridge, clientId]);
|
|
766
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppBridgeContext.Provider, { value: bridge, children });
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
navigate(path, message) {
|
|
650
|
+
if (this.onNavigate) {
|
|
651
|
+
this.onNavigate(path, message);
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
if (dispatchNavigateEvent(this.selfWindow.document, path)) {
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
this.selfWindow.location.assign(path);
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
function getOrCreateEmbeddedAppRuntime(config) {
|
|
661
|
+
const globalScope = globalThis;
|
|
662
|
+
const existingRuntime = globalScope[GLOBAL_RUNTIME_KEY];
|
|
663
|
+
if (existingRuntime) {
|
|
664
|
+
existingRuntime.update(config);
|
|
665
|
+
return existingRuntime;
|
|
666
|
+
}
|
|
667
|
+
const runtime = new EmbeddedAppRuntime(config);
|
|
668
|
+
globalScope[GLOBAL_RUNTIME_KEY] = runtime;
|
|
669
|
+
return runtime;
|
|
670
|
+
}
|
|
671
|
+
function dispatchNavigateEvent(document, path) {
|
|
672
|
+
const event = new CustomEvent(THOR_NAVIGATE_EVENT, {
|
|
673
|
+
cancelable: true,
|
|
674
|
+
detail: { path }
|
|
675
|
+
});
|
|
676
|
+
document.dispatchEvent(event);
|
|
677
|
+
return event.defaultPrevented;
|
|
767
678
|
}
|
|
768
679
|
function getReferrerOrigin(explicitWindow) {
|
|
769
680
|
const resolvedWindow = explicitWindow ?? (typeof window !== "undefined" ? window : void 0);
|
|
@@ -777,40 +688,190 @@ function getReferrerOrigin(explicitWindow) {
|
|
|
777
688
|
return void 0;
|
|
778
689
|
}
|
|
779
690
|
}
|
|
691
|
+
function installNavigationInterceptors({
|
|
692
|
+
bridge,
|
|
693
|
+
selfWindow,
|
|
694
|
+
navigate
|
|
695
|
+
}) {
|
|
696
|
+
const document = selfWindow.document;
|
|
697
|
+
const handleLocalNavigation = (path) => {
|
|
698
|
+
const sanitizedPath = sanitizeEmbeddedAppPath(path);
|
|
699
|
+
if (!sanitizedPath) {
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
const nextPath = preserveEmbeddedAppLaunchParams(
|
|
703
|
+
sanitizedPath,
|
|
704
|
+
selfWindow.location.href
|
|
705
|
+
);
|
|
706
|
+
navigate(nextPath ?? sanitizedPath);
|
|
707
|
+
};
|
|
708
|
+
const handleDocumentClick = (event) => {
|
|
709
|
+
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) {
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
const target = event.target;
|
|
713
|
+
if (!(target instanceof Element)) {
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
const anchor = target.closest("a[href]");
|
|
717
|
+
if (!(anchor instanceof HTMLAnchorElement)) {
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
if (anchor.hasAttribute("download")) {
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
const targetWindow = anchor.target.toLowerCase();
|
|
724
|
+
const href = anchor.getAttribute("href");
|
|
725
|
+
if (!href) {
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
if (targetWindow === "_top" || targetWindow === "_parent") {
|
|
729
|
+
event.preventDefault();
|
|
730
|
+
bridge.redirectToRemote(anchor.href);
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
if (targetWindow && targetWindow !== "_self") {
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
const nextPath = resolveLocalNavigationPath(href, selfWindow.location.origin);
|
|
737
|
+
if (!nextPath) {
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
event.preventDefault();
|
|
741
|
+
handleLocalNavigation(nextPath);
|
|
742
|
+
};
|
|
743
|
+
const originalOpen = selfWindow.open.bind(selfWindow);
|
|
744
|
+
selfWindow.open = (url, target, features) => {
|
|
745
|
+
if (url == null) {
|
|
746
|
+
return originalOpen(url, target, features);
|
|
747
|
+
}
|
|
748
|
+
const href = typeof url === "string" ? url : url.toString();
|
|
749
|
+
const targetName = (target ?? "").toLowerCase();
|
|
750
|
+
if (targetName === "_top" || targetName === "_parent") {
|
|
751
|
+
bridge.redirectToRemote(new URL(href, selfWindow.location.href).toString());
|
|
752
|
+
return null;
|
|
753
|
+
}
|
|
754
|
+
if (!targetName || targetName === "_self") {
|
|
755
|
+
const nextPath = resolveLocalNavigationPath(
|
|
756
|
+
href,
|
|
757
|
+
selfWindow.location.origin
|
|
758
|
+
);
|
|
759
|
+
if (nextPath) {
|
|
760
|
+
handleLocalNavigation(nextPath);
|
|
761
|
+
return selfWindow;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
return originalOpen(url, target, features);
|
|
765
|
+
};
|
|
766
|
+
document.addEventListener("click", handleDocumentClick, true);
|
|
767
|
+
return () => {
|
|
768
|
+
document.removeEventListener("click", handleDocumentClick, true);
|
|
769
|
+
selfWindow.open = originalOpen;
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
function installFetchInterceptor({
|
|
773
|
+
bridge,
|
|
774
|
+
getClientId,
|
|
775
|
+
getProject,
|
|
776
|
+
setProject,
|
|
777
|
+
readCachedToken,
|
|
778
|
+
writeCachedToken,
|
|
779
|
+
readPendingToken,
|
|
780
|
+
writePendingToken
|
|
781
|
+
}) {
|
|
782
|
+
if (typeof window === "undefined") {
|
|
783
|
+
return () => {
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
const originalFetch = globalThis.fetch.bind(globalThis);
|
|
787
|
+
const interceptedFetch = async (input, init) => {
|
|
788
|
+
if (!shouldAttachSessionToken(input)) {
|
|
789
|
+
return originalFetch(input, init);
|
|
790
|
+
}
|
|
791
|
+
const existingAuthorization = getExistingAuthorization(input, init);
|
|
792
|
+
if (existingAuthorization) {
|
|
793
|
+
return originalFetch(input, init);
|
|
794
|
+
}
|
|
795
|
+
const nextHeaders = new Headers(
|
|
796
|
+
input instanceof Request ? input.headers : init?.headers
|
|
797
|
+
);
|
|
798
|
+
try {
|
|
799
|
+
const sessionToken = await getSessionToken({
|
|
800
|
+
bridge,
|
|
801
|
+
clientId: getClientId(),
|
|
802
|
+
project: getProject,
|
|
803
|
+
setProject,
|
|
804
|
+
readCachedToken,
|
|
805
|
+
writeCachedToken,
|
|
806
|
+
readPendingToken,
|
|
807
|
+
writePendingToken
|
|
808
|
+
});
|
|
809
|
+
nextHeaders.set("Authorization", `Bearer ${sessionToken}`);
|
|
810
|
+
} catch {
|
|
811
|
+
if (!getProject()) {
|
|
812
|
+
throw new Error("Missing Thor embedded session token");
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
if (!nextHeaders.has("X-Requested-With")) {
|
|
816
|
+
nextHeaders.set("X-Requested-With", "XMLHttpRequest");
|
|
817
|
+
}
|
|
818
|
+
if (input instanceof Request) {
|
|
819
|
+
return originalFetch(
|
|
820
|
+
new Request(input, {
|
|
821
|
+
headers: nextHeaders
|
|
822
|
+
})
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
return originalFetch(input, {
|
|
826
|
+
...init,
|
|
827
|
+
headers: nextHeaders
|
|
828
|
+
});
|
|
829
|
+
};
|
|
830
|
+
globalThis.fetch = interceptedFetch;
|
|
831
|
+
window.fetch = interceptedFetch;
|
|
832
|
+
return () => {
|
|
833
|
+
globalThis.fetch = originalFetch;
|
|
834
|
+
window.fetch = originalFetch;
|
|
835
|
+
};
|
|
836
|
+
}
|
|
780
837
|
async function getSessionToken({
|
|
781
838
|
bridge,
|
|
782
839
|
clientId,
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
840
|
+
project,
|
|
841
|
+
setProject,
|
|
842
|
+
readCachedToken,
|
|
843
|
+
writeCachedToken,
|
|
844
|
+
readPendingToken,
|
|
845
|
+
writePendingToken
|
|
786
846
|
}) {
|
|
787
|
-
const cachedToken =
|
|
847
|
+
const cachedToken = readCachedToken();
|
|
788
848
|
if (cachedToken && !isExpired(cachedToken.expiresAt)) {
|
|
789
849
|
return cachedToken.token;
|
|
790
850
|
}
|
|
791
|
-
|
|
792
|
-
|
|
851
|
+
const pendingToken = readPendingToken();
|
|
852
|
+
if (pendingToken) {
|
|
853
|
+
return pendingToken;
|
|
793
854
|
}
|
|
794
|
-
const
|
|
855
|
+
const nextPendingToken = bridge.getSessionToken({ clientId }).then((response) => {
|
|
795
856
|
const token = response.sessionToken ?? response.idToken;
|
|
796
857
|
if (!token) {
|
|
797
858
|
throw new Error("Missing Thor embedded session token");
|
|
798
859
|
}
|
|
799
860
|
if (response.project) {
|
|
800
|
-
|
|
861
|
+
setProject(response.project);
|
|
801
862
|
}
|
|
802
|
-
|
|
863
|
+
writeCachedToken({
|
|
803
864
|
token,
|
|
804
865
|
expiresAt: normalizeTokenExpiry(token, response.exp)
|
|
805
|
-
};
|
|
806
|
-
|
|
866
|
+
});
|
|
867
|
+
writePendingToken(null);
|
|
807
868
|
return token;
|
|
808
869
|
}).catch((error) => {
|
|
809
|
-
|
|
870
|
+
writePendingToken(null);
|
|
810
871
|
throw error;
|
|
811
872
|
});
|
|
812
|
-
|
|
813
|
-
return
|
|
873
|
+
writePendingToken(nextPendingToken);
|
|
874
|
+
return nextPendingToken;
|
|
814
875
|
}
|
|
815
876
|
function shouldAttachSessionToken(input) {
|
|
816
877
|
if (typeof window === "undefined") {
|
|
@@ -877,6 +938,70 @@ function readInitialProject(explicitWindow) {
|
|
|
877
938
|
}
|
|
878
939
|
}
|
|
879
940
|
|
|
941
|
+
// src/react.tsx
|
|
942
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
943
|
+
var AppBridgeContext = (0, import_react.createContext)(null);
|
|
944
|
+
function AppBridgeProvider({
|
|
945
|
+
children,
|
|
946
|
+
clientId,
|
|
947
|
+
currentPath,
|
|
948
|
+
navigationItems,
|
|
949
|
+
navigationEventType = "navigation:go",
|
|
950
|
+
navigationUpdateEventType = "navigation:update",
|
|
951
|
+
namespace,
|
|
952
|
+
onNavigate,
|
|
953
|
+
readyEventType = "app:ready",
|
|
954
|
+
readyPayload,
|
|
955
|
+
requestTimeoutMs,
|
|
956
|
+
selfWindow,
|
|
957
|
+
targetOrigin,
|
|
958
|
+
targetWindow
|
|
959
|
+
}) {
|
|
960
|
+
const [bridge, setBridge] = (0, import_react.useState)(null);
|
|
961
|
+
(0, import_react.useEffect)(() => {
|
|
962
|
+
if (typeof window === "undefined" && !selfWindow) {
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
const runtime = getOrCreateEmbeddedAppRuntime({
|
|
966
|
+
clientId,
|
|
967
|
+
currentPath,
|
|
968
|
+
navigationEventType,
|
|
969
|
+
navigationItems,
|
|
970
|
+
navigationUpdateEventType,
|
|
971
|
+
namespace,
|
|
972
|
+
onNavigate,
|
|
973
|
+
readyEventType,
|
|
974
|
+
readyPayload,
|
|
975
|
+
requestTimeoutMs,
|
|
976
|
+
selfWindow,
|
|
977
|
+
targetOrigin,
|
|
978
|
+
targetWindow
|
|
979
|
+
});
|
|
980
|
+
setBridge(runtime.bridge);
|
|
981
|
+
return () => {
|
|
982
|
+
runtime.clearNavigationHandler();
|
|
983
|
+
setBridge(
|
|
984
|
+
(currentBridge) => currentBridge === runtime.bridge ? null : currentBridge
|
|
985
|
+
);
|
|
986
|
+
};
|
|
987
|
+
}, [
|
|
988
|
+
clientId,
|
|
989
|
+
currentPath,
|
|
990
|
+
navigationEventType,
|
|
991
|
+
navigationItems,
|
|
992
|
+
navigationUpdateEventType,
|
|
993
|
+
namespace,
|
|
994
|
+
onNavigate,
|
|
995
|
+
readyEventType,
|
|
996
|
+
readyPayload,
|
|
997
|
+
requestTimeoutMs,
|
|
998
|
+
selfWindow,
|
|
999
|
+
targetOrigin,
|
|
1000
|
+
targetWindow
|
|
1001
|
+
]);
|
|
1002
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppBridgeContext.Provider, { value: bridge, children });
|
|
1003
|
+
}
|
|
1004
|
+
|
|
880
1005
|
// src/react-router.tsx
|
|
881
1006
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
882
1007
|
function ReactRouterAppBridgeProvider({
|