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