{"version":3,"sources":["../src/utils.ts","../src/detectionTelegram.ts","../src/detectionCustom.ts","../src/regexAppName.ts","../src/regexInApp.ts","../src/detectionSFSVC.ts","../src/index.ts"],"sourcesContent":["import { AppKey, Skip } from \"./types\";\n\nexport const WIN_ERROR =\n  \"Window is not available and no user agent was provided.\";\n\nexport const getUA = (): string => {\n  if (typeof window !== \"undefined\") {\n    const ua =\n      window?.navigator?.userAgent ||\n      window?.navigator?.vendor ||\n      // @ts-ignore\n      window?.opera;\n    if (ua) return ua;\n  }\n  console.error(WIN_ERROR);\n  return \"\";\n};\n\nexport const empty = {\n  isInApp: false,\n  appKey: undefined,\n  appName: undefined,\n  skipped: false,\n};\n\nexport const getIsAppleDevice = (ua: string) => {\n  return ua.match(/(iPhone|iPad|iPod|Macintosh)/) !== null;\n};\n\nexport const checkSkip = ({\n  skip,\n  appKey,\n  ua,\n}: {\n  skip?: Skip;\n  appKey: AppKey;\n  ua: string;\n}) => {\n  if (!skip || skip.length === 0) return false;\n  const isApple = getIsAppleDevice(ua);\n  return skip.some(\n    ({ appKey: excludeAppKey, platform }) =>\n      appKey === excludeAppKey &&\n      (!platform ||\n        (isApple && platform === \"apple\") ||\n        (!isApple && platform === \"android\"))\n  );\n};\n","export const getIsTelegram = () => {\n  return (\n    \"TelegramWebview\" in window || // Android\n    \"TelegramWebviewProxy\" in window || // iPhone\n    \"TelegramWebviewProxyProto\" in window // iPhone\n  );\n};\n","import { getIsTelegram } from \"./detectionTelegram\";\n\nexport const appNameCustom = {\n  telegram: {\n    name: \"Telegram\",\n  },\n} as const;\n\nexport const getDetectionCustom = () => {\n  if (typeof window === \"undefined\") return; // Skip if not in browser ie: server-side and only ua given\n  if (getIsTelegram()) return \"telegram\";\n  return;\n};\n\nexport const appKeysDetectByCustom = Object.keys(\n  appNameCustom\n) as (keyof typeof appNameCustom)[];\n","// NOTE: Consider getting the versions of known in-app browsers\nexport const appNameRegExps = {\n  messenger: {\n    regex:\n      /(\\bFB[\\w_]+\\/(Messenger))|(^(?!.*\\buseragents)(?!.*\\bIABMV).*(FB_IAB|FBAN).*)/i, // Experimental for newer UAs - don't have `\"useragents:\" or end in \"IABMV\"\n    name: \"Facebook Messenger\",\n  },\n  instagram: {\n    regex: /\\bInstagram/i,\n    name: \"Instagram\",\n  },\n  facebook: {\n    regex: /\\bFB[\\w_]+\\//,\n    name: \"Facebook\",\n  },\n  twitter: {\n    regex: /\\bTwitter/i,\n    name: \"Twitter\",\n  },\n  line: {\n    regex: /\\bLine\\//i,\n    name: \"Line\",\n  },\n  wechat: {\n    regex: /\\bMicroMessenger\\//i,\n    name: \"WeChat\",\n  },\n  threads: {\n    regex: /\\bBarcelona/i,\n    name: \"Threads\",\n  },\n  tiktok: {\n    regex: /musical_ly|Bytedance/i,\n    name: \"TikTok\",\n  },\n  snapchat: {\n    regex: /Snapchat/i,\n    name: \"Snapchat\",\n  },\n  linkedin: {\n    regex: /LinkedInApp/i,\n    name: \"LinkedIn\",\n  },\n  gsa: {\n    regex: /GSA/i,\n    name: \"Google Search App\",\n  },\n} as const;\n\nexport const appKeysDetectByUA = Object.keys(\n  appNameRegExps\n) as (keyof typeof appNameRegExps)[];\n\nexport const getAppKey = (ua: string) => {\n  return appKeysDetectByUA.find((appName) =>\n    appNameRegExps[appName].regex.test(ua)\n  );\n};\n","const inAppRegExps = [\n  \"WebView\",\n  \"(iPhone|iPod|iPad)(?!.*Safari/)\", // Apple devices but not with \"Safari/\" following\n  \"Android.*wv\\\\)\",\n  \"FB_\\\\w|FB\\\\w\", // Match Facebook FB_ or FB then word char\n  \"Snapchat\",\n  \"GSA\",\n] as const;\n\nexport const inappRegex = new RegExp(\n  `${inAppRegExps.map((reg) => `(${reg})`).join(\"|\")}`,\n  \"ig\"\n);\n","import { getIsTelegram } from \"./detectionTelegram\";\nimport { getUA } from \"./utils\";\n\n// True for Safari on iOS, iPadOS, macOS\nconst isSafariRegex = new RegExp(\n  /Mozilla\\/5\\.0 \\([^\\)]+\\) AppleWebKit\\/[^\\s]+ \\(KHTML, like Gecko\\) Version\\/[^\\s]+ (Mobile\\/[^\\s]+ )?Safari\\/[^\\s]+$/\n);\n\nexport const getIsSafariUA = (ua: string) => {\n  return isSafariRegex.test(ua);\n};\n\n// source https://github.com/bowser-js/bowser/issues/510\nexport const isiOS = (ua: string) => {\n  return (\n    [\n      \"iPad Simulator\",\n      \"iPhone Simulator\",\n      \"iPod Simulator\",\n      \"iPad\",\n      \"iPhone\",\n      \"iPod\",\n    ].includes(ua) ||\n    // iPad on iOS 13 detection\n    (window &&\n      window.document &&\n      ua.includes(\"Mac\") &&\n      \"ontouchend\" in window.document)\n  );\n};\n\nexport const getSafariVersion = (ua: string) => {\n  const match = [...ua.matchAll(/Version\\/([^\\s]+)/g)];\n  return match[0][1]; // right now just returns 17 or 18 etc (major version) but could be more specific\n};\n\n// Good enough for our usage - no prerelease versions or alpha/beta versions\n// -1 if a < b, 0 if a == b, 1 if a > b\nexport const compare = (a: string, b: string) => {\n  return a.localeCompare(b, undefined, { numeric: true, sensitivity: \"base\" });\n};\n\nexport const delay = (ms: number) => new Promise((res) => setTimeout(res, ms));\n\nexport async function waitForPageLoad() {\n  return new Promise((resolve) => {\n    if (window.document.readyState === \"complete\") {\n      // Resolve immediately if readyState is already 'complete'\n      resolve(true);\n    } else {\n      // Otherwise, listen for the load event\n      const onLoad = () => {\n        resolve(true);\n        window.removeEventListener(\"load\", onLoad);\n      };\n      window.addEventListener(\"load\", onLoad);\n    }\n  });\n}\n\n// Function to poll for properties on the window object\nconst pollForProperties = async ({\n  maxTime,\n  properties,\n  interval,\n}: {\n  properties: string[];\n  maxTime: number;\n  interval: number;\n}) => {\n  let elapsed = 0;\n\n  return new Promise((resolve) => {\n    const intervalId = setInterval(() => {\n      elapsed += interval;\n\n      // Check if any of the properties exist on window\n      for (const property of properties) {\n        if (property in window) {\n          clearInterval(intervalId);\n          resolve(true); // Resolve if the property is found\n          return;\n        }\n      }\n\n      // If time exceeds the timeout, stop polling and resolve false\n      if (elapsed >= maxTime) {\n        clearInterval(intervalId);\n        resolve(false);\n      }\n    }, interval);\n  });\n};\n\nconst consoleDebug = ({\n  note,\n  debug,\n  last,\n}: {\n  note?: string;\n  debug: boolean;\n  last?: boolean;\n}) => {\n  if (debug) {\n    console.log(\n      note,\n      \"SchemaDataExtractor\" in window || \"MicrodataExtractor\" in window\n        ? \"This is Safari\"\n        : last\n          ? \"Did not detect Safari - assuming SFSVC\"\n          : \"Still checking if Safari\",\n      performance.now()\n    );\n  }\n};\n\n// !! Experimental !!\n// *** Could give us a false positive ***\n// *** Escape hatch is `maxVersion` - Max Safari Version ***\nconst minSafariVersion = \"17\"; // could possibly be lower would need to check 16\nexport const getSFSVCExperimental = async ({\n  debug = false,\n  maxVersion,\n  maxTime = 300, // Max time to figure out if it is Safari (ie not SFSVC)\n}: {\n  debug?: boolean;\n  maxTime?: number;\n  maxVersion?: string;\n} = {}) => {\n  const ua = getUA();\n\n  if (!ua) return false; // No user agent\n  if (!isiOS(ua)) return false; // iPad or iPhone\n  if (!getIsSafariUA(ua)) return false; // Safari\n  if (\"clearAppBadge\" in (window?.navigator || {})) return false; // PWAs\n\n  // Targeted versions of Safari that we'll check\n  const version = getSafariVersion(ua);\n  if (compare(version, minSafariVersion) < 0) return false;\n  if (\n    maxVersion !== undefined &&\n    (compare(maxVersion, minSafariVersion) < 0 ||\n      compare(version, maxVersion) > 0)\n  )\n    return false;\n\n  if (getIsTelegram()) return false;\n\n  // Wait for SchemaDataExtractor or MicrodataExtractor to be defined\n  // This is experimental!\n  await waitForPageLoad();\n  if (debug) consoleDebug({ note: \"Page loaded\", debug });\n\n  // Poll for the properties (SchemaDataExtractor or MicrodataExtractor)\n  const isSafari = await pollForProperties({\n    interval: 60,\n    maxTime,\n    properties: [\"SchemaDataExtractor\", \"MicrodataExtractor\"],\n  });\n\n  if (debug) consoleDebug({ note: \"Extra polling done\", debug, last: true });\n\n  return !isSafari;\n};\n","import { checkSkip, getUA } from \"./utils\";\nimport { appNameCustom, getDetectionCustom } from \"./detectionCustom\";\nimport { AppKey, AppName, Skip } from \"./types\";\nimport { empty } from \"./utils\";\nimport { appNameRegExps, getAppKey } from \"./regexAppName\";\nimport { inappRegex } from \"./regexInApp\";\nimport { getSFSVCExperimental } from \"./detectionSFSVC\";\n\ndeclare const __GLOBAL__: boolean;\n\nconst InAppSpy = (\n  options: {\n    ua?: string;\n    skip?: Skip;\n  } = {}\n): {\n  ua: string;\n  isInApp: boolean;\n  appKey: AppKey;\n  appName: AppName;\n  skipped: boolean; // a helper to know if we successfully skipped the app\n} => {\n  const { skip, ua = \"\" } = options;\n  const userAgent = ua || getUA();\n\n  // No userAgent\n  if (!userAgent)\n    return {\n      ...empty,\n      ua: userAgent,\n    };\n\n  // If user provides a list of apps to skip\n  const skipFn = (key: AppKey) =>\n    checkSkip({ skip, appKey: key, ua: userAgent });\n\n  // UA detection method (most common)\n  // - This method should be used first - order matters\n  if (userAgent.match(inappRegex) !== null) {\n    const appKey = getAppKey(userAgent);\n    if (skipFn(appKey)) return { ...empty, ua: userAgent, skipped: true };\n    return {\n      isInApp: true,\n      appKey: appKey,\n      appName: appKey ? appNameRegExps[appKey]!.name : undefined,\n      ua: userAgent,\n      skipped: false,\n    };\n  }\n\n  // Custom detection\n  // - Cannot be parsed via ua only (ie via window keys instead)\n  const appKey = getDetectionCustom();\n  if (appKey) {\n    if (skipFn(appKey)) return { ...empty, ua: userAgent, skipped: true };\n    return {\n      isInApp: true,\n      appKey: appKey,\n      appName: appNameCustom?.[appKey]?.name,\n      ua: userAgent,\n      skipped: false,\n    };\n  }\n\n  // Didn't find anything\n  return {\n    ...empty,\n    ua: userAgent,\n  };\n};\n\n// Separate exports for experimental detection\nexport const SFSVCExperimental = getSFSVCExperimental;\nexport default InAppSpy;\n\n// Only attach if UMD build (CDN build)\nif (typeof window !== \"undefined\" && __GLOBAL__) {\n  (window as any).InAppSpy = InAppSpy; // Default export\n  (window as any).SFSVCExperimental = SFSVCExperimental; // Named export\n}\n"],"mappings":"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","names":["appKey"]}