@bugban/js 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +79 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +79 -21
- package/dist/index.js.map +1 -1
- package/dist/standalone/bugban.global.js +3 -3
- package/dist/standalone/bugban.global.js.map +1 -1
- package/package.json +21 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts","../../src/env.ts","../../src/config.ts","../../src/utils.ts","../../src/transport.ts","../../src/breadcrumbs.ts","../../src/stacktrace.ts","../../src/snapshot.ts","../../src/vitals.ts","../../src/integrations/console.ts","../../src/redact.ts","../../src/integrations/network.ts","../../src/integrations/globals.ts","../../src/integrations/dom.ts","../../src/ping.ts","../../src/client.ts"],"sourcesContent":["import { BugbanClient } from './client';\nimport type { Breadcrumb, BugbanOptions, Level, UserInfo, VitalMetric } from './types';\nimport { SDK_VERSION } from './env';\nimport { safe } from './utils';\n\nexport { BugbanClient } from './client';\nexport { parseStack, normalizeError } from './stacktrace';\nexport { redact, redactUrl } from './redact';\nexport { SDK_VERSION, SDK_NAME, runtimeName, runtimeVersion, dependencyVersion } from './env';\nexport type {\n Breadcrumb,\n BreadcrumbType,\n BugbanEvent,\n BugbanOptions,\n ConsoleOptions,\n Level,\n NetworkOptions,\n Snapshot,\n SnapshotOptions,\n StackFrame,\n UserInfo,\n VitalMetric,\n VitalsOptions,\n} from './types';\n\n/**\n * Module-level singleton.\n *\n * Almost every app wants exactly one client, and the framework adapters need a\n * way to reach it from code the app never touches (an error boundary, an\n * exception filter). A singleton keeps `import { Bugban } from '@bugban/js'`\n * working everywhere; `new BugbanClient()` is still there for the rare app\n * that reports to two projects.\n */\nlet client: BugbanClient | null = null;\n\nexport function init(options: BugbanOptions = {}): BugbanClient {\n // Re-initialising would leave the previous client's hooks installed, so the\n // old one is torn down first.\n if (client) safe(() => client!.close());\n client = new BugbanClient(options);\n client.start();\n return client;\n}\n\n/** The active client, or null when init() has not been called. */\nexport function getClient(): BugbanClient | null {\n return client;\n}\n\n/**\n * Every helper below is a no-op before init(). That is deliberate: a component\n * that calls captureError must not crash because the app forgot to configure\n * monitoring, or because it is running in a test.\n */\n\nexport function capture(\n error: unknown,\n extra?: { handled?: boolean; level?: Level; type?: string; context?: Record<string, unknown> },\n): void {\n client?.capture(error, extra);\n}\n\nexport function captureMessage(message: string, level: Level = 'info'): void {\n client?.captureMessage(message, level);\n}\n\nexport function setUser(user: UserInfo | null): void {\n client?.setUser(user);\n}\n\nexport function setContext(key: string, value: unknown): void {\n client?.setContext(key, value);\n}\n\nexport function addBreadcrumb(crumb: Omit<Breadcrumb, 'timestamp'> & { timestamp?: string }): void {\n client?.addBreadcrumb(crumb);\n}\n\nexport function recordMetric(metric: VitalMetric): void {\n client?.recordMetric(metric);\n}\n\nexport async function flush(): Promise<void> {\n await client?.flush();\n}\n\nexport function close(): void {\n client?.close();\n client = null;\n}\n\n/**\n * Namespace form, so `Bugban.capture(e)` reads the same as the PHP facade.\n *\n * Deliberately NOT also a default export: mixing default and named exports\n * makes the CommonJS build require `.default`, which is exactly the kind of\n * \"works in one install shape, breaks in another\" trap that took a customer's\n * site down on the PHP side. One import style, everywhere:\n *\n * import { Bugban } from '@bugban/js';\n * const { Bugban } = require('@bugban/js');\n */\nexport const Bugban = {\n VERSION: SDK_VERSION,\n init,\n getClient,\n capture,\n captureMessage,\n setUser,\n setContext,\n addBreadcrumb,\n recordMetric,\n flush,\n close,\n};\n","/**\n * Runtime detection and environment facts.\n *\n * Every lookup is defensive: this file runs in browsers, in Node, in edge\n * runtimes, and during SSR where `window` exists but `document` does not.\n * Nothing here may throw — a crash in environment detection would take down\n * the host application on import, which is exactly the failure the PHP SDK\n * learned to avoid the hard way.\n */\n\nexport const SDK_NAME = 'bugban-js';\nexport const SDK_VERSION = '1.0.0';\n\nexport const isBrowser: boolean = (() => {\n try {\n return typeof window !== 'undefined' && typeof window.document !== 'undefined';\n } catch {\n return false;\n }\n})();\n\nexport const isNode: boolean = (() => {\n try {\n return (\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null\n );\n } catch {\n return false;\n }\n})();\n\n/** 'browser' | 'node' | 'unknown' — reported on the install ping. */\nexport function runtimeName(): string {\n if (isBrowser) return 'browser';\n if (isNode) return 'node';\n return 'unknown';\n}\n\n/**\n * The runtime's own version: Node's `v22.13.1`, or the browser's UA string.\n * The panel shows this next to the framework version, the same way it shows\n * the PHP version for the PHP SDKs.\n */\nexport function runtimeVersion(): string | undefined {\n try {\n if (isNode) return process.versions.node;\n if (isBrowser) return navigator.userAgent;\n } catch {\n /* ignore */\n }\n return undefined;\n}\n\n/**\n * Load a Node built-in without letting any bundler see it.\n *\n * Three constraints collide here:\n * 1. In ESM there is no `require`, so the old `globalThis.require` trick\n * silently returned undefined and the SDK went quiet on modern Node.\n * 2. In a browser bundle a literal `import('http')` makes Vite/webpack try\n * to resolve — and warn or fail — even though the call is unreachable.\n * 3. Customers run old Node. `node:` prefixes need 14.18+, and dynamic\n * import itself needs 12.17+, so every step needs a fallback.\n *\n * The specifier is built at runtime so static analysis cannot follow it, and\n * `require` remains the last resort for old CJS bundles.\n */\nexport async function nodeModule(name: string): Promise<any> {\n if (!isNode) return undefined;\n\n // Computed on purpose — a literal would be statically analysable.\n const prefixed = 'node:'.concat(name);\n for (const spec of [prefixed, String(name)]) {\n try {\n const ns: any = await import(/* @vite-ignore */ /* webpackIgnore: true */ spec);\n if (ns) return ns.default && !ns.hostname && !ns.existsSync ? ns.default : ns;\n } catch {\n /* try the next specifier */\n }\n }\n\n return tryRequire(name);\n}\n\n/** Best-effort hostname — the machine for Node, the site for a browser. */\nexport async function hostname(): Promise<string | undefined> {\n try {\n if (isBrowser) return window.location.hostname;\n if (isNode) {\n const os = await nodeModule('os');\n if (os && typeof os.hostname === 'function') return String(os.hostname());\n }\n } catch {\n /* ignore */\n }\n return undefined;\n}\n\n/**\n * Read the host application's name/version from its package.json (Node only).\n * Browsers have no filesystem, so there `release` must be passed to init() —\n * usually wired to the bundler's define (e.g. Vite's import.meta.env).\n */\nexport async function appPackageInfo(): Promise<{ name?: string; version?: string }> {\n if (!isNode) return {};\n try {\n const fs = await nodeModule('fs');\n const path = await nodeModule('path');\n if (!fs || !path || typeof fs.existsSync !== 'function') return {};\n\n // Walk up from the working directory: in a monorepo the nearest\n // package.json is the app being run, not the repo root.\n let dir = process.cwd();\n for (let depth = 0; depth < 6; depth++) {\n const file = path.join(dir, 'package.json');\n if (fs.existsSync(file)) {\n const json = JSON.parse(fs.readFileSync(file, 'utf8'));\n return { name: json.name, version: json.version };\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n } catch {\n /* ignore */\n }\n return {};\n}\n\n/**\n * Read a dependency's version out of the host app's node_modules, so an\n * adapter can report \"react 19.0.0\" without importing react itself.\n */\nexport async function dependencyVersion(pkg: string): Promise<string | undefined> {\n if (!isNode) return undefined;\n try {\n const mod = await nodeModule('module');\n if (mod && typeof mod.createRequire === 'function') {\n const r = mod.createRequire(process.cwd() + '/package.json');\n const json = r(`${pkg}/package.json`);\n return json && json.version ? String(json.version) : undefined;\n }\n } catch {\n /* the dependency may simply not be installed */\n }\n return undefined;\n}\n\n/** Environment variable read that is safe in the browser. */\nexport function env(key: string): string | undefined {\n try {\n if (typeof process !== 'undefined' && process.env) {\n const v = process.env[key];\n return v == null || v === '' ? undefined : String(v);\n }\n } catch {\n /* ignore */\n }\n return undefined;\n}\n\n/**\n * CommonJS require that bundlers do not statically analyse. Returns undefined\n * in ESM-only or browser contexts instead of throwing.\n */\nfunction tryRequire(name: string): any {\n try {\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n const req: any =\n typeof module !== 'undefined' && typeof (module as any).require === 'function'\n ? (module as any).require\n : typeof (globalThis as any).require === 'function'\n ? (globalThis as any).require\n : undefined;\n return req ? req(name) : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Device/app context sent with every event. */\nexport function deviceInfo(): Record<string, unknown> {\n const out: Record<string, unknown> = {\n sdk: SDK_NAME,\n sdk_version: SDK_VERSION,\n runtime: runtimeName(),\n runtime_version: runtimeVersion(),\n };\n\n try {\n if (isBrowser) {\n out.user_agent = navigator.userAgent;\n out.language = navigator.language;\n out.screen = { width: window.screen?.width, height: window.screen?.height };\n out.viewport = { width: window.innerWidth, height: window.innerHeight };\n out.online = navigator.onLine;\n }\n if (isNode) {\n out.platform = process.platform;\n out.arch = process.arch;\n out.pid = process.pid;\n }\n } catch {\n /* ignore */\n }\n\n return out;\n}\n","import type {\n BugbanOptions,\n ConsoleOptions,\n NetworkOptions,\n ResolvedOptions,\n SnapshotOptions,\n VitalsOptions,\n} from './types';\nimport { env } from './env';\n\n/**\n * Option resolution.\n *\n * `true` / `false` / an object are all valid for each feature block, so the app\n * can write `console: true` or `console: { levels: [...] }`. Everything is\n * normalised here once, and the rest of the SDK only ever sees the full shape.\n */\n\nfunction section<T extends object>(\n value: boolean | T | undefined,\n defaults: Required<T>,\n defaultOn: boolean,\n): Required<T> | false {\n if (value === false) return false;\n if (value === true || value === undefined) return defaultOn || value === true ? defaults : false;\n return { ...defaults, ...(value as object) } as Required<T>;\n}\n\nconst CONSOLE_DEFAULTS: Required<ConsoleOptions> = {\n levels: ['log', 'info', 'warn', 'error', 'debug'],\n // Only console.error becomes an event. console.warn is far too noisy in a\n // typical app — React alone emits several per render in development.\n captureAsEvent: ['error'],\n};\n\nconst NETWORK_DEFAULTS: Required<NetworkOptions> = {\n enabled: true,\n captureFailures: true,\n ignoreUrls: [],\n};\n\nconst SNAPSHOT_DEFAULTS: Required<SnapshotOptions> = {\n enabled: true,\n // Never flipped to false by a preset. Turning this off ships whatever the\n // end user typed — passwords included — to the Bugban server, so it has to\n // be an explicit, deliberate line in the app's own config.\n maskInputs: true,\n maskSelectors: [],\n maxBytes: 500_000,\n};\n\nconst VITALS_DEFAULTS: Required<VitalsOptions> = {\n enabled: true,\n // Vitals describe the whole audience, not one error, so a sample is enough\n // and keeps ingest volume proportional to traffic.\n sampleRate: 0.2,\n longTaskMs: 100,\n slowResourceMs: 1000,\n};\n\nexport function resolveOptions(input: BugbanOptions = {}): ResolvedOptions {\n const apiKey = input.apiKey || env('BUGBAN_API_KEY') || env('NEXT_PUBLIC_BUGBAN_API_KEY') || '';\n const host =\n input.host ||\n env('BUGBAN_HOST') ||\n env('NEXT_PUBLIC_BUGBAN_HOST') ||\n 'https://bugban.online';\n\n return {\n ...input,\n apiKey,\n host: host.replace(/\\/+$/, ''),\n release: input.release || env('BUGBAN_RELEASE'),\n environment: input.environment || env('BUGBAN_ENV') || env('NODE_ENV') || 'production',\n // No key means no-op, exactly like the PHP SDK: an app that ships\n // without configuration must not error, it must simply do nothing.\n enabled: input.enabled !== false && apiKey !== '',\n debug: input.debug === true,\n maxBreadcrumbs: clamp(input.maxBreadcrumbs ?? 50, 1, 200),\n sampleRate: clamp(input.sampleRate ?? 1, 0, 1),\n\n console: section(input.console, CONSOLE_DEFAULTS, true),\n network: section(input.network, NETWORK_DEFAULTS, true),\n snapshot: section(input.snapshot, SNAPSHOT_DEFAULTS, true),\n vitals: section(input.vitals, VITALS_DEFAULTS, true),\n\n globalHandlers: input.globalHandlers !== false,\n domBreadcrumbs: input.domBreadcrumbs !== false,\n installPing: input.installPing !== false,\n\n redactKeys: input.redactKeys || [],\n ignoreErrors: input.ignoreErrors || [],\n };\n}\n\nfunction clamp(n: number, min: number, max: number): number {\n if (typeof n !== 'number' || isNaN(n)) return min;\n return Math.min(max, Math.max(min, n));\n}\n","/** Small helpers shared across the SDK. All of them are failure-tolerant. */\n\n/**\n * Run a function and swallow anything it throws.\n *\n * The SDK must never take the host application down — that rule is written in\n * blood after a PHP adapter crashed a customer's production site. Every entry\n * point into SDK code goes through this.\n */\nexport function safe<T>(fn: () => T, fallback?: T): T | undefined {\n try {\n return fn();\n } catch {\n return fallback;\n }\n}\n\nexport function nowIso(): string {\n try {\n return new Date().toISOString();\n } catch {\n return '';\n }\n}\n\nexport function truncate(value: unknown, max: number): string {\n const s = typeof value === 'string' ? value : stringify(value);\n return s.length > max ? s.slice(0, max) + '…' : s;\n}\n\n/** JSON.stringify that survives circular references and exotic values. */\nexport function stringify(value: unknown, max = 2000): string {\n try {\n const seen = new WeakSet<object>();\n const out = JSON.stringify(value, (_k, v) => {\n if (typeof v === 'bigint') return v.toString();\n if (typeof v === 'function') return '[Function]';\n if (v instanceof Error) return { name: v.name, message: v.message };\n if (typeof v === 'object' && v !== null) {\n if (seen.has(v)) return '[Circular]';\n seen.add(v);\n }\n return v;\n });\n if (out == null) return String(value);\n return out.length > max ? out.slice(0, max) + '…' : out;\n } catch {\n try {\n return String(value);\n } catch {\n return '[unserializable]';\n }\n }\n}\n\nexport function matchesAny(value: string, patterns: Array<string | RegExp>): boolean {\n for (const p of patterns) {\n try {\n if (typeof p === 'string') {\n if (value.indexOf(p) !== -1) return true;\n } else if (p.test(value)) {\n return true;\n }\n } catch {\n /* a bad pattern must not break matching */\n }\n }\n return false;\n}\n\n/** Deterministic-enough id for correlating a session's events. */\nexport function randomId(): string {\n try {\n const c: any = (globalThis as any).crypto;\n if (c && typeof c.randomUUID === 'function') return c.randomUUID();\n if (c && typeof c.getRandomValues === 'function') {\n const b = new Uint8Array(16);\n c.getRandomValues(b);\n return Array.from(b, (x) => x.toString(16).padStart(2, '0')).join('');\n }\n } catch {\n /* ignore */\n }\n // Math.random is fine here: this id only correlates telemetry, it is not\n // a security token.\n return Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\n/** 0..1 sample decision. rate >= 1 always passes, <= 0 never does. */\nexport function sampled(rate: number): boolean {\n if (rate >= 1) return true;\n if (rate <= 0) return false;\n return Math.random() < rate;\n}\n\n/** A CSS-ish selector for an element, used in click breadcrumbs and vitals. */\nexport function selectorFor(el: unknown): string | undefined {\n try {\n const node = el as any;\n if (!node || typeof node.tagName !== 'string') return undefined;\n let s = node.tagName.toLowerCase();\n if (node.id) return `${s}#${node.id}`;\n if (typeof node.className === 'string' && node.className.trim()) {\n const cls = node.className.trim().split(/\\s+/).slice(0, 2).join('.');\n if (cls) s += `.${cls}`;\n }\n return s;\n } catch {\n return undefined;\n }\n}\n","import { isBrowser, isNode, nodeModule } from './env';\nimport { safe } from './utils';\n\n/**\n * UTF-8 byte length without depending on Buffer (absent in edge runtimes) or\n * TextEncoder (absent in very old Node).\n */\nfunction byteLength(s: string): number {\n try {\n if (typeof TextEncoder === 'function') return new TextEncoder().encode(s).length;\n } catch {\n /* fall through */\n }\n try {\n const B: any = (globalThis as any).Buffer;\n if (B && typeof B.byteLength === 'function') return B.byteLength(s);\n } catch {\n /* fall through */\n }\n // Manual UTF-8 count — correct for the surrogate pairs emojis produce.\n let n = 0;\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i);\n if (c < 0x80) n += 1;\n else if (c < 0x800) n += 2;\n else if (c >= 0xd800 && c <= 0xdbff) {\n n += 4;\n i++;\n } else n += 3;\n }\n return n;\n}\n\n/**\n * Delivery of payloads to the Bugban ingest API.\n *\n * Mirrors the PHP SDK's transport philosophy: pick the best mechanism the\n * runtime offers, fall back automatically, and never block or throw. The\n * browser adds one concern PHP does not have — a page can be closing while a\n * request is in flight, which is what `sendBeacon` and `keepalive` exist for.\n */\n\nexport interface SendOptions {\n /** Use a delivery mechanism that survives page unload. */\n beacon?: boolean;\n timeoutMs?: number;\n}\n\nexport class Transport {\n constructor(\n private host: string,\n private apiKey: string,\n private debug = false,\n ) {}\n\n /** Fire-and-forget POST. Resolves to true when the server accepted it. */\n async send(path: string, body: unknown, opts: SendOptions = {}): Promise<boolean> {\n const url = this.host.replace(/\\/+$/, '') + path;\n let json: string;\n try {\n json = JSON.stringify(body);\n } catch {\n return false;\n }\n\n // Page-unload path: sendBeacon is the only mechanism the browser\n // guarantees to flush after the document goes away.\n if (opts.beacon && isBrowser) {\n const sent = safe(() => {\n const nav: any = navigator;\n if (typeof nav.sendBeacon !== 'function') return false;\n // sendBeacon cannot set headers, so the key travels in the body\n // as `_key` (the server accepts it there for exactly this case).\n // Not a query parameter — that would land in the access log.\n const blob = new Blob([JSON.stringify({ ...(body as object), _key: this.apiKey })], {\n type: 'application/json',\n });\n return nav.sendBeacon(url, blob);\n }, false);\n if (sent) return true;\n // fall through to fetch\n }\n\n if (typeof fetch === 'function') {\n return this.viaFetch(url, json, opts);\n }\n if (isNode) {\n return this.viaNodeHttp(url, json, opts);\n }\n\n this.log('no transport available');\n return false;\n }\n\n private async viaFetch(url: string, json: string, opts: SendOptions): Promise<boolean> {\n try {\n const controller =\n typeof AbortController === 'function' ? new AbortController() : undefined;\n const timer = controller\n ? setTimeout(() => safe(() => controller.abort()), opts.timeoutMs ?? 8000)\n : undefined;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Bugban-Key': this.apiKey,\n },\n body: json,\n // keepalive lets the request outlive the page in browsers that\n // support it; it is ignored elsewhere.\n keepalive: opts.beacon === true,\n signal: controller ? controller.signal : undefined,\n // Never send the site's cookies to Bugban.\n credentials: 'omit',\n mode: 'cors',\n } as RequestInit);\n\n if (timer) clearTimeout(timer);\n if (!res.ok) this.log('ingest rejected', res.status);\n return res.ok;\n } catch (e) {\n this.log('fetch failed', e);\n return false;\n }\n }\n\n /**\n * Node without global fetch — that is Node 17 and older, which a fair\n * number of customers still run in production. Uses the http/https module\n * loaded the bundler-opaque way, because `globalThis.require` does not\n * exist under ESM and this path would otherwise silently deliver nothing.\n */\n private async viaNodeHttp(url: string, json: string, opts: SendOptions): Promise<boolean> {\n const isHttps = url.indexOf('https://') === 0;\n const mod = await nodeModule(isHttps ? 'https' : 'http');\n if (!mod || typeof mod.request !== 'function') return false;\n\n return new Promise((resolve) => {\n try {\n const u = new URL(url);\n const req = mod.request(\n {\n method: 'POST',\n hostname: u.hostname,\n port: u.port || (isHttps ? 443 : 80),\n path: u.pathname + u.search,\n timeout: opts.timeoutMs ?? 8000,\n headers: {\n 'Content-Type': 'application/json',\n // Byte length, not string length — a multi-byte\n // message would otherwise truncate the body.\n 'Content-Length': byteLength(json),\n 'X-Bugban-Key': this.apiKey,\n },\n },\n (res: any) => {\n res.resume();\n resolve(res.statusCode >= 200 && res.statusCode < 300);\n },\n );\n req.on('error', () => resolve(false));\n req.on('timeout', () => {\n safe(() => req.destroy());\n resolve(false);\n });\n req.write(json);\n req.end();\n } catch {\n resolve(false);\n }\n });\n }\n\n private log(...args: unknown[]): void {\n if (!this.debug) return;\n safe(() => console.warn('[bugban]', ...args));\n }\n}\n","import type { Breadcrumb } from './types';\nimport { nowIso } from './utils';\n\n/**\n * Fixed-size ring buffer of recent activity.\n *\n * Breadcrumbs are what turn \"TypeError: cannot read x of undefined\" into a\n * story: the click, the route change, the 500 from /api/orders, then the\n * crash. The buffer is capped so a long-lived SPA session cannot grow it\n * without bound.\n */\nexport class BreadcrumbBuffer {\n private items: Breadcrumb[] = [];\n\n constructor(private max: number) {}\n\n add(crumb: Omit<Breadcrumb, 'timestamp'> & { timestamp?: string }): void {\n try {\n const full: Breadcrumb = {\n type: crumb.type,\n message: crumb.message,\n level: crumb.level,\n data: crumb.data,\n timestamp: crumb.timestamp || nowIso(),\n };\n this.items.push(full);\n if (this.items.length > this.max) {\n this.items.splice(0, this.items.length - this.max);\n }\n } catch {\n /* never let telemetry break the app */\n }\n }\n\n /** Snapshot for sending. Copied so a later push cannot mutate a sent event. */\n all(): Breadcrumb[] {\n return this.items.slice();\n }\n\n clear(): void {\n this.items = [];\n }\n\n setMax(max: number): void {\n this.max = max;\n if (this.items.length > max) {\n this.items.splice(0, this.items.length - max);\n }\n }\n}\n","import type { StackFrame } from './types';\n\n/**\n * Error.stack parsing.\n *\n * There is no standard for `Error.stack`, so this handles the three shapes that\n * matter in practice: V8 (Chrome/Node/Edge), SpiderMonkey (Firefox) and\n * JavaScriptCore (Safari). Anything unrecognised degrades to a single frame\n * carrying the raw line rather than being dropped — a partial stack still\n * beats none in the panel.\n */\n\n// V8: \" at fnName (/path/file.js:10:5)\" | \" at /path/file.js:10:5\"\nconst V8_LINE = /^\\s*at (?:(.+?)\\s+\\()?(?:(.+?):(\\d+):(\\d+)|([^)]+))\\)?\\s*$/;\n\n// Firefox/Safari: \"fnName@/path/file.js:10:5\" | \"@/path/file.js:10:5\"\nconst MOZ_LINE = /^\\s*(?:(.*?)@)?(.+?):(\\d+):(\\d+)\\s*$/;\n\n/** Frames from these paths are framework/vendor noise, collapsed in the panel. */\nconst VENDOR_PATTERNS = [\n 'node_modules',\n 'webpack-internal',\n 'webpack://',\n '/.next/',\n '/.nuxt/',\n 'node:internal',\n 'internal/process',\n];\n\nfunction isInApp(file?: string): boolean {\n if (!file) return false;\n for (const p of VENDOR_PATTERNS) {\n if (file.indexOf(p) !== -1) return false;\n }\n return true;\n}\n\nfunction toFrame(fn: string | undefined, file: string, line: string, col: string): StackFrame {\n const f: StackFrame = {\n file: file || undefined,\n line: line ? parseInt(line, 10) : undefined,\n column: col ? parseInt(col, 10) : undefined,\n in_app: isInApp(file),\n };\n if (fn && fn !== '<anonymous>') f.function = fn.trim();\n return f;\n}\n\nexport function parseStack(stack: unknown, limit = 50): StackFrame[] {\n if (typeof stack !== 'string' || stack === '') return [];\n\n const frames: StackFrame[] = [];\n const lines = stack.split('\\n');\n\n for (const raw of lines) {\n if (frames.length >= limit) break;\n const line = raw.replace(/\\r$/, '');\n if (!line.trim()) continue;\n // The first line is usually \"TypeError: message\" — not a frame.\n if (!/^\\s*at\\s/.test(line) && line.indexOf('@') === -1) continue;\n\n let m = V8_LINE.exec(line);\n if (m) {\n // Group 5 is the \"at /path:1:1\" form with no function name, in which\n // case the location still needs splitting off the tail.\n if (m[5] && !m[2]) {\n const loc = /^(.*?):(\\d+):(\\d+)$/.exec(m[5]);\n frames.push(\n loc\n ? toFrame(m[1], loc[1], loc[2], loc[3])\n : { function: m[1], file: m[5], in_app: isInApp(m[5]) },\n );\n } else {\n frames.push(toFrame(m[1], m[2] || '', m[3] || '', m[4] || ''));\n }\n continue;\n }\n\n m = MOZ_LINE.exec(line);\n if (m) {\n frames.push(toFrame(m[1], m[2] || '', m[3] || '', m[4] || ''));\n continue;\n }\n\n frames.push({ function: line.trim(), in_app: false });\n }\n\n return frames;\n}\n\n/**\n * Normalise anything a JS app can throw into an error-shaped object.\n * `throw 'a string'` and `Promise.reject({code: 500})` are both common; both\n * must produce a usable event rather than \"undefined\".\n */\nexport function normalizeError(input: unknown): {\n name: string;\n message: string;\n stack?: string;\n} {\n if (input instanceof Error) {\n return {\n name: input.name || 'Error',\n message: input.message || String(input),\n stack: input.stack,\n };\n }\n\n if (typeof input === 'string') return { name: 'Error', message: input };\n\n if (input && typeof input === 'object') {\n const o = input as any;\n // DOMException, ErrorEvent, and plain {name, message} objects.\n if (typeof o.message === 'string') {\n return {\n name: typeof o.name === 'string' ? o.name : 'Error',\n message: o.message,\n stack: typeof o.stack === 'string' ? o.stack : undefined,\n };\n }\n try {\n return { name: 'Error', message: JSON.stringify(o) };\n } catch {\n return { name: 'Error', message: '[object]' };\n }\n }\n\n return { name: 'Error', message: String(input) };\n}\n","import type { Snapshot, SnapshotOptions } from './types';\nimport { isBrowser } from './env';\nimport { nowIso } from './utils';\n\n/**\n * DOM snapshot taken at error time.\n *\n * This is deliberately NOT a pixel screenshot. Serializing the DOM is smaller\n * than an image, keeps text selectable, lets the panel inspect elements, and\n * needs no extra library (html2canvas would add ~200KB to every customer's\n * bundle and still mis-renders modern CSS). The trade-off is that canvas and\n * video content come back blank — an acceptable loss for debugging layout and\n * state at the moment of failure.\n *\n * PRIVACY: this leaves the end user's screen and lands on the Bugban server.\n * `maskInputs` defaults to true and every form value is replaced before\n * serialization. Turning it off is a conscious choice the developer makes.\n */\n\nconst MASK_CHAR = '•';\n\n/** Elements that carry no visual meaning or would re-execute on replay. */\nconst DROP_TAGS = ['SCRIPT', 'NOSCRIPT', 'TEMPLATE'];\n\nfunction maskValue(value: string): string {\n const len = Math.min(value.length, 12);\n return len > 0 ? MASK_CHAR.repeat(len) : '';\n}\n\n/**\n * Replace form values in the CLONE. Inputs are the highest-risk content on a\n * page: passwords, card numbers, personal details, search terms.\n */\nfunction maskFormFields(root: Element): void {\n const fields = root.querySelectorAll('input, textarea, select');\n for (let i = 0; i < fields.length; i++) {\n const el = fields[i] as HTMLInputElement;\n try {\n const type = (el.getAttribute('type') || '').toLowerCase();\n\n // A password field's length is itself a hint — use a fixed mask.\n if (type === 'password') {\n el.setAttribute('value', MASK_CHAR.repeat(8));\n continue;\n }\n // Checkboxes/radios carry no free text; keep their state.\n if (type === 'checkbox' || type === 'radio' || type === 'submit' || type === 'button') {\n continue;\n }\n\n const current = el.getAttribute('value') || '';\n if (current) el.setAttribute('value', maskValue(current));\n\n if (el.tagName === 'TEXTAREA' && el.textContent) {\n el.textContent = maskValue(el.textContent);\n }\n } catch {\n /* keep going — one bad node must not lose the whole snapshot */\n }\n }\n}\n\n/** Blank out anything the developer flagged as sensitive. */\nfunction maskSelectors(root: Element, selectors: string[]): void {\n for (const sel of selectors) {\n try {\n const nodes = root.querySelectorAll(sel);\n for (let i = 0; i < nodes.length; i++) {\n const el = nodes[i] as HTMLElement;\n if (el.textContent) el.textContent = MASK_CHAR.repeat(6);\n }\n } catch {\n /* an invalid selector is the developer's typo, not a crash */\n }\n }\n}\n\n/**\n * Copy live form state onto the clone's attributes.\n *\n * `cloneNode` copies attributes, not properties — a user-typed value lives in\n * `el.value` and would vanish. Copying it first, then masking, means the\n * snapshot shows \"a filled field\" rather than an empty one.\n */\nfunction materializeFormState(source: Element, clone: Element): void {\n try {\n const src = source.querySelectorAll('input, textarea, select');\n const dst = clone.querySelectorAll('input, textarea, select');\n const n = Math.min(src.length, dst.length);\n for (let i = 0; i < n; i++) {\n const s = src[i] as HTMLInputElement;\n const d = dst[i] as HTMLInputElement;\n if (s.tagName === 'SELECT') {\n d.setAttribute('data-bugban-selected', String((s as unknown as HTMLSelectElement).selectedIndex));\n continue;\n }\n if (typeof s.value === 'string' && s.value !== '') d.setAttribute('value', s.value);\n if (s.checked) d.setAttribute('checked', 'checked');\n }\n } catch {\n /* ignore */\n }\n}\n\n/** Concatenate same-origin stylesheet text so the replay renders standalone. */\nfunction collectCss(maxBytes: number): string {\n let css = '';\n try {\n const sheets = document.styleSheets;\n for (let i = 0; i < sheets.length; i++) {\n if (css.length > maxBytes) break;\n try {\n // Cross-origin sheets throw on cssRules access — expected, skip.\n const rules = (sheets[i] as CSSStyleSheet).cssRules;\n if (!rules) continue;\n for (let j = 0; j < rules.length; j++) {\n css += rules[j].cssText + '\\n';\n if (css.length > maxBytes) break;\n }\n } catch {\n continue;\n }\n }\n } catch {\n /* ignore */\n }\n return css.length > maxBytes ? css.slice(0, maxBytes) : css;\n}\n\nexport function takeSnapshot(opts: Required<SnapshotOptions>): Snapshot | null {\n if (!isBrowser || !opts.enabled) return null;\n\n try {\n const source = document.documentElement;\n if (!source) return null;\n\n const clone = source.cloneNode(true) as Element;\n\n // Order matters: materialize live values first, then mask them.\n materializeFormState(source, clone);\n if (opts.maskInputs) maskFormFields(clone);\n if (opts.maskSelectors && opts.maskSelectors.length) {\n maskSelectors(clone, opts.maskSelectors);\n }\n\n for (const tag of DROP_TAGS) {\n const nodes = clone.getElementsByTagName(tag);\n // Live HTMLCollection shrinks as we remove — always take index 0.\n while (nodes.length > 0) {\n const n = nodes[0];\n if (n.parentNode) n.parentNode.removeChild(n);\n else break;\n }\n }\n\n // A <base> makes relative asset URLs resolve against the original page\n // when the panel renders the snapshot from a different origin.\n try {\n const head = clone.querySelector('head');\n if (head && !head.querySelector('base')) {\n const base = document.createElement('base');\n base.setAttribute('href', document.baseURI || location.href);\n head.insertBefore(base, head.firstChild);\n }\n } catch {\n /* ignore */\n }\n\n let html = clone.outerHTML || '';\n if (html.length > opts.maxBytes) {\n // Oversized pages are dropped rather than truncated: half a DOM\n // renders as garbage and would be more confusing than nothing.\n return null;\n }\n\n const css = collectCss(Math.max(0, opts.maxBytes - html.length));\n\n return {\n kind: 'dom',\n html,\n css: css || undefined,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n scrollX: window.scrollX || 0,\n scrollY: window.scrollY || 0,\n },\n url: location.href,\n taken_at: nowIso(),\n };\n } catch {\n return null;\n }\n}\n","import type { VitalMetric, VitalsOptions } from './types';\nimport { isBrowser } from './env';\nimport { nowIso, safe, selectorFor } from './utils';\n\n/**\n * Web Vitals and render-performance collection.\n *\n * This is the browser's answer to the \"why is my page slow, what do I do about\n * it\" question — the same role slow-query capture plays on the server side.\n * Everything here rides on PerformanceObserver, which the browser computes\n * anyway, so the CPU cost is effectively zero. No external dependency: the\n * web-vitals package would add weight for logic that is a few hundred lines.\n *\n * Metrics are buffered and flushed once, when the page is hidden. A page load\n * has no single \"done\" moment — LCP and CLS keep changing until the user\n * leaves — so reporting early would report the wrong number.\n */\n\n// Google's good / needs-improvement thresholds. Above the second value is poor.\nconst THRESHOLDS: Record<string, [number, number]> = {\n LCP: [2500, 4000],\n FCP: [1800, 3000],\n CLS: [0.1, 0.25],\n INP: [200, 500],\n TTFB: [800, 1800],\n};\n\nexport function rate(name: string, value: number): VitalMetric['rating'] | undefined {\n const t = THRESHOLDS[name];\n if (!t) return undefined;\n if (value <= t[0]) return 'good';\n if (value <= t[1]) return 'needs-improvement';\n return 'poor';\n}\n\ntype Flush = (metrics: VitalMetric[]) => void;\n\nexport class VitalsCollector {\n private metrics: VitalMetric[] = [];\n private observers: PerformanceObserver[] = [];\n private flushed = false;\n /** LCP/CLS/INP are \"final value wins\" — keyed so later values replace. */\n private latest: Record<string, VitalMetric> = {};\n\n constructor(\n private opts: Required<VitalsOptions>,\n private flush: Flush,\n ) {}\n\n start(): void {\n if (!isBrowser || !this.opts.enabled) return;\n if (typeof PerformanceObserver !== 'function') return;\n\n this.observeTtfb();\n this.observePaint();\n this.observeLcp();\n this.observeCls();\n this.observeInp();\n this.observeLongTasks();\n this.observeResources();\n this.installFlushTriggers();\n }\n\n stop(): void {\n for (const o of this.observers) safe(() => o.disconnect());\n this.observers = [];\n }\n\n /** Manually add a metric — adapters use this for component render times. */\n push(metric: VitalMetric): void {\n try {\n this.metrics.push({\n ...metric,\n rating: metric.rating ?? rate(metric.name, metric.value),\n url: metric.url ?? location.href,\n occurred_at: metric.occurred_at ?? nowIso(),\n });\n } catch {\n /* ignore */\n }\n }\n\n private set(name: string, value: number, extra: Partial<VitalMetric> = {}): void {\n this.latest[name] = {\n name,\n value: Math.round(value * 1000) / 1000,\n rating: rate(name, value),\n url: safe(() => location.href),\n occurred_at: nowIso(),\n ...extra,\n };\n }\n\n private observe(type: string, cb: (entries: PerformanceEntryList) => void, buffered = true): void {\n safe(() => {\n const obs = new PerformanceObserver((list) => safe(() => cb(list.getEntries())));\n // `buffered` replays entries that fired before the SDK loaded —\n // without it, a late-initialised SDK misses FCP and LCP entirely.\n obs.observe({ type, buffered } as PerformanceObserverInit);\n this.observers.push(obs);\n });\n }\n\n private observeTtfb(): void {\n safe(() => {\n const nav = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming;\n if (nav && typeof nav.responseStart === 'number' && nav.responseStart > 0) {\n this.set('TTFB', nav.responseStart, { navigation_type: nav.type });\n }\n });\n }\n\n private observePaint(): void {\n this.observe('paint', (entries) => {\n for (const e of entries) {\n if (e.name === 'first-contentful-paint') this.set('FCP', e.startTime);\n }\n });\n }\n\n private observeLcp(): void {\n this.observe('largest-contentful-paint', (entries) => {\n // Only the LAST entry counts: the browser keeps upgrading its guess\n // at the largest element as more content paints.\n const last: any = entries[entries.length - 1];\n if (!last) return;\n this.set('LCP', last.startTime, {\n target: selectorFor(last.element),\n data: { size: last.size, url: last.url || undefined },\n });\n });\n }\n\n private observeCls(): void {\n let clsValue = 0;\n let sessionValue = 0;\n let sessionEntries: any[] = [];\n\n this.observe('layout-shift', (entries) => {\n for (const entry of entries as any[]) {\n // Shifts the user caused (typing, clicking) are not penalised.\n if (entry.hadRecentInput) continue;\n\n const first = sessionEntries[0];\n const last = sessionEntries[sessionEntries.length - 1];\n\n // CLS is the worst 5-second / 1-second-gap window, not the sum\n // of everything — a long session would otherwise always fail.\n if (\n sessionValue &&\n entry.startTime - last.startTime < 1000 &&\n entry.startTime - first.startTime < 5000\n ) {\n sessionValue += entry.value;\n sessionEntries.push(entry);\n } else {\n sessionValue = entry.value;\n sessionEntries = [entry];\n }\n\n if (sessionValue > clsValue) {\n clsValue = sessionValue;\n const worst = sessionEntries\n .slice()\n .sort((a, b) => b.value - a.value)[0];\n this.set('CLS', clsValue, {\n target: worst?.sources?.[0]\n ? selectorFor(worst.sources[0].node)\n : undefined,\n });\n }\n }\n });\n }\n\n private observeInp(): void {\n let worst = 0;\n this.observe('event', (entries) => {\n for (const entry of entries as any[]) {\n const duration = entry.duration;\n if (typeof duration !== 'number' || duration <= worst) continue;\n worst = duration;\n this.set('INP', duration, {\n target: selectorFor(entry.target),\n data: { interaction: entry.name },\n });\n }\n });\n }\n\n private observeLongTasks(): void {\n this.observe('longtask', (entries) => {\n for (const e of entries) {\n if (e.duration < this.opts.longTaskMs) continue;\n this.push({\n name: 'LONG_TASK',\n value: Math.round(e.duration),\n rating: e.duration > 200 ? 'poor' : 'needs-improvement',\n target: (e as any).attribution?.[0]?.containerName || undefined,\n data: { start: Math.round(e.startTime) },\n });\n }\n });\n }\n\n private observeResources(): void {\n this.observe('resource', (entries) => {\n for (const e of entries as PerformanceResourceTiming[]) {\n if (e.duration < this.opts.slowResourceMs) continue;\n // Our own ingest calls are not the customer's problem.\n if (e.name.indexOf('/api/ingest/') !== -1) continue;\n this.push({\n name: 'RESOURCE',\n value: Math.round(e.duration),\n rating: e.duration > 3000 ? 'poor' : 'needs-improvement',\n target: e.name,\n data: {\n type: e.initiatorType,\n size: e.transferSize || undefined,\n cached: e.transferSize === 0 && e.decodedBodySize > 0,\n },\n });\n }\n });\n }\n\n /**\n * Flush when the page is hidden. `visibilitychange` fires reliably on\n * mobile where `beforeunload` often does not; `pagehide` covers bfcache.\n */\n private installFlushTriggers(): void {\n const doFlush = () => this.flushNow();\n safe(() => {\n document.addEventListener(\n 'visibilitychange',\n () => {\n if (document.visibilityState === 'hidden') doFlush();\n },\n { capture: true },\n );\n window.addEventListener('pagehide', doFlush, { capture: true });\n });\n }\n\n flushNow(): void {\n if (this.flushed) return;\n try {\n const all = this.metrics.concat(Object.keys(this.latest).map((k) => this.latest[k]));\n if (all.length === 0) return;\n this.flushed = true;\n this.metrics = [];\n this.latest = {};\n this.flush(all);\n } catch {\n /* ignore */\n }\n }\n}\n","import type { ConsoleOptions, Level } from '../types';\nimport { safe, truncate } from '../utils';\n\n/**\n * console.* interception.\n *\n * Most real-world failures never reach window.onerror: the app catches the\n * error, logs it with console.error, and shows a generic \"something went\n * wrong\". Those are exactly the ones a developer wants reported, so\n * console.error becomes a first-class event, not just a breadcrumb.\n *\n * The original console methods are always called — the developer's own logging\n * must behave identically with the SDK installed.\n */\n\nexport interface ConsoleHooks {\n breadcrumb: (level: Level, message: string, args: unknown[]) => void;\n capture: (level: Level, message: string, args: unknown[]) => void;\n}\n\nconst LEVEL_MAP: Record<string, Level> = {\n log: 'info',\n info: 'info',\n debug: 'debug',\n warn: 'warning',\n error: 'error',\n};\n\nexport function installConsole(opts: Required<ConsoleOptions>, hooks: ConsoleHooks): () => void {\n if (typeof console === 'undefined') return () => {};\n\n const originals: Record<string, any> = {};\n // Re-entrancy guard: if a hook itself logs (or the transport warns in debug\n // mode), we must not recurse into our own interceptor.\n let inside = false;\n\n for (const method of opts.levels) {\n const original = (console as any)[method];\n if (typeof original !== 'function') continue;\n originals[method] = original;\n\n (console as any)[method] = function (...args: unknown[]) {\n try {\n if (!inside) {\n inside = true;\n const level = LEVEL_MAP[method] || 'info';\n const message = args\n .map((a) => (typeof a === 'string' ? a : truncate(a, 200)))\n .join(' ');\n\n hooks.breadcrumb(level, truncate(message, 500), args);\n\n if (\n (method === 'error' || method === 'warn') &&\n opts.captureAsEvent.indexOf(method as 'error' | 'warn') !== -1\n ) {\n hooks.capture(level, message, args);\n }\n inside = false;\n }\n } catch {\n inside = false;\n }\n\n // Always pass through to the real console.\n return safe(() => original.apply(console, args));\n };\n }\n\n return () => {\n for (const m in originals) {\n safe(() => {\n (console as any)[m] = originals[m];\n });\n }\n };\n}\n","/**\n * PII / secret redaction.\n *\n * The SDK sends request metadata and breadcrumbs to a server the developer\n * controls but their end users do not. Anything that looks like a credential\n * is replaced before it leaves the process. This runs on data the SDK collects\n * itself AND on data the app hands us via setContext/addBreadcrumb.\n */\n\nexport const DEFAULT_REDACT_KEYS = [\n 'password',\n 'passwd',\n 'pwd',\n 'secret',\n 'token',\n 'access_token',\n 'refresh_token',\n 'api_key',\n 'apikey',\n 'authorization',\n 'auth',\n 'cookie',\n 'set-cookie',\n 'session',\n 'csrf',\n 'xsrf',\n 'card',\n 'card_number',\n 'cardnumber',\n 'cvv',\n 'cvc',\n 'pin',\n 'ssn',\n 'iban',\n];\n\nexport const REDACTED = '[redacted]';\n\nfunction isSensitiveKey(key: string, extra: string[]): boolean {\n const k = key.toLowerCase();\n for (const s of DEFAULT_REDACT_KEYS) {\n if (k.indexOf(s) !== -1) return true;\n }\n for (const s of extra) {\n if (s && k.indexOf(s.toLowerCase()) !== -1) return true;\n }\n return false;\n}\n\n/**\n * Deep-redact an object by key name. Depth-limited so a pathological structure\n * cannot lock up the main thread.\n */\nexport function redact<T>(value: T, extraKeys: string[] = [], depth = 0): T {\n if (depth > 6 || value == null) return value;\n\n try {\n if (Array.isArray(value)) {\n return value.slice(0, 100).map((v) => redact(v, extraKeys, depth + 1)) as unknown as T;\n }\n if (typeof value === 'object') {\n const src = value as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n let count = 0;\n for (const key in src) {\n if (!Object.prototype.hasOwnProperty.call(src, key)) continue;\n if (++count > 100) break;\n out[key] = isSensitiveKey(key, extraKeys)\n ? REDACTED\n : redact(src[key], extraKeys, depth + 1);\n }\n return out as unknown as T;\n }\n } catch {\n /* fall through — return the value untouched rather than crash */\n }\n\n return value;\n}\n\n/**\n * Strip credentials out of a URL: query params named like secrets, plus any\n * user:pass@ prefix. Returns the input unchanged if it cannot be parsed.\n */\nexport function redactUrl(url: string, extraKeys: string[] = []): string {\n try {\n // Relative URLs need a base to parse; the base is discarded after.\n const hasScheme = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(url);\n const u = new URL(url, hasScheme ? undefined : 'http://localhost');\n\n if (u.username || u.password) {\n u.username = '';\n u.password = '';\n }\n u.searchParams.forEach((_v, k) => {\n if (isSensitiveKey(k, extraKeys)) u.searchParams.set(k, REDACTED);\n });\n\n return hasScheme ? u.toString() : u.pathname + u.search + u.hash;\n } catch {\n return url;\n }\n}\n\n/** Header maps arrive in several shapes (Headers, array pairs, plain object). */\nexport function redactHeaders(\n headers: unknown,\n extraKeys: string[] = [],\n): Record<string, string> | undefined {\n try {\n const out: Record<string, string> = {};\n const put = (k: string, v: unknown) => {\n out[k] = isSensitiveKey(k, extraKeys) ? REDACTED : String(v);\n };\n\n const h = headers as any;\n if (!h) return undefined;\n\n if (typeof h.forEach === 'function' && typeof h.get === 'function') {\n h.forEach((v: unknown, k: string) => put(k, v));\n return out;\n }\n if (Array.isArray(h)) {\n for (const pair of h) {\n if (Array.isArray(pair) && pair.length >= 2) put(String(pair[0]), pair[1]);\n }\n return out;\n }\n if (typeof h === 'object') {\n for (const k in h) {\n if (Object.prototype.hasOwnProperty.call(h, k)) put(k, h[k]);\n }\n return out;\n }\n } catch {\n /* ignore */\n }\n return undefined;\n}\n","import type { NetworkOptions } from '../types';\nimport { matchesAny, safe } from '../utils';\nimport { redactUrl } from '../redact';\n\n/**\n * fetch / XMLHttpRequest instrumentation.\n *\n * \"The button did nothing\" is almost always a failed request. Recording method,\n * URL, status and duration turns that into an obvious answer. Request and\n * response BODIES are never captured — they are the most likely place for\n * personal data, and the status code alone answers the question.\n */\n\nexport interface NetworkHooks {\n breadcrumb: (message: string, data: Record<string, unknown>, failed: boolean) => void;\n capture: (message: string, data: Record<string, unknown>) => void;\n}\n\nexport function installNetwork(\n opts: Required<NetworkOptions>,\n hooks: NetworkHooks,\n redactKeys: string[],\n ownHost: string,\n): () => void {\n const undo: Array<() => void> = [];\n\n const ignored = (url: string): boolean => {\n // Never record our own ingest traffic: it would create a feedback loop\n // where reporting an error generates a breadcrumb that is then reported.\n if (url.indexOf('/api/ingest/') !== -1) return true;\n if (ownHost && url.indexOf(ownHost) === 0) return true;\n return matchesAny(url, opts.ignoreUrls);\n };\n\n const record = (\n method: string,\n rawUrl: string,\n status: number | undefined,\n startedAt: number,\n errored: boolean,\n ) => {\n try {\n const url = redactUrl(rawUrl, redactKeys);\n const duration = Math.round(now() - startedAt);\n const failed = errored || (typeof status === 'number' && status >= 400);\n\n const data: Record<string, unknown> = {\n method,\n url,\n status_code: status,\n duration_ms: duration,\n };\n\n const label = `${method} ${url} → ${errored ? 'failed' : status} (${duration}ms)`;\n hooks.breadcrumb(label, data, failed);\n\n // A 5xx or a transport failure is a real incident; a 404 usually is\n // not, so only the former becomes its own event.\n if (opts.captureFailures && (errored || (status !== undefined && status >= 500))) {\n hooks.capture(label, data);\n }\n } catch {\n /* ignore */\n }\n };\n\n if (opts.enabled && typeof fetch === 'function') {\n const original = fetch;\n const patched = function (this: unknown, input: any, init?: any) {\n let url = '';\n let method = 'GET';\n const started = now();\n\n try {\n url = typeof input === 'string' ? input : input && input.url ? input.url : String(input);\n method = String((init && init.method) || (input && input.method) || 'GET').toUpperCase();\n } catch {\n /* ignore */\n }\n\n if (!url || ignored(url)) return original.apply(this as any, [input, init] as any);\n\n return original.apply(this as any, [input, init] as any).then(\n (res: Response) => {\n record(method, url, res ? res.status : undefined, started, false);\n return res;\n },\n (err: unknown) => {\n record(method, url, undefined, started, true);\n throw err;\n },\n );\n };\n (globalThis as any).fetch = patched;\n undo.push(() => {\n (globalThis as any).fetch = original;\n });\n }\n\n if (opts.enabled && typeof XMLHttpRequest === 'function') {\n const proto = XMLHttpRequest.prototype as any;\n const origOpen = proto.open;\n const origSend = proto.send;\n\n proto.open = function (method: string, url: string, ...rest: unknown[]) {\n safe(() => {\n this.__bugban = { method: String(method || 'GET').toUpperCase(), url: String(url || '') };\n });\n return origOpen.apply(this, [method, url, ...rest] as any);\n };\n\n proto.send = function (...args: unknown[]) {\n const meta = safe(() => this.__bugban) as { method: string; url: string } | undefined;\n if (meta && meta.url && !ignored(meta.url)) {\n const started = now();\n safe(() => {\n this.addEventListener('loadend', () => {\n // status 0 means the request never completed (CORS,\n // offline, aborted) — that is a failure, not a 0 code.\n const status = this.status || undefined;\n record(meta.method, meta.url, status, started, !status);\n });\n });\n }\n return origSend.apply(this, args as any);\n };\n\n undo.push(() => {\n proto.open = origOpen;\n proto.send = origSend;\n });\n }\n\n return () => {\n for (const fn of undo) safe(fn);\n };\n}\n\nfunction now(): number {\n try {\n return typeof performance !== 'undefined' && typeof performance.now === 'function'\n ? performance.now()\n : Date.now();\n } catch {\n return Date.now();\n }\n}\n","import { isBrowser, isNode } from '../env';\nimport { safe } from '../utils';\n\n/**\n * Global error handlers.\n *\n * Browser: window.onerror and unhandledrejection. Node: uncaughtException and\n * unhandledRejection.\n *\n * The Node side deliberately does NOT swallow a fatal error. Keeping a process\n * alive after an uncaught exception leaves it in an undefined state; the SDK's\n * job is to report and then let the default behaviour happen. This is the same\n * lesson the PHP SDK carries: telemetry must never change how the host app\n * behaves.\n */\n\nexport interface GlobalHooks {\n capture: (error: unknown, extra: { handled: boolean; type?: string }) => void;\n /** Give the transport a moment to flush before the process dies. */\n flush: () => Promise<void>;\n}\n\nexport function installGlobalHandlers(hooks: GlobalHooks): () => void {\n const undo: Array<() => void> = [];\n\n if (isBrowser) {\n const onError = (event: ErrorEvent) => {\n safe(() => {\n // event.error carries the real stack; message-only events (e.g.\n // cross-origin \"Script error.\") still produce a usable record.\n const err =\n event.error ||\n ({\n name: 'Error',\n message: event.message,\n stack: undefined,\n } as any);\n hooks.capture(err, { handled: false, type: 'onerror' });\n });\n };\n\n const onRejection = (event: PromiseRejectionEvent) => {\n safe(() => {\n const reason = (event as any).reason;\n hooks.capture(reason, { handled: false, type: 'unhandledrejection' });\n });\n };\n\n safe(() => window.addEventListener('error', onError, true));\n safe(() => window.addEventListener('unhandledrejection', onRejection as any, true));\n\n undo.push(() => {\n safe(() => window.removeEventListener('error', onError, true));\n safe(() => window.removeEventListener('unhandledrejection', onRejection as any, true));\n });\n }\n\n if (isNode) {\n const onUncaught = (err: unknown) => {\n hooks.capture(err, { handled: false, type: 'uncaughtException' });\n // Flush, then re-raise the default behaviour. If another listener is\n // registered, Node will not exit on its own — that is the host's\n // choice and we must not override it.\n safe(() => {\n void hooks.flush().then(() => {\n if (process.listenerCount('uncaughtException') <= 1) {\n process.exit(1);\n }\n });\n });\n };\n\n const onUnhandled = (reason: unknown) => {\n hooks.capture(reason, { handled: false, type: 'unhandledRejection' });\n };\n\n safe(() => process.on('uncaughtException', onUncaught));\n safe(() => process.on('unhandledRejection', onUnhandled));\n // Best-effort flush of anything still queued at normal shutdown.\n safe(() => process.on('beforeExit', () => void hooks.flush()));\n\n undo.push(() => {\n safe(() => process.off('uncaughtException', onUncaught));\n safe(() => process.off('unhandledRejection', onUnhandled));\n });\n }\n\n return () => {\n for (const fn of undo) safe(fn);\n };\n}\n","import { isBrowser } from '../env';\nimport { safe, selectorFor, truncate } from '../utils';\n\n/**\n * Click and navigation breadcrumbs.\n *\n * These are the \"what was the user doing\" half of the story. Only the element's\n * selector and its visible label are recorded — never the value of any field\n * the user typed into.\n *\n * SPA route changes do not fire a page load, so history.pushState/replaceState\n * are wrapped as well; without that a React or Vue app looks like it never\n * navigates.\n */\n\nexport interface DomHooks {\n click: (label: string, data: Record<string, unknown>) => void;\n navigate: (from: string, to: string) => void;\n}\n\n/** A short human label for a clicked element, safe to record. */\nfunction labelFor(el: Element): string {\n return (\n safe(() => {\n const aria = el.getAttribute('aria-label');\n if (aria) return truncate(aria, 60);\n\n const tag = el.tagName.toLowerCase();\n // Inputs: the label is the placeholder or name, NEVER the value.\n if (tag === 'input' || tag === 'textarea' || tag === 'select') {\n const ph = el.getAttribute('placeholder') || el.getAttribute('name') || '';\n return ph ? `${tag}[${truncate(ph, 40)}]` : tag;\n }\n\n const text = (el.textContent || '').trim().replace(/\\s+/g, ' ');\n return text ? truncate(text, 60) : tag;\n }) || 'element'\n );\n}\n\nexport function installDomBreadcrumbs(hooks: DomHooks): () => void {\n if (!isBrowser) return () => {};\n\n const undo: Array<() => void> = [];\n\n const onClick = (event: Event) => {\n safe(() => {\n const target = event.target as Element;\n if (!target || typeof (target as any).tagName !== 'string') return;\n\n // Walk up to the nearest interactive ancestor: a click usually\n // lands on the <span> inside a <button>, which is not the story.\n let el: Element | null = target;\n for (let i = 0; i < 4 && el; i++) {\n const tag = el.tagName.toLowerCase();\n if (tag === 'button' || tag === 'a' || el.getAttribute('role') === 'button') break;\n el = el.parentElement;\n }\n const chosen = el || target;\n\n hooks.click(labelFor(chosen), {\n selector: selectorFor(chosen),\n href: safe(() => chosen.getAttribute('href')) || undefined,\n });\n });\n };\n\n safe(() => document.addEventListener('click', onClick, { capture: true, passive: true }));\n undo.push(() => safe(() => document.removeEventListener('click', onClick, true)));\n\n // --- SPA navigation -----------------------------------------------------\n let current = safe(() => location.href) || '';\n\n const report = () => {\n safe(() => {\n const next = location.href;\n if (next !== current) {\n hooks.navigate(current, next);\n current = next;\n }\n });\n };\n\n safe(() => {\n const history = window.history as any;\n const origPush = history.pushState;\n const origReplace = history.replaceState;\n\n if (typeof origPush === 'function') {\n history.pushState = function (...args: unknown[]) {\n const r = origPush.apply(this, args as any);\n report();\n return r;\n };\n undo.push(() => {\n history.pushState = origPush;\n });\n }\n if (typeof origReplace === 'function') {\n history.replaceState = function (...args: unknown[]) {\n const r = origReplace.apply(this, args as any);\n report();\n return r;\n };\n undo.push(() => {\n history.replaceState = origReplace;\n });\n }\n });\n\n safe(() => window.addEventListener('popstate', report));\n undo.push(() => safe(() => window.removeEventListener('popstate', report)));\n\n return () => {\n for (const fn of undo) safe(fn);\n };\n}\n","import type { ResolvedOptions } from './types';\nimport type { Transport } from './transport';\nimport {\n SDK_NAME,\n SDK_VERSION,\n appPackageInfo,\n hostname,\n isBrowser,\n isNode,\n runtimeName,\n runtimeVersion,\n} from './env';\nimport { safe } from './utils';\n\n/**\n * One-time install ping.\n *\n * The panel needs to distinguish \"the SDK is installed and quiet\" from \"the SDK\n * was never wired up\" — otherwise a correctly working integration looks\n * identical to a broken one. This is the same handshake the PHP SDK sends;\n * `POST /api/ingest/ping` fills first_ping_at / last_ping_at / sdk_info and the\n * project page turns into \"SDK connected ✓\".\n *\n * Fires at most once per install. The marker differs by runtime because there\n * is no shared notion of persistent state: a temp file in Node, localStorage\n * in the browser (falling back to a per-page in-memory flag in private mode).\n */\n\nconst MARKER_KEY = 'bugban.ping';\nlet memoryMarker = false;\n\nasync function alreadyPinged(apiKey: string, version: string): Promise<boolean> {\n const stamp = `${apiKey.slice(0, 12)}:${version}`;\n\n if (isBrowser) {\n const stored = safe(() => localStorage.getItem(MARKER_KEY));\n if (stored === stamp) return true;\n safe(() => localStorage.setItem(MARKER_KEY, stamp));\n // Private mode throws on setItem — fall back to once per page load\n // rather than pinging on every single error.\n if (memoryMarker) return true;\n memoryMarker = true;\n return false;\n }\n\n if (isNode) {\n try {\n const [fs, os, path] = await Promise.all([\n nodeModule('fs'),\n nodeModule('os'),\n nodeModule('path'),\n ]);\n if (!fs || !os || !path || typeof fs.existsSync !== 'function') {\n // No filesystem access (bundled/edge runtime): degrade to\n // once per process instead of pinging on every error.\n if (memoryMarker) return true;\n memoryMarker = true;\n return false;\n }\n const key = toHex(stamp).slice(0, 32);\n const file = path.join(os.tmpdir(), `.bugban-ping-${key}`);\n if (fs.existsSync(file)) return true;\n fs.writeFileSync(file, stamp);\n return false;\n } catch {\n return false;\n }\n }\n\n if (memoryMarker) return true;\n memoryMarker = true;\n return false;\n}\n\n/** Buffer is not guaranteed outside Node, so the marker name is hashed by hand. */\nfunction toHex(s: string): string {\n let out = '';\n for (let i = 0; i < s.length; i++) {\n out += s.charCodeAt(i).toString(16);\n }\n return out;\n}\n\nexport async function sendInstallPing(opts: ResolvedOptions, transport: Transport): Promise<void> {\n if (!opts.installPing || !opts.enabled) return;\n\n try {\n if (await alreadyPinged(opts.apiKey, SDK_VERSION)) return;\n\n const pkg = await appPackageInfo();\n const host = await hostname();\n\n const payload: Record<string, unknown> = {\n sdk: SDK_NAME,\n sdk_version: SDK_VERSION,\n framework: opts.framework || runtimeName(),\n framework_version: opts.frameworkVersion,\n environment: opts.environment,\n hostname: host,\n\n // The app's own identity. In Node this is read from package.json; in\n // the browser there is no filesystem, so it comes from `release`\n // (usually wired to the bundler's define) and the page host.\n app_name: pkg.name || (isBrowser ? safe(() => location.hostname) : undefined),\n app_version: opts.release || pkg.version,\n\n // Where the SDK is running, and that runtime's version: Node's\n // process.version, or the browser UA. The panel shows this the same\n // way it shows the PHP version for the PHP SDKs.\n runtime: runtimeName(),\n runtime_version: runtimeVersion(),\n };\n\n // Drop empty fields so a sparse ping never overwrites what the server\n // already learned from a richer one.\n for (const k in payload) {\n if (payload[k] == null || payload[k] === '') delete payload[k];\n }\n\n void transport.send('/api/ingest/ping', payload);\n } catch {\n // A failed handshake must never surface to the host application.\n }\n}\n","import type {\n Breadcrumb,\n BugbanEvent,\n BugbanOptions,\n Level,\n ResolvedOptions,\n UserInfo,\n VitalMetric,\n} from './types';\nimport { resolveOptions } from './config';\nimport { Transport } from './transport';\nimport { BreadcrumbBuffer } from './breadcrumbs';\nimport { normalizeError, parseStack } from './stacktrace';\nimport { takeSnapshot } from './snapshot';\nimport { VitalsCollector } from './vitals';\nimport { installConsole } from './integrations/console';\nimport { installNetwork } from './integrations/network';\nimport { installGlobalHandlers } from './integrations/globals';\nimport { installDomBreadcrumbs } from './integrations/dom';\nimport { sendInstallPing } from './ping';\nimport { deviceInfo, isBrowser } from './env';\nimport { redact, redactUrl } from './redact';\nimport { matchesAny, nowIso, randomId, safe, sampled, truncate } from './utils';\n\n/**\n * The SDK client.\n *\n * One rule governs every method here: nothing may throw into the host\n * application, and nothing may block it. Every public entry point is wrapped,\n * every optional browser API is feature-detected, and delivery is\n * fire-and-forget. A monitoring tool that can take down the app it monitors is\n * worse than no monitoring at all.\n */\nexport class BugbanClient {\n private opts: ResolvedOptions;\n private transport: Transport;\n private crumbs: BreadcrumbBuffer;\n private vitals?: VitalsCollector;\n private teardown: Array<() => void> = [];\n\n private user: UserInfo | null = null;\n private context: Record<string, unknown> = {};\n private sessionId = randomId();\n private startedAt = Date.now();\n\n /** Events waiting to be sent, coalesced so an error storm is one request. */\n private queue: BugbanEvent[] = [];\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n /** Guard against reporting an error that our own reporting caused. */\n private sending = false;\n private started = false;\n\n constructor(options: BugbanOptions = {}) {\n this.opts = resolveOptions(options);\n this.transport = new Transport(this.opts.host, this.opts.apiKey, this.opts.debug);\n this.crumbs = new BreadcrumbBuffer(this.opts.maxBreadcrumbs);\n }\n\n get options(): ResolvedOptions {\n return this.opts;\n }\n\n /** Wire up integrations. Safe to call twice — the second call is ignored. */\n start(): void {\n if (this.started) return;\n this.started = true;\n\n // No API key → the SDK is inert. Same contract as the PHP SDK: an app\n // shipped without configuration must behave as if we were not there.\n if (!this.opts.enabled) {\n this.debug('disabled (no API key)');\n return;\n }\n\n safe(() => this.installIntegrations());\n safe(() => sendInstallPing(this.opts, this.transport));\n }\n\n private installIntegrations(): void {\n const o = this.opts;\n\n if (o.globalHandlers) {\n this.teardown.push(\n installGlobalHandlers({\n capture: (err, extra) => this.capture(err, extra),\n flush: () => this.flush(),\n }),\n );\n }\n\n if (o.console) {\n this.teardown.push(\n installConsole(o.console, {\n breadcrumb: (level, message) =>\n this.addBreadcrumb({ type: 'console', level, message }),\n capture: (level, message, args) => {\n // console.error(err) — prefer the real Error argument so\n // the event carries a stack instead of a stringified one.\n const real = args.find((a) => a instanceof Error);\n this.capture(real ?? message, {\n handled: true,\n type: 'console',\n level,\n });\n },\n }),\n );\n }\n\n if (o.network) {\n this.teardown.push(\n installNetwork(\n o.network,\n {\n breadcrumb: (message, data, failed) =>\n this.addBreadcrumb({\n type: 'http',\n level: failed ? 'error' : 'info',\n message,\n data,\n }),\n capture: (message, data) =>\n this.capture(new Error(message), {\n handled: true,\n type: 'http',\n context: data,\n }),\n },\n o.redactKeys,\n o.host,\n ),\n );\n }\n\n if (o.domBreadcrumbs) {\n this.teardown.push(\n installDomBreadcrumbs({\n click: (label, data) =>\n this.addBreadcrumb({ type: 'click', message: `Clicked ${label}`, data }),\n navigate: (from, to) =>\n this.addBreadcrumb({\n type: 'navigation',\n message: `${redactUrl(from, o.redactKeys)} → ${redactUrl(to, o.redactKeys)}`,\n }),\n }),\n );\n }\n\n if (o.vitals && isBrowser) {\n // Sample per session, not per metric: half a page's vitals would be\n // meaningless, and the decision has to be stable for the session.\n if (sampled(o.vitals.sampleRate)) {\n this.vitals = new VitalsCollector(o.vitals, (metrics) => this.sendVitals(metrics));\n this.vitals.start();\n this.teardown.push(() => this.vitals?.stop());\n } else {\n this.debug('vitals not sampled for this session');\n }\n }\n\n if (isBrowser) {\n this.teardown.push(this.installUnloadFlush());\n }\n }\n\n /**\n * Send whatever is queued before the page goes away.\n *\n * Events are batched with a short debounce so an error loop becomes one\n * request instead of hundreds. That debounce loses the last batch whenever\n * the user navigates immediately after the error — which is the common\n * case, not an edge case: click a link, something throws, the document is\n * torn down before the timer fires. Observed exactly that while testing:\n * an uncaught TypeError never arrived while the beacon-based vitals from the\n * same page did.\n *\n * `visibilitychange` is the reliable signal (mobile Safari often skips\n * `beforeunload`), and `pagehide` covers the bfcache case. Both drain with\n * `beacon: true`, the only delivery a closing document is guaranteed to\n * complete.\n */\n private installUnloadFlush(): () => void {\n const onHide = () => {\n // `hidden` also fires on tab switch, which is fine — flushing early\n // costs one request and never loses data.\n if (document.visibilityState === 'hidden') void this.drain(true);\n };\n const onPageHide = () => void this.drain(true);\n\n safe(() => document.addEventListener('visibilitychange', onHide, true));\n safe(() => window.addEventListener('pagehide', onPageHide, true));\n\n return () => {\n safe(() => document.removeEventListener('visibilitychange', onHide, true));\n safe(() => window.removeEventListener('pagehide', onPageHide, true));\n };\n }\n\n // --- public API ---------------------------------------------------------\n\n addBreadcrumb(crumb: Omit<Breadcrumb, 'timestamp'> & { timestamp?: string }): void {\n if (!this.opts.enabled) return;\n safe(() => {\n let c: Breadcrumb = {\n ...crumb,\n data: crumb.data ? redact(crumb.data, this.opts.redactKeys) : undefined,\n timestamp: crumb.timestamp || nowIso(),\n };\n if (this.opts.beforeBreadcrumb) {\n const out = this.opts.beforeBreadcrumb(c);\n if (!out) return;\n c = out;\n }\n this.crumbs.add(c);\n });\n }\n\n setUser(user: UserInfo | null): void {\n safe(() => {\n this.user = user ? (redact(user, this.opts.redactKeys) as UserInfo) : null;\n });\n }\n\n setContext(key: string, value: unknown): void {\n safe(() => {\n this.context[key] = redact(value, this.opts.redactKeys);\n });\n }\n\n captureMessage(message: string, level: Level = 'info'): void {\n this.capture(new Error(message), { handled: true, level, type: 'message' });\n }\n\n /** Report an error. Never throws, never blocks. */\n capture(\n error: unknown,\n extra: {\n handled?: boolean;\n level?: Level;\n type?: string;\n context?: Record<string, unknown>;\n request?: Record<string, unknown>;\n } = {},\n ): void {\n if (!this.opts.enabled) return;\n // Reporting must not report itself.\n if (this.sending) return;\n\n safe(() => {\n const norm = normalizeError(error);\n\n if (this.opts.ignoreErrors.length && matchesAny(norm.message, this.opts.ignoreErrors)) {\n return;\n }\n if (!sampled(this.opts.sampleRate)) return;\n\n const frames = parseStack(norm.stack);\n const top = frames.find((f) => f.in_app) || frames[0];\n\n let event: BugbanEvent = {\n exception_class: norm.name,\n message: truncate(norm.message, 2000),\n level: extra.level || 'error',\n type: extra.type || 'error',\n handled: extra.handled ?? true,\n file: top?.file,\n line: top?.line,\n stacktrace: frames,\n release: this.opts.release,\n environment: this.opts.environment,\n user: this.user,\n breadcrumbs: this.crumbs.all(),\n device: deviceInfo(),\n session: {\n id: this.sessionId,\n started_at: new Date(this.startedAt).toISOString(),\n duration_ms: Date.now() - this.startedAt,\n },\n request: extra.request || this.requestInfo(),\n context: {\n ...this.context,\n ...(extra.context ? redact(extra.context, this.opts.redactKeys) : {}),\n },\n snapshot: this.opts.snapshot ? takeSnapshot(this.opts.snapshot) : null,\n };\n\n if (this.opts.beforeSend) {\n const out = this.opts.beforeSend(event);\n if (!out) return;\n event = out;\n }\n\n this.enqueue(event);\n });\n }\n\n /** Flush anything queued. Await it before a process exits. */\n async flush(): Promise<void> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n await this.drain(false);\n safe(() => this.vitals?.flushNow());\n }\n\n /** Remove every hook the SDK installed. */\n close(): void {\n for (const fn of this.teardown) safe(fn);\n this.teardown = [];\n this.started = false;\n }\n\n /** Adapters use this to report render timings alongside browser vitals. */\n recordMetric(metric: VitalMetric): void {\n safe(() => this.vitals?.push(metric));\n }\n\n // --- internals ----------------------------------------------------------\n\n private requestInfo(): Record<string, unknown> | undefined {\n if (!isBrowser) return undefined;\n return safe(() => ({\n url: redactUrl(location.href, this.opts.redactKeys),\n referrer: document.referrer ? redactUrl(document.referrer, this.opts.redactKeys) : undefined,\n method: 'GET',\n }));\n }\n\n private enqueue(event: BugbanEvent): void {\n this.queue.push(event);\n // Cap the queue: an error loop must not eat the page's memory.\n if (this.queue.length > 50) this.queue.splice(0, this.queue.length - 50);\n\n if (this.flushTimer) return;\n // A short window coalesces a burst (a render loop throwing on every\n // frame) into one request instead of hundreds.\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n void this.drain(false);\n }, 300);\n\n safe(() => {\n const t = this.flushTimer as any;\n // Do not hold a Node process open just to flush telemetry.\n if (t && typeof t.unref === 'function') t.unref();\n });\n }\n\n private async drain(beacon: boolean): Promise<void> {\n if (this.queue.length === 0) return;\n const batch = this.queue.splice(0, this.queue.length);\n\n this.sending = true;\n try {\n await this.transport.send('/api/ingest/events', { events: batch }, { beacon });\n } finally {\n this.sending = false;\n }\n }\n\n private sendVitals(metrics: VitalMetric[]): void {\n safe(() => {\n // Slow database queries share the metric pipeline for batching, but\n // they are NOT web vitals: the server has had /api/ingest/queries\n // since the PHP SDKs, with its own grouping, EXPLAIN handling and\n // Performance tab. Route them there in that endpoint's shape so a\n // Node app's slow queries land next to a Laravel app's.\n const queries: Array<Record<string, unknown>> = [];\n const vitals: VitalMetric[] = [];\n\n for (const m of metrics) {\n if (m.name === 'SLOW_QUERY') {\n const d = (m.data || {}) as Record<string, unknown>;\n queries.push({\n sql: d.sql,\n duration_ms: m.value,\n connection: d.connection,\n bindings: d.bindings,\n url: d.url,\n method: d.method,\n occurred_at: m.occurred_at,\n });\n } else {\n vitals.push(m);\n }\n }\n\n const url = safe(() => redactUrl(location.href, this.opts.redactKeys));\n\n if (queries.length) {\n void this.transport.send('/api/ingest/queries', { queries }, { beacon: true });\n }\n\n if (vitals.length) {\n void this.transport.send(\n '/api/ingest/vitals',\n {\n vitals,\n url,\n release: this.opts.release,\n environment: this.opts.environment,\n session_id: this.sessionId,\n device: deviceInfo(),\n },\n // The page is usually unloading when vitals flush — beacon\n // is the only delivery that survives that.\n { beacon: true },\n );\n }\n });\n }\n\n private debug(...args: unknown[]): void {\n if (!this.opts.debug) return;\n safe(() => console.info('[bugban]', ...args));\n }\n}\n"],"mappings":"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","names":["src_exports","__export","Bugban","BugbanClient","SDK_NAME","SDK_VERSION","addBreadcrumb","capture","captureMessage","close","dependencyVersion","flush","getClient","init","normalizeError","parseStack","recordMetric","redact","redactUrl","runtimeName","runtimeVersion","setContext","setUser","SDK_NAME","SDK_VERSION","isBrowser","e","isNode","runtimeName","runtimeVersion","nodeModule","name","prefixed","spec","ns","tryRequire","hostname","os","appPackageInfo","fs","path","dir","depth","file","json","parent","dependencyVersion","pkg","mod","env","key","v","req","deviceInfo","_a","_b","out","section","value","defaults","defaultOn","__spreadValues","CONSOLE_DEFAULTS","NETWORK_DEFAULTS","SNAPSHOT_DEFAULTS","VITALS_DEFAULTS","resolveOptions","input","_a","_b","apiKey","env","host","__spreadProps","clamp","min","max","safe","fn","fallback","e","nowIso","truncate","value","max","s","stringify","seen","out","_k","v","matchesAny","patterns","p","randomId","c","b","x","sampled","rate","selectorFor","el","node","cls","byteLength","s","e","B","n","i","c","Transport","host","apiKey","debug","path","body","opts","url","json","isBrowser","safe","nav","blob","__spreadProps","__spreadValues","isNode","_a","controller","timer","res","isHttps","mod","nodeModule","resolve","u","req","args","BreadcrumbBuffer","max","crumb","full","nowIso","e","V8_LINE","MOZ_LINE","VENDOR_PATTERNS","isInApp","file","p","toFrame","fn","line","col","f","parseStack","stack","limit","frames","lines","raw","m","loc","normalizeError","input","o","e","MASK_CHAR","DROP_TAGS","maskValue","value","len","maskFormFields","root","fields","i","el","type","current","e","maskSelectors","selectors","sel","nodes","materializeFormState","source","clone","src","dst","n","s","d","collectCss","maxBytes","css","sheets","rules","j","takeSnapshot","opts","isBrowser","tag","head","base","html","nowIso","THRESHOLDS","rate","name","value","VitalsCollector","opts","flush","isBrowser","o","safe","metric","_a","_b","_c","__spreadProps","__spreadValues","nowIso","e","extra","type","cb","buffered","obs","list","nav","entries","last","selectorFor","clsValue","sessionValue","sessionEntries","entry","first","worst","a","b","duration","doFlush","all","k","LEVEL_MAP","installConsole","opts","hooks","originals","inside","method","original","args","level","message","a","truncate","e","safe","m","DEFAULT_REDACT_KEYS","REDACTED","isSensitiveKey","key","extra","k","s","redact","value","extraKeys","depth","v","src","out","count","e","redactUrl","url","hasScheme","u","_v","installNetwork","opts","hooks","redactKeys","ownHost","undo","ignored","url","matchesAny","record","method","rawUrl","status","startedAt","errored","redactUrl","duration","now","failed","data","label","e","original","patched","input","init","started","res","err","proto","origOpen","origSend","rest","safe","args","meta","fn","installGlobalHandlers","hooks","undo","isBrowser","onError","event","safe","err","onRejection","reason","isNode","onUncaught","onUnhandled","fn","labelFor","el","safe","aria","truncate","tag","ph","text","installDomBreadcrumbs","hooks","isBrowser","undo","onClick","event","target","i","chosen","selectorFor","current","report","next","history","origPush","origReplace","args","r","fn","MARKER_KEY","memoryMarker","alreadyPinged","apiKey","version","stamp","isBrowser","safe","isNode","fs","os","path","key","toHex","file","e","s","out","i","sendInstallPing","opts","transport","SDK_VERSION","pkg","appPackageInfo","host","hostname","payload","SDK_NAME","runtimeName","runtimeVersion","k","BugbanClient","options","randomId","resolveOptions","Transport","BreadcrumbBuffer","safe","sendInstallPing","o","installGlobalHandlers","err","extra","installConsole","level","message","args","real","a","installNetwork","data","failed","installDomBreadcrumbs","label","from","to","redactUrl","isBrowser","sampled","VitalsCollector","metrics","_a","onHide","onPageHide","crumb","c","__spreadProps","__spreadValues","redact","nowIso","out","user","key","value","error","norm","normalizeError","matchesAny","frames","parseStack","top","f","event","truncate","deviceInfo","takeSnapshot","fn","metric","beacon","batch","queries","vitals","m","d","url","client","init","options","safe","BugbanClient","getClient","capture","error","extra","captureMessage","message","level","setUser","user","setContext","key","value","addBreadcrumb","crumb","recordMetric","metric","flush","close","Bugban","SDK_VERSION"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/env.ts","../../src/config.ts","../../src/utils.ts","../../src/transport.ts","../../src/breadcrumbs.ts","../../src/stacktrace.ts","../../src/snapshot.ts","../../src/vitals.ts","../../src/integrations/console.ts","../../src/redact.ts","../../src/integrations/network.ts","../../src/integrations/globals.ts","../../src/integrations/dom.ts","../../src/ping.ts","../../src/client.ts"],"sourcesContent":["import { BugbanClient } from './client';\nimport type { Breadcrumb, BugbanOptions, Level, UserInfo, VitalMetric } from './types';\nimport { SDK_VERSION } from './env';\nimport { safe } from './utils';\n\nexport { BugbanClient } from './client';\nexport { parseStack, normalizeError } from './stacktrace';\nexport { redact, redactUrl } from './redact';\nexport { SDK_VERSION, SDK_NAME, runtimeName, runtimeVersion, dependencyVersion } from './env';\nexport type {\n Breadcrumb,\n BreadcrumbType,\n BugbanEvent,\n BugbanOptions,\n ConsoleOptions,\n Level,\n NetworkOptions,\n Snapshot,\n SnapshotOptions,\n StackFrame,\n UserInfo,\n VitalMetric,\n VitalsOptions,\n} from './types';\n\n/**\n * Module-level singleton.\n *\n * Almost every app wants exactly one client, and the framework adapters need a\n * way to reach it from code the app never touches (an error boundary, an\n * exception filter). A singleton keeps `import { Bugban } from '@bugban/js'`\n * working everywhere; `new BugbanClient()` is still there for the rare app\n * that reports to two projects.\n *\n * The singleton lives on globalThis, not in a module variable.\n *\n * A module variable assumes one copy of this package per process, and modern\n * bundlers break that assumption routinely. Next.js is the clearest case: it\n * bundles `instrumentation.ts` and every route handler separately, so the copy\n * that ran init() is NOT the copy a route's `capture()` call reaches. The\n * result was silent — the install ping arrived, the route threw, and nothing\n * was ever reported. The same happens with a pnpm monorepo that hoists two\n * versions, and it is the JS echo of the PHP mixed-install failure.\n *\n * A well-known key on globalThis is the one thing every copy agrees on.\n */\nconst SINGLETON_KEY = '__bugban_client__';\n\ntype GlobalWithClient = typeof globalThis & { [SINGLETON_KEY]?: BugbanClient | null };\n\nfunction readClient(): BugbanClient | null {\n return safe(() => (globalThis as GlobalWithClient)[SINGLETON_KEY] ?? null, null) ?? null;\n}\n\nfunction writeClient(value: BugbanClient | null): void {\n safe(() => {\n (globalThis as GlobalWithClient)[SINGLETON_KEY] = value;\n });\n}\n\nexport function init(options: BugbanOptions = {}): BugbanClient {\n // Re-initialising would leave the previous client's hooks installed, so the\n // old one is torn down first.\n const previous = readClient();\n if (previous) safe(() => previous.close());\n\n const created = new BugbanClient(options);\n writeClient(created);\n created.start();\n return created;\n}\n\n/** The active client, or null when init() has not been called. */\nexport function getClient(): BugbanClient | null {\n return readClient();\n}\n\n/**\n * Every helper below is a no-op before init(). That is deliberate: a component\n * that calls captureError must not crash because the app forgot to configure\n * monitoring, or because it is running in a test.\n */\n\nexport function capture(\n error: unknown,\n extra?: { handled?: boolean; level?: Level; type?: string; context?: Record<string, unknown> },\n): void {\n readClient()?.capture(error, extra);\n}\n\nexport function captureMessage(message: string, level: Level = 'info'): void {\n readClient()?.captureMessage(message, level);\n}\n\nexport function setUser(user: UserInfo | null): void {\n readClient()?.setUser(user);\n}\n\nexport function setContext(key: string, value: unknown): void {\n readClient()?.setContext(key, value);\n}\n\nexport function addBreadcrumb(crumb: Omit<Breadcrumb, 'timestamp'> & { timestamp?: string }): void {\n readClient()?.addBreadcrumb(crumb);\n}\n\nexport function recordMetric(metric: VitalMetric): void {\n readClient()?.recordMetric(metric);\n}\n\nexport async function flush(): Promise<void> {\n await readClient()?.flush();\n}\n\nexport function close(): void {\n readClient()?.close();\n writeClient(null);\n}\n\n/**\n * Namespace form, so `Bugban.capture(e)` reads the same as the PHP facade.\n *\n * Deliberately NOT also a default export: mixing default and named exports\n * makes the CommonJS build require `.default`, which is exactly the kind of\n * \"works in one install shape, breaks in another\" trap that took a customer's\n * site down on the PHP side. One import style, everywhere:\n *\n * import { Bugban } from '@bugban/js';\n * const { Bugban } = require('@bugban/js');\n */\nexport const Bugban = {\n VERSION: SDK_VERSION,\n init,\n getClient,\n capture,\n captureMessage,\n setUser,\n setContext,\n addBreadcrumb,\n recordMetric,\n flush,\n close,\n};\n","/**\n * Runtime detection and environment facts.\n *\n * Every lookup is defensive: this file runs in browsers, in Node, in edge\n * runtimes, and during SSR where `window` exists but `document` does not.\n * Nothing here may throw — a crash in environment detection would take down\n * the host application on import, which is exactly the failure the PHP SDK\n * learned to avoid the hard way.\n */\n\nexport const SDK_NAME = 'bugban-js';\nexport const SDK_VERSION = '1.0.1';\n\nexport const isBrowser: boolean = (() => {\n try {\n return typeof window !== 'undefined' && typeof window.document !== 'undefined';\n } catch {\n return false;\n }\n})();\n\nexport const isNode: boolean = (() => {\n try {\n return (\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null\n );\n } catch {\n return false;\n }\n})();\n\n/** 'browser' | 'node' | 'unknown' — reported on the install ping. */\nexport function runtimeName(): string {\n if (isBrowser) return 'browser';\n if (isNode) return 'node';\n return 'unknown';\n}\n\n/**\n * The runtime's own version: Node's `v22.13.1`, or the browser's UA string.\n * The panel shows this next to the framework version, the same way it shows\n * the PHP version for the PHP SDKs.\n */\nexport function runtimeVersion(): string | undefined {\n try {\n if (isNode) return process.versions.node;\n if (isBrowser) return navigator.userAgent;\n } catch {\n /* ignore */\n }\n return undefined;\n}\n\n/**\n * Load a Node built-in without letting any bundler see it.\n *\n * Three constraints collide here:\n * 1. In ESM there is no `require`, so the old `globalThis.require` trick\n * silently returned undefined and the SDK went quiet on modern Node.\n * 2. In a browser bundle a literal `import('http')` makes Vite/webpack try\n * to resolve — and warn or fail — even though the call is unreachable.\n * 3. Customers run old Node. `node:` prefixes need 14.18+, and dynamic\n * import itself needs 12.17+, so every step needs a fallback.\n *\n * The specifier is built at runtime so static analysis cannot follow it, and\n * `require` remains the last resort for old CJS bundles.\n */\nexport async function nodeModule(name: string): Promise<any> {\n if (!isNode) return undefined;\n\n // Computed on purpose — a literal would be statically analysable.\n const prefixed = 'node:'.concat(name);\n for (const spec of [prefixed, String(name)]) {\n try {\n const ns: any = await import(/* @vite-ignore */ /* webpackIgnore: true */ spec);\n if (ns) return ns.default && !ns.hostname && !ns.existsSync ? ns.default : ns;\n } catch {\n /* try the next specifier */\n }\n }\n\n return tryRequire(name);\n}\n\n/** Best-effort hostname — the machine for Node, the site for a browser. */\nexport async function hostname(): Promise<string | undefined> {\n try {\n if (isBrowser) return window.location.hostname;\n if (isNode) {\n const os = await nodeModule('os');\n if (os && typeof os.hostname === 'function') return String(os.hostname());\n }\n } catch {\n /* ignore */\n }\n return undefined;\n}\n\n/**\n * Read the host application's name/version from its package.json (Node only).\n * Browsers have no filesystem, so there `release` must be passed to init() —\n * usually wired to the bundler's define (e.g. Vite's import.meta.env).\n */\nexport async function appPackageInfo(): Promise<{ name?: string; version?: string }> {\n if (!isNode) return {};\n try {\n const fs = await nodeModule('fs');\n const path = await nodeModule('path');\n if (!fs || !path || typeof fs.existsSync !== 'function') return {};\n\n // Walk up from the working directory: in a monorepo the nearest\n // package.json is the app being run, not the repo root.\n let dir = process.cwd();\n for (let depth = 0; depth < 6; depth++) {\n const file = path.join(dir, 'package.json');\n if (fs.existsSync(file)) {\n const json = JSON.parse(fs.readFileSync(file, 'utf8'));\n return { name: json.name, version: json.version };\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n } catch {\n /* ignore */\n }\n return {};\n}\n\n/**\n * Read a dependency's version out of the host app's node_modules, so an\n * adapter can report \"react 19.0.0\" without importing react itself.\n */\nexport async function dependencyVersion(pkg: string): Promise<string | undefined> {\n if (!isNode) return undefined;\n try {\n const mod = await nodeModule('module');\n if (mod && typeof mod.createRequire === 'function') {\n const r = mod.createRequire(process.cwd() + '/package.json');\n const json = r(`${pkg}/package.json`);\n return json && json.version ? String(json.version) : undefined;\n }\n } catch {\n /* the dependency may simply not be installed */\n }\n return undefined;\n}\n\n/** Environment variable read that is safe in the browser. */\nexport function env(key: string): string | undefined {\n try {\n if (typeof process !== 'undefined' && process.env) {\n const v = process.env[key];\n return v == null || v === '' ? undefined : String(v);\n }\n } catch {\n /* ignore */\n }\n return undefined;\n}\n\n/**\n * CommonJS require that bundlers do not statically analyse. Returns undefined\n * in ESM-only or browser contexts instead of throwing.\n */\nfunction tryRequire(name: string): any {\n try {\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n const req: any =\n typeof module !== 'undefined' && typeof (module as any).require === 'function'\n ? (module as any).require\n : typeof (globalThis as any).require === 'function'\n ? (globalThis as any).require\n : undefined;\n return req ? req(name) : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Device/app context sent with every event. */\nexport function deviceInfo(): Record<string, unknown> {\n const out: Record<string, unknown> = {\n sdk: SDK_NAME,\n sdk_version: SDK_VERSION,\n runtime: runtimeName(),\n runtime_version: runtimeVersion(),\n };\n\n try {\n if (isBrowser) {\n out.user_agent = navigator.userAgent;\n out.language = navigator.language;\n out.screen = { width: window.screen?.width, height: window.screen?.height };\n out.viewport = { width: window.innerWidth, height: window.innerHeight };\n out.online = navigator.onLine;\n }\n if (isNode) {\n out.platform = process.platform;\n out.arch = process.arch;\n out.pid = process.pid;\n }\n } catch {\n /* ignore */\n }\n\n return out;\n}\n","import type {\n BugbanOptions,\n ConsoleOptions,\n NetworkOptions,\n ResolvedOptions,\n SnapshotOptions,\n VitalsOptions,\n} from './types';\nimport { env, isBrowser } from './env';\n\n/**\n * Option resolution.\n *\n * `true` / `false` / an object are all valid for each feature block, so the app\n * can write `console: true` or `console: { levels: [...] }`. Everything is\n * normalised here once, and the rest of the SDK only ever sees the full shape.\n */\n\nfunction section<T extends object>(\n value: boolean | T | undefined,\n defaults: Required<T>,\n defaultOn: boolean,\n): Required<T> | false {\n if (value === false) return false;\n if (value === true || value === undefined) return defaultOn || value === true ? defaults : false;\n return { ...defaults, ...(value as object) } as Required<T>;\n}\n\nconst CONSOLE_DEFAULTS: Required<ConsoleOptions> = {\n levels: ['log', 'info', 'warn', 'error', 'debug'],\n /**\n * Whether console.error becomes an event of its own, or stays a breadcrumb.\n *\n * Browser: yes. Most real front-end failures never reach window.onerror —\n * the app catches the error, logs it, and renders \"something went wrong\".\n * console.error is the only signal those leave behind.\n *\n * Node: no. Server frameworks log every error they handle, so capturing the\n * log too reports the same failure twice AND defeats filtering: NestJS logs\n * a deliberate 404 that the exception filter correctly skipped, and the\n * console path turned it back into an event. Observed exactly that. The\n * framework adapter already reports real errors with route context, so here\n * the console is breadcrumbs only.\n */\n captureAsEvent: isBrowser ? ['error'] : [],\n};\n\nconst NETWORK_DEFAULTS: Required<NetworkOptions> = {\n enabled: true,\n captureFailures: true,\n ignoreUrls: [],\n};\n\nconst SNAPSHOT_DEFAULTS: Required<SnapshotOptions> = {\n enabled: true,\n // Never flipped to false by a preset. Turning this off ships whatever the\n // end user typed — passwords included — to the Bugban server, so it has to\n // be an explicit, deliberate line in the app's own config.\n maskInputs: true,\n maskSelectors: [],\n maxBytes: 500_000,\n};\n\nconst VITALS_DEFAULTS: Required<VitalsOptions> = {\n enabled: true,\n // Vitals describe the whole audience, not one error, so a sample is enough\n // and keeps ingest volume proportional to traffic.\n sampleRate: 0.2,\n longTaskMs: 100,\n slowResourceMs: 1000,\n};\n\nexport function resolveOptions(input: BugbanOptions = {}): ResolvedOptions {\n const apiKey = input.apiKey || env('BUGBAN_API_KEY') || env('NEXT_PUBLIC_BUGBAN_API_KEY') || '';\n const host =\n input.host ||\n env('BUGBAN_HOST') ||\n env('NEXT_PUBLIC_BUGBAN_HOST') ||\n 'https://bugban.online';\n\n return {\n ...input,\n apiKey,\n host: host.replace(/\\/+$/, ''),\n release: input.release || env('BUGBAN_RELEASE'),\n environment: input.environment || env('BUGBAN_ENV') || env('NODE_ENV') || 'production',\n // No key means no-op, exactly like the PHP SDK: an app that ships\n // without configuration must not error, it must simply do nothing.\n enabled: input.enabled !== false && apiKey !== '',\n debug: input.debug === true,\n maxBreadcrumbs: clamp(input.maxBreadcrumbs ?? 50, 1, 200),\n sampleRate: clamp(input.sampleRate ?? 1, 0, 1),\n\n console: section(input.console, CONSOLE_DEFAULTS, true),\n network: section(input.network, NETWORK_DEFAULTS, true),\n snapshot: section(input.snapshot, SNAPSHOT_DEFAULTS, true),\n vitals: section(input.vitals, VITALS_DEFAULTS, true),\n\n globalHandlers: input.globalHandlers !== false,\n domBreadcrumbs: input.domBreadcrumbs !== false,\n installPing: input.installPing !== false,\n\n redactKeys: input.redactKeys || [],\n ignoreErrors: input.ignoreErrors || [],\n };\n}\n\nfunction clamp(n: number, min: number, max: number): number {\n if (typeof n !== 'number' || isNaN(n)) return min;\n return Math.min(max, Math.max(min, n));\n}\n","/** Small helpers shared across the SDK. All of them are failure-tolerant. */\n\n/**\n * Run a function and swallow anything it throws.\n *\n * The SDK must never take the host application down — that rule is written in\n * blood after a PHP adapter crashed a customer's production site. Every entry\n * point into SDK code goes through this.\n */\nexport function safe<T>(fn: () => T, fallback?: T): T | undefined {\n try {\n return fn();\n } catch {\n return fallback;\n }\n}\n\nexport function nowIso(): string {\n try {\n return new Date().toISOString();\n } catch {\n return '';\n }\n}\n\nexport function truncate(value: unknown, max: number): string {\n const s = typeof value === 'string' ? value : stringify(value);\n return s.length > max ? s.slice(0, max) + '…' : s;\n}\n\n/** JSON.stringify that survives circular references and exotic values. */\nexport function stringify(value: unknown, max = 2000): string {\n try {\n const seen = new WeakSet<object>();\n const out = JSON.stringify(value, (_k, v) => {\n if (typeof v === 'bigint') return v.toString();\n if (typeof v === 'function') return '[Function]';\n if (v instanceof Error) return { name: v.name, message: v.message };\n if (typeof v === 'object' && v !== null) {\n if (seen.has(v)) return '[Circular]';\n seen.add(v);\n }\n return v;\n });\n if (out == null) return String(value);\n return out.length > max ? out.slice(0, max) + '…' : out;\n } catch {\n try {\n return String(value);\n } catch {\n return '[unserializable]';\n }\n }\n}\n\nexport function matchesAny(value: string, patterns: Array<string | RegExp>): boolean {\n for (const p of patterns) {\n try {\n if (typeof p === 'string') {\n if (value.indexOf(p) !== -1) return true;\n } else if (p.test(value)) {\n return true;\n }\n } catch {\n /* a bad pattern must not break matching */\n }\n }\n return false;\n}\n\n/** Deterministic-enough id for correlating a session's events. */\nexport function randomId(): string {\n try {\n const c: any = (globalThis as any).crypto;\n if (c && typeof c.randomUUID === 'function') return c.randomUUID();\n if (c && typeof c.getRandomValues === 'function') {\n const b = new Uint8Array(16);\n c.getRandomValues(b);\n return Array.from(b, (x) => x.toString(16).padStart(2, '0')).join('');\n }\n } catch {\n /* ignore */\n }\n // Math.random is fine here: this id only correlates telemetry, it is not\n // a security token.\n return Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\n/** 0..1 sample decision. rate >= 1 always passes, <= 0 never does. */\nexport function sampled(rate: number): boolean {\n if (rate >= 1) return true;\n if (rate <= 0) return false;\n return Math.random() < rate;\n}\n\n/** A CSS-ish selector for an element, used in click breadcrumbs and vitals. */\nexport function selectorFor(el: unknown): string | undefined {\n try {\n const node = el as any;\n if (!node || typeof node.tagName !== 'string') return undefined;\n let s = node.tagName.toLowerCase();\n if (node.id) return `${s}#${node.id}`;\n if (typeof node.className === 'string' && node.className.trim()) {\n const cls = node.className.trim().split(/\\s+/).slice(0, 2).join('.');\n if (cls) s += `.${cls}`;\n }\n return s;\n } catch {\n return undefined;\n }\n}\n","import { isBrowser, isNode, nodeModule } from './env';\nimport { safe } from './utils';\n\n/**\n * UTF-8 byte length without depending on Buffer (absent in edge runtimes) or\n * TextEncoder (absent in very old Node).\n */\nfunction byteLength(s: string): number {\n try {\n if (typeof TextEncoder === 'function') return new TextEncoder().encode(s).length;\n } catch {\n /* fall through */\n }\n try {\n const B: any = (globalThis as any).Buffer;\n if (B && typeof B.byteLength === 'function') return B.byteLength(s);\n } catch {\n /* fall through */\n }\n // Manual UTF-8 count — correct for the surrogate pairs emojis produce.\n let n = 0;\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i);\n if (c < 0x80) n += 1;\n else if (c < 0x800) n += 2;\n else if (c >= 0xd800 && c <= 0xdbff) {\n n += 4;\n i++;\n } else n += 3;\n }\n return n;\n}\n\n/**\n * Delivery of payloads to the Bugban ingest API.\n *\n * Mirrors the PHP SDK's transport philosophy: pick the best mechanism the\n * runtime offers, fall back automatically, and never block or throw. The\n * browser adds one concern PHP does not have — a page can be closing while a\n * request is in flight, which is what `sendBeacon` and `keepalive` exist for.\n */\n\nexport interface SendOptions {\n /** Use a delivery mechanism that survives page unload. */\n beacon?: boolean;\n timeoutMs?: number;\n}\n\nexport class Transport {\n constructor(\n private host: string,\n private apiKey: string,\n private debug = false,\n ) {}\n\n /** Fire-and-forget POST. Resolves to true when the server accepted it. */\n async send(path: string, body: unknown, opts: SendOptions = {}): Promise<boolean> {\n const url = this.host.replace(/\\/+$/, '') + path;\n let json: string;\n try {\n json = JSON.stringify(body);\n } catch {\n return false;\n }\n\n // Page-unload path: sendBeacon is the only mechanism the browser\n // guarantees to flush after the document goes away.\n if (opts.beacon && isBrowser) {\n const sent = safe(() => {\n const nav: any = navigator;\n if (typeof nav.sendBeacon !== 'function') return false;\n // sendBeacon cannot set headers, so the key travels in the body\n // as `_key` (the server accepts it there for exactly this case).\n // Not a query parameter — that would land in the access log.\n //\n // The MIME type must be text/plain, not application/json.\n // application/json makes the request non-simple, which triggers\n // a CORS preflight; sendBeacon always sends credentials, and a\n // credentialed request cannot accept the wildcard\n // Access-Control-Allow-Origin the ingest API returns. The result\n // was silent: vitals from any customer domain were dropped by\n // the browser before they were ever sent. text/plain is a\n // CORS-safelisted type, so there is no preflight at all.\n const blob = new Blob([JSON.stringify({ ...(body as object), _key: this.apiKey })], {\n type: 'text/plain;charset=UTF-8',\n });\n return nav.sendBeacon(url, blob);\n }, false);\n if (sent) return true;\n // fall through to fetch\n }\n\n if (typeof fetch === 'function') {\n return this.viaFetch(url, json, opts);\n }\n if (isNode) {\n return this.viaNodeHttp(url, json, opts);\n }\n\n this.log('no transport available');\n return false;\n }\n\n private async viaFetch(url: string, json: string, opts: SendOptions): Promise<boolean> {\n try {\n const controller =\n typeof AbortController === 'function' ? new AbortController() : undefined;\n const timer = controller\n ? setTimeout(() => safe(() => controller.abort()), opts.timeoutMs ?? 8000)\n : undefined;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Bugban-Key': this.apiKey,\n },\n body: json,\n // keepalive lets the request outlive the page in browsers that\n // support it; it is ignored elsewhere.\n keepalive: opts.beacon === true,\n signal: controller ? controller.signal : undefined,\n // Never send the site's cookies to Bugban.\n credentials: 'omit',\n mode: 'cors',\n } as RequestInit);\n\n if (timer) clearTimeout(timer);\n if (!res.ok) this.log('ingest rejected', res.status);\n return res.ok;\n } catch (e) {\n this.log('fetch failed', e);\n return false;\n }\n }\n\n /**\n * Node without global fetch — that is Node 17 and older, which a fair\n * number of customers still run in production. Uses the http/https module\n * loaded the bundler-opaque way, because `globalThis.require` does not\n * exist under ESM and this path would otherwise silently deliver nothing.\n */\n private async viaNodeHttp(url: string, json: string, opts: SendOptions): Promise<boolean> {\n const isHttps = url.indexOf('https://') === 0;\n const mod = await nodeModule(isHttps ? 'https' : 'http');\n if (!mod || typeof mod.request !== 'function') return false;\n\n return new Promise((resolve) => {\n try {\n const u = new URL(url);\n const req = mod.request(\n {\n method: 'POST',\n hostname: u.hostname,\n port: u.port || (isHttps ? 443 : 80),\n path: u.pathname + u.search,\n timeout: opts.timeoutMs ?? 8000,\n headers: {\n 'Content-Type': 'application/json',\n // Byte length, not string length — a multi-byte\n // message would otherwise truncate the body.\n 'Content-Length': byteLength(json),\n 'X-Bugban-Key': this.apiKey,\n },\n },\n (res: any) => {\n res.resume();\n resolve(res.statusCode >= 200 && res.statusCode < 300);\n },\n );\n req.on('error', () => resolve(false));\n req.on('timeout', () => {\n safe(() => req.destroy());\n resolve(false);\n });\n req.write(json);\n req.end();\n } catch {\n resolve(false);\n }\n });\n }\n\n private log(...args: unknown[]): void {\n if (!this.debug) return;\n safe(() => console.warn('[bugban]', ...args));\n }\n}\n","import type { Breadcrumb } from './types';\nimport { nowIso } from './utils';\n\n/**\n * Fixed-size ring buffer of recent activity.\n *\n * Breadcrumbs are what turn \"TypeError: cannot read x of undefined\" into a\n * story: the click, the route change, the 500 from /api/orders, then the\n * crash. The buffer is capped so a long-lived SPA session cannot grow it\n * without bound.\n */\nexport class BreadcrumbBuffer {\n private items: Breadcrumb[] = [];\n\n constructor(private max: number) {}\n\n add(crumb: Omit<Breadcrumb, 'timestamp'> & { timestamp?: string }): void {\n try {\n const full: Breadcrumb = {\n type: crumb.type,\n message: crumb.message,\n level: crumb.level,\n data: crumb.data,\n timestamp: crumb.timestamp || nowIso(),\n };\n this.items.push(full);\n if (this.items.length > this.max) {\n this.items.splice(0, this.items.length - this.max);\n }\n } catch {\n /* never let telemetry break the app */\n }\n }\n\n /** Snapshot for sending. Copied so a later push cannot mutate a sent event. */\n all(): Breadcrumb[] {\n return this.items.slice();\n }\n\n clear(): void {\n this.items = [];\n }\n\n setMax(max: number): void {\n this.max = max;\n if (this.items.length > max) {\n this.items.splice(0, this.items.length - max);\n }\n }\n}\n","import type { StackFrame } from './types';\n\n/**\n * Error.stack parsing.\n *\n * There is no standard for `Error.stack`, so this handles the three shapes that\n * matter in practice: V8 (Chrome/Node/Edge), SpiderMonkey (Firefox) and\n * JavaScriptCore (Safari). Anything unrecognised degrades to a single frame\n * carrying the raw line rather than being dropped — a partial stack still\n * beats none in the panel.\n */\n\n// V8: \" at fnName (/path/file.js:10:5)\" | \" at /path/file.js:10:5\"\nconst V8_LINE = /^\\s*at (?:(.+?)\\s+\\()?(?:(.+?):(\\d+):(\\d+)|([^)]+))\\)?\\s*$/;\n\n// Firefox/Safari: \"fnName@/path/file.js:10:5\" | \"@/path/file.js:10:5\"\nconst MOZ_LINE = /^\\s*(?:(.*?)@)?(.+?):(\\d+):(\\d+)\\s*$/;\n\n/** Frames from these paths are framework/vendor noise, collapsed in the panel. */\nconst VENDOR_PATTERNS = [\n 'node_modules',\n 'webpack-internal',\n 'webpack://',\n '/.next/',\n '/.nuxt/',\n 'node:internal',\n 'internal/process',\n];\n\nfunction isInApp(file?: string): boolean {\n if (!file) return false;\n for (const p of VENDOR_PATTERNS) {\n if (file.indexOf(p) !== -1) return false;\n }\n return true;\n}\n\nfunction toFrame(fn: string | undefined, file: string, line: string, col: string): StackFrame {\n const f: StackFrame = {\n file: file || undefined,\n line: line ? parseInt(line, 10) : undefined,\n column: col ? parseInt(col, 10) : undefined,\n in_app: isInApp(file),\n };\n if (fn && fn !== '<anonymous>') f.function = fn.trim();\n return f;\n}\n\nexport function parseStack(stack: unknown, limit = 50): StackFrame[] {\n if (typeof stack !== 'string' || stack === '') return [];\n\n const frames: StackFrame[] = [];\n const lines = stack.split('\\n');\n\n for (const raw of lines) {\n if (frames.length >= limit) break;\n const line = raw.replace(/\\r$/, '');\n if (!line.trim()) continue;\n // The first line is usually \"TypeError: message\" — not a frame.\n if (!/^\\s*at\\s/.test(line) && line.indexOf('@') === -1) continue;\n\n let m = V8_LINE.exec(line);\n if (m) {\n // Group 5 is the \"at /path:1:1\" form with no function name, in which\n // case the location still needs splitting off the tail.\n if (m[5] && !m[2]) {\n const loc = /^(.*?):(\\d+):(\\d+)$/.exec(m[5]);\n frames.push(\n loc\n ? toFrame(m[1], loc[1], loc[2], loc[3])\n : { function: m[1], file: m[5], in_app: isInApp(m[5]) },\n );\n } else {\n frames.push(toFrame(m[1], m[2] || '', m[3] || '', m[4] || ''));\n }\n continue;\n }\n\n m = MOZ_LINE.exec(line);\n if (m) {\n frames.push(toFrame(m[1], m[2] || '', m[3] || '', m[4] || ''));\n continue;\n }\n\n frames.push({ function: line.trim(), in_app: false });\n }\n\n return frames;\n}\n\n/**\n * Normalise anything a JS app can throw into an error-shaped object.\n * `throw 'a string'` and `Promise.reject({code: 500})` are both common; both\n * must produce a usable event rather than \"undefined\".\n */\nexport function normalizeError(input: unknown): {\n name: string;\n message: string;\n stack?: string;\n} {\n if (input instanceof Error) {\n return {\n name: input.name || 'Error',\n message: input.message || String(input),\n stack: input.stack,\n };\n }\n\n if (typeof input === 'string') return { name: 'Error', message: input };\n\n if (input && typeof input === 'object') {\n const o = input as any;\n // DOMException, ErrorEvent, and plain {name, message} objects.\n if (typeof o.message === 'string') {\n return {\n name: typeof o.name === 'string' ? o.name : 'Error',\n message: o.message,\n stack: typeof o.stack === 'string' ? o.stack : undefined,\n };\n }\n try {\n return { name: 'Error', message: JSON.stringify(o) };\n } catch {\n return { name: 'Error', message: '[object]' };\n }\n }\n\n return { name: 'Error', message: String(input) };\n}\n","import type { Snapshot, SnapshotOptions } from './types';\nimport { isBrowser } from './env';\nimport { nowIso } from './utils';\n\n/**\n * DOM snapshot taken at error time.\n *\n * This is deliberately NOT a pixel screenshot. Serializing the DOM is smaller\n * than an image, keeps text selectable, lets the panel inspect elements, and\n * needs no extra library (html2canvas would add ~200KB to every customer's\n * bundle and still mis-renders modern CSS). The trade-off is that canvas and\n * video content come back blank — an acceptable loss for debugging layout and\n * state at the moment of failure.\n *\n * PRIVACY: this leaves the end user's screen and lands on the Bugban server.\n * `maskInputs` defaults to true and every form value is replaced before\n * serialization. Turning it off is a conscious choice the developer makes.\n */\n\nconst MASK_CHAR = '•';\n\n/** Elements that carry no visual meaning or would re-execute on replay. */\nconst DROP_TAGS = ['SCRIPT', 'NOSCRIPT', 'TEMPLATE'];\n\nfunction maskValue(value: string): string {\n const len = Math.min(value.length, 12);\n return len > 0 ? MASK_CHAR.repeat(len) : '';\n}\n\n/**\n * Replace form values in the CLONE. Inputs are the highest-risk content on a\n * page: passwords, card numbers, personal details, search terms.\n */\nfunction maskFormFields(root: Element): void {\n const fields = root.querySelectorAll('input, textarea, select');\n for (let i = 0; i < fields.length; i++) {\n const el = fields[i] as HTMLInputElement;\n try {\n const type = (el.getAttribute('type') || '').toLowerCase();\n\n // A password field's length is itself a hint — use a fixed mask.\n if (type === 'password') {\n el.setAttribute('value', MASK_CHAR.repeat(8));\n continue;\n }\n // Checkboxes/radios carry no free text; keep their state.\n if (type === 'checkbox' || type === 'radio' || type === 'submit' || type === 'button') {\n continue;\n }\n\n const current = el.getAttribute('value') || '';\n if (current) el.setAttribute('value', maskValue(current));\n\n if (el.tagName === 'TEXTAREA' && el.textContent) {\n el.textContent = maskValue(el.textContent);\n }\n } catch {\n /* keep going — one bad node must not lose the whole snapshot */\n }\n }\n}\n\n/** Blank out anything the developer flagged as sensitive. */\nfunction maskSelectors(root: Element, selectors: string[]): void {\n for (const sel of selectors) {\n try {\n const nodes = root.querySelectorAll(sel);\n for (let i = 0; i < nodes.length; i++) {\n const el = nodes[i] as HTMLElement;\n if (el.textContent) el.textContent = MASK_CHAR.repeat(6);\n }\n } catch {\n /* an invalid selector is the developer's typo, not a crash */\n }\n }\n}\n\n/**\n * Copy live form state onto the clone's attributes.\n *\n * `cloneNode` copies attributes, not properties — a user-typed value lives in\n * `el.value` and would vanish. Copying it first, then masking, means the\n * snapshot shows \"a filled field\" rather than an empty one.\n */\nfunction materializeFormState(source: Element, clone: Element): void {\n try {\n const src = source.querySelectorAll('input, textarea, select');\n const dst = clone.querySelectorAll('input, textarea, select');\n const n = Math.min(src.length, dst.length);\n for (let i = 0; i < n; i++) {\n const s = src[i] as HTMLInputElement;\n const d = dst[i] as HTMLInputElement;\n if (s.tagName === 'SELECT') {\n d.setAttribute('data-bugban-selected', String((s as unknown as HTMLSelectElement).selectedIndex));\n continue;\n }\n if (typeof s.value === 'string' && s.value !== '') d.setAttribute('value', s.value);\n if (s.checked) d.setAttribute('checked', 'checked');\n }\n } catch {\n /* ignore */\n }\n}\n\n/** Concatenate same-origin stylesheet text so the replay renders standalone. */\nfunction collectCss(maxBytes: number): string {\n let css = '';\n try {\n const sheets = document.styleSheets;\n for (let i = 0; i < sheets.length; i++) {\n if (css.length > maxBytes) break;\n try {\n // Cross-origin sheets throw on cssRules access — expected, skip.\n const rules = (sheets[i] as CSSStyleSheet).cssRules;\n if (!rules) continue;\n for (let j = 0; j < rules.length; j++) {\n css += rules[j].cssText + '\\n';\n if (css.length > maxBytes) break;\n }\n } catch {\n continue;\n }\n }\n } catch {\n /* ignore */\n }\n return css.length > maxBytes ? css.slice(0, maxBytes) : css;\n}\n\nexport function takeSnapshot(opts: Required<SnapshotOptions>): Snapshot | null {\n if (!isBrowser || !opts.enabled) return null;\n\n try {\n const source = document.documentElement;\n if (!source) return null;\n\n const clone = source.cloneNode(true) as Element;\n\n // Order matters: materialize live values first, then mask them.\n materializeFormState(source, clone);\n if (opts.maskInputs) maskFormFields(clone);\n if (opts.maskSelectors && opts.maskSelectors.length) {\n maskSelectors(clone, opts.maskSelectors);\n }\n\n for (const tag of DROP_TAGS) {\n const nodes = clone.getElementsByTagName(tag);\n // Live HTMLCollection shrinks as we remove — always take index 0.\n while (nodes.length > 0) {\n const n = nodes[0];\n if (n.parentNode) n.parentNode.removeChild(n);\n else break;\n }\n }\n\n // A <base> makes relative asset URLs resolve against the original page\n // when the panel renders the snapshot from a different origin.\n try {\n const head = clone.querySelector('head');\n if (head && !head.querySelector('base')) {\n const base = document.createElement('base');\n base.setAttribute('href', document.baseURI || location.href);\n head.insertBefore(base, head.firstChild);\n }\n } catch {\n /* ignore */\n }\n\n let html = clone.outerHTML || '';\n if (html.length > opts.maxBytes) {\n // Oversized pages are dropped rather than truncated: half a DOM\n // renders as garbage and would be more confusing than nothing.\n return null;\n }\n\n const css = collectCss(Math.max(0, opts.maxBytes - html.length));\n\n return {\n kind: 'dom',\n html,\n css: css || undefined,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n scrollX: window.scrollX || 0,\n scrollY: window.scrollY || 0,\n },\n url: location.href,\n taken_at: nowIso(),\n };\n } catch {\n return null;\n }\n}\n","import type { VitalMetric, VitalsOptions } from './types';\nimport { isBrowser } from './env';\nimport { nowIso, safe, selectorFor } from './utils';\n\n/**\n * Web Vitals and render-performance collection.\n *\n * This is the browser's answer to the \"why is my page slow, what do I do about\n * it\" question — the same role slow-query capture plays on the server side.\n * Everything here rides on PerformanceObserver, which the browser computes\n * anyway, so the CPU cost is effectively zero. No external dependency: the\n * web-vitals package would add weight for logic that is a few hundred lines.\n *\n * Metrics are buffered and flushed once, when the page is hidden. A page load\n * has no single \"done\" moment — LCP and CLS keep changing until the user\n * leaves — so reporting early would report the wrong number.\n */\n\n// Google's good / needs-improvement thresholds. Above the second value is poor.\nconst THRESHOLDS: Record<string, [number, number]> = {\n LCP: [2500, 4000],\n FCP: [1800, 3000],\n CLS: [0.1, 0.25],\n INP: [200, 500],\n TTFB: [800, 1800],\n};\n\nexport function rate(name: string, value: number): VitalMetric['rating'] | undefined {\n const t = THRESHOLDS[name];\n if (!t) return undefined;\n if (value <= t[0]) return 'good';\n if (value <= t[1]) return 'needs-improvement';\n return 'poor';\n}\n\ntype Flush = (metrics: VitalMetric[]) => void;\n\nexport class VitalsCollector {\n private metrics: VitalMetric[] = [];\n private observers: PerformanceObserver[] = [];\n private flushed = false;\n /** LCP/CLS/INP are \"final value wins\" — keyed so later values replace. */\n private latest: Record<string, VitalMetric> = {};\n\n constructor(\n private opts: Required<VitalsOptions>,\n private flush: Flush,\n ) {}\n\n start(): void {\n if (!isBrowser || !this.opts.enabled) return;\n if (typeof PerformanceObserver !== 'function') return;\n\n this.observeTtfb();\n this.observePaint();\n this.observeLcp();\n this.observeCls();\n this.observeInp();\n this.observeLongTasks();\n this.observeResources();\n this.installFlushTriggers();\n }\n\n stop(): void {\n for (const o of this.observers) safe(() => o.disconnect());\n this.observers = [];\n }\n\n /** Manually add a metric — adapters use this for component render times. */\n push(metric: VitalMetric): void {\n try {\n this.metrics.push({\n ...metric,\n rating: metric.rating ?? rate(metric.name, metric.value),\n url: metric.url ?? location.href,\n occurred_at: metric.occurred_at ?? nowIso(),\n });\n } catch {\n /* ignore */\n }\n }\n\n private set(name: string, value: number, extra: Partial<VitalMetric> = {}): void {\n this.latest[name] = {\n name,\n value: Math.round(value * 1000) / 1000,\n rating: rate(name, value),\n url: safe(() => location.href),\n occurred_at: nowIso(),\n ...extra,\n };\n }\n\n private observe(type: string, cb: (entries: PerformanceEntryList) => void, buffered = true): void {\n safe(() => {\n const obs = new PerformanceObserver((list) => safe(() => cb(list.getEntries())));\n // `buffered` replays entries that fired before the SDK loaded —\n // without it, a late-initialised SDK misses FCP and LCP entirely.\n obs.observe({ type, buffered } as PerformanceObserverInit);\n this.observers.push(obs);\n });\n }\n\n private observeTtfb(): void {\n safe(() => {\n const nav = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming;\n if (nav && typeof nav.responseStart === 'number' && nav.responseStart > 0) {\n this.set('TTFB', nav.responseStart, { navigation_type: nav.type });\n }\n });\n }\n\n private observePaint(): void {\n this.observe('paint', (entries) => {\n for (const e of entries) {\n if (e.name === 'first-contentful-paint') this.set('FCP', e.startTime);\n }\n });\n }\n\n private observeLcp(): void {\n this.observe('largest-contentful-paint', (entries) => {\n // Only the LAST entry counts: the browser keeps upgrading its guess\n // at the largest element as more content paints.\n const last: any = entries[entries.length - 1];\n if (!last) return;\n this.set('LCP', last.startTime, {\n target: selectorFor(last.element),\n data: { size: last.size, url: last.url || undefined },\n });\n });\n }\n\n private observeCls(): void {\n let clsValue = 0;\n let sessionValue = 0;\n let sessionEntries: any[] = [];\n\n this.observe('layout-shift', (entries) => {\n for (const entry of entries as any[]) {\n // Shifts the user caused (typing, clicking) are not penalised.\n if (entry.hadRecentInput) continue;\n\n const first = sessionEntries[0];\n const last = sessionEntries[sessionEntries.length - 1];\n\n // CLS is the worst 5-second / 1-second-gap window, not the sum\n // of everything — a long session would otherwise always fail.\n if (\n sessionValue &&\n entry.startTime - last.startTime < 1000 &&\n entry.startTime - first.startTime < 5000\n ) {\n sessionValue += entry.value;\n sessionEntries.push(entry);\n } else {\n sessionValue = entry.value;\n sessionEntries = [entry];\n }\n\n if (sessionValue > clsValue) {\n clsValue = sessionValue;\n const worst = sessionEntries\n .slice()\n .sort((a, b) => b.value - a.value)[0];\n this.set('CLS', clsValue, {\n target: worst?.sources?.[0]\n ? selectorFor(worst.sources[0].node)\n : undefined,\n });\n }\n }\n });\n }\n\n private observeInp(): void {\n let worst = 0;\n this.observe('event', (entries) => {\n for (const entry of entries as any[]) {\n const duration = entry.duration;\n if (typeof duration !== 'number' || duration <= worst) continue;\n worst = duration;\n this.set('INP', duration, {\n target: selectorFor(entry.target),\n data: { interaction: entry.name },\n });\n }\n });\n }\n\n private observeLongTasks(): void {\n this.observe('longtask', (entries) => {\n for (const e of entries) {\n if (e.duration < this.opts.longTaskMs) continue;\n this.push({\n name: 'LONG_TASK',\n value: Math.round(e.duration),\n rating: e.duration > 200 ? 'poor' : 'needs-improvement',\n target: (e as any).attribution?.[0]?.containerName || undefined,\n data: { start: Math.round(e.startTime) },\n });\n }\n });\n }\n\n private observeResources(): void {\n this.observe('resource', (entries) => {\n for (const e of entries as PerformanceResourceTiming[]) {\n if (e.duration < this.opts.slowResourceMs) continue;\n // Our own ingest calls are not the customer's problem.\n if (e.name.indexOf('/api/ingest/') !== -1) continue;\n this.push({\n name: 'RESOURCE',\n value: Math.round(e.duration),\n rating: e.duration > 3000 ? 'poor' : 'needs-improvement',\n target: e.name,\n data: {\n type: e.initiatorType,\n size: e.transferSize || undefined,\n cached: e.transferSize === 0 && e.decodedBodySize > 0,\n },\n });\n }\n });\n }\n\n /**\n * Flush when the page is hidden. `visibilitychange` fires reliably on\n * mobile where `beforeunload` often does not; `pagehide` covers bfcache.\n */\n private installFlushTriggers(): void {\n const doFlush = () => this.flushNow();\n safe(() => {\n document.addEventListener(\n 'visibilitychange',\n () => {\n if (document.visibilityState === 'hidden') doFlush();\n },\n { capture: true },\n );\n window.addEventListener('pagehide', doFlush, { capture: true });\n });\n }\n\n flushNow(): void {\n if (this.flushed) return;\n try {\n const all = this.metrics.concat(Object.keys(this.latest).map((k) => this.latest[k]));\n if (all.length === 0) return;\n this.flushed = true;\n this.metrics = [];\n this.latest = {};\n this.flush(all);\n } catch {\n /* ignore */\n }\n }\n}\n","import type { ConsoleOptions, Level } from '../types';\nimport { safe, truncate } from '../utils';\n\n/**\n * console.* interception.\n *\n * Most real-world failures never reach window.onerror: the app catches the\n * error, logs it with console.error, and shows a generic \"something went\n * wrong\". Those are exactly the ones a developer wants reported, so\n * console.error becomes a first-class event, not just a breadcrumb.\n *\n * The original console methods are always called — the developer's own logging\n * must behave identically with the SDK installed.\n */\n\nexport interface ConsoleHooks {\n breadcrumb: (level: Level, message: string, args: unknown[]) => void;\n capture: (level: Level, message: string, args: unknown[]) => void;\n}\n\nconst LEVEL_MAP: Record<string, Level> = {\n log: 'info',\n info: 'info',\n debug: 'debug',\n warn: 'warning',\n error: 'error',\n};\n\n/** Was an actual Error passed to console.error, or just text? */\nfunction hasErrorArg(args: unknown[]): boolean {\n for (const a of args) {\n if (a instanceof Error) return true;\n }\n return false;\n}\n\nexport function installConsole(opts: Required<ConsoleOptions>, hooks: ConsoleHooks): () => void {\n if (typeof console === 'undefined') return () => {};\n\n const originals: Record<string, any> = {};\n // Re-entrancy guard: if a hook itself logs (or the transport warns in debug\n // mode), we must not recurse into our own interceptor.\n let inside = false;\n\n for (const method of opts.levels) {\n const original = (console as any)[method];\n if (typeof original !== 'function') continue;\n originals[method] = original;\n\n (console as any)[method] = function (...args: unknown[]) {\n try {\n if (!inside) {\n inside = true;\n const level = LEVEL_MAP[method] || 'info';\n const message = args\n .map((a) => (typeof a === 'string' ? a : truncate(a, 200)))\n .join(' ');\n\n hooks.breadcrumb(level, truncate(message, 500), args);\n\n if (\n (method === 'error' || method === 'warn') &&\n opts.captureAsEvent.indexOf(method as 'error' | 'warn') !== -1\n ) {\n // When the logged value is a real Error, some other\n // handler is usually about to report the same throw with\n // far better context — React logs a render crash to the\n // console just before componentDidCatch runs, and the\n // boundary knows the component stack while we only know\n // \"console\".\n //\n // Yield a tick so the richer reporter claims it first;\n // the client's identity-based dedupe then drops this\n // one. If nobody else claims it, this still fires and\n // the error is reported — only ~50ms later.\n if (hasErrorArg(args)) {\n const deferred = () => safe(() => hooks.capture(level, message, args));\n safe(() => {\n const t: any = setTimeout(deferred, 50);\n // Never hold a Node process open for this.\n if (t && typeof t.unref === 'function') t.unref();\n });\n } else {\n hooks.capture(level, message, args);\n }\n }\n inside = false;\n }\n } catch {\n inside = false;\n }\n\n // Always pass through to the real console.\n return safe(() => original.apply(console, args));\n };\n }\n\n return () => {\n for (const m in originals) {\n safe(() => {\n (console as any)[m] = originals[m];\n });\n }\n };\n}\n","/**\n * PII / secret redaction.\n *\n * The SDK sends request metadata and breadcrumbs to a server the developer\n * controls but their end users do not. Anything that looks like a credential\n * is replaced before it leaves the process. This runs on data the SDK collects\n * itself AND on data the app hands us via setContext/addBreadcrumb.\n */\n\nexport const DEFAULT_REDACT_KEYS = [\n 'password',\n 'passwd',\n 'pwd',\n 'secret',\n 'token',\n 'access_token',\n 'refresh_token',\n 'api_key',\n 'apikey',\n 'authorization',\n 'auth',\n 'cookie',\n 'set-cookie',\n 'session',\n 'csrf',\n 'xsrf',\n 'card',\n 'card_number',\n 'cardnumber',\n 'cvv',\n 'cvc',\n 'pin',\n 'ssn',\n 'iban',\n];\n\nexport const REDACTED = '[redacted]';\n\nfunction isSensitiveKey(key: string, extra: string[]): boolean {\n const k = key.toLowerCase();\n for (const s of DEFAULT_REDACT_KEYS) {\n if (k.indexOf(s) !== -1) return true;\n }\n for (const s of extra) {\n if (s && k.indexOf(s.toLowerCase()) !== -1) return true;\n }\n return false;\n}\n\n/**\n * Deep-redact an object by key name. Depth-limited so a pathological structure\n * cannot lock up the main thread.\n */\nexport function redact<T>(value: T, extraKeys: string[] = [], depth = 0): T {\n if (depth > 6 || value == null) return value;\n\n try {\n if (Array.isArray(value)) {\n return value.slice(0, 100).map((v) => redact(v, extraKeys, depth + 1)) as unknown as T;\n }\n if (typeof value === 'object') {\n const src = value as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n let count = 0;\n for (const key in src) {\n if (!Object.prototype.hasOwnProperty.call(src, key)) continue;\n if (++count > 100) break;\n out[key] = isSensitiveKey(key, extraKeys)\n ? REDACTED\n : redact(src[key], extraKeys, depth + 1);\n }\n return out as unknown as T;\n }\n } catch {\n /* fall through — return the value untouched rather than crash */\n }\n\n return value;\n}\n\n/**\n * Strip credentials out of a URL: query params named like secrets, plus any\n * user:pass@ prefix. Returns the input unchanged if it cannot be parsed.\n */\nexport function redactUrl(url: string, extraKeys: string[] = []): string {\n try {\n // Relative URLs need a base to parse; the base is discarded after.\n const hasScheme = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(url);\n const u = new URL(url, hasScheme ? undefined : 'http://localhost');\n\n if (u.username || u.password) {\n u.username = '';\n u.password = '';\n }\n u.searchParams.forEach((_v, k) => {\n if (isSensitiveKey(k, extraKeys)) u.searchParams.set(k, REDACTED);\n });\n\n return hasScheme ? u.toString() : u.pathname + u.search + u.hash;\n } catch {\n return url;\n }\n}\n\n/** Header maps arrive in several shapes (Headers, array pairs, plain object). */\nexport function redactHeaders(\n headers: unknown,\n extraKeys: string[] = [],\n): Record<string, string> | undefined {\n try {\n const out: Record<string, string> = {};\n const put = (k: string, v: unknown) => {\n out[k] = isSensitiveKey(k, extraKeys) ? REDACTED : String(v);\n };\n\n const h = headers as any;\n if (!h) return undefined;\n\n if (typeof h.forEach === 'function' && typeof h.get === 'function') {\n h.forEach((v: unknown, k: string) => put(k, v));\n return out;\n }\n if (Array.isArray(h)) {\n for (const pair of h) {\n if (Array.isArray(pair) && pair.length >= 2) put(String(pair[0]), pair[1]);\n }\n return out;\n }\n if (typeof h === 'object') {\n for (const k in h) {\n if (Object.prototype.hasOwnProperty.call(h, k)) put(k, h[k]);\n }\n return out;\n }\n } catch {\n /* ignore */\n }\n return undefined;\n}\n","import type { NetworkOptions } from '../types';\nimport { matchesAny, safe } from '../utils';\nimport { redactUrl } from '../redact';\n\n/**\n * fetch / XMLHttpRequest instrumentation.\n *\n * \"The button did nothing\" is almost always a failed request. Recording method,\n * URL, status and duration turns that into an obvious answer. Request and\n * response BODIES are never captured — they are the most likely place for\n * personal data, and the status code alone answers the question.\n */\n\nexport interface NetworkHooks {\n breadcrumb: (message: string, data: Record<string, unknown>, failed: boolean) => void;\n capture: (message: string, data: Record<string, unknown>) => void;\n}\n\nexport function installNetwork(\n opts: Required<NetworkOptions>,\n hooks: NetworkHooks,\n redactKeys: string[],\n ownHost: string,\n): () => void {\n const undo: Array<() => void> = [];\n\n const ignored = (url: string): boolean => {\n // Never record our own ingest traffic: it would create a feedback loop\n // where reporting an error generates a breadcrumb that is then reported.\n if (url.indexOf('/api/ingest/') !== -1) return true;\n if (ownHost && url.indexOf(ownHost) === 0) return true;\n return matchesAny(url, opts.ignoreUrls);\n };\n\n const record = (\n method: string,\n rawUrl: string,\n status: number | undefined,\n startedAt: number,\n errored: boolean,\n ) => {\n try {\n const url = redactUrl(rawUrl, redactKeys);\n const duration = Math.round(now() - startedAt);\n const failed = errored || (typeof status === 'number' && status >= 400);\n\n const data: Record<string, unknown> = {\n method,\n url,\n status_code: status,\n duration_ms: duration,\n };\n\n const label = `${method} ${url} → ${errored ? 'failed' : status} (${duration}ms)`;\n hooks.breadcrumb(label, data, failed);\n\n // A 5xx or a transport failure is a real incident; a 404 usually is\n // not, so only the former becomes its own event.\n if (opts.captureFailures && (errored || (status !== undefined && status >= 500))) {\n hooks.capture(label, data);\n }\n } catch {\n /* ignore */\n }\n };\n\n if (opts.enabled && typeof fetch === 'function') {\n const original = fetch;\n const patched = function (this: unknown, input: any, init?: any) {\n let url = '';\n let method = 'GET';\n const started = now();\n\n try {\n url = typeof input === 'string' ? input : input && input.url ? input.url : String(input);\n method = String((init && init.method) || (input && input.method) || 'GET').toUpperCase();\n } catch {\n /* ignore */\n }\n\n if (!url || ignored(url)) return original.apply(this as any, [input, init] as any);\n\n return original.apply(this as any, [input, init] as any).then(\n (res: Response) => {\n record(method, url, res ? res.status : undefined, started, false);\n return res;\n },\n (err: unknown) => {\n record(method, url, undefined, started, true);\n throw err;\n },\n );\n };\n (globalThis as any).fetch = patched;\n undo.push(() => {\n (globalThis as any).fetch = original;\n });\n }\n\n if (opts.enabled && typeof XMLHttpRequest === 'function') {\n const proto = XMLHttpRequest.prototype as any;\n const origOpen = proto.open;\n const origSend = proto.send;\n\n proto.open = function (method: string, url: string, ...rest: unknown[]) {\n safe(() => {\n this.__bugban = { method: String(method || 'GET').toUpperCase(), url: String(url || '') };\n });\n return origOpen.apply(this, [method, url, ...rest] as any);\n };\n\n proto.send = function (...args: unknown[]) {\n const meta = safe(() => this.__bugban) as { method: string; url: string } | undefined;\n if (meta && meta.url && !ignored(meta.url)) {\n const started = now();\n safe(() => {\n this.addEventListener('loadend', () => {\n // status 0 means the request never completed (CORS,\n // offline, aborted) — that is a failure, not a 0 code.\n const status = this.status || undefined;\n record(meta.method, meta.url, status, started, !status);\n });\n });\n }\n return origSend.apply(this, args as any);\n };\n\n undo.push(() => {\n proto.open = origOpen;\n proto.send = origSend;\n });\n }\n\n return () => {\n for (const fn of undo) safe(fn);\n };\n}\n\nfunction now(): number {\n try {\n return typeof performance !== 'undefined' && typeof performance.now === 'function'\n ? performance.now()\n : Date.now();\n } catch {\n return Date.now();\n }\n}\n","import { isBrowser, isNode } from '../env';\nimport { safe } from '../utils';\n\n/**\n * Global error handlers.\n *\n * Browser: window.onerror and unhandledrejection. Node: uncaughtException and\n * unhandledRejection.\n *\n * The Node side deliberately does NOT swallow a fatal error. Keeping a process\n * alive after an uncaught exception leaves it in an undefined state; the SDK's\n * job is to report and then let the default behaviour happen. This is the same\n * lesson the PHP SDK carries: telemetry must never change how the host app\n * behaves.\n */\n\nexport interface GlobalHooks {\n capture: (error: unknown, extra: { handled: boolean; type?: string }) => void;\n /** Give the transport a moment to flush before the process dies. */\n flush: () => Promise<void>;\n}\n\nexport function installGlobalHandlers(hooks: GlobalHooks): () => void {\n const undo: Array<() => void> = [];\n\n if (isBrowser) {\n const onError = (event: ErrorEvent) => {\n safe(() => {\n // event.error carries the real stack; message-only events (e.g.\n // cross-origin \"Script error.\") still produce a usable record.\n const err =\n event.error ||\n ({\n name: 'Error',\n message: event.message,\n stack: undefined,\n } as any);\n hooks.capture(err, { handled: false, type: 'onerror' });\n });\n };\n\n const onRejection = (event: PromiseRejectionEvent) => {\n safe(() => {\n const reason = (event as any).reason;\n hooks.capture(reason, { handled: false, type: 'unhandledrejection' });\n });\n };\n\n safe(() => window.addEventListener('error', onError, true));\n safe(() => window.addEventListener('unhandledrejection', onRejection as any, true));\n\n undo.push(() => {\n safe(() => window.removeEventListener('error', onError, true));\n safe(() => window.removeEventListener('unhandledrejection', onRejection as any, true));\n });\n }\n\n if (isNode) {\n const onUncaught = (err: unknown) => {\n hooks.capture(err, { handled: false, type: 'uncaughtException' });\n // Flush, then re-raise the default behaviour. If another listener is\n // registered, Node will not exit on its own — that is the host's\n // choice and we must not override it.\n safe(() => {\n void hooks.flush().then(() => {\n if (process.listenerCount('uncaughtException') <= 1) {\n process.exit(1);\n }\n });\n });\n };\n\n const onUnhandled = (reason: unknown) => {\n hooks.capture(reason, { handled: false, type: 'unhandledRejection' });\n };\n\n safe(() => process.on('uncaughtException', onUncaught));\n safe(() => process.on('unhandledRejection', onUnhandled));\n // Best-effort flush of anything still queued at normal shutdown.\n safe(() => process.on('beforeExit', () => void hooks.flush()));\n\n undo.push(() => {\n safe(() => process.off('uncaughtException', onUncaught));\n safe(() => process.off('unhandledRejection', onUnhandled));\n });\n }\n\n return () => {\n for (const fn of undo) safe(fn);\n };\n}\n","import { isBrowser } from '../env';\nimport { safe, selectorFor, truncate } from '../utils';\n\n/**\n * Click and navigation breadcrumbs.\n *\n * These are the \"what was the user doing\" half of the story. Only the element's\n * selector and its visible label are recorded — never the value of any field\n * the user typed into.\n *\n * SPA route changes do not fire a page load, so history.pushState/replaceState\n * are wrapped as well; without that a React or Vue app looks like it never\n * navigates.\n */\n\nexport interface DomHooks {\n click: (label: string, data: Record<string, unknown>) => void;\n navigate: (from: string, to: string) => void;\n}\n\n/** A short human label for a clicked element, safe to record. */\nfunction labelFor(el: Element): string {\n return (\n safe(() => {\n const aria = el.getAttribute('aria-label');\n if (aria) return truncate(aria, 60);\n\n const tag = el.tagName.toLowerCase();\n // Inputs: the label is the placeholder or name, NEVER the value.\n if (tag === 'input' || tag === 'textarea' || tag === 'select') {\n const ph = el.getAttribute('placeholder') || el.getAttribute('name') || '';\n return ph ? `${tag}[${truncate(ph, 40)}]` : tag;\n }\n\n const text = (el.textContent || '').trim().replace(/\\s+/g, ' ');\n return text ? truncate(text, 60) : tag;\n }) || 'element'\n );\n}\n\nexport function installDomBreadcrumbs(hooks: DomHooks): () => void {\n if (!isBrowser) return () => {};\n\n const undo: Array<() => void> = [];\n\n const onClick = (event: Event) => {\n safe(() => {\n const target = event.target as Element;\n if (!target || typeof (target as any).tagName !== 'string') return;\n\n // Walk up to the nearest interactive ancestor: a click usually\n // lands on the <span> inside a <button>, which is not the story.\n let el: Element | null = target;\n for (let i = 0; i < 4 && el; i++) {\n const tag = el.tagName.toLowerCase();\n if (tag === 'button' || tag === 'a' || el.getAttribute('role') === 'button') break;\n el = el.parentElement;\n }\n const chosen = el || target;\n\n hooks.click(labelFor(chosen), {\n selector: selectorFor(chosen),\n href: safe(() => chosen.getAttribute('href')) || undefined,\n });\n });\n };\n\n safe(() => document.addEventListener('click', onClick, { capture: true, passive: true }));\n undo.push(() => safe(() => document.removeEventListener('click', onClick, true)));\n\n // --- SPA navigation -----------------------------------------------------\n let current = safe(() => location.href) || '';\n\n const report = () => {\n safe(() => {\n const next = location.href;\n if (next !== current) {\n hooks.navigate(current, next);\n current = next;\n }\n });\n };\n\n safe(() => {\n const history = window.history as any;\n const origPush = history.pushState;\n const origReplace = history.replaceState;\n\n if (typeof origPush === 'function') {\n history.pushState = function (...args: unknown[]) {\n const r = origPush.apply(this, args as any);\n report();\n return r;\n };\n undo.push(() => {\n history.pushState = origPush;\n });\n }\n if (typeof origReplace === 'function') {\n history.replaceState = function (...args: unknown[]) {\n const r = origReplace.apply(this, args as any);\n report();\n return r;\n };\n undo.push(() => {\n history.replaceState = origReplace;\n });\n }\n });\n\n safe(() => window.addEventListener('popstate', report));\n undo.push(() => safe(() => window.removeEventListener('popstate', report)));\n\n return () => {\n for (const fn of undo) safe(fn);\n };\n}\n","import type { ResolvedOptions } from './types';\nimport type { Transport } from './transport';\nimport {\n SDK_NAME,\n SDK_VERSION,\n appPackageInfo,\n hostname,\n isBrowser,\n isNode,\n runtimeName,\n runtimeVersion,\n} from './env';\nimport { safe } from './utils';\n\n/**\n * One-time install ping.\n *\n * The panel needs to distinguish \"the SDK is installed and quiet\" from \"the SDK\n * was never wired up\" — otherwise a correctly working integration looks\n * identical to a broken one. This is the same handshake the PHP SDK sends;\n * `POST /api/ingest/ping` fills first_ping_at / last_ping_at / sdk_info and the\n * project page turns into \"SDK connected ✓\".\n *\n * Fires at most once per install. The marker differs by runtime because there\n * is no shared notion of persistent state: a temp file in Node, localStorage\n * in the browser (falling back to a per-page in-memory flag in private mode).\n */\n\nconst MARKER_KEY = 'bugban.ping';\nlet memoryMarker = false;\n\nasync function alreadyPinged(apiKey: string, version: string): Promise<boolean> {\n const stamp = `${apiKey.slice(0, 12)}:${version}`;\n\n if (isBrowser) {\n const stored = safe(() => localStorage.getItem(MARKER_KEY));\n if (stored === stamp) return true;\n safe(() => localStorage.setItem(MARKER_KEY, stamp));\n // Private mode throws on setItem — fall back to once per page load\n // rather than pinging on every single error.\n if (memoryMarker) return true;\n memoryMarker = true;\n return false;\n }\n\n if (isNode) {\n try {\n const [fs, os, path] = await Promise.all([\n nodeModule('fs'),\n nodeModule('os'),\n nodeModule('path'),\n ]);\n if (!fs || !os || !path || typeof fs.existsSync !== 'function') {\n // No filesystem access (bundled/edge runtime): degrade to\n // once per process instead of pinging on every error.\n if (memoryMarker) return true;\n memoryMarker = true;\n return false;\n }\n const key = toHex(stamp).slice(0, 32);\n const file = path.join(os.tmpdir(), `.bugban-ping-${key}`);\n if (fs.existsSync(file)) return true;\n fs.writeFileSync(file, stamp);\n return false;\n } catch {\n return false;\n }\n }\n\n if (memoryMarker) return true;\n memoryMarker = true;\n return false;\n}\n\n/** Buffer is not guaranteed outside Node, so the marker name is hashed by hand. */\nfunction toHex(s: string): string {\n let out = '';\n for (let i = 0; i < s.length; i++) {\n out += s.charCodeAt(i).toString(16);\n }\n return out;\n}\n\nexport async function sendInstallPing(opts: ResolvedOptions, transport: Transport): Promise<void> {\n if (!opts.installPing || !opts.enabled) return;\n\n try {\n if (await alreadyPinged(opts.apiKey, SDK_VERSION)) return;\n\n const pkg = await appPackageInfo();\n const host = await hostname();\n\n const payload: Record<string, unknown> = {\n sdk: SDK_NAME,\n sdk_version: SDK_VERSION,\n framework: opts.framework || runtimeName(),\n framework_version: opts.frameworkVersion,\n environment: opts.environment,\n hostname: host,\n\n // The app's own identity. In Node this is read from package.json; in\n // the browser there is no filesystem, so it comes from `release`\n // (usually wired to the bundler's define) and the page host.\n app_name: pkg.name || (isBrowser ? safe(() => location.hostname) : undefined),\n app_version: opts.release || pkg.version,\n\n // Where the SDK is running, and that runtime's version: Node's\n // process.version, or the browser UA. The panel shows this the same\n // way it shows the PHP version for the PHP SDKs.\n runtime: runtimeName(),\n runtime_version: runtimeVersion(),\n };\n\n // Drop empty fields so a sparse ping never overwrites what the server\n // already learned from a richer one.\n for (const k in payload) {\n if (payload[k] == null || payload[k] === '') delete payload[k];\n }\n\n void transport.send('/api/ingest/ping', payload);\n } catch {\n // A failed handshake must never surface to the host application.\n }\n}\n","import type {\n Breadcrumb,\n BugbanEvent,\n BugbanOptions,\n Level,\n ResolvedOptions,\n UserInfo,\n VitalMetric,\n} from './types';\nimport { resolveOptions } from './config';\nimport { Transport } from './transport';\nimport { BreadcrumbBuffer } from './breadcrumbs';\nimport { normalizeError, parseStack } from './stacktrace';\nimport { takeSnapshot } from './snapshot';\nimport { VitalsCollector } from './vitals';\nimport { installConsole } from './integrations/console';\nimport { installNetwork } from './integrations/network';\nimport { installGlobalHandlers } from './integrations/globals';\nimport { installDomBreadcrumbs } from './integrations/dom';\nimport { sendInstallPing } from './ping';\nimport { deviceInfo, isBrowser } from './env';\nimport { redact, redactUrl } from './redact';\nimport { matchesAny, nowIso, randomId, safe, sampled, truncate } from './utils';\n\n/**\n * The SDK client.\n *\n * One rule governs every method here: nothing may throw into the host\n * application, and nothing may block it. Every public entry point is wrapped,\n * every optional browser API is feature-detected, and delivery is\n * fire-and-forget. A monitoring tool that can take down the app it monitors is\n * worse than no monitoring at all.\n */\nexport class BugbanClient {\n private opts: ResolvedOptions;\n private transport: Transport;\n private crumbs: BreadcrumbBuffer;\n private vitals?: VitalsCollector;\n private teardown: Array<() => void> = [];\n\n private user: UserInfo | null = null;\n private context: Record<string, unknown> = {};\n private sessionId = randomId();\n private startedAt = Date.now();\n\n /** Events waiting to be sent, coalesced so an error storm is one request. */\n private queue: BugbanEvent[] = [];\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n /** Guard against reporting an error that our own reporting caused. */\n private sending = false;\n\n /**\n * Error objects already reported, so a throw seen by two handlers is only\n * sent once. A WeakSet holds no strong reference, so entries disappear with\n * the errors themselves and this can never grow into a leak.\n */\n private seen = new WeakSet<object>();\n private started = false;\n\n constructor(options: BugbanOptions = {}) {\n this.opts = resolveOptions(options);\n this.transport = new Transport(this.opts.host, this.opts.apiKey, this.opts.debug);\n this.crumbs = new BreadcrumbBuffer(this.opts.maxBreadcrumbs);\n }\n\n get options(): ResolvedOptions {\n return this.opts;\n }\n\n /** Wire up integrations. Safe to call twice — the second call is ignored. */\n start(): void {\n if (this.started) return;\n this.started = true;\n\n // No API key → the SDK is inert. Same contract as the PHP SDK: an app\n // shipped without configuration must behave as if we were not there.\n if (!this.opts.enabled) {\n this.debug('disabled (no API key)');\n return;\n }\n\n safe(() => this.installIntegrations());\n safe(() => sendInstallPing(this.opts, this.transport));\n }\n\n private installIntegrations(): void {\n const o = this.opts;\n\n if (o.globalHandlers) {\n this.teardown.push(\n installGlobalHandlers({\n capture: (err, extra) => this.capture(err, extra),\n flush: () => this.flush(),\n }),\n );\n }\n\n if (o.console) {\n this.teardown.push(\n installConsole(o.console, {\n breadcrumb: (level, message) =>\n this.addBreadcrumb({ type: 'console', level, message }),\n capture: (level, message, args) => {\n // console.error(err) — prefer the real Error argument so\n // the event carries a stack instead of a stringified one.\n const real = args.find((a) => a instanceof Error);\n this.capture(real ?? message, {\n handled: true,\n type: 'console',\n level,\n });\n },\n }),\n );\n }\n\n if (o.network) {\n this.teardown.push(\n installNetwork(\n o.network,\n {\n breadcrumb: (message, data, failed) =>\n this.addBreadcrumb({\n type: 'http',\n level: failed ? 'error' : 'info',\n message,\n data,\n }),\n capture: (message, data) =>\n this.capture(new Error(message), {\n handled: true,\n type: 'http',\n context: data,\n }),\n },\n o.redactKeys,\n o.host,\n ),\n );\n }\n\n if (o.domBreadcrumbs) {\n this.teardown.push(\n installDomBreadcrumbs({\n click: (label, data) =>\n this.addBreadcrumb({ type: 'click', message: `Clicked ${label}`, data }),\n navigate: (from, to) =>\n this.addBreadcrumb({\n type: 'navigation',\n message: `${redactUrl(from, o.redactKeys)} → ${redactUrl(to, o.redactKeys)}`,\n }),\n }),\n );\n }\n\n if (o.vitals && isBrowser) {\n // Sample per session, not per metric: half a page's vitals would be\n // meaningless, and the decision has to be stable for the session.\n if (sampled(o.vitals.sampleRate)) {\n this.vitals = new VitalsCollector(o.vitals, (metrics) => this.sendVitals(metrics));\n this.vitals.start();\n this.teardown.push(() => this.vitals?.stop());\n } else {\n this.debug('vitals not sampled for this session');\n }\n }\n\n if (isBrowser) {\n this.teardown.push(this.installUnloadFlush());\n }\n }\n\n /**\n * Send whatever is queued before the page goes away.\n *\n * Events are batched with a short debounce so an error loop becomes one\n * request instead of hundreds. That debounce loses the last batch whenever\n * the user navigates immediately after the error — which is the common\n * case, not an edge case: click a link, something throws, the document is\n * torn down before the timer fires. Observed exactly that while testing:\n * an uncaught TypeError never arrived while the beacon-based vitals from the\n * same page did.\n *\n * `visibilitychange` is the reliable signal (mobile Safari often skips\n * `beforeunload`), and `pagehide` covers the bfcache case. Both drain with\n * `beacon: true`, the only delivery a closing document is guaranteed to\n * complete.\n */\n private installUnloadFlush(): () => void {\n const onHide = () => {\n // `hidden` also fires on tab switch, which is fine — flushing early\n // costs one request and never loses data.\n if (document.visibilityState === 'hidden') void this.drain(true);\n };\n const onPageHide = () => void this.drain(true);\n\n safe(() => document.addEventListener('visibilitychange', onHide, true));\n safe(() => window.addEventListener('pagehide', onPageHide, true));\n\n return () => {\n safe(() => document.removeEventListener('visibilitychange', onHide, true));\n safe(() => window.removeEventListener('pagehide', onPageHide, true));\n };\n }\n\n // --- public API ---------------------------------------------------------\n\n addBreadcrumb(crumb: Omit<Breadcrumb, 'timestamp'> & { timestamp?: string }): void {\n if (!this.opts.enabled) return;\n safe(() => {\n let c: Breadcrumb = {\n ...crumb,\n data: crumb.data ? redact(crumb.data, this.opts.redactKeys) : undefined,\n timestamp: crumb.timestamp || nowIso(),\n };\n if (this.opts.beforeBreadcrumb) {\n const out = this.opts.beforeBreadcrumb(c);\n if (!out) return;\n c = out;\n }\n this.crumbs.add(c);\n });\n }\n\n setUser(user: UserInfo | null): void {\n safe(() => {\n this.user = user ? (redact(user, this.opts.redactKeys) as UserInfo) : null;\n });\n }\n\n setContext(key: string, value: unknown): void {\n safe(() => {\n this.context[key] = redact(value, this.opts.redactKeys);\n });\n }\n\n captureMessage(message: string, level: Level = 'info'): void {\n this.capture(new Error(message), { handled: true, level, type: 'message' });\n }\n\n /** Report an error. Never throws, never blocks. */\n capture(\n error: unknown,\n extra: {\n handled?: boolean;\n level?: Level;\n type?: string;\n context?: Record<string, unknown>;\n request?: Record<string, unknown>;\n } = {},\n ): void {\n if (!this.opts.enabled) return;\n // Reporting must not report itself.\n if (this.sending) return;\n\n // One throw, several observers.\n //\n // Frameworks route errors through their own handler AND log them to the\n // console, so a single React render crash arrives twice: once from the\n // console integration, once from the error boundary. Observed exactly\n // that — the event landed with occurrences=2 and the wrong type.\n //\n // Identity is the Error OBJECT, not its message: a genuine repeating\n // error (a render loop) constructs a new Error every time, so this\n // cannot swallow real recurrences the way a message-based check would.\n if (typeof error === 'object' && error !== null) {\n if (this.seen.has(error as object)) return;\n safe(() => this.seen.add(error as object));\n }\n\n safe(() => {\n const norm = normalizeError(error);\n\n if (this.opts.ignoreErrors.length && matchesAny(norm.message, this.opts.ignoreErrors)) {\n return;\n }\n if (!sampled(this.opts.sampleRate)) return;\n\n const frames = parseStack(norm.stack);\n const top = frames.find((f) => f.in_app) || frames[0];\n\n let event: BugbanEvent = {\n exception_class: norm.name,\n message: truncate(norm.message, 2000),\n level: extra.level || 'error',\n type: extra.type || 'error',\n handled: extra.handled ?? true,\n file: top?.file,\n line: top?.line,\n stacktrace: frames,\n release: this.opts.release,\n environment: this.opts.environment,\n user: this.user,\n breadcrumbs: this.crumbs.all(),\n device: deviceInfo(),\n session: {\n id: this.sessionId,\n started_at: new Date(this.startedAt).toISOString(),\n duration_ms: Date.now() - this.startedAt,\n },\n request: extra.request || this.requestInfo(),\n context: {\n ...this.context,\n ...(extra.context ? redact(extra.context, this.opts.redactKeys) : {}),\n },\n snapshot: this.opts.snapshot ? takeSnapshot(this.opts.snapshot) : null,\n };\n\n if (this.opts.beforeSend) {\n const out = this.opts.beforeSend(event);\n if (!out) return;\n event = out;\n }\n\n this.enqueue(event);\n });\n }\n\n /** Flush anything queued. Await it before a process exits. */\n async flush(): Promise<void> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n await this.drain(false);\n safe(() => this.vitals?.flushNow());\n }\n\n /** Remove every hook the SDK installed. */\n close(): void {\n for (const fn of this.teardown) safe(fn);\n this.teardown = [];\n this.started = false;\n }\n\n /** Adapters use this to report render timings alongside browser vitals. */\n recordMetric(metric: VitalMetric): void {\n safe(() => this.vitals?.push(metric));\n }\n\n // --- internals ----------------------------------------------------------\n\n private requestInfo(): Record<string, unknown> | undefined {\n if (!isBrowser) return undefined;\n return safe(() => ({\n url: redactUrl(location.href, this.opts.redactKeys),\n referrer: document.referrer ? redactUrl(document.referrer, this.opts.redactKeys) : undefined,\n method: 'GET',\n }));\n }\n\n private enqueue(event: BugbanEvent): void {\n this.queue.push(event);\n // Cap the queue: an error loop must not eat the page's memory.\n if (this.queue.length > 50) this.queue.splice(0, this.queue.length - 50);\n\n if (this.flushTimer) return;\n // A short window coalesces a burst (a render loop throwing on every\n // frame) into one request instead of hundreds.\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n void this.drain(false);\n }, 300);\n\n safe(() => {\n const t = this.flushTimer as any;\n // Do not hold a Node process open just to flush telemetry.\n if (t && typeof t.unref === 'function') t.unref();\n });\n }\n\n private async drain(beacon: boolean): Promise<void> {\n if (this.queue.length === 0) return;\n const batch = this.queue.splice(0, this.queue.length);\n\n this.sending = true;\n try {\n await this.transport.send('/api/ingest/events', { events: batch }, { beacon });\n } finally {\n this.sending = false;\n }\n }\n\n private sendVitals(metrics: VitalMetric[]): void {\n safe(() => {\n // Slow database queries share the metric pipeline for batching, but\n // they are NOT web vitals: the server has had /api/ingest/queries\n // since the PHP SDKs, with its own grouping, EXPLAIN handling and\n // Performance tab. Route them there in that endpoint's shape so a\n // Node app's slow queries land next to a Laravel app's.\n const queries: Array<Record<string, unknown>> = [];\n const vitals: VitalMetric[] = [];\n\n for (const m of metrics) {\n if (m.name === 'SLOW_QUERY') {\n const d = (m.data || {}) as Record<string, unknown>;\n queries.push({\n sql: d.sql,\n duration_ms: m.value,\n connection: d.connection,\n bindings: d.bindings,\n url: d.url,\n method: d.method,\n occurred_at: m.occurred_at,\n });\n } else {\n vitals.push(m);\n }\n }\n\n const url = safe(() => redactUrl(location.href, this.opts.redactKeys));\n\n if (queries.length) {\n void this.transport.send('/api/ingest/queries', { queries }, { beacon: true });\n }\n\n if (vitals.length) {\n void this.transport.send(\n '/api/ingest/vitals',\n {\n vitals,\n url,\n release: this.opts.release,\n environment: this.opts.environment,\n session_id: this.sessionId,\n device: deviceInfo(),\n },\n // The page is usually unloading when vitals flush — beacon\n // is the only delivery that survives that.\n { beacon: true },\n );\n }\n });\n }\n\n private debug(...args: unknown[]): void {\n if (!this.opts.debug) return;\n safe(() => console.info('[bugban]', ...args));\n }\n}\n"],"mappings":"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","names":["src_exports","__export","Bugban","BugbanClient","SDK_NAME","SDK_VERSION","addBreadcrumb","capture","captureMessage","close","dependencyVersion","flush","getClient","init","normalizeError","parseStack","recordMetric","redact","redactUrl","runtimeName","runtimeVersion","setContext","setUser","SDK_NAME","SDK_VERSION","isBrowser","e","isNode","runtimeName","runtimeVersion","nodeModule","name","prefixed","spec","ns","tryRequire","hostname","os","appPackageInfo","fs","path","dir","depth","file","json","parent","dependencyVersion","pkg","mod","env","key","v","req","deviceInfo","_a","_b","out","section","value","defaults","defaultOn","__spreadValues","CONSOLE_DEFAULTS","isBrowser","NETWORK_DEFAULTS","SNAPSHOT_DEFAULTS","VITALS_DEFAULTS","resolveOptions","input","_a","_b","apiKey","env","host","__spreadProps","clamp","min","max","safe","fn","fallback","e","nowIso","truncate","value","max","s","stringify","seen","out","_k","v","matchesAny","patterns","p","randomId","c","b","x","sampled","rate","selectorFor","el","node","cls","byteLength","s","e","B","n","i","c","Transport","host","apiKey","debug","path","body","opts","url","json","isBrowser","safe","nav","blob","__spreadProps","__spreadValues","isNode","_a","controller","timer","res","isHttps","mod","nodeModule","resolve","u","req","args","BreadcrumbBuffer","max","crumb","full","nowIso","e","V8_LINE","MOZ_LINE","VENDOR_PATTERNS","isInApp","file","p","toFrame","fn","line","col","f","parseStack","stack","limit","frames","lines","raw","m","loc","normalizeError","input","o","e","MASK_CHAR","DROP_TAGS","maskValue","value","len","maskFormFields","root","fields","i","el","type","current","e","maskSelectors","selectors","sel","nodes","materializeFormState","source","clone","src","dst","n","s","d","collectCss","maxBytes","css","sheets","rules","j","takeSnapshot","opts","isBrowser","tag","head","base","html","nowIso","THRESHOLDS","rate","name","value","VitalsCollector","opts","flush","isBrowser","o","safe","metric","_a","_b","_c","__spreadProps","__spreadValues","nowIso","e","extra","type","cb","buffered","obs","list","nav","entries","last","selectorFor","clsValue","sessionValue","sessionEntries","entry","first","worst","a","b","duration","doFlush","all","k","LEVEL_MAP","hasErrorArg","args","a","installConsole","opts","hooks","originals","inside","method","original","level","message","truncate","deferred","safe","t","e","m","DEFAULT_REDACT_KEYS","REDACTED","isSensitiveKey","key","extra","k","s","redact","value","extraKeys","depth","v","src","out","count","e","redactUrl","url","hasScheme","u","_v","installNetwork","opts","hooks","redactKeys","ownHost","undo","ignored","url","matchesAny","record","method","rawUrl","status","startedAt","errored","redactUrl","duration","now","failed","data","label","e","original","patched","input","init","started","res","err","proto","origOpen","origSend","rest","safe","args","meta","fn","installGlobalHandlers","hooks","undo","isBrowser","onError","event","safe","err","onRejection","reason","isNode","onUncaught","onUnhandled","fn","labelFor","el","safe","aria","truncate","tag","ph","text","installDomBreadcrumbs","hooks","isBrowser","undo","onClick","event","target","i","chosen","selectorFor","current","report","next","history","origPush","origReplace","args","r","fn","MARKER_KEY","memoryMarker","alreadyPinged","apiKey","version","stamp","isBrowser","safe","isNode","fs","os","path","key","toHex","file","e","s","out","i","sendInstallPing","opts","transport","SDK_VERSION","pkg","appPackageInfo","host","hostname","payload","SDK_NAME","runtimeName","runtimeVersion","k","BugbanClient","options","randomId","resolveOptions","Transport","BreadcrumbBuffer","safe","sendInstallPing","o","installGlobalHandlers","err","extra","installConsole","level","message","args","real","a","installNetwork","data","failed","installDomBreadcrumbs","label","from","to","redactUrl","isBrowser","sampled","VitalsCollector","metrics","_a","onHide","onPageHide","crumb","c","__spreadProps","__spreadValues","redact","nowIso","out","user","key","value","error","norm","normalizeError","matchesAny","frames","parseStack","top","f","event","truncate","deviceInfo","takeSnapshot","fn","metric","beacon","batch","queries","vitals","m","d","url","SINGLETON_KEY","readClient","_a","safe","writeClient","value","init","options","previous","created","BugbanClient","getClient","capture","error","extra","captureMessage","message","level","setUser","user","setContext","key","addBreadcrumb","crumb","recordMetric","metric","flush","close","Bugban","SDK_VERSION"]}
|