@thor-commerce/app-bridge-react 0.7.2 → 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-XPUL72AN.js → chunk-IRTDLWEQ.js} +337 -270
- package/dist/chunk-IRTDLWEQ.js.map +1 -0
- package/dist/index.cjs +408 -257
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -127
- package/dist/index.d.ts +4 -127
- package/dist/index.js +16 -4
- package/dist/next.cjs +392 -256
- 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 +392 -256
- 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-XPUL72AN.js.map +0 -1
|
@@ -7,6 +7,7 @@ var EMBEDDED_LAUNCH_PARAMS = [
|
|
|
7
7
|
"id_token",
|
|
8
8
|
"link_source",
|
|
9
9
|
"locale",
|
|
10
|
+
"project",
|
|
10
11
|
"protocol",
|
|
11
12
|
"session",
|
|
12
13
|
"shop",
|
|
@@ -72,6 +73,37 @@ function sanitizeEmbeddedAppPath(path) {
|
|
|
72
73
|
}
|
|
73
74
|
return `${url.pathname}${url.search}${url.hash}`;
|
|
74
75
|
}
|
|
76
|
+
function preserveEmbeddedAppLaunchParams(path, currentHref) {
|
|
77
|
+
if (!path || !currentHref) {
|
|
78
|
+
return path;
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const currentUrl = new URL(currentHref, NAVIGATION_BASE_URL);
|
|
82
|
+
const nextUrl = new URL(path, currentUrl.href);
|
|
83
|
+
if (nextUrl.origin !== currentUrl.origin) {
|
|
84
|
+
return path;
|
|
85
|
+
}
|
|
86
|
+
let changed = false;
|
|
87
|
+
for (const key of EMBEDDED_LAUNCH_PARAMS) {
|
|
88
|
+
if (!nextUrl.searchParams.has(key) && currentUrl.searchParams.has(key)) {
|
|
89
|
+
const value = currentUrl.searchParams.get(key);
|
|
90
|
+
if (value != null) {
|
|
91
|
+
nextUrl.searchParams.set(key, value);
|
|
92
|
+
changed = true;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (!changed) {
|
|
97
|
+
return path;
|
|
98
|
+
}
|
|
99
|
+
if (/^https?:\/\//i.test(path)) {
|
|
100
|
+
return nextUrl.toString();
|
|
101
|
+
}
|
|
102
|
+
return `${nextUrl.pathname}${nextUrl.search}${nextUrl.hash}`;
|
|
103
|
+
} catch {
|
|
104
|
+
return path;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
75
107
|
function resolveLocalNavigationPath(href, currentOrigin) {
|
|
76
108
|
if (!href || href.startsWith("#")) {
|
|
77
109
|
return null;
|
|
@@ -146,13 +178,6 @@ function normalizeBridgeNavigationItems(items) {
|
|
|
146
178
|
}
|
|
147
179
|
|
|
148
180
|
// src/core.ts
|
|
149
|
-
var PRESERVED_EMBEDDED_DOCUMENT_PARAMS = [
|
|
150
|
-
"hmac",
|
|
151
|
-
"id_token",
|
|
152
|
-
"project",
|
|
153
|
-
"tenant",
|
|
154
|
-
"timestamp"
|
|
155
|
-
];
|
|
156
181
|
var DEFAULT_NAMESPACE = "thorcommerce:app-bridge";
|
|
157
182
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
158
183
|
var DEFAULT_REDIRECT_EVENT_TYPE = "navigation:redirect";
|
|
@@ -466,273 +491,162 @@ var AppBridge = class {
|
|
|
466
491
|
throw new Error("AppBridge could not resolve a browser window for redirect.");
|
|
467
492
|
}
|
|
468
493
|
this.selfWindow.location.assign(
|
|
469
|
-
|
|
494
|
+
preserveEmbeddedAppLaunchParams(destination, this.selfWindow.location.href) ?? destination
|
|
470
495
|
);
|
|
471
496
|
}
|
|
472
497
|
};
|
|
473
|
-
function preserveEmbeddedDocumentParams(destination, currentHref) {
|
|
474
|
-
try {
|
|
475
|
-
const currentUrl = new URL(currentHref);
|
|
476
|
-
const nextUrl = new URL(destination, currentUrl.href);
|
|
477
|
-
if (nextUrl.origin !== currentUrl.origin) {
|
|
478
|
-
return destination;
|
|
479
|
-
}
|
|
480
|
-
let changed = false;
|
|
481
|
-
for (const key of PRESERVED_EMBEDDED_DOCUMENT_PARAMS) {
|
|
482
|
-
if (!nextUrl.searchParams.has(key) && currentUrl.searchParams.has(key)) {
|
|
483
|
-
const value = currentUrl.searchParams.get(key);
|
|
484
|
-
if (value != null) {
|
|
485
|
-
nextUrl.searchParams.set(key, value);
|
|
486
|
-
changed = true;
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
return changed ? nextUrl.toString() : destination;
|
|
491
|
-
} catch {
|
|
492
|
-
return destination;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
498
|
function createAppBridge(options = {}) {
|
|
496
499
|
return new AppBridge(options);
|
|
497
500
|
}
|
|
498
501
|
|
|
499
|
-
// src/
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
}) {
|
|
526
|
-
const [bridge, setBridge] = useState(null);
|
|
527
|
-
const onNavigateRef = useRef(onNavigate);
|
|
528
|
-
const normalizedNavigationItems = useMemo(
|
|
529
|
-
() => normalizeBridgeNavigationItems(navigationItems),
|
|
530
|
-
[navigationItems]
|
|
531
|
-
);
|
|
532
|
-
const sessionTokenCacheRef = useRef(null);
|
|
533
|
-
const projectRef = useRef(readInitialProject(selfWindow));
|
|
534
|
-
const pendingSessionTokenRef = useRef(null);
|
|
535
|
-
useEffect(() => {
|
|
536
|
-
onNavigateRef.current = onNavigate;
|
|
537
|
-
}, [onNavigate]);
|
|
538
|
-
useEffect(() => {
|
|
539
|
-
if (typeof window === "undefined" && !selfWindow) {
|
|
540
|
-
return;
|
|
541
|
-
}
|
|
542
|
-
const resolvedTargetOrigin = targetOrigin ?? getReferrerOrigin(selfWindow);
|
|
543
|
-
const resolvedAllowedOrigins = resolvedTargetOrigin ? [resolvedTargetOrigin] : void 0;
|
|
544
|
-
const nextBridge = createAppBridge({
|
|
545
|
-
allowedOrigins: resolvedAllowedOrigins,
|
|
546
|
-
clientId,
|
|
547
|
-
namespace,
|
|
548
|
-
requestTimeoutMs,
|
|
549
|
-
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.sessionTokenCache = null;
|
|
513
|
+
this.pendingSessionToken = null;
|
|
514
|
+
const resolvedWindow = config.selfWindow ?? (typeof window !== "undefined" ? window : void 0);
|
|
515
|
+
if (!resolvedWindow) {
|
|
516
|
+
throw new Error("EmbeddedAppRuntime requires a browser window.");
|
|
517
|
+
}
|
|
518
|
+
this.selfWindow = resolvedWindow;
|
|
519
|
+
this.targetOrigin = config.targetOrigin ?? getReferrerOrigin(resolvedWindow);
|
|
520
|
+
this.clientId = config.clientId;
|
|
521
|
+
this.project = readInitialProject(resolvedWindow);
|
|
522
|
+
this.readyPayload = config.readyPayload ?? { clientId: config.clientId };
|
|
523
|
+
this.bridge = createAppBridge({
|
|
524
|
+
allowedOrigins: this.targetOrigin ? [this.targetOrigin] : void 0,
|
|
525
|
+
namespace: config.namespace,
|
|
526
|
+
requestTimeoutMs: config.requestTimeoutMs,
|
|
527
|
+
selfWindow: resolvedWindow,
|
|
550
528
|
source: "embedded-app",
|
|
551
529
|
target: "dashboard",
|
|
552
|
-
targetOrigin:
|
|
553
|
-
targetWindow
|
|
554
|
-
});
|
|
555
|
-
setBridge(nextBridge);
|
|
556
|
-
return () => {
|
|
557
|
-
setBridge((currentBridge) => currentBridge === nextBridge ? null : currentBridge);
|
|
558
|
-
nextBridge.destroy();
|
|
559
|
-
};
|
|
560
|
-
}, [
|
|
561
|
-
clientId,
|
|
562
|
-
namespace,
|
|
563
|
-
requestTimeoutMs,
|
|
564
|
-
selfWindow,
|
|
565
|
-
targetOrigin,
|
|
566
|
-
targetWindow
|
|
567
|
-
]);
|
|
568
|
-
useEffect(() => {
|
|
569
|
-
if (!bridge || !bridge.hasTargetWindow()) {
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
bridge.send(
|
|
573
|
-
readyEventType,
|
|
574
|
-
readyPayload ?? {
|
|
575
|
-
clientId
|
|
576
|
-
}
|
|
577
|
-
);
|
|
578
|
-
}, [bridge, clientId, readyEventType, readyPayload]);
|
|
579
|
-
useEffect(() => {
|
|
580
|
-
if (!bridge || !bridge.hasTargetWindow()) {
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
bridge.send("navigation:items:update", {
|
|
584
|
-
items: normalizedNavigationItems
|
|
530
|
+
targetOrigin: this.targetOrigin,
|
|
531
|
+
targetWindow: config.targetWindow
|
|
585
532
|
});
|
|
586
|
-
|
|
587
|
-
useEffect(() => {
|
|
588
|
-
if (!bridge || !bridge.hasTargetWindow() || !currentPath) {
|
|
589
|
-
return;
|
|
590
|
-
}
|
|
591
|
-
bridge.send(navigationUpdateEventType, buildNavigationUpdatePayload(currentPath));
|
|
592
|
-
}, [bridge, currentPath, navigationUpdateEventType]);
|
|
593
|
-
useEffect(() => {
|
|
594
|
-
if (!bridge || !onNavigate) {
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
return bridge.on(navigationEventType, (message) => {
|
|
533
|
+
this.removeNavigationRequestHandler = this.bridge.on(this.navigationEventType, (message) => {
|
|
598
534
|
const destination = resolveNavigationDestination(message.payload);
|
|
599
535
|
if (!destination) {
|
|
600
536
|
return;
|
|
601
537
|
}
|
|
602
|
-
|
|
538
|
+
const nextPath = preserveEmbeddedAppLaunchParams(
|
|
539
|
+
destination,
|
|
540
|
+
this.selfWindow.location.href
|
|
541
|
+
);
|
|
542
|
+
this.navigate(nextPath ?? destination, message);
|
|
603
543
|
});
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
}
|
|
624
|
-
const anchor = target.closest("a[href]");
|
|
625
|
-
if (!(anchor instanceof HTMLAnchorElement)) {
|
|
626
|
-
return;
|
|
627
|
-
}
|
|
628
|
-
if (anchor.hasAttribute("download")) {
|
|
629
|
-
return;
|
|
630
|
-
}
|
|
631
|
-
const targetWindow2 = anchor.target.toLowerCase();
|
|
632
|
-
const href = anchor.getAttribute("href");
|
|
633
|
-
if (!href) {
|
|
634
|
-
return;
|
|
635
|
-
}
|
|
636
|
-
if (targetWindow2 === "_top" || targetWindow2 === "_parent") {
|
|
637
|
-
event.preventDefault();
|
|
638
|
-
bridge.redirectToRemote(anchor.href);
|
|
639
|
-
return;
|
|
640
|
-
}
|
|
641
|
-
if (targetWindow2 && targetWindow2 !== "_self") {
|
|
642
|
-
return;
|
|
643
|
-
}
|
|
644
|
-
const nextPath = resolveLocalNavigationPath(href, window.location.origin);
|
|
645
|
-
if (!nextPath) {
|
|
646
|
-
return;
|
|
647
|
-
}
|
|
648
|
-
event.preventDefault();
|
|
649
|
-
handleLocalNavigation(nextPath);
|
|
650
|
-
};
|
|
651
|
-
const originalOpen = window.open.bind(window);
|
|
652
|
-
window.open = (url, target, features) => {
|
|
653
|
-
if (url == null) {
|
|
654
|
-
return originalOpen(url, target, features);
|
|
655
|
-
}
|
|
656
|
-
const href = typeof url === "string" ? url : url.toString();
|
|
657
|
-
const targetName = (target ?? "").toLowerCase();
|
|
658
|
-
if (targetName === "_top" || targetName === "_parent") {
|
|
659
|
-
bridge.redirectToRemote(new URL(href, window.location.href).toString());
|
|
660
|
-
return null;
|
|
544
|
+
this.removeNavigationInterceptors = installNavigationInterceptors({
|
|
545
|
+
bridge: this.bridge,
|
|
546
|
+
selfWindow: this.selfWindow,
|
|
547
|
+
navigate: (path) => this.navigate(path)
|
|
548
|
+
});
|
|
549
|
+
this.restoreFetch = installFetchInterceptor({
|
|
550
|
+
bridge: this.bridge,
|
|
551
|
+
getClientId: () => this.clientId,
|
|
552
|
+
getProject: () => this.project,
|
|
553
|
+
setProject: (project) => {
|
|
554
|
+
this.project = project;
|
|
555
|
+
},
|
|
556
|
+
readCachedToken: () => this.sessionTokenCache,
|
|
557
|
+
writeCachedToken: (token) => {
|
|
558
|
+
this.sessionTokenCache = token;
|
|
559
|
+
},
|
|
560
|
+
readPendingToken: () => this.pendingSessionToken,
|
|
561
|
+
writePendingToken: (token) => {
|
|
562
|
+
this.pendingSessionToken = token;
|
|
661
563
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
564
|
+
});
|
|
565
|
+
this.update(config);
|
|
566
|
+
}
|
|
567
|
+
update(config) {
|
|
568
|
+
if (config.clientId) {
|
|
569
|
+
this.clientId = config.clientId;
|
|
570
|
+
if (!this.readyPayload || typeof this.readyPayload === "object" && this.readyPayload !== null && "clientId" in this.readyPayload) {
|
|
571
|
+
this.readyPayload = config.readyPayload ?? { clientId: config.clientId };
|
|
668
572
|
}
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
573
|
+
}
|
|
574
|
+
if (config.currentPath !== void 0) {
|
|
575
|
+
this.currentPath = config.currentPath;
|
|
576
|
+
}
|
|
577
|
+
if (config.navigationItems !== void 0) {
|
|
578
|
+
this.navigationItems = normalizeBridgeNavigationItems(config.navigationItems);
|
|
579
|
+
}
|
|
580
|
+
if (config.onNavigate !== void 0) {
|
|
581
|
+
this.onNavigate = config.onNavigate;
|
|
582
|
+
}
|
|
583
|
+
if (config.readyEventType) {
|
|
584
|
+
this.readyEventType = config.readyEventType;
|
|
585
|
+
}
|
|
586
|
+
if (config.readyPayload !== void 0) {
|
|
587
|
+
this.readyPayload = config.readyPayload;
|
|
588
|
+
}
|
|
589
|
+
if (config.targetWindow !== void 0) {
|
|
590
|
+
this.bridge.setTargetWindow(config.targetWindow ?? null);
|
|
591
|
+
}
|
|
592
|
+
this.syncBridgeState();
|
|
593
|
+
}
|
|
594
|
+
clearNavigationHandler() {
|
|
595
|
+
this.onNavigate = void 0;
|
|
596
|
+
}
|
|
597
|
+
destroy() {
|
|
598
|
+
this.removeNavigationRequestHandler?.();
|
|
599
|
+
this.removeNavigationInterceptors();
|
|
600
|
+
this.restoreFetch();
|
|
601
|
+
this.bridge.destroy();
|
|
602
|
+
}
|
|
603
|
+
syncBridgeState() {
|
|
604
|
+
if (!this.bridge.hasTargetWindow()) {
|
|
679
605
|
return;
|
|
680
606
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
}
|
|
690
|
-
const nextHeaders = new Headers(
|
|
691
|
-
input instanceof Request ? input.headers : init?.headers
|
|
607
|
+
this.bridge.send(this.readyEventType, this.readyPayload);
|
|
608
|
+
this.bridge.send("navigation:items:update", {
|
|
609
|
+
items: this.navigationItems
|
|
610
|
+
});
|
|
611
|
+
if (this.currentPath) {
|
|
612
|
+
this.bridge.send(
|
|
613
|
+
this.navigationUpdateEventType,
|
|
614
|
+
buildNavigationUpdatePayload(this.currentPath)
|
|
692
615
|
);
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
headers: nextHeaders
|
|
717
|
-
})
|
|
718
|
-
);
|
|
719
|
-
}
|
|
720
|
-
return originalFetch(input, {
|
|
721
|
-
...init,
|
|
722
|
-
headers: nextHeaders
|
|
723
|
-
});
|
|
724
|
-
};
|
|
725
|
-
globalThis.fetch = interceptedFetch;
|
|
726
|
-
window.fetch = interceptedFetch;
|
|
727
|
-
return () => {
|
|
728
|
-
globalThis.fetch = originalFetch;
|
|
729
|
-
window.fetch = originalFetch;
|
|
730
|
-
};
|
|
731
|
-
}, [bridge, clientId]);
|
|
732
|
-
return /* @__PURE__ */ jsx(AppBridgeContext.Provider, { value: bridge, children });
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
navigate(path, message) {
|
|
619
|
+
if (this.onNavigate) {
|
|
620
|
+
this.onNavigate(path, message);
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
if (dispatchNavigateEvent(this.selfWindow.document, path)) {
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
this.selfWindow.location.assign(path);
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
function getOrCreateEmbeddedAppRuntime(config) {
|
|
630
|
+
const globalScope = globalThis;
|
|
631
|
+
const existingRuntime = globalScope[GLOBAL_RUNTIME_KEY];
|
|
632
|
+
if (existingRuntime) {
|
|
633
|
+
existingRuntime.update(config);
|
|
634
|
+
return existingRuntime;
|
|
635
|
+
}
|
|
636
|
+
const runtime = new EmbeddedAppRuntime(config);
|
|
637
|
+
globalScope[GLOBAL_RUNTIME_KEY] = runtime;
|
|
638
|
+
return runtime;
|
|
733
639
|
}
|
|
734
|
-
function
|
|
735
|
-
return
|
|
640
|
+
function getEmbeddedAppRuntime() {
|
|
641
|
+
return globalThis[GLOBAL_RUNTIME_KEY] ?? null;
|
|
642
|
+
}
|
|
643
|
+
function dispatchNavigateEvent(document, path) {
|
|
644
|
+
const event = new CustomEvent(THOR_NAVIGATE_EVENT, {
|
|
645
|
+
cancelable: true,
|
|
646
|
+
detail: { path }
|
|
647
|
+
});
|
|
648
|
+
document.dispatchEvent(event);
|
|
649
|
+
return event.defaultPrevented;
|
|
736
650
|
}
|
|
737
651
|
function getReferrerOrigin(explicitWindow) {
|
|
738
652
|
const resolvedWindow = explicitWindow ?? (typeof window !== "undefined" ? window : void 0);
|
|
@@ -746,40 +660,190 @@ function getReferrerOrigin(explicitWindow) {
|
|
|
746
660
|
return void 0;
|
|
747
661
|
}
|
|
748
662
|
}
|
|
663
|
+
function installNavigationInterceptors({
|
|
664
|
+
bridge,
|
|
665
|
+
selfWindow,
|
|
666
|
+
navigate
|
|
667
|
+
}) {
|
|
668
|
+
const document = selfWindow.document;
|
|
669
|
+
const handleLocalNavigation = (path) => {
|
|
670
|
+
const sanitizedPath = sanitizeEmbeddedAppPath(path);
|
|
671
|
+
if (!sanitizedPath) {
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
const nextPath = preserveEmbeddedAppLaunchParams(
|
|
675
|
+
sanitizedPath,
|
|
676
|
+
selfWindow.location.href
|
|
677
|
+
);
|
|
678
|
+
navigate(nextPath ?? sanitizedPath);
|
|
679
|
+
};
|
|
680
|
+
const handleDocumentClick = (event) => {
|
|
681
|
+
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) {
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
const target = event.target;
|
|
685
|
+
if (!(target instanceof Element)) {
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
const anchor = target.closest("a[href]");
|
|
689
|
+
if (!(anchor instanceof HTMLAnchorElement)) {
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
if (anchor.hasAttribute("download")) {
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
const targetWindow = anchor.target.toLowerCase();
|
|
696
|
+
const href = anchor.getAttribute("href");
|
|
697
|
+
if (!href) {
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
if (targetWindow === "_top" || targetWindow === "_parent") {
|
|
701
|
+
event.preventDefault();
|
|
702
|
+
bridge.redirectToRemote(anchor.href);
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
if (targetWindow && targetWindow !== "_self") {
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
const nextPath = resolveLocalNavigationPath(href, selfWindow.location.origin);
|
|
709
|
+
if (!nextPath) {
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
event.preventDefault();
|
|
713
|
+
handleLocalNavigation(nextPath);
|
|
714
|
+
};
|
|
715
|
+
const originalOpen = selfWindow.open.bind(selfWindow);
|
|
716
|
+
selfWindow.open = (url, target, features) => {
|
|
717
|
+
if (url == null) {
|
|
718
|
+
return originalOpen(url, target, features);
|
|
719
|
+
}
|
|
720
|
+
const href = typeof url === "string" ? url : url.toString();
|
|
721
|
+
const targetName = (target ?? "").toLowerCase();
|
|
722
|
+
if (targetName === "_top" || targetName === "_parent") {
|
|
723
|
+
bridge.redirectToRemote(new URL(href, selfWindow.location.href).toString());
|
|
724
|
+
return null;
|
|
725
|
+
}
|
|
726
|
+
if (!targetName || targetName === "_self") {
|
|
727
|
+
const nextPath = resolveLocalNavigationPath(
|
|
728
|
+
href,
|
|
729
|
+
selfWindow.location.origin
|
|
730
|
+
);
|
|
731
|
+
if (nextPath) {
|
|
732
|
+
handleLocalNavigation(nextPath);
|
|
733
|
+
return selfWindow;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
return originalOpen(url, target, features);
|
|
737
|
+
};
|
|
738
|
+
document.addEventListener("click", handleDocumentClick, true);
|
|
739
|
+
return () => {
|
|
740
|
+
document.removeEventListener("click", handleDocumentClick, true);
|
|
741
|
+
selfWindow.open = originalOpen;
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
function installFetchInterceptor({
|
|
745
|
+
bridge,
|
|
746
|
+
getClientId,
|
|
747
|
+
getProject,
|
|
748
|
+
setProject,
|
|
749
|
+
readCachedToken,
|
|
750
|
+
writeCachedToken,
|
|
751
|
+
readPendingToken,
|
|
752
|
+
writePendingToken
|
|
753
|
+
}) {
|
|
754
|
+
if (typeof window === "undefined") {
|
|
755
|
+
return () => {
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
const originalFetch = globalThis.fetch.bind(globalThis);
|
|
759
|
+
const interceptedFetch = async (input, init) => {
|
|
760
|
+
if (!shouldAttachSessionToken(input)) {
|
|
761
|
+
return originalFetch(input, init);
|
|
762
|
+
}
|
|
763
|
+
const existingAuthorization = getExistingAuthorization(input, init);
|
|
764
|
+
if (existingAuthorization) {
|
|
765
|
+
return originalFetch(input, init);
|
|
766
|
+
}
|
|
767
|
+
const nextHeaders = new Headers(
|
|
768
|
+
input instanceof Request ? input.headers : init?.headers
|
|
769
|
+
);
|
|
770
|
+
try {
|
|
771
|
+
const sessionToken = await getSessionToken({
|
|
772
|
+
bridge,
|
|
773
|
+
clientId: getClientId(),
|
|
774
|
+
project: getProject,
|
|
775
|
+
setProject,
|
|
776
|
+
readCachedToken,
|
|
777
|
+
writeCachedToken,
|
|
778
|
+
readPendingToken,
|
|
779
|
+
writePendingToken
|
|
780
|
+
});
|
|
781
|
+
nextHeaders.set("Authorization", `Bearer ${sessionToken}`);
|
|
782
|
+
} catch {
|
|
783
|
+
if (!getProject()) {
|
|
784
|
+
throw new Error("Missing Thor embedded session token");
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
if (!nextHeaders.has("X-Requested-With")) {
|
|
788
|
+
nextHeaders.set("X-Requested-With", "XMLHttpRequest");
|
|
789
|
+
}
|
|
790
|
+
if (input instanceof Request) {
|
|
791
|
+
return originalFetch(
|
|
792
|
+
new Request(input, {
|
|
793
|
+
headers: nextHeaders
|
|
794
|
+
})
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
return originalFetch(input, {
|
|
798
|
+
...init,
|
|
799
|
+
headers: nextHeaders
|
|
800
|
+
});
|
|
801
|
+
};
|
|
802
|
+
globalThis.fetch = interceptedFetch;
|
|
803
|
+
window.fetch = interceptedFetch;
|
|
804
|
+
return () => {
|
|
805
|
+
globalThis.fetch = originalFetch;
|
|
806
|
+
window.fetch = originalFetch;
|
|
807
|
+
};
|
|
808
|
+
}
|
|
749
809
|
async function getSessionToken({
|
|
750
810
|
bridge,
|
|
751
811
|
clientId,
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
812
|
+
project,
|
|
813
|
+
setProject,
|
|
814
|
+
readCachedToken,
|
|
815
|
+
writeCachedToken,
|
|
816
|
+
readPendingToken,
|
|
817
|
+
writePendingToken
|
|
755
818
|
}) {
|
|
756
|
-
const cachedToken =
|
|
819
|
+
const cachedToken = readCachedToken();
|
|
757
820
|
if (cachedToken && !isExpired(cachedToken.expiresAt)) {
|
|
758
821
|
return cachedToken.token;
|
|
759
822
|
}
|
|
760
|
-
|
|
761
|
-
|
|
823
|
+
const pendingToken = readPendingToken();
|
|
824
|
+
if (pendingToken) {
|
|
825
|
+
return pendingToken;
|
|
762
826
|
}
|
|
763
|
-
const
|
|
827
|
+
const nextPendingToken = bridge.getSessionToken({ clientId }).then((response) => {
|
|
764
828
|
const token = response.sessionToken ?? response.idToken;
|
|
765
829
|
if (!token) {
|
|
766
830
|
throw new Error("Missing Thor embedded session token");
|
|
767
831
|
}
|
|
768
832
|
if (response.project) {
|
|
769
|
-
|
|
833
|
+
setProject(response.project);
|
|
770
834
|
}
|
|
771
|
-
|
|
835
|
+
writeCachedToken({
|
|
772
836
|
token,
|
|
773
837
|
expiresAt: normalizeTokenExpiry(token, response.exp)
|
|
774
|
-
};
|
|
775
|
-
|
|
838
|
+
});
|
|
839
|
+
writePendingToken(null);
|
|
776
840
|
return token;
|
|
777
841
|
}).catch((error) => {
|
|
778
|
-
|
|
842
|
+
writePendingToken(null);
|
|
779
843
|
throw error;
|
|
780
844
|
});
|
|
781
|
-
|
|
782
|
-
return
|
|
845
|
+
writePendingToken(nextPendingToken);
|
|
846
|
+
return nextPendingToken;
|
|
783
847
|
}
|
|
784
848
|
function shouldAttachSessionToken(input) {
|
|
785
849
|
if (typeof window === "undefined") {
|
|
@@ -850,6 +914,7 @@ export {
|
|
|
850
914
|
EMBEDDED_LAUNCH_PARAMS,
|
|
851
915
|
buildNavigationUpdatePayload,
|
|
852
916
|
sanitizeEmbeddedAppPath,
|
|
917
|
+
preserveEmbeddedAppLaunchParams,
|
|
853
918
|
resolveLocalNavigationPath,
|
|
854
919
|
resolveNavigationDestination,
|
|
855
920
|
normalizeBridgeNavigationItem,
|
|
@@ -857,7 +922,9 @@ export {
|
|
|
857
922
|
isBridgeMessage,
|
|
858
923
|
AppBridge,
|
|
859
924
|
createAppBridge,
|
|
860
|
-
|
|
861
|
-
|
|
925
|
+
THOR_NAVIGATE_EVENT,
|
|
926
|
+
EmbeddedAppRuntime,
|
|
927
|
+
getOrCreateEmbeddedAppRuntime,
|
|
928
|
+
getEmbeddedAppRuntime
|
|
862
929
|
};
|
|
863
|
-
//# sourceMappingURL=chunk-
|
|
930
|
+
//# sourceMappingURL=chunk-IRTDLWEQ.js.map
|