ghostplay-sdk 0.1.6 → 0.1.7
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.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/config.ts","../src/session.ts","../src/recorder.ts","../src/modules/error-tracker.ts","../src/modules/network-interceptor.ts","../src/modules/console-interceptor.ts","../src/modules/performance-tracker.ts","../src/modules/rage-click-detector.ts","../src/modules/breadcrumbs.ts","../src/modules/navigation-tracker.ts","../src/privacy.ts","../src/transport.ts","../src/index.ts"],"names":["DEFAULT_CONFIG","resolveConfig","config","generateId","timestamp","random","SessionManager","projectId","userId","traits","session","tag","data","Recorder","sessionId","emit","rrwebConfig","record","event","ErrorTracker","message","source","lineno","colno","error","reason","GHOSTPLAY_URL_PATTERN","NetworkInterceptor","self","input","init","url","method","startTime","requestHeaders","extractHeaders","requestBody","extractBody","response","responseHeaders","value","key","responseBody","contentType","text","headers","result","body","LEVELS","ConsoleInterceptor","level","args","arg","THRESHOLDS","PerformanceTracker","o","metric","good","poor","rating","observer","list","entries","last","first","clsValue","entry","RageClickDetector","target","now","r","t","el","testId","className","Breadcrumbs","maxSize","category","crumb","NavigationTracker","trigger","newUrl","from","to","ALWAYS_DENY_RESPONSE_HEADERS","PrivacyFilter","options","denyList","denyLower","h","filtered","patterns","pattern","Transport","eventSize","events","batch","useKeepalive","res","VERSION","sessionManager","recorder","errorTracker","networkInterceptor","consoleInterceptor","performanceTracker","rageClickDetector","breadcrumbs","navigationTracker","privacyFilter","transport","ensureInitialized","handleEvent","userConfig","stop","startRecording","sanitized","identify","tagName","setMetadata","Ghostplay","index_default"],"mappings":"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","file":"index.mjs","sourcesContent":["// rrweb type aliases — rrweb 2.0.0-alpha.4 does not re-export these from its\n// package root, so we define compatible local aliases to keep the same shape.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype eventWithTime = any;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype recordOptions<T = eventWithTime> = Record<string, any>;\n\n// --- SDK Config ---\n\nexport interface NetworkSanitizeConfig {\n denyHeaders: string[];\n denyBodyUrls: string[];\n}\n\nexport interface GhostplayConfig {\n projectId: string;\n apiUrl?: string;\n\n // Privacy\n maskAllInputs?: boolean;\n maskInputSelector?: string;\n blockSelector?: string;\n ignoreSelector?: string;\n networkSanitize?: NetworkSanitizeConfig;\n\n // Feature toggles\n recordNetwork?: boolean;\n recordConsole?: boolean;\n trackPerformance?: boolean;\n trackRageClicks?: boolean;\n trackNavigation?: boolean;\n\n // Transport\n flushIntervalMs?: number;\n flushMaxBytes?: number;\n\n // rrweb passthrough\n rrwebConfig?: Partial<recordOptions<eventWithTime>>;\n}\n\nexport const DEFAULT_CONFIG: Required<\n Pick<\n GhostplayConfig,\n | 'apiUrl'\n | 'maskAllInputs'\n | 'recordNetwork'\n | 'recordConsole'\n | 'trackPerformance'\n | 'trackRageClicks'\n | 'trackNavigation'\n | 'flushIntervalMs'\n | 'flushMaxBytes'\n >\n> = {\n apiUrl: 'https://api.ghostplay.dev/v1',\n maskAllInputs: true,\n recordNetwork: true,\n recordConsole: true,\n trackPerformance: true,\n trackRageClicks: true,\n trackNavigation: true,\n flushIntervalMs: 5000,\n flushMaxBytes: 50_000,\n};\n\n// --- Session ---\n\nexport interface Session {\n id: string;\n projectId: string;\n startedAt: number;\n userId?: string;\n userTraits?: Record<string, unknown>;\n tags: string[];\n metadata: Record<string, unknown>;\n}\n\n// --- Events ---\n\nexport type GhostplayEventType =\n | 'rrweb'\n | 'error'\n | 'network'\n | 'console'\n | 'performance'\n | 'rage-click'\n | 'breadcrumb'\n | 'identify'\n | 'tag'\n | 'metadata'\n | 'navigation';\n\nexport interface GhostplayEvent {\n type: GhostplayEventType;\n timestamp: number;\n sessionId: string;\n data: unknown;\n}\n\nexport interface ErrorEventData {\n message: string;\n stack?: string;\n source?: string;\n lineno?: number;\n colno?: number;\n type: 'onerror' | 'unhandledrejection';\n}\n\nexport interface NetworkEventData {\n method: string;\n url: string;\n status?: number;\n statusText?: string;\n requestHeaders?: Record<string, string>;\n responseHeaders?: Record<string, string>;\n requestBody?: string;\n responseBody?: string;\n startTime: number;\n endTime?: number;\n duration?: number;\n}\n\nexport interface ConsoleEventData {\n level: 'log' | 'warn' | 'error' | 'info' | 'debug';\n args: unknown[];\n}\n\nexport interface PerformanceEventData {\n metric: 'LCP' | 'FID' | 'CLS' | 'TTFB' | 'INP';\n value: number;\n rating: 'good' | 'needs-improvement' | 'poor';\n}\n\nexport interface RageClickEventData {\n selector: string;\n clickCount: number;\n x: number;\n y: number;\n}\n\nexport interface BreadcrumbEventData {\n category: 'navigation' | 'click' | 'input' | 'error' | 'network' | 'custom';\n message: string;\n data?: Record<string, unknown>;\n}\n\nexport interface NavigationEventData {\n from: string | null;\n to: string;\n trigger: 'pushState' | 'replaceState' | 'popstate' | 'hashchange' | 'initial';\n}\n\n// --- Transport ---\n\nexport interface EventBatch {\n projectId: string;\n sessionId: string;\n events: GhostplayEvent[];\n sentAt: number;\n}\n","import { type GhostplayConfig, DEFAULT_CONFIG } from './types';\n\nexport type ResolvedConfig = GhostplayConfig & typeof DEFAULT_CONFIG;\n\nexport function resolveConfig(config: GhostplayConfig): ResolvedConfig {\n if (!config.projectId) {\n throw new Error('[Ghostplay] projectId is required');\n }\n if (!config.projectId.startsWith('gp_')) {\n throw new Error('[Ghostplay] projectId must start with \"gp_\"');\n }\n\n return { ...DEFAULT_CONFIG, ...config };\n}\n","import type { Session } from './types';\n\nfunction generateId(): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 10);\n return `gs_${timestamp}_${random}`;\n}\n\nexport class SessionManager {\n private session: Session | null = null;\n\n constructor(private projectId: string) {}\n\n start(): Session {\n this.session = {\n id: generateId(),\n projectId: this.projectId,\n startedAt: Date.now(),\n tags: [],\n metadata: {},\n };\n return this.session;\n }\n\n current(): Session {\n if (!this.session) {\n throw new Error('[Ghostplay] No active session');\n }\n return this.session;\n }\n\n identify(userId: string, traits?: Record<string, unknown>): void {\n const session = this.current();\n session.userId = userId;\n session.userTraits = traits;\n }\n\n addTag(tag: string): void {\n const session = this.current();\n if (!session.tags.includes(tag)) {\n session.tags.push(tag);\n }\n }\n\n setMetadata(data: Record<string, unknown>): void {\n const session = this.current();\n session.metadata = { ...session.metadata, ...data };\n }\n\n end(): void {\n this.session = null;\n }\n}\n","import { record } from 'rrweb';\nimport type { GhostplayEvent } from './types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\n\nexport class Recorder {\n private stopFn: (() => void) | null = null;\n\n constructor(\n private sessionId: string,\n private emit: EventCallback,\n private rrwebConfig?: Record<string, any>\n ) {}\n\n start(): void {\n this.stopFn = record({\n ...this.rrwebConfig,\n emit: (event: any) => {\n this.emit({\n type: 'rrweb',\n timestamp: event.timestamp,\n sessionId: this.sessionId,\n data: event,\n });\n },\n }) ?? null;\n }\n\n stop(): void {\n if (this.stopFn) {\n this.stopFn();\n this.stopFn = null;\n }\n }\n}\n","import type { GhostplayEvent, ErrorEventData } from '../types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\n\nexport class ErrorTracker {\n private onErrorHandler: OnErrorEventHandler | null = null;\n private onRejectionHandler: ((e: PromiseRejectionEvent) => void) | null = null;\n private previousOnError: OnErrorEventHandler | null = null;\n\n constructor(\n private sessionId: string,\n private emit: EventCallback\n ) {}\n\n start(): void {\n this.previousOnError = window.onerror;\n\n this.onErrorHandler = (message, source, lineno, colno, error) => {\n const data: ErrorEventData = {\n message: String(message),\n stack: error?.stack,\n source: source ?? undefined,\n lineno: lineno ?? undefined,\n colno: colno ?? undefined,\n type: 'onerror',\n };\n\n this.emit({\n type: 'error',\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data,\n });\n\n if (this.previousOnError) {\n return this.previousOnError.call(window, message, source, lineno, colno, error);\n }\n return false;\n };\n\n this.onRejectionHandler = (e: PromiseRejectionEvent) => {\n const reason = e.reason;\n const data: ErrorEventData = {\n message:\n reason instanceof Error ? reason.message : String(reason),\n stack: reason instanceof Error ? reason.stack : undefined,\n type: 'unhandledrejection',\n };\n\n this.emit({\n type: 'error',\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data,\n });\n };\n\n window.onerror = this.onErrorHandler;\n window.addEventListener('unhandledrejection', this.onRejectionHandler);\n }\n\n stop(): void {\n if (this.previousOnError) {\n window.onerror = this.previousOnError;\n } else {\n window.onerror = null;\n }\n\n if (this.onRejectionHandler) {\n window.removeEventListener('unhandledrejection', this.onRejectionHandler);\n }\n\n this.onErrorHandler = null;\n this.onRejectionHandler = null;\n }\n}\n","import type { GhostplayEvent, NetworkEventData } from '../types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\n\nconst GHOSTPLAY_URL_PATTERN = /ghostplay\\.dev/;\nconst MAX_BODY_SIZE = 1024 * 1024; // 1MB limit per body\n\nexport class NetworkInterceptor {\n private originalFetch: typeof fetch | null = null;\n private active = false;\n\n constructor(\n private sessionId: string,\n private emit: EventCallback\n ) {}\n\n start(): void {\n this.active = true;\n this.patchFetch();\n }\n\n stop(): void {\n this.active = false;\n this.restoreFetch();\n }\n\n private patchFetch(): void {\n this.originalFetch = globalThis.fetch;\n const self = this;\n\n globalThis.fetch = async function (\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> {\n const url =\n typeof input === 'string'\n ? input\n : input instanceof URL\n ? input.toString()\n : input.url;\n const method = init?.method ?? 'GET';\n\n if (GHOSTPLAY_URL_PATTERN.test(url)) {\n return self.originalFetch!.call(globalThis, input, init);\n }\n\n const startTime = Date.now();\n\n // Extract request headers\n const requestHeaders = extractHeaders(init?.headers);\n\n // Extract request body\n const requestBody = extractBody(init?.body);\n\n try {\n const response = await self.originalFetch!.call(\n globalThis,\n input,\n init\n );\n\n if (self.active) {\n // Extract response headers\n const responseHeaders: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n // Clone response to read body without consuming the original\n let responseBody: string | undefined;\n try {\n const contentType = response.headers.get('content-type') ?? '';\n if (contentType.includes('json') || contentType.includes('text')) {\n const clone = response.clone();\n const text = await clone.text();\n responseBody = text.length > MAX_BODY_SIZE\n ? text.substring(0, MAX_BODY_SIZE) + '...[truncated]'\n : text;\n }\n } catch {\n // Body read failed — skip\n }\n\n const data: NetworkEventData = {\n method: method.toUpperCase(),\n url,\n status: response.status,\n statusText: response.statusText,\n requestHeaders,\n responseHeaders,\n requestBody,\n responseBody,\n startTime,\n endTime: Date.now(),\n duration: Date.now() - startTime,\n };\n\n self.emit({\n type: 'network',\n timestamp: startTime,\n sessionId: self.sessionId,\n data,\n });\n }\n\n return response;\n } catch (error) {\n if (self.active) {\n const data: NetworkEventData = {\n method: method.toUpperCase(),\n url,\n requestHeaders,\n requestBody,\n startTime,\n endTime: Date.now(),\n duration: Date.now() - startTime,\n };\n\n self.emit({\n type: 'network',\n timestamp: startTime,\n sessionId: self.sessionId,\n data,\n });\n }\n\n throw error;\n }\n };\n }\n\n private restoreFetch(): void {\n if (this.originalFetch) {\n globalThis.fetch = this.originalFetch;\n this.originalFetch = null;\n }\n }\n}\n\nfunction extractHeaders(headers: HeadersInit | undefined): Record<string, string> {\n const result: Record<string, string> = {};\n if (!headers) return result;\n\n if (headers instanceof Headers) {\n headers.forEach((value, key) => { result[key] = value; });\n } else if (Array.isArray(headers)) {\n for (const [key, value] of headers) { result[key] = value; }\n } else {\n for (const [key, value] of Object.entries(headers)) { result[key] = value; }\n }\n\n return result;\n}\n\nfunction extractBody(body: BodyInit | null | undefined): string | undefined {\n if (!body) return undefined;\n\n if (typeof body === 'string') {\n return body.length > MAX_BODY_SIZE\n ? body.substring(0, MAX_BODY_SIZE) + '...[truncated]'\n : body;\n }\n\n if (body instanceof URLSearchParams) {\n return body.toString();\n }\n\n // FormData, Blob, ArrayBuffer, ReadableStream — skip (too complex/binary)\n return undefined;\n}\n","import type { GhostplayEvent, ConsoleEventData } from '../types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\ntype ConsoleLevel = 'log' | 'warn' | 'error' | 'info' | 'debug';\n\nconst LEVELS: ConsoleLevel[] = ['log', 'warn', 'error', 'info', 'debug'];\n\nexport class ConsoleInterceptor {\n private originals: Partial<Record<ConsoleLevel, (...args: unknown[]) => void>> = {};\n\n constructor(\n private sessionId: string,\n private emit: EventCallback\n ) {}\n\n start(): void {\n for (const level of LEVELS) {\n this.originals[level] = console[level].bind(console);\n console[level] = (...args: unknown[]) => {\n const data: ConsoleEventData = {\n level,\n args: args.map((arg) => this.serialize(arg)),\n };\n this.emit({\n type: 'console',\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data,\n });\n this.originals[level]?.(...args);\n };\n }\n }\n\n stop(): void {\n for (const level of LEVELS) {\n if (this.originals[level]) {\n console[level] = this.originals[level] as any;\n }\n }\n this.originals = {};\n }\n\n private serialize(arg: unknown): unknown {\n if (arg instanceof Error) {\n return { __type: 'Error', message: arg.message, stack: arg.stack };\n }\n if (typeof arg === 'object' && arg !== null) {\n try { JSON.stringify(arg); return arg; } catch { return String(arg); }\n }\n return arg;\n }\n}\n","import type { GhostplayEvent, PerformanceEventData } from '../types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\ntype Metric = PerformanceEventData['metric'];\n\nconst THRESHOLDS: Record<Metric, [number, number]> = {\n LCP: [1000, 4000],\n FID: [100, 300],\n CLS: [0.1, 0.25],\n TTFB: [800, 1800],\n INP: [200, 500],\n};\n\nexport class PerformanceTracker {\n private observers: PerformanceObserver[] = [];\n\n constructor(\n private sessionId: string,\n private emit: EventCallback\n ) {}\n\n start(): void {\n if (typeof PerformanceObserver === 'undefined') return;\n this.observeLCP();\n this.observeFID();\n this.observeCLS();\n this.observeTTFB();\n this.observeINP();\n }\n\n stop(): void {\n this.observers.forEach((o) => o.disconnect());\n this.observers = [];\n }\n\n handleMetric(metric: Metric, value: number): void {\n const [good, poor] = THRESHOLDS[metric];\n const rating: PerformanceEventData['rating'] =\n value <= good ? 'good' : value <= poor ? 'needs-improvement' : 'poor';\n this.emit({\n type: 'performance',\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data: { metric, value, rating },\n });\n }\n\n private observeLCP(): void {\n try {\n const observer = new PerformanceObserver((list) => {\n const entries = list.getEntries();\n const last = entries[entries.length - 1];\n if (last) this.handleMetric('LCP', last.startTime);\n });\n observer.observe({ type: 'largest-contentful-paint', buffered: true });\n this.observers.push(observer);\n } catch {}\n }\n\n private observeFID(): void {\n try {\n const observer = new PerformanceObserver((list) => {\n const entries = list.getEntries();\n const first = entries[0] as any;\n if (first) this.handleMetric('FID', first.processingStart - first.startTime);\n });\n observer.observe({ type: 'first-input', buffered: true });\n this.observers.push(observer);\n } catch {}\n }\n\n private observeCLS(): void {\n let clsValue = 0;\n try {\n const observer = new PerformanceObserver((list) => {\n for (const entry of list.getEntries() as any[]) {\n if (!entry.hadRecentInput) clsValue += entry.value;\n }\n this.handleMetric('CLS', clsValue);\n });\n observer.observe({ type: 'layout-shift', buffered: true });\n this.observers.push(observer);\n } catch {}\n }\n\n private observeTTFB(): void {\n try {\n const observer = new PerformanceObserver((list) => {\n const entry = list.getEntries()[0] as any;\n if (entry) this.handleMetric('TTFB', entry.responseStart);\n });\n observer.observe({ type: 'navigation', buffered: true });\n this.observers.push(observer);\n } catch {}\n }\n\n private observeINP(): void {\n try {\n const observer = new PerformanceObserver((list) => {\n for (const entry of list.getEntries() as any[]) {\n this.handleMetric('INP', entry.duration);\n }\n });\n observer.observe({ type: 'event', buffered: true });\n this.observers.push(observer);\n } catch {}\n }\n}\n","import type { GhostplayEvent, RageClickEventData } from '../types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\n\nconst RAGE_THRESHOLD = 3;\nconst RAGE_WINDOW_MS = 1000;\n\ninterface ClickRecord {\n element: Element;\n timestamps: number[];\n}\n\nexport class RageClickDetector {\n private clickHandler: ((e: MouseEvent) => void) | null = null;\n private recentClicks: ClickRecord[] = [];\n\n constructor(\n private sessionId: string,\n private emit: EventCallback\n ) {}\n\n start(): void {\n this.clickHandler = (e: MouseEvent) => {\n const target = e.target as Element;\n if (!target) return;\n const now = Date.now();\n let record = this.recentClicks.find((r) => r.element === target);\n if (!record) {\n record = { element: target, timestamps: [] };\n this.recentClicks.push(record);\n }\n record.timestamps.push(now);\n record.timestamps = record.timestamps.filter((t) => now - t < RAGE_WINDOW_MS);\n if (record.timestamps.length >= RAGE_THRESHOLD) {\n const data: RageClickEventData = {\n selector: this.getSelector(target),\n clickCount: record.timestamps.length,\n x: e.clientX,\n y: e.clientY,\n };\n this.emit({\n type: 'rage-click',\n timestamp: now,\n sessionId: this.sessionId,\n data,\n });\n record.timestamps = [];\n }\n this.recentClicks = this.recentClicks.filter((r) => r.timestamps.length > 0);\n };\n document.addEventListener('click', this.clickHandler, true);\n }\n\n stop(): void {\n if (this.clickHandler) {\n document.removeEventListener('click', this.clickHandler, true);\n this.clickHandler = null;\n }\n this.recentClicks = [];\n }\n\n private getSelector(el: Element): string {\n if (el.id) return `#${el.id}`;\n const testId = el.getAttribute('data-testid');\n if (testId) return `[data-testid=\"${testId}\"]`;\n const tag = el.tagName.toLowerCase();\n const className = el.className\n ? `.${el.className.split(' ').filter(Boolean).join('.')}`\n : '';\n return `${tag}${className}`;\n }\n}\n","import type { BreadcrumbEventData } from '../types';\n\nexport class Breadcrumbs {\n private trail: BreadcrumbEventData[] = [];\n\n constructor(private maxSize: number = 50) {}\n\n add(\n category: BreadcrumbEventData['category'],\n message: string,\n data?: Record<string, unknown>\n ): void {\n const crumb: BreadcrumbEventData = { category, message };\n if (data) crumb.data = data;\n this.trail.push(crumb);\n if (this.trail.length > this.maxSize) {\n this.trail = this.trail.slice(-this.maxSize);\n }\n }\n\n getTrail(): BreadcrumbEventData[] {\n return [...this.trail];\n }\n\n clear(): void {\n this.trail = [];\n }\n}\n","import type { GhostplayEvent, NavigationEventData } from '../types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\n\nexport class NavigationTracker {\n private currentUrl: string = '';\n private originalPushState: typeof history.pushState | null = null;\n private originalReplaceState: typeof history.replaceState | null = null;\n private popstateHandler: (() => void) | null = null;\n private hashchangeHandler: (() => void) | null = null;\n\n constructor(\n private sessionId: string,\n private emit: EventCallback\n ) {}\n\n start(): void {\n this.currentUrl = window.location.href;\n\n // Emit initial navigation event\n this.emitNavigation(null, this.currentUrl, 'initial');\n\n // Patch history.pushState\n this.originalPushState = history.pushState.bind(history);\n history.pushState = (...args: Parameters<typeof history.pushState>) => {\n this.originalPushState!(...args);\n this.handleUrlChange('pushState');\n };\n\n // Patch history.replaceState\n this.originalReplaceState = history.replaceState.bind(history);\n history.replaceState = (...args: Parameters<typeof history.replaceState>) => {\n this.originalReplaceState!(...args);\n this.handleUrlChange('replaceState');\n };\n\n // Listen for popstate (back/forward)\n this.popstateHandler = () => this.handleUrlChange('popstate');\n window.addEventListener('popstate', this.popstateHandler);\n\n // Listen for hashchange\n this.hashchangeHandler = () => this.handleUrlChange('hashchange');\n window.addEventListener('hashchange', this.hashchangeHandler);\n }\n\n stop(): void {\n if (this.originalPushState) {\n history.pushState = this.originalPushState;\n this.originalPushState = null;\n }\n if (this.originalReplaceState) {\n history.replaceState = this.originalReplaceState;\n this.originalReplaceState = null;\n }\n if (this.popstateHandler) {\n window.removeEventListener('popstate', this.popstateHandler);\n this.popstateHandler = null;\n }\n if (this.hashchangeHandler) {\n window.removeEventListener('hashchange', this.hashchangeHandler);\n this.hashchangeHandler = null;\n }\n }\n\n private handleUrlChange(trigger: NavigationEventData['trigger']): void {\n const newUrl = window.location.href;\n if (newUrl !== this.currentUrl) {\n const from = this.currentUrl;\n this.currentUrl = newUrl;\n this.emitNavigation(from, newUrl, trigger);\n }\n }\n\n private emitNavigation(from: string | null, to: string, trigger: NavigationEventData['trigger']): void {\n const data: NavigationEventData = { from, to, trigger };\n this.emit({\n type: 'navigation',\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data,\n });\n }\n}\n","import type { GhostplayConfig, NetworkEventData } from './types';\n\nconst ALWAYS_DENY_RESPONSE_HEADERS = ['set-cookie'];\n\ninterface PrivacyOptions {\n networkSanitize?: GhostplayConfig['networkSanitize'];\n}\n\nexport class PrivacyFilter {\n constructor(private options: PrivacyOptions) {}\n\n sanitizeNetworkEvent(event: NetworkEventData): NetworkEventData {\n const result = { ...event };\n const config = this.options.networkSanitize;\n\n // Always remove sensitive response headers\n if (result.responseHeaders) {\n result.responseHeaders = this.filterHeaders(\n result.responseHeaders,\n ALWAYS_DENY_RESPONSE_HEADERS\n );\n }\n\n if (!config) return result;\n\n // Remove denied request headers\n if (result.requestHeaders && config.denyHeaders.length > 0) {\n result.requestHeaders = this.filterHeaders(\n result.requestHeaders,\n config.denyHeaders\n );\n }\n\n // Remove denied response headers\n if (result.responseHeaders && config.denyHeaders.length > 0) {\n result.responseHeaders = this.filterHeaders(\n result.responseHeaders,\n config.denyHeaders\n );\n }\n\n // Redact body for denied URLs\n if (config.denyBodyUrls.length > 0 && this.urlMatchesDeny(event.url, config.denyBodyUrls)) {\n if (result.requestBody) result.requestBody = '[REDACTED]';\n if (result.responseBody) result.responseBody = '[REDACTED]';\n }\n\n return result;\n }\n\n private filterHeaders(\n headers: Record<string, string>,\n denyList: string[]\n ): Record<string, string> {\n const denyLower = denyList.map((h) => h.toLowerCase());\n const filtered: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (!denyLower.includes(key.toLowerCase())) {\n filtered[key] = value;\n }\n }\n return filtered;\n }\n\n private urlMatchesDeny(url: string, patterns: string[]): boolean {\n return patterns.some((pattern) => {\n const regex = new RegExp(\n '^' + pattern.replace(/\\*/g, '.*') + '$'\n );\n return regex.test(url);\n });\n }\n}\n","import type { GhostplayEvent, EventBatch } from './types';\n\ninterface TransportConfig {\n apiUrl: string;\n projectId: string;\n sessionId: string;\n flushIntervalMs: number;\n flushMaxBytes: number;\n}\n\nconst KEEPALIVE_LIMIT = 60_000; // Stay under 64KB browser limit\n\nexport class Transport {\n private buffer: GhostplayEvent[] = [];\n private bufferBytes = 0;\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(private config: TransportConfig) {}\n\n start(): void {\n this.flushTimer = setInterval(() => {\n this.flush();\n }, this.config.flushIntervalMs);\n }\n\n stop(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush();\n }\n\n send(event: GhostplayEvent): void {\n const eventSize = JSON.stringify(event).length;\n this.buffer.push(event);\n this.bufferBytes += eventSize;\n if (this.bufferBytes >= this.config.flushMaxBytes) {\n this.flush();\n }\n }\n\n private flush(): void {\n if (this.buffer.length === 0) return;\n const events = this.buffer;\n this.buffer = [];\n this.bufferBytes = 0;\n const batch: EventBatch = {\n projectId: this.config.projectId,\n sessionId: this.config.sessionId,\n events,\n sentAt: Date.now(),\n };\n const body = JSON.stringify(batch);\n const url = `${this.config.apiUrl}/events`;\n\n // Use keepalive only for small payloads (Safari enforces 64KB limit strictly)\n const useKeepalive = body.length < KEEPALIVE_LIMIT;\n\n try {\n fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-project-id': this.config.projectId,\n },\n body,\n keepalive: useKeepalive,\n })\n .then((res) => {\n if (!res.ok) {\n console.warn(`[Ghostplay] Event batch rejected (${res.status})`);\n }\n })\n .catch(() => {\n // Fallback to sendBeacon\n this.sendBeacon(url, body);\n });\n } catch {\n this.sendBeacon(url, body);\n }\n }\n\n private sendBeacon(url: string, body: string): void {\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n navigator.sendBeacon(url, new Blob([body], { type: 'application/json' }));\n }\n }\n}\n","import { resolveConfig, type ResolvedConfig } from './config';\nimport { SessionManager } from './session';\nimport { Recorder } from './recorder';\nimport { ErrorTracker } from './modules/error-tracker';\nimport { NetworkInterceptor } from './modules/network-interceptor';\nimport { ConsoleInterceptor } from './modules/console-interceptor';\nimport { PerformanceTracker } from './modules/performance-tracker';\nimport { RageClickDetector } from './modules/rage-click-detector';\nimport { Breadcrumbs } from './modules/breadcrumbs';\nimport { NavigationTracker } from './modules/navigation-tracker';\nimport { PrivacyFilter } from './privacy';\nimport { Transport } from './transport';\nimport type { GhostplayConfig, GhostplayEvent } from './types';\n\nexport const VERSION = '0.1.0';\n\nlet config: ResolvedConfig | null = null;\nlet sessionManager: SessionManager | null = null;\nlet recorder: Recorder | null = null;\nlet errorTracker: ErrorTracker | null = null;\nlet networkInterceptor: NetworkInterceptor | null = null;\nlet consoleInterceptor: ConsoleInterceptor | null = null;\nlet performanceTracker: PerformanceTracker | null = null;\nlet rageClickDetector: RageClickDetector | null = null;\nlet breadcrumbs: Breadcrumbs | null = null;\nlet navigationTracker: NavigationTracker | null = null;\nlet privacyFilter: PrivacyFilter | null = null;\nlet transport: Transport | null = null;\n\nfunction ensureInitialized(): void {\n if (!sessionManager) {\n throw new Error('[Ghostplay] SDK not initialized. Call Ghostplay.init() first.');\n }\n}\n\nfunction handleEvent(event: GhostplayEvent): void {\n if (breadcrumbs && event.type !== 'rrweb') {\n breadcrumbs.add(\n event.type === 'error'\n ? 'error'\n : event.type === 'network'\n ? 'network'\n : event.type === 'rage-click'\n ? 'click'\n : 'custom',\n `${event.type}: ${JSON.stringify(event.data).substring(0, 100)}`\n );\n }\n transport?.send(event);\n}\n\nfunction init(userConfig: GhostplayConfig): void {\n stop();\n config = resolveConfig(userConfig);\n sessionManager = new SessionManager(config.projectId);\n const session = sessionManager.start();\n\n privacyFilter = new PrivacyFilter({\n networkSanitize: config.networkSanitize,\n });\n\n transport = new Transport({\n apiUrl: config.apiUrl,\n projectId: config.projectId,\n sessionId: session.id,\n flushIntervalMs: config.flushIntervalMs,\n flushMaxBytes: config.flushMaxBytes,\n });\n transport.start();\n\n breadcrumbs = new Breadcrumbs();\n\n recorder = new Recorder(session.id, handleEvent, {\n maskAllInputs: config.maskAllInputs,\n ...(config.maskInputSelector ? { maskInputSelector: config.maskInputSelector } : {}),\n ...(config.blockSelector ? { blockSelector: config.blockSelector } : {}),\n ...(config.ignoreSelector ? { ignoreSelector: config.ignoreSelector } : {}),\n ...config.rrwebConfig,\n });\n\n // Defer recording start so the FullSnapshot captures the rendered DOM.\n // SPAs (React, Vue, etc.) mount into an empty root element — starting\n // rrweb synchronously would snapshot an empty page and the framework's\n // initial DOM mount can be lost. A double-rAF waits for the first\n // paint, giving frameworks time to render before the snapshot is taken.\n const startRecording = () => recorder?.start();\n if (document.readyState === 'complete') {\n requestAnimationFrame(() => requestAnimationFrame(startRecording));\n } else {\n window.addEventListener('load', () =>\n requestAnimationFrame(startRecording), { once: true });\n }\n\n errorTracker = new ErrorTracker(session.id, handleEvent);\n errorTracker.start();\n\n if (config.recordNetwork) {\n networkInterceptor = new NetworkInterceptor(session.id, (event) => {\n const sanitized = privacyFilter!.sanitizeNetworkEvent(event.data as any);\n handleEvent({ ...event, data: sanitized });\n });\n networkInterceptor.start();\n }\n\n if (config.recordConsole) {\n consoleInterceptor = new ConsoleInterceptor(session.id, handleEvent);\n consoleInterceptor.start();\n }\n\n if (config.trackPerformance) {\n performanceTracker = new PerformanceTracker(session.id, handleEvent);\n performanceTracker.start();\n }\n\n if (config.trackRageClicks) {\n rageClickDetector = new RageClickDetector(session.id, handleEvent);\n rageClickDetector.start();\n }\n\n if (config.trackNavigation) {\n navigationTracker = new NavigationTracker(session.id, handleEvent);\n navigationTracker.start();\n }\n}\n\nfunction identify(userId: string, traits?: Record<string, unknown>): void {\n ensureInitialized();\n sessionManager!.identify(userId, traits);\n handleEvent({\n type: 'identify',\n timestamp: Date.now(),\n sessionId: sessionManager!.current().id,\n data: { userId, traits },\n });\n}\n\nfunction tag(tagName: string): void {\n ensureInitialized();\n sessionManager!.addTag(tagName);\n handleEvent({\n type: 'tag',\n timestamp: Date.now(),\n sessionId: sessionManager!.current().id,\n data: { tag: tagName },\n });\n}\n\nfunction setMetadata(data: Record<string, unknown>): void {\n ensureInitialized();\n sessionManager!.setMetadata(data);\n handleEvent({\n type: 'metadata',\n timestamp: Date.now(),\n sessionId: sessionManager!.current().id,\n data,\n });\n}\n\nfunction stop(): void {\n recorder?.stop();\n errorTracker?.stop();\n networkInterceptor?.stop();\n consoleInterceptor?.stop();\n performanceTracker?.stop();\n rageClickDetector?.stop();\n navigationTracker?.stop();\n transport?.stop();\n sessionManager?.end();\n\n recorder = null;\n errorTracker = null;\n networkInterceptor = null;\n consoleInterceptor = null;\n performanceTracker = null;\n rageClickDetector = null;\n navigationTracker = null;\n transport = null;\n sessionManager = null;\n breadcrumbs = null;\n privacyFilter = null;\n config = null;\n}\n\nexport const Ghostplay = {\n VERSION,\n init,\n identify,\n tag,\n setMetadata,\n stop,\n};\n\nexport default Ghostplay;\nexport type { GhostplayConfig, GhostplayEvent, Session } from './types';\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/config.ts","../src/session.ts","../src/recorder.ts","../src/modules/error-tracker.ts","../src/modules/network-interceptor.ts","../src/modules/console-interceptor.ts","../src/modules/performance-tracker.ts","../src/modules/rage-click-detector.ts","../src/modules/breadcrumbs.ts","../src/modules/navigation-tracker.ts","../src/privacy.ts","../src/transport.ts","../src/index.ts"],"names":["DEFAULT_CONFIG","resolveConfig","config","generateId","timestamp","random","SessionManager","projectId","userId","traits","session","tag","data","Recorder","sessionId","emit","rrwebConfig","record","event","ErrorTracker","message","source","lineno","colno","error","reason","GHOSTPLAY_URL_PATTERN","NetworkInterceptor","self","input","init","url","method","startTime","requestHeaders","extractHeaders","requestBody","extractBody","response","responseHeaders","value","key","responseBody","contentType","text","headers","result","body","LEVELS","ConsoleInterceptor","level","args","arg","THRESHOLDS","PerformanceTracker","o","metric","good","poor","rating","observer","list","entries","last","first","clsValue","entry","RageClickDetector","target","now","r","t","el","testId","className","Breadcrumbs","maxSize","category","crumb","NavigationTracker","trigger","newUrl","from","to","ALWAYS_DENY_RESPONSE_HEADERS","PrivacyFilter","options","denyList","denyLower","h","filtered","patterns","pattern","Transport","eventSize","events","batch","useKeepalive","res","VERSION","sessionManager","recorder","errorTracker","networkInterceptor","consoleInterceptor","performanceTracker","rageClickDetector","breadcrumbs","navigationTracker","privacyFilter","transport","ensureInitialized","handleEvent","userConfig","stop","startRecording","sanitized","identify","tagName","setMetadata","Ghostplay","index_default"],"mappings":"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","file":"index.mjs","sourcesContent":["// rrweb type aliases — rrweb 2.0.0-alpha.4 does not re-export these from its\n// package root, so we define compatible local aliases to keep the same shape.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype eventWithTime = any;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype recordOptions<T = eventWithTime> = Record<string, any>;\n\n// --- SDK Config ---\n\nexport interface NetworkSanitizeConfig {\n denyHeaders: string[];\n denyBodyUrls: string[];\n}\n\nexport interface GhostplayConfig {\n projectId: string;\n apiUrl?: string;\n\n // Privacy\n maskAllInputs?: boolean;\n maskInputSelector?: string;\n blockSelector?: string;\n ignoreSelector?: string;\n networkSanitize?: NetworkSanitizeConfig;\n\n // Feature toggles\n recordNetwork?: boolean;\n recordConsole?: boolean;\n trackPerformance?: boolean;\n trackRageClicks?: boolean;\n trackNavigation?: boolean;\n\n // Transport\n flushIntervalMs?: number;\n flushMaxBytes?: number;\n\n // rrweb passthrough\n rrwebConfig?: Partial<recordOptions<eventWithTime>>;\n}\n\nexport const DEFAULT_CONFIG: Required<\n Pick<\n GhostplayConfig,\n | 'apiUrl'\n | 'maskAllInputs'\n | 'recordNetwork'\n | 'recordConsole'\n | 'trackPerformance'\n | 'trackRageClicks'\n | 'trackNavigation'\n | 'flushIntervalMs'\n | 'flushMaxBytes'\n >\n> = {\n apiUrl: 'https://api.ghostplay.dev/v1',\n maskAllInputs: true,\n recordNetwork: true,\n recordConsole: true,\n trackPerformance: true,\n trackRageClicks: true,\n trackNavigation: true,\n flushIntervalMs: 5000,\n flushMaxBytes: 50_000,\n};\n\n// --- Session ---\n\nexport interface Session {\n id: string;\n projectId: string;\n startedAt: number;\n userId?: string;\n userTraits?: Record<string, unknown>;\n tags: string[];\n metadata: Record<string, unknown>;\n}\n\n// --- Events ---\n\nexport type GhostplayEventType =\n | 'rrweb'\n | 'error'\n | 'network'\n | 'console'\n | 'performance'\n | 'rage-click'\n | 'breadcrumb'\n | 'identify'\n | 'tag'\n | 'metadata'\n | 'navigation';\n\nexport interface GhostplayEvent {\n type: GhostplayEventType;\n timestamp: number;\n sessionId: string;\n data: unknown;\n}\n\nexport interface ErrorEventData {\n message: string;\n stack?: string;\n source?: string;\n lineno?: number;\n colno?: number;\n type: 'onerror' | 'unhandledrejection';\n}\n\nexport interface NetworkEventData {\n method: string;\n url: string;\n status?: number;\n statusText?: string;\n requestHeaders?: Record<string, string>;\n responseHeaders?: Record<string, string>;\n requestBody?: string;\n responseBody?: string;\n startTime: number;\n endTime?: number;\n duration?: number;\n}\n\nexport interface ConsoleEventData {\n level: 'log' | 'warn' | 'error' | 'info' | 'debug';\n args: unknown[];\n}\n\nexport interface PerformanceEventData {\n metric: 'LCP' | 'FID' | 'CLS' | 'TTFB' | 'INP';\n value: number;\n rating: 'good' | 'needs-improvement' | 'poor';\n}\n\nexport interface RageClickEventData {\n selector: string;\n clickCount: number;\n x: number;\n y: number;\n}\n\nexport interface BreadcrumbEventData {\n category: 'navigation' | 'click' | 'input' | 'error' | 'network' | 'custom';\n message: string;\n data?: Record<string, unknown>;\n}\n\nexport interface NavigationEventData {\n from: string | null;\n to: string;\n trigger: 'pushState' | 'replaceState' | 'popstate' | 'hashchange' | 'initial';\n}\n\n// --- Transport ---\n\nexport interface EventBatch {\n projectId: string;\n sessionId: string;\n events: GhostplayEvent[];\n sentAt: number;\n}\n","import { type GhostplayConfig, DEFAULT_CONFIG } from './types';\n\nexport type ResolvedConfig = GhostplayConfig & typeof DEFAULT_CONFIG;\n\nexport function resolveConfig(config: GhostplayConfig): ResolvedConfig {\n if (!config.projectId) {\n throw new Error('[Ghostplay] projectId is required');\n }\n if (!config.projectId.startsWith('gp_')) {\n throw new Error('[Ghostplay] projectId must start with \"gp_\"');\n }\n\n return { ...DEFAULT_CONFIG, ...config };\n}\n","import type { Session } from './types';\n\nfunction generateId(): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 10);\n return `gs_${timestamp}_${random}`;\n}\n\nexport class SessionManager {\n private session: Session | null = null;\n\n constructor(private projectId: string) {}\n\n start(): Session {\n this.session = {\n id: generateId(),\n projectId: this.projectId,\n startedAt: Date.now(),\n tags: [],\n metadata: {},\n };\n return this.session;\n }\n\n current(): Session {\n if (!this.session) {\n throw new Error('[Ghostplay] No active session');\n }\n return this.session;\n }\n\n identify(userId: string, traits?: Record<string, unknown>): void {\n const session = this.current();\n session.userId = userId;\n session.userTraits = traits;\n }\n\n addTag(tag: string): void {\n const session = this.current();\n if (!session.tags.includes(tag)) {\n session.tags.push(tag);\n }\n }\n\n setMetadata(data: Record<string, unknown>): void {\n const session = this.current();\n session.metadata = { ...session.metadata, ...data };\n }\n\n end(): void {\n this.session = null;\n }\n}\n","import { record } from 'rrweb';\nimport type { GhostplayEvent } from './types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\n\nexport class Recorder {\n private stopFn: (() => void) | null = null;\n\n constructor(\n private sessionId: string,\n private emit: EventCallback,\n private rrwebConfig?: Record<string, any>\n ) {}\n\n start(): void {\n this.stopFn = record({\n ...this.rrwebConfig,\n emit: (event: any) => {\n this.emit({\n type: 'rrweb',\n timestamp: event.timestamp,\n sessionId: this.sessionId,\n data: event,\n });\n },\n }) ?? null;\n }\n\n stop(): void {\n if (this.stopFn) {\n this.stopFn();\n this.stopFn = null;\n }\n }\n}\n","import type { GhostplayEvent, ErrorEventData } from '../types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\n\nexport class ErrorTracker {\n private onErrorHandler: OnErrorEventHandler | null = null;\n private onRejectionHandler: ((e: PromiseRejectionEvent) => void) | null = null;\n private previousOnError: OnErrorEventHandler | null = null;\n\n constructor(\n private sessionId: string,\n private emit: EventCallback\n ) {}\n\n start(): void {\n this.previousOnError = window.onerror;\n\n this.onErrorHandler = (message, source, lineno, colno, error) => {\n const data: ErrorEventData = {\n message: String(message),\n stack: error?.stack,\n source: source ?? undefined,\n lineno: lineno ?? undefined,\n colno: colno ?? undefined,\n type: 'onerror',\n };\n\n this.emit({\n type: 'error',\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data,\n });\n\n if (this.previousOnError) {\n return this.previousOnError.call(window, message, source, lineno, colno, error);\n }\n return false;\n };\n\n this.onRejectionHandler = (e: PromiseRejectionEvent) => {\n const reason = e.reason;\n const data: ErrorEventData = {\n message:\n reason instanceof Error ? reason.message : String(reason),\n stack: reason instanceof Error ? reason.stack : undefined,\n type: 'unhandledrejection',\n };\n\n this.emit({\n type: 'error',\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data,\n });\n };\n\n window.onerror = this.onErrorHandler;\n window.addEventListener('unhandledrejection', this.onRejectionHandler);\n }\n\n stop(): void {\n if (this.previousOnError) {\n window.onerror = this.previousOnError;\n } else {\n window.onerror = null;\n }\n\n if (this.onRejectionHandler) {\n window.removeEventListener('unhandledrejection', this.onRejectionHandler);\n }\n\n this.onErrorHandler = null;\n this.onRejectionHandler = null;\n }\n}\n","import type { GhostplayEvent, NetworkEventData } from '../types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\n\nconst GHOSTPLAY_URL_PATTERN = /ghostplay\\.dev/;\nconst MAX_BODY_SIZE = 1024 * 1024; // 1MB limit per body\n\nexport class NetworkInterceptor {\n private originalFetch: typeof fetch | null = null;\n private active = false;\n\n constructor(\n private sessionId: string,\n private emit: EventCallback\n ) {}\n\n start(): void {\n this.active = true;\n this.patchFetch();\n }\n\n stop(): void {\n this.active = false;\n this.restoreFetch();\n }\n\n private patchFetch(): void {\n this.originalFetch = globalThis.fetch;\n const self = this;\n\n globalThis.fetch = async function (\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> {\n const url =\n typeof input === 'string'\n ? input\n : input instanceof URL\n ? input.toString()\n : input.url;\n const method = init?.method ?? 'GET';\n\n if (GHOSTPLAY_URL_PATTERN.test(url)) {\n return self.originalFetch!.call(globalThis, input, init);\n }\n\n const startTime = Date.now();\n\n // Extract request headers\n const requestHeaders = extractHeaders(init?.headers);\n\n // Extract request body\n const requestBody = extractBody(init?.body);\n\n try {\n const response = await self.originalFetch!.call(\n globalThis,\n input,\n init\n );\n\n if (self.active) {\n // Extract response headers\n const responseHeaders: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n // Clone response to read body without consuming the original\n let responseBody: string | undefined;\n try {\n const contentType = response.headers.get('content-type') ?? '';\n if (contentType.includes('json') || contentType.includes('text')) {\n const clone = response.clone();\n const text = await clone.text();\n responseBody = text.length > MAX_BODY_SIZE\n ? text.substring(0, MAX_BODY_SIZE) + '...[truncated]'\n : text;\n }\n } catch {\n // Body read failed — skip\n }\n\n const data: NetworkEventData = {\n method: method.toUpperCase(),\n url,\n status: response.status,\n statusText: response.statusText,\n requestHeaders,\n responseHeaders,\n requestBody,\n responseBody,\n startTime,\n endTime: Date.now(),\n duration: Date.now() - startTime,\n };\n\n self.emit({\n type: 'network',\n timestamp: startTime,\n sessionId: self.sessionId,\n data,\n });\n }\n\n return response;\n } catch (error) {\n if (self.active) {\n const data: NetworkEventData = {\n method: method.toUpperCase(),\n url,\n requestHeaders,\n requestBody,\n startTime,\n endTime: Date.now(),\n duration: Date.now() - startTime,\n };\n\n self.emit({\n type: 'network',\n timestamp: startTime,\n sessionId: self.sessionId,\n data,\n });\n }\n\n throw error;\n }\n };\n }\n\n private restoreFetch(): void {\n if (this.originalFetch) {\n globalThis.fetch = this.originalFetch;\n this.originalFetch = null;\n }\n }\n}\n\nfunction extractHeaders(headers: HeadersInit | undefined): Record<string, string> {\n const result: Record<string, string> = {};\n if (!headers) return result;\n\n if (headers instanceof Headers) {\n headers.forEach((value, key) => { result[key] = value; });\n } else if (Array.isArray(headers)) {\n for (const [key, value] of headers) { result[key] = value; }\n } else {\n for (const [key, value] of Object.entries(headers)) { result[key] = value; }\n }\n\n return result;\n}\n\nfunction extractBody(body: BodyInit | null | undefined): string | undefined {\n if (!body) return undefined;\n\n if (typeof body === 'string') {\n return body.length > MAX_BODY_SIZE\n ? body.substring(0, MAX_BODY_SIZE) + '...[truncated]'\n : body;\n }\n\n if (body instanceof URLSearchParams) {\n return body.toString();\n }\n\n // FormData, Blob, ArrayBuffer, ReadableStream — skip (too complex/binary)\n return undefined;\n}\n","import type { GhostplayEvent, ConsoleEventData } from '../types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\ntype ConsoleLevel = 'log' | 'warn' | 'error' | 'info' | 'debug';\n\nconst LEVELS: ConsoleLevel[] = ['log', 'warn', 'error', 'info', 'debug'];\n\nexport class ConsoleInterceptor {\n private originals: Partial<Record<ConsoleLevel, (...args: unknown[]) => void>> = {};\n\n constructor(\n private sessionId: string,\n private emit: EventCallback\n ) {}\n\n start(): void {\n for (const level of LEVELS) {\n this.originals[level] = console[level].bind(console);\n console[level] = (...args: unknown[]) => {\n const data: ConsoleEventData = {\n level,\n args: args.map((arg) => this.serialize(arg)),\n };\n this.emit({\n type: 'console',\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data,\n });\n this.originals[level]?.(...args);\n };\n }\n }\n\n stop(): void {\n for (const level of LEVELS) {\n if (this.originals[level]) {\n console[level] = this.originals[level] as any;\n }\n }\n this.originals = {};\n }\n\n private serialize(arg: unknown): unknown {\n if (arg instanceof Error) {\n return { __type: 'Error', message: arg.message, stack: arg.stack };\n }\n if (typeof arg === 'object' && arg !== null) {\n try { JSON.stringify(arg); return arg; } catch { return String(arg); }\n }\n return arg;\n }\n}\n","import type { GhostplayEvent, PerformanceEventData } from '../types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\ntype Metric = PerformanceEventData['metric'];\n\nconst THRESHOLDS: Record<Metric, [number, number]> = {\n LCP: [1000, 4000],\n FID: [100, 300],\n CLS: [0.1, 0.25],\n TTFB: [800, 1800],\n INP: [200, 500],\n};\n\nexport class PerformanceTracker {\n private observers: PerformanceObserver[] = [];\n\n constructor(\n private sessionId: string,\n private emit: EventCallback\n ) {}\n\n start(): void {\n if (typeof PerformanceObserver === 'undefined') return;\n this.observeLCP();\n this.observeFID();\n this.observeCLS();\n this.observeTTFB();\n this.observeINP();\n }\n\n stop(): void {\n this.observers.forEach((o) => o.disconnect());\n this.observers = [];\n }\n\n handleMetric(metric: Metric, value: number): void {\n const [good, poor] = THRESHOLDS[metric];\n const rating: PerformanceEventData['rating'] =\n value <= good ? 'good' : value <= poor ? 'needs-improvement' : 'poor';\n this.emit({\n type: 'performance',\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data: { metric, value, rating },\n });\n }\n\n private observeLCP(): void {\n try {\n const observer = new PerformanceObserver((list) => {\n const entries = list.getEntries();\n const last = entries[entries.length - 1];\n if (last) this.handleMetric('LCP', last.startTime);\n });\n observer.observe({ type: 'largest-contentful-paint', buffered: true });\n this.observers.push(observer);\n } catch {}\n }\n\n private observeFID(): void {\n try {\n const observer = new PerformanceObserver((list) => {\n const entries = list.getEntries();\n const first = entries[0] as any;\n if (first) this.handleMetric('FID', first.processingStart - first.startTime);\n });\n observer.observe({ type: 'first-input', buffered: true });\n this.observers.push(observer);\n } catch {}\n }\n\n private observeCLS(): void {\n let clsValue = 0;\n try {\n const observer = new PerformanceObserver((list) => {\n for (const entry of list.getEntries() as any[]) {\n if (!entry.hadRecentInput) clsValue += entry.value;\n }\n this.handleMetric('CLS', clsValue);\n });\n observer.observe({ type: 'layout-shift', buffered: true });\n this.observers.push(observer);\n } catch {}\n }\n\n private observeTTFB(): void {\n try {\n const observer = new PerformanceObserver((list) => {\n const entry = list.getEntries()[0] as any;\n if (entry) this.handleMetric('TTFB', entry.responseStart);\n });\n observer.observe({ type: 'navigation', buffered: true });\n this.observers.push(observer);\n } catch {}\n }\n\n private observeINP(): void {\n try {\n const observer = new PerformanceObserver((list) => {\n for (const entry of list.getEntries() as any[]) {\n this.handleMetric('INP', entry.duration);\n }\n });\n observer.observe({ type: 'event', buffered: true });\n this.observers.push(observer);\n } catch {}\n }\n}\n","import type { GhostplayEvent, RageClickEventData } from '../types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\n\nconst RAGE_THRESHOLD = 3;\nconst RAGE_WINDOW_MS = 1000;\n\ninterface ClickRecord {\n element: Element;\n timestamps: number[];\n}\n\nexport class RageClickDetector {\n private clickHandler: ((e: MouseEvent) => void) | null = null;\n private recentClicks: ClickRecord[] = [];\n\n constructor(\n private sessionId: string,\n private emit: EventCallback\n ) {}\n\n start(): void {\n this.clickHandler = (e: MouseEvent) => {\n const target = e.target as Element;\n if (!target) return;\n const now = Date.now();\n let record = this.recentClicks.find((r) => r.element === target);\n if (!record) {\n record = { element: target, timestamps: [] };\n this.recentClicks.push(record);\n }\n record.timestamps.push(now);\n record.timestamps = record.timestamps.filter((t) => now - t < RAGE_WINDOW_MS);\n if (record.timestamps.length >= RAGE_THRESHOLD) {\n const data: RageClickEventData = {\n selector: this.getSelector(target),\n clickCount: record.timestamps.length,\n x: e.clientX,\n y: e.clientY,\n };\n this.emit({\n type: 'rage-click',\n timestamp: now,\n sessionId: this.sessionId,\n data,\n });\n record.timestamps = [];\n }\n this.recentClicks = this.recentClicks.filter((r) => r.timestamps.length > 0);\n };\n document.addEventListener('click', this.clickHandler, true);\n }\n\n stop(): void {\n if (this.clickHandler) {\n document.removeEventListener('click', this.clickHandler, true);\n this.clickHandler = null;\n }\n this.recentClicks = [];\n }\n\n private getSelector(el: Element): string {\n if (el.id) return `#${el.id}`;\n const testId = el.getAttribute('data-testid');\n if (testId) return `[data-testid=\"${testId}\"]`;\n const tag = el.tagName.toLowerCase();\n const className = el.className\n ? `.${el.className.split(' ').filter(Boolean).join('.')}`\n : '';\n return `${tag}${className}`;\n }\n}\n","import type { BreadcrumbEventData } from '../types';\n\nexport class Breadcrumbs {\n private trail: BreadcrumbEventData[] = [];\n\n constructor(private maxSize: number = 50) {}\n\n add(\n category: BreadcrumbEventData['category'],\n message: string,\n data?: Record<string, unknown>\n ): void {\n const crumb: BreadcrumbEventData = { category, message };\n if (data) crumb.data = data;\n this.trail.push(crumb);\n if (this.trail.length > this.maxSize) {\n this.trail = this.trail.slice(-this.maxSize);\n }\n }\n\n getTrail(): BreadcrumbEventData[] {\n return [...this.trail];\n }\n\n clear(): void {\n this.trail = [];\n }\n}\n","import type { GhostplayEvent, NavigationEventData } from '../types';\n\ntype EventCallback = (event: GhostplayEvent) => void;\n\nexport class NavigationTracker {\n private currentUrl: string = '';\n private originalPushState: typeof history.pushState | null = null;\n private originalReplaceState: typeof history.replaceState | null = null;\n private popstateHandler: (() => void) | null = null;\n private hashchangeHandler: (() => void) | null = null;\n\n constructor(\n private sessionId: string,\n private emit: EventCallback\n ) {}\n\n start(): void {\n this.currentUrl = window.location.href;\n\n // Emit initial navigation event\n this.emitNavigation(null, this.currentUrl, 'initial');\n\n // Patch history.pushState\n this.originalPushState = history.pushState.bind(history);\n history.pushState = (...args: Parameters<typeof history.pushState>) => {\n this.originalPushState!(...args);\n this.handleUrlChange('pushState');\n };\n\n // Patch history.replaceState\n this.originalReplaceState = history.replaceState.bind(history);\n history.replaceState = (...args: Parameters<typeof history.replaceState>) => {\n this.originalReplaceState!(...args);\n this.handleUrlChange('replaceState');\n };\n\n // Listen for popstate (back/forward)\n this.popstateHandler = () => this.handleUrlChange('popstate');\n window.addEventListener('popstate', this.popstateHandler);\n\n // Listen for hashchange\n this.hashchangeHandler = () => this.handleUrlChange('hashchange');\n window.addEventListener('hashchange', this.hashchangeHandler);\n }\n\n stop(): void {\n if (this.originalPushState) {\n history.pushState = this.originalPushState;\n this.originalPushState = null;\n }\n if (this.originalReplaceState) {\n history.replaceState = this.originalReplaceState;\n this.originalReplaceState = null;\n }\n if (this.popstateHandler) {\n window.removeEventListener('popstate', this.popstateHandler);\n this.popstateHandler = null;\n }\n if (this.hashchangeHandler) {\n window.removeEventListener('hashchange', this.hashchangeHandler);\n this.hashchangeHandler = null;\n }\n }\n\n private handleUrlChange(trigger: NavigationEventData['trigger']): void {\n const newUrl = window.location.href;\n if (newUrl !== this.currentUrl) {\n const from = this.currentUrl;\n this.currentUrl = newUrl;\n this.emitNavigation(from, newUrl, trigger);\n }\n }\n\n private emitNavigation(from: string | null, to: string, trigger: NavigationEventData['trigger']): void {\n const data: NavigationEventData = { from, to, trigger };\n this.emit({\n type: 'navigation',\n timestamp: Date.now(),\n sessionId: this.sessionId,\n data,\n });\n }\n}\n","import type { GhostplayConfig, NetworkEventData } from './types';\n\nconst ALWAYS_DENY_RESPONSE_HEADERS = ['set-cookie'];\n\ninterface PrivacyOptions {\n networkSanitize?: GhostplayConfig['networkSanitize'];\n}\n\nexport class PrivacyFilter {\n constructor(private options: PrivacyOptions) {}\n\n sanitizeNetworkEvent(event: NetworkEventData): NetworkEventData {\n const result = { ...event };\n const config = this.options.networkSanitize;\n\n // Always remove sensitive response headers\n if (result.responseHeaders) {\n result.responseHeaders = this.filterHeaders(\n result.responseHeaders,\n ALWAYS_DENY_RESPONSE_HEADERS\n );\n }\n\n if (!config) return result;\n\n // Remove denied request headers\n if (result.requestHeaders && config.denyHeaders.length > 0) {\n result.requestHeaders = this.filterHeaders(\n result.requestHeaders,\n config.denyHeaders\n );\n }\n\n // Remove denied response headers\n if (result.responseHeaders && config.denyHeaders.length > 0) {\n result.responseHeaders = this.filterHeaders(\n result.responseHeaders,\n config.denyHeaders\n );\n }\n\n // Redact body for denied URLs\n if (config.denyBodyUrls.length > 0 && this.urlMatchesDeny(event.url, config.denyBodyUrls)) {\n if (result.requestBody) result.requestBody = '[REDACTED]';\n if (result.responseBody) result.responseBody = '[REDACTED]';\n }\n\n return result;\n }\n\n private filterHeaders(\n headers: Record<string, string>,\n denyList: string[]\n ): Record<string, string> {\n const denyLower = denyList.map((h) => h.toLowerCase());\n const filtered: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (!denyLower.includes(key.toLowerCase())) {\n filtered[key] = value;\n }\n }\n return filtered;\n }\n\n private urlMatchesDeny(url: string, patterns: string[]): boolean {\n return patterns.some((pattern) => {\n const regex = new RegExp(\n '^' + pattern.replace(/\\*/g, '.*') + '$'\n );\n return regex.test(url);\n });\n }\n}\n","import type { GhostplayEvent, EventBatch } from './types';\n\ninterface TransportConfig {\n apiUrl: string;\n projectId: string;\n sessionId: string;\n flushIntervalMs: number;\n flushMaxBytes: number;\n}\n\nconst KEEPALIVE_LIMIT = 60_000; // Stay under 64KB browser limit\n\nexport class Transport {\n private buffer: GhostplayEvent[] = [];\n private bufferBytes = 0;\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(private config: TransportConfig) {}\n\n start(): void {\n this.flushTimer = setInterval(() => {\n this.flush();\n }, this.config.flushIntervalMs);\n }\n\n stop(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush();\n }\n\n send(event: GhostplayEvent): void {\n const eventSize = JSON.stringify(event).length;\n this.buffer.push(event);\n this.bufferBytes += eventSize;\n if (this.bufferBytes >= this.config.flushMaxBytes) {\n this.flush();\n }\n }\n\n private flush(): void {\n if (this.buffer.length === 0) return;\n const events = this.buffer;\n this.buffer = [];\n this.bufferBytes = 0;\n const batch: EventBatch = {\n projectId: this.config.projectId,\n sessionId: this.config.sessionId,\n events,\n sentAt: Date.now(),\n };\n const body = JSON.stringify(batch);\n const url = `${this.config.apiUrl}/events`;\n\n // Use keepalive only for small payloads (Safari enforces 64KB limit strictly)\n const useKeepalive = body.length < KEEPALIVE_LIMIT;\n\n try {\n fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-project-id': this.config.projectId,\n },\n body,\n keepalive: useKeepalive,\n })\n .then((res) => {\n if (!res.ok) {\n console.warn(`[Ghostplay] Event batch rejected (${res.status})`);\n }\n })\n .catch(() => {\n // Fallback to sendBeacon\n this.sendBeacon(url, body);\n });\n } catch {\n this.sendBeacon(url, body);\n }\n }\n\n private sendBeacon(url: string, body: string): void {\n if (typeof navigator !== 'undefined' && navigator.sendBeacon) {\n navigator.sendBeacon(url, new Blob([body], { type: 'application/json' }));\n }\n }\n}\n","import { resolveConfig, type ResolvedConfig } from './config';\nimport { SessionManager } from './session';\nimport { Recorder } from './recorder';\nimport { ErrorTracker } from './modules/error-tracker';\nimport { NetworkInterceptor } from './modules/network-interceptor';\nimport { ConsoleInterceptor } from './modules/console-interceptor';\nimport { PerformanceTracker } from './modules/performance-tracker';\nimport { RageClickDetector } from './modules/rage-click-detector';\nimport { Breadcrumbs } from './modules/breadcrumbs';\nimport { NavigationTracker } from './modules/navigation-tracker';\nimport { PrivacyFilter } from './privacy';\nimport { Transport } from './transport';\nimport type { GhostplayConfig, GhostplayEvent } from './types';\n\nexport const VERSION = '0.1.0';\n\nlet config: ResolvedConfig | null = null;\nlet sessionManager: SessionManager | null = null;\nlet recorder: Recorder | null = null;\nlet errorTracker: ErrorTracker | null = null;\nlet networkInterceptor: NetworkInterceptor | null = null;\nlet consoleInterceptor: ConsoleInterceptor | null = null;\nlet performanceTracker: PerformanceTracker | null = null;\nlet rageClickDetector: RageClickDetector | null = null;\nlet breadcrumbs: Breadcrumbs | null = null;\nlet navigationTracker: NavigationTracker | null = null;\nlet privacyFilter: PrivacyFilter | null = null;\nlet transport: Transport | null = null;\n\nfunction ensureInitialized(): void {\n if (!sessionManager) {\n throw new Error('[Ghostplay] SDK not initialized. Call Ghostplay.init() first.');\n }\n}\n\nfunction handleEvent(event: GhostplayEvent): void {\n if (breadcrumbs && event.type !== 'rrweb') {\n breadcrumbs.add(\n event.type === 'error'\n ? 'error'\n : event.type === 'network'\n ? 'network'\n : event.type === 'rage-click'\n ? 'click'\n : 'custom',\n `${event.type}: ${JSON.stringify(event.data).substring(0, 100)}`\n );\n }\n transport?.send(event);\n}\n\nfunction init(userConfig: GhostplayConfig): void {\n stop();\n config = resolveConfig(userConfig);\n sessionManager = new SessionManager(config.projectId);\n const session = sessionManager.start();\n\n privacyFilter = new PrivacyFilter({\n networkSanitize: config.networkSanitize,\n });\n\n transport = new Transport({\n apiUrl: config.apiUrl,\n projectId: config.projectId,\n sessionId: session.id,\n flushIntervalMs: config.flushIntervalMs,\n flushMaxBytes: config.flushMaxBytes,\n });\n transport.start();\n\n breadcrumbs = new Breadcrumbs();\n\n recorder = new Recorder(session.id, handleEvent, {\n maskAllInputs: config.maskAllInputs,\n ...(config.maskInputSelector ? { maskInputSelector: config.maskInputSelector } : {}),\n ...(config.blockSelector ? { blockSelector: config.blockSelector } : {}),\n ...(config.ignoreSelector ? { ignoreSelector: config.ignoreSelector } : {}),\n // Take a fresh FullSnapshot every 5 seconds so async-loaded content\n // is captured even when MutationObserver misses framework renders\n // (e.g. conflicts with other replay tools like LogRocket).\n checkoutEveryNms: 5000,\n ...config.rrwebConfig,\n });\n\n // Defer recording start so the initial FullSnapshot captures the\n // rendered DOM shell rather than an empty SPA root element.\n const startRecording = () => recorder?.start();\n if (document.readyState === 'complete') {\n requestAnimationFrame(() => requestAnimationFrame(startRecording));\n } else {\n window.addEventListener('load', () =>\n requestAnimationFrame(startRecording), { once: true });\n }\n\n errorTracker = new ErrorTracker(session.id, handleEvent);\n errorTracker.start();\n\n if (config.recordNetwork) {\n networkInterceptor = new NetworkInterceptor(session.id, (event) => {\n const sanitized = privacyFilter!.sanitizeNetworkEvent(event.data as any);\n handleEvent({ ...event, data: sanitized });\n });\n networkInterceptor.start();\n }\n\n if (config.recordConsole) {\n consoleInterceptor = new ConsoleInterceptor(session.id, handleEvent);\n consoleInterceptor.start();\n }\n\n if (config.trackPerformance) {\n performanceTracker = new PerformanceTracker(session.id, handleEvent);\n performanceTracker.start();\n }\n\n if (config.trackRageClicks) {\n rageClickDetector = new RageClickDetector(session.id, handleEvent);\n rageClickDetector.start();\n }\n\n if (config.trackNavigation) {\n navigationTracker = new NavigationTracker(session.id, handleEvent);\n navigationTracker.start();\n }\n}\n\nfunction identify(userId: string, traits?: Record<string, unknown>): void {\n ensureInitialized();\n sessionManager!.identify(userId, traits);\n handleEvent({\n type: 'identify',\n timestamp: Date.now(),\n sessionId: sessionManager!.current().id,\n data: { userId, traits },\n });\n}\n\nfunction tag(tagName: string): void {\n ensureInitialized();\n sessionManager!.addTag(tagName);\n handleEvent({\n type: 'tag',\n timestamp: Date.now(),\n sessionId: sessionManager!.current().id,\n data: { tag: tagName },\n });\n}\n\nfunction setMetadata(data: Record<string, unknown>): void {\n ensureInitialized();\n sessionManager!.setMetadata(data);\n handleEvent({\n type: 'metadata',\n timestamp: Date.now(),\n sessionId: sessionManager!.current().id,\n data,\n });\n}\n\nfunction stop(): void {\n recorder?.stop();\n errorTracker?.stop();\n networkInterceptor?.stop();\n consoleInterceptor?.stop();\n performanceTracker?.stop();\n rageClickDetector?.stop();\n navigationTracker?.stop();\n transport?.stop();\n sessionManager?.end();\n\n recorder = null;\n errorTracker = null;\n networkInterceptor = null;\n consoleInterceptor = null;\n performanceTracker = null;\n rageClickDetector = null;\n navigationTracker = null;\n transport = null;\n sessionManager = null;\n breadcrumbs = null;\n privacyFilter = null;\n config = null;\n}\n\nexport const Ghostplay = {\n VERSION,\n init,\n identify,\n tag,\n setMetadata,\n stop,\n};\n\nexport default Ghostplay;\nexport type { GhostplayConfig, GhostplayEvent, Session } from './types';\n"]}
|