@sourav732/error-tracker-js 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +228 -2
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types/collectors/breadcrumbCollector.d.ts +45 -0
- package/dist/types/collectors/collector.d.ts +22 -0
- package/dist/types/collectors/cspCollector.d.ts +63 -0
- package/dist/types/collectors/errorCollector.d.ts +26 -0
- package/dist/types/collectors/httpErrorCollector.d.ts +34 -0
- package/dist/types/collectors/jsonResponseCollector.d.ts +24 -0
- package/dist/types/collectors/memoryCollector.d.ts +38 -0
- package/dist/types/collectors/networkInterceptor.d.ts +54 -0
- package/dist/types/collectors/performanceCollector.d.ts +50 -0
- package/dist/types/collectors/resourceCollector.d.ts +45 -0
- package/dist/types/collectors/responsivenessCollector.d.ts +45 -0
- package/dist/types/collectors/screenshotCollector.d.ts +52 -0
- package/dist/types/collectors/workerCollector.d.ts +22 -0
- package/dist/types/constants.d.ts +99 -0
- package/dist/types/core/circularBuffer.d.ts +15 -0
- package/dist/types/core/client.d.ts +71 -0
- package/dist/types/core/config.d.ts +28 -0
- package/dist/types/core/device.d.ts +23 -0
- package/dist/types/core/env.d.ts +21 -0
- package/dist/types/core/eventFilters.d.ts +32 -0
- package/dist/types/core/eventQueue.d.ts +52 -0
- package/dist/types/core/logger.d.ts +19 -0
- package/dist/types/core/payloadBuilder.d.ts +32 -0
- package/dist/types/core/reportedErrors.d.ts +18 -0
- package/dist/types/core/retryManager.d.ts +18 -0
- package/dist/types/core/safe.d.ts +10 -0
- package/dist/types/core/serialize.d.ts +13 -0
- package/dist/types/core/stackParser.d.ts +5 -0
- package/dist/types/index.d.ts +55 -0
- package/dist/types/transport/httpTransport.d.ts +24 -0
- package/dist/types/transport/offlineStore.d.ts +33 -0
- package/dist/types/types.d.ts +161 -0
- package/package.json +62 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/constants.ts","../src/core/env.ts","../src/core/logger.ts","../src/core/reportedErrors.ts","../src/core/safe.ts","../src/core/serialize.ts","../src/core/stackParser.ts","../src/collectors/errorCollector.ts","../src/collectors/breadcrumbCollector.ts","../src/collectors/cspCollector.ts","../src/collectors/httpErrorCollector.ts","../src/collectors/jsonResponseCollector.ts","../src/collectors/memoryCollector.ts","../src/collectors/networkInterceptor.ts","../src/core/circularBuffer.ts","../src/core/payloadBuilder.ts","../src/collectors/performanceCollector.ts","../src/collectors/resourceCollector.ts","../src/collectors/responsivenessCollector.ts","../src/collectors/screenshotCollector.ts","../src/collectors/workerCollector.ts","../src/transport/httpTransport.ts","../src/transport/offlineStore.ts","../src/core/device.ts","../src/core/eventFilters.ts","../src/core/retryManager.ts","../src/core/eventQueue.ts","../src/core/client.ts","../src/core/config.ts","../src/index.ts"],"sourcesContent":["/**\r\n * Every tunable number and fixed string used by the SDK lives here.\r\n * Nothing else in the codebase should contain a bare threshold, timeout or limit.\r\n */\r\n\r\nexport const SDK_NAME = 'error-tracker-js';\r\n/** Must match package.json \"version\" (a test enforces this). */\nexport const SDK_VERSION = '0.1.0';\r\nexport const PLATFORM = 'js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Config defaults\r\n// ---------------------------------------------------------------------------\r\nexport const DEFAULT_SAMPLE_RATE = 1.0;\r\nexport const DEFAULT_MAX_BREADCRUMBS = 30;\r\n/** Hard ceiling so a misconfigured app cannot make every payload huge. */\r\nexport const MAX_BREADCRUMBS_LIMIT = 100;\r\nexport const DEFAULT_ENVIRONMENT = 'production';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Transport\r\n// ---------------------------------------------------------------------------\r\nexport const API_KEY_HEADER = 'X-API-Key';\r\nexport const CONTENT_TYPE_JSON = 'application/json';\r\nexport const BATCH_SIZE = 10;\r\n/** How long to wait for more events before sending a partial batch. */\r\nexport const FLUSH_DELAY_MS = 2000;\r\n/** Backoff before each retry; length of this array is the retry count. */\r\nexport const RETRY_DELAYS_MS: readonly number[] = [1000, 2000, 4000];\r\nexport const REQUEST_TIMEOUT_MS = 30000;\r\n/** In-memory queue cap; oldest events are dropped beyond this. */\r\nexport const MAX_QUEUE_SIZE = 100;\r\nexport const OFFLINE_STORAGE_KEY = '_et_queue';\r\n/** Persisted queue cap; keeps localStorage usage bounded. */\r\nexport const MAX_PERSISTED_EVENTS = 50;\r\nexport const HTTP_STATUS_REQUEST_TIMEOUT = 408;\r\nexport const HTTP_STATUS_TOO_MANY_REQUESTS = 429;\r\nexport const HTTP_STATUS_SERVER_ERROR_MIN = 500;\r\nexport const HTTP_STATUS_OK_MIN = 200;\r\nexport const HTTP_STATUS_OK_MAX = 299;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Event filtering\r\n// ---------------------------------------------------------------------------\r\n/** Max events accepted per rolling window (error-storm protection). */\r\nexport const RATE_LIMIT_MAX_EVENTS = 100;\r\nexport const RATE_LIMIT_WINDOW_MS = 60000;\r\n/** Identical events inside this window are dropped as duplicates. */\r\nexport const DEDUP_WINDOW_MS = 5000;\r\n/** Number of distinct fingerprints remembered for dedup. */\r\nexport const DEDUP_MAX_ENTRIES = 200;\r\n/** Calls made to the public API before init() are buffered up to this count. */\r\nexport const MAX_PRE_INIT_CALLS = 100;\r\n/** How long a reported error's text signature suppresses a second copy of the same failure. */\r\nexport const REPORTED_SIGNATURE_TTL_MS = 2000;\r\n/** After the rate limiter starts dropping, a summary event is sent this long after the first drop. */\r\nexport const DROPPED_EVENTS_REPORT_DELAY_MS = 10000;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Stack traces & serialization\r\n// ---------------------------------------------------------------------------\r\nexport const MAX_STACK_FRAMES = 50;\r\nexport const MAX_SERIALIZE_DEPTH = 5;\r\nexport const MAX_SERIALIZE_KEYS = 50;\r\nexport const MAX_STRING_LENGTH = 1000;\r\nexport const MAX_MESSAGE_LENGTH = 2000;\r\nexport const UNKNOWN_FUNCTION = '<anonymous>';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Breadcrumbs\r\n// ---------------------------------------------------------------------------\r\nexport const MAX_CLICK_TEXT_LENGTH = 50;\r\nexport const MAX_CSS_PATH_DEPTH = 5;\r\nexport const MASKED_TEXT = '[masked]';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Performance\r\n// ---------------------------------------------------------------------------\r\nexport const SLOW_PAGE_LOAD_MS = 3000;\r\nexport const SLOW_API_CALL_MS = 2000;\r\n/** Responses at or above this status are reported as HttpError events. */\r\nexport const HTTP_ERROR_STATUS_MIN = 400;\r\n/** Number of most recent API calls attached to every payload. */\r\nexport const MAX_API_CALLS_TRACKED = 20;\r\n/** Delay after window `load` so loadEventEnd is populated. */\r\nexport const PAGE_LOAD_SETTLE_MS = 0;\r\n/** CLS session window rules (per the web-vitals definition). */\r\nexport const CLS_SESSION_GAP_MS = 1000;\r\nexport const CLS_SESSION_MAX_MS = 5000;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Responsiveness (main-thread blocking and frame rate)\r\n// ---------------------------------------------------------------------------\r\n/** A single main-thread task longer than this is reported as a page freeze. */\r\nexport const LONG_TASK_FREEZE_MS = 1000;\r\n/** Minimum gap between two freeze reports, so a sluggish page cannot flood events. */\r\nexport const FREEZE_REPORT_INTERVAL_MS = 30000;\r\n/** Delay before the first frame-rate sample, so page-load work doesn't skew it. */\r\nexport const FPS_FIRST_SAMPLE_DELAY_MS = 5000;\r\n/** How often the frame rate is sampled while the page is visible. */\r\nexport const FPS_SAMPLE_INTERVAL_MS = 30000;\r\n/** How long each frame-rate sample runs. */\r\nexport const FPS_SAMPLE_DURATION_MS = 1000;\r\n/** Sampled frame rates below this are reported as LowFrameRate. Kept well under 30 fps because low-power modes cap at 30. */\r\nexport const LOW_FPS_THRESHOLD = 20;\r\nexport const MS_PER_SECOND = 1000;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Memory\r\n// ---------------------------------------------------------------------------\r\nexport const MEMORY_POLL_INTERVAL_MS = 30000;\r\nexport const LEAK_CONSECUTIVE_READINGS = 3;\r\n/** Growth ratio across the consecutive readings that flags a leak (20%). */\r\nexport const LEAK_GROWTH_THRESHOLD = 0.2;\r\nexport const BYTES_PER_MB = 1024 * 1024;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Screenshots\r\n// ---------------------------------------------------------------------------\r\nexport const DEFAULT_HTML2CANVAS_URL =\r\n 'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js';\r\n/** Subresource-integrity hash of DEFAULT_HTML2CANVAS_URL. */\r\nexport const DEFAULT_HTML2CANVAS_INTEGRITY =\r\n 'sha384-ZZ1pncU3bQe8y31yfZdMFdSpttDoPmOZg2wguVK9almUodir1PghgT0eY7Mrty8H';\r\nexport const SCREENSHOT_MIME_TYPE = 'image/jpeg';\r\nexport const SCREENSHOT_QUALITY = 0.6;\r\n/** Fallback quality used when the first encode is over the size budget. */\r\nexport const SCREENSHOT_FALLBACK_QUALITY = 0.3;\r\n/** Max base64 length of a screenshot data URL (~750 KB). */\r\nexport const MAX_SCREENSHOT_LENGTH = 1000000;\r\n/** Library load + render must finish within this or the event is sent without it. */\r\nexport const SCREENSHOT_TIMEOUT_MS = 3000;\r\n/** At most one screenshot per interval to protect the host app's main thread. */\r\nexport const SCREENSHOT_MIN_INTERVAL_MS = 10000;\r\nexport const SCREENSHOT_MAX_SCALE = 1;\r\nexport const MASK_COLOR = '#000000';\r\n/** Always masked, in addition to config.maskSelectors. */\r\nexport const DEFAULT_MASK_SELECTORS: readonly string[] = ['input[type=\"password\"]'];\r\n","/**\r\n * Guarded access to browser globals so the SDK can be imported in Node.js,\r\n * SSR and web workers without throwing.\r\n */\r\n\r\nexport function getWindow(): Window | null {\r\n return typeof window !== 'undefined' ? window : null;\r\n}\r\n\r\nexport function getDocument(): Document | null {\r\n return typeof document !== 'undefined' ? document : null;\r\n}\r\n\r\nexport function getNavigator(): Navigator | null {\r\n return typeof navigator !== 'undefined' ? navigator : null;\r\n}\r\n\r\nexport function getPerformance(): Performance | null {\r\n return typeof performance !== 'undefined' ? performance : null;\r\n}\r\n\r\n/** localStorage throws on access in some privacy modes, so even reading the property is guarded. */\r\nexport function getLocalStorage(): Storage | null {\r\n try {\r\n return typeof localStorage !== 'undefined' ? localStorage : null;\r\n } catch (_e) {\r\n return null;\r\n }\r\n}\r\n\r\nexport function isOnline(): boolean {\r\n const nav = getNavigator();\r\n // Treat \"unknown\" as online so we attempt delivery rather than buffer forever.\r\n return nav === null || nav.onLine !== false;\r\n}\r\n\r\nexport function isPageVisible(): boolean {\r\n const doc = getDocument();\r\n return doc !== null && doc.visibilityState !== 'hidden';\r\n}\r\n\r\nexport function nowIso(): string {\r\n return new Date().toISOString();\r\n}\r\n\r\n/** High-resolution monotonic time where available. */\r\nexport function nowMs(): number {\r\n const perf = getPerformance();\r\n return perf !== null && typeof perf.now === 'function' ? perf.now() : Date.now();\r\n}\r\n\r\n/** Removes the query string and fragment, which commonly carry tokens or PII. */\r\nexport function stripQuery(url: string): string {\r\n const cut = url.search(/[?#]/);\r\n return cut === -1 ? url : url.slice(0, cut);\r\n}\r\n\r\n/** Resolves relative URLs against the page so comparisons are reliable. */\r\nexport function absoluteUrl(url: string): string {\r\n const doc = getDocument();\r\n try {\r\n return doc !== null ? new URL(url, doc.baseURI).href : url;\r\n } catch (_e) {\r\n return url;\r\n }\r\n}\r\n\r\n/** Rounds to whole milliseconds; negative or non-finite values become null. */\r\nexport function toMs(value: number | null | undefined): number | null {\r\n if (value === null || value === undefined || !isFinite(value) || value < 0) return null;\r\n return Math.round(value);\r\n}\r\n","/**\r\n * Debug-only logger. Produces no output unless `debug: true` was configured.\r\n *\r\n * Every line starts with LOG_PREFIX; the breadcrumb collector's console hook\r\n * uses it to keep SDK diagnostics out of the breadcrumb trail.\r\n */\r\n\r\nexport const LOG_PREFIX = '[ErrorTracker]';\r\n\r\ntype ConsoleMethod = 'log' | 'warn' | 'error';\r\n\r\nexport class Logger {\r\n private enabled: boolean;\r\n\r\n constructor(enabled: boolean) {\r\n this.enabled = enabled;\r\n }\r\n\r\n setEnabled(enabled: boolean): void {\r\n this.enabled = enabled;\r\n }\r\n\r\n isEnabled(): boolean {\r\n return this.enabled;\r\n }\r\n\r\n info(message: string, ...details: unknown[]): void {\r\n this.write('log', message, details);\r\n }\r\n\r\n warn(message: string, ...details: unknown[]): void {\r\n this.write('warn', message, details);\r\n }\r\n\r\n error(message: string, ...details: unknown[]): void {\r\n this.write('error', message, details);\r\n }\r\n\r\n private write(method: ConsoleMethod, message: string, details: unknown[]): void {\r\n if (!this.enabled || typeof console === 'undefined') return;\r\n try {\r\n const fn = console[method];\r\n if (typeof fn === 'function') fn.apply(console, ([LOG_PREFIX + ' ' + message] as unknown[]).concat(details));\r\n } catch (_e) {\r\n // Console itself is broken; nothing sensible left to do.\r\n }\r\n }\r\n}\r\n\r\n/** Shared logger used before init() and by modules without a client reference. */\r\nexport const sharedLogger = new Logger(false);\r\n","/**\n * Remembers error objects the SDK has already turned into events, so a single\n * failure is never reported twice. Example: a failed `fetch` is reported as a\n * NetworkError, and the same TypeError may later reach `unhandledrejection`\n * or `console.error`; those later sightings are skipped.\n *\n * Uses a WeakSet, so remembered errors are still garbage-collected normally.\n */\n\nimport { REPORTED_SIGNATURE_TTL_MS } from '../constants';\n\nconst reported: WeakSet<object> | null = typeof WeakSet !== 'undefined' ? new WeakSet<object>() : null;\n\nfunction isObject(value: unknown): value is object {\n return value !== null && (typeof value === 'object' || typeof value === 'function');\n}\n\n/** Marks `value` as reported. Primitives cannot be tracked and are ignored. */\nexport function markReported(value: unknown): void {\n if (reported !== null && isObject(value)) reported.add(value);\n}\n\n/** True if `value` was already turned into an event. */\nexport function wasReported(value: unknown): boolean {\n return reported !== null && isObject(value) && reported.has(value);\n}\n\n/**\n * Some failures reach the SDK twice as *different* objects, e.g. an unhandled\n * error inside a Web Worker fires on the Worker and may then be re-dispatched\n * on `window`. Those are matched by a text signature that expires quickly.\n */\nconst signatures: Record<string, number> = {};\n\n/** Remembers a signature (e.g. message + file + line) as reported, for a short time. */\nexport function markSignatureReported(signature: string, now: number = Date.now()): void {\n signatures[signature] = now;\n // Keep the map tiny: drop anything already expired.\n Object.keys(signatures).forEach(function prune(key) {\n if (now - signatures[key] > REPORTED_SIGNATURE_TTL_MS) delete signatures[key];\n });\n}\n\n/** True if the signature was reported within the last few seconds. */\nexport function wasSignatureReported(signature: string, now: number = Date.now()): boolean {\n const seen = signatures[signature];\n return seen !== undefined && now - seen <= REPORTED_SIGNATURE_TTL_MS;\n}\n\n/** Signature for an error that has only text and a location (no error object). */\nexport function locationSignature(message: string, filename: string | null, lineno: number | null): string {\n return message + '|' + String(filename) + '|' + String(lineno);\n}\n","import { Logger } from './logger';\r\n\r\n/**\r\n * Runs `fn` and converts any exception into a debug warning plus `fallback`.\r\n * This is the SDK's main guarantee that it never throws into the host app.\r\n */\r\nexport function safely<T>(logger: Logger, label: string, fn: () => T, fallback: T): T {\r\n try {\r\n return fn();\r\n } catch (e) {\r\n logger.warn(label + ' failed', e);\r\n return fallback;\r\n }\r\n}\r\n\r\n/** `safely` for functions with no meaningful return value. */\r\nexport function safelyRun(logger: Logger, label: string, fn: () => void): void {\r\n safely<void>(logger, label, fn, undefined);\r\n}\r\n\r\n/** Wraps a callback so exceptions inside it are swallowed (with a debug log). */\r\nexport function guard<A extends unknown[]>(\r\n logger: Logger,\r\n label: string,\r\n fn: (...args: A) => void,\r\n): (...args: A) => void {\r\n return function guarded(...args: A): void {\r\n safelyRun(logger, label, function run() {\r\n fn.apply(null, args);\r\n });\r\n };\r\n}\r\n","import {\r\n MAX_SERIALIZE_DEPTH,\r\n MAX_SERIALIZE_KEYS,\r\n MAX_STRING_LENGTH,\r\n} from '../constants';\r\nimport { JsonObject, JsonValue } from '../types';\r\n\r\nconst CIRCULAR = '[Circular]';\r\nconst MAX_DEPTH_MARKER = '[MaxDepth]';\r\nconst TRUNCATION_SUFFIX = '…';\r\n\r\n/** Shortens a string to `max` characters, marking that it was cut. */\r\nexport function truncate(value: string, max: number): string {\r\n return value.length > max ? value.slice(0, max) + TRUNCATION_SUFFIX : value;\r\n}\r\n\r\n/**\r\n * Converts an arbitrary value into JSON-safe data: circular references,\r\n * functions, DOM nodes, errors and deep/wide structures are all handled so\r\n * `JSON.stringify` on the result can never throw.\r\n */\r\nexport function normalize(value: unknown, depth: number = MAX_SERIALIZE_DEPTH): JsonValue {\r\n return normalizeInner(value, depth, []);\r\n}\r\n\r\n/** `normalize` for values that must end up as a JSON object. */\r\nexport function normalizeObject(value: unknown): JsonObject {\r\n const result = normalize(value);\r\n if (result !== null && typeof result === 'object' && !isArray(result)) return result;\r\n return {};\r\n}\r\n\r\nfunction isArray(value: unknown): value is unknown[] {\r\n return Object.prototype.toString.call(value) === '[object Array]';\r\n}\r\n\r\nfunction normalizeInner(value: unknown, depth: number, seen: unknown[]): JsonValue {\r\n if (value === null || value === undefined) return null;\r\n\r\n switch (typeof value) {\r\n case 'string':\r\n return truncate(value, MAX_STRING_LENGTH);\r\n case 'number':\r\n return isFinite(value) ? value : String(value);\r\n case 'boolean':\r\n return value;\r\n case 'bigint':\r\n return value.toString();\r\n case 'symbol':\r\n return value.toString();\r\n case 'function':\r\n return '[Function ' + (value.name || 'anonymous') + ']';\r\n default:\r\n break;\r\n }\r\n\r\n if (value instanceof Error) {\r\n return { name: value.name, message: truncate(value.message, MAX_STRING_LENGTH) };\r\n }\r\n if (value instanceof Date) {\r\n return isNaN(value.getTime()) ? 'Invalid Date' : value.toISOString();\r\n }\r\n if (typeof Node !== 'undefined' && value instanceof Node) {\r\n return '[' + value.nodeName + ']';\r\n }\r\n\r\n if (seen.indexOf(value) !== -1) return CIRCULAR;\r\n if (depth <= 0) return MAX_DEPTH_MARKER;\r\n\r\n seen.push(value);\r\n try {\r\n if (isArray(value)) {\r\n const arr: JsonValue[] = [];\r\n const limit = Math.min(value.length, MAX_SERIALIZE_KEYS);\r\n for (let i = 0; i < limit; i++) arr.push(normalizeInner(value[i], depth - 1, seen));\r\n return arr;\r\n }\r\n\r\n const obj: JsonObject = {};\r\n const source = value as Record<string, unknown>;\r\n const keys = Object.keys(source).slice(0, MAX_SERIALIZE_KEYS);\r\n for (let i = 0; i < keys.length; i++) {\r\n let child: unknown;\r\n try {\r\n child = source[keys[i]];\r\n } catch (_e) {\r\n // Throwing getters are skipped rather than aborting the whole object.\r\n continue;\r\n }\r\n if (child === undefined) continue;\r\n obj[keys[i]] = normalizeInner(child, depth - 1, seen);\r\n }\r\n return obj;\r\n } finally {\r\n seen.pop();\r\n }\r\n}\r\n\r\n/** Converts any thrown value into a readable message string. */\r\nexport function describeValue(value: unknown): string {\r\n if (typeof value === 'string') return value;\r\n if (value instanceof Error) return value.message;\r\n try {\r\n const json = JSON.stringify(normalize(value));\r\n return json === undefined ? String(value) : json;\r\n } catch (_e) {\r\n return Object.prototype.toString.call(value);\r\n }\r\n}\r\n","import { MAX_STACK_FRAMES, UNKNOWN_FUNCTION } from '../constants';\r\nimport { StackFrame } from '../types';\r\n\r\n/**\r\n * Parses `Error.stack` strings from V8 (Chrome, Edge, Node), SpiderMonkey\r\n * (Firefox) and JavaScriptCore (Safari) into structured frames, newest first.\r\n * Source maps are not applied; the backend is expected to symbolicate.\r\n */\r\n\r\n// \" at fn (https://x/app.js:10:5)\" | \" at https://x/app.js:10:5\"\r\nconst V8_FRAME = /^\\s*at (?:(.+?) \\()?(.+?):(\\d+):(\\d+)\\)?\\s*$/;\r\n// \" at fn (native)\" / \" at fn (<anonymous>)\" — no usable location\r\nconst V8_NO_LOCATION = /^\\s*at (?:(.+?) \\()?(native|<anonymous>|unknown location)\\)?\\s*$/;\r\n// \" at eval (eval at outer (https://x/app.js:10:5), <anonymous>:1:1)\"\r\nconst V8_EVAL_ORIGIN = /\\(eval at [^()]*\\((.+?):(\\d+):(\\d+)\\)/;\r\nconst V8_LINE = /^\\s*at /;\r\n\r\n// \"fn@https://x/app.js:10:5\" | \"@https://x/app.js:10:5\"\r\nconst GECKO_FRAME = /^\\s*(.*?)@(.+?):(\\d+):(\\d+)\\s*$/;\r\n// \"fn@https://x/app.js line 7 > eval:1:1\"\r\nconst GECKO_EVAL = /^\\s*(.*?)@(.+?) line (\\d+) > (?:eval|Function)/;\r\n// Safari: \"fn@[native code]\"\r\nconst GECKO_NATIVE = /^\\s*(.*?)@\\[native code\\]\\s*$/;\r\n\r\n/** Parses a raw stack string. Unrecognised lines are skipped. */\r\nexport function parseStack(stack: string | undefined | null): StackFrame[] {\r\n if (typeof stack !== 'string' || stack.length === 0) return [];\r\n\r\n const lines = stack.split('\\n');\r\n const isV8 = lines.some(function test(line) {\r\n return V8_LINE.test(line);\r\n });\r\n\r\n const frames: StackFrame[] = [];\r\n for (let i = 0; i < lines.length && frames.length < MAX_STACK_FRAMES; i++) {\r\n const frame = isV8 ? parseV8Line(lines[i]) : parseGeckoLine(lines[i]);\r\n if (frame !== null) frames.push(frame);\r\n }\r\n return frames;\r\n}\r\n\r\n/** Extracts frames from any thrown value that carries a `stack` string. */\r\nexport function parseStackFromError(error: unknown): StackFrame[] {\r\n if (error !== null && typeof error === 'object' && 'stack' in error) {\r\n const stack = (error as { stack?: unknown }).stack;\r\n return typeof stack === 'string' ? parseStack(stack) : [];\r\n }\r\n return [];\r\n}\r\n\r\nfunction parseV8Line(line: string): StackFrame | null {\r\n if (!V8_LINE.test(line)) return null;\r\n\r\n const evalMatch = V8_EVAL_ORIGIN.exec(line);\r\n if (evalMatch !== null) {\r\n const fnName = /^\\s*at (.+?) \\(/.exec(line);\r\n return frame(fnName !== null ? fnName[1] : '', evalMatch[1], evalMatch[2], evalMatch[3]);\r\n }\r\n\r\n const match = V8_FRAME.exec(line);\r\n if (match !== null) return frame(match[1] || '', match[2], match[3], match[4]);\r\n\r\n const native = V8_NO_LOCATION.exec(line);\r\n if (native !== null) return frame(native[1] || '', null, null, null);\r\n\r\n return null;\r\n}\r\n\r\nfunction parseGeckoLine(line: string): StackFrame | null {\r\n const evalMatch = GECKO_EVAL.exec(line);\r\n if (evalMatch !== null) return frame(evalMatch[1], evalMatch[2], evalMatch[3], null);\r\n\r\n const match = GECKO_FRAME.exec(line);\r\n if (match !== null) return frame(match[1], match[2], match[3], match[4]);\r\n\r\n const native = GECKO_NATIVE.exec(line);\r\n if (native !== null) return frame(native[1], null, null, null);\r\n\r\n return null;\r\n}\r\n\r\nfunction frame(\r\n fn: string,\r\n filename: string | null,\r\n lineno: string | null,\r\n colno: string | null,\r\n): StackFrame {\r\n return {\r\n filename: filename !== null && filename.length > 0 ? filename : null,\r\n lineno: toInt(lineno),\r\n colno: toInt(colno),\r\n function: cleanFunctionName(fn),\r\n };\r\n}\r\n\r\nfunction cleanFunctionName(raw: string): string {\r\n let name = raw.trim();\r\n if (name.indexOf('async ') === 0) name = name.slice('async '.length);\r\n // Firefox marks closures as \"outer/<\" and \"outer/inner<\"; keep the readable part.\r\n name = name.replace(/\\/<+$/, '').replace(/<$/, '');\r\n return name.length > 0 ? name : UNKNOWN_FUNCTION;\r\n}\r\n\r\nfunction toInt(value: string | null): number | null {\r\n if (value === null) return null;\r\n const n = parseInt(value, 10);\r\n return isNaN(n) ? null : n;\r\n}\r\n","import { MAX_MESSAGE_LENGTH, UNKNOWN_FUNCTION } from '../constants';\r\nimport { getWindow, stripQuery } from '../core/env';\r\nimport { Logger } from '../core/logger';\r\nimport { locationSignature, markReported, wasReported, wasSignatureReported } from '../core/reportedErrors';\r\nimport { guard } from '../core/safe';\r\nimport { describeValue, truncate } from '../core/serialize';\r\nimport { parseStackFromError } from '../core/stackParser';\r\nimport { StackFrame } from '../types';\r\nimport { CapturedError, Collector, CollectorSink } from './collector';\r\n\r\nconst UNHANDLED_REJECTION_TYPE = 'UnhandledRejection';\r\nconst RESOURCE_ERROR_TYPE = 'ResourceError';\r\nconst DEFAULT_ERROR_TYPE = 'Error';\r\nconst CROSS_ORIGIN_ERROR_TYPE = 'CrossOriginScriptError';\r\n/** `<link rel>` values that only hint at a future load. */\r\nconst RESOURCE_HINT_RELS = ['preload', 'prefetch', 'modulepreload'];\r\nconst CROSS_ORIGIN_MESSAGE = /^Script error\\.?$/;\r\nconst CROSS_ORIGIN_HINT =\r\n 'Error details are hidden by the browser because the script came from another origin. ' +\r\n 'Load it with crossorigin=\"anonymous\" and serve it with an Access-Control-Allow-Origin header to get the real message and stack.';\r\n\r\n/**\r\n * Converts any thrown value into an error payload plus parsed stack trace.\r\n * Used for global handlers and for `captureError()`.\r\n */\r\nexport function captureFromThrown(thrown: unknown, handled: boolean, fallbackType: string = DEFAULT_ERROR_TYPE): CapturedError {\r\n const isErrorLike =\r\n thrown !== null && typeof thrown === 'object' && typeof (thrown as { message?: unknown }).message === 'string';\r\n\r\n let type = fallbackType;\r\n if (isErrorLike) {\r\n const name = (thrown as { name?: unknown }).name;\r\n if (typeof name === 'string' && name.length > 0) {\r\n type = name;\r\n } else {\r\n const ctor = (thrown as { constructor?: { name?: unknown } }).constructor;\r\n if (ctor !== undefined && typeof ctor.name === 'string' && ctor.name.length > 0) type = ctor.name;\r\n }\r\n }\r\n\r\n // Later sightings of the same object (unhandledrejection, console.error) are then skipped.\r\n markReported(thrown);\r\n\r\n return {\r\n error: {\r\n message: truncate(isErrorLike ? (thrown as { message: string }).message : describeValue(thrown), MAX_MESSAGE_LENGTH),\r\n type: type,\r\n handled: handled,\r\n },\r\n stacktrace: parseStackFromError(thrown),\r\n };\r\n}\r\n\r\n/**\r\n * Captures uncaught exceptions, unhandled promise rejections and failed\r\n * resource loads (scripts, images, stylesheets).\r\n *\r\n * A capture-phase `error` listener is used rather than assigning\r\n * `window.onerror`: it receives the same ErrorEvent, cannot be overwritten by\r\n * the host app reassigning `onerror`, and also sees resource load failures,\r\n * which do not bubble to `onerror`.\r\n */\r\nexport class ErrorCollector implements Collector {\r\n private installed = false;\r\n private readonly handleError: (event: Event) => void;\r\n private readonly handleRejection: (event: PromiseRejectionEvent) => void;\r\n\r\n constructor(\r\n private readonly sink: CollectorSink,\r\n logger: Logger,\r\n ) {\r\n const self = this;\r\n this.handleError = guard(logger, 'error handler', function onError(event: Event) {\r\n if (isErrorEvent(event)) {\r\n if (wasReported(event.error)) return;\r\n // e.g. a Web Worker error already reported by the worker collector, re-dispatched on window.\r\n const filename = event.filename ? stripQuery(event.filename) : null;\r\n if (wasSignatureReported(locationSignature(event.message, filename, event.lineno || null))) return;\r\n }\r\n const captured = self.fromErrorEvent(event);\r\n if (captured !== null) self.sink.onError(captured);\r\n });\r\n this.handleRejection = guard(logger, 'rejection handler', function onRejection(event: PromiseRejectionEvent) {\r\n // e.g. a failed fetch already reported as NetworkError, or invalid JSON already reported.\r\n if (wasReported(event.reason)) return;\r\n self.sink.onError(captureFromThrown(event.reason, false, UNHANDLED_REJECTION_TYPE));\r\n });\r\n }\r\n\r\n install(): void {\r\n const win = getWindow();\r\n if (this.installed || win === null) return;\r\n win.addEventListener('error', this.handleError, true);\r\n win.addEventListener('unhandledrejection', this.handleRejection);\r\n this.installed = true;\r\n }\r\n\r\n uninstall(): void {\r\n const win = getWindow();\r\n if (!this.installed || win === null) return;\r\n win.removeEventListener('error', this.handleError, true);\r\n win.removeEventListener('unhandledrejection', this.handleRejection);\r\n this.installed = false;\r\n }\r\n\r\n private fromErrorEvent(event: Event): CapturedError | null {\r\n if (isErrorEvent(event)) {\r\n let captured: CapturedError;\r\n if (event.error !== null && event.error !== undefined) {\r\n captured = captureFromThrown(event.error, false);\r\n } else if (CROSS_ORIGIN_MESSAGE.test(event.message || '')) {\r\n // The browser hides details of errors thrown by scripts from another\r\n // origin unless they are loaded with CORS. Label it so it isn't mistaken for a bug in our code.\r\n captured = {\r\n error: { message: event.message, type: CROSS_ORIGIN_ERROR_TYPE, handled: false },\r\n stacktrace: [] as StackFrame[],\r\n context: { hint: CROSS_ORIGIN_HINT },\r\n };\r\n } else {\r\n captured = {\r\n error: { message: truncate(event.message || 'Unknown error', MAX_MESSAGE_LENGTH), type: DEFAULT_ERROR_TYPE, handled: false },\r\n stacktrace: [] as StackFrame[],\r\n };\r\n }\r\n if (captured.stacktrace.length === 0 && event.filename) {\r\n captured.stacktrace = [\r\n { filename: event.filename, lineno: event.lineno || null, colno: event.colno || null, function: UNKNOWN_FUNCTION },\r\n ];\r\n }\r\n return captured;\r\n }\r\n\r\n const target = event.target;\r\n if (target !== null && target !== getWindow() && isElement(target)) {\r\n // A failed preload/prefetch hint is a duplicate: the element that actually\r\n // uses the file (e.g. the <img> React preloads) reports its own failure.\r\n if (isResourceHint(target)) return null;\r\n const source = resourceUrl(target);\r\n return {\r\n error: {\r\n message: truncate('Failed to load <' + target.tagName.toLowerCase() + '>' + (source !== null ? ' ' + source : ''), MAX_MESSAGE_LENGTH),\r\n type: RESOURCE_ERROR_TYPE,\r\n handled: false,\r\n },\r\n stacktrace: [],\r\n };\r\n }\r\n return null;\r\n }\r\n}\r\n\r\nfunction isErrorEvent(event: Event): event is ErrorEvent {\r\n return typeof ErrorEvent !== 'undefined' && event instanceof ErrorEvent;\r\n}\r\n\r\nfunction isElement(target: EventTarget): target is Element {\r\n return typeof Element !== 'undefined' && target instanceof Element;\r\n}\r\n\r\nfunction isResourceHint(el: Element): boolean {\r\n if (el.tagName !== 'LINK') return false;\r\n const rel = (el.getAttribute('rel') || '').toLowerCase().split(/\\s+/);\r\n for (let i = 0; i < rel.length; i++) {\r\n if (RESOURCE_HINT_RELS.indexOf(rel[i]) !== -1) return true;\r\n }\r\n return false;\r\n}\r\n\r\nfunction resourceUrl(el: Element): string | null {\r\n const raw = el.getAttribute('src') || el.getAttribute('href');\r\n return raw !== null && raw.length > 0 ? stripQuery(raw) : null;\r\n}\r\n","import {\r\n MASKED_TEXT,\r\n MAX_CLICK_TEXT_LENGTH,\r\n MAX_CSS_PATH_DEPTH,\r\n MAX_MESSAGE_LENGTH,\r\n} from '../constants';\r\nimport { getDocument, getWindow, stripQuery } from '../core/env';\r\nimport { LOG_PREFIX, Logger } from '../core/logger';\r\nimport { wasReported } from '../core/reportedErrors';\r\nimport { guard, safelyRun } from '../core/safe';\r\nimport { describeValue, truncate } from '../core/serialize';\r\nimport { parseStack } from '../core/stackParser';\r\nimport { ApiCall } from '../types';\r\nimport { CapturedError, Collector, CollectorSink } from './collector';\r\nimport { captureFromThrown } from './errorCollector';\r\nimport { NetworkInterceptor, RequestDetails } from './networkInterceptor';\r\n\r\nconst CONSOLE_ERROR_TYPE = 'ConsoleError';\r\n/** The console wrapper's own frame, removed from console-error stacks. */\r\nconst CONSOLE_WRAPPER_FRAMES = 1;\r\n\r\n/**\r\n * Turns a `console.error(...)` call into an error. If one of the arguments is\r\n * an Error, its own type and stack are used. Returns null when that Error was\r\n * already reported (frameworks often log errors they have just rethrown).\r\n */\r\nexport function consoleErrorFromArgs(args: unknown[], callStack: string | undefined): CapturedError | null {\r\n const message = truncate(args.map(describeValue).join(' '), MAX_MESSAGE_LENGTH);\r\n for (let i = 0; i < args.length; i++) {\r\n const arg = args[i];\r\n if (arg instanceof Error) {\r\n if (wasReported(arg)) return null;\r\n const captured = captureFromThrown(arg, true);\r\n captured.context = { console_message: message };\r\n return captured;\r\n }\r\n }\r\n return {\r\n error: { message: message, type: CONSOLE_ERROR_TYPE, handled: true },\r\n stacktrace: parseStack(callStack).slice(CONSOLE_WRAPPER_FRAMES),\r\n };\r\n}\r\n\r\ntype ConsoleLevel = 'warn' | 'error';\r\ntype ConsoleFn = (...args: unknown[]) => void;\r\ntype HistoryFn = History['pushState'];\r\n\r\nconst CONSOLE_LEVELS: ConsoleLevel[] = ['warn', 'error'];\r\nconst INTERACTIVE_SELECTOR = 'button, a, input, select, textarea, label, summary, [role=\"button\"], [role=\"link\"], [onclick]';\r\nconst FORM_FIELD_TAGS = ['INPUT', 'TEXTAREA', 'SELECT'];\r\n\r\n/** Returns true if `el` or an ancestor matches any selector. Invalid selectors are ignored. */\r\nexport function isMasked(el: Element, selectors: readonly string[]): boolean {\r\n for (let i = 0; i < selectors.length; i++) {\r\n try {\r\n if (el.closest(selectors[i]) !== null) return true;\r\n } catch (_e) {\r\n // Invalid selector supplied by the host app; skip it.\r\n }\r\n }\r\n return false;\r\n}\r\n\r\n/** Short CSS path such as `form#checkout > div.actions > button.primary`. */\r\nexport function cssPath(el: Element): string {\r\n const parts: string[] = [];\r\n let current: Element | null = el;\r\n while (current !== null && parts.length < MAX_CSS_PATH_DEPTH) {\r\n let part = current.tagName.toLowerCase();\r\n if (current.id) {\r\n parts.unshift(part + '#' + current.id);\r\n break;\r\n }\r\n const className = typeof current.className === 'string' ? current.className.trim() : '';\r\n if (className.length > 0) part += '.' + className.split(/\\s+/).slice(0, 2).join('.');\r\n parts.unshift(part);\r\n if (current.tagName === 'BODY') break;\r\n current = current.parentElement;\r\n }\r\n return parts.join(' > ');\r\n}\r\n\r\n/** Human-readable label for a clicked element, never exposing form values or masked text. */\r\nexport function describeElementText(el: Element, maskSelectors: readonly string[]): string {\r\n if (isMasked(el, maskSelectors)) return MASKED_TEXT;\r\n if (FORM_FIELD_TAGS.indexOf(el.tagName) !== -1) {\r\n return truncate(el.getAttribute('aria-label') || el.getAttribute('name') || el.getAttribute('type') || '', MAX_CLICK_TEXT_LENGTH);\r\n }\r\n const label = el.getAttribute('aria-label');\r\n if (label !== null && label.length > 0) return truncate(label, MAX_CLICK_TEXT_LENGTH);\r\n const text = (el.textContent || '').replace(/\\s+/g, ' ').trim();\r\n return truncate(text, MAX_CLICK_TEXT_LENGTH);\r\n}\r\n\r\n/**\r\n * Records clicks, navigations, page visibility changes, console warnings and\r\n * errors, and network requests as breadcrumbs.\r\n */\r\nexport class BreadcrumbCollector implements Collector {\r\n private installed = false;\r\n private lastUrl: string | null = null;\r\n private originalPushState: HistoryFn | null = null;\r\n private originalReplaceState: HistoryFn | null = null;\r\n private originalConsole: Partial<Record<ConsoleLevel, ConsoleFn>> = {};\r\n private inConsoleHook = false;\r\n\r\n private readonly handleClick: (event: MouseEvent) => void;\r\n private readonly handlePopState: () => void;\r\n private readonly handleVisibility: () => void;\r\n\r\n constructor(\r\n private readonly sink: CollectorSink,\r\n private readonly network: NetworkInterceptor,\r\n private readonly maskSelectors: readonly string[],\r\n private readonly logger: Logger,\r\n /** Also report `console.error` calls as error events (opt-in). */\r\n private readonly captureConsoleErrors: boolean = false,\r\n ) {\r\n const self = this;\r\n this.handleClick = guard(logger, 'click breadcrumb', function onClick(event: MouseEvent) {\r\n self.recordClick(event);\r\n });\r\n this.handlePopState = guard(logger, 'navigation breadcrumb', function onPop() {\r\n self.recordNavigation('popstate');\r\n });\r\n this.handleVisibility = guard(logger, 'lifecycle breadcrumb', function onVisibility() {\r\n const doc = getDocument();\r\n if (doc !== null) self.sink.onBreadcrumb({ type: 'lifecycle', message: 'Page ' + doc.visibilityState });\r\n });\r\n }\r\n\r\n install(): void {\r\n const win = getWindow();\r\n const doc = getDocument();\r\n if (this.installed || win === null || doc === null) return;\r\n this.installed = true;\r\n this.lastUrl = stripQuery(win.location.href);\r\n\r\n doc.addEventListener('click', this.handleClick, true);\r\n doc.addEventListener('visibilitychange', this.handleVisibility);\r\n win.addEventListener('popstate', this.handlePopState);\r\n safelyRun(this.logger, 'history instrumentation', () => this.wrapHistory(win));\r\n safelyRun(this.logger, 'console instrumentation', () => this.wrapConsole());\r\n\r\n const self = this;\r\n this.network.subscribe(function onApiCall(call: ApiCall, details: RequestDetails) {\r\n const outcome = details.failure !== null ? details.failure : String(call.status);\r\n self.sink.onBreadcrumb({\r\n type: 'api',\r\n message: call.method + ' ' + call.url + ' → ' + outcome,\r\n data: { url: call.url, method: call.method, status: call.status, duration_ms: call.duration_ms, failure: details.failure },\r\n });\r\n });\r\n }\r\n\r\n uninstall(): void {\r\n const win = getWindow();\r\n const doc = getDocument();\r\n if (!this.installed || win === null || doc === null) return;\r\n\r\n doc.removeEventListener('click', this.handleClick, true);\r\n doc.removeEventListener('visibilitychange', this.handleVisibility);\r\n win.removeEventListener('popstate', this.handlePopState);\r\n if (this.originalPushState !== null) win.history.pushState = this.originalPushState;\r\n if (this.originalReplaceState !== null) win.history.replaceState = this.originalReplaceState;\r\n for (let i = 0; i < CONSOLE_LEVELS.length; i++) {\r\n const original = this.originalConsole[CONSOLE_LEVELS[i]];\r\n if (original !== undefined) console[CONSOLE_LEVELS[i]] = original;\r\n }\r\n this.originalPushState = null;\r\n this.originalReplaceState = null;\r\n this.originalConsole = {};\r\n this.installed = false;\r\n }\r\n\r\n private recordClick(event: MouseEvent): void {\r\n const target = event.target;\r\n if (target === null || typeof Element === 'undefined' || !(target instanceof Element)) return;\r\n const el = target.closest(INTERACTIVE_SELECTOR) || target;\r\n const text = describeElementText(el, this.maskSelectors);\r\n const tag = el.tagName.toLowerCase();\r\n this.sink.onBreadcrumb({\r\n type: 'click',\r\n message: 'Clicked ' + (text.length > 0 ? text : tag),\r\n data: { tag: tag, text: text, selector: cssPath(el) },\r\n });\r\n }\r\n\r\n private recordNavigation(trigger: string): void {\r\n const win = getWindow();\r\n if (win === null) return;\r\n const to = stripQuery(win.location.href);\r\n if (to === this.lastUrl) return;\r\n const from = this.lastUrl;\r\n this.lastUrl = to;\r\n this.sink.onBreadcrumb({ type: 'navigation', message: 'Navigated to ' + to, data: { from: from, to: to, trigger: trigger } });\r\n this.sink.onNavigation();\r\n }\r\n\r\n private wrapHistory(win: Window): void {\r\n const history = win.history;\r\n const self = this;\r\n const originalPush = history.pushState;\r\n const originalReplace = history.replaceState;\r\n this.originalPushState = originalPush;\r\n this.originalReplaceState = originalReplace;\r\n\r\n history.pushState = function trackedPushState(this: History, data: unknown, unused: string, url?: string | URL | null) {\r\n const result = originalPush.call(this, data, unused, url);\r\n safelyRun(self.logger, 'pushState breadcrumb', function record() {\r\n self.recordNavigation('pushState');\r\n });\r\n return result;\r\n };\r\n history.replaceState = function trackedReplaceState(this: History, data: unknown, unused: string, url?: string | URL | null) {\r\n const result = originalReplace.call(this, data, unused, url);\r\n safelyRun(self.logger, 'replaceState breadcrumb', function record() {\r\n self.recordNavigation('replaceState');\r\n });\r\n return result;\r\n };\r\n }\r\n\r\n private wrapConsole(): void {\r\n if (typeof console === 'undefined') return;\r\n const self = this;\r\n\r\n CONSOLE_LEVELS.forEach(function wrap(level) {\r\n const original = console[level] as ConsoleFn | undefined;\r\n if (typeof original !== 'function') return;\r\n self.originalConsole[level] = original;\r\n\r\n console[level] = function trackedConsole(...args: unknown[]) {\r\n const isSdkLog = typeof args[0] === 'string' && args[0].indexOf(LOG_PREFIX) === 0;\r\n // Re-entrancy guard: a breadcrumb sink that logs must not loop forever.\r\n if (!self.inConsoleHook && !isSdkLog) {\r\n self.inConsoleHook = true;\r\n safelyRun(self.logger, 'console breadcrumb', function record() {\r\n const message = args.map(describeValue).join(' ');\r\n self.sink.onBreadcrumb({\r\n type: 'log',\r\n message: truncate(message, MAX_MESSAGE_LENGTH),\r\n data: { level: level },\r\n });\r\n });\r\n if (level === 'error' && self.captureConsoleErrors) {\r\n const stack = new Error().stack;\r\n safelyRun(self.logger, 'console error event', function report() {\r\n const captured = consoleErrorFromArgs(args, stack);\r\n if (captured !== null) self.sink.onError(captured);\r\n });\r\n }\r\n self.inConsoleHook = false;\r\n }\r\n original.apply(console, args);\r\n };\r\n });\r\n }\r\n}\r\n","import { MAX_MESSAGE_LENGTH, UNKNOWN_FUNCTION } from '../constants';\nimport { getDocument, stripQuery } from '../core/env';\nimport { Logger } from '../core/logger';\nimport { guard, safelyRun } from '../core/safe';\nimport { truncate } from '../core/serialize';\nimport { StackFrame } from '../types';\nimport { CapturedError, Collector, CollectorSink } from './collector';\n\nconst CSP_ERROR_TYPE = 'CspViolation';\nconst CSP_REPORT_TYPE = 'csp-violation';\n/** blockedURI values that are keywords rather than URLs. */\nconst CSP_KEYWORDS = ['inline', 'eval', 'self', 'data', 'blob', 'wasm-eval', 'trusted-types-policy', 'trusted-types-sink'];\n\n/** The fields shared by `SecurityPolicyViolationEvent` and the Reporting API's CSP report body. */\nexport interface CspViolation {\n blocked: string;\n directive: string;\n disposition: string | null;\n sourceFile: string | null;\n lineNumber: number | null;\n columnNumber: number | null;\n}\n\n/** Reporting API `csp-violation` report body (not in every TypeScript DOM lib). */\ninterface CspReportBody {\n blockedURL?: string | null;\n effectiveDirective?: string;\n disposition?: string;\n sourceFile?: string | null;\n lineNumber?: number | null;\n columnNumber?: number | null;\n}\n\ninterface ReportLike {\n type: string;\n body: unknown;\n}\n\ntype ReportingObserverConstructor = new (\n callback: (reports: ReportLike[]) => void,\n options: { types: string[]; buffered: boolean },\n) => { observe(): void; disconnect(): void };\n\nexport function violationFromEvent(event: SecurityPolicyViolationEvent): CspViolation {\n return {\n blocked: event.blockedURI || 'inline',\n directive: event.effectiveDirective || event.violatedDirective || 'unknown-directive',\n disposition: event.disposition || null,\n sourceFile: event.sourceFile || null,\n lineNumber: event.lineNumber || null,\n columnNumber: event.columnNumber || null,\n };\n}\n\nexport function violationFromReport(body: CspReportBody): CspViolation {\n return {\n blocked: body.blockedURL || 'inline',\n directive: body.effectiveDirective || 'unknown-directive',\n disposition: body.disposition || null,\n sourceFile: body.sourceFile || null,\n lineNumber: body.lineNumber || null,\n columnNumber: body.columnNumber || null,\n };\n}\n\n/** Builds the error for one Content-Security-Policy violation. */\nexport function cspError(violation: CspViolation): CapturedError {\n const blockedLabel = CSP_KEYWORDS.indexOf(violation.blocked) !== -1 ? violation.blocked : stripQuery(violation.blocked);\n const verb = violation.disposition === 'report' ? 'would block' : 'blocked';\n\n const stacktrace: StackFrame[] =\n violation.sourceFile !== null\n ? [{ filename: stripQuery(violation.sourceFile), lineno: violation.lineNumber, colno: violation.columnNumber, function: UNKNOWN_FUNCTION }]\n : [];\n\n return {\n error: {\n message: truncate('CSP ' + verb + ' ' + blockedLabel + ' (' + violation.directive + ')', MAX_MESSAGE_LENGTH),\n type: CSP_ERROR_TYPE,\n handled: false,\n },\n stacktrace: stacktrace,\n context: {\n directive: violation.directive,\n blocked_uri: blockedLabel,\n disposition: violation.disposition,\n // The browser's `sample` field (first characters of blocked inline code) is\n // deliberately not kept: it can contain anything, including PII.\n },\n };\n}\n\n/**\n * Reports Content-Security-Policy violations (enforced and report-only),\n * such as a blocked third-party script, an inline script without a nonce or\n * a disallowed `eval`.\n *\n * Where the Reporting API exists (Chromium), a buffered `ReportingObserver`\n * is used: it also delivers violations that happened while the page's HTML\n * was still loading, before the SDK started. Other browsers fall back to the\n * `securitypolicyviolation` event, which only sees violations after init.\n */\nexport class CspCollector implements Collector {\n private installed = false;\n private observer: { observe(): void; disconnect(): void } | null = null;\n private readonly handleEvent: (event: SecurityPolicyViolationEvent) => void;\n private readonly handleReports: (reports: ReportLike[]) => void;\n\n constructor(\n private readonly sink: CollectorSink,\n private readonly logger: Logger,\n /**\n * Scripts loaded by the SDK itself (the screenshot library). Violations\n * they cause, e.g. drawing `data:` images under a strict `img-src`, are not the app's problem.\n */\n sdkScriptUrls: readonly string[] = [],\n private readonly reportingObserver: ReportingObserverConstructor | null = defaultReportingObserver(),\n ) {\n const self = this;\n const ignored = sdkScriptUrls.map(stripQuery);\n const report = function report(violation: CspViolation) {\n if (violation.sourceFile !== null && ignored.indexOf(stripQuery(violation.sourceFile)) !== -1) return;\n self.sink.onError(cspError(violation));\n };\n this.handleEvent = guard(logger, 'CSP violation handler', function onViolation(event: SecurityPolicyViolationEvent) {\n report(violationFromEvent(event));\n });\n this.handleReports = guard(logger, 'CSP report handler', function onReports(reports: ReportLike[]) {\n for (let i = 0; i < reports.length; i++) {\n if (reports[i].type === CSP_REPORT_TYPE) report(violationFromReport(reports[i].body as CspReportBody));\n }\n });\n }\n\n install(): void {\n const doc = getDocument();\n if (this.installed || doc === null) return;\n this.installed = true;\n\n const Observer = this.reportingObserver;\n if (Observer !== null) {\n const self = this;\n safelyRun(this.logger, 'CSP reporting observer', function observe() {\n const observer = new Observer(self.handleReports, { types: [CSP_REPORT_TYPE], buffered: true });\n observer.observe();\n self.observer = observer;\n });\n if (this.observer !== null) return;\n }\n doc.addEventListener('securitypolicyviolation', this.handleEvent);\n }\n\n uninstall(): void {\n const doc = getDocument();\n if (!this.installed || doc === null) return;\n if (this.observer !== null) {\n const observer = this.observer;\n safelyRun(this.logger, 'disconnect CSP observer', function disconnect() {\n observer.disconnect();\n });\n this.observer = null;\n } else {\n doc.removeEventListener('securitypolicyviolation', this.handleEvent);\n }\n this.installed = false;\n }\n}\n\nfunction defaultReportingObserver(): ReportingObserverConstructor | null {\n const g = (typeof window !== 'undefined' ? window : {}) as { ReportingObserver?: ReportingObserverConstructor };\n return typeof g.ReportingObserver === 'function' ? g.ReportingObserver : null;\n}\n","import { HTTP_ERROR_STATUS_MIN, MAX_MESSAGE_LENGTH } from '../constants';\nimport { markReported } from '../core/reportedErrors';\nimport { truncate } from '../core/serialize';\nimport { ApiCall } from '../types';\nimport { CapturedError, Collector, CollectorSink } from './collector';\nimport { NetworkFailure, NetworkInterceptor, RequestDetails } from './networkInterceptor';\n\nconst HTTP_ERROR_TYPE = 'HttpError';\nconst NETWORK_ERROR_TYPE = 'NetworkError';\n\nconst FAILURE_DESCRIPTIONS: Record<NetworkFailure, string> = {\n offline: 'device offline',\n timeout: 'timed out',\n aborted: 'aborted',\n network: 'no response (connection refused, DNS, SSL or CORS)',\n};\n\n/** Builds the error for a response with an error status, e.g. `GET /api/cart → 500`. */\nexport function httpErrorFromCall(call: ApiCall, details?: RequestDetails): CapturedError {\n return {\n error: {\n message: truncate(call.method + ' ' + call.url + ' → ' + call.status, MAX_MESSAGE_LENGTH),\n type: HTTP_ERROR_TYPE,\n // The request did not throw; the app received the response and decides what to do with it.\n handled: true,\n },\n stacktrace: details !== undefined ? details.callSite() : [],\n context: { url: call.url, method: call.method, status: call.status, duration_ms: call.duration_ms },\n };\n}\n\n/** Builds the error for a request that never got a response. */\nexport function networkErrorFromCall(call: ApiCall, details: RequestDetails): CapturedError {\n const failure = details.failure !== null ? details.failure : 'network';\n return {\n error: {\n message: truncate(call.method + ' ' + call.url + ' failed: ' + FAILURE_DESCRIPTIONS[failure], MAX_MESSAGE_LENGTH),\n type: NETWORK_ERROR_TYPE,\n // The failure was handed back to the app (rejected promise / XHR error event).\n handled: true,\n },\n stacktrace: details.callSite(),\n context: { url: call.url, method: call.method, failure: failure, duration_ms: call.duration_ms },\n };\n}\n\nexport interface HttpErrorOptions {\n /** Report 4xx/5xx responses. */\n httpErrors: boolean;\n /** Report requests that got no response (except user aborts). */\n networkErrors: boolean;\n}\n\n/**\n * Turns failed fetch/XHR requests into `error` events:\n * - `HttpError` for responses with a 4xx or 5xx status;\n * - `NetworkError` for requests that never got a response (offline, timeout,\n * connection refused, DNS/SSL failure, CORS). Requests the app cancelled\n * itself are not errors and are skipped.\n *\n * Each event's stack trace points at the line of app code that made the request.\n * The rejection value of a failed fetch is marked as reported, so if the app\n * leaves that promise uncaught it is not reported a second time.\n */\nexport class HttpErrorCollector implements Collector {\n private installed = false;\n\n constructor(\n private readonly sink: CollectorSink,\n private readonly network: NetworkInterceptor,\n private readonly options: HttpErrorOptions,\n ) {}\n\n install(): void {\n if (this.installed) return;\n this.installed = true;\n const self = this;\n this.network.subscribe(function onApiCall(call, details) {\n if (self.installed) self.handle(call, details);\n });\n }\n\n uninstall(): void {\n // The interceptor drops all listeners on its own uninstall; this flag\n // covers the window between the two.\n this.installed = false;\n }\n\n private handle(call: ApiCall, details: RequestDetails): void {\n if (details.failure === null) {\n if (this.options.httpErrors && call.status >= HTTP_ERROR_STATUS_MIN) this.sink.onError(httpErrorFromCall(call, details));\n return;\n }\n if (!this.options.networkErrors || details.failure === 'aborted') return;\n markReported(details.error);\n this.sink.onError(networkErrorFromCall(call, details));\n }\n}\n","import { MAX_MESSAGE_LENGTH } from '../constants';\nimport { absoluteUrl, getWindow, stripQuery } from '../core/env';\nimport { Logger } from '../core/logger';\nimport { markReported } from '../core/reportedErrors';\nimport { safelyRun } from '../core/safe';\nimport { truncate } from '../core/serialize';\nimport { parseStack } from '../core/stackParser';\nimport { CapturedError, Collector, CollectorSink } from './collector';\n\nconst INVALID_JSON_TYPE = 'InvalidJsonResponse';\n/** The `json()` wrapper's own frame, removed from call-site stacks. */\nconst WRAPPER_FRAMES = 1;\n\n/** Builds the error for a response body that could not be parsed as JSON. */\nexport function invalidJsonError(url: string, status: number, cause: unknown, callStack: string | undefined): CapturedError {\n const reason = cause instanceof Error ? cause.message : String(cause);\n return {\n error: {\n message: truncate('Invalid JSON from ' + url + ' (status ' + status + '): ' + reason, MAX_MESSAGE_LENGTH),\n type: INVALID_JSON_TYPE,\n // The parse error was handed back to the app's code.\n handled: true,\n },\n stacktrace: parseStack(callStack).slice(WRAPPER_FRAMES),\n context: { url: url, status: status },\n };\n}\n\n/**\n * Reports responses whose body is not valid JSON when the app calls\n * `response.json()`, even if the app catches the resulting SyntaxError.\n * A malformed body from an API is a bug on one side or the other, so it is\n * worth knowing about either way.\n *\n * Only parse failures (SyntaxError) are reported; aborted or already-read\n * bodies are left alone. The error object is marked as reported so an\n * uncaught rejection of it is not reported a second time.\n */\nexport class JsonResponseCollector implements Collector {\n private original: Response['json'] | null = null;\n private patched: Response['json'] | null = null;\n\n constructor(\n private readonly sink: CollectorSink,\n private readonly logger: Logger,\n private readonly isSdkUrl: (url: string) => boolean,\n ) {}\n\n install(): void {\n // Browser only, like every other automatic collector: never patch globals in a Node server.\n if (this.original !== null || getWindow() === null) return;\n if (typeof Response === 'undefined' || typeof Response.prototype.json !== 'function') return;\n const original = Response.prototype.json;\n const self = this;\n\n const patched = function trackedJson(this: Response): Promise<unknown> {\n const response = this;\n const callStack = new Error().stack;\n return original.call(response).then(null, function onParseError(error: unknown) {\n if (error instanceof Error && error.name === 'SyntaxError') {\n safelyRun(self.logger, 'invalid JSON report', function report() {\n const url = stripQuery(absoluteUrl(response.url || ''));\n if (self.isSdkUrl(url)) return;\n markReported(error);\n self.sink.onError(invalidJsonError(url, response.status, error, callStack));\n });\n }\n throw error;\n });\n };\n\n this.original = original;\n this.patched = patched;\n Response.prototype.json = patched;\n }\n\n uninstall(): void {\n if (this.original === null) return;\n // Only restore if nobody wrapped on top of us.\n if (Response.prototype.json === this.patched) Response.prototype.json = this.original;\n this.original = null;\n this.patched = null;\n }\n}\n","import {\r\n BYTES_PER_MB,\r\n LEAK_CONSECUTIVE_READINGS,\r\n LEAK_GROWTH_THRESHOLD,\r\n MEMORY_POLL_INTERVAL_MS,\r\n} from '../constants';\r\nimport { getPerformance } from '../core/env';\r\nimport { Logger } from '../core/logger';\r\nimport { guard } from '../core/safe';\r\nimport { MemoryPayload } from '../types';\r\nimport { Collector, CollectorSink } from './collector';\r\n\r\n/** One heap sample, in bytes. */\r\nexport interface MemoryReading {\r\n usedBytes: number;\r\n totalBytes: number;\r\n}\r\n\r\n/** Non-standard Chromium `performance.memory`. */\r\ninterface ChromeMemoryInfo {\r\n usedJSHeapSize: number;\r\n totalJSHeapSize: number;\r\n}\r\n\r\n/** Reads `performance.memory`, which only Chromium-based browsers provide. */\r\nexport function readChromeMemory(): MemoryReading | null {\r\n const perf = getPerformance() as (Performance & { memory?: ChromeMemoryInfo }) | null;\r\n if (perf === null || perf.memory === undefined) return null;\r\n return { usedBytes: perf.memory.usedJSHeapSize, totalBytes: perf.memory.totalJSHeapSize };\r\n}\r\n\r\n/**\r\n * True when the last N readings grow strictly and the newest is more than\r\n * the growth threshold above the oldest of the N.\r\n */\r\nexport function isLeakPattern(\r\n usedBytes: readonly number[],\r\n consecutive: number = LEAK_CONSECUTIVE_READINGS,\r\n threshold: number = LEAK_GROWTH_THRESHOLD,\r\n): boolean {\r\n if (usedBytes.length < consecutive) return false;\r\n const recent = usedBytes.slice(-consecutive);\r\n for (let i = 1; i < recent.length; i++) {\r\n if (recent[i] <= recent[i - 1]) return false;\r\n }\r\n return recent[0] > 0 && (recent[recent.length - 1] - recent[0]) / recent[0] > threshold;\r\n}\r\n\r\nfunction toMb(bytes: number): number {\r\n return Math.round((bytes / BYTES_PER_MB) * 10) / 10;\r\n}\r\n\r\n/**\r\n * Polls JS heap usage every 30 s and flags a suspected leak when the heap\r\n * grows by more than 20% across 3 consecutive readings with no navigation in\r\n * between. Readings reset on every navigation.\r\n */\r\nexport class MemoryCollector implements Collector {\r\n private timer: ReturnType<typeof setInterval> | null = null;\r\n private readings: number[] = [];\r\n private latest: MemoryReading | null = null;\r\n private leakSuspected = false;\r\n private readonly poll: () => void;\r\n\r\n constructor(\r\n private readonly sink: CollectorSink,\r\n logger: Logger,\r\n private readonly read: () => MemoryReading | null = readChromeMemory,\r\n private readonly intervalMs: number = MEMORY_POLL_INTERVAL_MS,\r\n ) {\r\n const self = this;\r\n this.poll = guard(logger, 'memory poll', function poll() {\r\n self.sample();\r\n });\r\n }\r\n\r\n install(): void {\r\n if (this.timer !== null || this.read() === null) return;\r\n this.sample();\r\n this.timer = setInterval(this.poll, this.intervalMs);\r\n }\r\n\r\n uninstall(): void {\r\n if (this.timer !== null) clearInterval(this.timer);\r\n this.timer = null;\r\n }\r\n\r\n /** Called on navigation: a new page means a new baseline. */\r\n resetBaseline(): void {\r\n this.readings = [];\r\n this.leakSuspected = false;\r\n }\r\n\r\n /** Takes one reading; exposed for tests. */\r\n sample(): void {\r\n const reading = this.read();\r\n if (reading === null) return;\r\n this.latest = reading;\r\n this.readings.push(reading.usedBytes);\r\n if (this.readings.length > LEAK_CONSECUTIVE_READINGS) this.readings.shift();\r\n\r\n if (!this.leakSuspected && isLeakPattern(this.readings)) {\r\n this.leakSuspected = true;\r\n this.sink.onPerformanceIssue(\r\n 'MemoryLeakSuspected',\r\n 'JS heap grew from ' + toMb(this.readings[0]) + 'MB to ' + toMb(reading.usedBytes) +\r\n 'MB across ' + LEAK_CONSECUTIVE_READINGS + ' readings without navigation',\r\n );\r\n }\r\n }\r\n\r\n snapshot(): MemoryPayload {\r\n if (this.latest === null) {\r\n return { used_mb: null, total_mb: null, leak_suspected: null, oom_kill: null };\r\n }\r\n return {\r\n used_mb: toMb(this.latest.usedBytes),\r\n total_mb: toMb(this.latest.totalBytes),\r\n leak_suspected: this.leakSuspected,\r\n // Browsers give pages no signal for OOM kills.\r\n oom_kill: null,\r\n };\r\n }\r\n}\r\n","import { absoluteUrl, getWindow, isOnline, nowMs, stripQuery } from '../core/env';\nimport { Logger } from '../core/logger';\nimport { safelyRun } from '../core/safe';\nimport { parseStack } from '../core/stackParser';\nimport { ApiCall, StackFrame } from '../types';\nimport { Collector } from './collector';\n\n/**\n * Why a request ended without a response.\n * - `offline`: the browser reported no connectivity.\n * - `timeout`: the request timed out (`AbortSignal.timeout()`, `xhr.timeout`).\n * - `aborted`: the app cancelled it (`AbortController.abort()`, `xhr.abort()`).\n * - `network`: anything else the browser hides behind one generic error:\n * connection refused, DNS failure, TLS/SSL failure, CORS rejection.\n */\nexport type NetworkFailure = 'offline' | 'timeout' | 'aborted' | 'network';\n\n/** Extra information about a request, beyond the schema's `ApiCall` fields. */\nexport interface RequestDetails {\n /** Set when no HTTP response was received; `null` when one was. */\n failure: NetworkFailure | null;\n /** The value fetch rejected with, when it rejected. */\n error: unknown;\n /** Where in the app the request was made (SDK frames removed). Parsed lazily. */\n callSite(): StackFrame[];\n}\n\nexport type NetworkListener = (call: ApiCall, details: RequestDetails) => void;\n\ninterface TrackedXhr extends XMLHttpRequest {\n __et_method?: string;\n __et_url?: string;\n __et_failure?: NetworkFailure | null;\n}\n\n/** Frames added by the SDK (`rawStack` + the fetch/XHR wrapper), removed from call-site stacks. */\nconst WRAPPER_FRAMES = 2;\n\n/** Classifies a fetch rejection. */\nexport function classifyFetchFailure(error: unknown): NetworkFailure {\n const name = error !== null && typeof error === 'object' ? (error as { name?: unknown }).name : undefined;\n if (name === 'AbortError') return 'aborted';\n if (name === 'TimeoutError') return 'timeout';\n return isOnline() ? 'network' : 'offline';\n}\n\n/** Captures the current stack as a raw string, for later parsing. */\nfunction rawStack(): string | undefined {\n try {\n return new Error().stack;\n } catch (_e) {\n return undefined;\n }\n}\n\nfunction lazyCallSite(stack: string | undefined): () => StackFrame[] {\n let parsed: StackFrame[] | null = null;\n return function callSite() {\n if (parsed === null) parsed = parseStack(stack).slice(WRAPPER_FRAMES);\n return parsed;\n };\n}\n\n/**\n * Wraps `fetch` and `XMLHttpRequest` once and fans each completed request out\n * to listeners (breadcrumbs, performance, HTTP/network errors). Requests to\n * the SDK's own endpoint are ignored. Query strings are stripped from\n * recorded URLs.\n *\n * The wrappers never alter request or response behaviour; listener failures\n * are isolated from the host app's request.\n */\nexport class NetworkInterceptor implements Collector {\n private listeners: NetworkListener[] = [];\n private installed = false;\n private originalFetch: typeof fetch | null = null;\n private patchedFetch: typeof fetch | null = null;\n private originalOpen: XMLHttpRequest['open'] | null = null;\n private originalSend: XMLHttpRequest['send'] | null = null;\n private patchedOpen: XMLHttpRequest['open'] | null = null;\n private patchedSend: XMLHttpRequest['send'] | null = null;\n private readonly ignoredUrl: string;\n\n constructor(\n sdkEndpoint: string,\n private readonly logger: Logger,\n ) {\n this.ignoredUrl = stripQuery(absoluteUrl(sdkEndpoint));\n }\n\n subscribe(listener: NetworkListener): void {\n this.listeners.push(listener);\n }\n\n /** True for the SDK's own ingestion endpoint, which must never be tracked. */\n isSdkUrl(rawUrl: string): boolean {\n return stripQuery(absoluteUrl(rawUrl)) === this.ignoredUrl;\n }\n\n install(): void {\n if (this.installed) return;\n const win = getWindow();\n if (win === null) return;\n this.installed = true;\n safelyRun(this.logger, 'fetch instrumentation', () => this.wrapFetch(win));\n safelyRun(this.logger, 'XHR instrumentation', () => this.wrapXhr());\n }\n\n uninstall(): void {\n if (!this.installed) return;\n const win = getWindow();\n if (win !== null) {\n // Only restore if nobody wrapped on top of us; otherwise we'd drop their wrapper.\n if (this.originalFetch !== null && win.fetch === this.patchedFetch) win.fetch = this.originalFetch;\n if (typeof XMLHttpRequest !== 'undefined') {\n const proto = XMLHttpRequest.prototype;\n if (this.originalOpen !== null && proto.open === this.patchedOpen) proto.open = this.originalOpen;\n if (this.originalSend !== null && proto.send === this.patchedSend) proto.send = this.originalSend;\n }\n }\n this.originalFetch = null;\n this.patchedFetch = null;\n this.originalOpen = null;\n this.originalSend = null;\n this.patchedOpen = null;\n this.patchedSend = null;\n this.listeners = [];\n this.installed = false;\n }\n\n private emit(method: string, rawUrl: string, status: number, startedAt: number, details: RequestDetails): void {\n if (this.isSdkUrl(rawUrl)) return;\n const call: ApiCall = {\n url: stripQuery(absoluteUrl(rawUrl)),\n method: method.toUpperCase(),\n status: status,\n duration_ms: Math.max(0, Math.round(nowMs() - startedAt)),\n };\n for (let i = 0; i < this.listeners.length; i++) {\n const listener = this.listeners[i];\n safelyRun(this.logger, 'network listener', function notify() {\n listener(call, details);\n });\n }\n }\n\n private wrapFetch(win: Window): void {\n if (typeof win.fetch !== 'function') return;\n const original = win.fetch;\n const self = this;\n this.originalFetch = original;\n\n const patched = function trackedFetch(this: unknown, input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n const startedAt = nowMs();\n const callSite = lazyCallSite(rawStack());\n let method = 'GET';\n let url = '';\n safelyRun(self.logger, 'fetch argument parsing', function parse() {\n if (typeof input === 'string') {\n url = input;\n } else if (typeof URL !== 'undefined' && input instanceof URL) {\n url = input.href;\n } else {\n url = (input as Request).url;\n method = (input as Request).method || method;\n }\n if (init !== undefined && init !== null && typeof init.method === 'string') method = init.method;\n });\n\n return original.call(this === undefined ? win : this, input, init).then(\n function onResponse(response: Response) {\n self.emit(method, url, response.status, startedAt, { failure: null, error: null, callSite: callSite });\n return response;\n },\n function onError(error: unknown) {\n self.emit(method, url, 0, startedAt, { failure: classifyFetchFailure(error), error: error, callSite: callSite });\n throw error;\n },\n );\n } as typeof fetch;\n\n this.patchedFetch = patched;\n win.fetch = patched;\n }\n\n private wrapXhr(): void {\n if (typeof XMLHttpRequest === 'undefined') return;\n const proto = XMLHttpRequest.prototype;\n const originalOpen = proto.open;\n const originalSend = proto.send;\n const self = this;\n this.originalOpen = originalOpen;\n this.originalSend = originalSend;\n\n proto.open = function trackedOpen(this: TrackedXhr, method: string, url: string | URL) {\n safelyRun(self.logger, 'XHR open tracking', () => {\n this.__et_method = method;\n this.__et_url = typeof url === 'string' ? url : url.href;\n this.__et_failure = null;\n });\n // eslint-disable-next-line prefer-rest-params\n return originalOpen.apply(this, arguments as unknown as Parameters<XMLHttpRequest['open']>);\n } as XMLHttpRequest['open'];\n\n proto.send = function trackedSend(this: TrackedXhr, body?: Document | XMLHttpRequestBodyInit | null) {\n const xhr = this;\n safelyRun(self.logger, 'XHR send tracking', function track() {\n const startedAt = nowMs();\n const callSite = lazyCallSite(rawStack());\n const markFailure = function mark(kind: NetworkFailure) {\n return function onFailure() {\n xhr.__et_failure = kind;\n };\n };\n xhr.addEventListener('abort', markFailure('aborted'));\n xhr.addEventListener('timeout', markFailure('timeout'));\n xhr.addEventListener('error', function onError() {\n // Checked at failure time: connectivity may have changed since send().\n xhr.__et_failure = isOnline() ? 'network' : 'offline';\n });\n xhr.addEventListener('loadend', function onLoadEnd() {\n let failure = xhr.__et_failure || null;\n // Status 0 with no failure event still means no response (e.g. CORS).\n if (failure === null && xhr.status === 0) failure = isOnline() ? 'network' : 'offline';\n self.emit(xhr.__et_method || 'GET', xhr.__et_url || '', xhr.status, startedAt, {\n failure: failure,\n error: null,\n callSite: callSite,\n });\n });\n });\n return originalSend.call(this, body);\n };\n this.patchedOpen = proto.open;\n this.patchedSend = proto.send;\n }\n}\n","/**\r\n * Fixed-capacity FIFO buffer. Once full, each push overwrites the oldest item.\r\n */\r\nexport class CircularBuffer<T> {\r\n private readonly items: Array<T | undefined>;\r\n private start = 0;\r\n private count = 0;\r\n\r\n constructor(private readonly capacity: number) {\r\n this.items = new Array<T | undefined>(Math.max(0, capacity));\r\n }\r\n\r\n push(item: T): void {\r\n if (this.capacity === 0) return;\r\n const index = (this.start + this.count) % this.capacity;\r\n this.items[index] = item;\r\n if (this.count < this.capacity) {\r\n this.count++;\r\n } else {\r\n this.start = (this.start + 1) % this.capacity;\r\n }\r\n }\r\n\r\n /** Items from oldest to newest. */\r\n toArray(): T[] {\r\n const out: T[] = [];\r\n for (let i = 0; i < this.count; i++) {\r\n const item = this.items[(this.start + i) % this.capacity];\r\n if (item !== undefined) out.push(item);\r\n }\r\n return out;\r\n }\r\n\r\n get size(): number {\r\n return this.count;\r\n }\r\n\r\n clear(): void {\r\n for (let i = 0; i < this.items.length; i++) this.items[i] = undefined;\r\n this.start = 0;\r\n this.count = 0;\r\n }\r\n}\r\n","import { SDK_NAME, SDK_VERSION } from '../constants';\r\nimport {\r\n Breadcrumb,\r\n DevicePayload,\r\n ErrorPayload,\r\n EventLevel,\r\n EventType,\r\n JsonObject,\r\n MemoryPayload,\r\n PerformancePayload,\r\n StackFrame,\r\n TrackedUser,\r\n TrackerEvent,\r\n UserPayload,\r\n} from '../types';\r\n\r\n/** What happened: the event-specific part of a payload. */\r\nexport interface EventInput {\r\n eventType: EventType;\r\n level: EventLevel;\r\n error: ErrorPayload | null;\r\n stacktrace: StackFrame[];\r\n context: JsonObject | null;\r\n}\r\n\r\n/** Ambient state captured at the moment of the event. */\r\nexport interface EventScope {\r\n apiKey: string;\r\n environment: string;\r\n appVersion: string | null;\r\n user: TrackedUser | null;\r\n breadcrumbs: Breadcrumb[];\r\n performance: PerformancePayload;\r\n memory: MemoryPayload;\r\n device: DevicePayload;\r\n screenshot: string | null;\r\n}\r\n\r\n/** Performance block with every field present and nothing measured. */\r\nexport function emptyPerformance(): PerformancePayload {\r\n return {\r\n page_load_ms: null,\r\n ttfb_ms: null,\r\n fcp_ms: null,\r\n lcp_ms: null,\r\n cls: null,\r\n startup_ms: null,\r\n frame_rate_fps: null,\r\n slow_screen: false,\r\n api_calls: [],\r\n slow_api_calls: [],\r\n };\r\n}\r\n\r\n/** Memory block with every field present and nothing measured. */\r\nexport function emptyMemory(): MemoryPayload {\r\n return { used_mb: null, total_mb: null, leak_suspected: null, oom_kill: null };\r\n}\r\n\r\nfunction buildUser(user: TrackedUser | null): UserPayload {\r\n if (user === null) return { id: null, email: null, name: null };\r\n return {\r\n id: typeof user.id === 'string' ? user.id : String(user.id),\r\n email: typeof user.email === 'string' ? user.email : null,\r\n name: typeof user.name === 'string' ? user.name : null,\r\n };\r\n}\r\n\r\n/**\r\n * Assembles a schema-complete event. All arrays and nested objects are copied\r\n * so later mutation of SDK state cannot alter an event already in the queue.\r\n */\r\nexport function buildEvent(input: EventInput, scope: EventScope, timestamp: string): TrackerEvent {\r\n return {\r\n sdk: { name: SDK_NAME, version: SDK_VERSION },\r\n api_key: scope.apiKey,\r\n event_type: input.eventType,\r\n level: input.level,\r\n timestamp: timestamp,\r\n environment: scope.environment,\r\n app_version: scope.appVersion,\r\n user: buildUser(scope.user),\r\n error: input.error !== null ? { message: input.error.message, type: input.error.type, handled: input.error.handled } : null,\r\n stacktrace: input.stacktrace.slice(),\r\n breadcrumbs: scope.breadcrumbs.slice(),\r\n screenshot: scope.screenshot,\r\n performance: {\r\n page_load_ms: scope.performance.page_load_ms,\r\n ttfb_ms: scope.performance.ttfb_ms,\r\n fcp_ms: scope.performance.fcp_ms,\r\n lcp_ms: scope.performance.lcp_ms,\r\n cls: scope.performance.cls,\r\n startup_ms: scope.performance.startup_ms,\r\n frame_rate_fps: scope.performance.frame_rate_fps,\r\n slow_screen: scope.performance.slow_screen,\r\n api_calls: scope.performance.api_calls.slice(),\r\n slow_api_calls: scope.performance.slow_api_calls.slice(),\r\n },\r\n memory: {\r\n used_mb: scope.memory.used_mb,\r\n total_mb: scope.memory.total_mb,\r\n leak_suspected: scope.memory.leak_suspected,\r\n oom_kill: scope.memory.oom_kill,\r\n },\r\n device: {\r\n platform: scope.device.platform,\r\n os: scope.device.os,\r\n os_version: scope.device.os_version,\r\n manufacturer: scope.device.manufacturer,\r\n model: scope.device.model,\r\n browser: scope.device.browser,\r\n browser_version: scope.device.browser_version,\r\n screen_width: scope.device.screen_width,\r\n screen_height: scope.device.screen_height,\r\n url: scope.device.url,\r\n referrer: scope.device.referrer,\r\n locale: scope.device.locale,\r\n },\r\n context: input.context,\r\n };\r\n}\r\n\r\n/** Returns a shallow copy of `event` with one top-level field replaced. */\r\nexport function withField<K extends keyof TrackerEvent>(event: TrackerEvent, key: K, value: TrackerEvent[K]): TrackerEvent {\r\n const copy = {} as TrackerEvent;\r\n (Object.keys(event) as Array<keyof TrackerEvent>).forEach(function assign(k) {\r\n (copy as unknown as Record<string, unknown>)[k] = event[k];\r\n });\r\n copy[key] = value;\r\n return copy;\r\n}\r\n","import {\r\n CLS_SESSION_GAP_MS,\r\n CLS_SESSION_MAX_MS,\r\n MAX_API_CALLS_TRACKED,\r\n PAGE_LOAD_SETTLE_MS,\r\n SLOW_API_CALL_MS,\r\n SLOW_PAGE_LOAD_MS,\r\n} from '../constants';\r\nimport { CircularBuffer } from '../core/circularBuffer';\r\nimport { emptyPerformance } from '../core/payloadBuilder';\r\nimport { getDocument, getPerformance, getWindow, toMs } from '../core/env';\r\nimport { Logger } from '../core/logger';\r\nimport { guard, safelyRun } from '../core/safe';\r\nimport { ApiCall, PerformancePayload } from '../types';\r\nimport { Collector, CollectorSink } from './collector';\r\nimport { NetworkInterceptor } from './networkInterceptor';\r\n\r\n/** Fields of a `layout-shift` entry (not yet in TypeScript's DOM lib). */\r\ninterface LayoutShiftEntry extends PerformanceEntry {\r\n value: number;\r\n hadRecentInput: boolean;\r\n}\r\n\r\n/** Fields of a `largest-contentful-paint` entry. */\r\ninterface LcpEntry extends PerformanceEntry {\r\n renderTime: number;\r\n loadTime: number;\r\n}\r\n\r\n/** Raw page timings, already relative to navigation start. */\r\nexport interface PageTimings {\r\n pageLoadMs: number | null;\r\n ttfbMs: number | null;\r\n}\r\n\r\n/** Reads load time and TTFB from Navigation Timing Level 2, falling back to Level 1. */\r\nexport function readPageTimings(perf: Performance): PageTimings {\r\n const entries = typeof perf.getEntriesByType === 'function' ? perf.getEntriesByType('navigation') : [];\r\n if (entries.length > 0) {\r\n const nav = entries[0] as PerformanceNavigationTiming;\r\n return {\r\n pageLoadMs: nav.loadEventEnd > 0 ? toMs(nav.loadEventEnd - nav.startTime) : null,\r\n ttfbMs: nav.responseStart > 0 ? toMs(nav.responseStart - nav.startTime) : null,\r\n };\r\n }\r\n\r\n // Fallback: performance.timing (Navigation Timing Level 1) is deprecated but\r\n // is the only source in Safari < 15 and older Chromium-based webviews.\r\n // TODO: test on Safari 12-14\r\n const timing = perf.timing;\r\n if (timing !== undefined && timing.navigationStart > 0) {\r\n return {\r\n pageLoadMs: timing.loadEventEnd > 0 ? toMs(timing.loadEventEnd - timing.navigationStart) : null,\r\n ttfbMs: timing.responseStart > 0 ? toMs(timing.responseStart - timing.navigationStart) : null,\r\n };\r\n }\r\n return { pageLoadMs: null, ttfbMs: null };\r\n}\r\n\r\n/** Tracks CLS using the web-vitals \"session window\" definition. */\r\nexport class ClsTracker {\r\n private sessionValue = 0;\r\n private sessionStart = 0;\r\n private sessionLast = 0;\r\n private max = 0;\r\n private seen = false;\r\n\r\n add(value: number, startTime: number, hadRecentInput: boolean): void {\r\n if (hadRecentInput) return;\r\n this.seen = true;\r\n const continuesSession =\r\n this.sessionValue > 0 &&\r\n startTime - this.sessionLast < CLS_SESSION_GAP_MS &&\r\n startTime - this.sessionStart < CLS_SESSION_MAX_MS;\r\n if (continuesSession) {\r\n this.sessionValue += value;\r\n } else {\r\n this.sessionValue = value;\r\n this.sessionStart = startTime;\r\n }\r\n this.sessionLast = startTime;\r\n if (this.sessionValue > this.max) this.max = this.sessionValue;\r\n }\r\n\r\n value(): number | null {\r\n return this.seen ? Math.round(this.max * 10000) / 10000 : null;\r\n }\r\n}\r\n\r\n/**\r\n * Collects page-load metrics (load time, TTFB, FCP, LCP, CLS) and the duration\r\n * of every fetch/XHR call. Reports a `performance` event when the page load\r\n * exceeds 3 s or an API call exceeds 2 s.\r\n */\r\nexport class PerformanceCollector implements Collector {\r\n private installed = false;\r\n private metrics: PerformancePayload = emptyPerformance();\r\n private readonly apiCalls = new CircularBuffer<ApiCall>(MAX_API_CALLS_TRACKED);\r\n private readonly slowApiCalls = new CircularBuffer<ApiCall>(MAX_API_CALLS_TRACKED);\r\n private readonly cls = new ClsTracker();\r\n private observers: PerformanceObserver[] = [];\r\n private lcpFinal = false;\r\n private readonly handleLoad: () => void;\r\n private readonly finalizeLcp: () => void;\r\n\r\n constructor(\r\n private readonly sink: CollectorSink,\r\n private readonly network: NetworkInterceptor,\r\n private readonly logger: Logger,\r\n ) {\r\n const self = this;\r\n this.handleLoad = guard(logger, 'page load metrics', function onLoad() {\r\n setTimeout(\r\n guard(logger, 'page load metrics', function measure() {\r\n self.measurePageLoad();\r\n }),\r\n PAGE_LOAD_SETTLE_MS,\r\n );\r\n });\r\n this.finalizeLcp = function onFirstInput() {\r\n // LCP stops being reported once the user interacts with the page.\r\n self.lcpFinal = true;\r\n };\r\n }\r\n\r\n install(): void {\r\n const win = getWindow();\r\n const doc = getDocument();\r\n if (this.installed || win === null || doc === null) return;\r\n this.installed = true;\r\n\r\n const self = this;\r\n this.network.subscribe(function onApiCall(call) {\r\n self.recordApiCall(call);\r\n });\r\n\r\n this.observe('paint', function onPaint(entry) {\r\n if (entry.name === 'first-contentful-paint') self.metrics.fcp_ms = toMs(entry.startTime);\r\n });\r\n this.observe('largest-contentful-paint', function onLcp(entry) {\r\n if (self.lcpFinal) return;\r\n const lcp = entry as LcpEntry;\r\n self.metrics.lcp_ms = toMs(lcp.renderTime || lcp.loadTime || lcp.startTime);\r\n });\r\n this.observe('layout-shift', function onShift(entry) {\r\n const shift = entry as LayoutShiftEntry;\r\n self.cls.add(shift.value, shift.startTime, shift.hadRecentInput);\r\n });\r\n\r\n win.addEventListener('keydown', this.finalizeLcp, { once: true, capture: true } as AddEventListenerOptions);\r\n win.addEventListener('pointerdown', this.finalizeLcp, { once: true, capture: true } as AddEventListenerOptions);\r\n\r\n if (doc.readyState === 'complete') {\r\n this.handleLoad();\r\n } else {\r\n win.addEventListener('load', this.handleLoad);\r\n }\r\n }\r\n\r\n uninstall(): void {\r\n const win = getWindow();\r\n if (!this.installed || win === null) return;\r\n for (let i = 0; i < this.observers.length; i++) {\r\n safelyRun(this.logger, 'disconnect observer', disconnect(this.observers[i]));\r\n }\r\n this.observers = [];\r\n win.removeEventListener('load', this.handleLoad);\r\n win.removeEventListener('keydown', this.finalizeLcp, true);\r\n win.removeEventListener('pointerdown', this.finalizeLcp, true);\r\n this.installed = false;\r\n }\r\n\r\n /** Current metrics for inclusion in a payload. */\r\n snapshot(): PerformancePayload {\r\n const m = this.metrics;\r\n return {\r\n page_load_ms: m.page_load_ms,\r\n ttfb_ms: m.ttfb_ms,\r\n fcp_ms: m.fcp_ms,\r\n lcp_ms: m.lcp_ms,\r\n cls: this.cls.value(),\r\n startup_ms: null,\r\n frame_rate_fps: null,\r\n slow_screen: m.slow_screen,\r\n api_calls: this.apiCalls.toArray(),\r\n slow_api_calls: this.slowApiCalls.toArray(),\r\n };\r\n }\r\n\r\n /** Records a completed request; exposed so it can be unit-tested without patching fetch. */\r\n recordApiCall(call: ApiCall): void {\r\n this.apiCalls.push(call);\r\n if (call.duration_ms > SLOW_API_CALL_MS) {\r\n this.slowApiCalls.push(call);\r\n this.sink.onPerformanceIssue(\r\n 'SlowApiCall',\r\n 'Slow API call: ' + call.method + ' ' + call.url + ' took ' + call.duration_ms + 'ms',\r\n );\r\n }\r\n }\r\n\r\n /** Reads navigation timings; exposed for tests. */\r\n measurePageLoad(): void {\r\n const perf = getPerformance();\r\n if (perf === null) return;\r\n const timings = readPageTimings(perf);\r\n this.metrics.page_load_ms = timings.pageLoadMs;\r\n this.metrics.ttfb_ms = timings.ttfbMs;\r\n\r\n if (this.metrics.fcp_ms === null && typeof perf.getEntriesByName === 'function') {\r\n const fcp = perf.getEntriesByName('first-contentful-paint');\r\n if (fcp.length > 0) this.metrics.fcp_ms = toMs(fcp[0].startTime);\r\n }\r\n\r\n if (timings.pageLoadMs !== null && timings.pageLoadMs > SLOW_PAGE_LOAD_MS) {\r\n this.metrics.slow_screen = true;\r\n this.sink.onPerformanceIssue('SlowPageLoad', 'Slow page load: ' + timings.pageLoadMs + 'ms');\r\n }\r\n }\r\n\r\n private observe(type: string, onEntry: (entry: PerformanceEntry) => void): void {\r\n if (typeof PerformanceObserver === 'undefined') return;\r\n const supported = PerformanceObserver.supportedEntryTypes;\r\n if (supported !== undefined && supported.indexOf(type) === -1) return;\r\n\r\n const logger = this.logger;\r\n safelyRun(logger, 'observe ' + type, () => {\r\n const observer = new PerformanceObserver(\r\n guard(logger, type + ' observer', function onList(list: PerformanceObserverEntryList) {\r\n const entries = list.getEntries();\r\n for (let i = 0; i < entries.length; i++) onEntry(entries[i]);\r\n }),\r\n );\r\n observer.observe({ type: type, buffered: true });\r\n this.observers.push(observer);\r\n });\r\n }\r\n}\r\n\r\nfunction disconnect(observer: PerformanceObserver): () => void {\r\n return function run() {\r\n observer.disconnect();\r\n };\r\n}\r\n","import { HTTP_ERROR_STATUS_MIN, MAX_MESSAGE_LENGTH } from '../constants';\nimport { getDocument, nowMs, stripQuery } from '../core/env';\nimport { Logger } from '../core/logger';\nimport { guard, safelyRun } from '../core/safe';\nimport { truncate } from '../core/serialize';\nimport { CapturedError, Collector, CollectorSink } from './collector';\n\nconst RESOURCE_ERROR_TYPE = 'ResourceError';\n/** Resources requested by stylesheets: background images, @import, fonts. */\nconst CSS_INITIATOR = 'css';\n/** Font files are reported through FontFaceSet instead, which also works outside Chromium. */\nconst FONT_FILE = /\\.(woff2?|ttf|otf|eot)$/i;\n\n/** Element-loaded resources. After init the error collector sees these via element `error` events. */\nconst ELEMENT_INITIATORS = ['img', 'script', 'link'];\n\n/** A resource timing entry. `responseStatus` is Chromium 109+, so it may be missing at runtime. */\ntype ResourceEntryWithStatus = PerformanceEntry & { initiatorType: string; responseEnd: number; responseStatus?: number };\n\n/** Builds the error for an element resource that failed before the SDK started. */\nexport function earlyElementResourceError(tag: string, url: string, status: number): CapturedError {\n return {\n error: {\n message: truncate('Failed to load <' + tag + '> ' + url + ' (status ' + status + ')', MAX_MESSAGE_LENGTH),\n type: RESOURCE_ERROR_TYPE,\n handled: false,\n },\n stacktrace: [],\n context: { resource: tag, url: url, status: status, before_sdk_start: true },\n };\n}\n\n/** Builds the error for a stylesheet-initiated resource that came back with an error status. */\nexport function cssResourceError(url: string, status: number): CapturedError {\n return {\n error: {\n message: truncate('Failed to load CSS resource ' + url + ' (status ' + status + ')', MAX_MESSAGE_LENGTH),\n type: RESOURCE_ERROR_TYPE,\n handled: false,\n },\n stacktrace: [],\n context: { resource: 'css', url: url, status: status },\n };\n}\n\n/** Builds the error for a web font that failed to load or decode. */\nexport function fontError(family: string): CapturedError {\n return {\n error: { message: truncate(\"Failed to load font '\" + family + \"'\", MAX_MESSAGE_LENGTH), type: RESOURCE_ERROR_TYPE, handled: false },\n stacktrace: [],\n context: { resource: 'font', family: family },\n };\n}\n\n/**\n * Covers resource failures that never fire an element `error` event, so the\n * error collector cannot see them:\n * - **Web fonts** (`@font-face`, `new FontFace()`): via `document.fonts`\n * `loadingerror`, in all modern browsers.\n * - **CSS background images and `@import`ed files** with a 4xx/5xx status:\n * via Resource Timing `responseStatus`.\n * - **`<img>`, `<script>` and `<link>` failures from before the SDK started**\n * (e.g. a broken image in the server-rendered HTML): read from the buffered\n * Resource Timing entries at startup.\n *\n * Resource Timing status is Chromium 109+ only, and only for same-origin\n * resources or ones served with `Timing-Allow-Origin`.\n */\nexport class ResourceCollector implements Collector {\n private observer: PerformanceObserver | null = null;\n private fonts: FontFaceSet | null = null;\n /** performance.now() at install; element failures that finished earlier were missed by the error collector. */\n private installedAt = 0;\n private earlyReported: string[] = [];\n private readonly handleFontError: (event: FontFaceSetLoadEvent) => void;\n\n constructor(\n private readonly sink: CollectorSink,\n private readonly logger: Logger,\n ) {\n const self = this;\n this.handleFontError = guard(logger, 'font error handler', function onFontError(event: FontFaceSetLoadEvent) {\n const faces = event.fontfaces || [];\n for (let i = 0; i < faces.length; i++) self.sink.onError(fontError(faces[i].family.replace(/^[\"']|[\"']$/g, '')));\n });\n }\n\n install(): void {\n const doc = getDocument();\n if (doc === null || this.fonts !== null || this.observer !== null) return;\n this.installedAt = nowMs();\n\n if (doc.fonts !== undefined && typeof doc.fonts.addEventListener === 'function') {\n doc.fonts.addEventListener('loadingerror', this.handleFontError as EventListener);\n this.fonts = doc.fonts;\n }\n this.observeCssResources();\n }\n\n uninstall(): void {\n if (this.fonts !== null) this.fonts.removeEventListener('loadingerror', this.handleFontError as EventListener);\n if (this.observer !== null) {\n const observer = this.observer;\n safelyRun(this.logger, 'disconnect resource observer', function disconnect() {\n observer.disconnect();\n });\n }\n this.fonts = null;\n this.observer = null;\n }\n\n /** Handles one resource timing entry; exposed for tests. */\n recordResource(entry: ResourceEntryWithStatus): void {\n const status = entry.responseStatus;\n // 0 or undefined: status unknown (older browser, or cross-origin without Timing-Allow-Origin).\n if (typeof status !== 'number' || status < HTTP_ERROR_STATUS_MIN) return;\n const url = stripQuery(entry.name);\n\n if (entry.initiatorType === CSS_INITIATOR) {\n if (!FONT_FILE.test(url)) this.sink.onError(cssResourceError(url, status));\n return;\n }\n if (ELEMENT_INITIATORS.indexOf(entry.initiatorType) !== -1 && entry.responseEnd <= this.installedAt) {\n // One file can fail twice (e.g. a <link rel=\"preload\"> plus the <img> using it): report the URL once.\n if (this.earlyReported.indexOf(url) !== -1) return;\n this.earlyReported.push(url);\n this.sink.onError(earlyElementResourceError(entry.initiatorType, url, status));\n }\n }\n\n private observeCssResources(): void {\n if (typeof PerformanceObserver === 'undefined') return;\n const supported = PerformanceObserver.supportedEntryTypes;\n if (supported === undefined || supported.indexOf('resource') === -1) return;\n\n const self = this;\n safelyRun(this.logger, 'observe resources', function observe() {\n const observer = new PerformanceObserver(\n guard(self.logger, 'resource observer', function onList(list: PerformanceObserverEntryList) {\n const entries = list.getEntries();\n for (let i = 0; i < entries.length; i++) self.recordResource(entries[i] as ResourceEntryWithStatus);\n }),\n );\n observer.observe({ type: 'resource', buffered: true });\n self.observer = observer;\n });\n }\n}\n","import {\n FPS_FIRST_SAMPLE_DELAY_MS,\n FPS_SAMPLE_DURATION_MS,\n FPS_SAMPLE_INTERVAL_MS,\n FREEZE_REPORT_INTERVAL_MS,\n LONG_TASK_FREEZE_MS,\n LOW_FPS_THRESHOLD,\n MS_PER_SECOND,\n} from '../constants';\nimport { getWindow, isPageVisible, nowMs } from '../core/env';\nimport { Logger } from '../core/logger';\nimport { guard, safelyRun } from '../core/safe';\nimport { Collector, CollectorSink } from './collector';\n\n/** A sample is discarded if it took this many times longer than planned (tab was hidden mid-sample). */\nconst MAX_SAMPLE_STRETCH = 2;\n\nexport interface ResponsivenessDependencies {\n now?: () => number;\n requestFrame?: (callback: () => void) => void;\n sampleIntervalMs?: number;\n}\n\n/**\n * Watches main-thread responsiveness:\n * - **Freezes:** uses the Long Tasks API (Chromium browsers only) and reports\n * a `MainThreadBlocked` performance event when one task blocks the page for\n * longer than 1 s. At most one report per 30 s.\n * - **Frame rate:** 5 s after start and then every 30 s, while the page is\n * visible, counts animation frames for 1 s. The latest value fills `performance.frame_rate_fps`, and a\n * sample under 20 fps is reported as `LowFrameRate`.\n *\n * A page stuck in an infinite loop never finishes its task, so it cannot be\n * reported from inside the page.\n */\nexport class ResponsivenessCollector implements Collector {\n private observer: PerformanceObserver | null = null;\n private timer: ReturnType<typeof setInterval> | null = null;\n private firstSampleTimer: ReturnType<typeof setTimeout> | null = null;\n private sampling = false;\n private fps: number | null = null;\n private lastFreezeReport = -Infinity;\n private lastLowFpsReport = -Infinity;\n private readonly now: () => number;\n private readonly requestFrame: ((callback: () => void) => void) | null;\n private readonly sampleIntervalMs: number;\n private readonly runSample: () => void;\n\n constructor(\n private readonly sink: CollectorSink,\n private readonly logger: Logger,\n deps: ResponsivenessDependencies = {},\n ) {\n this.now = deps.now || nowMs;\n const win = getWindow();\n this.requestFrame =\n deps.requestFrame ||\n (win !== null && typeof win.requestAnimationFrame === 'function'\n ? function frame(callback: () => void) {\n win.requestAnimationFrame(callback);\n }\n : null);\n this.sampleIntervalMs = deps.sampleIntervalMs !== undefined ? deps.sampleIntervalMs : FPS_SAMPLE_INTERVAL_MS;\n const self = this;\n this.runSample = guard(logger, 'frame rate sample', function sample() {\n self.sampleFrameRate();\n });\n }\n\n install(): void {\n if (this.timer !== null || getWindow() === null) return;\n this.observeLongTasks();\n if (this.requestFrame === null) return;\n // The first sample waits a few seconds so page-load work doesn't skew it.\n this.firstSampleTimer = setTimeout(this.runSample, FPS_FIRST_SAMPLE_DELAY_MS);\n this.timer = setInterval(this.runSample, this.sampleIntervalMs);\n }\n\n uninstall(): void {\n if (this.observer !== null) {\n const observer = this.observer;\n safelyRun(this.logger, 'disconnect long task observer', function disconnect() {\n observer.disconnect();\n });\n }\n if (this.timer !== null) clearInterval(this.timer);\n if (this.firstSampleTimer !== null) clearTimeout(this.firstSampleTimer);\n this.observer = null;\n this.timer = null;\n this.firstSampleTimer = null;\n }\n\n /** Latest sampled frame rate, or null if none was measured yet. */\n frameRate(): number | null {\n return this.fps;\n }\n\n /** Handles one long task; exposed for tests. */\n recordLongTask(durationMs: number): void {\n if (durationMs <= LONG_TASK_FREEZE_MS) return;\n const now = this.now();\n if (now - this.lastFreezeReport < FREEZE_REPORT_INTERVAL_MS) return;\n this.lastFreezeReport = now;\n this.sink.onPerformanceIssue(\n 'MainThreadBlocked',\n 'Main thread blocked for ' + Math.round(durationMs) + 'ms (page unresponsive)',\n );\n }\n\n /** Counts frames for one sample window; exposed for tests. */\n sampleFrameRate(): void {\n const requestFrame = this.requestFrame;\n if (this.sampling || requestFrame === null || !isPageVisible()) return;\n this.sampling = true;\n\n const self = this;\n const start = this.now();\n let frames = 0;\n\n const onFrame = guard(this.logger, 'frame rate sample', function onFrame() {\n frames++;\n const elapsed = self.now() - start;\n if (elapsed < FPS_SAMPLE_DURATION_MS) {\n requestFrame(onFrame);\n return;\n }\n self.sampling = false;\n // Hidden tabs pause animation frames; a stretched sample would read as a fake slowdown.\n if (elapsed > FPS_SAMPLE_DURATION_MS * MAX_SAMPLE_STRETCH || !isPageVisible()) return;\n self.recordFrameRate(Math.round((frames * MS_PER_SECOND) / elapsed));\n });\n requestFrame(onFrame);\n }\n\n private recordFrameRate(fps: number): void {\n this.fps = fps;\n if (fps >= LOW_FPS_THRESHOLD) return;\n const now = this.now();\n if (now - this.lastLowFpsReport < FREEZE_REPORT_INTERVAL_MS) return;\n this.lastLowFpsReport = now;\n this.sink.onPerformanceIssue('LowFrameRate', 'Low frame rate: ' + fps + ' fps (janky scrolling/animation)');\n }\n\n private observeLongTasks(): void {\n if (typeof PerformanceObserver === 'undefined') return;\n const supported = PerformanceObserver.supportedEntryTypes;\n // Long Tasks API: Chromium only. Firefox/Safari simply get no freeze reports.\n if (supported === undefined || supported.indexOf('longtask') === -1) return;\n\n const self = this;\n safelyRun(this.logger, 'observe long tasks', function observe() {\n const observer = new PerformanceObserver(\n guard(self.logger, 'long task observer', function onList(list: PerformanceObserverEntryList) {\n const entries = list.getEntries();\n for (let i = 0; i < entries.length; i++) self.recordLongTask(entries[i].duration);\n }),\n );\n observer.observe({ type: 'longtask', buffered: true });\n self.observer = observer;\n });\n }\n}\n","import {\r\n MASK_COLOR,\r\n MAX_SCREENSHOT_LENGTH,\r\n SCREENSHOT_FALLBACK_QUALITY,\r\n SCREENSHOT_MAX_SCALE,\r\n SCREENSHOT_MIME_TYPE,\r\n SCREENSHOT_MIN_INTERVAL_MS,\r\n SCREENSHOT_QUALITY,\r\n SCREENSHOT_TIMEOUT_MS,\r\n} from '../constants';\r\nimport { getDocument, getWindow, isPageVisible } from '../core/env';\r\nimport { Logger } from '../core/logger';\r\nimport { safelyRun } from '../core/safe';\r\n\r\n/** The subset of html2canvas options the SDK uses. */\r\nexport interface Html2CanvasOptions {\r\n logging: boolean;\r\n useCORS: boolean;\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n scale: number;\r\n onclone: (clonedDocument: Document) => void;\r\n}\r\n\r\nexport type Html2Canvas = (element: HTMLElement, options: Html2CanvasOptions) => Promise<HTMLCanvasElement>;\r\n\r\ninterface WindowWithHtml2Canvas extends Window {\r\n html2canvas?: Html2Canvas;\r\n}\r\n\r\nexport interface ScreenshotOptions {\r\n maskSelectors: readonly string[];\r\n libraryUrl: string;\r\n /** SRI hash for `libraryUrl`; empty string disables the integrity attribute. */\r\n libraryIntegrity: string;\r\n}\r\n\r\n/** Returns every element matching any selector. Invalid selectors are skipped. */\r\nexport function findMaskedElements(root: ParentNode, selectors: readonly string[]): Element[] {\r\n const found: Element[] = [];\r\n for (let i = 0; i < selectors.length; i++) {\r\n let matches: NodeListOf<Element>;\r\n try {\r\n matches = root.querySelectorAll(selectors[i]);\r\n } catch (_e) {\r\n continue;\r\n }\r\n for (let j = 0; j < matches.length; j++) {\r\n if (found.indexOf(matches[j]) === -1) found.push(matches[j]);\r\n }\r\n }\r\n return found;\r\n}\r\n\r\n/**\r\n * Pre-render masking applied to html2canvas's cloned DOM: masked elements are\r\n * painted solid black and form values are blanked, so their content never\r\n * reaches the renderer. The live page is not touched.\r\n */\r\nexport function maskClonedDocument(clone: Document, selectors: readonly string[]): void {\r\n const elements = findMaskedElements(clone, selectors);\r\n for (let i = 0; i < elements.length; i++) {\r\n const el = elements[i] as HTMLElement;\r\n if (el.style === undefined) continue;\r\n el.style.setProperty('background', MASK_COLOR, 'important');\r\n el.style.setProperty('color', MASK_COLOR, 'important');\r\n el.style.setProperty('border-color', MASK_COLOR, 'important');\r\n el.style.setProperty('text-shadow', 'none', 'important');\r\n if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {\r\n el.value = '';\r\n el.setAttribute('value', '');\r\n el.setAttribute('placeholder', '');\r\n }\r\n // Hide descendants (images, nested text) so only the black box renders.\r\n const children = el.querySelectorAll('*');\r\n for (let j = 0; j < children.length; j++) {\r\n (children[j] as HTMLElement).style.setProperty('visibility', 'hidden', 'important');\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Post-render masking: draws an opaque rectangle over each masked element's\r\n * on-screen bounds. Belt-and-braces with `maskClonedDocument`.\r\n */\r\nexport function paintMasks(ctx: CanvasRenderingContext2D, elements: Element[], scale: number): void {\r\n ctx.fillStyle = MASK_COLOR;\r\n for (let i = 0; i < elements.length; i++) {\r\n const rect = elements[i].getBoundingClientRect();\r\n if (rect.width <= 0 || rect.height <= 0) continue;\r\n ctx.fillRect(rect.left * scale, rect.top * scale, rect.width * scale, rect.height * scale);\r\n }\r\n}\r\n\r\n/**\r\n * Captures the visible viewport as a JPEG data URL using html2canvas, which\r\n * is loaded from a CDN on first use (it is never bundled with the SDK).\r\n * Elements matching the mask selectors are blacked out.\r\n *\r\n * Screenshots are skipped when the page is hidden, when one was taken in the\r\n * last 10 s, or when capture takes longer than 3 s.\r\n */\r\nexport class ScreenshotCollector {\r\n private loader: Promise<Html2Canvas> | null = null;\r\n private lastCaptureAt = 0;\r\n\r\n constructor(\r\n private readonly options: ScreenshotOptions,\r\n private readonly logger: Logger,\r\n private readonly clock: () => number = Date.now,\r\n ) {}\r\n\r\n /** Resolves to a data URL, or `null` if no screenshot could or should be taken. Never rejects. */\r\n capture(): Promise<string | null> {\r\n const win = getWindow() as WindowWithHtml2Canvas | null;\r\n const doc = getDocument();\r\n if (win === null || doc === null || doc.documentElement === null) return Promise.resolve(null);\r\n\r\n if (!isPageVisible()) {\r\n this.logger.warn('page is hidden; skipping screenshot');\r\n return Promise.resolve(null);\r\n }\r\n const now = this.clock();\r\n if (now - this.lastCaptureAt < SCREENSHOT_MIN_INTERVAL_MS) {\r\n this.logger.info('screenshot throttled');\r\n return Promise.resolve(null);\r\n }\r\n this.lastCaptureAt = now;\r\n\r\n const self = this;\r\n const work = this.loadLibrary(win)\r\n .then(function render(html2canvas) {\r\n return self.render(html2canvas, win, doc);\r\n })\r\n .then(null, function onFailure(error: unknown): string | null {\r\n self.logger.warn('screenshot failed', error);\r\n return null;\r\n });\r\n\r\n return withTimeout(work, SCREENSHOT_TIMEOUT_MS, function onTimeout() {\r\n self.logger.warn('screenshot timed out');\r\n });\r\n }\r\n\r\n private render(html2canvas: Html2Canvas, win: Window, doc: Document): Promise<string | null> {\r\n if (!isPageVisible()) return Promise.resolve(null);\r\n\r\n const selectors = this.options.maskSelectors;\r\n const scale = Math.min(win.devicePixelRatio || 1, SCREENSHOT_MAX_SCALE);\r\n // Measure masked elements on the live page before rendering.\r\n const masked = findMaskedElements(doc, selectors);\r\n const logger = this.logger;\r\n\r\n return html2canvas(doc.documentElement, {\r\n logging: false,\r\n useCORS: true,\r\n x: win.scrollX || win.pageXOffset || 0,\r\n y: win.scrollY || win.pageYOffset || 0,\r\n width: win.innerWidth,\r\n height: win.innerHeight,\r\n scale: scale,\r\n onclone: function onClone(clone: Document) {\r\n safelyRun(logger, 'mask cloned document', function mask() {\r\n maskClonedDocument(clone, selectors);\r\n });\r\n },\r\n }).then(function encode(canvas) {\r\n const ctx = canvas.getContext('2d');\r\n if (ctx === null) {\r\n // Without a 2D context the post-render mask cannot be guaranteed: refuse to send.\r\n logger.warn('canvas 2D context unavailable; discarding screenshot');\r\n return null;\r\n }\r\n paintMasks(ctx, masked, scale);\r\n\r\n let dataUrl = canvas.toDataURL(SCREENSHOT_MIME_TYPE, SCREENSHOT_QUALITY);\r\n if (dataUrl.length > MAX_SCREENSHOT_LENGTH) {\r\n dataUrl = canvas.toDataURL(SCREENSHOT_MIME_TYPE, SCREENSHOT_FALLBACK_QUALITY);\r\n }\r\n if (dataUrl.length > MAX_SCREENSHOT_LENGTH) {\r\n logger.warn('screenshot exceeds size budget; discarding it');\r\n return null;\r\n }\r\n return dataUrl;\r\n });\r\n }\r\n\r\n private loadLibrary(win: WindowWithHtml2Canvas): Promise<Html2Canvas> {\r\n if (typeof win.html2canvas === 'function') return Promise.resolve(win.html2canvas);\r\n if (this.loader !== null) return this.loader;\r\n\r\n const options = this.options;\r\n const self = this;\r\n this.loader = new Promise<Html2Canvas>(function load(resolve, reject) {\r\n const doc = win.document;\r\n const script = doc.createElement('script');\r\n script.src = options.libraryUrl;\r\n script.async = true;\r\n script.crossOrigin = 'anonymous';\r\n if (options.libraryIntegrity.length > 0) script.integrity = options.libraryIntegrity;\r\n script.onload = function onLoad() {\r\n if (typeof win.html2canvas === 'function') {\r\n resolve(win.html2canvas);\r\n } else {\r\n reject(new Error('html2canvas loaded but did not register itself'));\r\n }\r\n };\r\n script.onerror = function onError() {\r\n reject(new Error('failed to load html2canvas from ' + options.libraryUrl));\r\n };\r\n (doc.head || doc.documentElement).appendChild(script);\r\n }).then(null, function resetLoader(error: unknown): Promise<Html2Canvas> {\r\n // Allow a later attempt (e.g. after the CDN recovers).\r\n self.loader = null;\r\n return Promise.reject(error);\r\n });\r\n return this.loader;\r\n }\r\n}\r\n\r\nfunction withTimeout(work: Promise<string | null>, timeoutMs: number, onTimeout: () => void): Promise<string | null> {\r\n return new Promise<string | null>(function race(resolve) {\r\n let settled = false;\r\n const timer = setTimeout(function expire() {\r\n if (settled) return;\r\n settled = true;\r\n onTimeout();\r\n resolve(null);\r\n }, timeoutMs);\r\n work.then(function done(value) {\r\n if (settled) return;\r\n settled = true;\r\n clearTimeout(timer);\r\n resolve(value);\r\n });\r\n });\r\n}\r\n","import { MAX_MESSAGE_LENGTH, UNKNOWN_FUNCTION } from '../constants';\nimport { getWindow, stripQuery } from '../core/env';\nimport { Logger } from '../core/logger';\nimport { locationSignature, markSignatureReported } from '../core/reportedErrors';\nimport { guard, safelyRun } from '../core/safe';\nimport { truncate } from '../core/serialize';\nimport { StackFrame } from '../types';\nimport { CapturedError, Collector, CollectorSink } from './collector';\n\nconst WORKER_ERROR_TYPE = 'WorkerError';\n\ntype WorkerConstructor = typeof Worker;\n/** `Worker` lives on the global object but is not declared on TypeScript's `Window`. */\ntype WindowWithWorker = Window & { Worker?: WorkerConstructor };\n\n/** Builds the error for an `error` event fired on a Worker object. */\nexport function workerErrorFromEvent(event: Event, workerUrl: string): CapturedError {\n const errorEvent = typeof ErrorEvent !== 'undefined' && event instanceof ErrorEvent ? event : null;\n const message =\n errorEvent !== null && errorEvent.message\n ? errorEvent.message\n : // No message means the worker script itself could not be loaded or parsed.\n 'Worker failed to start: ' + workerUrl;\n const stacktrace: StackFrame[] =\n errorEvent !== null && errorEvent.filename\n ? [{ filename: stripQuery(errorEvent.filename), lineno: errorEvent.lineno || null, colno: errorEvent.colno || null, function: UNKNOWN_FUNCTION }]\n : [];\n\n return {\n error: { message: truncate(message, MAX_MESSAGE_LENGTH), type: WORKER_ERROR_TYPE, handled: false },\n stacktrace: stacktrace,\n context: { worker_url: workerUrl },\n };\n}\n\n/**\n * Reports uncaught errors inside dedicated Web Workers, and workers that fail\n * to load. Errors inside a worker never reach the page's `window` error\n * handler in every browser, so `window.Worker` is wrapped to attach an\n * `error` listener to each worker the app creates. The returned object is the\n * real Worker, so `instanceof Worker` and all behaviour are unchanged.\n *\n * Service Worker errors are not visible from the page and are not covered.\n */\nexport class WorkerCollector implements Collector {\n private original: WorkerConstructor | null = null;\n private patched: WorkerConstructor | null = null;\n\n constructor(\n private readonly sink: CollectorSink,\n private readonly logger: Logger,\n ) {}\n\n install(): void {\n const win = getWindow() as WindowWithWorker | null;\n if (this.original !== null || win === null || typeof win.Worker !== 'function') return;\n const Original: WorkerConstructor = win.Worker;\n const self = this;\n\n const Tracked = function TrackedWorker(scriptUrl: string | URL, options?: WorkerOptions): Worker {\n // Constructing may throw (bad URL, CSP); that must reach the app unchanged.\n const worker = new Original(scriptUrl, options);\n safelyRun(self.logger, 'worker error tracking', function attach() {\n const url = stripQuery(typeof scriptUrl === 'string' ? scriptUrl : scriptUrl.href);\n worker.addEventListener(\n 'error',\n guard(self.logger, 'worker error handler', function onWorkerError(event: Event) {\n const captured = workerErrorFromEvent(event, url);\n const top = captured.stacktrace.length > 0 ? captured.stacktrace[0] : null;\n // Some browsers re-dispatch the same error on window; let the error collector skip it.\n markSignatureReported(locationSignature(captured.error.message, top !== null ? top.filename : null, top !== null ? top.lineno : null));\n self.sink.onError(captured);\n }),\n );\n });\n return worker;\n } as unknown as WorkerConstructor;\n Tracked.prototype = Original.prototype;\n\n this.original = Original;\n this.patched = Tracked;\n win.Worker = Tracked;\n }\n\n uninstall(): void {\n const win = getWindow() as WindowWithWorker | null;\n if (this.original === null || win === null) return;\n // Only restore if nobody wrapped on top of us.\n if (win.Worker === this.patched) win.Worker = this.original;\n this.original = null;\n this.patched = null;\n }\n}\n","import {\r\n API_KEY_HEADER,\r\n CONTENT_TYPE_JSON,\r\n HTTP_STATUS_OK_MAX,\r\n HTTP_STATUS_OK_MIN,\r\n HTTP_STATUS_REQUEST_TIMEOUT,\r\n HTTP_STATUS_SERVER_ERROR_MIN,\r\n HTTP_STATUS_TOO_MANY_REQUESTS,\r\n REQUEST_TIMEOUT_MS,\r\n} from '../constants';\r\nimport { Logger } from '../core/logger';\r\nimport { withField } from '../core/payloadBuilder';\r\nimport { AttemptResult } from '../core/retryManager';\r\nimport { EventBatch, TrackerEvent } from '../types';\r\n\r\n/** Anything that can deliver a batch of events. */\r\nexport interface Transport {\r\n send(events: TrackerEvent[]): Promise<AttemptResult>;\r\n}\r\n\r\ntype FetchFn = typeof fetch;\r\n\r\n/** Classifies an HTTP status into the retry decision used by the queue. */\r\nexport function classifyStatus(status: number): AttemptResult {\r\n const ok = status >= HTTP_STATUS_OK_MIN && status <= HTTP_STATUS_OK_MAX;\r\n const retryable =\r\n !ok &&\r\n (status >= HTTP_STATUS_SERVER_ERROR_MIN ||\r\n status === HTTP_STATUS_REQUEST_TIMEOUT ||\r\n status === HTTP_STATUS_TOO_MANY_REQUESTS);\r\n return { ok: ok, retryable: retryable, status: status };\r\n}\r\n\r\n/**\r\n * POSTs batches as JSON using `fetch`. The API key is applied here, at send\r\n * time, so it never needs to be written to persistent storage.\r\n */\r\nexport class HttpTransport implements Transport {\r\n private readonly fetchFn: FetchFn | null;\r\n\r\n constructor(\r\n private readonly endpoint: string,\r\n private readonly apiKey: string,\r\n private readonly logger: Logger,\r\n fetchFn?: FetchFn,\r\n ) {\r\n // Capture fetch now, before the network collector wraps it, so the SDK's\r\n // own requests are never recorded as breadcrumbs or API calls.\r\n if (fetchFn !== undefined) {\r\n this.fetchFn = fetchFn;\r\n } else if (typeof fetch === 'function') {\r\n this.fetchFn = fetch.bind(typeof window !== 'undefined' ? window : undefined);\r\n } else {\r\n this.fetchFn = null;\r\n }\r\n }\r\n\r\n send(events: TrackerEvent[]): Promise<AttemptResult> {\r\n if (this.fetchFn === null) {\r\n this.logger.warn('fetch is not available in this environment; events cannot be sent');\r\n return Promise.resolve<AttemptResult>({ ok: false, retryable: false, status: null });\r\n }\r\n\r\n let body: string;\r\n try {\r\n body = this.serialize(events);\r\n } catch (e) {\r\n this.logger.warn('failed to serialize batch; dropping it', e);\r\n return Promise.resolve<AttemptResult>({ ok: false, retryable: false, status: null });\r\n }\r\n\r\n const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;\r\n const timer =\r\n controller !== null\r\n ? setTimeout(function abort() {\r\n controller.abort();\r\n }, REQUEST_TIMEOUT_MS)\r\n : null;\r\n\r\n const headers: Record<string, string> = { 'Content-Type': CONTENT_TYPE_JSON };\r\n headers[API_KEY_HEADER] = this.apiKey;\r\n\r\n const logger = this.logger;\r\n return this.fetchFn(this.endpoint, {\r\n method: 'POST',\r\n headers: headers,\r\n body: body,\r\n credentials: 'omit',\r\n signal: controller !== null ? controller.signal : undefined,\r\n }).then(\r\n function onResponse(response) {\r\n if (timer !== null) clearTimeout(timer);\r\n const result = classifyStatus(response.status);\r\n if (!result.ok) logger.warn('endpoint responded with status ' + response.status);\r\n return result;\r\n },\r\n function onNetworkError(error: unknown): AttemptResult {\r\n if (timer !== null) clearTimeout(timer);\r\n logger.warn('network error while sending events', error);\r\n return { ok: false, retryable: true, status: null };\r\n },\r\n );\r\n }\r\n\r\n private serialize(events: TrackerEvent[]): string {\r\n const apiKey = this.apiKey;\r\n const batch: EventBatch = {\r\n events: events.map(function stamp(event) {\r\n return withField(event, 'api_key', apiKey);\r\n }),\r\n };\r\n return JSON.stringify(batch);\r\n }\r\n}\r\n","import { MAX_PERSISTED_EVENTS, OFFLINE_STORAGE_KEY } from '../constants';\r\nimport { getLocalStorage } from '../core/env';\r\nimport { Logger } from '../core/logger';\r\nimport { withField } from '../core/payloadBuilder';\r\nimport { TrackerEvent } from '../types';\r\n\r\n/** Persistence for events that could not be delivered. */\r\nexport interface OfflineStore {\r\n append(events: TrackerEvent[]): void;\r\n /** Returns every stored event and clears storage. */\r\n takeAll(): TrackerEvent[];\r\n}\r\n\r\n/**\r\n * Stores undelivered events in localStorage under `_et_queue`.\r\n *\r\n * The API key is blanked before writing (it is re-applied by the transport\r\n * at send time), and storage failures — quota exceeded, disabled storage,\r\n * corrupt data — are handled without ever throwing.\r\n */\r\nexport class LocalStorageStore implements OfflineStore {\r\n constructor(\r\n private readonly logger: Logger,\r\n private readonly maxEvents: number = MAX_PERSISTED_EVENTS,\r\n private readonly key: string = OFFLINE_STORAGE_KEY,\r\n ) {}\r\n\r\n append(events: TrackerEvent[]): void {\r\n if (events.length === 0) return;\r\n const storage = getLocalStorage();\r\n if (storage === null) {\r\n this.logger.warn('localStorage unavailable; dropping ' + events.length + ' undeliverable event(s)');\r\n return;\r\n }\r\n\r\n let combined = this.read(storage).concat(events.map(redact)).slice(-this.maxEvents);\r\n\r\n // Quota strategy: first drop screenshots (by far the largest field), then\r\n // repeatedly halve the stored set keeping the newest events.\r\n let strippedScreenshots = false;\r\n while (combined.length > 0) {\r\n if (this.write(storage, combined)) return;\r\n if (!strippedScreenshots) {\r\n combined = combined.map(withoutScreenshot);\r\n strippedScreenshots = true;\r\n } else {\r\n combined = combined.slice(Math.ceil(combined.length / 2));\r\n }\r\n }\r\n this.logger.warn('localStorage is full; could not persist events');\r\n }\r\n\r\n takeAll(): TrackerEvent[] {\r\n const storage = getLocalStorage();\r\n if (storage === null) return [];\r\n const events = this.read(storage);\r\n try {\r\n storage.removeItem(this.key);\r\n } catch (e) {\r\n this.logger.warn('failed to clear persisted queue', e);\r\n }\r\n return events;\r\n }\r\n\r\n private read(storage: Storage): TrackerEvent[] {\r\n let raw: string | null;\r\n try {\r\n raw = storage.getItem(this.key);\r\n } catch (e) {\r\n this.logger.warn('failed to read persisted queue', e);\r\n return [];\r\n }\r\n if (raw === null || raw.length === 0) return [];\r\n\r\n try {\r\n const parsed: unknown = JSON.parse(raw);\r\n if (Object.prototype.toString.call(parsed) !== '[object Array]') throw new Error('not an array');\r\n return (parsed as unknown[]).filter(isEventLike);\r\n } catch (e) {\r\n this.logger.warn('persisted queue was corrupt; discarding it', e);\r\n try {\r\n storage.removeItem(this.key);\r\n } catch (_ignored) {\r\n // Already reported the corruption; removal failure changes nothing.\r\n }\r\n return [];\r\n }\r\n }\r\n\r\n private write(storage: Storage, events: TrackerEvent[]): boolean {\r\n try {\r\n storage.setItem(this.key, JSON.stringify(events));\r\n return true;\r\n } catch (e) {\r\n this.logger.warn('failed to write persisted queue (' + events.length + ' event(s))', e);\r\n return false;\r\n }\r\n }\r\n}\r\n\r\n/** In-memory store for environments without localStorage, and for tests. */\r\nexport class MemoryStore implements OfflineStore {\r\n private events: TrackerEvent[] = [];\r\n\r\n constructor(private readonly maxEvents: number = MAX_PERSISTED_EVENTS) {}\r\n\r\n append(events: TrackerEvent[]): void {\r\n this.events = this.events.concat(events.map(redact)).slice(-this.maxEvents);\r\n }\r\n\r\n takeAll(): TrackerEvent[] {\r\n const out = this.events;\r\n this.events = [];\r\n return out;\r\n }\r\n}\r\n\r\nfunction redact(event: TrackerEvent): TrackerEvent {\r\n return withField(event, 'api_key', '');\r\n}\r\n\r\nfunction withoutScreenshot(event: TrackerEvent): TrackerEvent {\r\n return withField(event, 'screenshot', null);\r\n}\r\n\r\nfunction isEventLike(value: unknown): value is TrackerEvent {\r\n return (\r\n value !== null &&\r\n typeof value === 'object' &&\r\n typeof (value as { event_type?: unknown }).event_type === 'string' &&\r\n typeof (value as { timestamp?: unknown }).timestamp === 'string'\r\n );\r\n}\r\n","import { PLATFORM } from '../constants';\r\nimport { DevicePayload } from '../types';\r\nimport { getDocument, getNavigator, getWindow, stripQuery } from './env';\r\n\r\n/** Browser/OS identity parsed from a user-agent string. */\r\nexport interface ParsedUserAgent {\r\n browser: string | null;\r\n browserVersion: string | null;\r\n os: string | null;\r\n osVersion: string | null;\r\n model: string | null;\r\n}\r\n\r\n/** Subset of the User-Agent Client Hints API (Chromium only). */\r\ninterface UADataValues {\r\n platform?: string;\r\n platformVersion?: string;\r\n model?: string;\r\n}\r\ninterface NavigatorUAData {\r\n getHighEntropyValues(hints: string[]): Promise<UADataValues>;\r\n}\r\n\r\n/** Windows 11 reports a UA-CH platformVersion of 13.0.0 or higher. */\r\nconst WINDOWS_11_MIN_PLATFORM_MAJOR = 13;\r\n\r\n// Order matters: Edge and Opera also contain \"Chrome\", Chrome also contains \"Safari\".\r\nconst BROWSER_RULES: Array<{ name: string; pattern: RegExp }> = [\r\n { name: 'Edge', pattern: /Edg(?:e|A|iOS)?\\/([\\d.]+)/ },\r\n { name: 'Opera', pattern: /(?:OPR|Opera)\\/([\\d.]+)/ },\r\n { name: 'Samsung Internet', pattern: /SamsungBrowser\\/([\\d.]+)/ },\r\n { name: 'Firefox', pattern: /(?:Firefox|FxiOS)\\/([\\d.]+)/ },\r\n { name: 'Chrome', pattern: /(?:Chrome|CriOS)\\/([\\d.]+)/ },\r\n { name: 'Safari', pattern: /Version\\/([\\d.]+).*Safari/ },\r\n { name: 'Node.js', pattern: /Node\\.js\\/v?([\\d.]+)/ },\r\n];\r\n\r\nconst WINDOWS_NT_VERSIONS: Record<string, string> = {\r\n '10.0': '10',\r\n '6.3': '8.1',\r\n '6.2': '8',\r\n '6.1': '7',\r\n};\r\n\r\n/** Pure user-agent parser; exported for testing. */\r\nexport function parseUserAgent(ua: string): ParsedUserAgent {\r\n const result: ParsedUserAgent = {\r\n browser: null,\r\n browserVersion: null,\r\n os: null,\r\n osVersion: null,\r\n model: null,\r\n };\r\n\r\n for (let i = 0; i < BROWSER_RULES.length; i++) {\r\n const match = BROWSER_RULES[i].pattern.exec(ua);\r\n if (match !== null) {\r\n result.browser = BROWSER_RULES[i].name;\r\n result.browserVersion = majorMinor(match[1]);\r\n break;\r\n }\r\n }\r\n\r\n let m: RegExpExecArray | null;\r\n if ((m = /Windows NT ([\\d.]+)/.exec(ua)) !== null) {\r\n const name = WINDOWS_NT_VERSIONS[m[1]];\r\n result.os = name !== undefined ? 'Windows ' + name : 'Windows';\r\n result.osVersion = m[1];\r\n } else if ((m = /Android ([\\d.]+)/.exec(ua)) !== null) {\r\n result.os = 'Android ' + m[1].split('.')[0];\r\n result.osVersion = m[1];\r\n const model = /Android [\\d.]+; (?:[a-z]{2}-[a-z]{2}; )?([^;)]+?)(?: Build\\/[^;)]*)?\\)/i.exec(ua);\r\n if (model !== null && model[1] !== 'K') result.model = model[1].trim();\r\n } else if ((m = /(?:iPhone|iPad|iPod).*? OS ([\\d_]+)/.exec(ua)) !== null) {\r\n const version = m[1].replace(/_/g, '.');\r\n result.os = 'iOS ' + majorMinor(version);\r\n result.osVersion = version;\r\n const device = /(iPhone|iPad|iPod)/.exec(ua);\r\n result.model = device !== null ? device[1] : null;\r\n } else if ((m = /Mac OS X ([\\d_.]+)/.exec(ua)) !== null) {\r\n const version = m[1].replace(/_/g, '.');\r\n result.os = 'macOS ' + majorMinor(version);\r\n result.osVersion = version;\r\n } else if (/CrOS/.test(ua)) {\r\n result.os = 'ChromeOS';\r\n } else if (/Linux/.test(ua)) {\r\n result.os = 'Linux';\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction majorMinor(version: string): string {\r\n const parts = version.split('.');\r\n return parts.length > 1 ? parts[0] + '.' + parts[1] : parts[0] + '.0';\r\n}\r\n\r\n/**\r\n * Collects static device information once, then refines the OS name\r\n * asynchronously using UA Client Hints where the browser supports them.\r\n */\r\nexport class DeviceInfo {\r\n private parsed: ParsedUserAgent;\r\n\r\n constructor() {\r\n const nav = getNavigator();\r\n this.parsed = parseUserAgent(nav !== null && typeof nav.userAgent === 'string' ? nav.userAgent : '');\r\n }\r\n\r\n /** Best-effort async refinement (distinguishes Windows 11 from 10, adds Android model). */\r\n refine(): Promise<void> {\r\n const nav = getNavigator() as (Navigator & { userAgentData?: NavigatorUAData }) | null;\r\n if (nav === null || nav.userAgentData === undefined) return Promise.resolve();\r\n\r\n const self = this;\r\n return nav.userAgentData\r\n .getHighEntropyValues(['platformVersion', 'model'])\r\n .then(function apply(values) {\r\n if (values.platform === 'Windows' && typeof values.platformVersion === 'string') {\r\n const major = parseInt(values.platformVersion.split('.')[0], 10);\r\n self.parsed.os = major >= WINDOWS_11_MIN_PLATFORM_MAJOR ? 'Windows 11' : 'Windows 10';\r\n self.parsed.osVersion = values.platformVersion;\r\n }\r\n if (typeof values.model === 'string' && values.model.length > 0) {\r\n self.parsed.model = values.model;\r\n }\r\n })\r\n .catch(function ignore() {\r\n // Client hints are optional; UA-derived values remain.\r\n });\r\n }\r\n\r\n /** Snapshot for a payload; URL and screen size are read fresh each time. */\r\n snapshot(): DevicePayload {\r\n const win = getWindow();\r\n const doc = getDocument();\r\n const nav = getNavigator();\r\n const screen = win !== null ? win.screen : undefined;\r\n\r\n return {\r\n platform: PLATFORM,\r\n os: this.parsed.os,\r\n os_version: this.parsed.osVersion,\r\n manufacturer: null,\r\n model: this.parsed.model,\r\n browser: this.parsed.browser,\r\n browser_version: this.parsed.browserVersion,\r\n screen_width: screen !== undefined ? screen.width : null,\r\n screen_height: screen !== undefined ? screen.height : null,\r\n url: win !== null && win.location !== undefined ? stripQuery(win.location.href) : null,\r\n referrer: doc !== null && doc.referrer.length > 0 ? stripQuery(doc.referrer) : null,\r\n locale: nav !== null && typeof nav.language === 'string' ? nav.language : null,\r\n };\r\n }\r\n}\r\n","import {\r\n DEDUP_MAX_ENTRIES,\r\n DEDUP_WINDOW_MS,\r\n RATE_LIMIT_MAX_EVENTS,\r\n RATE_LIMIT_WINDOW_MS,\r\n} from '../constants';\r\nimport { ErrorPayload, StackFrame } from '../types';\r\n\r\ntype Clock = () => number;\r\n\r\nconst defaultClock: Clock = function now() {\r\n return Date.now();\r\n};\r\n\r\n/**\r\n * Sliding-window rate limiter that protects the host app and the backend\r\n * from error storms (e.g. an exception thrown inside an animation frame).\r\n */\r\nexport class RateLimiter {\r\n private timestamps: number[] = [];\r\n\r\n constructor(\r\n private readonly maxEvents: number = RATE_LIMIT_MAX_EVENTS,\r\n private readonly windowMs: number = RATE_LIMIT_WINDOW_MS,\r\n private readonly clock: Clock = defaultClock,\r\n ) {}\r\n\r\n /** Returns true and records the event if it fits within the limit. */\r\n tryAcquire(): boolean {\r\n const now = this.clock();\r\n const cutoff = now - this.windowMs;\r\n while (this.timestamps.length > 0 && this.timestamps[0] <= cutoff) this.timestamps.shift();\r\n if (this.timestamps.length >= this.maxEvents) return false;\r\n this.timestamps.push(now);\r\n return true;\r\n }\r\n}\r\n\r\n/**\r\n * Drops events whose fingerprint was already seen within the dedup window,\r\n * so a loop throwing the same error does not send hundreds of copies.\r\n */\r\nexport class Deduplicator {\r\n private seen: Record<string, number> = {};\r\n private order: string[] = [];\r\n\r\n constructor(\r\n private readonly windowMs: number = DEDUP_WINDOW_MS,\r\n private readonly maxEntries: number = DEDUP_MAX_ENTRIES,\r\n private readonly clock: Clock = defaultClock,\r\n ) {}\r\n\r\n /** Returns true if this fingerprint is new (or its previous sighting has expired). */\r\n isNew(fingerprint: string): boolean {\r\n const now = this.clock();\r\n const last = this.seen[fingerprint];\r\n if (last !== undefined && now - last < this.windowMs) return false;\r\n\r\n if (last === undefined) {\r\n this.order.push(fingerprint);\r\n if (this.order.length > this.maxEntries) {\r\n const evicted = this.order.shift();\r\n if (evicted !== undefined) delete this.seen[evicted];\r\n }\r\n }\r\n this.seen[fingerprint] = now;\r\n return true;\r\n }\r\n}\r\n\r\n/** Fingerprint used for dedup: event type + error identity + top stack frame. */\r\nexport function fingerprint(\r\n eventType: string,\r\n error: ErrorPayload | null,\r\n stacktrace: StackFrame[],\r\n): string {\r\n const top = stacktrace.length > 0 ? stacktrace[0] : null;\r\n return [\r\n eventType,\r\n error !== null ? error.type : '',\r\n error !== null ? error.message : '',\r\n top !== null ? String(top.filename) + ':' + String(top.lineno) + ':' + String(top.colno) : '',\r\n ].join('|');\r\n}\r\n","import { RETRY_DELAYS_MS } from '../constants';\r\n\r\n/** Outcome of a single delivery attempt. */\r\nexport interface AttemptResult {\r\n ok: boolean;\r\n /** Whether trying again could succeed (network error, 5xx, 408, 429). */\r\n retryable: boolean;\r\n status: number | null;\r\n}\r\n\r\n/** Final outcome after all attempts. */\r\nexport interface RetryOutcome extends AttemptResult {\r\n attempts: number;\r\n}\r\n\r\nexport type Scheduler = (fn: () => void, delayMs: number) => void;\r\n\r\nconst defaultScheduler: Scheduler = function schedule(fn, delayMs) {\r\n setTimeout(fn, delayMs);\r\n};\r\n\r\n/**\r\n * Runs `attempt` until it succeeds, fails non-retryably, or the backoff\r\n * schedule (1s, 2s, 4s by default) is exhausted. Never rejects: a rejected\r\n * attempt is treated as a retryable network failure.\r\n */\r\nexport function retryWithBackoff(\r\n attempt: () => Promise<AttemptResult>,\r\n delaysMs: readonly number[] = RETRY_DELAYS_MS,\r\n schedule: Scheduler = defaultScheduler,\r\n): Promise<RetryOutcome> {\r\n return new Promise<RetryOutcome>(function run(resolve) {\r\n let attempts = 0;\r\n\r\n function next(): void {\r\n attempts++;\r\n let pending: Promise<AttemptResult>;\r\n try {\r\n pending = attempt();\r\n } catch (_e) {\r\n pending = Promise.resolve<AttemptResult>({ ok: false, retryable: true, status: null });\r\n }\r\n\r\n pending\r\n .then(\r\n function onResult(result) {\r\n return result;\r\n },\r\n function onReject(): AttemptResult {\r\n return { ok: false, retryable: true, status: null };\r\n },\r\n )\r\n .then(function decide(result) {\r\n const retriesUsed = attempts - 1;\r\n if (result.ok || !result.retryable || retriesUsed >= delaysMs.length) {\r\n resolve({ ok: result.ok, retryable: result.retryable, status: result.status, attempts: attempts });\r\n return;\r\n }\r\n schedule(next, delaysMs[retriesUsed]);\r\n });\r\n }\r\n\r\n next();\r\n });\r\n}\r\n","import { BATCH_SIZE, FLUSH_DELAY_MS, MAX_QUEUE_SIZE, RETRY_DELAYS_MS } from '../constants';\r\nimport { TrackerEvent } from '../types';\r\nimport { OfflineStore } from '../transport/offlineStore';\r\nimport { Transport } from '../transport/httpTransport';\r\nimport { isOnline } from './env';\r\nimport { Logger } from './logger';\r\nimport { retryWithBackoff, Scheduler } from './retryManager';\r\n\r\nexport interface EventQueueOptions {\r\n transport: Transport;\r\n store: OfflineStore;\r\n logger: Logger;\r\n batchSize?: number;\r\n flushDelayMs?: number;\r\n retryDelaysMs?: readonly number[];\r\n /** Injectable for tests; defaults to setTimeout. */\r\n schedule?: Scheduler;\r\n /** Injectable for tests; defaults to navigator.onLine. */\r\n isOnline?: () => boolean;\r\n}\r\n\r\n/**\r\n * In-memory event queue. Sends batches with retry, and falls back to the\r\n * offline store when the device is offline or delivery keeps failing.\r\n */\r\nexport class EventQueue {\r\n private queue: TrackerEvent[] = [];\r\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\r\n private inFlight: Promise<void> | null = null;\r\n private closed = false;\r\n\r\n private readonly transport: Transport;\r\n private readonly store: OfflineStore;\r\n private readonly logger: Logger;\r\n private readonly batchSize: number;\r\n private readonly flushDelayMs: number;\r\n private readonly retryDelaysMs: readonly number[];\r\n private readonly schedule: Scheduler | undefined;\r\n private readonly online: () => boolean;\r\n\r\n constructor(options: EventQueueOptions) {\r\n this.transport = options.transport;\r\n this.store = options.store;\r\n this.logger = options.logger;\r\n this.batchSize = options.batchSize !== undefined ? options.batchSize : BATCH_SIZE;\r\n this.flushDelayMs = options.flushDelayMs !== undefined ? options.flushDelayMs : FLUSH_DELAY_MS;\r\n this.retryDelaysMs = options.retryDelaysMs !== undefined ? options.retryDelaysMs : RETRY_DELAYS_MS;\r\n this.schedule = options.schedule;\r\n this.online = options.isOnline !== undefined ? options.isOnline : isOnline;\r\n }\r\n\r\n /** Number of events waiting in memory (not counting the batch in flight). */\r\n get size(): number {\r\n return this.queue.length;\r\n }\r\n\r\n /** Adds an event and schedules delivery. */\r\n enqueue(event: TrackerEvent): void {\r\n if (this.closed) return;\r\n\r\n if (!this.online()) {\r\n this.logger.info('offline; persisting event');\r\n this.store.append([event]);\r\n return;\r\n }\r\n\r\n this.queue.push(event);\r\n if (this.queue.length > MAX_QUEUE_SIZE) {\r\n this.queue.splice(0, this.queue.length - MAX_QUEUE_SIZE);\r\n this.logger.warn('queue full; dropped oldest events');\r\n }\r\n\r\n if (this.queue.length >= this.batchSize) {\r\n this.flush();\r\n } else {\r\n this.scheduleFlush();\r\n }\r\n }\r\n\r\n /** Sends everything currently queued. Resolves when the queue is drained or parked offline. */\r\n flush(): Promise<void> {\r\n this.cancelTimer();\r\n if (this.inFlight !== null) {\r\n // A send is running; chain another pass so newly queued events go too.\r\n const self = this;\r\n return this.inFlight.then(function again() {\r\n return self.queue.length > 0 ? self.flush() : undefined;\r\n });\r\n }\r\n if (this.queue.length === 0) return Promise.resolve();\r\n\r\n const self = this;\r\n this.inFlight = this.drain().then(function done() {\r\n self.inFlight = null;\r\n });\r\n return this.inFlight;\r\n }\r\n\r\n /** Moves events from the offline store back into the queue and sends them. */\r\n restoreFromStore(): Promise<void> {\r\n if (this.closed || !this.online()) return Promise.resolve();\r\n const persisted = this.store.takeAll();\r\n if (persisted.length === 0) return Promise.resolve();\r\n this.logger.info('restoring ' + persisted.length + ' persisted event(s)');\r\n this.queue = persisted.concat(this.queue).slice(-MAX_QUEUE_SIZE);\r\n return this.flush();\r\n }\r\n\r\n /** Writes queued (not in-flight) events to the offline store, e.g. when the page is hidden. */\r\n persistPending(): void {\r\n this.cancelTimer();\r\n if (this.queue.length === 0) return;\r\n this.store.append(this.queue);\r\n this.queue = [];\r\n }\r\n\r\n /** Stops accepting events. Pending events are persisted for the next session. */\r\n close(): void {\r\n this.persistPending();\r\n this.closed = true;\r\n }\r\n\r\n private scheduleFlush(): void {\r\n if (this.flushTimer !== null) return;\r\n const self = this;\r\n this.flushTimer = setTimeout(function timedFlush() {\r\n self.flushTimer = null;\r\n self.flush();\r\n }, this.flushDelayMs);\r\n }\r\n\r\n private cancelTimer(): void {\r\n if (this.flushTimer !== null) {\r\n clearTimeout(this.flushTimer);\r\n this.flushTimer = null;\r\n }\r\n }\r\n\r\n /** Sends batch after batch until the queue is empty or delivery has to stop. */\r\n private drain(): Promise<void> {\r\n if (this.queue.length === 0) return Promise.resolve();\r\n\r\n if (!this.online()) {\r\n this.persistPending();\r\n return Promise.resolve();\r\n }\r\n\r\n const batch = this.queue.splice(0, this.batchSize);\r\n const self = this;\r\n return retryWithBackoff(\r\n function attempt() {\r\n return self.transport.send(batch);\r\n },\r\n this.retryDelaysMs,\r\n this.schedule,\r\n ).then(function handle(outcome) {\r\n if (outcome.ok) {\r\n self.logger.info('sent ' + batch.length + ' event(s)');\r\n return self.drain();\r\n }\r\n if (!outcome.retryable) {\r\n // e.g. 400/401/403: resending the same payload cannot succeed.\r\n self.logger.warn('endpoint rejected batch with status ' + String(outcome.status) + '; dropping ' + batch.length + ' event(s)');\r\n return self.drain();\r\n }\r\n self.logger.warn('delivery failed after ' + outcome.attempts + ' attempt(s); persisting for later');\r\n self.store.append(batch);\r\n self.persistPending();\r\n return undefined;\r\n });\r\n }\r\n}\r\n","import { DROPPED_EVENTS_REPORT_DELAY_MS, MAX_MESSAGE_LENGTH } from '../constants';\r\nimport { BreadcrumbCollector } from '../collectors/breadcrumbCollector';\r\nimport { CapturedError, Collector, CollectorSink, PerformanceIssueKind } from '../collectors/collector';\r\nimport { CspCollector } from '../collectors/cspCollector';\r\nimport { captureFromThrown, ErrorCollector } from '../collectors/errorCollector';\r\nimport { HttpErrorCollector } from '../collectors/httpErrorCollector';\r\nimport { JsonResponseCollector } from '../collectors/jsonResponseCollector';\r\nimport { MemoryCollector, MemoryReading } from '../collectors/memoryCollector';\r\nimport { NetworkInterceptor } from '../collectors/networkInterceptor';\r\nimport { PerformanceCollector } from '../collectors/performanceCollector';\r\nimport { ResourceCollector } from '../collectors/resourceCollector';\r\nimport { ResponsivenessCollector } from '../collectors/responsivenessCollector';\r\nimport { ScreenshotCollector } from '../collectors/screenshotCollector';\r\nimport { WorkerCollector } from '../collectors/workerCollector';\r\nimport { HttpTransport, Transport } from '../transport/httpTransport';\r\nimport { LocalStorageStore, OfflineStore } from '../transport/offlineStore';\r\nimport { Breadcrumb, BreadcrumbInput, EventLevel, TrackedUser, TrackerEvent } from '../types';\r\nimport { CircularBuffer } from './circularBuffer';\r\nimport { ResolvedConfig } from './config';\r\nimport { DeviceInfo } from './device';\r\nimport { getDocument, getWindow, nowIso } from './env';\r\nimport { Deduplicator, fingerprint, RateLimiter } from './eventFilters';\r\nimport { EventQueue } from './eventQueue';\r\nimport { Logger } from './logger';\r\nimport { buildEvent, EventInput, EventScope } from './payloadBuilder';\r\nimport { guard, safely, safelyRun } from './safe';\r\nimport { normalizeObject, truncate } from './serialize';\r\n\r\n/** Dependency overrides, used by tests. */\r\nexport interface ClientDependencies {\r\n transport?: Transport;\r\n store?: OfflineStore;\r\n random?: () => number;\r\n rateLimiter?: RateLimiter;\r\n deduplicator?: Deduplicator;\r\n readMemory?: () => MemoryReading | null;\r\n screenshot?: ScreenshotCollector;\r\n queueRetryDelaysMs?: readonly number[];\r\n queueFlushDelayMs?: number;\r\n}\r\n\r\n/**\r\n * Owns all SDK state for one `init()` call: configuration, collectors,\r\n * scope (user, breadcrumbs) and the delivery queue.\r\n */\r\nexport class Client implements CollectorSink {\r\n readonly logger: Logger;\r\n private readonly config: ResolvedConfig;\r\n private readonly breadcrumbs: CircularBuffer<Breadcrumb>;\r\n private readonly device = new DeviceInfo();\r\n private readonly queue: EventQueue;\r\n private readonly random: () => number;\r\n private readonly rateLimiter: RateLimiter;\r\n private readonly deduplicator: Deduplicator;\r\n private readonly network: NetworkInterceptor;\r\n private readonly performance: PerformanceCollector;\r\n private readonly memory: MemoryCollector;\r\n private readonly responsiveness: ResponsivenessCollector;\r\n private readonly screenshot: ScreenshotCollector;\r\n private readonly collectors: Collector[];\r\n private user: TrackedUser | null = null;\r\n private rateLimitWarned = false;\r\n /** Events dropped by the rate limiter since the last summary event. */\r\n private droppedCount = 0;\r\n private droppedTimer: ReturnType<typeof setTimeout> | null = null;\r\n private started = false;\r\n /** Events waiting on a screenshot before they can be queued. */\r\n private pendingCaptures: Array<Promise<void>> = [];\r\n\r\n private readonly handleOnline: () => void;\r\n private readonly handleVisibility: () => void;\r\n private readonly handlePageHide: () => void;\r\n\r\n constructor(config: ResolvedConfig, deps: ClientDependencies = {}) {\r\n this.config = config;\r\n this.logger = new Logger(config.debug);\r\n this.breadcrumbs = new CircularBuffer<Breadcrumb>(config.maxBreadcrumbs);\r\n this.random = deps.random || Math.random;\r\n this.rateLimiter = deps.rateLimiter || new RateLimiter();\r\n this.deduplicator = deps.deduplicator || new Deduplicator();\r\n\r\n // Transport must be created before NetworkInterceptor.install() so it\r\n // captures the unwrapped fetch.\r\n this.queue = new EventQueue({\r\n transport: deps.transport || new HttpTransport(config.endpoint, config.apiKey, this.logger),\r\n store: deps.store || new LocalStorageStore(this.logger),\r\n logger: this.logger,\r\n retryDelaysMs: deps.queueRetryDelaysMs,\r\n flushDelayMs: deps.queueFlushDelayMs,\r\n });\r\n\r\n this.network = new NetworkInterceptor(config.endpoint, this.logger);\r\n this.performance = new PerformanceCollector(this, this.network, this.logger);\r\n this.memory = new MemoryCollector(this, this.logger, deps.readMemory);\r\n this.responsiveness = new ResponsivenessCollector(this, this.logger);\r\n this.screenshot =\r\n deps.screenshot ||\r\n new ScreenshotCollector(\r\n { maskSelectors: config.maskSelectors, libraryUrl: config.html2canvasUrl, libraryIntegrity: config.html2canvasIntegrity },\r\n this.logger,\r\n );\r\n this.collectors = [\r\n new ErrorCollector(this, this.logger),\r\n new BreadcrumbCollector(this, this.network, config.maskSelectors, this.logger, config.captureConsoleErrors),\r\n this.performance,\r\n this.memory,\r\n this.responsiveness,\r\n new CspCollector(this, this.logger, [config.html2canvasUrl]),\r\n new WorkerCollector(this, this.logger),\r\n new ResourceCollector(this, this.logger),\r\n new JsonResponseCollector(this, this.logger, (url: string) => this.network.isSdkUrl(url)),\r\n ];\r\n if (config.captureHttpErrors || config.captureNetworkErrors) {\r\n this.collectors.push(\r\n new HttpErrorCollector(this, this.network, { httpErrors: config.captureHttpErrors, networkErrors: config.captureNetworkErrors }),\r\n );\r\n }\r\n this.collectors.push(\r\n // Installed last: subscribers above register before requests start flowing.\r\n this.network,\r\n );\r\n\r\n const self = this;\r\n this.handleOnline = guard(this.logger, 'online handler', function onOnline() {\r\n self.queue.restoreFromStore();\r\n });\r\n this.handleVisibility = guard(this.logger, 'visibility handler', function onVisibility() {\r\n const doc = getDocument();\r\n if (doc === null) return;\r\n if (doc.visibilityState === 'hidden') {\r\n self.queue.flush();\r\n } else {\r\n self.queue.restoreFromStore();\r\n }\r\n });\r\n this.handlePageHide = guard(this.logger, 'pagehide handler', function onPageHide() {\r\n // The page may be unloading; anything not yet sent is kept for next time.\r\n self.queue.persistPending();\r\n });\r\n }\r\n\r\n /** Installs collectors and lifecycle listeners, then sends events left over from earlier sessions. */\r\n start(): void {\r\n if (this.started) return;\r\n this.started = true;\r\n\r\n for (let i = 0; i < this.collectors.length; i++) {\r\n const collector = this.collectors[i];\r\n safelyRun(this.logger, 'install collector', function install() {\r\n collector.install();\r\n });\r\n }\r\n\r\n const win = getWindow();\r\n const doc = getDocument();\r\n if (win !== null) {\r\n win.addEventListener('online', this.handleOnline);\r\n win.addEventListener('pagehide', this.handlePageHide);\r\n }\r\n if (doc !== null) doc.addEventListener('visibilitychange', this.handleVisibility);\r\n\r\n this.device.refine();\r\n this.queue.restoreFromStore();\r\n this.logger.info('initialized', { environment: this.config.environment, sampleRate: this.config.sampleRate });\r\n }\r\n\r\n /** Removes every hook from the page. Unsent events are persisted. */\r\n close(): Promise<void> {\r\n const self = this;\r\n return this.flush().then(function teardown() {\r\n for (let i = 0; i < self.collectors.length; i++) {\r\n const collector = self.collectors[i];\r\n safelyRun(self.logger, 'uninstall collector', function uninstall() {\r\n collector.uninstall();\r\n });\r\n }\r\n const win = getWindow();\r\n const doc = getDocument();\r\n if (win !== null) {\r\n win.removeEventListener('online', self.handleOnline);\r\n win.removeEventListener('pagehide', self.handlePageHide);\r\n }\r\n if (doc !== null) doc.removeEventListener('visibilitychange', self.handleVisibility);\r\n if (self.droppedTimer !== null) clearTimeout(self.droppedTimer);\r\n self.droppedTimer = null;\r\n self.queue.close();\r\n self.started = false;\r\n });\r\n }\r\n\r\n /** Waits for events still awaiting a screenshot, then sends everything queued. */\r\n flush(): Promise<void> {\r\n const queue = this.queue;\r\n return Promise.all(this.pendingCaptures.slice())\r\n .then(function send() {\r\n return queue.flush();\r\n })\r\n .then(null, () => {\r\n this.logger.warn('flush failed');\r\n });\r\n }\r\n\r\n captureError(thrown: unknown, context?: object): void {\r\n const captured = captureFromThrown(thrown, true);\r\n this.capture(\r\n {\r\n eventType: 'error',\r\n level: 'error',\r\n error: captured.error,\r\n stacktrace: captured.stacktrace,\r\n context: context !== undefined && context !== null ? normalizeObject(context) : null,\r\n },\r\n true,\r\n );\r\n }\r\n\r\n captureMessage(message: string, level: EventLevel): void {\r\n this.capture(\r\n {\r\n eventType: 'message',\r\n level: level,\r\n error: { message: truncate(String(message), MAX_MESSAGE_LENGTH), type: 'Message', handled: true },\r\n stacktrace: [],\r\n context: null,\r\n },\r\n false,\r\n );\r\n }\r\n\r\n setUser(user: TrackedUser | null): void {\r\n if (user === null || user === undefined) {\r\n this.user = null;\r\n return;\r\n }\r\n if (typeof user !== 'object' || user.id === undefined || user.id === null) {\r\n this.logger.warn('setUser requires an object with an id; ignoring');\r\n return;\r\n }\r\n this.user = { id: String(user.id), email: user.email, name: user.name };\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // CollectorSink\r\n // -------------------------------------------------------------------------\r\n\r\n onError(captured: CapturedError): void {\r\n this.capture(\r\n {\r\n eventType: 'error',\r\n level: 'error',\r\n error: captured.error,\r\n stacktrace: captured.stacktrace,\r\n context: captured.context !== undefined ? captured.context : null,\r\n },\r\n true,\r\n );\r\n }\r\n\r\n onBreadcrumb(input: BreadcrumbInput): void {\r\n if (input === null || typeof input !== 'object') return;\r\n this.breadcrumbs.push({\r\n timestamp: nowIso(),\r\n type: typeof input.type === 'string' ? input.type : 'log',\r\n message: truncate(String(input.message), MAX_MESSAGE_LENGTH),\r\n data: input.data !== undefined ? normalizeObject(input.data) : {},\r\n });\r\n }\r\n\r\n onPerformanceIssue(kind: PerformanceIssueKind, message: string): void {\r\n this.capture(\r\n { eventType: 'performance', level: 'warning', error: { message: message, type: kind, handled: true }, stacktrace: [], context: null },\r\n false,\r\n );\r\n }\r\n\r\n onNavigation(): void {\r\n this.memory.resetBaseline();\r\n }\r\n\r\n // -------------------------------------------------------------------------\r\n // Pipeline: sample → dedup → rate limit → build → screenshot → beforeSend → queue\r\n // -------------------------------------------------------------------------\r\n\r\n private capture(input: EventInput, withScreenshot: boolean): void {\r\n if (this.random() > this.config.sampleRate) {\r\n this.logger.info('event dropped by sampleRate');\r\n return;\r\n }\r\n if (!this.deduplicator.isNew(fingerprint(input.eventType, input.error, input.stacktrace))) {\r\n this.logger.info('duplicate event dropped');\r\n return;\r\n }\r\n if (!this.rateLimiter.tryAcquire()) {\r\n if (!this.rateLimitWarned) this.logger.warn('rate limit reached; dropping events');\r\n this.rateLimitWarned = true;\r\n this.recordDropped();\r\n return;\r\n }\r\n this.rateLimitWarned = false;\r\n\r\n // Snapshot scope now so breadcrumbs reflect the moment of the error, not\r\n // whatever happens while the screenshot renders.\r\n const scope = this.scope();\r\n const timestamp = nowIso();\r\n const self = this;\r\n\r\n if (!withScreenshot || !this.config.captureScreenshots) {\r\n this.finish(buildEvent(input, scope, timestamp));\r\n return;\r\n }\r\n\r\n const pending = this.screenshot.capture().then(\r\n function attach(shot) {\r\n scope.screenshot = shot;\r\n self.finish(buildEvent(input, scope, timestamp));\r\n },\r\n function withoutShot() {\r\n self.finish(buildEvent(input, scope, timestamp));\r\n },\r\n );\r\n this.pendingCaptures.push(pending);\r\n pending.then(function untrack() {\r\n const index = self.pendingCaptures.indexOf(pending);\r\n if (index !== -1) self.pendingCaptures.splice(index, 1);\r\n });\r\n }\r\n\r\n /** Counts a rate-limited event and schedules one summary event, so storms stay visible. */\r\n private recordDropped(): void {\r\n this.droppedCount++;\r\n if (this.droppedTimer !== null) return;\r\n const self = this;\r\n this.droppedTimer = setTimeout(\r\n guard(this.logger, 'dropped events summary', function report() {\r\n self.droppedTimer = null;\r\n const count = self.droppedCount;\r\n self.droppedCount = 0;\r\n if (count === 0) return;\r\n // Bypasses sampling, dedup and the rate limiter: this is the one event that explains the gap.\r\n self.finish(\r\n buildEvent(\r\n {\r\n eventType: 'message',\r\n level: 'warning',\r\n error: {\r\n message: 'Rate limit dropped ' + count + ' event(s) during an error storm',\r\n type: 'EventsDropped',\r\n handled: true,\r\n },\r\n stacktrace: [],\r\n context: { dropped_count: count },\r\n },\r\n self.scope(),\r\n nowIso(),\r\n ),\r\n );\r\n }),\r\n DROPPED_EVENTS_REPORT_DELAY_MS,\r\n );\r\n }\r\n\r\n private finish(event: TrackerEvent): void {\r\n safelyRun(this.logger, 'enqueue event', () => {\r\n const beforeSend = this.config.beforeSend;\r\n let final: TrackerEvent | null = event;\r\n if (beforeSend !== null) {\r\n // A throwing hook must not lose the event or break the app; send it unmodified.\r\n final = safely(this.logger, 'beforeSend', function run() {\r\n return beforeSend(event);\r\n }, event);\r\n }\r\n if (final === null || final === undefined) {\r\n this.logger.info('event dropped by beforeSend');\r\n return;\r\n }\r\n this.queue.enqueue(final);\r\n });\r\n }\r\n\r\n private scope(): EventScope {\r\n const performance = this.performance.snapshot();\r\n performance.frame_rate_fps = this.responsiveness.frameRate();\r\n return {\r\n apiKey: this.config.apiKey,\r\n environment: this.config.environment,\r\n appVersion: this.config.appVersion,\r\n user: this.user,\r\n breadcrumbs: this.breadcrumbs.toArray(),\r\n performance: performance,\r\n memory: this.memory.snapshot(),\r\n device: this.device.snapshot(),\r\n screenshot: null,\r\n };\r\n }\r\n}\r\n\r\n","import {\r\n DEFAULT_ENVIRONMENT,\r\n DEFAULT_HTML2CANVAS_INTEGRITY,\r\n DEFAULT_HTML2CANVAS_URL,\r\n DEFAULT_MASK_SELECTORS,\r\n DEFAULT_MAX_BREADCRUMBS,\r\n DEFAULT_SAMPLE_RATE,\r\n MAX_BREADCRUMBS_LIMIT,\r\n} from '../constants';\r\nimport { ErrorTrackerConfig, TrackerEvent } from '../types';\r\n\r\n/** Config with defaults applied and values validated. */\r\nexport interface ResolvedConfig {\r\n apiKey: string;\r\n endpoint: string;\r\n environment: string;\r\n appVersion: string | null;\r\n sampleRate: number;\r\n maxBreadcrumbs: number;\r\n maskSelectors: string[];\r\n debug: boolean;\r\n captureHttpErrors: boolean;\r\n captureNetworkErrors: boolean;\r\n captureConsoleErrors: boolean;\r\n captureScreenshots: boolean;\r\n html2canvasUrl: string;\r\n html2canvasIntegrity: string;\r\n beforeSend: ((event: TrackerEvent) => TrackerEvent | null) | null;\r\n}\r\n\r\nexport type ConfigResult = { ok: true; config: ResolvedConfig } | { ok: false; reason: string };\r\n\r\nfunction clamp(value: number, min: number, max: number): number {\r\n return Math.min(max, Math.max(min, value));\r\n}\r\n\r\nfunction isValidUrl(value: string): boolean {\r\n try {\r\n // Relative endpoints are allowed in browsers (same-origin ingestion proxies).\r\n new URL(value, typeof document !== 'undefined' ? document.baseURI : undefined);\r\n return true;\r\n } catch (_e) {\r\n return false;\r\n }\r\n}\r\n\r\n/** Validates user config and fills in defaults. Never throws. */\r\nexport function resolveConfig(input: ErrorTrackerConfig | null | undefined): ConfigResult {\r\n if (input === null || typeof input !== 'object') return { ok: false, reason: 'config object is required' };\r\n if (typeof input.apiKey !== 'string' || input.apiKey.trim().length === 0) {\r\n return { ok: false, reason: 'apiKey must be a non-empty string' };\r\n }\r\n if (typeof input.endpoint !== 'string' || !isValidUrl(input.endpoint)) {\r\n return { ok: false, reason: 'endpoint must be a valid URL' };\r\n }\r\n\r\n const sampleRate =\r\n typeof input.sampleRate === 'number' && !isNaN(input.sampleRate) ? clamp(input.sampleRate, 0, 1) : DEFAULT_SAMPLE_RATE;\r\n const maxBreadcrumbs =\r\n typeof input.maxBreadcrumbs === 'number' && isFinite(input.maxBreadcrumbs)\r\n ? clamp(Math.floor(input.maxBreadcrumbs), 0, MAX_BREADCRUMBS_LIMIT)\r\n : DEFAULT_MAX_BREADCRUMBS;\r\n const userSelectors = Object.prototype.toString.call(input.maskSelectors) === '[object Array]' ? input.maskSelectors || [] : [];\r\n\r\n return {\r\n ok: true,\r\n config: {\r\n apiKey: input.apiKey,\r\n endpoint: input.endpoint,\r\n environment: typeof input.environment === 'string' && input.environment.length > 0 ? input.environment : DEFAULT_ENVIRONMENT,\r\n appVersion: typeof input.appVersion === 'string' && input.appVersion.length > 0 ? input.appVersion : null,\r\n sampleRate: sampleRate,\r\n maxBreadcrumbs: maxBreadcrumbs,\r\n maskSelectors: DEFAULT_MASK_SELECTORS.concat(\r\n userSelectors.filter(function isString(s): s is string {\r\n return typeof s === 'string' && s.length > 0;\r\n }),\r\n ),\r\n debug: input.debug === true,\r\n captureHttpErrors: input.captureHttpErrors !== false,\r\n captureNetworkErrors: input.captureNetworkErrors !== false,\r\n captureConsoleErrors: input.captureConsoleErrors === true,\r\n captureScreenshots: input.captureScreenshots !== false,\r\n html2canvasUrl: typeof input.html2canvasUrl === 'string' && input.html2canvasUrl.length > 0 ? input.html2canvasUrl : DEFAULT_HTML2CANVAS_URL,\r\n html2canvasIntegrity:\r\n typeof input.html2canvasIntegrity === 'string'\r\n ? input.html2canvasIntegrity\r\n : typeof input.html2canvasUrl === 'string' && input.html2canvasUrl.length > 0\r\n ? '' // A custom URL cannot share the default file's hash.\r\n : DEFAULT_HTML2CANVAS_INTEGRITY,\r\n beforeSend: typeof input.beforeSend === 'function' ? input.beforeSend : null,\r\n },\r\n };\r\n}\r\n","/**\r\n * Error Tracker JS SDK — public API.\r\n *\r\n * Every method is safe to call at any time: before `init()` calls are\r\n * buffered and replayed once the SDK starts, and no method ever throws into\r\n * the host application.\r\n */\r\nimport { MAX_PRE_INIT_CALLS, SDK_VERSION } from './constants';\r\nimport { Client } from './core/client';\r\nimport { resolveConfig } from './core/config';\r\nimport { sharedLogger } from './core/logger';\r\nimport { safely, safelyRun } from './core/safe';\r\nimport { BreadcrumbInput, ErrorTrackerConfig, EventLevel, TrackedUser } from './types';\r\n\r\ntype PendingCall = (client: Client) => void;\r\n\r\nlet client: Client | null = null;\r\nlet pending: PendingCall[] = [];\r\n\r\n/** Runs `call` now if initialized, otherwise buffers it until `init()`. */\r\nfunction withClient(label: string, call: PendingCall): void {\r\n safelyRun(client !== null ? client.logger : sharedLogger, label, function dispatch() {\r\n if (client !== null) {\r\n call(client);\r\n return;\r\n }\r\n if (pending.length >= MAX_PRE_INIT_CALLS) {\r\n sharedLogger.warn(label + ' called before init(); pre-init buffer full, dropping call');\r\n return;\r\n }\r\n pending.push(call);\r\n });\r\n}\r\n\r\n/**\r\n * Starts the SDK: validates config, installs collectors and begins delivering\r\n * events. Calling it again while running is ignored; call `close()` first to\r\n * re-initialize. An invalid config leaves the SDK disabled (and logs a warning\r\n * when `debug` is true) rather than throwing.\r\n */\r\nfunction init(config: ErrorTrackerConfig): void {\r\n safelyRun(sharedLogger, 'init', function start() {\r\n sharedLogger.setEnabled(config !== null && typeof config === 'object' && config.debug === true);\r\n if (client !== null) {\r\n sharedLogger.warn('init() called more than once; ignoring');\r\n return;\r\n }\r\n const resolved = resolveConfig(config);\r\n if (!resolved.ok) {\r\n sharedLogger.warn('invalid config: ' + resolved.reason + '; SDK disabled');\r\n return;\r\n }\r\n\r\n const created = new Client(resolved.config);\r\n created.start();\r\n client = created;\r\n\r\n const replay = pending;\r\n pending = [];\r\n for (let i = 0; i < replay.length; i++) {\r\n const call = replay[i];\r\n safelyRun(created.logger, 'replay pre-init call', function run() {\r\n call(created);\r\n });\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Reports a caught error. `handled` is `true` on the resulting event.\r\n * @param error The thrown value; non-Error values are converted to a message.\r\n * @param context Extra JSON-serializable data attached as `context`.\r\n */\r\nfunction captureError(error: unknown, context?: Record<string, unknown>): void {\r\n withClient('captureError', function run(c) {\r\n c.captureError(error, context);\r\n });\r\n}\r\n\r\n/**\r\n * Reports a free-form message.\r\n * @param message Text of the message.\r\n * @param level Severity; defaults to `'info'`.\r\n */\r\nfunction captureMessage(message: string, level: EventLevel = 'info'): void {\r\n withClient('captureMessage', function run(c) {\r\n c.captureMessage(message, level);\r\n });\r\n}\r\n\r\n/**\r\n * Attaches a user to all subsequent events. Pass `null` to clear it (e.g. on logout).\r\n */\r\nfunction setUser(user: TrackedUser | null): void {\r\n withClient('setUser', function run(c) {\r\n c.setUser(user);\r\n });\r\n}\r\n\r\n/**\r\n * Records a custom breadcrumb in the trail attached to future events.\r\n */\r\nfunction addBreadcrumb(breadcrumb: BreadcrumbInput): void {\r\n withClient('addBreadcrumb', function run(c) {\r\n c.onBreadcrumb(breadcrumb);\r\n });\r\n}\r\n\r\n/**\r\n * Sends queued events immediately. Resolves when the queue is drained or\r\n * parked offline; never rejects. Resolves immediately before `init()`.\r\n */\r\nfunction flush(): Promise<void> {\r\n return safely(sharedLogger, 'flush', function run() {\r\n return client !== null ? client.flush() : Promise.resolve();\r\n }, Promise.resolve());\r\n}\r\n\r\n/**\r\n * Flushes, then removes every hook the SDK installed (global handlers, fetch/XHR,\r\n * history, console). Unsent events are persisted for the next session.\r\n */\r\nfunction close(): Promise<void> {\r\n return safely(sharedLogger, 'close', function run() {\r\n const current = client;\r\n client = null;\r\n pending = [];\r\n return current !== null ? current.close() : Promise.resolve();\r\n }, Promise.resolve());\r\n}\r\n\r\n/** Whether `init()` has completed successfully. */\r\nfunction isInitialized(): boolean {\r\n return client !== null;\r\n}\r\n\r\n/** The SDK's public surface. */\r\nexport const ErrorTracker = {\r\n init: init,\r\n captureError: captureError,\r\n captureMessage: captureMessage,\r\n setUser: setUser,\r\n addBreadcrumb: addBreadcrumb,\r\n flush: flush,\r\n close: close,\r\n isInitialized: isInitialized,\r\n version: SDK_VERSION,\r\n};\r\n\r\nexport { init, captureError, captureMessage, setUser, addBreadcrumb, flush, close, isInitialized };\r\nexport default ErrorTracker;\r\n\r\nexport type {\r\n ApiCall,\r\n Breadcrumb,\r\n BreadcrumbInput,\r\n BreadcrumbType,\r\n DevicePayload,\r\n ErrorPayload,\r\n ErrorTrackerConfig,\r\n EventBatch,\r\n EventLevel,\r\n EventType,\r\n JsonObject,\r\n JsonValue,\r\n MemoryPayload,\r\n PerformancePayload,\r\n StackFrame,\r\n TrackedUser,\r\n TrackerEvent,\r\n UserPayload,\r\n} from './types';\r\n"],"names":["SDK_VERSION","RETRY_DELAYS_MS","MAX_MESSAGE_LENGTH","UNKNOWN_FUNCTION","SCREENSHOT_MIME_TYPE","MAX_SCREENSHOT_LENGTH","MASK_COLOR","DEFAULT_MASK_SELECTORS","getWindow","window","getDocument","document","getNavigator","navigator","getPerformance","performance","getLocalStorage","localStorage","_e","isOnline","nav","onLine","isPageVisible","doc","visibilityState","nowIso","Date","toISOString","nowMs","perf","now","stripQuery","url","cut","search","slice","absoluteUrl","URL","baseURI","href","toMs","value","isFinite","Math","round","LOG_PREFIX","Logger","enabled","this","prototype","setEnabled","isEnabled","info","message","details","_i","arguments","length","write","warn","error","method","console","fn","apply","concat","sharedLogger","reported","WeakSet","isObject","markReported","add","wasReported","has","signatures","locationSignature","filename","lineno","String","safely","logger","label","fallback","e","safelyRun","undefined","guard","args","truncate","max","normalize","depth","normalizeInner","normalizeObject","result","isArray","Object","toString","call","seen","name","Error","isNaN","getTime","Node","nodeName","indexOf","push","arr","limit","min","i","obj","source","keys","child","pop","describeValue","json","JSON","stringify","V8_FRAME","V8_NO_LOCATION","V8_EVAL_ORIGIN","V8_LINE","GECKO_FRAME","GECKO_EVAL","GECKO_NATIVE","parseStack","stack","lines","split","isV8","some","line","test","frames","frame_1","parseV8Line","parseGeckoLine","parseStackFromError","evalMatch","exec","fnName","frame","match","native","colno","toInt","function","cleanFunctionName","raw","trim","replace","n","parseInt","DEFAULT_ERROR_TYPE","RESOURCE_HINT_RELS","CROSS_ORIGIN_MESSAGE","captureFromThrown","thrown","handled","fallbackType","isErrorLike","type","name_1","ctor","constructor","stacktrace","ErrorCollector","sink","installed","self","handleError","event","isErrorEvent","signature","wasSignatureReported","captured","fromErrorEvent","onError","handleRejection","reason","install","win","addEventListener","uninstall","removeEventListener","context","hint","el","target","Element","isElement","tagName","rel","getAttribute","toLowerCase","isResourceHint","ErrorEvent","CONSOLE_LEVELS","FORM_FIELD_TAGS","cssPath","parts","current","part","id","unshift","className","join","parentElement","BreadcrumbCollector","network","maskSelectors","captureConsoleErrors","lastUrl","originalPushState","originalReplaceState","originalConsole","inConsoleHook","handleClick","recordClick","handlePopState","recordNavigation","handleVisibility","onBreadcrumb","_this","location","wrapHistory","wrapConsole","subscribe","outcome","failure","status","data","duration_ms","history","pushState","replaceState","original","closest","text","selectors","isMasked","textContent","describeElementText","tag","selector","trigger","to","from","onNavigation","originalPush","originalReplace","unused","forEach","level","isSdkLog","map","stack_1","callStack","arg","console_message","consoleErrorFromArgs","CSP_REPORT_TYPE","CSP_KEYWORDS","violationFromReport","body","blocked","blockedURL","directive","effectiveDirective","disposition","sourceFile","lineNumber","columnNumber","CspCollector","sdkScriptUrls","reportingObserver","g","ReportingObserver","observer","ignored","report","violation","blockedLabel","verb","blocked_uri","cspError","handleEvent","blockedURI","violatedDirective","violationFromEvent","handleReports","reports","Observer","self_1","types","buffered","observe","observer_1","disconnect","FAILURE_DESCRIPTIONS","offline","timeout","aborted","HttpErrorCollector","options","handle","networkErrors","callSite","networkErrorFromCall","httpErrors","httpErrorFromCall","JsonResponseCollector","isSdkUrl","patched","Response","response","then","cause","invalidJsonError","readChromeMemory","memory","usedBytes","usedJSHeapSize","totalBytes","totalJSHeapSize","toMb","bytes","MemoryCollector","read","intervalMs","timer","readings","latest","leakSuspected","poll","sample","setInterval","clearInterval","resetBaseline","reading","shift","consecutive","threshold","recent","isLeakPattern","onPerformanceIssue","snapshot","used_mb","total_mb","leak_suspected","oom_kill","classifyFetchFailure","rawStack","lazyCallSite","parsed","NetworkInterceptor","sdkEndpoint","listeners","originalFetch","patchedFetch","originalOpen","originalSend","patchedOpen","patchedSend","ignoredUrl","listener","rawUrl","wrapFetch","wrapXhr","fetch","XMLHttpRequest","proto","open","send","emit","startedAt","toUpperCase","this_1","input","init","__et_method","__et_url","__et_failure","xhr","markFailure","kind","CircularBuffer","capacity","start","count","items","Array","item","index","toArray","out","defineProperty","get","clear","buildEvent","scope","timestamp","sdk","version","api_key","apiKey","event_type","eventType","environment","app_version","appVersion","user","email","breadcrumbs","screenshot","page_load_ms","ttfb_ms","fcp_ms","lcp_ms","cls","startup_ms","frame_rate_fps","slow_screen","api_calls","slow_api_calls","device","platform","os","os_version","manufacturer","model","browser","browser_version","screen_width","screen_height","referrer","locale","withField","key","copy","k","ClsTracker","sessionValue","sessionStart","sessionLast","startTime","hadRecentInput","PerformanceCollector","metrics","apiCalls","slowApiCalls","observers","lcpFinal","handleLoad","setTimeout","measurePageLoad","finalizeLcp","recordApiCall","entry","lcp","renderTime","loadTime","once","capture","readyState","m","timings","entries","getEntriesByType","pageLoadMs","loadEventEnd","ttfbMs","responseStart","timing","navigationStart","readPageTimings","getEntriesByName","fcp","onEntry","PerformanceObserver","supported","supportedEntryTypes","list","getEntries","RESOURCE_ERROR_TYPE","FONT_FILE","ELEMENT_INITIATORS","fontError","family","resource","ResourceCollector","fonts","installedAt","earlyReported","handleFontError","faces","fontfaces","observeCssResources","recordResource","responseStatus","initiatorType","responseEnd","before_sdk_start","earlyElementResourceError","cssResourceError","ResponsivenessCollector","deps","firstSampleTimer","sampling","fps","lastFreezeReport","Infinity","lastLowFpsReport","requestFrame","requestAnimationFrame","callback","sampleIntervalMs","runSample","sampleFrameRate","observeLongTasks","clearTimeout","frameRate","recordLongTask","durationMs","onFrame","elapsed","FPS_SAMPLE_DURATION_MS","recordFrameRate","duration","findMaskedElements","root","found","matches","querySelectorAll","j","ScreenshotCollector","clock","loader","lastCaptureAt","documentElement","Promise","resolve","work","timeoutMs","onTimeout","settled","withTimeout","loadLibrary","html2canvas","render","scale","devicePixelRatio","masked","logging","useCORS","x","scrollX","pageXOffset","y","scrollY","pageYOffset","width","innerWidth","height","innerHeight","onclone","clone","elements","style","setProperty","HTMLInputElement","HTMLTextAreaElement","setAttribute","children","maskClonedDocument","canvas","ctx","getContext","fillStyle","rect","getBoundingClientRect","fillRect","left","top","paintMasks","dataUrl","toDataURL","reject","script","createElement","src","libraryUrl","async","crossOrigin","libraryIntegrity","integrity","onload","onerror","head","appendChild","WorkerCollector","Worker","Original","Tracked","scriptUrl","worker","workerUrl","errorEvent","worker_url","workerErrorFromEvent","HttpTransport","endpoint","fetchFn","bind","events","ok","retryable","serialize","controller","AbortController","abort","headers","credentials","signal","batch","LocalStorageStore","maxEvents","append","storage","combined","redact","strippedScreenshots","ceil","withoutScreenshot","takeAll","removeItem","getItem","parse","filter","isEventLike","_ignored","setItem","BROWSER_RULES","pattern","WINDOWS_NT_VERSIONS","majorMinor","DeviceInfo","ua","browserVersion","osVersion","parseUserAgent","userAgent","refine","userAgentData","getHighEntropyValues","values","platformVersion","major","catch","screen","language","defaultClock","RateLimiter","windowMs","timestamps","tryAcquire","cutoff","Deduplicator","maxEntries","order","isNew","fingerprint","last","evicted","defaultScheduler","delayMs","EventQueue","queue","flushTimer","inFlight","closed","transport","store","batchSize","flushDelayMs","retryDelaysMs","schedule","online","enqueue","splice","flush","scheduleFlush","cancelTimer","drain","restoreFromStore","persisted","persistPending","close","attempt","delaysMs","attempts","next","pending","retriesUsed","Client","config","rateLimitWarned","droppedCount","droppedTimer","started","pendingCaptures","debug","maxBreadcrumbs","random","rateLimiter","deduplicator","queueRetryDelaysMs","queueFlushDelayMs","readMemory","responsiveness","html2canvasUrl","html2canvasIntegrity","collectors","captureHttpErrors","captureNetworkErrors","handleOnline","handlePageHide","collector","sampleRate","all","captureError","captureMessage","setUser","withScreenshot","recordDropped","captureScreenshots","shot","finish","dropped_count","beforeSend","final","clamp","resolveConfig","isValidUrl","floor","userSelectors","s","client","withClient","resolved","created","replay","c","addBreadcrumb","breadcrumb","isInitialized","ErrorTracker"],"mappings":"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"}
|