@thor-commerce/app-bridge-react 0.6.2 → 0.7.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/dist/{chunk-6LS2PKXH.js → chunk-2JYVH4LK.js} +51 -2
- package/dist/chunk-2JYVH4LK.js.map +1 -0
- package/dist/index.cjs +51 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -3
- package/dist/index.d.ts +15 -3
- package/dist/index.js +5 -1
- package/dist/next.cjs +47 -1
- package/dist/next.cjs.map +1 -1
- package/dist/next.js +1 -1
- package/dist/react-router.cjs +47 -1
- 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 +1 -1
- package/dist/react-router.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6LS2PKXH.js.map +0 -1
|
@@ -7,7 +7,6 @@ var EMBEDDED_LAUNCH_PARAMS = [
|
|
|
7
7
|
"id_token",
|
|
8
8
|
"link_source",
|
|
9
9
|
"locale",
|
|
10
|
-
"project",
|
|
11
10
|
"protocol",
|
|
12
11
|
"session",
|
|
13
12
|
"shop",
|
|
@@ -111,6 +110,40 @@ function resolveNavigationDestination(payload) {
|
|
|
111
110
|
`${value.pathname}${normalizeSearch(value.search ?? "")}${normalizeHash(value.hash ?? "")}`
|
|
112
111
|
) ?? null;
|
|
113
112
|
}
|
|
113
|
+
function normalizeNavigationItemPath(path) {
|
|
114
|
+
if (!path) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
const trimmedPath = path.trim();
|
|
118
|
+
if (!trimmedPath || /^https?:\/\//i.test(trimmedPath)) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
const normalizedPath = trimmedPath.startsWith("/") ? trimmedPath : "/" + trimmedPath;
|
|
122
|
+
return sanitizeEmbeddedAppPath(normalizedPath) ?? normalizedPath;
|
|
123
|
+
}
|
|
124
|
+
function normalizeBridgeNavigationItem(item) {
|
|
125
|
+
const label = item.label?.trim();
|
|
126
|
+
const path = normalizeNavigationItemPath(item.path);
|
|
127
|
+
if (!label || !path) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
const matchPattern = normalizeNavigationItemPath(item.matchPattern ?? item.path);
|
|
131
|
+
return {
|
|
132
|
+
label,
|
|
133
|
+
path,
|
|
134
|
+
...matchPattern ? { matchPattern } : {},
|
|
135
|
+
...item.exactMatch !== void 0 ? { exactMatch: item.exactMatch } : {}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function normalizeBridgeNavigationItems(items) {
|
|
139
|
+
if (!items?.length) {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
return items.flatMap((item) => {
|
|
143
|
+
const normalizedItem = normalizeBridgeNavigationItem(item);
|
|
144
|
+
return normalizedItem ? [normalizedItem] : [];
|
|
145
|
+
});
|
|
146
|
+
}
|
|
114
147
|
|
|
115
148
|
// src/core.ts
|
|
116
149
|
var DEFAULT_NAMESPACE = "thorcommerce:app-bridge";
|
|
@@ -437,6 +470,7 @@ import {
|
|
|
437
470
|
createContext,
|
|
438
471
|
useContext,
|
|
439
472
|
useEffect,
|
|
473
|
+
useMemo,
|
|
440
474
|
useRef,
|
|
441
475
|
useState
|
|
442
476
|
} from "react";
|
|
@@ -446,6 +480,7 @@ function AppBridgeProvider({
|
|
|
446
480
|
children,
|
|
447
481
|
clientId,
|
|
448
482
|
currentPath,
|
|
483
|
+
navigationItems,
|
|
449
484
|
navigationEventType = "navigation:go",
|
|
450
485
|
navigationUpdateEventType = "navigation:update",
|
|
451
486
|
namespace,
|
|
@@ -459,6 +494,10 @@ function AppBridgeProvider({
|
|
|
459
494
|
}) {
|
|
460
495
|
const [bridge, setBridge] = useState(null);
|
|
461
496
|
const onNavigateRef = useRef(onNavigate);
|
|
497
|
+
const normalizedNavigationItems = useMemo(
|
|
498
|
+
() => normalizeBridgeNavigationItems(navigationItems),
|
|
499
|
+
[navigationItems]
|
|
500
|
+
);
|
|
462
501
|
const sessionTokenCacheRef = useRef(null);
|
|
463
502
|
const projectRef = useRef(readInitialProject(selfWindow));
|
|
464
503
|
const pendingSessionTokenRef = useRef(null);
|
|
@@ -506,6 +545,14 @@ function AppBridgeProvider({
|
|
|
506
545
|
}
|
|
507
546
|
);
|
|
508
547
|
}, [bridge, clientId, readyEventType, readyPayload]);
|
|
548
|
+
useEffect(() => {
|
|
549
|
+
if (!bridge || !bridge.hasTargetWindow()) {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
bridge.send("navigation:items:update", {
|
|
553
|
+
items: normalizedNavigationItems
|
|
554
|
+
});
|
|
555
|
+
}, [bridge, normalizedNavigationItems]);
|
|
509
556
|
useEffect(() => {
|
|
510
557
|
if (!bridge || !bridge.hasTargetWindow() || !currentPath) {
|
|
511
558
|
return;
|
|
@@ -774,10 +821,12 @@ export {
|
|
|
774
821
|
sanitizeEmbeddedAppPath,
|
|
775
822
|
resolveLocalNavigationPath,
|
|
776
823
|
resolveNavigationDestination,
|
|
824
|
+
normalizeBridgeNavigationItem,
|
|
825
|
+
normalizeBridgeNavigationItems,
|
|
777
826
|
isBridgeMessage,
|
|
778
827
|
AppBridge,
|
|
779
828
|
createAppBridge,
|
|
780
829
|
AppBridgeProvider,
|
|
781
830
|
useAppBridge
|
|
782
831
|
};
|
|
783
|
-
//# sourceMappingURL=chunk-
|
|
832
|
+
//# sourceMappingURL=chunk-2JYVH4LK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/navigation.ts","../src/core.ts","../src/react.tsx"],"sourcesContent":["export interface BridgeNavigationGoPayload {\n path?: string;\n href?: string;\n pathname?: string;\n search?: string;\n hash?: string;\n}\n\nexport interface BridgeNavigationRedirectPayload extends BridgeNavigationGoPayload {}\n\nexport interface BridgeNavigationUpdatePayload {\n path: string;\n pathname: string;\n search: string;\n hash: string;\n}\n\nexport interface BridgeNavigationItem {\n path: string;\n label: string;\n matchPattern?: string;\n exactMatch?: boolean;\n}\n\nexport interface BridgeNavigationItemsPayload {\n items: BridgeNavigationItem[];\n}\n\nexport const EMBEDDED_LAUNCH_PARAMS = [\n \"appLoadId\",\n \"embedded\",\n \"hmac\",\n \"host\",\n \"id_token\",\n \"link_source\",\n \"locale\",\n \"protocol\",\n \"session\",\n \"shop\",\n \"tenant\",\n \"timestamp\"\n] as const;\n\nconst NAVIGATION_BASE_URL = \"https://embedded-app.local\";\n\nfunction normalizeSearch(search: string) {\n if (!search) {\n return \"\";\n }\n\n return search.startsWith(\"?\") ? search : `?${search}`;\n}\n\nfunction normalizeHash(hash: string) {\n if (!hash) {\n return \"\";\n }\n\n return hash.startsWith(\"#\") ? hash : `#${hash}`;\n}\n\nexport function buildNavigationUpdatePayload(path: string): BridgeNavigationUpdatePayload {\n const sanitizedPath = sanitizeEmbeddedAppPath(path) ?? path;\n let pathname = sanitizedPath;\n let search = \"\";\n let hash = \"\";\n\n const hashIndex = pathname.indexOf(\"#\");\n if (hashIndex >= 0) {\n hash = pathname.slice(hashIndex);\n pathname = pathname.slice(0, hashIndex);\n }\n\n const searchIndex = pathname.indexOf(\"?\");\n if (searchIndex >= 0) {\n search = pathname.slice(searchIndex);\n pathname = pathname.slice(0, searchIndex);\n }\n\n return {\n path: `${pathname || \"/\"}${search}${hash}`,\n pathname: pathname || \"/\",\n search,\n hash\n };\n}\n\nexport function sanitizeEmbeddedAppPath(path: string | undefined) {\n if (!path) {\n return path;\n }\n\n const trimmedPath = path.trim();\n if (!trimmedPath) {\n return trimmedPath;\n }\n\n const url = new URL(trimmedPath, NAVIGATION_BASE_URL);\n let changed = false;\n\n for (const key of EMBEDDED_LAUNCH_PARAMS) {\n if (url.searchParams.has(key)) {\n url.searchParams.delete(key);\n changed = true;\n }\n }\n\n if (!changed) {\n return trimmedPath;\n }\n\n if (/^https?:\\/\\//i.test(trimmedPath)) {\n return url.toString();\n }\n\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nexport function resolveLocalNavigationPath(\n href: string,\n currentOrigin: string\n): string | null {\n if (!href || href.startsWith(\"#\")) {\n return null;\n }\n\n let destination: URL;\n try {\n destination = new URL(href, currentOrigin);\n } catch {\n return null;\n }\n\n if (destination.origin !== currentOrigin) {\n return null;\n }\n\n return sanitizeEmbeddedAppPath(\n `${destination.pathname}${destination.search}${destination.hash}`\n ) ?? null;\n}\n\nexport function resolveNavigationDestination(payload: unknown): string | null {\n if (typeof payload === \"string\") {\n return sanitizeEmbeddedAppPath(payload) ?? null;\n }\n\n if (!payload || typeof payload !== \"object\") {\n return null;\n }\n\n const value = payload as BridgeNavigationGoPayload;\n\n if (typeof value.path === \"string\" && value.path) {\n return sanitizeEmbeddedAppPath(value.path) ?? null;\n }\n\n if (typeof value.href === \"string\" && value.href) {\n return sanitizeEmbeddedAppPath(value.href) ?? null;\n }\n\n if (typeof value.pathname !== \"string\" || !value.pathname) {\n return null;\n }\n\n return (\n sanitizeEmbeddedAppPath(\n `${value.pathname}${normalizeSearch(value.search ?? \"\")}${normalizeHash(value.hash ?? \"\")}`\n ) ?? null\n );\n}\n\n\nfunction normalizeNavigationItemPath(path: string | undefined) {\n if (!path) {\n return null;\n }\n\n const trimmedPath = path.trim();\n if (!trimmedPath || /^https?:\\/\\//i.test(trimmedPath)) {\n return null;\n }\n\n const normalizedPath = trimmedPath.startsWith(\"/\") ? trimmedPath : \"/\" + trimmedPath;\n return sanitizeEmbeddedAppPath(normalizedPath) ?? normalizedPath;\n}\n\nexport function normalizeBridgeNavigationItem(\n item: BridgeNavigationItem\n): BridgeNavigationItem | null {\n const label = item.label?.trim();\n const path = normalizeNavigationItemPath(item.path);\n\n if (!label || !path) {\n return null;\n }\n\n const matchPattern = normalizeNavigationItemPath(item.matchPattern ?? item.path);\n\n return {\n label,\n path,\n ...(matchPattern ? {matchPattern} : {}),\n ...(item.exactMatch !== undefined ? {exactMatch: item.exactMatch} : {}),\n };\n}\n\nexport function normalizeBridgeNavigationItems(\n items: BridgeNavigationItem[] | undefined\n) {\n if (!items?.length) {\n return [];\n }\n\n return items.flatMap((item) => {\n const normalizedItem = normalizeBridgeNavigationItem(item);\n return normalizedItem ? [normalizedItem] : [];\n });\n}\n","import {\n resolveNavigationDestination,\n type BridgeNavigationGoPayload,\n type BridgeNavigationRedirectPayload\n} from \"./navigation\";\n\nexport type BridgeParticipant = \"embedded-app\" | \"dashboard\" | \"unknown\";\n\nexport type BridgeMessageKind = \"event\" | \"request\" | \"response\";\n\nexport interface BridgeErrorPayload {\n code: string;\n message: string;\n}\n\nexport interface BridgeMessage<TPayload = unknown> {\n namespace: string;\n version: \"1.0\";\n kind: BridgeMessageKind;\n id: string;\n type: string;\n source: BridgeParticipant;\n target?: BridgeParticipant;\n payload?: TPayload;\n replyTo?: string;\n error?: BridgeErrorPayload;\n}\n\nexport interface AppBridgeOptions {\n clientId?: string;\n source?: BridgeParticipant;\n target?: BridgeParticipant;\n namespace?: string;\n targetOrigin?: string;\n allowedOrigins?: string[];\n requestTimeoutMs?: number;\n selfWindow?: Window;\n targetWindow?: Window | null;\n}\n\nexport interface RequestOptions {\n timeoutMs?: number;\n}\n\nexport interface SessionTokenRequest {\n clientId?: string;\n}\n\nexport interface SessionTokenResponse {\n sessionToken?: string;\n idToken: string;\n exp?: number;\n project?: string;\n}\n\nexport interface ReceivedBridgeMessage<TPayload = unknown> extends BridgeMessage<TPayload> {\n origin: string;\n rawEvent: MessageEvent<unknown>;\n}\n\nexport type BridgeEventHandler<TPayload = unknown> = (\n message: ReceivedBridgeMessage<TPayload>\n) => void;\n\nexport type BridgeRequestHandler<TRequest = unknown, TResponse = unknown> = (\n payload: TRequest,\n message: ReceivedBridgeMessage<TRequest>\n) => TResponse | Promise<TResponse>;\n\nexport type Unsubscribe = () => void;\n\nconst DEFAULT_NAMESPACE = \"thorcommerce:app-bridge\";\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_REDIRECT_EVENT_TYPE = \"navigation:redirect\";\n\nfunction createMessageId() {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n\n return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction resolveSelfWindow(explicitWindow?: Window) {\n if (explicitWindow) {\n return explicitWindow;\n }\n\n if (typeof window !== \"undefined\") {\n return window;\n }\n\n return undefined;\n}\n\nfunction resolveTargetWindow(selfWindow: Window | undefined, targetWindow?: Window | null) {\n if (targetWindow) {\n return targetWindow;\n }\n\n if (!selfWindow) {\n return undefined;\n }\n\n if (selfWindow.parent && selfWindow.parent !== selfWindow) {\n return selfWindow.parent;\n }\n\n return undefined;\n}\n\nfunction isDevelopmentEnvironment() {\n const nodeEnv =\n typeof globalThis !== \"undefined\" && \"process\" in globalThis\n ? (\n globalThis as typeof globalThis & {\n process?: { env?: { NODE_ENV?: string } };\n }\n ).process?.env?.NODE_ENV\n : undefined;\n\n if (nodeEnv) {\n return nodeEnv !== \"production\";\n }\n\n return true;\n}\n\nfunction hasAllowedOrigin(origin: string, allowedOrigins?: string[]) {\n if (!allowedOrigins || allowedOrigins.length === 0) {\n return true;\n }\n\n return allowedOrigins.includes(origin);\n}\n\nfunction isMessageTarget(value: unknown): value is Window {\n return !!value && typeof (value as Window).postMessage === \"function\";\n}\n\nfunction omitUndefinedFields<T extends object>(value: T): T {\n return Object.fromEntries(\n Object.entries(value).filter(([, fieldValue]) => fieldValue !== undefined)\n ) as T;\n}\n\nexport function isBridgeMessage<TPayload = unknown>(\n value: unknown,\n namespace = DEFAULT_NAMESPACE\n): value is BridgeMessage<TPayload> {\n if (!value || typeof value !== \"object\") {\n return false;\n }\n\n const message = value as Partial<BridgeMessage<TPayload>>;\n\n return (\n message.namespace === namespace &&\n message.version === \"1.0\" &&\n typeof message.kind === \"string\" &&\n typeof message.id === \"string\" &&\n typeof message.type === \"string\" &&\n typeof message.source === \"string\"\n );\n}\n\nexport class AppBridge {\n private readonly namespace: string;\n private readonly clientId?: string;\n private readonly source: BridgeParticipant;\n private readonly target: BridgeParticipant | undefined;\n private readonly targetOrigin: string;\n private readonly allowedOrigins?: string[];\n private readonly selfWindow?: Window;\n private readonly defaultTimeoutMs: number;\n private targetWindow?: Window;\n private readonly eventHandlers = new Map<string, Set<BridgeEventHandler>>();\n private readonly requestHandlers = new Map<string, BridgeRequestHandler>();\n private readonly pendingRequests = new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n }\n >();\n private readonly messageListener: (event: MessageEvent<unknown>) => void;\n\n constructor(options: AppBridgeOptions = {}) {\n this.namespace = options.namespace ?? DEFAULT_NAMESPACE;\n this.clientId = options.clientId;\n this.source = options.source ?? \"embedded-app\";\n this.target = options.target;\n this.targetOrigin = options.targetOrigin ?? \"*\";\n this.allowedOrigins = options.allowedOrigins;\n this.defaultTimeoutMs = options.requestTimeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.selfWindow = resolveSelfWindow(options.selfWindow);\n this.targetWindow = resolveTargetWindow(this.selfWindow, options.targetWindow);\n this.messageListener = (event) => {\n this.handleMessage(event);\n };\n\n if (!this.selfWindow) {\n throw new Error(\n \"AppBridge requires a browser window. Pass selfWindow explicitly when constructing it outside global window scope.\"\n );\n }\n\n if (this.targetOrigin === \"*\" && isDevelopmentEnvironment()) {\n console.warn(\n 'AppBridge is using \"*\" as targetOrigin. Set targetOrigin explicitly for both the dashboard and embedded app in production.'\n );\n }\n\n this.selfWindow.addEventListener(\"message\", this.messageListener);\n }\n\n setTargetWindow(targetWindow: Window | null) {\n this.targetWindow = targetWindow ?? undefined;\n }\n\n hasTargetWindow() {\n return this.targetWindow !== undefined;\n }\n\n redirect(payload: string | BridgeNavigationRedirectPayload) {\n const destination = resolveNavigationDestination(payload);\n if (!destination) {\n throw new Error(\"AppBridge redirect requires a valid destination.\");\n }\n\n if (!this.targetWindow) {\n this.navigateSelf(destination);\n return;\n }\n\n this.postMessage<BridgeNavigationRedirectPayload>({\n kind: \"event\",\n type: DEFAULT_REDIRECT_EVENT_TYPE,\n payload: typeof payload === \"string\" ? { href: payload } : payload\n });\n }\n\n redirectToRemote(href: string) {\n this.redirect({ href });\n }\n\n redirectToApp(path: string | BridgeNavigationGoPayload) {\n this.redirect(typeof path === \"string\" ? { path } : path);\n }\n\n send<TPayload = unknown>(type: string, payload?: TPayload) {\n this.postMessage({\n kind: \"event\",\n type,\n payload\n });\n }\n\n request<TRequest = unknown, TResponse = unknown>(\n type: string,\n payload?: TRequest,\n options: RequestOptions = {}\n ) {\n const messageId = createMessageId();\n const timeoutMs = options.timeoutMs ?? this.defaultTimeoutMs;\n\n return new Promise<TResponse>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pendingRequests.delete(messageId);\n reject(new Error(`Bridge request timed out for \"${type}\" after ${timeoutMs}ms.`));\n }, timeoutMs);\n\n this.pendingRequests.set(messageId, {\n resolve: (value) => resolve(value as TResponse),\n reject,\n timeoutId\n });\n\n try {\n this.postMessage({\n id: messageId,\n kind: \"request\",\n type,\n payload\n });\n } catch (error) {\n clearTimeout(timeoutId);\n this.pendingRequests.delete(messageId);\n reject(error instanceof Error ? error : new Error(\"Failed to send bridge request.\"));\n }\n });\n }\n\n getSessionToken(\n request: SessionTokenRequest = {},\n options: RequestOptions = {}\n ) {\n const resolvedRequest =\n request.clientId || this.clientId\n ? {\n ...request,\n clientId: request.clientId ?? this.clientId\n }\n : request;\n\n return this.request<SessionTokenRequest, SessionTokenResponse>(\n \"thor:session-token:get\",\n resolvedRequest,\n options\n );\n }\n\n on<TPayload = unknown>(type: string, handler: BridgeEventHandler<TPayload>): Unsubscribe {\n const handlers = this.eventHandlers.get(type) ?? new Set<BridgeEventHandler>();\n handlers.add(handler as BridgeEventHandler);\n this.eventHandlers.set(type, handlers);\n\n return () => {\n handlers.delete(handler as BridgeEventHandler);\n if (handlers.size === 0) {\n this.eventHandlers.delete(type);\n }\n };\n }\n\n onRequest<TRequest = unknown, TResponse = unknown>(\n type: string,\n handler: BridgeRequestHandler<TRequest, TResponse>\n ): Unsubscribe {\n this.requestHandlers.set(type, handler as BridgeRequestHandler);\n\n return () => {\n const registeredHandler = this.requestHandlers.get(type);\n if (registeredHandler === handler) {\n this.requestHandlers.delete(type);\n }\n };\n }\n\n destroy() {\n if (this.selfWindow) {\n this.selfWindow.removeEventListener(\"message\", this.messageListener);\n }\n\n for (const pendingRequest of this.pendingRequests.values()) {\n clearTimeout(pendingRequest.timeoutId);\n pendingRequest.reject(new Error(\"AppBridge destroyed before a response was received.\"));\n }\n\n this.pendingRequests.clear();\n this.eventHandlers.clear();\n this.requestHandlers.clear();\n }\n\n private handleMessage(event: MessageEvent<unknown>) {\n if (!hasAllowedOrigin(event.origin, this.allowedOrigins)) {\n return;\n }\n\n if (!isBridgeMessage(event.data, this.namespace)) {\n return;\n }\n\n const message = event.data;\n\n if (this.target && message.target && message.target !== this.source) {\n return;\n }\n\n const receivedMessage: ReceivedBridgeMessage = {\n ...message,\n origin: event.origin,\n rawEvent: event\n };\n\n if (\n message.kind === \"event\" &&\n message.type === DEFAULT_REDIRECT_EVENT_TYPE &&\n this.handleRedirectMessage(receivedMessage)\n ) {\n return;\n }\n\n if (message.kind === \"response\" && message.replyTo) {\n this.resolvePendingRequest(message.replyTo, message);\n return;\n }\n\n this.emitHandlers(message.type, receivedMessage);\n\n if (message.kind === \"request\") {\n void this.handleRequest(receivedMessage);\n }\n }\n\n private emitHandlers(type: string, message: ReceivedBridgeMessage) {\n const typeHandlers = this.eventHandlers.get(type);\n if (typeHandlers) {\n for (const handler of typeHandlers) {\n handler(message);\n }\n }\n\n if (type === \"*\") {\n return;\n }\n\n const wildcardHandlers = this.eventHandlers.get(\"*\");\n if (wildcardHandlers) {\n for (const handler of wildcardHandlers) {\n handler(message);\n }\n }\n }\n\n private async handleRequest(message: ReceivedBridgeMessage) {\n const handler = this.requestHandlers.get(message.type);\n if (!handler) {\n return;\n }\n\n const replyTarget = isMessageTarget(message.rawEvent.source)\n ? message.rawEvent.source\n : this.targetWindow;\n\n try {\n const payload = await handler(message.payload, message);\n this.postMessage(\n {\n kind: \"response\",\n type: message.type,\n payload,\n replyTo: message.id\n },\n replyTarget\n );\n } catch (error) {\n const bridgeError =\n error instanceof Error\n ? { code: \"request_handler_error\", message: error.message }\n : { code: \"request_handler_error\", message: \"Unknown request handler error.\" };\n\n this.postMessage(\n {\n kind: \"response\",\n type: message.type,\n error: bridgeError,\n replyTo: message.id\n },\n replyTarget\n );\n }\n }\n\n private resolvePendingRequest(messageId: string, message: BridgeMessage) {\n const pendingRequest = this.pendingRequests.get(messageId);\n if (!pendingRequest) {\n return;\n }\n\n clearTimeout(pendingRequest.timeoutId);\n this.pendingRequests.delete(messageId);\n\n if (message.error) {\n pendingRequest.reject(new Error(`${message.error.code}: ${message.error.message}`));\n return;\n }\n\n pendingRequest.resolve(message.payload);\n }\n\n private postMessage<TPayload = unknown>(\n partialMessage: Pick<BridgeMessage<TPayload>, \"kind\" | \"type\"> &\n Partial<Omit<BridgeMessage<TPayload>, \"namespace\" | \"version\" | \"source\">>,\n targetWindowOverride?: Window\n ) {\n const targetWindow = targetWindowOverride ?? this.targetWindow;\n if (!targetWindow) {\n throw new Error(\n \"AppBridge could not resolve a target window. Pass targetWindow explicitly or call setTargetWindow().\"\n );\n }\n\n const message = omitUndefinedFields({\n namespace: this.namespace,\n version: \"1.0\",\n id: partialMessage.id ?? createMessageId(),\n kind: partialMessage.kind,\n type: partialMessage.type,\n source: this.source,\n target: partialMessage.target ?? this.target,\n payload: partialMessage.payload,\n replyTo: partialMessage.replyTo,\n error: partialMessage.error\n }) as BridgeMessage<TPayload>;\n\n targetWindow.postMessage(message, this.targetOrigin);\n }\n\n private handleRedirectMessage(message: ReceivedBridgeMessage): boolean {\n const destination = resolveNavigationDestination(message.payload);\n if (!destination) {\n return false;\n }\n\n this.navigateSelf(destination);\n return true;\n }\n\n private navigateSelf(destination: string) {\n if (!this.selfWindow) {\n throw new Error(\"AppBridge could not resolve a browser window for redirect.\");\n }\n\n this.selfWindow.location.assign(destination);\n }\n}\n\nexport function createAppBridge(options: AppBridgeOptions = {}) {\n return new AppBridge(options);\n}\n","import {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type MutableRefObject,\n type ReactNode\n} from \"react\";\n\nimport {\n createAppBridge,\n type AppBridge,\n type AppBridgeOptions,\n type ReceivedBridgeMessage\n} from \"./core\";\nimport {\n buildNavigationUpdatePayload,\n normalizeBridgeNavigationItems,\n resolveLocalNavigationPath,\n resolveNavigationDestination,\n sanitizeEmbeddedAppPath,\n type BridgeNavigationGoPayload,\n type BridgeNavigationItem\n} from \"./navigation\";\n\nconst AppBridgeContext = createContext<AppBridge | null>(null);\n\nexport interface AppBridgeProviderProps\n extends Omit<AppBridgeOptions, \"source\" | \"target\" | \"allowedOrigins\"> {\n children: ReactNode;\n clientId: string;\n readyEventType?: string;\n readyPayload?: unknown;\n currentPath?: string | null;\n navigationItems?: BridgeNavigationItem[];\n navigationEventType?: string;\n navigationUpdateEventType?: string;\n onNavigate?: (\n path: string,\n message?: ReceivedBridgeMessage<BridgeNavigationGoPayload>\n ) => void;\n}\n\nexport function AppBridgeProvider({\n children,\n clientId,\n currentPath,\n navigationItems,\n navigationEventType = \"navigation:go\",\n navigationUpdateEventType = \"navigation:update\",\n namespace,\n onNavigate,\n readyEventType = \"app:ready\",\n readyPayload,\n requestTimeoutMs,\n selfWindow,\n targetOrigin,\n targetWindow\n}: AppBridgeProviderProps) {\n const [bridge, setBridge] = useState<AppBridge | null>(null);\n const onNavigateRef = useRef(onNavigate);\n const normalizedNavigationItems = useMemo(\n () => normalizeBridgeNavigationItems(navigationItems),\n [navigationItems]\n );\n const sessionTokenCacheRef = useRef<{\n token: string;\n expiresAt?: number;\n } | null>(null);\n const projectRef = useRef<string | null>(readInitialProject(selfWindow));\n const pendingSessionTokenRef = useRef<Promise<string> | null>(null);\n\n useEffect(() => {\n onNavigateRef.current = onNavigate;\n }, [onNavigate]);\n\n useEffect(() => {\n if (typeof window === \"undefined\" && !selfWindow) {\n return;\n }\n\n const resolvedTargetOrigin = targetOrigin ?? getReferrerOrigin(selfWindow);\n const resolvedAllowedOrigins = resolvedTargetOrigin\n ? [resolvedTargetOrigin]\n : undefined;\n\n const nextBridge = createAppBridge({\n allowedOrigins: resolvedAllowedOrigins,\n clientId,\n namespace,\n requestTimeoutMs,\n selfWindow,\n source: \"embedded-app\",\n target: \"dashboard\",\n targetOrigin: resolvedTargetOrigin,\n targetWindow\n });\n\n setBridge(nextBridge);\n\n return () => {\n setBridge((currentBridge) => (currentBridge === nextBridge ? null : currentBridge));\n nextBridge.destroy();\n };\n }, [\n clientId,\n namespace,\n requestTimeoutMs,\n selfWindow,\n targetOrigin,\n targetWindow\n ]);\n\n useEffect(() => {\n if (!bridge || !bridge.hasTargetWindow()) {\n return;\n }\n\n bridge.send(\n readyEventType,\n readyPayload ?? {\n clientId\n }\n );\n }, [bridge, clientId, readyEventType, readyPayload]);\n\n useEffect(() => {\n if (!bridge || !bridge.hasTargetWindow()) {\n return;\n }\n\n bridge.send(\"navigation:items:update\", {\n items: normalizedNavigationItems\n });\n }, [bridge, normalizedNavigationItems]);\n\n useEffect(() => {\n if (!bridge || !bridge.hasTargetWindow() || !currentPath) {\n return;\n }\n\n bridge.send(navigationUpdateEventType, buildNavigationUpdatePayload(currentPath));\n }, [bridge, currentPath, navigationUpdateEventType]);\n\n useEffect(() => {\n if (!bridge || !onNavigate) {\n return;\n }\n\n return bridge.on<BridgeNavigationGoPayload>(navigationEventType, (message) => {\n const destination = resolveNavigationDestination(message.payload);\n if (!destination) {\n return;\n }\n\n onNavigateRef.current?.(destination, message);\n });\n }, [bridge, navigationEventType, onNavigate]);\n\n useEffect(() => {\n if (\n !bridge ||\n !onNavigate ||\n typeof document === \"undefined\" ||\n typeof window === \"undefined\"\n ) {\n return;\n }\n\n const handleLocalNavigation = (path: string) => {\n const sanitizedPath = sanitizeEmbeddedAppPath(path);\n if (!sanitizedPath) {\n return;\n }\n\n onNavigateRef.current?.(sanitizedPath);\n };\n\n const handleDocumentClick = (event: MouseEvent) => {\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.altKey ||\n event.ctrlKey ||\n event.shiftKey\n ) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Element)) {\n return;\n }\n\n const anchor = target.closest(\"a[href]\");\n if (!(anchor instanceof HTMLAnchorElement)) {\n return;\n }\n\n if (anchor.hasAttribute(\"download\")) {\n return;\n }\n\n const targetWindow = anchor.target.toLowerCase();\n const href = anchor.getAttribute(\"href\");\n if (!href) {\n return;\n }\n\n if (targetWindow === \"_top\" || targetWindow === \"_parent\") {\n event.preventDefault();\n bridge.redirectToRemote(anchor.href);\n return;\n }\n\n if (targetWindow && targetWindow !== \"_self\") {\n return;\n }\n\n const nextPath = resolveLocalNavigationPath(href, window.location.origin);\n if (!nextPath) {\n return;\n }\n\n event.preventDefault();\n handleLocalNavigation(nextPath);\n };\n\n const originalOpen = window.open.bind(window);\n window.open = (url?: string | URL, target?: string, features?: string) => {\n if (url == null) {\n return originalOpen(url, target, features);\n }\n\n const href = typeof url === \"string\" ? url : url.toString();\n const targetName = (target ?? \"\").toLowerCase();\n\n if (targetName === \"_top\" || targetName === \"_parent\") {\n bridge.redirectToRemote(new URL(href, window.location.href).toString());\n return null;\n }\n\n if (!targetName || targetName === \"_self\") {\n const nextPath = resolveLocalNavigationPath(href, window.location.origin);\n if (nextPath) {\n handleLocalNavigation(nextPath);\n return window;\n }\n }\n\n return originalOpen(url, target, features);\n };\n\n document.addEventListener(\"click\", handleDocumentClick, true);\n\n return () => {\n document.removeEventListener(\"click\", handleDocumentClick, true);\n window.open = originalOpen;\n };\n }, [bridge, onNavigate]);\n\n useEffect(() => {\n if (!bridge || typeof window === \"undefined\") {\n return;\n }\n\n const originalFetch = globalThis.fetch.bind(globalThis);\n\n const interceptedFetch = async (input: RequestInfo | URL, init?: RequestInit) => {\n if (!shouldAttachSessionToken(input)) {\n return originalFetch(input, init);\n }\n\n const existingAuthorization = getExistingAuthorization(input, init);\n if (existingAuthorization) {\n return originalFetch(input, init);\n }\n\n const nextHeaders = new Headers(\n input instanceof Request ? input.headers : init?.headers\n );\n\n if (projectRef.current && !nextHeaders.has(\"X-Thor-Project\")) {\n nextHeaders.set(\"X-Thor-Project\", projectRef.current);\n }\n\n try {\n const sessionToken = await getSessionToken({\n bridge,\n clientId,\n pendingSessionTokenRef,\n projectRef,\n sessionTokenCacheRef\n });\n\n nextHeaders.set(\"Authorization\", `Bearer ${sessionToken}`);\n } catch {\n if (!projectRef.current) {\n throw new Error(\"Missing Thor embedded session token\");\n }\n }\n\n if (!nextHeaders.has(\"X-Requested-With\")) {\n nextHeaders.set(\"X-Requested-With\", \"XMLHttpRequest\");\n }\n\n if (input instanceof Request) {\n return originalFetch(\n new Request(input, {\n headers: nextHeaders\n })\n );\n }\n\n return originalFetch(input, {\n ...init,\n headers: nextHeaders\n });\n };\n\n globalThis.fetch = interceptedFetch;\n window.fetch = interceptedFetch;\n\n return () => {\n globalThis.fetch = originalFetch;\n window.fetch = originalFetch;\n };\n }, [bridge, clientId]);\n\n return <AppBridgeContext.Provider value={bridge}>{children}</AppBridgeContext.Provider>;\n}\n\nexport function useAppBridge() {\n return useContext(AppBridgeContext);\n}\n\nfunction getReferrerOrigin(explicitWindow?: Window) {\n const resolvedWindow = explicitWindow ?? (typeof window !== \"undefined\" ? window : undefined);\n const referrer = resolvedWindow?.document?.referrer;\n\n if (!referrer) {\n return undefined;\n }\n\n try {\n return new URL(referrer).origin;\n } catch {\n return undefined;\n }\n}\n\nasync function getSessionToken({\n bridge,\n clientId,\n pendingSessionTokenRef,\n projectRef,\n sessionTokenCacheRef\n}: {\n bridge: AppBridge;\n clientId: string;\n pendingSessionTokenRef: MutableRefObject<Promise<string> | null>;\n projectRef: MutableRefObject<string | null>;\n sessionTokenCacheRef: MutableRefObject<{\n token: string;\n expiresAt?: number;\n } | null>;\n}) {\n const cachedToken = sessionTokenCacheRef.current;\n if (cachedToken && !isExpired(cachedToken.expiresAt)) {\n return cachedToken.token;\n }\n\n if (pendingSessionTokenRef.current) {\n return pendingSessionTokenRef.current;\n }\n\n const pendingToken = bridge\n .getSessionToken({ clientId })\n .then((response) => {\n const token = response.sessionToken ?? response.idToken;\n if (!token) {\n throw new Error(\"Missing Thor embedded session token\");\n }\n\n if (response.project) {\n projectRef.current = response.project;\n }\n\n sessionTokenCacheRef.current = {\n token,\n expiresAt: normalizeTokenExpiry(token, response.exp)\n };\n pendingSessionTokenRef.current = null;\n\n return token;\n })\n .catch((error) => {\n pendingSessionTokenRef.current = null;\n throw error;\n });\n\n pendingSessionTokenRef.current = pendingToken;\n return pendingToken;\n}\n\nfunction shouldAttachSessionToken(input: RequestInfo | URL) {\n if (typeof window === \"undefined\") {\n return false;\n }\n\n const requestUrl = resolveRequestUrl(input);\n return requestUrl.origin === window.location.origin;\n}\n\nfunction resolveRequestUrl(input: RequestInfo | URL) {\n if (input instanceof Request) {\n return new URL(input.url);\n }\n\n if (input instanceof URL) {\n return input;\n }\n\n return new URL(input, window.location.href);\n}\n\nfunction getExistingAuthorization(input: RequestInfo | URL, init?: RequestInit) {\n if (input instanceof Request && input.headers.has(\"Authorization\")) {\n return input.headers.get(\"Authorization\");\n }\n\n if (!init?.headers) {\n return null;\n }\n\n return new Headers(init.headers).get(\"Authorization\");\n}\n\nfunction normalizeTokenExpiry(token: string, explicitExp?: number) {\n const tokenExp = explicitExp ?? decodeJwtExpiry(token);\n return tokenExp ? tokenExp * 1000 : undefined;\n}\n\nfunction decodeJwtExpiry(token: string) {\n const [, payload] = token.split(\".\");\n if (!payload || typeof window === \"undefined\") {\n return undefined;\n }\n\n try {\n const normalized = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized.padEnd(\n normalized.length + ((4 - (normalized.length % 4)) % 4),\n \"=\"\n );\n const json = JSON.parse(window.atob(padded)) as { exp?: unknown };\n\n return typeof json.exp === \"number\" ? json.exp : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isExpired(expiresAt?: number) {\n if (!expiresAt) {\n return false;\n }\n\n return Date.now() >= expiresAt - 5_000;\n}\n\nfunction readInitialProject(explicitWindow?: Window) {\n const resolvedWindow = explicitWindow ?? (typeof window !== \"undefined\" ? window : undefined);\n if (!resolvedWindow) {\n return null;\n }\n\n try {\n const url = new URL(resolvedWindow.location.href);\n return url.searchParams.get(\"project\");\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":["targetWindow"]}
|
package/dist/index.cjs
CHANGED
|
@@ -26,6 +26,8 @@ __export(index_exports, {
|
|
|
26
26
|
buildNavigationUpdatePayload: () => buildNavigationUpdatePayload,
|
|
27
27
|
createAppBridge: () => createAppBridge,
|
|
28
28
|
isBridgeMessage: () => isBridgeMessage,
|
|
29
|
+
normalizeBridgeNavigationItem: () => normalizeBridgeNavigationItem,
|
|
30
|
+
normalizeBridgeNavigationItems: () => normalizeBridgeNavigationItems,
|
|
29
31
|
resolveLocalNavigationPath: () => resolveLocalNavigationPath,
|
|
30
32
|
resolveNavigationDestination: () => resolveNavigationDestination,
|
|
31
33
|
sanitizeEmbeddedAppPath: () => sanitizeEmbeddedAppPath,
|
|
@@ -42,7 +44,6 @@ var EMBEDDED_LAUNCH_PARAMS = [
|
|
|
42
44
|
"id_token",
|
|
43
45
|
"link_source",
|
|
44
46
|
"locale",
|
|
45
|
-
"project",
|
|
46
47
|
"protocol",
|
|
47
48
|
"session",
|
|
48
49
|
"shop",
|
|
@@ -146,6 +147,40 @@ function resolveNavigationDestination(payload) {
|
|
|
146
147
|
`${value.pathname}${normalizeSearch(value.search ?? "")}${normalizeHash(value.hash ?? "")}`
|
|
147
148
|
) ?? null;
|
|
148
149
|
}
|
|
150
|
+
function normalizeNavigationItemPath(path) {
|
|
151
|
+
if (!path) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
const trimmedPath = path.trim();
|
|
155
|
+
if (!trimmedPath || /^https?:\/\//i.test(trimmedPath)) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
const normalizedPath = trimmedPath.startsWith("/") ? trimmedPath : "/" + trimmedPath;
|
|
159
|
+
return sanitizeEmbeddedAppPath(normalizedPath) ?? normalizedPath;
|
|
160
|
+
}
|
|
161
|
+
function normalizeBridgeNavigationItem(item) {
|
|
162
|
+
const label = item.label?.trim();
|
|
163
|
+
const path = normalizeNavigationItemPath(item.path);
|
|
164
|
+
if (!label || !path) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
const matchPattern = normalizeNavigationItemPath(item.matchPattern ?? item.path);
|
|
168
|
+
return {
|
|
169
|
+
label,
|
|
170
|
+
path,
|
|
171
|
+
...matchPattern ? { matchPattern } : {},
|
|
172
|
+
...item.exactMatch !== void 0 ? { exactMatch: item.exactMatch } : {}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function normalizeBridgeNavigationItems(items) {
|
|
176
|
+
if (!items?.length) {
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
return items.flatMap((item) => {
|
|
180
|
+
const normalizedItem = normalizeBridgeNavigationItem(item);
|
|
181
|
+
return normalizedItem ? [normalizedItem] : [];
|
|
182
|
+
});
|
|
183
|
+
}
|
|
149
184
|
|
|
150
185
|
// src/core.ts
|
|
151
186
|
var DEFAULT_NAMESPACE = "thorcommerce:app-bridge";
|
|
@@ -475,6 +510,7 @@ function AppBridgeProvider({
|
|
|
475
510
|
children,
|
|
476
511
|
clientId,
|
|
477
512
|
currentPath,
|
|
513
|
+
navigationItems,
|
|
478
514
|
navigationEventType = "navigation:go",
|
|
479
515
|
navigationUpdateEventType = "navigation:update",
|
|
480
516
|
namespace,
|
|
@@ -488,6 +524,10 @@ function AppBridgeProvider({
|
|
|
488
524
|
}) {
|
|
489
525
|
const [bridge, setBridge] = (0, import_react.useState)(null);
|
|
490
526
|
const onNavigateRef = (0, import_react.useRef)(onNavigate);
|
|
527
|
+
const normalizedNavigationItems = (0, import_react.useMemo)(
|
|
528
|
+
() => normalizeBridgeNavigationItems(navigationItems),
|
|
529
|
+
[navigationItems]
|
|
530
|
+
);
|
|
491
531
|
const sessionTokenCacheRef = (0, import_react.useRef)(null);
|
|
492
532
|
const projectRef = (0, import_react.useRef)(readInitialProject(selfWindow));
|
|
493
533
|
const pendingSessionTokenRef = (0, import_react.useRef)(null);
|
|
@@ -535,6 +575,14 @@ function AppBridgeProvider({
|
|
|
535
575
|
}
|
|
536
576
|
);
|
|
537
577
|
}, [bridge, clientId, readyEventType, readyPayload]);
|
|
578
|
+
(0, import_react.useEffect)(() => {
|
|
579
|
+
if (!bridge || !bridge.hasTargetWindow()) {
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
bridge.send("navigation:items:update", {
|
|
583
|
+
items: normalizedNavigationItems
|
|
584
|
+
});
|
|
585
|
+
}, [bridge, normalizedNavigationItems]);
|
|
538
586
|
(0, import_react.useEffect)(() => {
|
|
539
587
|
if (!bridge || !bridge.hasTargetWindow() || !currentPath) {
|
|
540
588
|
return;
|
|
@@ -804,6 +852,8 @@ function readInitialProject(explicitWindow) {
|
|
|
804
852
|
buildNavigationUpdatePayload,
|
|
805
853
|
createAppBridge,
|
|
806
854
|
isBridgeMessage,
|
|
855
|
+
normalizeBridgeNavigationItem,
|
|
856
|
+
normalizeBridgeNavigationItems,
|
|
807
857
|
resolveLocalNavigationPath,
|
|
808
858
|
resolveNavigationDestination,
|
|
809
859
|
sanitizeEmbeddedAppPath,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/navigation.ts","../src/core.ts","../src/react.tsx"],"sourcesContent":["export * from \"./core\";\nexport * from \"./navigation\";\nexport * from \"./react\";\n","export interface BridgeNavigationGoPayload {\n path?: string;\n href?: string;\n pathname?: string;\n search?: string;\n hash?: string;\n}\n\nexport interface BridgeNavigationRedirectPayload extends BridgeNavigationGoPayload {}\n\nexport interface BridgeNavigationUpdatePayload {\n path: string;\n pathname: string;\n search: string;\n hash: string;\n}\n\nexport const EMBEDDED_LAUNCH_PARAMS = [\n \"appLoadId\",\n \"embedded\",\n \"hmac\",\n \"host\",\n \"id_token\",\n \"link_source\",\n \"locale\",\n \"project\",\n \"protocol\",\n \"session\",\n \"shop\",\n \"tenant\",\n \"timestamp\"\n] as const;\n\nconst NAVIGATION_BASE_URL = \"https://embedded-app.local\";\n\nfunction normalizeSearch(search: string) {\n if (!search) {\n return \"\";\n }\n\n return search.startsWith(\"?\") ? search : `?${search}`;\n}\n\nfunction normalizeHash(hash: string) {\n if (!hash) {\n return \"\";\n }\n\n return hash.startsWith(\"#\") ? hash : `#${hash}`;\n}\n\nexport function buildNavigationUpdatePayload(path: string): BridgeNavigationUpdatePayload {\n const sanitizedPath = sanitizeEmbeddedAppPath(path) ?? path;\n let pathname = sanitizedPath;\n let search = \"\";\n let hash = \"\";\n\n const hashIndex = pathname.indexOf(\"#\");\n if (hashIndex >= 0) {\n hash = pathname.slice(hashIndex);\n pathname = pathname.slice(0, hashIndex);\n }\n\n const searchIndex = pathname.indexOf(\"?\");\n if (searchIndex >= 0) {\n search = pathname.slice(searchIndex);\n pathname = pathname.slice(0, searchIndex);\n }\n\n return {\n path: `${pathname || \"/\"}${search}${hash}`,\n pathname: pathname || \"/\",\n search,\n hash\n };\n}\n\nexport function sanitizeEmbeddedAppPath(path: string | undefined) {\n if (!path) {\n return path;\n }\n\n const trimmedPath = path.trim();\n if (!trimmedPath) {\n return trimmedPath;\n }\n\n const url = new URL(trimmedPath, NAVIGATION_BASE_URL);\n let changed = false;\n\n for (const key of EMBEDDED_LAUNCH_PARAMS) {\n if (url.searchParams.has(key)) {\n url.searchParams.delete(key);\n changed = true;\n }\n }\n\n if (!changed) {\n return trimmedPath;\n }\n\n if (/^https?:\\/\\//i.test(trimmedPath)) {\n return url.toString();\n }\n\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nexport function resolveLocalNavigationPath(\n href: string,\n currentOrigin: string\n): string | null {\n if (!href || href.startsWith(\"#\")) {\n return null;\n }\n\n let destination: URL;\n try {\n destination = new URL(href, currentOrigin);\n } catch {\n return null;\n }\n\n if (destination.origin !== currentOrigin) {\n return null;\n }\n\n return sanitizeEmbeddedAppPath(\n `${destination.pathname}${destination.search}${destination.hash}`\n ) ?? null;\n}\n\nexport function resolveNavigationDestination(payload: unknown): string | null {\n if (typeof payload === \"string\") {\n return sanitizeEmbeddedAppPath(payload) ?? null;\n }\n\n if (!payload || typeof payload !== \"object\") {\n return null;\n }\n\n const value = payload as BridgeNavigationGoPayload;\n\n if (typeof value.path === \"string\" && value.path) {\n return sanitizeEmbeddedAppPath(value.path) ?? null;\n }\n\n if (typeof value.href === \"string\" && value.href) {\n return sanitizeEmbeddedAppPath(value.href) ?? null;\n }\n\n if (typeof value.pathname !== \"string\" || !value.pathname) {\n return null;\n }\n\n return (\n sanitizeEmbeddedAppPath(\n `${value.pathname}${normalizeSearch(value.search ?? \"\")}${normalizeHash(value.hash ?? \"\")}`\n ) ?? null\n );\n}\n","import {\n resolveNavigationDestination,\n type BridgeNavigationGoPayload,\n type BridgeNavigationRedirectPayload\n} from \"./navigation\";\n\nexport type BridgeParticipant = \"embedded-app\" | \"dashboard\" | \"unknown\";\n\nexport type BridgeMessageKind = \"event\" | \"request\" | \"response\";\n\nexport interface BridgeErrorPayload {\n code: string;\n message: string;\n}\n\nexport interface BridgeMessage<TPayload = unknown> {\n namespace: string;\n version: \"1.0\";\n kind: BridgeMessageKind;\n id: string;\n type: string;\n source: BridgeParticipant;\n target?: BridgeParticipant;\n payload?: TPayload;\n replyTo?: string;\n error?: BridgeErrorPayload;\n}\n\nexport interface AppBridgeOptions {\n clientId?: string;\n source?: BridgeParticipant;\n target?: BridgeParticipant;\n namespace?: string;\n targetOrigin?: string;\n allowedOrigins?: string[];\n requestTimeoutMs?: number;\n selfWindow?: Window;\n targetWindow?: Window | null;\n}\n\nexport interface RequestOptions {\n timeoutMs?: number;\n}\n\nexport interface SessionTokenRequest {\n clientId?: string;\n}\n\nexport interface SessionTokenResponse {\n sessionToken?: string;\n idToken: string;\n exp?: number;\n project?: string;\n}\n\nexport interface ReceivedBridgeMessage<TPayload = unknown> extends BridgeMessage<TPayload> {\n origin: string;\n rawEvent: MessageEvent<unknown>;\n}\n\nexport type BridgeEventHandler<TPayload = unknown> = (\n message: ReceivedBridgeMessage<TPayload>\n) => void;\n\nexport type BridgeRequestHandler<TRequest = unknown, TResponse = unknown> = (\n payload: TRequest,\n message: ReceivedBridgeMessage<TRequest>\n) => TResponse | Promise<TResponse>;\n\nexport type Unsubscribe = () => void;\n\nconst DEFAULT_NAMESPACE = \"thorcommerce:app-bridge\";\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_REDIRECT_EVENT_TYPE = \"navigation:redirect\";\n\nfunction createMessageId() {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n\n return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction resolveSelfWindow(explicitWindow?: Window) {\n if (explicitWindow) {\n return explicitWindow;\n }\n\n if (typeof window !== \"undefined\") {\n return window;\n }\n\n return undefined;\n}\n\nfunction resolveTargetWindow(selfWindow: Window | undefined, targetWindow?: Window | null) {\n if (targetWindow) {\n return targetWindow;\n }\n\n if (!selfWindow) {\n return undefined;\n }\n\n if (selfWindow.parent && selfWindow.parent !== selfWindow) {\n return selfWindow.parent;\n }\n\n return undefined;\n}\n\nfunction isDevelopmentEnvironment() {\n const nodeEnv =\n typeof globalThis !== \"undefined\" && \"process\" in globalThis\n ? (\n globalThis as typeof globalThis & {\n process?: { env?: { NODE_ENV?: string } };\n }\n ).process?.env?.NODE_ENV\n : undefined;\n\n if (nodeEnv) {\n return nodeEnv !== \"production\";\n }\n\n return true;\n}\n\nfunction hasAllowedOrigin(origin: string, allowedOrigins?: string[]) {\n if (!allowedOrigins || allowedOrigins.length === 0) {\n return true;\n }\n\n return allowedOrigins.includes(origin);\n}\n\nfunction isMessageTarget(value: unknown): value is Window {\n return !!value && typeof (value as Window).postMessage === \"function\";\n}\n\nfunction omitUndefinedFields<T extends object>(value: T): T {\n return Object.fromEntries(\n Object.entries(value).filter(([, fieldValue]) => fieldValue !== undefined)\n ) as T;\n}\n\nexport function isBridgeMessage<TPayload = unknown>(\n value: unknown,\n namespace = DEFAULT_NAMESPACE\n): value is BridgeMessage<TPayload> {\n if (!value || typeof value !== \"object\") {\n return false;\n }\n\n const message = value as Partial<BridgeMessage<TPayload>>;\n\n return (\n message.namespace === namespace &&\n message.version === \"1.0\" &&\n typeof message.kind === \"string\" &&\n typeof message.id === \"string\" &&\n typeof message.type === \"string\" &&\n typeof message.source === \"string\"\n );\n}\n\nexport class AppBridge {\n private readonly namespace: string;\n private readonly clientId?: string;\n private readonly source: BridgeParticipant;\n private readonly target: BridgeParticipant | undefined;\n private readonly targetOrigin: string;\n private readonly allowedOrigins?: string[];\n private readonly selfWindow?: Window;\n private readonly defaultTimeoutMs: number;\n private targetWindow?: Window;\n private readonly eventHandlers = new Map<string, Set<BridgeEventHandler>>();\n private readonly requestHandlers = new Map<string, BridgeRequestHandler>();\n private readonly pendingRequests = new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n }\n >();\n private readonly messageListener: (event: MessageEvent<unknown>) => void;\n\n constructor(options: AppBridgeOptions = {}) {\n this.namespace = options.namespace ?? DEFAULT_NAMESPACE;\n this.clientId = options.clientId;\n this.source = options.source ?? \"embedded-app\";\n this.target = options.target;\n this.targetOrigin = options.targetOrigin ?? \"*\";\n this.allowedOrigins = options.allowedOrigins;\n this.defaultTimeoutMs = options.requestTimeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.selfWindow = resolveSelfWindow(options.selfWindow);\n this.targetWindow = resolveTargetWindow(this.selfWindow, options.targetWindow);\n this.messageListener = (event) => {\n this.handleMessage(event);\n };\n\n if (!this.selfWindow) {\n throw new Error(\n \"AppBridge requires a browser window. Pass selfWindow explicitly when constructing it outside global window scope.\"\n );\n }\n\n if (this.targetOrigin === \"*\" && isDevelopmentEnvironment()) {\n console.warn(\n 'AppBridge is using \"*\" as targetOrigin. Set targetOrigin explicitly for both the dashboard and embedded app in production.'\n );\n }\n\n this.selfWindow.addEventListener(\"message\", this.messageListener);\n }\n\n setTargetWindow(targetWindow: Window | null) {\n this.targetWindow = targetWindow ?? undefined;\n }\n\n hasTargetWindow() {\n return this.targetWindow !== undefined;\n }\n\n redirect(payload: string | BridgeNavigationRedirectPayload) {\n const destination = resolveNavigationDestination(payload);\n if (!destination) {\n throw new Error(\"AppBridge redirect requires a valid destination.\");\n }\n\n if (!this.targetWindow) {\n this.navigateSelf(destination);\n return;\n }\n\n this.postMessage<BridgeNavigationRedirectPayload>({\n kind: \"event\",\n type: DEFAULT_REDIRECT_EVENT_TYPE,\n payload: typeof payload === \"string\" ? { href: payload } : payload\n });\n }\n\n redirectToRemote(href: string) {\n this.redirect({ href });\n }\n\n redirectToApp(path: string | BridgeNavigationGoPayload) {\n this.redirect(typeof path === \"string\" ? { path } : path);\n }\n\n send<TPayload = unknown>(type: string, payload?: TPayload) {\n this.postMessage({\n kind: \"event\",\n type,\n payload\n });\n }\n\n request<TRequest = unknown, TResponse = unknown>(\n type: string,\n payload?: TRequest,\n options: RequestOptions = {}\n ) {\n const messageId = createMessageId();\n const timeoutMs = options.timeoutMs ?? this.defaultTimeoutMs;\n\n return new Promise<TResponse>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pendingRequests.delete(messageId);\n reject(new Error(`Bridge request timed out for \"${type}\" after ${timeoutMs}ms.`));\n }, timeoutMs);\n\n this.pendingRequests.set(messageId, {\n resolve: (value) => resolve(value as TResponse),\n reject,\n timeoutId\n });\n\n try {\n this.postMessage({\n id: messageId,\n kind: \"request\",\n type,\n payload\n });\n } catch (error) {\n clearTimeout(timeoutId);\n this.pendingRequests.delete(messageId);\n reject(error instanceof Error ? error : new Error(\"Failed to send bridge request.\"));\n }\n });\n }\n\n getSessionToken(\n request: SessionTokenRequest = {},\n options: RequestOptions = {}\n ) {\n const resolvedRequest =\n request.clientId || this.clientId\n ? {\n ...request,\n clientId: request.clientId ?? this.clientId\n }\n : request;\n\n return this.request<SessionTokenRequest, SessionTokenResponse>(\n \"thor:session-token:get\",\n resolvedRequest,\n options\n );\n }\n\n on<TPayload = unknown>(type: string, handler: BridgeEventHandler<TPayload>): Unsubscribe {\n const handlers = this.eventHandlers.get(type) ?? new Set<BridgeEventHandler>();\n handlers.add(handler as BridgeEventHandler);\n this.eventHandlers.set(type, handlers);\n\n return () => {\n handlers.delete(handler as BridgeEventHandler);\n if (handlers.size === 0) {\n this.eventHandlers.delete(type);\n }\n };\n }\n\n onRequest<TRequest = unknown, TResponse = unknown>(\n type: string,\n handler: BridgeRequestHandler<TRequest, TResponse>\n ): Unsubscribe {\n this.requestHandlers.set(type, handler as BridgeRequestHandler);\n\n return () => {\n const registeredHandler = this.requestHandlers.get(type);\n if (registeredHandler === handler) {\n this.requestHandlers.delete(type);\n }\n };\n }\n\n destroy() {\n if (this.selfWindow) {\n this.selfWindow.removeEventListener(\"message\", this.messageListener);\n }\n\n for (const pendingRequest of this.pendingRequests.values()) {\n clearTimeout(pendingRequest.timeoutId);\n pendingRequest.reject(new Error(\"AppBridge destroyed before a response was received.\"));\n }\n\n this.pendingRequests.clear();\n this.eventHandlers.clear();\n this.requestHandlers.clear();\n }\n\n private handleMessage(event: MessageEvent<unknown>) {\n if (!hasAllowedOrigin(event.origin, this.allowedOrigins)) {\n return;\n }\n\n if (!isBridgeMessage(event.data, this.namespace)) {\n return;\n }\n\n const message = event.data;\n\n if (this.target && message.target && message.target !== this.source) {\n return;\n }\n\n const receivedMessage: ReceivedBridgeMessage = {\n ...message,\n origin: event.origin,\n rawEvent: event\n };\n\n if (\n message.kind === \"event\" &&\n message.type === DEFAULT_REDIRECT_EVENT_TYPE &&\n this.handleRedirectMessage(receivedMessage)\n ) {\n return;\n }\n\n if (message.kind === \"response\" && message.replyTo) {\n this.resolvePendingRequest(message.replyTo, message);\n return;\n }\n\n this.emitHandlers(message.type, receivedMessage);\n\n if (message.kind === \"request\") {\n void this.handleRequest(receivedMessage);\n }\n }\n\n private emitHandlers(type: string, message: ReceivedBridgeMessage) {\n const typeHandlers = this.eventHandlers.get(type);\n if (typeHandlers) {\n for (const handler of typeHandlers) {\n handler(message);\n }\n }\n\n if (type === \"*\") {\n return;\n }\n\n const wildcardHandlers = this.eventHandlers.get(\"*\");\n if (wildcardHandlers) {\n for (const handler of wildcardHandlers) {\n handler(message);\n }\n }\n }\n\n private async handleRequest(message: ReceivedBridgeMessage) {\n const handler = this.requestHandlers.get(message.type);\n if (!handler) {\n return;\n }\n\n const replyTarget = isMessageTarget(message.rawEvent.source)\n ? message.rawEvent.source\n : this.targetWindow;\n\n try {\n const payload = await handler(message.payload, message);\n this.postMessage(\n {\n kind: \"response\",\n type: message.type,\n payload,\n replyTo: message.id\n },\n replyTarget\n );\n } catch (error) {\n const bridgeError =\n error instanceof Error\n ? { code: \"request_handler_error\", message: error.message }\n : { code: \"request_handler_error\", message: \"Unknown request handler error.\" };\n\n this.postMessage(\n {\n kind: \"response\",\n type: message.type,\n error: bridgeError,\n replyTo: message.id\n },\n replyTarget\n );\n }\n }\n\n private resolvePendingRequest(messageId: string, message: BridgeMessage) {\n const pendingRequest = this.pendingRequests.get(messageId);\n if (!pendingRequest) {\n return;\n }\n\n clearTimeout(pendingRequest.timeoutId);\n this.pendingRequests.delete(messageId);\n\n if (message.error) {\n pendingRequest.reject(new Error(`${message.error.code}: ${message.error.message}`));\n return;\n }\n\n pendingRequest.resolve(message.payload);\n }\n\n private postMessage<TPayload = unknown>(\n partialMessage: Pick<BridgeMessage<TPayload>, \"kind\" | \"type\"> &\n Partial<Omit<BridgeMessage<TPayload>, \"namespace\" | \"version\" | \"source\">>,\n targetWindowOverride?: Window\n ) {\n const targetWindow = targetWindowOverride ?? this.targetWindow;\n if (!targetWindow) {\n throw new Error(\n \"AppBridge could not resolve a target window. Pass targetWindow explicitly or call setTargetWindow().\"\n );\n }\n\n const message = omitUndefinedFields({\n namespace: this.namespace,\n version: \"1.0\",\n id: partialMessage.id ?? createMessageId(),\n kind: partialMessage.kind,\n type: partialMessage.type,\n source: this.source,\n target: partialMessage.target ?? this.target,\n payload: partialMessage.payload,\n replyTo: partialMessage.replyTo,\n error: partialMessage.error\n }) as BridgeMessage<TPayload>;\n\n targetWindow.postMessage(message, this.targetOrigin);\n }\n\n private handleRedirectMessage(message: ReceivedBridgeMessage): boolean {\n const destination = resolveNavigationDestination(message.payload);\n if (!destination) {\n return false;\n }\n\n this.navigateSelf(destination);\n return true;\n }\n\n private navigateSelf(destination: string) {\n if (!this.selfWindow) {\n throw new Error(\"AppBridge could not resolve a browser window for redirect.\");\n }\n\n this.selfWindow.location.assign(destination);\n }\n}\n\nexport function createAppBridge(options: AppBridgeOptions = {}) {\n return new AppBridge(options);\n}\n","import {\n createContext,\n useContext,\n useEffect,\n useRef,\n useState,\n type MutableRefObject,\n type ReactNode\n} from \"react\";\n\nimport {\n createAppBridge,\n type AppBridge,\n type AppBridgeOptions,\n type ReceivedBridgeMessage\n} from \"./core\";\nimport {\n buildNavigationUpdatePayload,\n resolveLocalNavigationPath,\n resolveNavigationDestination,\n sanitizeEmbeddedAppPath,\n type BridgeNavigationGoPayload\n} from \"./navigation\";\n\nconst AppBridgeContext = createContext<AppBridge | null>(null);\n\nexport interface AppBridgeProviderProps\n extends Omit<AppBridgeOptions, \"source\" | \"target\" | \"allowedOrigins\"> {\n children: ReactNode;\n clientId: string;\n readyEventType?: string;\n readyPayload?: unknown;\n currentPath?: string | null;\n navigationEventType?: string;\n navigationUpdateEventType?: string;\n onNavigate?: (\n path: string,\n message?: ReceivedBridgeMessage<BridgeNavigationGoPayload>\n ) => void;\n}\n\nexport function AppBridgeProvider({\n children,\n clientId,\n currentPath,\n navigationEventType = \"navigation:go\",\n navigationUpdateEventType = \"navigation:update\",\n namespace,\n onNavigate,\n readyEventType = \"app:ready\",\n readyPayload,\n requestTimeoutMs,\n selfWindow,\n targetOrigin,\n targetWindow\n}: AppBridgeProviderProps) {\n const [bridge, setBridge] = useState<AppBridge | null>(null);\n const onNavigateRef = useRef(onNavigate);\n const sessionTokenCacheRef = useRef<{\n token: string;\n expiresAt?: number;\n } | null>(null);\n const projectRef = useRef<string | null>(readInitialProject(selfWindow));\n const pendingSessionTokenRef = useRef<Promise<string> | null>(null);\n\n useEffect(() => {\n onNavigateRef.current = onNavigate;\n }, [onNavigate]);\n\n useEffect(() => {\n if (typeof window === \"undefined\" && !selfWindow) {\n return;\n }\n\n const resolvedTargetOrigin = targetOrigin ?? getReferrerOrigin(selfWindow);\n const resolvedAllowedOrigins = resolvedTargetOrigin\n ? [resolvedTargetOrigin]\n : undefined;\n\n const nextBridge = createAppBridge({\n allowedOrigins: resolvedAllowedOrigins,\n clientId,\n namespace,\n requestTimeoutMs,\n selfWindow,\n source: \"embedded-app\",\n target: \"dashboard\",\n targetOrigin: resolvedTargetOrigin,\n targetWindow\n });\n\n setBridge(nextBridge);\n\n return () => {\n setBridge((currentBridge) => (currentBridge === nextBridge ? null : currentBridge));\n nextBridge.destroy();\n };\n }, [\n clientId,\n namespace,\n requestTimeoutMs,\n selfWindow,\n targetOrigin,\n targetWindow\n ]);\n\n useEffect(() => {\n if (!bridge || !bridge.hasTargetWindow()) {\n return;\n }\n\n bridge.send(\n readyEventType,\n readyPayload ?? {\n clientId\n }\n );\n }, [bridge, clientId, readyEventType, readyPayload]);\n\n useEffect(() => {\n if (!bridge || !bridge.hasTargetWindow() || !currentPath) {\n return;\n }\n\n bridge.send(navigationUpdateEventType, buildNavigationUpdatePayload(currentPath));\n }, [bridge, currentPath, navigationUpdateEventType]);\n\n useEffect(() => {\n if (!bridge || !onNavigate) {\n return;\n }\n\n return bridge.on<BridgeNavigationGoPayload>(navigationEventType, (message) => {\n const destination = resolveNavigationDestination(message.payload);\n if (!destination) {\n return;\n }\n\n onNavigateRef.current?.(destination, message);\n });\n }, [bridge, navigationEventType, onNavigate]);\n\n useEffect(() => {\n if (\n !bridge ||\n !onNavigate ||\n typeof document === \"undefined\" ||\n typeof window === \"undefined\"\n ) {\n return;\n }\n\n const handleLocalNavigation = (path: string) => {\n const sanitizedPath = sanitizeEmbeddedAppPath(path);\n if (!sanitizedPath) {\n return;\n }\n\n onNavigateRef.current?.(sanitizedPath);\n };\n\n const handleDocumentClick = (event: MouseEvent) => {\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.altKey ||\n event.ctrlKey ||\n event.shiftKey\n ) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Element)) {\n return;\n }\n\n const anchor = target.closest(\"a[href]\");\n if (!(anchor instanceof HTMLAnchorElement)) {\n return;\n }\n\n if (anchor.hasAttribute(\"download\")) {\n return;\n }\n\n const targetWindow = anchor.target.toLowerCase();\n const href = anchor.getAttribute(\"href\");\n if (!href) {\n return;\n }\n\n if (targetWindow === \"_top\" || targetWindow === \"_parent\") {\n event.preventDefault();\n bridge.redirectToRemote(anchor.href);\n return;\n }\n\n if (targetWindow && targetWindow !== \"_self\") {\n return;\n }\n\n const nextPath = resolveLocalNavigationPath(href, window.location.origin);\n if (!nextPath) {\n return;\n }\n\n event.preventDefault();\n handleLocalNavigation(nextPath);\n };\n\n const originalOpen = window.open.bind(window);\n window.open = (url?: string | URL, target?: string, features?: string) => {\n if (url == null) {\n return originalOpen(url, target, features);\n }\n\n const href = typeof url === \"string\" ? url : url.toString();\n const targetName = (target ?? \"\").toLowerCase();\n\n if (targetName === \"_top\" || targetName === \"_parent\") {\n bridge.redirectToRemote(new URL(href, window.location.href).toString());\n return null;\n }\n\n if (!targetName || targetName === \"_self\") {\n const nextPath = resolveLocalNavigationPath(href, window.location.origin);\n if (nextPath) {\n handleLocalNavigation(nextPath);\n return window;\n }\n }\n\n return originalOpen(url, target, features);\n };\n\n document.addEventListener(\"click\", handleDocumentClick, true);\n\n return () => {\n document.removeEventListener(\"click\", handleDocumentClick, true);\n window.open = originalOpen;\n };\n }, [bridge, onNavigate]);\n\n useEffect(() => {\n if (!bridge || typeof window === \"undefined\") {\n return;\n }\n\n const originalFetch = globalThis.fetch.bind(globalThis);\n\n const interceptedFetch = async (input: RequestInfo | URL, init?: RequestInit) => {\n if (!shouldAttachSessionToken(input)) {\n return originalFetch(input, init);\n }\n\n const existingAuthorization = getExistingAuthorization(input, init);\n if (existingAuthorization) {\n return originalFetch(input, init);\n }\n\n const nextHeaders = new Headers(\n input instanceof Request ? input.headers : init?.headers\n );\n\n if (projectRef.current && !nextHeaders.has(\"X-Thor-Project\")) {\n nextHeaders.set(\"X-Thor-Project\", projectRef.current);\n }\n\n try {\n const sessionToken = await getSessionToken({\n bridge,\n clientId,\n pendingSessionTokenRef,\n projectRef,\n sessionTokenCacheRef\n });\n\n nextHeaders.set(\"Authorization\", `Bearer ${sessionToken}`);\n } catch {\n if (!projectRef.current) {\n throw new Error(\"Missing Thor embedded session token\");\n }\n }\n\n if (!nextHeaders.has(\"X-Requested-With\")) {\n nextHeaders.set(\"X-Requested-With\", \"XMLHttpRequest\");\n }\n\n if (input instanceof Request) {\n return originalFetch(\n new Request(input, {\n headers: nextHeaders\n })\n );\n }\n\n return originalFetch(input, {\n ...init,\n headers: nextHeaders\n });\n };\n\n globalThis.fetch = interceptedFetch;\n window.fetch = interceptedFetch;\n\n return () => {\n globalThis.fetch = originalFetch;\n window.fetch = originalFetch;\n };\n }, [bridge, clientId]);\n\n return <AppBridgeContext.Provider value={bridge}>{children}</AppBridgeContext.Provider>;\n}\n\nexport function useAppBridge() {\n return useContext(AppBridgeContext);\n}\n\nfunction getReferrerOrigin(explicitWindow?: Window) {\n const resolvedWindow = explicitWindow ?? (typeof window !== \"undefined\" ? window : undefined);\n const referrer = resolvedWindow?.document?.referrer;\n\n if (!referrer) {\n return undefined;\n }\n\n try {\n return new URL(referrer).origin;\n } catch {\n return undefined;\n }\n}\n\nasync function getSessionToken({\n bridge,\n clientId,\n pendingSessionTokenRef,\n projectRef,\n sessionTokenCacheRef\n}: {\n bridge: AppBridge;\n clientId: string;\n pendingSessionTokenRef: MutableRefObject<Promise<string> | null>;\n projectRef: MutableRefObject<string | null>;\n sessionTokenCacheRef: MutableRefObject<{\n token: string;\n expiresAt?: number;\n } | null>;\n}) {\n const cachedToken = sessionTokenCacheRef.current;\n if (cachedToken && !isExpired(cachedToken.expiresAt)) {\n return cachedToken.token;\n }\n\n if (pendingSessionTokenRef.current) {\n return pendingSessionTokenRef.current;\n }\n\n const pendingToken = bridge\n .getSessionToken({ clientId })\n .then((response) => {\n const token = response.sessionToken ?? response.idToken;\n if (!token) {\n throw new Error(\"Missing Thor embedded session token\");\n }\n\n if (response.project) {\n projectRef.current = response.project;\n }\n\n sessionTokenCacheRef.current = {\n token,\n expiresAt: normalizeTokenExpiry(token, response.exp)\n };\n pendingSessionTokenRef.current = null;\n\n return token;\n })\n .catch((error) => {\n pendingSessionTokenRef.current = null;\n throw error;\n });\n\n pendingSessionTokenRef.current = pendingToken;\n return pendingToken;\n}\n\nfunction shouldAttachSessionToken(input: RequestInfo | URL) {\n if (typeof window === \"undefined\") {\n return false;\n }\n\n const requestUrl = resolveRequestUrl(input);\n return requestUrl.origin === window.location.origin;\n}\n\nfunction resolveRequestUrl(input: RequestInfo | URL) {\n if (input instanceof Request) {\n return new URL(input.url);\n }\n\n if (input instanceof URL) {\n return input;\n }\n\n return new URL(input, window.location.href);\n}\n\nfunction getExistingAuthorization(input: RequestInfo | URL, init?: RequestInit) {\n if (input instanceof Request && input.headers.has(\"Authorization\")) {\n return input.headers.get(\"Authorization\");\n }\n\n if (!init?.headers) {\n return null;\n }\n\n return new Headers(init.headers).get(\"Authorization\");\n}\n\nfunction normalizeTokenExpiry(token: string, explicitExp?: number) {\n const tokenExp = explicitExp ?? decodeJwtExpiry(token);\n return tokenExp ? tokenExp * 1000 : undefined;\n}\n\nfunction decodeJwtExpiry(token: string) {\n const [, payload] = token.split(\".\");\n if (!payload || typeof window === \"undefined\") {\n return undefined;\n }\n\n try {\n const normalized = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized.padEnd(\n normalized.length + ((4 - (normalized.length % 4)) % 4),\n \"=\"\n );\n const json = JSON.parse(window.atob(padded)) as { exp?: unknown };\n\n return typeof json.exp === \"number\" ? json.exp : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isExpired(expiresAt?: number) {\n if (!expiresAt) {\n return false;\n }\n\n return Date.now() >= expiresAt - 5_000;\n}\n\nfunction readInitialProject(explicitWindow?: Window) {\n const resolvedWindow = explicitWindow ?? (typeof window !== \"undefined\" ? window : undefined);\n if (!resolvedWindow) {\n return null;\n }\n\n try {\n const url = new URL(resolvedWindow.location.href);\n return url.searchParams.get(\"project\");\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":["targetWindow"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/navigation.ts","../src/core.ts","../src/react.tsx"],"sourcesContent":["export * from \"./core\";\nexport * from \"./navigation\";\nexport * from \"./react\";\n","export interface BridgeNavigationGoPayload {\n path?: string;\n href?: string;\n pathname?: string;\n search?: string;\n hash?: string;\n}\n\nexport interface BridgeNavigationRedirectPayload extends BridgeNavigationGoPayload {}\n\nexport interface BridgeNavigationUpdatePayload {\n path: string;\n pathname: string;\n search: string;\n hash: string;\n}\n\nexport interface BridgeNavigationItem {\n path: string;\n label: string;\n matchPattern?: string;\n exactMatch?: boolean;\n}\n\nexport interface BridgeNavigationItemsPayload {\n items: BridgeNavigationItem[];\n}\n\nexport const EMBEDDED_LAUNCH_PARAMS = [\n \"appLoadId\",\n \"embedded\",\n \"hmac\",\n \"host\",\n \"id_token\",\n \"link_source\",\n \"locale\",\n \"protocol\",\n \"session\",\n \"shop\",\n \"tenant\",\n \"timestamp\"\n] as const;\n\nconst NAVIGATION_BASE_URL = \"https://embedded-app.local\";\n\nfunction normalizeSearch(search: string) {\n if (!search) {\n return \"\";\n }\n\n return search.startsWith(\"?\") ? search : `?${search}`;\n}\n\nfunction normalizeHash(hash: string) {\n if (!hash) {\n return \"\";\n }\n\n return hash.startsWith(\"#\") ? hash : `#${hash}`;\n}\n\nexport function buildNavigationUpdatePayload(path: string): BridgeNavigationUpdatePayload {\n const sanitizedPath = sanitizeEmbeddedAppPath(path) ?? path;\n let pathname = sanitizedPath;\n let search = \"\";\n let hash = \"\";\n\n const hashIndex = pathname.indexOf(\"#\");\n if (hashIndex >= 0) {\n hash = pathname.slice(hashIndex);\n pathname = pathname.slice(0, hashIndex);\n }\n\n const searchIndex = pathname.indexOf(\"?\");\n if (searchIndex >= 0) {\n search = pathname.slice(searchIndex);\n pathname = pathname.slice(0, searchIndex);\n }\n\n return {\n path: `${pathname || \"/\"}${search}${hash}`,\n pathname: pathname || \"/\",\n search,\n hash\n };\n}\n\nexport function sanitizeEmbeddedAppPath(path: string | undefined) {\n if (!path) {\n return path;\n }\n\n const trimmedPath = path.trim();\n if (!trimmedPath) {\n return trimmedPath;\n }\n\n const url = new URL(trimmedPath, NAVIGATION_BASE_URL);\n let changed = false;\n\n for (const key of EMBEDDED_LAUNCH_PARAMS) {\n if (url.searchParams.has(key)) {\n url.searchParams.delete(key);\n changed = true;\n }\n }\n\n if (!changed) {\n return trimmedPath;\n }\n\n if (/^https?:\\/\\//i.test(trimmedPath)) {\n return url.toString();\n }\n\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nexport function resolveLocalNavigationPath(\n href: string,\n currentOrigin: string\n): string | null {\n if (!href || href.startsWith(\"#\")) {\n return null;\n }\n\n let destination: URL;\n try {\n destination = new URL(href, currentOrigin);\n } catch {\n return null;\n }\n\n if (destination.origin !== currentOrigin) {\n return null;\n }\n\n return sanitizeEmbeddedAppPath(\n `${destination.pathname}${destination.search}${destination.hash}`\n ) ?? null;\n}\n\nexport function resolveNavigationDestination(payload: unknown): string | null {\n if (typeof payload === \"string\") {\n return sanitizeEmbeddedAppPath(payload) ?? null;\n }\n\n if (!payload || typeof payload !== \"object\") {\n return null;\n }\n\n const value = payload as BridgeNavigationGoPayload;\n\n if (typeof value.path === \"string\" && value.path) {\n return sanitizeEmbeddedAppPath(value.path) ?? null;\n }\n\n if (typeof value.href === \"string\" && value.href) {\n return sanitizeEmbeddedAppPath(value.href) ?? null;\n }\n\n if (typeof value.pathname !== \"string\" || !value.pathname) {\n return null;\n }\n\n return (\n sanitizeEmbeddedAppPath(\n `${value.pathname}${normalizeSearch(value.search ?? \"\")}${normalizeHash(value.hash ?? \"\")}`\n ) ?? null\n );\n}\n\n\nfunction normalizeNavigationItemPath(path: string | undefined) {\n if (!path) {\n return null;\n }\n\n const trimmedPath = path.trim();\n if (!trimmedPath || /^https?:\\/\\//i.test(trimmedPath)) {\n return null;\n }\n\n const normalizedPath = trimmedPath.startsWith(\"/\") ? trimmedPath : \"/\" + trimmedPath;\n return sanitizeEmbeddedAppPath(normalizedPath) ?? normalizedPath;\n}\n\nexport function normalizeBridgeNavigationItem(\n item: BridgeNavigationItem\n): BridgeNavigationItem | null {\n const label = item.label?.trim();\n const path = normalizeNavigationItemPath(item.path);\n\n if (!label || !path) {\n return null;\n }\n\n const matchPattern = normalizeNavigationItemPath(item.matchPattern ?? item.path);\n\n return {\n label,\n path,\n ...(matchPattern ? {matchPattern} : {}),\n ...(item.exactMatch !== undefined ? {exactMatch: item.exactMatch} : {}),\n };\n}\n\nexport function normalizeBridgeNavigationItems(\n items: BridgeNavigationItem[] | undefined\n) {\n if (!items?.length) {\n return [];\n }\n\n return items.flatMap((item) => {\n const normalizedItem = normalizeBridgeNavigationItem(item);\n return normalizedItem ? [normalizedItem] : [];\n });\n}\n","import {\n resolveNavigationDestination,\n type BridgeNavigationGoPayload,\n type BridgeNavigationRedirectPayload\n} from \"./navigation\";\n\nexport type BridgeParticipant = \"embedded-app\" | \"dashboard\" | \"unknown\";\n\nexport type BridgeMessageKind = \"event\" | \"request\" | \"response\";\n\nexport interface BridgeErrorPayload {\n code: string;\n message: string;\n}\n\nexport interface BridgeMessage<TPayload = unknown> {\n namespace: string;\n version: \"1.0\";\n kind: BridgeMessageKind;\n id: string;\n type: string;\n source: BridgeParticipant;\n target?: BridgeParticipant;\n payload?: TPayload;\n replyTo?: string;\n error?: BridgeErrorPayload;\n}\n\nexport interface AppBridgeOptions {\n clientId?: string;\n source?: BridgeParticipant;\n target?: BridgeParticipant;\n namespace?: string;\n targetOrigin?: string;\n allowedOrigins?: string[];\n requestTimeoutMs?: number;\n selfWindow?: Window;\n targetWindow?: Window | null;\n}\n\nexport interface RequestOptions {\n timeoutMs?: number;\n}\n\nexport interface SessionTokenRequest {\n clientId?: string;\n}\n\nexport interface SessionTokenResponse {\n sessionToken?: string;\n idToken: string;\n exp?: number;\n project?: string;\n}\n\nexport interface ReceivedBridgeMessage<TPayload = unknown> extends BridgeMessage<TPayload> {\n origin: string;\n rawEvent: MessageEvent<unknown>;\n}\n\nexport type BridgeEventHandler<TPayload = unknown> = (\n message: ReceivedBridgeMessage<TPayload>\n) => void;\n\nexport type BridgeRequestHandler<TRequest = unknown, TResponse = unknown> = (\n payload: TRequest,\n message: ReceivedBridgeMessage<TRequest>\n) => TResponse | Promise<TResponse>;\n\nexport type Unsubscribe = () => void;\n\nconst DEFAULT_NAMESPACE = \"thorcommerce:app-bridge\";\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_REDIRECT_EVENT_TYPE = \"navigation:redirect\";\n\nfunction createMessageId() {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n\n return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction resolveSelfWindow(explicitWindow?: Window) {\n if (explicitWindow) {\n return explicitWindow;\n }\n\n if (typeof window !== \"undefined\") {\n return window;\n }\n\n return undefined;\n}\n\nfunction resolveTargetWindow(selfWindow: Window | undefined, targetWindow?: Window | null) {\n if (targetWindow) {\n return targetWindow;\n }\n\n if (!selfWindow) {\n return undefined;\n }\n\n if (selfWindow.parent && selfWindow.parent !== selfWindow) {\n return selfWindow.parent;\n }\n\n return undefined;\n}\n\nfunction isDevelopmentEnvironment() {\n const nodeEnv =\n typeof globalThis !== \"undefined\" && \"process\" in globalThis\n ? (\n globalThis as typeof globalThis & {\n process?: { env?: { NODE_ENV?: string } };\n }\n ).process?.env?.NODE_ENV\n : undefined;\n\n if (nodeEnv) {\n return nodeEnv !== \"production\";\n }\n\n return true;\n}\n\nfunction hasAllowedOrigin(origin: string, allowedOrigins?: string[]) {\n if (!allowedOrigins || allowedOrigins.length === 0) {\n return true;\n }\n\n return allowedOrigins.includes(origin);\n}\n\nfunction isMessageTarget(value: unknown): value is Window {\n return !!value && typeof (value as Window).postMessage === \"function\";\n}\n\nfunction omitUndefinedFields<T extends object>(value: T): T {\n return Object.fromEntries(\n Object.entries(value).filter(([, fieldValue]) => fieldValue !== undefined)\n ) as T;\n}\n\nexport function isBridgeMessage<TPayload = unknown>(\n value: unknown,\n namespace = DEFAULT_NAMESPACE\n): value is BridgeMessage<TPayload> {\n if (!value || typeof value !== \"object\") {\n return false;\n }\n\n const message = value as Partial<BridgeMessage<TPayload>>;\n\n return (\n message.namespace === namespace &&\n message.version === \"1.0\" &&\n typeof message.kind === \"string\" &&\n typeof message.id === \"string\" &&\n typeof message.type === \"string\" &&\n typeof message.source === \"string\"\n );\n}\n\nexport class AppBridge {\n private readonly namespace: string;\n private readonly clientId?: string;\n private readonly source: BridgeParticipant;\n private readonly target: BridgeParticipant | undefined;\n private readonly targetOrigin: string;\n private readonly allowedOrigins?: string[];\n private readonly selfWindow?: Window;\n private readonly defaultTimeoutMs: number;\n private targetWindow?: Window;\n private readonly eventHandlers = new Map<string, Set<BridgeEventHandler>>();\n private readonly requestHandlers = new Map<string, BridgeRequestHandler>();\n private readonly pendingRequests = new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n }\n >();\n private readonly messageListener: (event: MessageEvent<unknown>) => void;\n\n constructor(options: AppBridgeOptions = {}) {\n this.namespace = options.namespace ?? DEFAULT_NAMESPACE;\n this.clientId = options.clientId;\n this.source = options.source ?? \"embedded-app\";\n this.target = options.target;\n this.targetOrigin = options.targetOrigin ?? \"*\";\n this.allowedOrigins = options.allowedOrigins;\n this.defaultTimeoutMs = options.requestTimeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.selfWindow = resolveSelfWindow(options.selfWindow);\n this.targetWindow = resolveTargetWindow(this.selfWindow, options.targetWindow);\n this.messageListener = (event) => {\n this.handleMessage(event);\n };\n\n if (!this.selfWindow) {\n throw new Error(\n \"AppBridge requires a browser window. Pass selfWindow explicitly when constructing it outside global window scope.\"\n );\n }\n\n if (this.targetOrigin === \"*\" && isDevelopmentEnvironment()) {\n console.warn(\n 'AppBridge is using \"*\" as targetOrigin. Set targetOrigin explicitly for both the dashboard and embedded app in production.'\n );\n }\n\n this.selfWindow.addEventListener(\"message\", this.messageListener);\n }\n\n setTargetWindow(targetWindow: Window | null) {\n this.targetWindow = targetWindow ?? undefined;\n }\n\n hasTargetWindow() {\n return this.targetWindow !== undefined;\n }\n\n redirect(payload: string | BridgeNavigationRedirectPayload) {\n const destination = resolveNavigationDestination(payload);\n if (!destination) {\n throw new Error(\"AppBridge redirect requires a valid destination.\");\n }\n\n if (!this.targetWindow) {\n this.navigateSelf(destination);\n return;\n }\n\n this.postMessage<BridgeNavigationRedirectPayload>({\n kind: \"event\",\n type: DEFAULT_REDIRECT_EVENT_TYPE,\n payload: typeof payload === \"string\" ? { href: payload } : payload\n });\n }\n\n redirectToRemote(href: string) {\n this.redirect({ href });\n }\n\n redirectToApp(path: string | BridgeNavigationGoPayload) {\n this.redirect(typeof path === \"string\" ? { path } : path);\n }\n\n send<TPayload = unknown>(type: string, payload?: TPayload) {\n this.postMessage({\n kind: \"event\",\n type,\n payload\n });\n }\n\n request<TRequest = unknown, TResponse = unknown>(\n type: string,\n payload?: TRequest,\n options: RequestOptions = {}\n ) {\n const messageId = createMessageId();\n const timeoutMs = options.timeoutMs ?? this.defaultTimeoutMs;\n\n return new Promise<TResponse>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pendingRequests.delete(messageId);\n reject(new Error(`Bridge request timed out for \"${type}\" after ${timeoutMs}ms.`));\n }, timeoutMs);\n\n this.pendingRequests.set(messageId, {\n resolve: (value) => resolve(value as TResponse),\n reject,\n timeoutId\n });\n\n try {\n this.postMessage({\n id: messageId,\n kind: \"request\",\n type,\n payload\n });\n } catch (error) {\n clearTimeout(timeoutId);\n this.pendingRequests.delete(messageId);\n reject(error instanceof Error ? error : new Error(\"Failed to send bridge request.\"));\n }\n });\n }\n\n getSessionToken(\n request: SessionTokenRequest = {},\n options: RequestOptions = {}\n ) {\n const resolvedRequest =\n request.clientId || this.clientId\n ? {\n ...request,\n clientId: request.clientId ?? this.clientId\n }\n : request;\n\n return this.request<SessionTokenRequest, SessionTokenResponse>(\n \"thor:session-token:get\",\n resolvedRequest,\n options\n );\n }\n\n on<TPayload = unknown>(type: string, handler: BridgeEventHandler<TPayload>): Unsubscribe {\n const handlers = this.eventHandlers.get(type) ?? new Set<BridgeEventHandler>();\n handlers.add(handler as BridgeEventHandler);\n this.eventHandlers.set(type, handlers);\n\n return () => {\n handlers.delete(handler as BridgeEventHandler);\n if (handlers.size === 0) {\n this.eventHandlers.delete(type);\n }\n };\n }\n\n onRequest<TRequest = unknown, TResponse = unknown>(\n type: string,\n handler: BridgeRequestHandler<TRequest, TResponse>\n ): Unsubscribe {\n this.requestHandlers.set(type, handler as BridgeRequestHandler);\n\n return () => {\n const registeredHandler = this.requestHandlers.get(type);\n if (registeredHandler === handler) {\n this.requestHandlers.delete(type);\n }\n };\n }\n\n destroy() {\n if (this.selfWindow) {\n this.selfWindow.removeEventListener(\"message\", this.messageListener);\n }\n\n for (const pendingRequest of this.pendingRequests.values()) {\n clearTimeout(pendingRequest.timeoutId);\n pendingRequest.reject(new Error(\"AppBridge destroyed before a response was received.\"));\n }\n\n this.pendingRequests.clear();\n this.eventHandlers.clear();\n this.requestHandlers.clear();\n }\n\n private handleMessage(event: MessageEvent<unknown>) {\n if (!hasAllowedOrigin(event.origin, this.allowedOrigins)) {\n return;\n }\n\n if (!isBridgeMessage(event.data, this.namespace)) {\n return;\n }\n\n const message = event.data;\n\n if (this.target && message.target && message.target !== this.source) {\n return;\n }\n\n const receivedMessage: ReceivedBridgeMessage = {\n ...message,\n origin: event.origin,\n rawEvent: event\n };\n\n if (\n message.kind === \"event\" &&\n message.type === DEFAULT_REDIRECT_EVENT_TYPE &&\n this.handleRedirectMessage(receivedMessage)\n ) {\n return;\n }\n\n if (message.kind === \"response\" && message.replyTo) {\n this.resolvePendingRequest(message.replyTo, message);\n return;\n }\n\n this.emitHandlers(message.type, receivedMessage);\n\n if (message.kind === \"request\") {\n void this.handleRequest(receivedMessage);\n }\n }\n\n private emitHandlers(type: string, message: ReceivedBridgeMessage) {\n const typeHandlers = this.eventHandlers.get(type);\n if (typeHandlers) {\n for (const handler of typeHandlers) {\n handler(message);\n }\n }\n\n if (type === \"*\") {\n return;\n }\n\n const wildcardHandlers = this.eventHandlers.get(\"*\");\n if (wildcardHandlers) {\n for (const handler of wildcardHandlers) {\n handler(message);\n }\n }\n }\n\n private async handleRequest(message: ReceivedBridgeMessage) {\n const handler = this.requestHandlers.get(message.type);\n if (!handler) {\n return;\n }\n\n const replyTarget = isMessageTarget(message.rawEvent.source)\n ? message.rawEvent.source\n : this.targetWindow;\n\n try {\n const payload = await handler(message.payload, message);\n this.postMessage(\n {\n kind: \"response\",\n type: message.type,\n payload,\n replyTo: message.id\n },\n replyTarget\n );\n } catch (error) {\n const bridgeError =\n error instanceof Error\n ? { code: \"request_handler_error\", message: error.message }\n : { code: \"request_handler_error\", message: \"Unknown request handler error.\" };\n\n this.postMessage(\n {\n kind: \"response\",\n type: message.type,\n error: bridgeError,\n replyTo: message.id\n },\n replyTarget\n );\n }\n }\n\n private resolvePendingRequest(messageId: string, message: BridgeMessage) {\n const pendingRequest = this.pendingRequests.get(messageId);\n if (!pendingRequest) {\n return;\n }\n\n clearTimeout(pendingRequest.timeoutId);\n this.pendingRequests.delete(messageId);\n\n if (message.error) {\n pendingRequest.reject(new Error(`${message.error.code}: ${message.error.message}`));\n return;\n }\n\n pendingRequest.resolve(message.payload);\n }\n\n private postMessage<TPayload = unknown>(\n partialMessage: Pick<BridgeMessage<TPayload>, \"kind\" | \"type\"> &\n Partial<Omit<BridgeMessage<TPayload>, \"namespace\" | \"version\" | \"source\">>,\n targetWindowOverride?: Window\n ) {\n const targetWindow = targetWindowOverride ?? this.targetWindow;\n if (!targetWindow) {\n throw new Error(\n \"AppBridge could not resolve a target window. Pass targetWindow explicitly or call setTargetWindow().\"\n );\n }\n\n const message = omitUndefinedFields({\n namespace: this.namespace,\n version: \"1.0\",\n id: partialMessage.id ?? createMessageId(),\n kind: partialMessage.kind,\n type: partialMessage.type,\n source: this.source,\n target: partialMessage.target ?? this.target,\n payload: partialMessage.payload,\n replyTo: partialMessage.replyTo,\n error: partialMessage.error\n }) as BridgeMessage<TPayload>;\n\n targetWindow.postMessage(message, this.targetOrigin);\n }\n\n private handleRedirectMessage(message: ReceivedBridgeMessage): boolean {\n const destination = resolveNavigationDestination(message.payload);\n if (!destination) {\n return false;\n }\n\n this.navigateSelf(destination);\n return true;\n }\n\n private navigateSelf(destination: string) {\n if (!this.selfWindow) {\n throw new Error(\"AppBridge could not resolve a browser window for redirect.\");\n }\n\n this.selfWindow.location.assign(destination);\n }\n}\n\nexport function createAppBridge(options: AppBridgeOptions = {}) {\n return new AppBridge(options);\n}\n","import {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type MutableRefObject,\n type ReactNode\n} from \"react\";\n\nimport {\n createAppBridge,\n type AppBridge,\n type AppBridgeOptions,\n type ReceivedBridgeMessage\n} from \"./core\";\nimport {\n buildNavigationUpdatePayload,\n normalizeBridgeNavigationItems,\n resolveLocalNavigationPath,\n resolveNavigationDestination,\n sanitizeEmbeddedAppPath,\n type BridgeNavigationGoPayload,\n type BridgeNavigationItem\n} from \"./navigation\";\n\nconst AppBridgeContext = createContext<AppBridge | null>(null);\n\nexport interface AppBridgeProviderProps\n extends Omit<AppBridgeOptions, \"source\" | \"target\" | \"allowedOrigins\"> {\n children: ReactNode;\n clientId: string;\n readyEventType?: string;\n readyPayload?: unknown;\n currentPath?: string | null;\n navigationItems?: BridgeNavigationItem[];\n navigationEventType?: string;\n navigationUpdateEventType?: string;\n onNavigate?: (\n path: string,\n message?: ReceivedBridgeMessage<BridgeNavigationGoPayload>\n ) => void;\n}\n\nexport function AppBridgeProvider({\n children,\n clientId,\n currentPath,\n navigationItems,\n navigationEventType = \"navigation:go\",\n navigationUpdateEventType = \"navigation:update\",\n namespace,\n onNavigate,\n readyEventType = \"app:ready\",\n readyPayload,\n requestTimeoutMs,\n selfWindow,\n targetOrigin,\n targetWindow\n}: AppBridgeProviderProps) {\n const [bridge, setBridge] = useState<AppBridge | null>(null);\n const onNavigateRef = useRef(onNavigate);\n const normalizedNavigationItems = useMemo(\n () => normalizeBridgeNavigationItems(navigationItems),\n [navigationItems]\n );\n const sessionTokenCacheRef = useRef<{\n token: string;\n expiresAt?: number;\n } | null>(null);\n const projectRef = useRef<string | null>(readInitialProject(selfWindow));\n const pendingSessionTokenRef = useRef<Promise<string> | null>(null);\n\n useEffect(() => {\n onNavigateRef.current = onNavigate;\n }, [onNavigate]);\n\n useEffect(() => {\n if (typeof window === \"undefined\" && !selfWindow) {\n return;\n }\n\n const resolvedTargetOrigin = targetOrigin ?? getReferrerOrigin(selfWindow);\n const resolvedAllowedOrigins = resolvedTargetOrigin\n ? [resolvedTargetOrigin]\n : undefined;\n\n const nextBridge = createAppBridge({\n allowedOrigins: resolvedAllowedOrigins,\n clientId,\n namespace,\n requestTimeoutMs,\n selfWindow,\n source: \"embedded-app\",\n target: \"dashboard\",\n targetOrigin: resolvedTargetOrigin,\n targetWindow\n });\n\n setBridge(nextBridge);\n\n return () => {\n setBridge((currentBridge) => (currentBridge === nextBridge ? null : currentBridge));\n nextBridge.destroy();\n };\n }, [\n clientId,\n namespace,\n requestTimeoutMs,\n selfWindow,\n targetOrigin,\n targetWindow\n ]);\n\n useEffect(() => {\n if (!bridge || !bridge.hasTargetWindow()) {\n return;\n }\n\n bridge.send(\n readyEventType,\n readyPayload ?? {\n clientId\n }\n );\n }, [bridge, clientId, readyEventType, readyPayload]);\n\n useEffect(() => {\n if (!bridge || !bridge.hasTargetWindow()) {\n return;\n }\n\n bridge.send(\"navigation:items:update\", {\n items: normalizedNavigationItems\n });\n }, [bridge, normalizedNavigationItems]);\n\n useEffect(() => {\n if (!bridge || !bridge.hasTargetWindow() || !currentPath) {\n return;\n }\n\n bridge.send(navigationUpdateEventType, buildNavigationUpdatePayload(currentPath));\n }, [bridge, currentPath, navigationUpdateEventType]);\n\n useEffect(() => {\n if (!bridge || !onNavigate) {\n return;\n }\n\n return bridge.on<BridgeNavigationGoPayload>(navigationEventType, (message) => {\n const destination = resolveNavigationDestination(message.payload);\n if (!destination) {\n return;\n }\n\n onNavigateRef.current?.(destination, message);\n });\n }, [bridge, navigationEventType, onNavigate]);\n\n useEffect(() => {\n if (\n !bridge ||\n !onNavigate ||\n typeof document === \"undefined\" ||\n typeof window === \"undefined\"\n ) {\n return;\n }\n\n const handleLocalNavigation = (path: string) => {\n const sanitizedPath = sanitizeEmbeddedAppPath(path);\n if (!sanitizedPath) {\n return;\n }\n\n onNavigateRef.current?.(sanitizedPath);\n };\n\n const handleDocumentClick = (event: MouseEvent) => {\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.altKey ||\n event.ctrlKey ||\n event.shiftKey\n ) {\n return;\n }\n\n const target = event.target;\n if (!(target instanceof Element)) {\n return;\n }\n\n const anchor = target.closest(\"a[href]\");\n if (!(anchor instanceof HTMLAnchorElement)) {\n return;\n }\n\n if (anchor.hasAttribute(\"download\")) {\n return;\n }\n\n const targetWindow = anchor.target.toLowerCase();\n const href = anchor.getAttribute(\"href\");\n if (!href) {\n return;\n }\n\n if (targetWindow === \"_top\" || targetWindow === \"_parent\") {\n event.preventDefault();\n bridge.redirectToRemote(anchor.href);\n return;\n }\n\n if (targetWindow && targetWindow !== \"_self\") {\n return;\n }\n\n const nextPath = resolveLocalNavigationPath(href, window.location.origin);\n if (!nextPath) {\n return;\n }\n\n event.preventDefault();\n handleLocalNavigation(nextPath);\n };\n\n const originalOpen = window.open.bind(window);\n window.open = (url?: string | URL, target?: string, features?: string) => {\n if (url == null) {\n return originalOpen(url, target, features);\n }\n\n const href = typeof url === \"string\" ? url : url.toString();\n const targetName = (target ?? \"\").toLowerCase();\n\n if (targetName === \"_top\" || targetName === \"_parent\") {\n bridge.redirectToRemote(new URL(href, window.location.href).toString());\n return null;\n }\n\n if (!targetName || targetName === \"_self\") {\n const nextPath = resolveLocalNavigationPath(href, window.location.origin);\n if (nextPath) {\n handleLocalNavigation(nextPath);\n return window;\n }\n }\n\n return originalOpen(url, target, features);\n };\n\n document.addEventListener(\"click\", handleDocumentClick, true);\n\n return () => {\n document.removeEventListener(\"click\", handleDocumentClick, true);\n window.open = originalOpen;\n };\n }, [bridge, onNavigate]);\n\n useEffect(() => {\n if (!bridge || typeof window === \"undefined\") {\n return;\n }\n\n const originalFetch = globalThis.fetch.bind(globalThis);\n\n const interceptedFetch = async (input: RequestInfo | URL, init?: RequestInit) => {\n if (!shouldAttachSessionToken(input)) {\n return originalFetch(input, init);\n }\n\n const existingAuthorization = getExistingAuthorization(input, init);\n if (existingAuthorization) {\n return originalFetch(input, init);\n }\n\n const nextHeaders = new Headers(\n input instanceof Request ? input.headers : init?.headers\n );\n\n if (projectRef.current && !nextHeaders.has(\"X-Thor-Project\")) {\n nextHeaders.set(\"X-Thor-Project\", projectRef.current);\n }\n\n try {\n const sessionToken = await getSessionToken({\n bridge,\n clientId,\n pendingSessionTokenRef,\n projectRef,\n sessionTokenCacheRef\n });\n\n nextHeaders.set(\"Authorization\", `Bearer ${sessionToken}`);\n } catch {\n if (!projectRef.current) {\n throw new Error(\"Missing Thor embedded session token\");\n }\n }\n\n if (!nextHeaders.has(\"X-Requested-With\")) {\n nextHeaders.set(\"X-Requested-With\", \"XMLHttpRequest\");\n }\n\n if (input instanceof Request) {\n return originalFetch(\n new Request(input, {\n headers: nextHeaders\n })\n );\n }\n\n return originalFetch(input, {\n ...init,\n headers: nextHeaders\n });\n };\n\n globalThis.fetch = interceptedFetch;\n window.fetch = interceptedFetch;\n\n return () => {\n globalThis.fetch = originalFetch;\n window.fetch = originalFetch;\n };\n }, [bridge, clientId]);\n\n return <AppBridgeContext.Provider value={bridge}>{children}</AppBridgeContext.Provider>;\n}\n\nexport function useAppBridge() {\n return useContext(AppBridgeContext);\n}\n\nfunction getReferrerOrigin(explicitWindow?: Window) {\n const resolvedWindow = explicitWindow ?? (typeof window !== \"undefined\" ? window : undefined);\n const referrer = resolvedWindow?.document?.referrer;\n\n if (!referrer) {\n return undefined;\n }\n\n try {\n return new URL(referrer).origin;\n } catch {\n return undefined;\n }\n}\n\nasync function getSessionToken({\n bridge,\n clientId,\n pendingSessionTokenRef,\n projectRef,\n sessionTokenCacheRef\n}: {\n bridge: AppBridge;\n clientId: string;\n pendingSessionTokenRef: MutableRefObject<Promise<string> | null>;\n projectRef: MutableRefObject<string | null>;\n sessionTokenCacheRef: MutableRefObject<{\n token: string;\n expiresAt?: number;\n } | null>;\n}) {\n const cachedToken = sessionTokenCacheRef.current;\n if (cachedToken && !isExpired(cachedToken.expiresAt)) {\n return cachedToken.token;\n }\n\n if (pendingSessionTokenRef.current) {\n return pendingSessionTokenRef.current;\n }\n\n const pendingToken = bridge\n .getSessionToken({ clientId })\n .then((response) => {\n const token = response.sessionToken ?? response.idToken;\n if (!token) {\n throw new Error(\"Missing Thor embedded session token\");\n }\n\n if (response.project) {\n projectRef.current = response.project;\n }\n\n sessionTokenCacheRef.current = {\n token,\n expiresAt: normalizeTokenExpiry(token, response.exp)\n };\n pendingSessionTokenRef.current = null;\n\n return token;\n })\n .catch((error) => {\n pendingSessionTokenRef.current = null;\n throw error;\n });\n\n pendingSessionTokenRef.current = pendingToken;\n return pendingToken;\n}\n\nfunction shouldAttachSessionToken(input: RequestInfo | URL) {\n if (typeof window === \"undefined\") {\n return false;\n }\n\n const requestUrl = resolveRequestUrl(input);\n return requestUrl.origin === window.location.origin;\n}\n\nfunction resolveRequestUrl(input: RequestInfo | URL) {\n if (input instanceof Request) {\n return new URL(input.url);\n }\n\n if (input instanceof URL) {\n return input;\n }\n\n return new URL(input, window.location.href);\n}\n\nfunction getExistingAuthorization(input: RequestInfo | URL, init?: RequestInit) {\n if (input instanceof Request && input.headers.has(\"Authorization\")) {\n return input.headers.get(\"Authorization\");\n }\n\n if (!init?.headers) {\n return null;\n }\n\n return new Headers(init.headers).get(\"Authorization\");\n}\n\nfunction normalizeTokenExpiry(token: string, explicitExp?: number) {\n const tokenExp = explicitExp ?? decodeJwtExpiry(token);\n return tokenExp ? tokenExp * 1000 : undefined;\n}\n\nfunction decodeJwtExpiry(token: string) {\n const [, payload] = token.split(\".\");\n if (!payload || typeof window === \"undefined\") {\n return undefined;\n }\n\n try {\n const normalized = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized.padEnd(\n normalized.length + ((4 - (normalized.length % 4)) % 4),\n \"=\"\n );\n const json = JSON.parse(window.atob(padded)) as { exp?: unknown };\n\n return typeof json.exp === \"number\" ? json.exp : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isExpired(expiresAt?: number) {\n if (!expiresAt) {\n return false;\n }\n\n return Date.now() >= expiresAt - 5_000;\n}\n\nfunction readInitialProject(explicitWindow?: Window) {\n const resolvedWindow = explicitWindow ?? (typeof window !== \"undefined\" ? window : undefined);\n if (!resolvedWindow) {\n return null;\n }\n\n try {\n const url = new URL(resolvedWindow.location.href);\n return url.searchParams.get(\"project\");\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":["targetWindow"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -16,11 +16,22 @@ interface BridgeNavigationUpdatePayload {
|
|
|
16
16
|
search: string;
|
|
17
17
|
hash: string;
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
interface BridgeNavigationItem {
|
|
20
|
+
path: string;
|
|
21
|
+
label: string;
|
|
22
|
+
matchPattern?: string;
|
|
23
|
+
exactMatch?: boolean;
|
|
24
|
+
}
|
|
25
|
+
interface BridgeNavigationItemsPayload {
|
|
26
|
+
items: BridgeNavigationItem[];
|
|
27
|
+
}
|
|
28
|
+
declare const EMBEDDED_LAUNCH_PARAMS: readonly ["appLoadId", "embedded", "hmac", "host", "id_token", "link_source", "locale", "protocol", "session", "shop", "tenant", "timestamp"];
|
|
20
29
|
declare function buildNavigationUpdatePayload(path: string): BridgeNavigationUpdatePayload;
|
|
21
30
|
declare function sanitizeEmbeddedAppPath(path: string | undefined): string | undefined;
|
|
22
31
|
declare function resolveLocalNavigationPath(href: string, currentOrigin: string): string | null;
|
|
23
32
|
declare function resolveNavigationDestination(payload: unknown): string | null;
|
|
33
|
+
declare function normalizeBridgeNavigationItem(item: BridgeNavigationItem): BridgeNavigationItem | null;
|
|
34
|
+
declare function normalizeBridgeNavigationItems(items: BridgeNavigationItem[] | undefined): BridgeNavigationItem[];
|
|
24
35
|
|
|
25
36
|
type BridgeParticipant = "embedded-app" | "dashboard" | "unknown";
|
|
26
37
|
type BridgeMessageKind = "event" | "request" | "response";
|
|
@@ -113,11 +124,12 @@ interface AppBridgeProviderProps extends Omit<AppBridgeOptions, "source" | "targ
|
|
|
113
124
|
readyEventType?: string;
|
|
114
125
|
readyPayload?: unknown;
|
|
115
126
|
currentPath?: string | null;
|
|
127
|
+
navigationItems?: BridgeNavigationItem[];
|
|
116
128
|
navigationEventType?: string;
|
|
117
129
|
navigationUpdateEventType?: string;
|
|
118
130
|
onNavigate?: (path: string, message?: ReceivedBridgeMessage<BridgeNavigationGoPayload>) => void;
|
|
119
131
|
}
|
|
120
|
-
declare function AppBridgeProvider({ children, clientId, currentPath, navigationEventType, navigationUpdateEventType, namespace, onNavigate, readyEventType, readyPayload, requestTimeoutMs, selfWindow, targetOrigin, targetWindow }: AppBridgeProviderProps): react_jsx_runtime.JSX.Element;
|
|
132
|
+
declare function AppBridgeProvider({ children, clientId, currentPath, navigationItems, navigationEventType, navigationUpdateEventType, namespace, onNavigate, readyEventType, readyPayload, requestTimeoutMs, selfWindow, targetOrigin, targetWindow }: AppBridgeProviderProps): react_jsx_runtime.JSX.Element;
|
|
121
133
|
declare function useAppBridge(): AppBridge | null;
|
|
122
134
|
|
|
123
|
-
export { AppBridge, type AppBridgeOptions, AppBridgeProvider, type AppBridgeProviderProps, type BridgeErrorPayload, type BridgeEventHandler, type BridgeMessage, type BridgeMessageKind, type BridgeNavigationGoPayload, type BridgeNavigationRedirectPayload, type BridgeNavigationUpdatePayload, type BridgeParticipant, type BridgeRequestHandler, EMBEDDED_LAUNCH_PARAMS, type ReceivedBridgeMessage, type RequestOptions, type SessionTokenRequest, type SessionTokenResponse, type Unsubscribe, buildNavigationUpdatePayload, createAppBridge, isBridgeMessage, resolveLocalNavigationPath, resolveNavigationDestination, sanitizeEmbeddedAppPath, useAppBridge };
|
|
135
|
+
export { AppBridge, type AppBridgeOptions, AppBridgeProvider, type AppBridgeProviderProps, type BridgeErrorPayload, type BridgeEventHandler, type BridgeMessage, type BridgeMessageKind, type BridgeNavigationGoPayload, type BridgeNavigationItem, type BridgeNavigationItemsPayload, type BridgeNavigationRedirectPayload, type BridgeNavigationUpdatePayload, type BridgeParticipant, type BridgeRequestHandler, EMBEDDED_LAUNCH_PARAMS, type ReceivedBridgeMessage, type RequestOptions, type SessionTokenRequest, type SessionTokenResponse, type Unsubscribe, buildNavigationUpdatePayload, createAppBridge, isBridgeMessage, normalizeBridgeNavigationItem, normalizeBridgeNavigationItems, resolveLocalNavigationPath, resolveNavigationDestination, sanitizeEmbeddedAppPath, useAppBridge };
|