posthog-js 1.200.2 → 1.201.1

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.
Files changed (57) hide show
  1. package/README.md +7 -0
  2. package/dist/all-external-dependencies.js.map +1 -1
  3. package/dist/array.full.es5.js +1 -1
  4. package/dist/array.full.es5.js.map +1 -1
  5. package/dist/array.full.js +1 -1
  6. package/dist/array.full.js.map +1 -1
  7. package/dist/array.full.no-external.js +1 -1
  8. package/dist/array.full.no-external.js.map +1 -1
  9. package/dist/array.js +1 -1
  10. package/dist/array.js.map +1 -1
  11. package/dist/array.no-external.js +1 -1
  12. package/dist/array.no-external.js.map +1 -1
  13. package/dist/customizations.full.js +1 -1
  14. package/dist/customizations.full.js.map +1 -1
  15. package/dist/dead-clicks-autocapture.js.map +1 -1
  16. package/dist/exception-autocapture.js.map +1 -1
  17. package/dist/external-scripts-loader.js.map +1 -1
  18. package/dist/main.js +1 -1
  19. package/dist/main.js.map +1 -1
  20. package/dist/module.d.ts +4 -2
  21. package/dist/module.full.d.ts +4 -2
  22. package/dist/module.full.js +1 -1
  23. package/dist/module.full.js.map +1 -1
  24. package/dist/module.full.no-external.d.ts +4 -2
  25. package/dist/module.full.no-external.js +1 -1
  26. package/dist/module.full.no-external.js.map +1 -1
  27. package/dist/module.js +1 -1
  28. package/dist/module.js.map +1 -1
  29. package/dist/module.no-external.d.ts +4 -2
  30. package/dist/module.no-external.js +1 -1
  31. package/dist/module.no-external.js.map +1 -1
  32. package/dist/recorder-v2.js.map +1 -1
  33. package/dist/recorder.js.map +1 -1
  34. package/dist/src/sessionid.d.ts +2 -0
  35. package/dist/src/types.d.ts +2 -2
  36. package/dist/surveys-preview.js.map +1 -1
  37. package/dist/surveys.js.map +1 -1
  38. package/dist/tracing-headers.js.map +1 -1
  39. package/lib/package.json +3 -3
  40. package/lib/src/entrypoints/dead-clicks-autocapture.js.map +1 -1
  41. package/lib/src/extensions/exception-autocapture/error-conversion.js +1 -1
  42. package/lib/src/extensions/exception-autocapture/error-conversion.js.map +1 -1
  43. package/lib/src/extensions/replay/config.js +1 -1
  44. package/lib/src/extensions/replay/config.js.map +1 -1
  45. package/lib/src/extensions/replay/sessionrecording.js.map +1 -1
  46. package/lib/src/posthog-core.js.map +1 -1
  47. package/lib/src/remote-config.js +30 -27
  48. package/lib/src/remote-config.js.map +1 -1
  49. package/lib/src/sessionid.d.ts +2 -0
  50. package/lib/src/sessionid.js +21 -9
  51. package/lib/src/sessionid.js.map +1 -1
  52. package/lib/src/types.d.ts +2 -2
  53. package/lib/src/types.js.map +1 -1
  54. package/lib/src/utils/event-utils.js.map +1 -1
  55. package/lib/src/utils/user-agent-utils.js.map +1 -1
  56. package/lib/src/web-experiments-types.js.map +1 -1
  57. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"tracing-headers.js","sources":["../src/utils/globals.ts","../src/types.ts","../src/extensions/replay/rrweb-plugins/patch.ts","../src/utils/type-utils.ts","../src/entrypoints/tracing-headers.ts"],"sourcesContent":["import { ErrorProperties } from '../extensions/exception-autocapture/error-conversion'\nimport type { PostHog } from '../posthog-core'\nimport { SessionIdManager } from '../sessionid'\nimport {\n DeadClicksAutoCaptureConfig,\n ErrorEventArgs,\n ErrorMetadata,\n Properties,\n RemoteConfig,\n SiteAppLoader,\n} from '../types'\n\n/*\n * Global helpers to protect access to browser globals in a way that is safer for different targets\n * like DOM, SSR, Web workers etc.\n *\n * NOTE: Typically we want the \"window\" but globalThis works for both the typical browser context as\n * well as other contexts such as the web worker context. Window is still exported for any bits that explicitly require it.\n * If in doubt - export the global you need from this file and use that as an optional value. This way the code path is forced\n * to handle the case where the global is not available.\n */\n\n// eslint-disable-next-line no-restricted-globals\nconst win: (Window & typeof globalThis) | undefined = typeof window !== 'undefined' ? window : undefined\n\nexport type AssignableWindow = Window &\n typeof globalThis &\n Record<string, any> & {\n __PosthogExtensions__?: PostHogExtensions\n _POSTHOG_CONFIG?: RemoteConfig\n _POSTHOG_JS_APPS?: SiteAppLoader[]\n }\n\n/**\n * This is our contract between (potentially) lazily loaded extensions and the SDK\n * changes to this interface can be breaking changes for users of the SDK\n */\n\nexport type PostHogExtensionKind =\n | 'toolbar'\n | 'exception-autocapture'\n | 'web-vitals'\n | 'recorder'\n | 'tracing-headers'\n | 'surveys'\n | 'dead-clicks-autocapture'\n | 'remote-config'\n\nexport interface LazyLoadedDeadClicksAutocaptureInterface {\n start: (observerTarget: Node) => void\n stop: () => void\n}\n\ninterface PostHogExtensions {\n loadExternalDependency?: (\n posthog: PostHog,\n kind: PostHogExtensionKind,\n callback: (error?: string | Event, event?: Event) => void\n ) => void\n\n loadSiteApp?: (posthog: PostHog, appUrl: string, callback: (error?: string | Event, event?: Event) => void) => void\n\n parseErrorAsProperties?: (\n [event, source, lineno, colno, error]: ErrorEventArgs,\n metadata?: ErrorMetadata\n ) => ErrorProperties\n errorWrappingFunctions?: {\n wrapOnError: (captureFn: (props: Properties) => void) => () => void\n wrapUnhandledRejection: (captureFn: (props: Properties) => void) => () => void\n }\n rrweb?: { record: any; version: string }\n rrwebPlugins?: { getRecordConsolePlugin: any; getRecordNetworkPlugin?: any }\n canActivateRepeatedly?: (survey: any) => boolean\n generateSurveys?: (posthog: PostHog) => any | undefined\n postHogWebVitalsCallbacks?: {\n onLCP: (metric: any) => void\n onCLS: (metric: any) => void\n onFCP: (metric: any) => void\n onINP: (metric: any) => void\n }\n tracingHeadersPatchFns?: {\n _patchFetch: (sessionManager?: SessionIdManager) => () => void\n _patchXHR: (sessionManager?: SessionIdManager) => () => void\n }\n initDeadClicksAutocapture?: (\n ph: PostHog,\n config: DeadClicksAutoCaptureConfig\n ) => LazyLoadedDeadClicksAutocaptureInterface\n}\n\nconst global: typeof globalThis | undefined = typeof globalThis !== 'undefined' ? globalThis : win\n\nexport const ArrayProto = Array.prototype\nexport const nativeForEach = ArrayProto.forEach\nexport const nativeIndexOf = ArrayProto.indexOf\n\nexport const navigator = global?.navigator\nexport const document = global?.document\nexport const location = global?.location\nexport const fetch = global?.fetch\nexport const XMLHttpRequest =\n global?.XMLHttpRequest && 'withCredentials' in new global.XMLHttpRequest() ? global.XMLHttpRequest : undefined\nexport const AbortController = global?.AbortController\nexport const userAgent = navigator?.userAgent\nexport const assignableWindow: AssignableWindow = win ?? ({} as any)\n\nexport { win as window }\n","import { PostHog } from './posthog-core'\nimport type { SegmentAnalytics } from './extensions/segment-integration'\nimport { recordOptions } from './extensions/replay/sessionrecording-utils'\n\nexport type Property = any\nexport type Properties = Record<string, Property>\n\nexport const COPY_AUTOCAPTURE_EVENT = '$copy_autocapture'\n\nexport const knownUnsafeEditableEvent = [\n '$snapshot',\n '$pageview',\n '$pageleave',\n '$set',\n 'survey dismissed',\n 'survey sent',\n 'survey shown',\n '$identify',\n '$groupidentify',\n '$create_alias',\n '$$client_ingestion_warning',\n '$web_experiment_applied',\n '$feature_enrollment_update',\n '$feature_flag_called',\n] as const\n\n/**\n * These events can be processed by the `beforeCapture` function\n * but can cause unexpected confusion in data.\n *\n * Some features of PostHog rely on receiving 100% of these events\n */\nexport type KnownUnsafeEditableEvent = typeof knownUnsafeEditableEvent[number]\n\n/**\n * These are known events PostHog events that can be processed by the `beforeCapture` function\n * That means PostHog functionality does not rely on receiving 100% of these for calculations\n * So, it is safe to sample them to reduce the volume of events sent to PostHog\n */\nexport type KnownEventName =\n | '$heatmaps_data'\n | '$opt_in'\n | '$exception'\n | '$$heatmap'\n | '$web_vitals'\n | '$dead_click'\n | '$autocapture'\n | typeof COPY_AUTOCAPTURE_EVENT\n | '$rageclick'\n\nexport type EventName =\n | KnownUnsafeEditableEvent\n | KnownEventName\n // magic value so that the type of EventName is a set of known strings or any other string\n // which means you get autocomplete for known strings\n // but no type complaints when you add an arbitrary string\n | (string & {})\n\nexport interface CaptureResult {\n uuid: string\n event: EventName\n properties: Properties\n $set?: Properties\n $set_once?: Properties\n timestamp?: Date\n}\n\nexport type AutocaptureCompatibleElement = 'a' | 'button' | 'form' | 'input' | 'select' | 'textarea' | 'label'\nexport type DomAutocaptureEvents = 'click' | 'change' | 'submit'\n\n/**\n * If an array is passed for an allowlist, autocapture events will only be sent for elements matching\n * at least one of the elements in the array. Multiple allowlists can be used\n */\nexport interface AutocaptureConfig {\n /**\n * List of URLs to allow autocapture on, can be strings to match\n * or regexes e.g. ['https://example.com', 'test.com/.*']\n * this is useful when you want to autocapture on specific pages only\n *\n * if you set both url_allowlist and url_ignorelist,\n * we check the allowlist first and then the ignorelist.\n * the ignorelist can override the allowlist\n */\n url_allowlist?: (string | RegExp)[]\n\n /**\n * List of URLs to not allow autocapture on, can be strings to match\n * or regexes e.g. ['https://example.com', 'test.com/.*']\n * this is useful when you want to autocapture on most pages but not some specific ones\n *\n * if you set both url_allowlist and url_ignorelist,\n * we check the allowlist first and then the ignorelist.\n * the ignorelist can override the allowlist\n */\n url_ignorelist?: (string | RegExp)[]\n\n /**\n * List of DOM events to allow autocapture on e.g. ['click', 'change', 'submit']\n */\n dom_event_allowlist?: DomAutocaptureEvents[]\n\n /**\n * List of DOM elements to allow autocapture on\n * e.g. ['a', 'button', 'form', 'input', 'select', 'textarea', 'label']\n * we consider the tree of elements from the root to the target element of the click event\n * so for the tree div > div > button > svg\n * if the allowlist has button then we allow the capture when the button or the svg is the click target\n * but not if either of the divs are detected as the click target\n */\n element_allowlist?: AutocaptureCompatibleElement[]\n\n /**\n * List of CSS selectors to allow autocapture on\n * e.g. ['[ph-capture]']\n * we consider the tree of elements from the root to the target element of the click event\n * so for the tree div > div > button > svg\n * and allow list config `['[id]']`\n * we will capture the click if the click-target or its parents has any id\n */\n css_selector_allowlist?: string[]\n\n /**\n * Exclude certain element attributes from autocapture\n * E.g. ['aria-label'] or [data-attr-pii]\n */\n element_attribute_ignorelist?: string[]\n\n capture_copied_text?: boolean\n}\n\nexport interface BootstrapConfig {\n distinctID?: string\n isIdentifiedID?: boolean\n featureFlags?: Record<string, boolean | string>\n featureFlagPayloads?: Record<string, JsonType>\n /**\n * Optionally provide a sessionID, this is so that you can provide an existing sessionID here to continue a user's session across a domain or device. It MUST be:\n * - unique to this user\n * - a valid UUID v7\n * - the timestamp part must be <= the timestamp of the first event in the session\n * - the timestamp of the last event in the session must be < the timestamp part + 24 hours\n * **/\n sessionID?: string\n}\n\nexport type SupportedWebVitalsMetrics = 'LCP' | 'CLS' | 'FCP' | 'INP'\n\nexport interface PerformanceCaptureConfig {\n /** works with session replay to use the browser's native performance observer to capture performance metrics */\n network_timing?: boolean\n /** use chrome's web vitals library to wrap fetch and capture web vitals */\n web_vitals?: boolean\n /**\n * We observe very large values reported by the Chrome web vitals library\n * These outliers are likely not real, useful values, and we exclude them\n * You can set this to 0 in order to include all values, NB this is not recommended\n * if not set this defaults to 15 minutes\n */\n __web_vitals_max_value?: number\n /**\n * By default all 4 metrics are captured\n * You can set this config to restrict which metrics are captured\n * e.g. ['CLS', 'FCP'] to only capture those two metrics\n * NB setting this does not override whether the capture is enabled\n */\n web_vitals_allowed_metrics?: SupportedWebVitalsMetrics[]\n /**\n * we delay flushing web vitals metrics to reduce the number of events we send\n * this is the maximum time we will wait before sending the metrics\n * if not set it defaults to 5 seconds\n */\n web_vitals_delayed_flush_ms?: number\n}\n\nexport interface DeadClickCandidate {\n node: Element\n originalEvent: MouseEvent\n timestamp: number\n // time between click and the most recent scroll\n scrollDelayMs?: number\n // time between click and the most recent mutation\n mutationDelayMs?: number\n // time between click and the most recent selection changed event\n selectionChangedDelayMs?: number\n // if neither scroll nor mutation seen before threshold passed\n absoluteDelayMs?: number\n}\n\nexport type DeadClicksAutoCaptureConfig = {\n // by default if a click is followed by a sroll within 100ms it is not a dead click\n scroll_threshold_ms?: number\n // by default if a click is followed by a selection change within 100ms it is not a dead click\n selection_change_threshold_ms?: number\n // by default if a click is followed by a mutation within 2500ms it is not a dead click\n mutation_threshold_ms?: number\n /**\n * Allows setting behavior for when a dead click is captured.\n * For e.g. to support capture to heatmaps\n *\n * If not provided the default behavior is to auto-capture dead click events\n *\n * Only intended to be provided by the SDK\n */\n __onCapture?: ((click: DeadClickCandidate, properties: Properties) => void) | undefined\n} & Pick<AutocaptureConfig, 'element_attribute_ignorelist'>\n\nexport interface HeatmapConfig {\n /*\n * how often to send batched data in $$heatmap_data events\n * if set to 0 or not set, sends using the default interval of 1 second\n * */\n flush_interval_milliseconds: number\n}\n\nexport type BeforeSendFn = (cr: CaptureResult | null) => CaptureResult | null\n\nexport interface PostHogConfig {\n api_host: string\n /** @deprecated - This property is no longer supported */\n api_method?: string\n api_transport?: 'XHR' | 'fetch'\n ui_host: string | null\n token: string\n autocapture: boolean | AutocaptureConfig\n rageclick: boolean\n cross_subdomain_cookie: boolean\n persistence: 'localStorage' | 'cookie' | 'memory' | 'localStorage+cookie' | 'sessionStorage'\n persistence_name: string\n /** @deprecated - Use 'persistence_name' instead */\n cookie_name?: string\n loaded: (posthog_instance: PostHog) => void\n store_google: boolean\n custom_campaign_params: string[]\n // a list of strings to be tested against navigator.userAgent to determine if the source is a bot\n // this is **added to** the default list of bots that we check\n // defaults to the empty array\n custom_blocked_useragents: string[]\n save_referrer: boolean\n verbose: boolean\n capture_pageview: boolean\n capture_pageleave: boolean | 'if_capture_pageview'\n debug: boolean\n cookie_expiration: number\n upgrade: boolean\n disable_session_recording: boolean\n disable_persistence: boolean\n /** @deprecated - use `disable_persistence` instead */\n disable_cookie?: boolean\n disable_surveys: boolean\n disable_web_experiments: boolean\n /** If set, posthog-js will never load external scripts such as those needed for Session Replay or Surveys. */\n disable_external_dependency_loading?: boolean\n enable_recording_console_log?: boolean\n secure_cookie: boolean\n ip: boolean\n /** Starts the SDK in an opted out state requiring opt_in_capturing() to be called before events will b captured */\n opt_out_capturing_by_default: boolean\n opt_out_capturing_persistence_type: 'localStorage' | 'cookie'\n /** If set to true this will disable persistence if the user is opted out of capturing. @default false */\n opt_out_persistence_by_default?: boolean\n /** Opt out of user agent filtering such as googlebot or other bots. Defaults to `false` */\n opt_out_useragent_filter: boolean\n\n opt_out_capturing_cookie_prefix: string | null\n opt_in_site_apps: boolean\n respect_dnt: boolean\n /** @deprecated - use `property_denylist` instead */\n property_blacklist?: string[]\n property_denylist: string[]\n request_headers: { [header_name: string]: string }\n on_request_error?: (error: RequestResponse) => void\n /** @deprecated - use `request_headers` instead */\n xhr_headers?: { [header_name: string]: string }\n /** @deprecated - use `on_request_error` instead */\n on_xhr_error?: (failedRequest: XMLHttpRequest) => void\n inapp_protocol: string\n inapp_link_new_window: boolean\n request_batching: boolean\n sanitize_properties: ((properties: Properties, event_name: string) => Properties) | null\n properties_string_max_length: number\n session_recording: SessionRecordingOptions\n session_idle_timeout_seconds: number\n mask_all_element_attributes: boolean\n mask_all_text: boolean\n advanced_disable_decide: boolean\n advanced_disable_feature_flags: boolean\n advanced_disable_feature_flags_on_first_load: boolean\n advanced_disable_toolbar_metrics: boolean\n feature_flag_request_timeout_ms: number\n get_device_id: (uuid: string) => string\n name: string\n /**\n * this is a read-only function that can be used to react to event capture\n * @deprecated - use `before_send` instead - NB before_send is not read only\n */\n _onCapture: (eventName: string, eventData: CaptureResult) => void\n /**\n * This function or array of functions - if provided - are called immediately before sending data to the server.\n * It allows you to edit data before it is sent, or choose not to send it all.\n * if provided as an array the functions are called in the order they are provided\n * any one function returning null means the event will not be sent\n */\n before_send?: BeforeSendFn | BeforeSendFn[]\n capture_performance?: boolean | PerformanceCaptureConfig\n // Should only be used for testing. Could negatively impact performance.\n disable_compression: boolean\n bootstrap: BootstrapConfig\n segment?: SegmentAnalytics\n __preview_send_client_session_params?: boolean\n /* @deprecated - use `capture_heatmaps` instead */\n enable_heatmaps?: boolean\n capture_heatmaps?: boolean | HeatmapConfig\n capture_dead_clicks?: boolean | DeadClicksAutoCaptureConfig\n disable_scroll_properties?: boolean\n // Let the pageview scroll stats use a custom css selector for the root element, e.g. `main`\n scroll_root_selector?: string | string[]\n\n /** You can control whether events from PostHog-js have person processing enabled with the `person_profiles` config setting. There are three options:\n * - `person_profiles: 'always'` _(default)_ - we will process persons data for all events\n * - `person_profiles: 'never'` - we won't process persons for any event. This means that anonymous users will not be merged once they sign up or login, so you lose the ability to create funnels that track users from anonymous to identified. All events (including `$identify`) will be sent with `$process_person_profile: False`.\n * - `person_profiles: 'identified_only'` - we will only process persons when you call `posthog.identify`, `posthog.alias`, `posthog.setPersonProperties`, `posthog.group`, `posthog.setPersonPropertiesForFlags` or `posthog.setGroupPropertiesForFlags` Anonymous users won't get person profiles.\n */\n person_profiles?: 'always' | 'never' | 'identified_only'\n /** @deprecated - use `person_profiles` instead */\n process_person?: 'always' | 'never' | 'identified_only'\n\n /** Client side rate limiting */\n rate_limiting?: {\n /** The average number of events per second that should be permitted (defaults to 10) */\n events_per_second?: number\n /** How many events can be captured in a burst. This defaults to 10 times the events_per_second count */\n events_burst_limit?: number\n }\n\n /** Used when sending data via `fetch`, use with care, this is intentionally meant to be used with NextJS `fetch`\n * Incorrect usage may cause out-of-date data for feature flags, actions tracking, etc.\n * See https://nextjs.org/docs/app/api-reference/functions/fetch#fetchurl-options\n */\n fetch_options?: {\n cache?: RequestInit['cache']\n next_options?: NextOptions\n }\n\n /**\n * PREVIEW - MAY CHANGE WITHOUT WARNING - DO NOT USE IN PRODUCTION\n * whether to wrap fetch and add tracing headers to the request\n * */\n __add_tracing_headers?: boolean\n\n /**\n * PREVIEW - MAY CHANGE WITHOUT WARNING - DO NOT USE IN PRODUCTION\n * enables the new RemoteConfig approach to loading config instead of decide\n * */\n __preview_remote_config?: boolean\n\n /**\n * PREVIEW - MAY CHANGE WITHOUT WARNING - DO NOT USE IN PRODUCTION\n * whether to send a sentinel value for distinct id, device id, and session id, which will be replaced server-side by a cookieless hash\n * */\n __preview_experimental_cookieless_mode?: boolean\n}\n\nexport interface OptInOutCapturingOptions {\n capture: (event: string, properties: Properties, options: CaptureOptions) => void\n capture_event_name: string\n capture_properties: Properties\n enable_persistence: boolean\n clear_persistence: boolean\n persistence_type: 'cookie' | 'localStorage' | 'localStorage+cookie'\n cookie_prefix: string\n cookie_expiration: number\n cross_subdomain_cookie: boolean\n secure_cookie: boolean\n}\n\nexport interface IsFeatureEnabledOptions {\n send_event: boolean\n}\n\nexport interface SessionRecordingOptions {\n blockClass?: string | RegExp\n blockSelector?: string | null\n ignoreClass?: string\n maskTextClass?: string | RegExp\n maskTextSelector?: string | null\n maskTextFn?: ((text: string, element: HTMLElement | null) => string) | null\n maskAllInputs?: boolean\n maskInputOptions?: recordOptions['maskInputOptions']\n maskInputFn?: ((text: string, element?: HTMLElement) => string) | null\n slimDOMOptions?: recordOptions['slimDOMOptions']\n collectFonts?: boolean\n inlineStylesheet?: boolean\n recordCrossOriginIframes?: boolean\n /**\n * Allows local config to override remote canvas recording settings from the decide response\n */\n captureCanvas?: SessionRecordingCanvasOptions\n /** @deprecated - use maskCapturedNetworkRequestFn instead */\n maskNetworkRequestFn?: ((data: NetworkRequest) => NetworkRequest | null | undefined) | null\n /** Modify the network request before it is captured. Returning null or undefined stops it being captured */\n maskCapturedNetworkRequestFn?: ((data: CapturedNetworkRequest) => CapturedNetworkRequest | null | undefined) | null\n // our settings here only support a subset of those proposed for rrweb's network capture plugin\n recordHeaders?: boolean\n recordBody?: boolean\n // ADVANCED: while a user is active we take a full snapshot of the browser every interval. For very few sites playback performance might be better with different interval. Set to 0 to disable\n full_snapshot_interval_millis?: number\n /*\n ADVANCED: whether to partially compress rrweb events before sending them to the server,\n defaults to true, can be set to false to disable partial compression\n NB requests are still compressed when sent to the server regardless of this setting\n */\n compress_events?: boolean\n /*\n ADVANCED: alters the threshold before a recording considers a user has become idle.\n Normally only altered alongside changes to session_idle_timeout_ms.\n Default is 5 minutes.\n */\n session_idle_threshold_ms?: number\n /*\n ADVANCED: alters the refill rate for the token bucket mutation throttling\n Normally only altered alongside posthog support guidance.\n Accepts values between 0 and 100\n Default is 10.\n */\n __mutationRateLimiterRefillRate?: number\n /*\n ADVANCED: alters the bucket size for the token bucket mutation throttling\n Normally only altered alongside posthog support guidance.\n Accepts values between 0 and 100\n Default is 100.\n */\n __mutationRateLimiterBucketSize?: number\n}\n\nexport type SessionIdChangedCallback = (\n sessionId: string,\n windowId: string | null | undefined,\n changeReason?: { noSessionId: boolean; activityTimeout: boolean; sessionPastMaximumLength: boolean }\n) => void\n\nexport enum Compression {\n GZipJS = 'gzip-js',\n Base64 = 'base64',\n}\n\n// Request types - these should be kept minimal to what request.ts needs\n\n// Minimal class to allow interop between different request methods (xhr / fetch)\nexport interface RequestResponse {\n statusCode: number\n text?: string\n json?: any\n}\n\nexport type RequestCallback = (response: RequestResponse) => void\n\n// See https://nextjs.org/docs/app/api-reference/functions/fetch#fetchurl-options\ntype NextOptions = { revalidate: false | 0 | number; tags: string[] }\n\nexport interface RequestOptions {\n url: string\n // Data can be a single object or an array of objects when batched\n data?: Record<string, any> | Record<string, any>[]\n headers?: Record<string, any>\n transport?: 'XHR' | 'fetch' | 'sendBeacon'\n method?: 'POST' | 'GET'\n urlQueryArgs?: { compression: Compression }\n callback?: RequestCallback\n timeout?: number\n noRetries?: boolean\n compression?: Compression | 'best-available'\n fetchOptions?: {\n cache?: RequestInit['cache']\n next?: NextOptions\n }\n}\n\n// Queued request types - the same as a request but with additional queueing information\n\nexport interface QueuedRequestOptions extends RequestOptions {\n batchKey?: string /** key of queue, e.g. 'sessionRecording' vs 'event' */\n}\n\n// Used explicitly for retriable requests\nexport interface RetriableRequestOptions extends QueuedRequestOptions {\n retriesPerformedSoFar?: number\n}\n\nexport interface CaptureOptions {\n $set?: Properties /** used with $identify */\n $set_once?: Properties /** used with $identify */\n _url?: string /** Used to override the desired endpoint for the captured event */\n _batchKey?: string /** key of queue, e.g. 'sessionRecording' vs 'event' */\n _noTruncate?: boolean /** if set, overrides and disables config.properties_string_max_length */\n send_instantly?: boolean /** if set skips the batched queue */\n skip_client_rate_limiting?: boolean /** if set skips the client side rate limiting */\n transport?: RequestOptions['transport'] /** if set, overrides the desired transport method */\n timestamp?: Date\n}\n\nexport type FlagVariant = { flag: string; variant: string }\n\nexport type SessionRecordingCanvasOptions = {\n recordCanvas?: boolean | null\n canvasFps?: number | null\n // the API returns a decimal between 0 and 1 as a string\n canvasQuality?: string | null\n}\n\nexport interface RemoteConfig {\n supportedCompression: Compression[]\n autocapture_opt_out?: boolean\n /**\n * originally capturePerformance was replay only and so boolean true\n * is equivalent to { network_timing: true }\n * now capture performance can be separately enabled within replay\n * and as a standalone web vitals tracker\n * people can have them enabled separately\n * they work standalone but enhance each other\n * TODO: deprecate this so we make a new config that doesn't need this explanation\n */\n capturePerformance?: boolean | PerformanceCaptureConfig\n analytics?: {\n endpoint?: string\n }\n elementsChainAsString?: boolean\n // this is currently in development and may have breaking changes without a major version bump\n autocaptureExceptions?:\n | boolean\n | {\n endpoint?: string\n }\n sessionRecording?: SessionRecordingCanvasOptions & {\n endpoint?: string\n consoleLogRecordingEnabled?: boolean\n // the API returns a decimal between 0 and 1 as a string\n sampleRate?: string | null\n minimumDurationMilliseconds?: number\n linkedFlag?: string | FlagVariant | null\n networkPayloadCapture?: Pick<NetworkRecordOptions, 'recordBody' | 'recordHeaders'>\n urlTriggers?: SessionRecordingUrlTrigger[]\n scriptConfig?: { script?: string | undefined }\n urlBlocklist?: SessionRecordingUrlTrigger[]\n eventTriggers?: string[]\n }\n surveys?: boolean\n toolbarParams: ToolbarParams\n editorParams?: ToolbarParams /** @deprecated, renamed to toolbarParams, still present on older API responses */\n toolbarVersion: 'toolbar' /** @deprecated, moved to toolbarParams */\n isAuthenticated: boolean\n siteApps: { id: string; url: string }[]\n heatmaps?: boolean\n defaultIdentifiedOnly?: boolean\n captureDeadClicks?: boolean\n hasFeatureFlags?: boolean // Indicates if the team has any flags enabled (if not we don't need to load them)\n}\n\nexport interface DecideResponse extends RemoteConfig {\n featureFlags: Record<string, string | boolean>\n featureFlagPayloads: Record<string, JsonType>\n errorsWhileComputingFlags: boolean\n}\n\nexport type SiteAppGlobals = {\n event: {\n uuid: string\n event: EventName\n properties: Properties\n timestamp?: Date\n elements_chain?: string\n distinct_id?: string\n }\n person: {\n properties: Properties\n }\n groups: Record<string, { id: string; type: string; properties: Properties }>\n}\n\nexport type SiteAppLoader = {\n id: string\n init: (config: { posthog: PostHog; callback: (success: boolean) => void }) => {\n processEvent?: (globals: SiteAppGlobals) => void\n }\n}\n\nexport type SiteApp = {\n id: string\n loaded: boolean\n errored: boolean\n processEvent?: (globals: SiteAppGlobals) => void\n}\n\nexport type FeatureFlagsCallback = (\n flags: string[],\n variants: Record<string, string | boolean>,\n context?: {\n errorsLoading?: boolean\n }\n) => void\n\nexport interface PersistentStore {\n is_supported: () => boolean\n error: (error: any) => void\n parse: (name: string) => any\n get: (name: string) => any\n set: (\n name: string,\n value: any,\n expire_days?: number | null,\n cross_subdomain?: boolean,\n secure?: boolean,\n debug?: boolean\n ) => void\n remove: (name: string, cross_subdomain?: boolean) => void\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Breaker = {}\nexport type EventHandler = (event: Event) => boolean | void\n\nexport type ToolbarUserIntent = 'add-action' | 'edit-action'\nexport type ToolbarSource = 'url' | 'localstorage'\nexport type ToolbarVersion = 'toolbar'\n\n/* sync with posthog */\nexport interface ToolbarParams {\n token?: string /** public posthog-js token */\n temporaryToken?: string /** private temporary user token */\n actionId?: number\n userIntent?: ToolbarUserIntent\n source?: ToolbarSource\n toolbarVersion?: ToolbarVersion\n instrument?: boolean\n distinctId?: string\n userEmail?: string\n dataAttributes?: string[]\n featureFlags?: Record<string, string | boolean>\n}\n\nexport type SnippetArrayItem = [method: string, ...args: any[]]\n\nexport type JsonRecord = { [key: string]: JsonType }\nexport type JsonType = string | number | boolean | null | JsonRecord | Array<JsonType>\n\n/** A feature that isn't publicly available yet.*/\nexport interface EarlyAccessFeature {\n // Sync this with the backend's EarlyAccessFeatureSerializer!\n name: string\n description: string\n stage: 'concept' | 'alpha' | 'beta'\n documentationUrl: string | null\n flagKey: string | null\n}\n\nexport type EarlyAccessFeatureCallback = (earlyAccessFeatures: EarlyAccessFeature[]) => void\n\nexport interface EarlyAccessFeatureResponse {\n earlyAccessFeatures: EarlyAccessFeature[]\n}\n\nexport type Headers = Record<string, string>\n\n/* for rrweb/network@1\n ** when that is released as part of rrweb this can be removed\n ** don't rely on this type, it may change without notice\n */\nexport type InitiatorType =\n | 'audio'\n | 'beacon'\n | 'body'\n | 'css'\n | 'early-hint'\n | 'embed'\n | 'fetch'\n | 'frame'\n | 'iframe'\n | 'icon'\n | 'image'\n | 'img'\n | 'input'\n | 'link'\n | 'navigation'\n | 'object'\n | 'ping'\n | 'script'\n | 'track'\n | 'video'\n | 'xmlhttprequest'\n\nexport type NetworkRecordOptions = {\n initiatorTypes?: InitiatorType[]\n maskRequestFn?: (data: CapturedNetworkRequest) => CapturedNetworkRequest | undefined\n recordHeaders?: boolean | { request: boolean; response: boolean }\n recordBody?: boolean | string[] | { request: boolean | string[]; response: boolean | string[] }\n recordInitialRequests?: boolean\n /**\n * whether to record PerformanceEntry events for network requests\n */\n recordPerformance?: boolean\n /**\n * the PerformanceObserver will only observe these entry types\n */\n performanceEntryTypeToObserve: string[]\n /**\n * the maximum size of the request/response body to record\n * NB this will be at most 1MB even if set larger\n */\n payloadSizeLimitBytes: number\n /**\n * some domains we should never record the payload\n * for example other companies session replay ingestion payloads aren't super useful but are gigantic\n * if this isn't provided we use a default list\n * if this is provided - we add the provided list to the default list\n * i.e. we never record the payloads on the default deny list\n */\n payloadHostDenyList?: string[]\n}\n\n/** @deprecated - use CapturedNetworkRequest instead */\nexport type NetworkRequest = {\n url: string\n}\n\n// In rrweb this is called NetworkRequest, but we already exposed that as having only URL\n// we also want to vary from the rrweb NetworkRequest because we want to include\n// all PerformanceEntry properties too.\n// that has 4 required properties\n// readonly duration: DOMHighResTimeStamp;\n// readonly entryType: string;\n// readonly name: string;\n// readonly startTime: DOMHighResTimeStamp;\n// NB: properties below here are ALPHA, don't rely on them, they may change without notice\n\n// we mirror PerformanceEntry since we read into this type from a PerformanceObserver,\n// but we don't want to inherit its readonly-iness\ntype Writable<T> = { -readonly [P in keyof T]: T[P] }\n\nexport type CapturedNetworkRequest = Writable<Omit<PerformanceEntry, 'toJSON'>> & {\n // properties below here are ALPHA, don't rely on them, they may change without notice\n method?: string\n initiatorType?: InitiatorType\n status?: number\n timeOrigin?: number\n timestamp?: number\n startTime?: number\n endTime?: number\n requestHeaders?: Headers\n requestBody?: string | null\n responseHeaders?: Headers\n responseBody?: string | null\n // was this captured before fetch/xhr could have been wrapped\n isInitial?: boolean\n}\n\nexport type ErrorEventArgs = [\n event: string | Event,\n source?: string | undefined,\n lineno?: number | undefined,\n colno?: number | undefined,\n error?: Error | undefined\n]\n\nexport type ErrorMetadata = {\n handled?: boolean\n synthetic?: boolean\n syntheticException?: Error\n overrideExceptionType?: string\n overrideExceptionMessage?: string\n defaultExceptionType?: string\n defaultExceptionMessage?: string\n}\n\n// levels originally copied from Sentry to work with the sentry integration\n// and to avoid relying on a frequently changing @sentry/types dependency\n// but provided as an array of literal types, so we can constrain the level below\nexport const severityLevels = ['fatal', 'error', 'warning', 'log', 'info', 'debug'] as const\nexport declare type SeverityLevel = typeof severityLevels[number]\n\nexport interface ErrorProperties {\n $exception_type: string\n $exception_message: string\n $exception_level: SeverityLevel\n $exception_source?: string\n $exception_lineno?: number\n $exception_colno?: number\n $exception_DOMException_code?: string\n $exception_is_synthetic?: boolean\n $exception_stack_trace_raw?: string\n $exception_handled?: boolean\n $exception_personURL?: string\n}\n\nexport interface ErrorConversions {\n errorToProperties: (args: ErrorEventArgs) => ErrorProperties\n unhandledRejectionToProperties: (args: [ev: PromiseRejectionEvent]) => ErrorProperties\n}\n\nexport interface SessionRecordingUrlTrigger {\n url: string\n matching: 'regex'\n}\n","// import { patch } from 'rrweb/typings/utils'\n// copied from https://github.com/rrweb-io/rrweb/blob/8aea5b00a4dfe5a6f59bd2ae72bb624f45e51e81/packages/rrweb/src/utils.ts#L129\n// which was copied from https://github.com/getsentry/sentry-javascript/blob/b2109071975af8bf0316d3b5b38f519bdaf5dc15/packages/utils/src/object.ts\nimport { isFunction } from '../../../utils/type-utils'\n\nexport function patch(\n source: { [key: string]: any },\n name: string,\n replacement: (...args: unknown[]) => unknown\n): () => void {\n try {\n if (!(name in source)) {\n return () => {\n //\n }\n }\n\n const original = source[name] as () => unknown\n const wrapped = replacement(original)\n\n // Make sure it's a function first, as we need to attach an empty prototype for `defineProperties` to work\n // otherwise it'll throw \"TypeError: Object.defineProperties called on non-object\"\n if (isFunction(wrapped)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n wrapped.prototype = wrapped.prototype || {}\n Object.defineProperties(wrapped, {\n __posthog_wrapped__: {\n enumerable: false,\n value: true,\n },\n })\n }\n\n source[name] = wrapped\n\n return () => {\n source[name] = original\n }\n } catch {\n return () => {\n //\n }\n // This can throw if multiple fill happens on a global object like XMLHttpRequest\n // Fixes https://github.com/getsentry/sentry-javascript/issues/2043\n }\n}\n","import { includes } from '.'\nimport { window } from './globals'\nimport { knownUnsafeEditableEvent, KnownUnsafeEditableEvent } from '../types'\n\n// eslint-disable-next-line posthog-js/no-direct-array-check\nconst nativeIsArray = Array.isArray\nconst ObjProto = Object.prototype\nexport const hasOwnProperty = ObjProto.hasOwnProperty\nconst toString = ObjProto.toString\n\nexport const isArray =\n nativeIsArray ||\n function (obj: any): obj is any[] {\n return toString.call(obj) === '[object Array]'\n }\n\n// from a comment on http://dbj.org/dbj/?p=286\n// fails on only one very rare and deliberate custom object:\n// let bomb = { toString : undefined, valueOf: function(o) { return \"function BOMBA!\"; }};\nexport const isFunction = (x: unknown): x is (...args: any[]) => any => {\n // eslint-disable-next-line posthog-js/no-direct-function-check\n return typeof x === 'function'\n}\n\nexport const isNativeFunction = (x: unknown): x is (...args: any[]) => any =>\n isFunction(x) && x.toString().indexOf('[native code]') !== -1\n\n// When angular patches functions they pass the above `isNativeFunction` check (at least the MutationObserver)\nexport const isAngularZonePresent = (): boolean => {\n return !!(window as any).Zone\n}\n\n// Underscore Addons\nexport const isObject = (x: unknown): x is Record<string, any> => {\n // eslint-disable-next-line posthog-js/no-direct-object-check\n return x === Object(x) && !isArray(x)\n}\nexport const isEmptyObject = (x: unknown): x is Record<string, any> => {\n if (isObject(x)) {\n for (const key in x) {\n if (hasOwnProperty.call(x, key)) {\n return false\n }\n }\n return true\n }\n return false\n}\nexport const isUndefined = (x: unknown): x is undefined => x === void 0\n\nexport const isString = (x: unknown): x is string => {\n // eslint-disable-next-line posthog-js/no-direct-string-check\n return toString.call(x) == '[object String]'\n}\n\nexport const isEmptyString = (x: unknown): boolean => isString(x) && x.trim().length === 0\n\nexport const isNull = (x: unknown): x is null => {\n // eslint-disable-next-line posthog-js/no-direct-null-check\n return x === null\n}\n\n/*\n sometimes you want to check if something is null or undefined\n that's what this is for\n */\nexport const isNullish = (x: unknown): x is null | undefined => isUndefined(x) || isNull(x)\n\nexport const isNumber = (x: unknown): x is number => {\n // eslint-disable-next-line posthog-js/no-direct-number-check\n return toString.call(x) == '[object Number]'\n}\nexport const isBoolean = (x: unknown): x is boolean => {\n // eslint-disable-next-line posthog-js/no-direct-boolean-check\n return toString.call(x) === '[object Boolean]'\n}\n\nexport const isDocument = (x: unknown): x is Document => {\n // eslint-disable-next-line posthog-js/no-direct-document-check\n return x instanceof Document\n}\n\nexport const isFormData = (x: unknown): x is FormData => {\n // eslint-disable-next-line posthog-js/no-direct-form-data-check\n return x instanceof FormData\n}\n\nexport const isFile = (x: unknown): x is File => {\n // eslint-disable-next-line posthog-js/no-direct-file-check\n return x instanceof File\n}\n\nexport const isKnownUnsafeEditableEvent = (x: unknown): x is KnownUnsafeEditableEvent => {\n return includes(knownUnsafeEditableEvent as unknown as string[], x)\n}\n","import { SessionIdManager } from '../sessionid'\nimport { patch } from '../extensions/replay/rrweb-plugins/patch'\nimport { assignableWindow, window } from '../utils/globals'\n\nconst addTracingHeaders = (sessionManager: SessionIdManager | undefined, req: Request) => {\n if (sessionManager) {\n const { sessionId, windowId } = sessionManager.checkAndGetSessionAndWindowId(true)\n req.headers.set('X-POSTHOG-SESSION-ID', sessionId)\n req.headers.set('X-POSTHOG-WINDOW-ID', windowId)\n }\n}\n\nconst patchFetch = (sessionManager?: SessionIdManager): (() => void) => {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return patch(window, 'fetch', (originalFetch: typeof fetch) => {\n return async function (url: URL | RequestInfo, init?: RequestInit | undefined) {\n // check IE earlier than this, we only initialize if Request is present\n // eslint-disable-next-line compat/compat\n const req = new Request(url, init)\n\n addTracingHeaders(sessionManager, req)\n\n return originalFetch(req)\n }\n })\n}\n\nconst patchXHR = (sessionManager?: SessionIdManager): (() => void) => {\n return patch(\n // we can assert this is present because we've checked previously\n window!.XMLHttpRequest.prototype,\n 'open',\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n (originalOpen: typeof XMLHttpRequest.prototype.open) => {\n return function (\n method: string,\n url: string | URL,\n async = true,\n username?: string | null,\n password?: string | null\n ) {\n // because this function is returned in its actual context `this` _is_ an XMLHttpRequest\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const xhr = this as XMLHttpRequest\n\n // check IE earlier than this, we only initialize if Request is present\n // eslint-disable-next-line compat/compat\n const req = new Request(url)\n\n addTracingHeaders(sessionManager, req)\n\n return originalOpen.call(xhr, method, req.url, async, username, password)\n }\n }\n )\n}\n\nassignableWindow.__PosthogExtensions__ = assignableWindow.__PosthogExtensions__ || {}\nconst patchFns = {\n _patchFetch: patchFetch,\n _patchXHR: patchXHR,\n}\nassignableWindow.__PosthogExtensions__.tracingHeadersPatchFns = patchFns\n\n// we used to put tracingHeadersPatchFns on window, and now we put it on __PosthogExtensions__\n// but that means that old clients which lazily load this extension are looking in the wrong place\n// yuck,\n// so we also put it directly on the window\n// when 1.161.1 is the oldest version seen in production we can remove this\nassignableWindow.postHogTracingHeadersPatchFns = patchFns\n\nexport default patchFns\n"],"names":["win","window","undefined","global","globalThis","navigator","document","location","fetch","XMLHttpRequest","AbortController","userAgent","Compression","assignableWindow","patch","source","name","replacement","original","wrapped","prototype","Object","defineProperties","__posthog_wrapped__","enumerable","value","_unused","addTracingHeaders","sessionManager","req","sessionId","windowId","checkAndGetSessionAndWindowId","headers","set","__PosthogExtensions__","patchFns","_patchFetch","originalFetch","_ref","url","init","Request","_x","_x2","apply","this","arguments","_patchXHR","originalOpen","method","async","length","username","password","call","tracingHeadersPatchFns","postHogTracingHeadersPatchFns"],"mappings":"kJAuBA,IAAMA,EAAkE,oBAAXC,OAAyBA,YAASC,EAmEzFC,EAA8D,oBAAfC,WAA6BA,WAAaJ,EAMlFK,EAAYF,aAAM,EAANA,EAAQE,UACTF,SAAAA,EAAQG,SACRH,SAAAA,EAAQI,SACXJ,SAAAA,EAAQK,MAEzBL,SAAAA,EAAQM,gBAAkB,oBAAqB,IAAIN,EAAOM,gBAAmBN,EAAOM,eACzDN,SAAAA,EAAQO,gBACdL,SAAAA,EAAWM,UAC7B,ICiVKC,EDjVCC,EAAqCb,QAAAA,EAAQ,CAAU,GCwVpE,SAPYY,GAAAA,EAAW,OAAA,UAAXA,EAAW,OAAA,QAAXA,CAOZ,CAPYA,IAAAA,EAgBZ,CAAA,ICpcO,SAASE,EACZC,EACAC,EACAC,GAEA,IACI,KAAMD,KAAQD,GACV,MAAO,OAKX,IAAMG,EAAWH,EAAOC,GAClBG,EAAUF,EAAYC,GAiB5B,MCdgB,mBDCDC,IAEXA,EAAQC,UAAYD,EAAQC,WAAa,CAAA,EACzCC,OAAOC,iBAAiBH,EAAS,CAC7BI,oBAAqB,CACjBC,YAAY,EACZC,OAAO,MAKnBV,EAAOC,GAAQG,EAER,KACHJ,EAAOC,GAAQE,CAAQ,CAE9B,CAAC,MAAAQ,GACE,MAAO,MAKX,CACJ,CEzCA,IAAMC,EAAoBA,CAACC,EAA8CC,KACrE,GAAID,EAAgB,CAChB,IAAME,UAAEA,EAASC,SAAEA,GAAaH,EAAeI,+BAA8B,GAC7EH,EAAII,QAAQC,IAAI,uBAAwBJ,GACxCD,EAAII,QAAQC,IAAI,sBAAuBH,EAC3C,GAmDJlB,EAAiBsB,sBAAwBtB,EAAiBsB,uBAAyB,GACnF,IAAMC,EAAW,CACbC,YAlDgBT,GAGTd,EAAMb,EAAQ,SAAUqC,GAC3B,WAAA,MAAAC,KAAO,UAAgBC,EAAwBC,GAG3C,IAAMZ,EAAM,IAAIa,QAAQF,EAAKC,GAI7B,OAFAd,EAAkBC,EAAgBC,GAE3BS,EAAcT,mLACxB,OAAAc,SAAAA,EAAAC,GAAA,OAAAL,EAAAM,MAAAC,KAAAC,UAAA,CAAA,CARD,KA+CJC,UAnCcpB,GACPd,EAEHb,EAAQQ,eAAeW,UACvB,QAGC6B,GACU,SACHC,EACAV,GAIF,IAHEW,IAAKJ,UAAAK,OAAA,QAAAlD,IAAA6C,UAAA,KAAAA,UAAA,GACLM,EAAwBN,UAAAK,OAAAL,EAAAA,kBAAA7C,EACxBoD,EAAwBP,UAAAK,OAAAL,EAAAA,kBAAA7C,EASlB2B,EAAM,IAAIa,QAAQF,GAIxB,OAFAb,EAAkBC,EAAgBC,GAE3BoB,EAAaM,KARRT,KAQkBI,EAAQrB,EAAIW,IAAKW,EAAOE,EAAUC,OAWhFzC,EAAiBsB,sBAAsBqB,uBAAyBpB,EAOhEvB,EAAiB4C,8BAAgCrB"}
