import { buildMobileShellUrl, type MobileShellBaseWebUrlOptions, type MobileShellUrlOptions, resolveMobileShellBaseWebUrl, } from './url'; const supportedHosts = new Set(['open', 'app']); type MobileShellDeepLinkResolutionStatus = 'default' | 'mapped' | 'rejected'; export type MobileShellDeepLinkResolution = { status: MobileShellDeepLinkResolutionStatus; url: string; }; function extractPathFromNativeUrl(url: URL) { if (supportedHosts.has(url.hostname)) { return `${url.pathname}${url.search}${url.hash}`; } return `${url.hostname ? `/${url.hostname}` : ''}${url.pathname}${url.search}${url.hash}`; } function resolveTargetPath(rawUrl: string, webOrigin: string) { try { const url = new URL(rawUrl); if (url.protocol === 'genarrative:') { return extractPathFromNativeUrl(url); } if (url.protocol !== 'http:' && url.protocol !== 'https:') { return null; } if (url.origin !== webOrigin) { return null; } return `${url.pathname}${url.search}${url.hash}`; } catch { if (!rawUrl.startsWith('/') && !rawUrl.startsWith('#')) { return null; } try { const relativeUrl = new URL(rawUrl, webOrigin); if (relativeUrl.origin !== webOrigin) { return null; } return `${relativeUrl.pathname}${relativeUrl.search}${relativeUrl.hash}`; } catch { return null; } } } export function buildMobileShellUrlFromDeepLink( rawUrl: string | null | undefined, baseWebUrl: string, options: MobileShellUrlOptions, baseWebUrlOptions: MobileShellBaseWebUrlOptions = {}, ) { return resolveMobileShellUrlFromDeepLink( rawUrl, baseWebUrl, options, baseWebUrlOptions, ).url; } export function resolveMobileShellUrlFromDeepLink( rawUrl: string | null | undefined, baseWebUrl: string, options: MobileShellUrlOptions, baseWebUrlOptions: MobileShellBaseWebUrlOptions = {}, ): MobileShellDeepLinkResolution { const normalizedBaseWebUrl = resolveMobileShellBaseWebUrl( baseWebUrl, baseWebUrlOptions, ); const defaultUrl = buildMobileShellUrl( normalizedBaseWebUrl, options, baseWebUrlOptions, ); if (!rawUrl) { return { status: 'default', url: defaultUrl, }; } const webOrigin = new URL(normalizedBaseWebUrl).origin; const targetPath = resolveTargetPath(rawUrl, webOrigin); if (!targetPath) { return { status: 'rejected', url: defaultUrl, }; } return { status: 'mapped', url: buildMobileShellUrl( new URL(targetPath, webOrigin).toString(), options, baseWebUrlOptions, ), }; }