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