1
+ {"version":3,"file":"tracing-headers.js","sources":["../src/utils/globals.ts","../src/types.ts","../src/extensions/replay/rrweb-plugins/patch.ts","../src/utils/type-utils.ts","../src/entrypoints/tracing-headers.ts"],"sourcesContent":["import { ErrorProperties } from '../extensions/exception-autocapture/error-conversion'\nimport type { PostHog } from '../posthog-core'\nimport { SessionIdManager } from '../sessionid'\nimport {\n DeadClicksAutoCaptureConfig,\n ErrorEventArgs,\n ErrorMetadata,\n Properties,\n RemoteConfig,\n SiteAppLoader,\n} from '../types'\n\n/*\n * Global helpers to protect access to browser globals in a way that is safer for different targets\n * like DOM, SSR, Web workers etc.\n *\n * NOTE: Typically we want the \"window\" but globalThis works for both the typical browser context as\n * well as other contexts such as the web worker context. Window is still exported for any bits that explicitly require it.\n * If in doubt - export the global you need from this file and use that as an optional value. This way the code path is forced\n * to handle the case where the global is not available.\n */\n\n// eslint-disable-next-line no-restricted-globals\nconst win: (Window & typeof globalThis) | undefined = typeof window !== 'undefined' ? window : undefined\n\nexport type AssignableWindow = Window &\n typeof globalThis &\n Record<string, any> & {\n __PosthogExtensions__?: PostHogExtensions\n _POSTHOG_CONFIG?: RemoteConfig\n _POSTHOG_JS_APPS?: SiteAppLoader[]\n }\n\n/**\n * This is our contract between (potentially) lazily loaded extensions and the SDK\n * changes to this interface can be breaking changes for users of the SDK\n */\n\nexport type PostHogExtensionKind =\n | 'toolbar'\n | 'exception-autocapture'\n | 'web-vitals'\n | 'recorder'\n | 'tracing-headers'\n | 'surveys'\n | 'dead-clicks-autocapture'\n | 'remote-config'\n\nexport interface LazyLoadedDeadClicksAutocaptureInterface {\n start: (observerTarget: Node) => void\n stop: () => void\n}\n\ninterface PostHogExtensions {\n loadExternalDependency?: (\n posthog: PostHog,\n kind: PostHogExtensionKind,\n callback: (error?: string | Event, event?: Event) => void\n ) => void\n\n loadSiteApp?: (posthog: PostHog, appUrl: string, callback: (error?: string | Event, event?: Event) => void) => void\n\n parseErrorAsProperties?: (\n [event, source, lineno, colno, error]: ErrorEventArgs,\n metadata?: ErrorMetadata\n ) => ErrorProperties\n errorWrappingFunctions?: {\n wrapOnError: (captureFn: (props: Properties) => void) => () => void\n wrapUnhandledRejection: (captureFn: (props: Properties) => void) => () => void\n }\n rrweb?: { record: any; version: string }\n rrwebPlugins?: { getRecordConsolePlugin: any; getRecordNetworkPlugin?: any }\n canActivateRepeatedly?: (survey: any) => boolean\n generateSurveys?: (posthog: PostHog) => any | undefined\n postHogWebVitalsCallbacks?: {\n onLCP: (metric: any) => void\n onCLS: (metric: any) => void\n onFCP: (metric: any) => void\n onINP: (metric: any) => void\n }\n tracingHeadersPatchFns?: {\n _patchFetch: (sessionManager?: SessionIdManager) => () => void\n _patchXHR: (sessionManager?: SessionIdManager) => () => void\n }\n initDeadClicksAutocapture?: (\n ph: PostHog,\n config: DeadClicksAutoCaptureConfig\n ) => LazyLoadedDeadClicksAutocaptureInterface\n}\n\nconst global: typeof globalThis | undefined = typeof globalThis !== 'undefined' ? globalThis : win\n\nexport const ArrayProto = Array.prototype\nexport const nativeForEach = ArrayProto.forEach\nexport const nativeIndexOf = ArrayProto.indexOf\n\nexport const navigator = global?.navigator\nexport const document = global?.document\nexport const location = global?.location\nexport const fetch = global?.fetch\nexport const XMLHttpRequest =\n global?.XMLHttpRequest && 'withCredentials' in new global.XMLHttpRequest() ? global.XMLHttpRequest : undefined\nexport const AbortController = global?.AbortController\nexport const userAgent = navigator?.userAgent\nexport const assignableWindow: AssignableWindow = win ?? ({} as any)\n\nexport { win as window }\n","import { PostHog } from './posthog-core'\nimport type { SegmentAnalytics } from './extensions/segment-integration'\nimport { recordOptions } from './extensions/replay/sessionrecording-utils'\n\nexport type Property = any\nexport type Properties = Record<string, Property>\n\nexport const COPY_AUTOCAPTURE_EVENT = '$copy_autocapture'\n\nexport const knownUnsafeEditableEvent = [\n '$snapshot',\n '$pageview',\n '$pageleave',\n '$set',\n 'survey dismissed',\n 'survey sent',\n 'survey shown',\n '$identify',\n '$groupidentify',\n '$create_alias',\n '$$client_ingestion_warning',\n '$web_experiment_applied',\n '$feature_enrollment_update',\n '$feature_flag_called',\n] as const\n\n/**\n * These events can be processed by the `beforeCapture` function\n * but can cause unexpected confusion in data.\n *\n * Some features of PostHog rely on receiving 100% of these events\n */\nexport type KnownUnsafeEditableEvent = (typeof knownUnsafeEditableEvent)[number]\n\n/**\n * These are known events PostHog events that can be processed by the `beforeCapture` function\n * That means PostHog functionality does not rely on receiving 100% of these for calculations\n * So, it is safe to sample them to reduce the volume of events sent to PostHog\n */\nexport type KnownEventName =\n | '$heatmaps_data'\n | '$opt_in'\n | '$exception'\n | '$$heatmap'\n | '$web_vitals'\n | '$dead_click'\n | '$autocapture'\n | typeof COPY_AUTOCAPTURE_EVENT\n | '$rageclick'\n\nexport type EventName =\n | KnownUnsafeEditableEvent\n | KnownEventName\n // magic value so that the type of EventName is a set of known strings or any other string\n // which means you get autocomplete for known strings\n // but no type complaints when you add an arbitrary string\n | (string & {})\n\nexport interface CaptureResult {\n uuid: string\n event: EventName\n properties: Properties\n $set?: Properties\n $set_once?: Properties\n timestamp?: Date\n}\n\nexport type AutocaptureCompatibleElement = 'a' | 'button' | 'form' | 'input' | 'select' | 'textarea' | 'label'\nexport type DomAutocaptureEvents = 'click' | 'change' | 'submit'\n\n/**\n * If an array is passed for an allowlist, autocapture events will only be sent for elements matching\n * at least one of the elements in the array. Multiple allowlists can be used\n */\nexport interface AutocaptureConfig {\n /**\n * List of URLs to allow autocapture on, can be strings to match\n * or regexes e.g. ['https://example.com', 'test.com/.*']\n * this is useful when you want to autocapture on specific pages only\n *\n * if you set both url_allowlist and url_ignorelist,\n * we check the allowlist first and then the ignorelist.\n * the ignorelist can override the allowlist\n */\n url_allowlist?: (string | RegExp)[]\n\n /**\n * List of URLs to not allow autocapture on, can be strings to match\n * or regexes e.g. ['https://example.com', 'test.com/.*']\n * this is useful when you want to autocapture on most pages but not some specific ones\n *\n * if you set both url_allowlist and url_ignorelist,\n * we check the allowlist first and then the ignorelist.\n * the ignorelist can override the allowlist\n */\n url_ignorelist?: (string | RegExp)[]\n\n /**\n * List of DOM events to allow autocapture on e.g. ['click', 'change', 'submit']\n */\n dom_event_allowlist?: DomAutocaptureEvents[]\n\n /**\n * List of DOM elements to allow autocapture on\n * e.g. ['a', 'button', 'form', 'input', 'select', 'textarea', 'label']\n * we consider the tree of elements from the root to the target element of the click event\n * so for the tree div > div > button > svg\n * if the allowlist has button then we allow the capture when the button or the svg is the click target\n * but not if either of the divs are detected as the click target\n */\n element_allowlist?: AutocaptureCompatibleElement[]\n\n /**\n * List of CSS selectors to allow autocapture on\n * e.g. ['[ph-capture]']\n * we consider the tree of elements from the root to the target element of the click event\n * so for the tree div > div > button > svg\n * and allow list config `['[id]']`\n * we will capture the click if the click-target or its parents has any id\n */\n css_selector_allowlist?: string[]\n\n /**\n * Exclude certain element attributes from autocapture\n * E.g. ['aria-label'] or [data-attr-pii]\n */\n element_attribute_ignorelist?: string[]\n\n capture_copied_text?: boolean\n}\n\nexport interface BootstrapConfig {\n distinctID?: string\n isIdentifiedID?: boolean\n featureFlags?: Record<string, boolean | string>\n featureFlagPayloads?: Record<string, JsonType>\n /**\n * Optionally provide a sessionID, this is so that you can provide an existing sessionID here to continue a user's session across a domain or device. It MUST be:\n * - unique to this user\n * - a valid UUID v7\n * - the timestamp part must be <= the timestamp of the first event in the session\n * - the timestamp of the last event in the session must be < the timestamp part + 24 hours\n * **/\n sessionID?: string\n}\n\nexport type SupportedWebVitalsMetrics = 'LCP' | 'CLS' | 'FCP' | 'INP'\n\nexport interface PerformanceCaptureConfig {\n /** works with session replay to use the browser's native performance observer to capture performance metrics */\n network_timing?: boolean\n /** use chrome's web vitals library to wrap fetch and capture web vitals */\n web_vitals?: boolean\n /**\n * We observe very large values reported by the Chrome web vitals library\n * These outliers are likely not real, useful values, and we exclude them\n * You can set this to 0 in order to include all values, NB this is not recommended\n * if not set this defaults to 15 minutes\n */\n __web_vitals_max_value?: number\n /**\n * By default all 4 metrics are captured\n * You can set this config to restrict which metrics are captured\n * e.g. ['CLS', 'FCP'] to only capture those two metrics\n * NB setting this does not override whether the capture is enabled\n */\n web_vitals_allowed_metrics?: SupportedWebVitalsMetrics[]\n /**\n * we delay flushing web vitals metrics to reduce the number of events we send\n * this is the maximum time we will wait before sending the metrics\n * if not set it defaults to 5 seconds\n */\n web_vitals_delayed_flush_ms?: number\n}\n\nexport interface DeadClickCandidate {\n node: Element\n originalEvent: MouseEvent\n timestamp: number\n // time between click and the most recent scroll\n scrollDelayMs?: number\n // time between click and the most recent mutation\n mutationDelayMs?: number\n // time between click and the most recent selection changed event\n selectionChangedDelayMs?: number\n // if neither scroll nor mutation seen before threshold passed\n absoluteDelayMs?: number\n}\n\nexport type DeadClicksAutoCaptureConfig = {\n // by default if a click is followed by a sroll within 100ms it is not a dead click\n scroll_threshold_ms?: number\n // by default if a click is followed by a selection change within 100ms it is not a dead click\n selection_change_threshold_ms?: number\n // by default if a click is followed by a mutation within 2500ms it is not a dead click\n mutation_threshold_ms?: number\n /**\n * Allows setting behavior for when a dead click is captured.\n * For e.g. to support capture to heatmaps\n *\n * If not provided the default behavior is to auto-capture dead click events\n *\n * Only intended to be provided by the SDK\n */\n __onCapture?: ((click: DeadClickCandidate, properties: Properties) => void) | undefined\n} & Pick<AutocaptureConfig, 'element_attribute_ignorelist'>\n\nexport interface HeatmapConfig {\n /*\n * how often to send batched data in $$heatmap_data events\n * if set to 0 or not set, sends using the default interval of 1 second\n * */\n flush_interval_milliseconds: number\n}\n\nexport type BeforeSendFn = (cr: CaptureResult | null) => CaptureResult | null\n\nexport interface PostHogConfig {\n api_host: string\n /** @deprecated - This property is no longer supported */\n api_method?: string\n api_transport?: 'XHR' | 'fetch'\n ui_host: string | null\n token: string\n autocapture: boolean | AutocaptureConfig\n rageclick: boolean\n cross_subdomain_cookie: boolean\n persistence: 'localStorage' | 'cookie' | 'memory' | 'localStorage+cookie' | 'sessionStorage'\n persistence_name: string\n /** @deprecated - Use 'persistence_name' instead */\n cookie_name?: string\n loaded: (posthog_instance: PostHog) => void\n store_google: boolean\n custom_campaign_params: string[]\n // a list of strings to be tested against navigator.userAgent to determine if the source is a bot\n // this is **added to** the default list of bots that we check\n // defaults to the empty array\n custom_blocked_useragents: string[]\n save_referrer: boolean\n verbose: boolean\n capture_pageview: boolean\n capture_pageleave: boolean | 'if_capture_pageview'\n debug: boolean\n cookie_expiration: number\n upgrade: boolean\n disable_session_recording: boolean\n disable_persistence: boolean\n /** @deprecated - use `disable_persistence` instead */\n disable_cookie?: boolean\n disable_surveys: boolean\n disable_web_experiments: boolean\n /** If set, posthog-js will never load external scripts such as those needed for Session Replay or Surveys. */\n disable_external_dependency_loading?: boolean\n enable_recording_console_log?: boolean\n secure_cookie: boolean\n ip: boolean\n /** Starts the SDK in an opted out state requiring opt_in_capturing() to be called before events will b captured */\n opt_out_capturing_by_default: boolean\n opt_out_capturing_persistence_type: 'localStorage' | 'cookie'\n /** If set to true this will disable persistence if the user is opted out of capturing. @default false */\n opt_out_persistence_by_default?: boolean\n /** Opt out of user agent filtering such as googlebot or other bots. Defaults to `false` */\n opt_out_useragent_filter: boolean\n\n opt_out_capturing_cookie_prefix: string | null\n opt_in_site_apps: boolean\n respect_dnt: boolean\n /** @deprecated - use `property_denylist` instead */\n property_blacklist?: string[]\n property_denylist: string[]\n request_headers: { [header_name: string]: string }\n on_request_error?: (error: RequestResponse) => void\n /** @deprecated - use `request_headers` instead */\n xhr_headers?: { [header_name: string]: string }\n /** @deprecated - use `on_request_error` instead */\n on_xhr_error?: (failedRequest: XMLHttpRequest) => void\n inapp_protocol: string\n inapp_link_new_window: boolean\n request_batching: boolean\n sanitize_properties: ((properties: Properties, event_name: string) => Properties) | null\n properties_string_max_length: number\n session_recording: SessionRecordingOptions\n session_idle_timeout_seconds: number\n mask_all_element_attributes: boolean\n mask_all_text: boolean\n advanced_disable_decide: boolean\n advanced_disable_feature_flags: boolean\n advanced_disable_feature_flags_on_first_load: boolean\n advanced_disable_toolbar_metrics: boolean\n feature_flag_request_timeout_ms: number\n get_device_id: (uuid: string) => string\n name: string\n /**\n * this is a read-only function that can be used to react to event capture\n * @deprecated - use `before_send` instead - NB before_send is not read only\n */\n _onCapture: (eventName: string, eventData: CaptureResult) => void\n /**\n * This function or array of functions - if provided - are called immediately before sending data to the server.\n * It allows you to edit data before it is sent, or choose not to send it all.\n * if provided as an array the functions are called in the order they are provided\n * any one function returning null means the event will not be sent\n */\n before_send?: BeforeSendFn | BeforeSendFn[]\n capture_performance?: boolean | PerformanceCaptureConfig\n // Should only be used for testing. Could negatively impact performance.\n disable_compression: boolean\n bootstrap: BootstrapConfig\n segment?: SegmentAnalytics\n __preview_send_client_session_params?: boolean\n /* @deprecated - use `capture_heatmaps` instead */\n enable_heatmaps?: boolean\n capture_heatmaps?: boolean | HeatmapConfig\n capture_dead_clicks?: boolean | DeadClicksAutoCaptureConfig\n disable_scroll_properties?: boolean\n // Let the pageview scroll stats use a custom css selector for the root element, e.g. `main`\n scroll_root_selector?: string | string[]\n\n /** You can control whether events from PostHog-js have person processing enabled with the `person_profiles` config setting. There are three options:\n * - `person_profiles: 'always'` _(default)_ - we will process persons data for all events\n * - `person_profiles: 'never'` - we won't process persons for any event. This means that anonymous users will not be merged once they sign up or login, so you lose the ability to create funnels that track users from anonymous to identified. All events (including `$identify`) will be sent with `$process_person_profile: False`.\n * - `person_profiles: 'identified_only'` - we will only process persons when you call `posthog.identify`, `posthog.alias`, `posthog.setPersonProperties`, `posthog.group`, `posthog.setPersonPropertiesForFlags` or `posthog.setGroupPropertiesForFlags` Anonymous users won't get person profiles.\n */\n person_profiles?: 'always' | 'never' | 'identified_only'\n /** @deprecated - use `person_profiles` instead */\n process_person?: 'always' | 'never' | 'identified_only'\n\n /** Client side rate limiting */\n rate_limiting?: {\n /** The average number of events per second that should be permitted (defaults to 10) */\n events_per_second?: number\n /** How many events can be captured in a burst. This defaults to 10 times the events_per_second count */\n events_burst_limit?: number\n }\n\n /** Used when sending data via `fetch`, use with care, this is intentionally meant to be used with NextJS `fetch`\n * Incorrect usage may cause out-of-date data for feature flags, actions tracking, etc.\n * See https://nextjs.org/docs/app/api-reference/functions/fetch#fetchurl-options\n */\n fetch_options?: {\n cache?: RequestInit['cache']\n next_options?: NextOptions\n }\n\n /**\n * PREVIEW - MAY CHANGE WITHOUT WARNING - DO NOT USE IN PRODUCTION\n * whether to wrap fetch and add tracing headers to the request\n * */\n __add_tracing_headers?: boolean\n\n /**\n * PREVIEW - MAY CHANGE WITHOUT WARNING - DO NOT USE IN PRODUCTION\n * enables the new RemoteConfig approach to loading config instead of decide\n * */\n __preview_remote_config?: boolean\n\n /**\n * PREVIEW - MAY CHANGE WITHOUT WARNING - DO NOT USE IN PRODUCTION\n * whether to send a sentinel value for distinct id, device id, and session id, which will be replaced server-side by a cookieless hash\n * */\n __preview_experimental_cookieless_mode?: boolean\n}\n\nexport interface OptInOutCapturingOptions {\n capture: (event: string, properties: Properties, options: CaptureOptions) => void\n capture_event_name: string\n capture_properties: Properties\n enable_persistence: boolean\n clear_persistence: boolean\n persistence_type: 'cookie' | 'localStorage' | 'localStorage+cookie'\n cookie_prefix: string\n cookie_expiration: number\n cross_subdomain_cookie: boolean\n secure_cookie: boolean\n}\n\nexport interface IsFeatureEnabledOptions {\n send_event: boolean\n}\n\nexport interface SessionRecordingOptions {\n blockClass?: string | RegExp\n blockSelector?: string | null\n ignoreClass?: string\n maskTextClass?: string | RegExp\n maskTextSelector?: string | null\n maskTextFn?: ((text: string, element: HTMLElement | null) => string) | null\n maskAllInputs?: boolean\n maskInputOptions?: recordOptions['maskInputOptions']\n maskInputFn?: ((text: string, element?: HTMLElement) => string) | null\n slimDOMOptions?: recordOptions['slimDOMOptions']\n collectFonts?: boolean\n inlineStylesheet?: boolean\n recordCrossOriginIframes?: boolean\n /**\n * Allows local config to override remote canvas recording settings from the decide response\n */\n captureCanvas?: SessionRecordingCanvasOptions\n /** @deprecated - use maskCapturedNetworkRequestFn instead */\n maskNetworkRequestFn?: ((data: NetworkRequest) => NetworkRequest | null | undefined) | null\n /** Modify the network request before it is captured. Returning null or undefined stops it being captured */\n maskCapturedNetworkRequestFn?: ((data: CapturedNetworkRequest) => CapturedNetworkRequest | null | undefined) | null\n // our settings here only support a subset of those proposed for rrweb's network capture plugin\n recordHeaders?: boolean\n recordBody?: boolean\n // ADVANCED: while a user is active we take a full snapshot of the browser every interval. For very few sites playback performance might be better with different interval. Set to 0 to disable\n full_snapshot_interval_millis?: number\n /*\n ADVANCED: whether to partially compress rrweb events before sending them to the server,\n defaults to true, can be set to false to disable partial compression\n NB requests are still compressed when sent to the server regardless of this setting\n */\n compress_events?: boolean\n /*\n ADVANCED: alters the threshold before a recording considers a user has become idle.\n Normally only altered alongside changes to session_idle_timeout_ms.\n Default is 5 minutes.\n */\n session_idle_threshold_ms?: number\n /*\n ADVANCED: alters the refill rate for the token bucket mutation throttling\n Normally only altered alongside posthog support guidance.\n Accepts values between 0 and 100\n Default is 10.\n */\n __mutationRateLimiterRefillRate?: number\n /*\n ADVANCED: alters the bucket size for the token bucket mutation throttling\n Normally only altered alongside posthog support guidance.\n Accepts values between 0 and 100\n Default is 100.\n */\n __mutationRateLimiterBucketSize?: number\n}\n\nexport type SessionIdChangedCallback = (\n sessionId: string,\n windowId: string | null | undefined,\n changeReason?: { noSessionId: boolean; activityTimeout: boolean; sessionPastMaximumLength: boolean }\n) => void\n\nexport enum Compression {\n GZipJS = 'gzip-js',\n Base64 = 'base64',\n}\n\n// Request types - these should be kept minimal to what request.ts needs\n\n// Minimal class to allow interop between different request methods (xhr / fetch)\nexport interface RequestResponse {\n statusCode: number\n text?: string\n json?: any\n}\n\nexport type RequestCallback = (response: RequestResponse) => void\n\n// See https://nextjs.org/docs/app/api-reference/functions/fetch#fetchurl-options\ntype NextOptions = { revalidate: false | 0 | number; tags: string[] }\n\nexport interface RequestOptions {\n url: string\n // Data can be a single object or an array of objects when batched\n data?: Record<string, any> | Record<string, any>[]\n headers?: Record<string, any>\n transport?: 'XHR' | 'fetch' | 'sendBeacon'\n method?: 'POST' | 'GET'\n urlQueryArgs?: { compression: Compression }\n callback?: RequestCallback\n timeout?: number\n noRetries?: boolean\n compression?: Compression | 'best-available'\n fetchOptions?: {\n cache?: RequestInit['cache']\n next?: NextOptions\n }\n}\n\n// Queued request types - the same as a request but with additional queueing information\n\nexport interface QueuedRequestOptions extends RequestOptions {\n batchKey?: string /** key of queue, e.g. 'sessionRecording' vs 'event' */\n}\n\n// Used explicitly for retriable requests\nexport interface RetriableRequestOptions extends QueuedRequestOptions {\n retriesPerformedSoFar?: number\n}\n\nexport interface CaptureOptions {\n $set?: Properties /** used with $identify */\n $set_once?: Properties /** used with $identify */\n _url?: string /** Used to override the desired endpoint for the captured event */\n _batchKey?: string /** key of queue, e.g. 'sessionRecording' vs 'event' */\n _noTruncate?: boolean /** if set, overrides and disables config.properties_string_max_length */\n send_instantly?: boolean /** if set skips the batched queue */\n skip_client_rate_limiting?: boolean /** if set skips the client side rate limiting */\n transport?: RequestOptions['transport'] /** if set, overrides the desired transport method */\n timestamp?: Date\n}\n\nexport type FlagVariant = { flag: string; variant: string }\n\nexport type SessionRecordingCanvasOptions = {\n recordCanvas?: boolean | null\n canvasFps?: number | null\n // the API returns a decimal between 0 and 1 as a string\n canvasQuality?: string | null\n}\n\nexport interface RemoteConfig {\n supportedCompression: Compression[]\n autocapture_opt_out?: boolean\n /**\n * originally capturePerformance was replay only and so boolean true\n * is equivalent to { network_timing: true }\n * now capture performance can be separately enabled within replay\n * and as a standalone web vitals tracker\n * people can have them enabled separately\n * they work standalone but enhance each other\n * TODO: deprecate this so we make a new config that doesn't need this explanation\n */\n capturePerformance?: boolean | PerformanceCaptureConfig\n analytics?: {\n endpoint?: string\n }\n elementsChainAsString?: boolean\n // this is currently in development and may have breaking changes without a major version bump\n autocaptureExceptions?:\n | boolean\n | {\n endpoint?: string\n }\n sessionRecording?: SessionRecordingCanvasOptions & {\n endpoint?: string\n consoleLogRecordingEnabled?: boolean\n // the API returns a decimal between 0 and 1 as a string\n sampleRate?: string | null\n minimumDurationMilliseconds?: number\n linkedFlag?: string | FlagVariant | null\n networkPayloadCapture?: Pick<NetworkRecordOptions, 'recordBody' | 'recordHeaders'>\n urlTriggers?: SessionRecordingUrlTrigger[]\n scriptConfig?: { script?: string | undefined }\n urlBlocklist?: SessionRecordingUrlTrigger[]\n eventTriggers?: string[]\n }\n surveys?: boolean\n toolbarParams: ToolbarParams\n editorParams?: ToolbarParams /** @deprecated, renamed to toolbarParams, still present on older API responses */\n toolbarVersion: 'toolbar' /** @deprecated, moved to toolbarParams */\n isAuthenticated: boolean\n siteApps: { id: string; url: string }[]\n heatmaps?: boolean\n defaultIdentifiedOnly?: boolean\n captureDeadClicks?: boolean\n hasFeatureFlags?: boolean // Indicates if the team has any flags enabled (if not we don't need to load them)\n}\n\nexport interface DecideResponse extends RemoteConfig {\n featureFlags: Record<string, string | boolean>\n featureFlagPayloads: Record<string, JsonType>\n errorsWhileComputingFlags: boolean\n}\n\nexport type SiteAppGlobals = {\n event: {\n uuid: string\n event: EventName\n properties: Properties\n timestamp?: Date\n elements_chain?: string\n distinct_id?: string\n }\n person: {\n properties: Properties\n }\n groups: Record<string, { id: string; type: string; properties: Properties }>\n}\n\nexport type SiteAppLoader = {\n id: string\n init: (config: { posthog: PostHog; callback: (success: boolean) => void }) => {\n processEvent?: (globals: SiteAppGlobals) => void\n }\n}\n\nexport type SiteApp = {\n id: string\n loaded: boolean\n errored: boolean\n processEvent?: (globals: SiteAppGlobals) => void\n}\n\nexport type FeatureFlagsCallback = (\n flags: string[],\n variants: Record<string, string | boolean>,\n context?: {\n errorsLoading?: boolean\n }\n) => void\n\nexport interface PersistentStore {\n is_supported: () => boolean\n error: (error: any) => void\n parse: (name: string) => any\n get: (name: string) => any\n set: (\n name: string,\n value: any,\n expire_days?: number | null,\n cross_subdomain?: boolean,\n secure?: boolean,\n debug?: boolean\n ) => void\n remove: (name: string, cross_subdomain?: boolean) => void\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport type Breaker = {}\nexport type EventHandler = (event: Event) => boolean | void\n\nexport type ToolbarUserIntent = 'add-action' | 'edit-action'\nexport type ToolbarSource = 'url' | 'localstorage'\nexport type ToolbarVersion = 'toolbar'\n\n/* sync with posthog */\nexport interface ToolbarParams {\n token?: string /** public posthog-js token */\n temporaryToken?: string /** private temporary user token */\n actionId?: number\n userIntent?: ToolbarUserIntent\n source?: ToolbarSource\n toolbarVersion?: ToolbarVersion\n instrument?: boolean\n distinctId?: string\n userEmail?: string\n dataAttributes?: string[]\n featureFlags?: Record<string, string | boolean>\n}\n\nexport type SnippetArrayItem = [method: string, ...args: any[]]\n\nexport type JsonRecord = { [key: string]: JsonType }\nexport type JsonType = string | number | boolean | null | JsonRecord | Array<JsonType>\n\n/** A feature that isn't publicly available yet.*/\nexport interface EarlyAccessFeature {\n // Sync this with the backend's EarlyAccessFeatureSerializer!\n name: string\n description: string\n stage: 'concept' | 'alpha' | 'beta'\n documentationUrl: string | null\n flagKey: string | null\n}\n\nexport type EarlyAccessFeatureCallback = (earlyAccessFeatures: EarlyAccessFeature[]) => void\n\nexport interface EarlyAccessFeatureResponse {\n earlyAccessFeatures: EarlyAccessFeature[]\n}\n\nexport type Headers = Record<string, string>\n\n/* for rrweb/network@1\n ** when that is released as part of rrweb this can be removed\n ** don't rely on this type, it may change without notice\n */\nexport type InitiatorType =\n | 'audio'\n | 'beacon'\n | 'body'\n | 'css'\n | 'early-hint'\n | 'embed'\n | 'fetch'\n | 'frame'\n | 'iframe'\n | 'icon'\n | 'image'\n | 'img'\n | 'input'\n | 'link'\n | 'navigation'\n | 'object'\n | 'ping'\n | 'script'\n | 'track'\n | 'video'\n | 'xmlhttprequest'\n\nexport type NetworkRecordOptions = {\n initiatorTypes?: InitiatorType[]\n maskRequestFn?: (data: CapturedNetworkRequest) => CapturedNetworkRequest | undefined\n recordHeaders?: boolean | { request: boolean; response: boolean }\n recordBody?: boolean | string[] | { request: boolean | string[]; response: boolean | string[] }\n recordInitialRequests?: boolean\n /**\n * whether to record PerformanceEntry events for network requests\n */\n recordPerformance?: boolean\n /**\n * the PerformanceObserver will only observe these entry types\n */\n performanceEntryTypeToObserve: string[]\n /**\n * the maximum size of the request/response body to record\n * NB this will be at most 1MB even if set larger\n */\n payloadSizeLimitBytes: number\n /**\n * some domains we should never record the payload\n * for example other companies session replay ingestion payloads aren't super useful but are gigantic\n * if this isn't provided we use a default list\n * if this is provided - we add the provided list to the default list\n * i.e. we never record the payloads on the default deny list\n */\n payloadHostDenyList?: string[]\n}\n\n/** @deprecated - use CapturedNetworkRequest instead */\nexport type NetworkRequest = {\n url: string\n}\n\n// In rrweb this is called NetworkRequest, but we already exposed that as having only URL\n// we also want to vary from the rrweb NetworkRequest because we want to include\n// all PerformanceEntry properties too.\n// that has 4 required properties\n// readonly duration: DOMHighResTimeStamp;\n// readonly entryType: string;\n// readonly name: string;\n// readonly startTime: DOMHighResTimeStamp;\n// NB: properties below here are ALPHA, don't rely on them, they may change without notice\n\n// we mirror PerformanceEntry since we read into this type from a PerformanceObserver,\n// but we don't want to inherit its readonly-iness\ntype Writable<T> = { -readonly [P in keyof T]: T[P] }\n\nexport type CapturedNetworkRequest = Writable<Omit<PerformanceEntry, 'toJSON'>> & {\n // properties below here are ALPHA, don't rely on them, they may change without notice\n method?: string\n initiatorType?: InitiatorType\n status?: number\n timeOrigin?: number\n timestamp?: number\n startTime?: number\n endTime?: number\n requestHeaders?: Headers\n requestBody?: string | null\n responseHeaders?: Headers\n responseBody?: string | null\n // was this captured before fetch/xhr could have been wrapped\n isInitial?: boolean\n}\n\nexport type ErrorEventArgs = [\n event: string | Event,\n source?: string | undefined,\n lineno?: number | undefined,\n colno?: number | undefined,\n error?: Error | undefined,\n]\n\nexport type ErrorMetadata = {\n handled?: boolean\n synthetic?: boolean\n syntheticException?: Error\n overrideExceptionType?: string\n overrideExceptionMessage?: string\n defaultExceptionType?: string\n defaultExceptionMessage?: string\n}\n\n// levels originally copied from Sentry to work with the sentry integration\n// and to avoid relying on a frequently changing @sentry/types dependency\n// but provided as an array of literal types, so we can constrain the level below\nexport const severityLevels = ['fatal', 'error', 'warning', 'log', 'info', 'debug'] as const\nexport declare type SeverityLevel = (typeof severityLevels)[number]\n\nexport interface ErrorProperties {\n $exception_type: string\n $exception_message: string\n $exception_level: SeverityLevel\n $exception_source?: string\n $exception_lineno?: number\n $exception_colno?: number\n $exception_DOMException_code?: string\n $exception_is_synthetic?: boolean\n $exception_stack_trace_raw?: string\n $exception_handled?: boolean\n $exception_personURL?: string\n}\n\nexport interface ErrorConversions {\n errorToProperties: (args: ErrorEventArgs) => ErrorProperties\n unhandledRejectionToProperties: (args: [ev: PromiseRejectionEvent]) => ErrorProperties\n}\n\nexport interface SessionRecordingUrlTrigger {\n url: string\n matching: 'regex'\n}\n","// import { patch } from 'rrweb/typings/utils'\n// copied from https://github.com/rrweb-io/rrweb/blob/8aea5b00a4dfe5a6f59bd2ae72bb624f45e51e81/packages/rrweb/src/utils.ts#L129\n// which was copied from https://github.com/getsentry/sentry-javascript/blob/b2109071975af8bf0316d3b5b38f519bdaf5dc15/packages/utils/src/object.ts\nimport { isFunction } from '../../../utils/type-utils'\n\nexport function patch(\n source: { [key: string]: any },\n name: string,\n replacement: (...args: unknown[]) => unknown\n): () => void {\n try {\n if (!(name in source)) {\n return () => {\n //\n }\n }\n\n const original = source[name] as () => unknown\n const wrapped = replacement(original)\n\n // Make sure it's a function first, as we need to attach an empty prototype for `defineProperties` to work\n // otherwise it'll throw \"TypeError: Object.defineProperties called on non-object\"\n if (isFunction(wrapped)) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n wrapped.prototype = wrapped.prototype || {}\n Object.defineProperties(wrapped, {\n __posthog_wrapped__: {\n enumerable: false,\n value: true,\n },\n })\n }\n\n source[name] = wrapped\n\n return () => {\n source[name] = original\n }\n } catch {\n return () => {\n //\n }\n // This can throw if multiple fill happens on a global object like XMLHttpRequest\n // Fixes https://github.com/getsentry/sentry-javascript/issues/2043\n }\n}\n","import { includes } from '.'\nimport { window } from './globals'\nimport { knownUnsafeEditableEvent, KnownUnsafeEditableEvent } from '../types'\n\n// eslint-disable-next-line posthog-js/no-direct-array-check\nconst nativeIsArray = Array.isArray\nconst ObjProto = Object.prototype\nexport const hasOwnProperty = ObjProto.hasOwnProperty\nconst toString = ObjProto.toString\n\nexport const isArray =\n nativeIsArray ||\n function (obj: any): obj is any[] {\n return toString.call(obj) === '[object Array]'\n }\n\n// from a comment on http://dbj.org/dbj/?p=286\n// fails on only one very rare and deliberate custom object:\n// let bomb = { toString : undefined, valueOf: function(o) { return \"function BOMBA!\"; }};\nexport const isFunction = (x: unknown): x is (...args: any[]) => any => {\n // eslint-disable-next-line posthog-js/no-direct-function-check\n return typeof x === 'function'\n}\n\nexport const isNativeFunction = (x: unknown): x is (...args: any[]) => any =>\n isFunction(x) && x.toString().indexOf('[native code]') !== -1\n\n// When angular patches functions they pass the above `isNativeFunction` check (at least the MutationObserver)\nexport const isAngularZonePresent = (): boolean => {\n return !!(window as any).Zone\n}\n\n// Underscore Addons\nexport const isObject = (x: unknown): x is Record<string, any> => {\n // eslint-disable-next-line posthog-js/no-direct-object-check\n return x === Object(x) && !isArray(x)\n}\nexport const isEmptyObject = (x: unknown): x is Record<string, any> => {\n if (isObject(x)) {\n for (const key in x) {\n if (hasOwnProperty.call(x, key)) {\n return false\n }\n }\n return true\n }\n return false\n}\nexport const isUndefined = (x: unknown): x is undefined => x === void 0\n\nexport const isString = (x: unknown): x is string => {\n // eslint-disable-next-line posthog-js/no-direct-string-check\n return toString.call(x) == '[object String]'\n}\n\nexport const isEmptyString = (x: unknown): boolean => isString(x) && x.trim().length === 0\n\nexport const isNull = (x: unknown): x is null => {\n // eslint-disable-next-line posthog-js/no-direct-null-check\n return x === null\n}\n\n/*\n sometimes you want to check if something is null or undefined\n that's what this is for\n */\nexport const isNullish = (x: unknown): x is null | undefined => isUndefined(x) || isNull(x)\n\nexport const isNumber = (x: unknown): x is number => {\n // eslint-disable-next-line posthog-js/no-direct-number-check\n return toString.call(x) == '[object Number]'\n}\nexport const isBoolean = (x: unknown): x is boolean => {\n // eslint-disable-next-line posthog-js/no-direct-boolean-check\n return toString.call(x) === '[object Boolean]'\n}\n\nexport const isDocument = (x: unknown): x is Document => {\n // eslint-disable-next-line posthog-js/no-direct-document-check\n return x instanceof Document\n}\n\nexport const isFormData = (x: unknown): x is FormData => {\n // eslint-disable-next-line posthog-js/no-direct-form-data-check\n return x instanceof FormData\n}\n\nexport const isFile = (x: unknown): x is File => {\n // eslint-disable-next-line posthog-js/no-direct-file-check\n return x instanceof File\n}\n\nexport const isKnownUnsafeEditableEvent = (x: unknown): x is KnownUnsafeEditableEvent => {\n return includes(knownUnsafeEditableEvent as unknown as string[], x)\n}\n","import { SessionIdManager } from '../sessionid'\nimport { patch } from '../extensions/replay/rrweb-plugins/patch'\nimport { assignableWindow, window } from '../utils/globals'\n\nconst addTracingHeaders = (sessionManager: SessionIdManager | undefined, req: Request) => {\n if (sessionManager) {\n const { sessionId, windowId } = sessionManager.checkAndGetSessionAndWindowId(true)\n req.headers.set('X-POSTHOG-SESSION-ID', sessionId)\n req.headers.set('X-POSTHOG-WINDOW-ID', windowId)\n }\n}\n\nconst patchFetch = (sessionManager?: SessionIdManager): (() => void) => {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return patch(window, 'fetch', (originalFetch: typeof fetch) => {\n return async function (url: URL | RequestInfo, init?: RequestInit | undefined) {\n // check IE earlier than this, we only initialize if Request is present\n // eslint-disable-next-line compat/compat\n const req = new Request(url, init)\n\n addTracingHeaders(sessionManager, req)\n\n return originalFetch(req)\n }\n })\n}\n\nconst patchXHR = (sessionManager?: SessionIdManager): (() => void) => {\n return patch(\n // we can assert this is present because we've checked previously\n window!.XMLHttpRequest.prototype,\n 'open',\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n (originalOpen: typeof XMLHttpRequest.prototype.open) => {\n return function (\n method: string,\n url: string | URL,\n async = true,\n username?: string | null,\n password?: string | null\n ) {\n // because this function is returned in its actual context `this` _is_ an XMLHttpRequest\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const xhr = this as XMLHttpRequest\n\n // check IE earlier than this, we only initialize if Request is present\n // eslint-disable-next-line compat/compat\n const req = new Request(url)\n\n addTracingHeaders(sessionManager, req)\n\n return originalOpen.call(xhr, method, req.url, async, username, password)\n }\n }\n )\n}\n\nassignableWindow.__PosthogExtensions__ = assignableWindow.__PosthogExtensions__ || {}\nconst patchFns = {\n _patchFetch: patchFetch,\n _patchXHR: patchXHR,\n}\nassignableWindow.__PosthogExtensions__.tracingHeadersPatchFns = patchFns\n\n// we used to put tracingHeadersPatchFns on window, and now we put it on __PosthogExtensions__\n// but that means that old clients which lazily load this extension are looking in the wrong place\n// yuck,\n// so we also put it directly on the window\n// when 1.161.1 is the oldest version seen in production we can remove this\nassignableWindow.postHogTracingHeadersPatchFns = patchFns\n\nexport default patchFns\n"],"names":["win","window","undefined","global","globalThis","navigator","document","location","fetch","XMLHttpRequest","AbortController","userAgent","Compression","assignableWindow","patch","source","name","replacement","original","wrapped","prototype","Object","defineProperties","__posthog_wrapped__","enumerable","value","_unused","addTracingHeaders","sessionManager","req","sessionId","windowId","checkAndGetSessionAndWindowId","headers","set","__PosthogExtensions__","patchFns","_patchFetch","originalFetch","_ref","url","init","Request","_x","_x2","apply","this","arguments","_patchXHR","originalOpen","method","async","length","username","password","call","tracingHeadersPatchFns","postHogTracingHeadersPatchFns"],"mappings":"kJAuBA,IAAMA,EAAkE,oBAAXC,OAAyBA,YAASC,EAmEzFC,EAA8D,oBAAfC,WAA6BA,WAAaJ,EAMlFK,EAAYF,aAAM,EAANA,EAAQE,UACTF,SAAAA,EAAQG,SACRH,SAAAA,EAAQI,SACXJ,SAAAA,EAAQK,MAEzBL,SAAAA,EAAQM,gBAAkB,oBAAqB,IAAIN,EAAOM,gBAAmBN,EAAOM,eACzDN,SAAAA,EAAQO,gBACdL,SAAAA,EAAWM,UAC7B,ICiVKC,EDjVCC,EAAqCb,QAAAA,EAAQ,CAAU,GCwVpE,SAPYY,GAAAA,EAAW,OAAA,UAAXA,EAAW,OAAA,QAAXA,CAOZ,CAPYA,IAAAA,EAgBZ,CAAA,ICpcO,SAASE,EACZC,EACAC,EACAC,GAEA,IACI,KAAMD,KAAQD,GACV,MAAO,OAKX,IAAMG,EAAWH,EAAOC,GAClBG,EAAUF,EAAYC,GAiB5B,MCdgB,mBDCDC,IAEXA,EAAQC,UAAYD,EAAQC,WAAa,CAAA,EACzCC,OAAOC,iBAAiBH,EAAS,CAC7BI,oBAAqB,CACjBC,YAAY,EACZC,OAAO,MAKnBV,EAAOC,GAAQG,EAER,KACHJ,EAAOC,GAAQE,CAAQ,CAE9B,CAAC,MAAAQ,GACE,MAAO,MAKX,CACJ,CEzCA,IAAMC,EAAoBA,CAACC,EAA8CC,KACrE,GAAID,EAAgB,CAChB,IAAME,UAAEA,EAASC,SAAEA,GAAaH,EAAeI,+BAA8B,GAC7EH,EAAII,QAAQC,IAAI,uBAAwBJ,GACxCD,EAAII,QAAQC,IAAI,sBAAuBH,EAC3C,GAmDJlB,EAAiBsB,sBAAwBtB,EAAiBsB,uBAAyB,GACnF,IAAMC,EAAW,CACbC,YAlDgBT,GAGTd,EAAMb,EAAQ,SAAUqC,GAC3B,WAAA,MAAAC,KAAO,UAAgBC,EAAwBC,GAG3C,IAAMZ,EAAM,IAAIa,QAAQF,EAAKC,GAI7B,OAFAd,EAAkBC,EAAgBC,GAE3BS,EAAcT,mLACxB,OAAAc,SAAAA,EAAAC,GAAA,OAAAL,EAAAM,MAAAC,KAAAC,UAAA,CAAA,CARD,KA+CJC,UAnCcpB,GACPd,EAEHb,EAAQQ,eAAeW,UACvB,QAGC6B,GACU,SACHC,EACAV,GAIF,IAHEW,IAAKJ,UAAAK,OAAA,QAAAlD,IAAA6C,UAAA,KAAAA,UAAA,GACLM,EAAwBN,UAAAK,OAAAL,EAAAA,kBAAA7C,EACxBoD,EAAwBP,UAAAK,OAAAL,EAAAA,kBAAA7C,EASlB2B,EAAM,IAAIa,QAAQF,GAIxB,OAFAb,EAAkBC,EAAgBC,GAE3BoB,EAAaM,KARRT,KAQkBI,EAAQrB,EAAIW,IAAKW,EAAOE,EAAUC,OAWhFzC,EAAiBsB,sBAAsBqB,uBAAyBpB,EAOhEvB,EAAiB4C,8BAAgCrB"}
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posthog-js",
3
- "version": "1.200.2",
3
+ "version": "1.201.1",
4
4
  "description": "Posthog-js allows you to automatically capture usage and send events to PostHog.",
5
5
  "repository": "https://github.com/PostHog/posthog-js",
6
6
  "author": "hey@posthog.com",
@@ -87,7 +87,7 @@
87
87
  "eslint-plugin-jest": "^28.8.3",
88
88
  "eslint-plugin-no-only-tests": "^3.1.0",
89
89
  "eslint-plugin-posthog-js": "link:eslint-rules",
90
- "eslint-plugin-prettier": "^4.2.1",
90
+ "eslint-plugin-prettier": "^5.2.1",
91
91
  "eslint-plugin-react": "^7.30.1",
92
92
  "eslint-plugin-react-hooks": "^4.6.0",
93
93
  "expect": "^29.7.0",
@@ -102,7 +102,7 @@
102
102
  "node-fetch": "^2.6.11",
103
103
  "posthog-js": "link:",
104
104
  "preact-render-to-string": "^6.3.1",
105
- "prettier": "^2.7.1",
105
+ "prettier": "^3.4.2",
106
106
  "rollup": "^4.24.0",
107
107
  "rollup-plugin-dts": "^6.1.1",
108
108
  "rollup-plugin-visualizer": "^5.12.0",
@@ -1 +1 @@
1
- {"version":3,"file":"dead-clicks-autocapture.js","sourceRoot":"","sources":["../../../src/entrypoints/dead-clicks-autocapture.ts"],"names":[],"mappings":"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","sourcesContent":["import { assignableWindow, LazyLoadedDeadClicksAutocaptureInterface } from '../utils/globals'\nimport { PostHog } from '../posthog-core'\nimport { isNull, isNumber, isUndefined } from '../utils/type-utils'\nimport { autocaptureCompatibleElements, getEventTarget } from '../autocapture-utils'\nimport { DeadClickCandidate, DeadClicksAutoCaptureConfig, Properties } from '../types'\nimport { autocapturePropertiesForElement } from '../autocapture'\nimport { isElementInToolbar, isElementNode, isTag } from '../utils/element-utils'\nimport { getNativeMutationObserverImplementation } from '../utils/prototype-utils'\n\nfunction asClick(event: MouseEvent): DeadClickCandidate | null {\n const eventTarget = getEventTarget(event)\n if (eventTarget) {\n return {\n node: eventTarget,\n originalEvent: event,\n timestamp: Date.now(),\n }\n }\n return null\n}\n\nfunction checkTimeout(value: number | undefined, thresholdMs: number) {\n return isNumber(value) && value >= thresholdMs\n}\n\nclass LazyLoadedDeadClicksAutocapture implements LazyLoadedDeadClicksAutocaptureInterface {\n private _mutationObserver: MutationObserver | undefined\n private _lastMutation: number | undefined\n private _lastSelectionChanged: number | undefined\n private _clicks: DeadClickCandidate[] = []\n private _checkClickTimer: number | undefined\n private _config: Required<DeadClicksAutoCaptureConfig>\n private _onCapture: (click: DeadClickCandidate, properties: Properties) => void\n\n private _defaultConfig = (defaultOnCapture: (click: DeadClickCandidate, properties: Properties) => void) => ({\n element_attribute_ignorelist: [],\n scroll_threshold_ms: 100,\n selection_change_threshold_ms: 100,\n mutation_threshold_ms: 2500,\n __onCapture: defaultOnCapture,\n })\n\n private asRequiredConfig(providedConfig?: DeadClicksAutoCaptureConfig): Required<DeadClicksAutoCaptureConfig> {\n const defaultConfig = this._defaultConfig(providedConfig?.__onCapture || this._captureDeadClick.bind(this))\n return {\n element_attribute_ignorelist:\n providedConfig?.element_attribute_ignorelist ?? defaultConfig.element_attribute_ignorelist,\n scroll_threshold_ms: providedConfig?.scroll_threshold_ms ?? defaultConfig.scroll_threshold_ms,\n selection_change_threshold_ms:\n providedConfig?.selection_change_threshold_ms ?? defaultConfig.selection_change_threshold_ms,\n mutation_threshold_ms: providedConfig?.mutation_threshold_ms ?? defaultConfig.mutation_threshold_ms,\n __onCapture: defaultConfig.__onCapture,\n }\n }\n\n constructor(readonly instance: PostHog, config?: DeadClicksAutoCaptureConfig) {\n this._config = this.asRequiredConfig(config)\n this._onCapture = this._config.__onCapture\n }\n\n start(observerTarget: Node) {\n this._startClickObserver()\n this._startScrollObserver()\n this._startSelectionChangedObserver()\n this._startMutationObserver(observerTarget)\n }\n\n private _startMutationObserver(observerTarget: Node) {\n if (!this._mutationObserver) {\n const NativeMutationObserver = getNativeMutationObserverImplementation(assignableWindow)\n this._mutationObserver = new NativeMutationObserver((mutations) => {\n this.onMutation(mutations)\n })\n this._mutationObserver.observe(observerTarget, {\n attributes: true,\n characterData: true,\n childList: true,\n subtree: true,\n })\n }\n }\n\n stop() {\n this._mutationObserver?.disconnect()\n this._mutationObserver = undefined\n assignableWindow.removeEventListener('click', this._onClick)\n assignableWindow.removeEventListener('scroll', this._onScroll, true)\n assignableWindow.removeEventListener('selectionchange', this._onSelectionChange)\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n private onMutation(_mutations: MutationRecord[]): void {\n // we don't actually care about the content of the mutations, right now\n this._lastMutation = Date.now()\n }\n\n private _startClickObserver() {\n assignableWindow.addEventListener('click', this._onClick)\n }\n\n private _onClick = (event: MouseEvent): void => {\n const click = asClick(event)\n if (!isNull(click) && !this._ignoreClick(click)) {\n this._clicks.push(click)\n }\n\n if (this._clicks.length && isUndefined(this._checkClickTimer)) {\n this._checkClickTimer = assignableWindow.setTimeout(() => {\n this._checkClicks()\n }, 1000)\n }\n }\n\n private _startScrollObserver() {\n // setting the third argument to `true` means that we will receive scroll events for other scrollable elements\n // on the page, not just the window\n // see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#usecapture\n assignableWindow.addEventListener('scroll', this._onScroll, true)\n }\n\n private _onScroll = (): void => {\n const candidateNow = Date.now()\n // very naive throttle\n if (candidateNow % 50 === 0) {\n // we can see many scrolls between scheduled checks,\n // so we update scroll delay as we see them\n // to avoid false positives\n this._clicks.forEach((click) => {\n if (isUndefined(click.scrollDelayMs)) {\n click.scrollDelayMs = candidateNow - click.timestamp\n }\n })\n }\n }\n\n private _startSelectionChangedObserver() {\n assignableWindow.addEventListener('selectionchange', this._onSelectionChange)\n }\n\n private _onSelectionChange = (): void => {\n this._lastSelectionChanged = Date.now()\n }\n\n private _ignoreClick(click: DeadClickCandidate | null): boolean {\n if (!click) {\n return true\n }\n\n if (isElementInToolbar(click.node)) {\n return true\n }\n\n const alreadyClickedInLastSecond = this._clicks.some((c) => {\n return c.node === click.node && Math.abs(c.timestamp - click.timestamp) < 1000\n })\n\n if (alreadyClickedInLastSecond) {\n return true\n }\n\n if (\n isTag(click.node, 'html') ||\n !isElementNode(click.node) ||\n autocaptureCompatibleElements.includes(click.node.tagName.toLowerCase())\n ) {\n return true\n }\n\n return false\n }\n\n private _checkClicks() {\n if (!this._clicks.length) {\n return\n }\n\n clearTimeout(this._checkClickTimer)\n this._checkClickTimer = undefined\n\n const clicksToCheck = this._clicks\n this._clicks = []\n\n for (const click of clicksToCheck) {\n click.mutationDelayMs =\n click.mutationDelayMs ??\n (this._lastMutation && click.timestamp <= this._lastMutation\n ? this._lastMutation - click.timestamp\n : undefined)\n click.absoluteDelayMs = Date.now() - click.timestamp\n click.selectionChangedDelayMs =\n this._lastSelectionChanged && click.timestamp <= this._lastSelectionChanged\n ? this._lastSelectionChanged - click.timestamp\n : undefined\n\n const scrollTimeout = checkTimeout(click.scrollDelayMs, this._config.scroll_threshold_ms)\n const selectionChangedTimeout = checkTimeout(\n click.selectionChangedDelayMs,\n this._config.selection_change_threshold_ms\n )\n const mutationTimeout = checkTimeout(click.mutationDelayMs, this._config.mutation_threshold_ms)\n // we want to timeout eventually even if nothing else catches it...\n // we leave a little longer than the maximum threshold to give the other checks a chance to catch it\n const absoluteTimeout = checkTimeout(click.absoluteDelayMs, this._config.mutation_threshold_ms * 1.1)\n\n const hadScroll = isNumber(click.scrollDelayMs) && click.scrollDelayMs < this._config.scroll_threshold_ms\n const hadMutation =\n isNumber(click.mutationDelayMs) && click.mutationDelayMs < this._config.mutation_threshold_ms\n const hadSelectionChange =\n isNumber(click.selectionChangedDelayMs) &&\n click.selectionChangedDelayMs < this._config.selection_change_threshold_ms\n\n if (hadScroll || hadMutation || hadSelectionChange) {\n // ignore clicks that had a scroll or mutation\n continue\n }\n\n if (scrollTimeout || mutationTimeout || absoluteTimeout || selectionChangedTimeout) {\n this._onCapture(click, {\n $dead_click_last_mutation_timestamp: this._lastMutation,\n $dead_click_event_timestamp: click.timestamp,\n $dead_click_scroll_timeout: scrollTimeout,\n $dead_click_mutation_timeout: mutationTimeout,\n $dead_click_absolute_timeout: absoluteTimeout,\n $dead_click_selection_changed_timeout: selectionChangedTimeout,\n })\n } else if (click.absoluteDelayMs < this._config.mutation_threshold_ms) {\n // keep waiting until next check\n this._clicks.push(click)\n }\n }\n\n if (this._clicks.length && isUndefined(this._checkClickTimer)) {\n this._checkClickTimer = assignableWindow.setTimeout(() => {\n this._checkClicks()\n }, 1000)\n }\n }\n\n private _captureDeadClick(click: DeadClickCandidate, properties: Properties) {\n // TODO need to check safe and captur-able as with autocapture\n // TODO autocaputure config\n this.instance.capture(\n '$dead_click',\n {\n ...properties,\n ...autocapturePropertiesForElement(click.node, {\n e: click.originalEvent,\n maskAllElementAttributes: this.instance.config.mask_all_element_attributes,\n maskAllText: this.instance.config.mask_all_text,\n elementAttributeIgnoreList: this._config.element_attribute_ignorelist,\n // TRICKY: it appears that we were moving to elementsChainAsString, but the UI still depends on elements, so :shrug:\n elementsChainAsString: false,\n }).props,\n $dead_click_scroll_delay_ms: click.scrollDelayMs,\n $dead_click_mutation_delay_ms: click.mutationDelayMs,\n $dead_click_absolute_delay_ms: click.absoluteDelayMs,\n $dead_click_selection_changed_delay_ms: click.selectionChangedDelayMs,\n },\n {\n timestamp: new Date(click.timestamp),\n }\n )\n }\n}\n\nassignableWindow.__PosthogExtensions__ = assignableWindow.__PosthogExtensions__ || {}\nassignableWindow.__PosthogExtensions__.initDeadClicksAutocapture = (ph, config) =>\n new LazyLoadedDeadClicksAutocapture(ph, config)\n\nexport default LazyLoadedDeadClicksAutocapture\n"]}
1
+ {"version":3,"file":"dead-clicks-autocapture.js","sourceRoot":"","sources":["../../../src/entrypoints/dead-clicks-autocapture.ts"],"names":[],"mappings":"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","sourcesContent":["import { assignableWindow, LazyLoadedDeadClicksAutocaptureInterface } from '../utils/globals'\nimport { PostHog } from '../posthog-core'\nimport { isNull, isNumber, isUndefined } from '../utils/type-utils'\nimport { autocaptureCompatibleElements, getEventTarget } from '../autocapture-utils'\nimport { DeadClickCandidate, DeadClicksAutoCaptureConfig, Properties } from '../types'\nimport { autocapturePropertiesForElement } from '../autocapture'\nimport { isElementInToolbar, isElementNode, isTag } from '../utils/element-utils'\nimport { getNativeMutationObserverImplementation } from '../utils/prototype-utils'\n\nfunction asClick(event: MouseEvent): DeadClickCandidate | null {\n const eventTarget = getEventTarget(event)\n if (eventTarget) {\n return {\n node: eventTarget,\n originalEvent: event,\n timestamp: Date.now(),\n }\n }\n return null\n}\n\nfunction checkTimeout(value: number | undefined, thresholdMs: number) {\n return isNumber(value) && value >= thresholdMs\n}\n\nclass LazyLoadedDeadClicksAutocapture implements LazyLoadedDeadClicksAutocaptureInterface {\n private _mutationObserver: MutationObserver | undefined\n private _lastMutation: number | undefined\n private _lastSelectionChanged: number | undefined\n private _clicks: DeadClickCandidate[] = []\n private _checkClickTimer: number | undefined\n private _config: Required<DeadClicksAutoCaptureConfig>\n private _onCapture: (click: DeadClickCandidate, properties: Properties) => void\n\n private _defaultConfig = (defaultOnCapture: (click: DeadClickCandidate, properties: Properties) => void) => ({\n element_attribute_ignorelist: [],\n scroll_threshold_ms: 100,\n selection_change_threshold_ms: 100,\n mutation_threshold_ms: 2500,\n __onCapture: defaultOnCapture,\n })\n\n private asRequiredConfig(providedConfig?: DeadClicksAutoCaptureConfig): Required<DeadClicksAutoCaptureConfig> {\n const defaultConfig = this._defaultConfig(providedConfig?.__onCapture || this._captureDeadClick.bind(this))\n return {\n element_attribute_ignorelist:\n providedConfig?.element_attribute_ignorelist ?? defaultConfig.element_attribute_ignorelist,\n scroll_threshold_ms: providedConfig?.scroll_threshold_ms ?? defaultConfig.scroll_threshold_ms,\n selection_change_threshold_ms:\n providedConfig?.selection_change_threshold_ms ?? defaultConfig.selection_change_threshold_ms,\n mutation_threshold_ms: providedConfig?.mutation_threshold_ms ?? defaultConfig.mutation_threshold_ms,\n __onCapture: defaultConfig.__onCapture,\n }\n }\n\n constructor(\n readonly instance: PostHog,\n config?: DeadClicksAutoCaptureConfig\n ) {\n this._config = this.asRequiredConfig(config)\n this._onCapture = this._config.__onCapture\n }\n\n start(observerTarget: Node) {\n this._startClickObserver()\n this._startScrollObserver()\n this._startSelectionChangedObserver()\n this._startMutationObserver(observerTarget)\n }\n\n private _startMutationObserver(observerTarget: Node) {\n if (!this._mutationObserver) {\n const NativeMutationObserver = getNativeMutationObserverImplementation(assignableWindow)\n this._mutationObserver = new NativeMutationObserver((mutations) => {\n this.onMutation(mutations)\n })\n this._mutationObserver.observe(observerTarget, {\n attributes: true,\n characterData: true,\n childList: true,\n subtree: true,\n })\n }\n }\n\n stop() {\n this._mutationObserver?.disconnect()\n this._mutationObserver = undefined\n assignableWindow.removeEventListener('click', this._onClick)\n assignableWindow.removeEventListener('scroll', this._onScroll, true)\n assignableWindow.removeEventListener('selectionchange', this._onSelectionChange)\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n private onMutation(_mutations: MutationRecord[]): void {\n // we don't actually care about the content of the mutations, right now\n this._lastMutation = Date.now()\n }\n\n private _startClickObserver() {\n assignableWindow.addEventListener('click', this._onClick)\n }\n\n private _onClick = (event: MouseEvent): void => {\n const click = asClick(event)\n if (!isNull(click) && !this._ignoreClick(click)) {\n this._clicks.push(click)\n }\n\n if (this._clicks.length && isUndefined(this._checkClickTimer)) {\n this._checkClickTimer = assignableWindow.setTimeout(() => {\n this._checkClicks()\n }, 1000)\n }\n }\n\n private _startScrollObserver() {\n // setting the third argument to `true` means that we will receive scroll events for other scrollable elements\n // on the page, not just the window\n // see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#usecapture\n assignableWindow.addEventListener('scroll', this._onScroll, true)\n }\n\n private _onScroll = (): void => {\n const candidateNow = Date.now()\n // very naive throttle\n if (candidateNow % 50 === 0) {\n // we can see many scrolls between scheduled checks,\n // so we update scroll delay as we see them\n // to avoid false positives\n this._clicks.forEach((click) => {\n if (isUndefined(click.scrollDelayMs)) {\n click.scrollDelayMs = candidateNow - click.timestamp\n }\n })\n }\n }\n\n private _startSelectionChangedObserver() {\n assignableWindow.addEventListener('selectionchange', this._onSelectionChange)\n }\n\n private _onSelectionChange = (): void => {\n this._lastSelectionChanged = Date.now()\n }\n\n private _ignoreClick(click: DeadClickCandidate | null): boolean {\n if (!click) {\n return true\n }\n\n if (isElementInToolbar(click.node)) {\n return true\n }\n\n const alreadyClickedInLastSecond = this._clicks.some((c) => {\n return c.node === click.node && Math.abs(c.timestamp - click.timestamp) < 1000\n })\n\n if (alreadyClickedInLastSecond) {\n return true\n }\n\n if (\n isTag(click.node, 'html') ||\n !isElementNode(click.node) ||\n autocaptureCompatibleElements.includes(click.node.tagName.toLowerCase())\n ) {\n return true\n }\n\n return false\n }\n\n private _checkClicks() {\n if (!this._clicks.length) {\n return\n }\n\n clearTimeout(this._checkClickTimer)\n this._checkClickTimer = undefined\n\n const clicksToCheck = this._clicks\n this._clicks = []\n\n for (const click of clicksToCheck) {\n click.mutationDelayMs =\n click.mutationDelayMs ??\n (this._lastMutation && click.timestamp <= this._lastMutation\n ? this._lastMutation - click.timestamp\n : undefined)\n click.absoluteDelayMs = Date.now() - click.timestamp\n click.selectionChangedDelayMs =\n this._lastSelectionChanged && click.timestamp <= this._lastSelectionChanged\n ? this._lastSelectionChanged - click.timestamp\n : undefined\n\n const scrollTimeout = checkTimeout(click.scrollDelayMs, this._config.scroll_threshold_ms)\n const selectionChangedTimeout = checkTimeout(\n click.selectionChangedDelayMs,\n this._config.selection_change_threshold_ms\n )\n const mutationTimeout = checkTimeout(click.mutationDelayMs, this._config.mutation_threshold_ms)\n // we want to timeout eventually even if nothing else catches it...\n // we leave a little longer than the maximum threshold to give the other checks a chance to catch it\n const absoluteTimeout = checkTimeout(click.absoluteDelayMs, this._config.mutation_threshold_ms * 1.1)\n\n const hadScroll = isNumber(click.scrollDelayMs) && click.scrollDelayMs < this._config.scroll_threshold_ms\n const hadMutation =\n isNumber(click.mutationDelayMs) && click.mutationDelayMs < this._config.mutation_threshold_ms\n const hadSelectionChange =\n isNumber(click.selectionChangedDelayMs) &&\n click.selectionChangedDelayMs < this._config.selection_change_threshold_ms\n\n if (hadScroll || hadMutation || hadSelectionChange) {\n // ignore clicks that had a scroll or mutation\n continue\n }\n\n if (scrollTimeout || mutationTimeout || absoluteTimeout || selectionChangedTimeout) {\n this._onCapture(click, {\n $dead_click_last_mutation_timestamp: this._lastMutation,\n $dead_click_event_timestamp: click.timestamp,\n $dead_click_scroll_timeout: scrollTimeout,\n $dead_click_mutation_timeout: mutationTimeout,\n $dead_click_absolute_timeout: absoluteTimeout,\n $dead_click_selection_changed_timeout: selectionChangedTimeout,\n })\n } else if (click.absoluteDelayMs < this._config.mutation_threshold_ms) {\n // keep waiting until next check\n this._clicks.push(click)\n }\n }\n\n if (this._clicks.length && isUndefined(this._checkClickTimer)) {\n this._checkClickTimer = assignableWindow.setTimeout(() => {\n this._checkClicks()\n }, 1000)\n }\n }\n\n private _captureDeadClick(click: DeadClickCandidate, properties: Properties) {\n // TODO need to check safe and captur-able as with autocapture\n // TODO autocaputure config\n this.instance.capture(\n '$dead_click',\n {\n ...properties,\n ...autocapturePropertiesForElement(click.node, {\n e: click.originalEvent,\n maskAllElementAttributes: this.instance.config.mask_all_element_attributes,\n maskAllText: this.instance.config.mask_all_text,\n elementAttributeIgnoreList: this._config.element_attribute_ignorelist,\n // TRICKY: it appears that we were moving to elementsChainAsString, but the UI still depends on elements, so :shrug:\n elementsChainAsString: false,\n }).props,\n $dead_click_scroll_delay_ms: click.scrollDelayMs,\n $dead_click_mutation_delay_ms: click.mutationDelayMs,\n $dead_click_absolute_delay_ms: click.absoluteDelayMs,\n $dead_click_selection_changed_delay_ms: click.selectionChangedDelayMs,\n },\n {\n timestamp: new Date(click.timestamp),\n }\n )\n }\n}\n\nassignableWindow.__PosthogExtensions__ = assignableWindow.__PosthogExtensions__ || {}\nassignableWindow.__PosthogExtensions__.initDeadClicksAutocapture = (ph, config) =>\n new LazyLoadedDeadClicksAutocapture(ph, config)\n\nexport default LazyLoadedDeadClicksAutocapture\n"]}
@@ -108,7 +108,7 @@ function errorPropertiesFromString(candidate, metadata) {
108
108
  var synthetic = (_b = metadata === null || metadata === void 0 ? void 0 : metadata.synthetic) !== null && _b !== void 0 ? _b : true;
109
109
  var exceptionType = (metadata === null || metadata === void 0 ? void 0 : metadata.overrideExceptionType)
110
110
  ? metadata.overrideExceptionType
111
- : (_c = metadata === null || metadata === void 0 ? void 0 : metadata.defaultExceptionType) !== null && _c !== void 0 ? _c : 'Error';
111
+ : ((_c = metadata === null || metadata === void 0 ? void 0 : metadata.defaultExceptionType) !== null && _c !== void 0 ? _c : 'Error');
112
112
  var exceptionMessage = (metadata === null || metadata === void 0 ? void 0 : metadata.overrideExceptionMessage)
113
113
  ? metadata.overrideExceptionMessage
114
114
  : candidate
@@ -1 +1 @@
1
- {"version":3,"file":"error-conversion.js","sourceRoot":"","sources":["../../../../src/extensions/exception-autocapture/error-conversion.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n isDOMError,\n isDOMException,\n isError,\n isErrorEvent,\n isErrorWithStack,\n isEvent,\n isPlainObject,\n isPrimitive,\n} from './type-checking'\nimport { defaultStackParser, StackFrame } from './stack-trace'\n\nimport { isEmptyString, isString, isUndefined } from '../../utils/type-utils'\nimport { ErrorEventArgs, ErrorMetadata, SeverityLevel, severityLevels } from '../../types'\n\nexport interface ErrorProperties {\n $exception_list: Exception[]\n $exception_level?: SeverityLevel\n $exception_DOMException_code?: string\n $exception_personURL?: string\n}\n\nexport interface Exception {\n type?: string\n value?: string\n mechanism?: {\n /**\n * In theory, whether or not the exception has been handled by the user. In practice, whether or not we see it before\n * it hits the global error/rejection handlers, whether through explicit handling by the user or auto instrumentation.\n */\n handled?: boolean\n type?: string\n source?: string\n /**\n * True when `captureException` is called with anything other than an instance of `Error` (or, in the case of browser,\n * an instance of `ErrorEvent`, `DOMError`, or `DOMException`). causing us to create a synthetic error in an attempt\n * to recreate the stacktrace.\n */\n synthetic?: boolean\n }\n module?: string\n thread_id?: number\n stacktrace?: {\n frames?: StackFrame[]\n type: 'raw'\n }\n}\n\nexport interface ErrorConversions {\n errorToProperties: (args: ErrorEventArgs, metadata?: ErrorMetadata) => ErrorProperties\n unhandledRejectionToProperties: (args: [ev: PromiseRejectionEvent]) => ErrorProperties\n}\n/**\n * based on the very wonderful MIT licensed Sentry SDK\n */\n\nconst ERROR_TYPES_PATTERN =\n /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i\n\nexport function parseStackFrames(ex: Error & { stacktrace?: string }, framesToPop: number = 0): StackFrame[] {\n // Access and store the stacktrace property before doing ANYTHING\n // else to it because Opera is not very good at providing it\n // reliably in other circumstances.\n const stacktrace = ex.stacktrace || ex.stack || ''\n\n const skipLines = getSkipFirstStackStringLines(ex)\n\n try {\n const frames = defaultStackParser(stacktrace, skipLines)\n // frames are reversed so we remove the from the back of the array\n return frames.slice(0, frames.length - framesToPop)\n } catch {\n // no-empty\n }\n\n return []\n}\n\nconst reactMinifiedRegexp = /Minified React error #\\d+;/i\n\n/**\n * Certain known React errors contain links that would be falsely\n * parsed as frames. This function check for these errors and\n * returns number of the stack string lines to skip.\n */\nfunction getSkipFirstStackStringLines(ex: Error): number {\n if (ex && reactMinifiedRegexp.test(ex.message)) {\n return 1\n }\n\n return 0\n}\n\nfunction errorPropertiesFromError(error: Error, metadata?: ErrorMetadata): ErrorProperties {\n const frames = parseStackFrames(error)\n\n const handled = metadata?.handled ?? true\n const synthetic = metadata?.synthetic ?? false\n\n const exceptionType = metadata?.overrideExceptionType ? metadata.overrideExceptionType : error.name\n const exceptionMessage = metadata?.overrideExceptionMessage\n ? metadata.overrideExceptionMessage\n : extractMessage(error)\n\n return {\n $exception_list: [\n {\n type: exceptionType,\n value: exceptionMessage,\n stacktrace: {\n frames,\n type: 'raw',\n },\n mechanism: {\n handled,\n synthetic,\n },\n },\n ],\n $exception_level: 'error',\n }\n}\n\n/**\n * There are cases where stacktrace.message is an Event object\n * https://github.com/getsentry/sentry-javascript/issues/1949\n * In this specific case we try to extract stacktrace.message.error.message\n */\nexport function extractMessage(err: Error & { message: { error?: Error } }): string {\n const message = err.message\n\n if (message.error && typeof message.error.message === 'string') {\n return message.error.message\n }\n\n return message\n}\n\nfunction errorPropertiesFromString(candidate: string, metadata?: ErrorMetadata): ErrorProperties {\n // Defaults for metadata are based on what the error candidate is.\n const handled = metadata?.handled ?? true\n const synthetic = metadata?.synthetic ?? true\n\n const exceptionType = metadata?.overrideExceptionType\n ? metadata.overrideExceptionType\n : metadata?.defaultExceptionType ?? 'Error'\n const exceptionMessage = metadata?.overrideExceptionMessage\n ? metadata.overrideExceptionMessage\n : candidate\n ? candidate\n : metadata?.defaultExceptionMessage\n\n const exception: Exception = {\n type: exceptionType,\n value: exceptionMessage,\n mechanism: {\n handled,\n synthetic,\n },\n }\n\n if (metadata?.syntheticException) {\n // Kludge: strip the last frame from a synthetically created error\n // so that it does not appear in a users stack trace\n const frames = parseStackFrames(metadata.syntheticException, 1)\n if (frames.length) {\n exception.stacktrace = { frames, type: 'raw' }\n }\n }\n\n return {\n $exception_list: [exception],\n $exception_level: 'error',\n }\n}\n\n/**\n * Given any captured exception, extract its keys and create a sorted\n * and truncated list that will be used inside the event message.\n * eg. `Non-error exception captured with keys: foo, bar, baz`\n */\nfunction extractExceptionKeysForMessage(exception: Record<string, unknown>, maxLength = 40): string {\n const keys = Object.keys(exception)\n keys.sort()\n\n if (!keys.length) {\n return '[object has no keys]'\n }\n\n for (let i = keys.length; i > 0; i--) {\n const serialized = keys.slice(0, i).join(', ')\n if (serialized.length > maxLength) {\n continue\n }\n if (i === keys.length) {\n return serialized\n }\n return serialized.length <= maxLength ? serialized : `${serialized.slice(0, maxLength)}...`\n }\n\n return ''\n}\n\nfunction isSeverityLevel(x: unknown): x is SeverityLevel {\n return isString(x) && !isEmptyString(x) && severityLevels.indexOf(x as SeverityLevel) >= 0\n}\n\nfunction errorPropertiesFromObject(candidate: Record<string, unknown>, metadata?: ErrorMetadata): ErrorProperties {\n // Defaults for metadata are based on what the error candidate is.\n const handled = metadata?.handled ?? true\n const synthetic = metadata?.synthetic ?? true\n\n const exceptionType = metadata?.overrideExceptionType\n ? metadata.overrideExceptionType\n : isEvent(candidate)\n ? candidate.constructor.name\n : 'Error'\n const exceptionMessage = metadata?.overrideExceptionMessage\n ? metadata.overrideExceptionMessage\n : `Non-Error ${'exception'} captured with keys: ${extractExceptionKeysForMessage(candidate)}`\n\n const exception: Exception = {\n type: exceptionType,\n value: exceptionMessage,\n mechanism: {\n handled,\n synthetic,\n },\n }\n\n if (metadata?.syntheticException) {\n // Kludge: strip the last frame from a synthetically created error\n // so that it does not appear in a users stack trace\n const frames = parseStackFrames(metadata?.syntheticException, 1)\n if (frames.length) {\n exception.stacktrace = { frames, type: 'raw' }\n }\n }\n\n return {\n $exception_list: [exception],\n $exception_level: isSeverityLevel(candidate.level) ? candidate.level : 'error',\n }\n}\n\nexport function errorToProperties(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n [event, _, __, ___, error]: ErrorEventArgs,\n metadata?: ErrorMetadata\n): ErrorProperties {\n let errorProperties: ErrorProperties = { $exception_list: [] }\n\n const candidate = error || event\n\n if (isDOMError(candidate) || isDOMException(candidate)) {\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMError\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMException\n\n const domException = candidate as unknown as DOMException\n\n if (isErrorWithStack(candidate)) {\n errorProperties = errorPropertiesFromError(candidate as Error, metadata)\n } else {\n const name = domException.name || (isDOMError(domException) ? 'DOMError' : 'DOMException')\n const message = domException.message ? `${name}: ${domException.message}` : name\n const exceptionType = isDOMError(domException) ? 'DOMError' : 'DOMException'\n errorProperties = errorPropertiesFromString(message, {\n ...metadata,\n overrideExceptionType: exceptionType,\n defaultExceptionMessage: message,\n })\n }\n if ('code' in domException) {\n errorProperties['$exception_DOMException_code'] = `${domException.code}`\n }\n return errorProperties\n } else if (isErrorEvent(candidate as ErrorEvent) && (candidate as ErrorEvent).error) {\n return errorPropertiesFromError((candidate as ErrorEvent).error as Error, metadata)\n } else if (isError(candidate)) {\n return errorPropertiesFromError(candidate, metadata)\n } else if (isPlainObject(candidate) || isEvent(candidate)) {\n // group these by using the keys available on the object\n const objectException = candidate as Record<string, unknown>\n return errorPropertiesFromObject(objectException, metadata)\n } else if (isUndefined(error) && isString(event)) {\n let name = 'Error'\n let message = event\n const groups = event.match(ERROR_TYPES_PATTERN)\n if (groups) {\n name = groups[1]\n message = groups[2]\n }\n\n return errorPropertiesFromString(message, {\n ...metadata,\n overrideExceptionType: name,\n defaultExceptionMessage: message,\n })\n } else {\n return errorPropertiesFromString(candidate as string, metadata)\n }\n}\n\nexport function unhandledRejectionToProperties([ev]: [ev: PromiseRejectionEvent]): ErrorProperties {\n const error = getUnhandledRejectionError(ev)\n\n if (isPrimitive(error)) {\n return errorPropertiesFromString(`Non-Error promise rejection captured with value: ${String(error)}`, {\n handled: false,\n synthetic: false,\n overrideExceptionType: 'UnhandledRejection',\n })\n }\n\n return errorToProperties([error as string | Event], {\n handled: false,\n overrideExceptionType: 'UnhandledRejection',\n defaultExceptionMessage: String(error),\n })\n}\n\nfunction getUnhandledRejectionError(error: unknown): unknown {\n if (isPrimitive(error)) {\n return error\n }\n\n // dig the object of the rejection out of known event types\n try {\n type ErrorWithReason = { reason: unknown }\n // PromiseRejectionEvents store the object of the rejection under 'reason'\n // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent\n if ('reason' in (error as ErrorWithReason)) {\n return (error as ErrorWithReason).reason\n }\n\n type CustomEventWithDetail = { detail: { reason: unknown } }\n // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents\n // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into\n // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec\n // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and\n // https://github.com/getsentry/sentry-javascript/issues/2380\n if ('detail' in (error as CustomEventWithDetail) && 'reason' in (error as CustomEventWithDetail).detail) {\n return (error as CustomEventWithDetail).detail.reason\n }\n } catch {\n // no-empty\n }\n\n return error\n}\n"]}
1
+ {"version":3,"file":"error-conversion.js","sourceRoot":"","sources":["../../../../src/extensions/exception-autocapture/error-conversion.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,EACH,UAAU,EACV,cAAc,EACd,OAAO,EACP,YAAY,EACZ,gBAAgB,EAChB,OAAO,EACP,aAAa,EACb,WAAW,GACd,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,kBAAkB,EAAc,MAAM,eAAe,CAAA;AAE9D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAC7E,OAAO,EAAgD,cAAc,EAAE,MAAM,aAAa,CAAA;AAuC1F;;GAEG;AAEH,IAAM,mBAAmB,GACrB,0GAA0G,CAAA;AAE9G,MAAM,UAAU,gBAAgB,CAAC,EAAmC,EAAE,WAAuB;IAAvB,4BAAA,EAAA,eAAuB;IACzF,iEAAiE;IACjE,4DAA4D;IAC5D,mCAAmC;IACnC,IAAM,UAAU,GAAG,EAAE,CAAC,UAAU,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE,CAAA;IAElD,IAAM,SAAS,GAAG,4BAA4B,CAAC,EAAE,CAAC,CAAA;IAElD,IAAI,CAAC;QACD,IAAM,QAAM,GAAG,kBAAkB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;QACxD,kEAAkE;QAClE,OAAO,QAAM,CAAC,KAAK,CAAC,CAAC,EAAE,QAAM,CAAC,MAAM,GAAG,WAAW,CAAC,CAAA;IACvD,CAAC;IAAC,WAAM,CAAC;QACL,WAAW;IACf,CAAC;IAED,OAAO,EAAE,CAAA;AACb,CAAC;AAED,IAAM,mBAAmB,GAAG,6BAA6B,CAAA;AAEzD;;;;GAIG;AACH,SAAS,4BAA4B,CAAC,EAAS;IAC3C,IAAI,EAAE,IAAI,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,OAAO,CAAC,CAAA;IACZ,CAAC;IAED,OAAO,CAAC,CAAA;AACZ,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAY,EAAE,QAAwB;;IACpE,IAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;IAEtC,IAAM,OAAO,GAAG,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,OAAO,mCAAI,IAAI,CAAA;IACzC,IAAM,SAAS,GAAG,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,SAAS,mCAAI,KAAK,CAAA;IAE9C,IAAM,aAAa,GAAG,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,qBAAqB,EAAC,CAAC,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAA;IACnG,IAAM,gBAAgB,GAAG,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,wBAAwB;QACvD,CAAC,CAAC,QAAQ,CAAC,wBAAwB;QACnC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;IAE3B,OAAO;QACH,eAAe,EAAE;YACb;gBACI,IAAI,EAAE,aAAa;gBACnB,KAAK,EAAE,gBAAgB;gBACvB,UAAU,EAAE;oBACR,MAAM,QAAA;oBACN,IAAI,EAAE,KAAK;iBACd;gBACD,SAAS,EAAE;oBACP,OAAO,SAAA;oBACP,SAAS,WAAA;iBACZ;aACJ;SACJ;QACD,gBAAgB,EAAE,OAAO;KAC5B,CAAA;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,GAA2C;IACtE,IAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAA;IAE3B,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,OAAO,CAAC,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC7D,OAAO,OAAO,CAAC,KAAK,CAAC,OAAO,CAAA;IAChC,CAAC;IAED,OAAO,OAAO,CAAA;AAClB,CAAC;AAED,SAAS,yBAAyB,CAAC,SAAiB,EAAE,QAAwB;;IAC1E,kEAAkE;IAClE,IAAM,OAAO,GAAG,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,OAAO,mCAAI,IAAI,CAAA;IACzC,IAAM,SAAS,GAAG,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,SAAS,mCAAI,IAAI,CAAA;IAE7C,IAAM,aAAa,GAAG,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,qBAAqB;QACjD,CAAC,CAAC,QAAQ,CAAC,qBAAqB;QAChC,CAAC,CAAC,CAAC,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,oBAAoB,mCAAI,OAAO,CAAC,CAAA;IACjD,IAAM,gBAAgB,GAAG,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,wBAAwB;QACvD,CAAC,CAAC,QAAQ,CAAC,wBAAwB;QACnC,CAAC,CAAC,SAAS;YACT,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,uBAAuB,CAAA;IAEzC,IAAM,SAAS,GAAc;QACzB,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,gBAAgB;QACvB,SAAS,EAAE;YACP,OAAO,SAAA;YACP,SAAS,WAAA;SACZ;KACJ,CAAA;IAED,IAAI,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,kBAAkB,EAAE,CAAC;QAC/B,kEAAkE;QAClE,oDAAoD;QACpD,IAAM,QAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAA;QAC/D,IAAI,QAAM,CAAC,MAAM,EAAE,CAAC;YAChB,SAAS,CAAC,UAAU,GAAG,EAAE,MAAM,UAAA,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;QAClD,CAAC;IACL,CAAC;IAED,OAAO;QACH,eAAe,EAAE,CAAC,SAAS,CAAC;QAC5B,gBAAgB,EAAE,OAAO;KAC5B,CAAA;AACL,CAAC;AAED;;;;GAIG;AACH,SAAS,8BAA8B,CAAC,SAAkC,EAAE,SAAc;IAAd,0BAAA,EAAA,cAAc;IACtF,IAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACnC,IAAI,CAAC,IAAI,EAAE,CAAA;IAEX,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACf,OAAO,sBAAsB,CAAA;IACjC,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,IAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC9C,IAAI,UAAU,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;YAChC,SAAQ;QACZ,CAAC;QACD,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YACpB,OAAO,UAAU,CAAA;QACrB,CAAC;QACD,OAAO,UAAU,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,QAAK,CAAA;IAC/F,CAAC;IAED,OAAO,EAAE,CAAA;AACb,CAAC;AAED,SAAS,eAAe,CAAC,CAAU;IAC/B,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,CAAkB,CAAC,IAAI,CAAC,CAAA;AAC9F,CAAC;AAED,SAAS,yBAAyB,CAAC,SAAkC,EAAE,QAAwB;;IAC3F,kEAAkE;IAClE,IAAM,OAAO,GAAG,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,OAAO,mCAAI,IAAI,CAAA;IACzC,IAAM,SAAS,GAAG,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,SAAS,mCAAI,IAAI,CAAA;IAE7C,IAAM,aAAa,GAAG,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,qBAAqB;QACjD,CAAC,CAAC,QAAQ,CAAC,qBAAqB;QAChC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;YAClB,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI;YAC5B,CAAC,CAAC,OAAO,CAAA;IACf,IAAM,gBAAgB,GAAG,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,wBAAwB;QACvD,CAAC,CAAC,QAAQ,CAAC,wBAAwB;QACnC,CAAC,CAAC,oBAAa,WAAW,kCAAwB,8BAA8B,CAAC,SAAS,CAAC,CAAE,CAAA;IAEjG,IAAM,SAAS,GAAc;QACzB,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,gBAAgB;QACvB,SAAS,EAAE;YACP,OAAO,SAAA;YACP,SAAS,WAAA;SACZ;KACJ,CAAA;IAED,IAAI,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,kBAAkB,EAAE,CAAC;QAC/B,kEAAkE;QAClE,oDAAoD;QACpD,IAAM,QAAM,GAAG,gBAAgB,CAAC,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,kBAAkB,EAAE,CAAC,CAAC,CAAA;QAChE,IAAI,QAAM,CAAC,MAAM,EAAE,CAAC;YAChB,SAAS,CAAC,UAAU,GAAG,EAAE,MAAM,UAAA,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;QAClD,CAAC;IACL,CAAC;IAED,OAAO;QACH,eAAe,EAAE,CAAC,SAAS,CAAC;QAC5B,gBAAgB,EAAE,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO;KACjF,CAAA;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB;AAC7B,6DAA6D;AAC7D,EAA0C,EAC1C,QAAwB;;IAFxB,6DAA6D;IAC7D,KAAA,aAA0C,EAAzC,KAAK,QAAA,EAAE,CAAC,QAAA,EAAE,EAAE,QAAA,EAAE,GAAG,QAAA,EAAE,KAAK,QAAA;IAGzB,IAAI,eAAe,GAAoB,EAAE,eAAe,EAAE,EAAE,EAAE,CAAA;IAE9D,IAAM,SAAS,GAAG,KAAK,IAAI,KAAK,CAAA;IAEhC,IAAI,UAAU,CAAC,SAAS,CAAC,IAAI,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;QACrD,4DAA4D;QAC5D,gEAAgE;QAEhE,IAAM,YAAY,GAAG,SAAoC,CAAA;QAEzD,IAAI,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,eAAe,GAAG,wBAAwB,CAAC,SAAkB,EAAE,QAAQ,CAAC,CAAA;QAC5E,CAAC;aAAM,CAAC;YACJ,IAAM,MAAI,GAAG,YAAY,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc,CAAC,CAAA;YAC1F,IAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,UAAG,MAAI,eAAK,YAAY,CAAC,OAAO,CAAE,CAAC,CAAC,CAAC,MAAI,CAAA;YAChF,IAAM,aAAa,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc,CAAA;YAC5E,eAAe,GAAG,yBAAyB,CAAC,OAAO,wBAC5C,QAAQ,KACX,qBAAqB,EAAE,aAAa,EACpC,uBAAuB,EAAE,OAAO,IAClC,CAAA;QACN,CAAC;QACD,IAAI,MAAM,IAAI,YAAY,EAAE,CAAC;YACzB,eAAe,CAAC,8BAA8B,CAAC,GAAG,UAAG,YAAY,CAAC,IAAI,CAAE,CAAA;QAC5E,CAAC;QACD,OAAO,eAAe,CAAA;IAC1B,CAAC;SAAM,IAAI,YAAY,CAAC,SAAuB,CAAC,IAAK,SAAwB,CAAC,KAAK,EAAE,CAAC;QAClF,OAAO,wBAAwB,CAAE,SAAwB,CAAC,KAAc,EAAE,QAAQ,CAAC,CAAA;IACvF,CAAC;SAAM,IAAI,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,OAAO,wBAAwB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IACxD,CAAC;SAAM,IAAI,aAAa,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACxD,wDAAwD;QACxD,IAAM,eAAe,GAAG,SAAoC,CAAA;QAC5D,OAAO,yBAAyB,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAA;IAC/D,CAAC;SAAM,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,IAAI,MAAI,GAAG,OAAO,CAAA;QAClB,IAAI,OAAO,GAAG,KAAK,CAAA;QACnB,IAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAA;QAC/C,IAAI,MAAM,EAAE,CAAC;YACT,MAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;YAChB,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;QACvB,CAAC;QAED,OAAO,yBAAyB,CAAC,OAAO,wBACjC,QAAQ,KACX,qBAAqB,EAAE,MAAI,EAC3B,uBAAuB,EAAE,OAAO,IAClC,CAAA;IACN,CAAC;SAAM,CAAC;QACJ,OAAO,yBAAyB,CAAC,SAAmB,EAAE,QAAQ,CAAC,CAAA;IACnE,CAAC;AACL,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,EAAiC;QAAjC,KAAA,aAAiC,EAAhC,EAAE,QAAA;IAC9C,IAAM,KAAK,GAAG,0BAA0B,CAAC,EAAE,CAAC,CAAA;IAE5C,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,yBAAyB,CAAC,2DAAoD,MAAM,CAAC,KAAK,CAAC,CAAE,EAAE;YAClG,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,KAAK;YAChB,qBAAqB,EAAE,oBAAoB;SAC9C,CAAC,CAAA;IACN,CAAC;IAED,OAAO,iBAAiB,CAAC,CAAC,KAAuB,CAAC,EAAE;QAChD,OAAO,EAAE,KAAK;QACd,qBAAqB,EAAE,oBAAoB;QAC3C,uBAAuB,EAAE,MAAM,CAAC,KAAK,CAAC;KACzC,CAAC,CAAA;AACN,CAAC;AAED,SAAS,0BAA0B,CAAC,KAAc;IAC9C,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAA;IAChB,CAAC;IAED,2DAA2D;IAC3D,IAAI,CAAC;QAED,0EAA0E;QAC1E,6EAA6E;QAC7E,IAAI,QAAQ,IAAK,KAAyB,EAAE,CAAC;YACzC,OAAQ,KAAyB,CAAC,MAAM,CAAA;QAC5C,CAAC;QAGD,8FAA8F;QAC9F,gFAAgF;QAChF,qFAAqF;QACrF,uEAAuE;QACvE,6DAA6D;QAC7D,IAAI,QAAQ,IAAK,KAA+B,IAAI,QAAQ,IAAK,KAA+B,CAAC,MAAM,EAAE,CAAC;YACtG,OAAQ,KAA+B,CAAC,MAAM,CAAC,MAAM,CAAA;QACzD,CAAC;IACL,CAAC;IAAC,WAAM,CAAC;QACL,WAAW;IACf,CAAC;IAED,OAAO,KAAK,CAAA;AAChB,CAAC","sourcesContent":["import {\n isDOMError,\n isDOMException,\n isError,\n isErrorEvent,\n isErrorWithStack,\n isEvent,\n isPlainObject,\n isPrimitive,\n} from './type-checking'\nimport { defaultStackParser, StackFrame } from './stack-trace'\n\nimport { isEmptyString, isString, isUndefined } from '../../utils/type-utils'\nimport { ErrorEventArgs, ErrorMetadata, SeverityLevel, severityLevels } from '../../types'\n\nexport interface ErrorProperties {\n $exception_list: Exception[]\n $exception_level?: SeverityLevel\n $exception_DOMException_code?: string\n $exception_personURL?: string\n}\n\nexport interface Exception {\n type?: string\n value?: string\n mechanism?: {\n /**\n * In theory, whether or not the exception has been handled by the user. In practice, whether or not we see it before\n * it hits the global error/rejection handlers, whether through explicit handling by the user or auto instrumentation.\n */\n handled?: boolean\n type?: string\n source?: string\n /**\n * True when `captureException` is called with anything other than an instance of `Error` (or, in the case of browser,\n * an instance of `ErrorEvent`, `DOMError`, or `DOMException`). causing us to create a synthetic error in an attempt\n * to recreate the stacktrace.\n */\n synthetic?: boolean\n }\n module?: string\n thread_id?: number\n stacktrace?: {\n frames?: StackFrame[]\n type: 'raw'\n }\n}\n\nexport interface ErrorConversions {\n errorToProperties: (args: ErrorEventArgs, metadata?: ErrorMetadata) => ErrorProperties\n unhandledRejectionToProperties: (args: [ev: PromiseRejectionEvent]) => ErrorProperties\n}\n/**\n * based on the very wonderful MIT licensed Sentry SDK\n */\n\nconst ERROR_TYPES_PATTERN =\n /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i\n\nexport function parseStackFrames(ex: Error & { stacktrace?: string }, framesToPop: number = 0): StackFrame[] {\n // Access and store the stacktrace property before doing ANYTHING\n // else to it because Opera is not very good at providing it\n // reliably in other circumstances.\n const stacktrace = ex.stacktrace || ex.stack || ''\n\n const skipLines = getSkipFirstStackStringLines(ex)\n\n try {\n const frames = defaultStackParser(stacktrace, skipLines)\n // frames are reversed so we remove the from the back of the array\n return frames.slice(0, frames.length - framesToPop)\n } catch {\n // no-empty\n }\n\n return []\n}\n\nconst reactMinifiedRegexp = /Minified React error #\\d+;/i\n\n/**\n * Certain known React errors contain links that would be falsely\n * parsed as frames. This function check for these errors and\n * returns number of the stack string lines to skip.\n */\nfunction getSkipFirstStackStringLines(ex: Error): number {\n if (ex && reactMinifiedRegexp.test(ex.message)) {\n return 1\n }\n\n return 0\n}\n\nfunction errorPropertiesFromError(error: Error, metadata?: ErrorMetadata): ErrorProperties {\n const frames = parseStackFrames(error)\n\n const handled = metadata?.handled ?? true\n const synthetic = metadata?.synthetic ?? false\n\n const exceptionType = metadata?.overrideExceptionType ? metadata.overrideExceptionType : error.name\n const exceptionMessage = metadata?.overrideExceptionMessage\n ? metadata.overrideExceptionMessage\n : extractMessage(error)\n\n return {\n $exception_list: [\n {\n type: exceptionType,\n value: exceptionMessage,\n stacktrace: {\n frames,\n type: 'raw',\n },\n mechanism: {\n handled,\n synthetic,\n },\n },\n ],\n $exception_level: 'error',\n }\n}\n\n/**\n * There are cases where stacktrace.message is an Event object\n * https://github.com/getsentry/sentry-javascript/issues/1949\n * In this specific case we try to extract stacktrace.message.error.message\n */\nexport function extractMessage(err: Error & { message: { error?: Error } }): string {\n const message = err.message\n\n if (message.error && typeof message.error.message === 'string') {\n return message.error.message\n }\n\n return message\n}\n\nfunction errorPropertiesFromString(candidate: string, metadata?: ErrorMetadata): ErrorProperties {\n // Defaults for metadata are based on what the error candidate is.\n const handled = metadata?.handled ?? true\n const synthetic = metadata?.synthetic ?? true\n\n const exceptionType = metadata?.overrideExceptionType\n ? metadata.overrideExceptionType\n : (metadata?.defaultExceptionType ?? 'Error')\n const exceptionMessage = metadata?.overrideExceptionMessage\n ? metadata.overrideExceptionMessage\n : candidate\n ? candidate\n : metadata?.defaultExceptionMessage\n\n const exception: Exception = {\n type: exceptionType,\n value: exceptionMessage,\n mechanism: {\n handled,\n synthetic,\n },\n }\n\n if (metadata?.syntheticException) {\n // Kludge: strip the last frame from a synthetically created error\n // so that it does not appear in a users stack trace\n const frames = parseStackFrames(metadata.syntheticException, 1)\n if (frames.length) {\n exception.stacktrace = { frames, type: 'raw' }\n }\n }\n\n return {\n $exception_list: [exception],\n $exception_level: 'error',\n }\n}\n\n/**\n * Given any captured exception, extract its keys and create a sorted\n * and truncated list that will be used inside the event message.\n * eg. `Non-error exception captured with keys: foo, bar, baz`\n */\nfunction extractExceptionKeysForMessage(exception: Record<string, unknown>, maxLength = 40): string {\n const keys = Object.keys(exception)\n keys.sort()\n\n if (!keys.length) {\n return '[object has no keys]'\n }\n\n for (let i = keys.length; i > 0; i--) {\n const serialized = keys.slice(0, i).join(', ')\n if (serialized.length > maxLength) {\n continue\n }\n if (i === keys.length) {\n return serialized\n }\n return serialized.length <= maxLength ? serialized : `${serialized.slice(0, maxLength)}...`\n }\n\n return ''\n}\n\nfunction isSeverityLevel(x: unknown): x is SeverityLevel {\n return isString(x) && !isEmptyString(x) && severityLevels.indexOf(x as SeverityLevel) >= 0\n}\n\nfunction errorPropertiesFromObject(candidate: Record<string, unknown>, metadata?: ErrorMetadata): ErrorProperties {\n // Defaults for metadata are based on what the error candidate is.\n const handled = metadata?.handled ?? true\n const synthetic = metadata?.synthetic ?? true\n\n const exceptionType = metadata?.overrideExceptionType\n ? metadata.overrideExceptionType\n : isEvent(candidate)\n ? candidate.constructor.name\n : 'Error'\n const exceptionMessage = metadata?.overrideExceptionMessage\n ? metadata.overrideExceptionMessage\n : `Non-Error ${'exception'} captured with keys: ${extractExceptionKeysForMessage(candidate)}`\n\n const exception: Exception = {\n type: exceptionType,\n value: exceptionMessage,\n mechanism: {\n handled,\n synthetic,\n },\n }\n\n if (metadata?.syntheticException) {\n // Kludge: strip the last frame from a synthetically created error\n // so that it does not appear in a users stack trace\n const frames = parseStackFrames(metadata?.syntheticException, 1)\n if (frames.length) {\n exception.stacktrace = { frames, type: 'raw' }\n }\n }\n\n return {\n $exception_list: [exception],\n $exception_level: isSeverityLevel(candidate.level) ? candidate.level : 'error',\n }\n}\n\nexport function errorToProperties(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n [event, _, __, ___, error]: ErrorEventArgs,\n metadata?: ErrorMetadata\n): ErrorProperties {\n let errorProperties: ErrorProperties = { $exception_list: [] }\n\n const candidate = error || event\n\n if (isDOMError(candidate) || isDOMException(candidate)) {\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMError\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMException\n\n const domException = candidate as unknown as DOMException\n\n if (isErrorWithStack(candidate)) {\n errorProperties = errorPropertiesFromError(candidate as Error, metadata)\n } else {\n const name = domException.name || (isDOMError(domException) ? 'DOMError' : 'DOMException')\n const message = domException.message ? `${name}: ${domException.message}` : name\n const exceptionType = isDOMError(domException) ? 'DOMError' : 'DOMException'\n errorProperties = errorPropertiesFromString(message, {\n ...metadata,\n overrideExceptionType: exceptionType,\n defaultExceptionMessage: message,\n })\n }\n if ('code' in domException) {\n errorProperties['$exception_DOMException_code'] = `${domException.code}`\n }\n return errorProperties\n } else if (isErrorEvent(candidate as ErrorEvent) && (candidate as ErrorEvent).error) {\n return errorPropertiesFromError((candidate as ErrorEvent).error as Error, metadata)\n } else if (isError(candidate)) {\n return errorPropertiesFromError(candidate, metadata)\n } else if (isPlainObject(candidate) || isEvent(candidate)) {\n // group these by using the keys available on the object\n const objectException = candidate as Record<string, unknown>\n return errorPropertiesFromObject(objectException, metadata)\n } else if (isUndefined(error) && isString(event)) {\n let name = 'Error'\n let message = event\n const groups = event.match(ERROR_TYPES_PATTERN)\n if (groups) {\n name = groups[1]\n message = groups[2]\n }\n\n return errorPropertiesFromString(message, {\n ...metadata,\n overrideExceptionType: name,\n defaultExceptionMessage: message,\n })\n } else {\n return errorPropertiesFromString(candidate as string, metadata)\n }\n}\n\nexport function unhandledRejectionToProperties([ev]: [ev: PromiseRejectionEvent]): ErrorProperties {\n const error = getUnhandledRejectionError(ev)\n\n if (isPrimitive(error)) {\n return errorPropertiesFromString(`Non-Error promise rejection captured with value: ${String(error)}`, {\n handled: false,\n synthetic: false,\n overrideExceptionType: 'UnhandledRejection',\n })\n }\n\n return errorToProperties([error as string | Event], {\n handled: false,\n overrideExceptionType: 'UnhandledRejection',\n defaultExceptionMessage: String(error),\n })\n}\n\nfunction getUnhandledRejectionError(error: unknown): unknown {\n if (isPrimitive(error)) {\n return error\n }\n\n // dig the object of the rejection out of known event types\n try {\n type ErrorWithReason = { reason: unknown }\n // PromiseRejectionEvents store the object of the rejection under 'reason'\n // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent\n if ('reason' in (error as ErrorWithReason)) {\n return (error as ErrorWithReason).reason\n }\n\n type CustomEventWithDetail = { detail: { reason: unknown } }\n // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents\n // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into\n // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec\n // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and\n // https://github.com/getsentry/sentry-javascript/issues/2380\n if ('detail' in (error as CustomEventWithDetail) && 'reason' in (error as CustomEventWithDetail).detail) {\n return (error as CustomEventWithDetail).detail.reason\n }\n } catch {\n // no-empty\n }\n\n return error\n}\n"]}
@@ -228,7 +228,7 @@ export var buildNetworkRequestOptions = function (instanceConfig, remoteNetworkO
228
228
  var _a, _b, _c;
229
229
  var cleanedRequest = enforcedCleaningFn(data);
230
230
  return cleanedRequest
231
- ? (_c = (_b = (_a = instanceConfig.session_recording).maskCapturedNetworkRequestFn) === null || _b === void 0 ? void 0 : _b.call(_a, cleanedRequest)) !== null && _c !== void 0 ? _c : undefined
231
+ ? ((_c = (_b = (_a = instanceConfig.session_recording).maskCapturedNetworkRequestFn) === null || _b === void 0 ? void 0 : _b.call(_a, cleanedRequest)) !== null && _c !== void 0 ? _c : undefined)
232
232
  : undefined;
233
233
  }
234
234
  : function (data) { return scrubPayloads(enforcedCleaningFn(data)); };
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../src/extensions/replay/config.ts"],"names":[],"mappings":"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","sourcesContent":["import { CapturedNetworkRequest, NetworkRecordOptions, PostHogConfig } from '../../types'\nimport { isFunction, isNullish, isString, isUndefined } from '../../utils/type-utils'\nimport { convertToURL } from '../../utils/request-utils'\nimport { logger } from '../../utils/logger'\nimport { shouldCaptureValue } from '../../autocapture-utils'\nimport { each } from '../../utils'\n\nconst LOGGER_PREFIX = '[SessionRecording]'\n\nconst REDACTED = 'redacted'\n\nexport const defaultNetworkOptions: Required<NetworkRecordOptions> = {\n initiatorTypes: [\n 'audio',\n 'beacon',\n 'body',\n 'css',\n 'early-hint',\n 'embed',\n 'fetch',\n 'frame',\n 'iframe',\n 'icon',\n 'image',\n 'img',\n 'input',\n 'link',\n 'navigation',\n 'object',\n 'ping',\n 'script',\n 'track',\n 'video',\n 'xmlhttprequest',\n ],\n maskRequestFn: (data: CapturedNetworkRequest) => data,\n recordHeaders: false,\n recordBody: false,\n recordInitialRequests: false,\n recordPerformance: false,\n performanceEntryTypeToObserve: [\n // 'event', // This is too noisy as it covers all browser events\n 'first-input',\n // 'mark', // Mark is used too liberally. We would need to filter for specific marks\n // 'measure', // Measure is used too liberally. We would need to filter for specific measures\n 'navigation',\n 'paint',\n 'resource',\n ],\n payloadSizeLimitBytes: 1000000,\n payloadHostDenyList: ['.lr-ingest.io', '.ingest.sentry.io'],\n}\n\nconst HEADER_DENY_LIST = [\n 'authorization',\n 'x-forwarded-for',\n 'authorization',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n 'x-real-ip',\n 'remote-addr',\n 'forwarded',\n 'proxy-authorization',\n 'x-csrf-token',\n 'x-csrftoken',\n 'x-xsrf-token',\n]\n\nconst PAYLOAD_CONTENT_DENY_LIST = [\n 'password',\n 'secret',\n 'passwd',\n 'api_key',\n 'apikey',\n 'auth',\n 'credentials',\n 'mysql_pwd',\n 'privatekey',\n 'private_key',\n 'token',\n]\n\n// we always remove headers on the deny list because we never want to capture this sensitive data\nconst removeAuthorizationHeader = (data: CapturedNetworkRequest): CapturedNetworkRequest => {\n const headers = data.requestHeaders\n if (!isNullish(headers)) {\n each(Object.keys(headers ?? {}), (header) => {\n if (HEADER_DENY_LIST.includes(header.toLowerCase())) {\n headers[header] = REDACTED\n }\n })\n }\n return data\n}\n\nconst POSTHOG_PATHS_TO_IGNORE = ['/s/', '/e/', '/i/']\n// want to ignore posthog paths when capturing requests, or we can get trapped in a loop\n// because calls to PostHog would be reported using a call to PostHog which would be reported....\nconst ignorePostHogPaths = (\n data: CapturedNetworkRequest,\n apiHostConfig: PostHogConfig['api_host']\n): CapturedNetworkRequest | undefined => {\n const url = convertToURL(data.name)\n\n // we need to account for api host config as e.g. pathname could be /ingest/s/ and we want to ignore that\n let replaceValue = apiHostConfig.indexOf('http') === 0 ? convertToURL(apiHostConfig)?.pathname : apiHostConfig\n if (replaceValue === '/') {\n replaceValue = ''\n }\n const pathname = url?.pathname.replace(replaceValue || '', '')\n\n if (url && pathname && POSTHOG_PATHS_TO_IGNORE.some((path) => pathname.indexOf(path) === 0)) {\n return undefined\n }\n return data\n}\n\nfunction estimateBytes(payload: string): number {\n return new Blob([payload]).size\n}\n\nfunction enforcePayloadSizeLimit(\n payload: string | null | undefined,\n headers: Record<string, any> | undefined,\n limit: number,\n description: string\n): string | null | undefined {\n if (isNullish(payload)) {\n return payload\n }\n\n let requestContentLength: string | number = headers?.['content-length'] || estimateBytes(payload)\n if (isString(requestContentLength)) {\n requestContentLength = parseInt(requestContentLength)\n }\n\n if (requestContentLength > limit) {\n return LOGGER_PREFIX + ` ${description} body too large to record (${requestContentLength} bytes)`\n }\n\n return payload\n}\n\n// people can have arbitrarily large payloads on their site, but we don't want to ingest them\nconst limitPayloadSize = (\n options: NetworkRecordOptions\n): ((data: CapturedNetworkRequest | undefined) => CapturedNetworkRequest | undefined) => {\n // the smallest of 1MB or the specified limit if there is one\n const limit = Math.min(1000000, options.payloadSizeLimitBytes ?? 1000000)\n\n return (data) => {\n if (data?.requestBody) {\n data.requestBody = enforcePayloadSizeLimit(data.requestBody, data.requestHeaders, limit, 'Request')\n }\n\n if (data?.responseBody) {\n data.responseBody = enforcePayloadSizeLimit(data.responseBody, data.responseHeaders, limit, 'Response')\n }\n\n return data\n }\n}\n\nfunction scrubPayload(payload: string | null | undefined, label: 'Request' | 'Response'): string | null | undefined {\n if (isNullish(payload)) {\n return payload\n }\n let scrubbed = payload\n\n if (!shouldCaptureValue(scrubbed, false)) {\n scrubbed = LOGGER_PREFIX + ' ' + label + ' body ' + REDACTED\n }\n each(PAYLOAD_CONTENT_DENY_LIST, (text) => {\n if (scrubbed?.length && scrubbed?.indexOf(text) !== -1) {\n scrubbed = LOGGER_PREFIX + ' ' + label + ' body ' + REDACTED + ' as might contain: ' + text\n }\n })\n\n return scrubbed\n}\n\nfunction scrubPayloads(capturedRequest: CapturedNetworkRequest | undefined): CapturedNetworkRequest | undefined {\n if (isUndefined(capturedRequest)) {\n return undefined\n }\n\n capturedRequest.requestBody = scrubPayload(capturedRequest.requestBody, 'Request')\n capturedRequest.responseBody = scrubPayload(capturedRequest.responseBody, 'Response')\n\n return capturedRequest\n}\n\n/**\n * whether a maskRequestFn is provided or not,\n * we ensure that we remove the denied header from requests\n * we _never_ want to record that header by accident\n * if someone complains then we'll add an opt-in to let them override it\n */\nexport const buildNetworkRequestOptions = (\n instanceConfig: PostHogConfig,\n remoteNetworkOptions: Pick<\n NetworkRecordOptions,\n 'recordHeaders' | 'recordBody' | 'recordPerformance' | 'payloadHostDenyList'\n >\n): NetworkRecordOptions => {\n const config: NetworkRecordOptions = {\n payloadSizeLimitBytes: defaultNetworkOptions.payloadSizeLimitBytes,\n performanceEntryTypeToObserve: [...defaultNetworkOptions.performanceEntryTypeToObserve],\n payloadHostDenyList: [\n ...(remoteNetworkOptions.payloadHostDenyList || []),\n ...defaultNetworkOptions.payloadHostDenyList,\n ],\n }\n // client can always disable despite remote options\n const canRecordHeaders =\n instanceConfig.session_recording.recordHeaders === false ? false : remoteNetworkOptions.recordHeaders\n const canRecordBody =\n instanceConfig.session_recording.recordBody === false ? false : remoteNetworkOptions.recordBody\n const canRecordPerformance =\n instanceConfig.capture_performance === false ? false : remoteNetworkOptions.recordPerformance\n\n const payloadLimiter = limitPayloadSize(config)\n\n const enforcedCleaningFn: NetworkRecordOptions['maskRequestFn'] = (d: CapturedNetworkRequest) =>\n payloadLimiter(ignorePostHogPaths(removeAuthorizationHeader(d), instanceConfig.api_host))\n\n const hasDeprecatedMaskFunction = isFunction(instanceConfig.session_recording.maskNetworkRequestFn)\n\n if (hasDeprecatedMaskFunction && isFunction(instanceConfig.session_recording.maskCapturedNetworkRequestFn)) {\n logger.warn(\n 'Both `maskNetworkRequestFn` and `maskCapturedNetworkRequestFn` are defined. `maskNetworkRequestFn` will be ignored.'\n )\n }\n\n if (hasDeprecatedMaskFunction) {\n instanceConfig.session_recording.maskCapturedNetworkRequestFn = (data: CapturedNetworkRequest) => {\n const cleanedURL = instanceConfig.session_recording.maskNetworkRequestFn!({ url: data.name })\n return {\n ...data,\n name: cleanedURL?.url,\n } as CapturedNetworkRequest\n }\n }\n\n config.maskRequestFn = isFunction(instanceConfig.session_recording.maskCapturedNetworkRequestFn)\n ? (data) => {\n const cleanedRequest = enforcedCleaningFn(data)\n return cleanedRequest\n ? instanceConfig.session_recording.maskCapturedNetworkRequestFn?.(cleanedRequest) ?? undefined\n : undefined\n }\n : (data) => scrubPayloads(enforcedCleaningFn(data))\n\n return {\n ...defaultNetworkOptions,\n ...config,\n recordHeaders: canRecordHeaders,\n recordBody: canRecordBody,\n recordPerformance: canRecordPerformance,\n recordInitialRequests: canRecordPerformance,\n }\n}\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../src/extensions/replay/config.ts"],"names":[],"mappings":"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","sourcesContent":["import { CapturedNetworkRequest, NetworkRecordOptions, PostHogConfig } from '../../types'\nimport { isFunction, isNullish, isString, isUndefined } from '../../utils/type-utils'\nimport { convertToURL } from '../../utils/request-utils'\nimport { logger } from '../../utils/logger'\nimport { shouldCaptureValue } from '../../autocapture-utils'\nimport { each } from '../../utils'\n\nconst LOGGER_PREFIX = '[SessionRecording]'\n\nconst REDACTED = 'redacted'\n\nexport const defaultNetworkOptions: Required<NetworkRecordOptions> = {\n initiatorTypes: [\n 'audio',\n 'beacon',\n 'body',\n 'css',\n 'early-hint',\n 'embed',\n 'fetch',\n 'frame',\n 'iframe',\n 'icon',\n 'image',\n 'img',\n 'input',\n 'link',\n 'navigation',\n 'object',\n 'ping',\n 'script',\n 'track',\n 'video',\n 'xmlhttprequest',\n ],\n maskRequestFn: (data: CapturedNetworkRequest) => data,\n recordHeaders: false,\n recordBody: false,\n recordInitialRequests: false,\n recordPerformance: false,\n performanceEntryTypeToObserve: [\n // 'event', // This is too noisy as it covers all browser events\n 'first-input',\n // 'mark', // Mark is used too liberally. We would need to filter for specific marks\n // 'measure', // Measure is used too liberally. We would need to filter for specific measures\n 'navigation',\n 'paint',\n 'resource',\n ],\n payloadSizeLimitBytes: 1000000,\n payloadHostDenyList: ['.lr-ingest.io', '.ingest.sentry.io'],\n}\n\nconst HEADER_DENY_LIST = [\n 'authorization',\n 'x-forwarded-for',\n 'authorization',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n 'x-real-ip',\n 'remote-addr',\n 'forwarded',\n 'proxy-authorization',\n 'x-csrf-token',\n 'x-csrftoken',\n 'x-xsrf-token',\n]\n\nconst PAYLOAD_CONTENT_DENY_LIST = [\n 'password',\n 'secret',\n 'passwd',\n 'api_key',\n 'apikey',\n 'auth',\n 'credentials',\n 'mysql_pwd',\n 'privatekey',\n 'private_key',\n 'token',\n]\n\n// we always remove headers on the deny list because we never want to capture this sensitive data\nconst removeAuthorizationHeader = (data: CapturedNetworkRequest): CapturedNetworkRequest => {\n const headers = data.requestHeaders\n if (!isNullish(headers)) {\n each(Object.keys(headers ?? {}), (header) => {\n if (HEADER_DENY_LIST.includes(header.toLowerCase())) {\n headers[header] = REDACTED\n }\n })\n }\n return data\n}\n\nconst POSTHOG_PATHS_TO_IGNORE = ['/s/', '/e/', '/i/']\n// want to ignore posthog paths when capturing requests, or we can get trapped in a loop\n// because calls to PostHog would be reported using a call to PostHog which would be reported....\nconst ignorePostHogPaths = (\n data: CapturedNetworkRequest,\n apiHostConfig: PostHogConfig['api_host']\n): CapturedNetworkRequest | undefined => {\n const url = convertToURL(data.name)\n\n // we need to account for api host config as e.g. pathname could be /ingest/s/ and we want to ignore that\n let replaceValue = apiHostConfig.indexOf('http') === 0 ? convertToURL(apiHostConfig)?.pathname : apiHostConfig\n if (replaceValue === '/') {\n replaceValue = ''\n }\n const pathname = url?.pathname.replace(replaceValue || '', '')\n\n if (url && pathname && POSTHOG_PATHS_TO_IGNORE.some((path) => pathname.indexOf(path) === 0)) {\n return undefined\n }\n return data\n}\n\nfunction estimateBytes(payload: string): number {\n return new Blob([payload]).size\n}\n\nfunction enforcePayloadSizeLimit(\n payload: string | null | undefined,\n headers: Record<string, any> | undefined,\n limit: number,\n description: string\n): string | null | undefined {\n if (isNullish(payload)) {\n return payload\n }\n\n let requestContentLength: string | number = headers?.['content-length'] || estimateBytes(payload)\n if (isString(requestContentLength)) {\n requestContentLength = parseInt(requestContentLength)\n }\n\n if (requestContentLength > limit) {\n return LOGGER_PREFIX + ` ${description} body too large to record (${requestContentLength} bytes)`\n }\n\n return payload\n}\n\n// people can have arbitrarily large payloads on their site, but we don't want to ingest them\nconst limitPayloadSize = (\n options: NetworkRecordOptions\n): ((data: CapturedNetworkRequest | undefined) => CapturedNetworkRequest | undefined) => {\n // the smallest of 1MB or the specified limit if there is one\n const limit = Math.min(1000000, options.payloadSizeLimitBytes ?? 1000000)\n\n return (data) => {\n if (data?.requestBody) {\n data.requestBody = enforcePayloadSizeLimit(data.requestBody, data.requestHeaders, limit, 'Request')\n }\n\n if (data?.responseBody) {\n data.responseBody = enforcePayloadSizeLimit(data.responseBody, data.responseHeaders, limit, 'Response')\n }\n\n return data\n }\n}\n\nfunction scrubPayload(payload: string | null | undefined, label: 'Request' | 'Response'): string | null | undefined {\n if (isNullish(payload)) {\n return payload\n }\n let scrubbed = payload\n\n if (!shouldCaptureValue(scrubbed, false)) {\n scrubbed = LOGGER_PREFIX + ' ' + label + ' body ' + REDACTED\n }\n each(PAYLOAD_CONTENT_DENY_LIST, (text) => {\n if (scrubbed?.length && scrubbed?.indexOf(text) !== -1) {\n scrubbed = LOGGER_PREFIX + ' ' + label + ' body ' + REDACTED + ' as might contain: ' + text\n }\n })\n\n return scrubbed\n}\n\nfunction scrubPayloads(capturedRequest: CapturedNetworkRequest | undefined): CapturedNetworkRequest | undefined {\n if (isUndefined(capturedRequest)) {\n return undefined\n }\n\n capturedRequest.requestBody = scrubPayload(capturedRequest.requestBody, 'Request')\n capturedRequest.responseBody = scrubPayload(capturedRequest.responseBody, 'Response')\n\n return capturedRequest\n}\n\n/**\n * whether a maskRequestFn is provided or not,\n * we ensure that we remove the denied header from requests\n * we _never_ want to record that header by accident\n * if someone complains then we'll add an opt-in to let them override it\n */\nexport const buildNetworkRequestOptions = (\n instanceConfig: PostHogConfig,\n remoteNetworkOptions: Pick<\n NetworkRecordOptions,\n 'recordHeaders' | 'recordBody' | 'recordPerformance' | 'payloadHostDenyList'\n >\n): NetworkRecordOptions => {\n const config: NetworkRecordOptions = {\n payloadSizeLimitBytes: defaultNetworkOptions.payloadSizeLimitBytes,\n performanceEntryTypeToObserve: [...defaultNetworkOptions.performanceEntryTypeToObserve],\n payloadHostDenyList: [\n ...(remoteNetworkOptions.payloadHostDenyList || []),\n ...defaultNetworkOptions.payloadHostDenyList,\n ],\n }\n // client can always disable despite remote options\n const canRecordHeaders =\n instanceConfig.session_recording.recordHeaders === false ? false : remoteNetworkOptions.recordHeaders\n const canRecordBody =\n instanceConfig.session_recording.recordBody === false ? false : remoteNetworkOptions.recordBody\n const canRecordPerformance =\n instanceConfig.capture_performance === false ? false : remoteNetworkOptions.recordPerformance\n\n const payloadLimiter = limitPayloadSize(config)\n\n const enforcedCleaningFn: NetworkRecordOptions['maskRequestFn'] = (d: CapturedNetworkRequest) =>\n payloadLimiter(ignorePostHogPaths(removeAuthorizationHeader(d), instanceConfig.api_host))\n\n const hasDeprecatedMaskFunction = isFunction(instanceConfig.session_recording.maskNetworkRequestFn)\n\n if (hasDeprecatedMaskFunction && isFunction(instanceConfig.session_recording.maskCapturedNetworkRequestFn)) {\n logger.warn(\n 'Both `maskNetworkRequestFn` and `maskCapturedNetworkRequestFn` are defined. `maskNetworkRequestFn` will be ignored.'\n )\n }\n\n if (hasDeprecatedMaskFunction) {\n instanceConfig.session_recording.maskCapturedNetworkRequestFn = (data: CapturedNetworkRequest) => {\n const cleanedURL = instanceConfig.session_recording.maskNetworkRequestFn!({ url: data.name })\n return {\n ...data,\n name: cleanedURL?.url,\n } as CapturedNetworkRequest\n }\n }\n\n config.maskRequestFn = isFunction(instanceConfig.session_recording.maskCapturedNetworkRequestFn)\n ? (data) => {\n const cleanedRequest = enforcedCleaningFn(data)\n return cleanedRequest\n ? (instanceConfig.session_recording.maskCapturedNetworkRequestFn?.(cleanedRequest) ?? undefined)\n : undefined\n }\n : (data) => scrubPayloads(enforcedCleaningFn(data))\n\n return {\n ...defaultNetworkOptions,\n ...config,\n recordHeaders: canRecordHeaders,\n recordBody: canRecordBody,\n recordPerformance: canRecordPerformance,\n recordInitialRequests: canRecordPerformance,\n }\n}\n"]}