@watchupltd/browser 0.1.0 → 0.1.2

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transport.ts","../src/batcher.ts","../src/error-capture.ts","../src/perf.ts","../src/watchup.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["// ─────────────────────────────────────────────────────────────────────────────\n// @watchupltd/browser · transport\n//\n// Two delivery strategies:\n// 1. fetch(keepalive: true) — for regular periodic flushes.\n// 2. navigator.sendBeacon — for page-hide/unload; survives tab close.\n// ─────────────────────────────────────────────────────────────────────────────\n\nimport type { IngestBatch } from './types.js';\n\nexport class Transport {\n private readonly url: string;\n private readonly headers: Record<string, string>;\n private readonly debug: boolean;\n\n constructor(baseUrl: string, apiKey: string, debug = false) {\n this.url = `${baseUrl.replace(/\\/$/, '')}/api/v1/ingest/batch`;\n this.headers = {\n 'Content-Type': 'application/json',\n 'X-Api-Key': apiKey,\n };\n this.debug = debug;\n }\n\n /**\n * Send via `fetch` with `keepalive: true`.\n * `keepalive` lets the request outlive the current page — it's the\n * browser equivalent of a \"fire and forget\" POST.\n * Never rejects.\n */\n async send(batch: IngestBatch): Promise<void> {\n try {\n const body = JSON.stringify(batch);\n\n // keepalive has a 64 KiB payload limit; fall back to beacon for large batches\n if (body.length > 60_000) {\n this.beacon(batch);\n return;\n }\n\n const res = await fetch(this.url, {\n method: 'POST',\n headers: this.headers,\n body,\n keepalive: true,\n });\n\n if (this.debug && !res.ok) {\n const text = await res.text().catch(() => '');\n console.warn(`[watchup] ingest ${res.status}: ${text}`);\n }\n } catch (err) {\n if (this.debug) console.warn('[watchup] send failed:', err);\n }\n }\n\n /**\n * Send via `navigator.sendBeacon`.\n * Returns `true` if the browser accepted the request (doesn't guarantee delivery).\n * The server must accept `application/json` from sendBeacon via a Blob.\n */\n beacon(batch: IngestBatch): boolean {\n if (typeof navigator === 'undefined' || !navigator.sendBeacon) return false;\n try {\n const blob = new Blob([JSON.stringify(batch)], { type: 'application/json' });\n return navigator.sendBeacon(this.url, blob);\n } catch {\n return false;\n }\n }\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// @watchupltd/browser · batcher\n//\n// Browser-specific flush strategy:\n// - Periodic interval flush via fetch(keepalive)\n// - visibilitychange 'hidden' + pagehide → sendBeacon for reliable exit delivery\n// ─────────────────────────────────────────────────────────────────────────────\n\nimport type { TracePayload, ErrorPayload, EventPayload, IngestBatch } from './types.js';\nimport { Transport } from './transport.js';\n\nexport class Batcher {\n private traces: TracePayload[] = [];\n private errors: ErrorPayload[] = [];\n private events: EventPayload[] = [];\n\n private readonly transport: Transport;\n private readonly flushInterval: number;\n private readonly maxBatchSize: number;\n\n private timer: ReturnType<typeof setInterval> | null = null;\n private flushing = false;\n\n constructor(transport: Transport, flushInterval: number, maxBatchSize: number) {\n this.transport = transport;\n this.flushInterval = flushInterval;\n this.maxBatchSize = maxBatchSize;\n }\n\n start(): void {\n if (this.timer) return;\n\n // Periodic flush\n this.timer = setInterval(() => this.flush(), this.flushInterval);\n\n // Reliable delivery on tab hide — visibilitychange fires before the page\n // is destroyed, giving sendBeacon the best chance of succeeding.\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') this.beaconFlush();\n });\n\n // Belt-and-suspenders for browsers/environments that skip visibilitychange\n window.addEventListener('pagehide', () => this.beaconFlush(), { once: true });\n }\n\n stop(): void {\n if (this.timer) { clearInterval(this.timer); this.timer = null; }\n }\n\n addTrace(t: TracePayload): void {\n this.traces.push(t);\n if (this.traces.length >= this.maxBatchSize) this.flush();\n }\n\n addError(e: ErrorPayload): void {\n this.errors.push(e);\n // Errors are high-priority — flush at half capacity\n if (this.errors.length >= Math.ceil(this.maxBatchSize / 2)) this.flush();\n }\n\n addEvent(e: EventPayload): void {\n this.events.push(e);\n if (this.events.length >= this.maxBatchSize) this.flush();\n }\n\n private drain(): IngestBatch | null {\n const traces = this.traces.splice(0);\n const errors = this.errors.splice(0);\n const events = this.events.splice(0);\n if (!traces.length && !errors.length && !events.length) return null;\n return { traces, errors, events };\n }\n\n flush(): void {\n if (this.flushing) return;\n const batch = this.drain();\n if (!batch) return;\n this.flushing = true;\n this.transport.send(batch).finally(() => { this.flushing = false; });\n }\n\n beaconFlush(): void {\n const batch = this.drain();\n if (!batch) return;\n // Try beacon first; fall back to fetch if unsupported\n if (!this.transport.beacon(batch)) {\n this.transport.send(batch);\n }\n }\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// @watchupltd/browser · global error capture\n// ─────────────────────────────────────────────────────────────────────────────\n\nimport type { ErrorPayload } from './types.js';\n\ntype ErrorCallback = (error: ErrorPayload) => void;\n\n/**\n * Attaches `window.onerror` and `window.addEventListener('unhandledrejection')`\n * listeners that forward caught errors to `onError`.\n *\n * Returns a cleanup function that removes both listeners.\n */\nexport function captureGlobalErrors(onError: ErrorCallback, env?: string): () => void {\n const handleError = (event: ErrorEvent) => {\n onError({\n message: event.message || 'Unknown error',\n level: 'error',\n route: window.location.pathname,\n stack: event.error?.stack,\n context: {\n url: window.location.href,\n source: event.filename ?? undefined,\n line: event.lineno ?? undefined,\n col: event.colno ?? undefined,\n },\n timestamp: new Date().toISOString(),\n ...(env && { environment: env }),\n });\n };\n\n const handleRejection = (event: PromiseRejectionEvent) => {\n const reason = event.reason;\n const isErr = reason instanceof Error;\n onError({\n message: isErr ? reason.message : String(reason ?? 'Unhandled Promise rejection'),\n level: 'error',\n route: window.location.pathname,\n stack: isErr ? reason.stack : undefined,\n context: {\n url: window.location.href,\n type: 'unhandledrejection',\n },\n timestamp: new Date().toISOString(),\n ...(env && { environment: env }),\n });\n };\n\n window.addEventListener('error', handleError);\n window.addEventListener('unhandledrejection', handleRejection);\n\n return () => {\n window.removeEventListener('error', handleError);\n window.removeEventListener('unhandledrejection', handleRejection);\n };\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// @watchupltd/browser · Web Vitals capture\n//\n// Captures FCP, LCP, and overall page-load time via PerformanceObserver and\n// PerformanceNavigationTiming. Forwarded as traces so they appear in the\n// Watchup dashboard alongside request spans.\n//\n// Thresholds come from Google's Core Web Vitals 2024 targets:\n// FCP: good ≤ 1800 ms, needs improvement ≤ 3000 ms, poor > 3000 ms\n// LCP: good ≤ 2500 ms, needs improvement ≤ 4000 ms, poor > 4000 ms\n// ─────────────────────────────────────────────────────────────────────────────\n\nimport type { TracePayload } from './types.js';\n\ntype TraceCallback = (trace: TracePayload) => void;\n\nfunction rating(\n ms: number,\n good: number,\n needsImprovement: number,\n): TracePayload['status'] {\n if (ms <= good) return 'ok';\n if (ms <= needsImprovement) return 'warn';\n return 'err';\n}\n\nfunction statusCode(status: TracePayload['status']): number {\n return status === 'err' ? 500 : status === 'warn' ? 400 : 200;\n}\n\n// ── FCP — First Contentful Paint ─────────────────────────────────────────────\n\nexport function captureFCP(onTrace: TraceCallback, env?: string): void {\n if (typeof PerformanceObserver === 'undefined') return;\n try {\n const po = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) {\n if (entry.name !== 'first-contentful-paint') continue;\n const ms = Math.round(entry.startTime);\n const status = rating(ms, 1800, 3000);\n onTrace({\n span: 'web-vital fcp',\n ms,\n status_code: statusCode(status),\n status,\n timestamp: new Date().toISOString(),\n ...(env && { environment: env }),\n });\n po.disconnect();\n }\n });\n po.observe({ type: 'paint', buffered: true });\n } catch { /* PerformanceObserver 'paint' not supported */ }\n}\n\n// ── LCP — Largest Contentful Paint ───────────────────────────────────────────\n\nexport function captureLCP(onTrace: TraceCallback, env?: string): void {\n if (typeof PerformanceObserver === 'undefined') return;\n\n let last: PerformanceEntry | null = null;\n let reported = false;\n\n const report = () => {\n if (reported || !last) return;\n reported = true;\n try { po.disconnect(); } catch {}\n const ms = Math.round(last.startTime);\n const status = rating(ms, 2500, 4000);\n onTrace({\n span: 'web-vital lcp',\n ms,\n status_code: statusCode(status),\n status,\n timestamp: new Date().toISOString(),\n ...(env && { environment: env }),\n });\n };\n\n let po: PerformanceObserver;\n try {\n po = new PerformanceObserver((list) => {\n const entries = list.getEntries();\n if (entries.length) last = entries[entries.length - 1] ?? null;\n });\n po.observe({ type: 'largest-contentful-paint', buffered: true });\n } catch {\n return; // 'largest-contentful-paint' not supported\n }\n\n // LCP is only finalised once the user interacts or the tab hides.\n document.addEventListener('visibilitychange', report, { once: true });\n document.addEventListener('keydown', report, { once: true, capture: true });\n document.addEventListener('pointerdown', report, { once: true, capture: true });\n}\n\n// ── Page load (overall) ───────────────────────────────────────────────────────\n\nexport function capturePageLoad(onTrace: TraceCallback, env?: string): void {\n const report = () => {\n const nav = performance.getEntriesByType('navigation')[0] as\n PerformanceNavigationTiming | undefined;\n if (!nav || nav.loadEventEnd <= 0) return;\n\n const ms = Math.round(nav.loadEventEnd - nav.startTime);\n const ttfb = Math.round(nav.responseStart - nav.requestStart);\n const status = rating(ms, 2000, 4000);\n\n onTrace({\n span: 'pageload',\n ms,\n status_code: statusCode(status),\n status,\n timestamp: new Date().toISOString(),\n meta: { ttfb },\n ...(env && { environment: env }),\n });\n };\n\n if (document.readyState === 'complete') {\n // PerformanceNavigationTiming might not be fully populated yet\n setTimeout(report, 0);\n } else {\n window.addEventListener('load', () => setTimeout(report, 100), { once: true });\n }\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// @watchupltd/browser · Watchup client\n// ─────────────────────────────────────────────────────────────────────────────\n\nimport type { WatchupOptions, TracePayload, ErrorPayload, EventPayload } from './types.js';\nimport { Transport } from './transport.js';\nimport { Batcher } from './batcher.js';\nimport { captureGlobalErrors } from './error-capture.js';\nimport { captureFCP, captureLCP, capturePageLoad } from './perf.js';\n\nconst DEFAULTS = {\n baseUrl: 'https://api.watchup.site',\n flushInterval: 5_000,\n maxBatchSize: 100,\n debug: false,\n environment: 'production',\n release: '',\n sampleRate: 1,\n autoCapture: {\n errors: true,\n performance: true,\n pageViews: true,\n },\n} as const;\n\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport class Watchup {\n private readonly cfg: Required<WatchupOptions>;\n private readonly batcher: Batcher;\n private readonly cleanup: Array<() => void> = [];\n\n /**\n * A random UUID generated on init. Stable for the lifetime of the page —\n * useful for correlating all events from one user session.\n */\n readonly sessionId: string = crypto.randomUUID();\n\n constructor(options: WatchupOptions) {\n if (!options.apiKey) {\n throw new Error('[watchup] apiKey is required.');\n }\n\n this.cfg = {\n ...DEFAULTS,\n autoCapture: { ...DEFAULTS.autoCapture, ...options.autoCapture },\n ...options,\n } as Required<WatchupOptions>;\n\n const transport = new Transport(this.cfg.baseUrl, this.cfg.apiKey, this.cfg.debug);\n this.batcher = new Batcher(transport, this.cfg.flushInterval, this.cfg.maxBatchSize);\n this.batcher.start();\n\n this._setupAutoCapture();\n }\n\n // ── Public API ────────────────────────────────────────────────────────────\n\n /**\n * Track a custom analytics event.\n *\n * @example\n * watchup.track('button.clicked', { label: 'Sign Up', variant: 'A' });\n */\n track(name: string, properties?: Record<string, unknown>): void {\n if (!name) return;\n const event: EventPayload = {\n name,\n ...(properties && Object.keys(properties).length && { properties }),\n occurred_at: new Date().toISOString(),\n };\n this.batcher.addEvent(event);\n }\n\n /**\n * Manually capture an error.\n *\n * @example\n * try { ... } catch (err) {\n * watchup.captureError(err, { component: 'CheckoutForm' });\n * }\n */\n captureError(\n error: Error | string | unknown,\n context?: Record<string, unknown> & { route?: string; level?: ErrorPayload['level'] },\n ): void {\n const { route, level = 'error', ...rest } = context ?? {};\n const err = error instanceof Error ? error : new Error(String(error));\n\n const payload: ErrorPayload = {\n message: err.message,\n level,\n ...(err.stack !== undefined && { stack: err.stack }),\n route: route ?? window.location.pathname,\n ...(Object.keys(rest).length && {\n context: { ...rest, url: window.location.href },\n }),\n timestamp: new Date().toISOString(),\n environment: this.cfg.environment,\n ...(this.cfg.release && { release: this.cfg.release }),\n };\n\n this.batcher.addError(payload);\n }\n\n /**\n * Time any async operation and record it as a trace.\n * Returns an `end()` function — call it when the operation finishes.\n *\n * @example\n * const end = watchup.startTrace('fetch /api/cart');\n * const cart = await fetch('/api/cart');\n * end({ status: cart.ok ? 'ok' : 'err' });\n */\n startTrace(\n span: string,\n ): (opts?: { status?: TracePayload['status']; meta?: Record<string, unknown> }) => void {\n const start = Date.now();\n return (opts = {}) => {\n const status = opts.status ?? 'ok';\n this.batcher.addTrace({\n span,\n ms: Date.now() - start,\n status_code: status === 'err' ? 500 : status === 'warn' ? 400 : 200,\n status,\n timestamp: new Date().toISOString(),\n environment: this.cfg.environment,\n ...(this.cfg.release && { release: this.cfg.release }),\n ...(opts.meta && { meta: opts.meta }),\n });\n };\n }\n\n /** Immediately flush all queued items. */\n flush(): void { this.batcher.flush(); }\n\n /** Stop the flush timer and release all listeners. */\n shutdown(): void {\n this.batcher.stop();\n this.batcher.flush();\n this.cleanup.forEach((fn) => fn());\n }\n\n // ── Auto-capture setup ────────────────────────────────────────────────────\n\n private _setupAutoCapture(): void {\n const { autoCapture, environment } = this.cfg;\n\n if (autoCapture.errors) {\n this.cleanup.push(\n captureGlobalErrors((e) => this.batcher.addError(e), environment),\n );\n }\n\n if (autoCapture.performance) {\n captureFCP((t) => this.batcher.addTrace(t), environment);\n captureLCP((t) => this.batcher.addTrace(t), environment);\n capturePageLoad((t) => this.batcher.addTrace(t), environment);\n }\n\n if (autoCapture.pageViews) {\n this._setupPageViewTracking();\n }\n }\n\n private _setupPageViewTracking(): void {\n const track = () => {\n this.batcher.addEvent({\n name: 'pageview',\n properties: {\n path: window.location.pathname,\n ...(window.location.search && { search: window.location.search }),\n ...(document.referrer && { referrer: document.referrer }),\n title: document.title,\n },\n occurred_at: new Date().toISOString(),\n });\n };\n\n // Initial view\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', track, { once: true });\n } else {\n // Small timeout so the page title has settled\n setTimeout(track, 0);\n }\n\n // SPA navigation — patch History API\n const origPush = history.pushState.bind(history);\n const origReplace = history.replaceState.bind(history);\n\n history.pushState = (...args: Parameters<typeof history.pushState>) => {\n origPush(...args);\n setTimeout(track, 0); // title settles asynchronously\n };\n history.replaceState = (...args: Parameters<typeof history.replaceState>) => {\n origReplace(...args);\n // replaceState often doesn't mean a new \"page\" (it's used for URL\n // canonicalisation etc.) — only track if the pathname actually changed.\n };\n\n const onPopState = () => setTimeout(track, 0);\n window.addEventListener('popstate', onPopState);\n\n this.cleanup.push(() => {\n history.pushState = origPush;\n history.replaceState = origReplace;\n window.removeEventListener('popstate', onPopState);\n });\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/transport.ts","../src/batcher.ts","../src/error-capture.ts","../src/perf.ts","../src/watchup.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["// ─────────────────────────────────────────────────────────────────────────────\n// @watchupltd/browser · transport\n//\n// Two delivery strategies:\n// 1. fetch(keepalive: true) — for regular periodic flushes.\n// 2. navigator.sendBeacon — for page-hide/unload; survives tab close.\n//\n// Web analytics events are sent to a separate endpoint (/web-batch) that is\n// optimised for high-volume, low-latency browser hits.\n// ─────────────────────────────────────────────────────────────────────────────\n\nimport type { IngestBatch, WebAnalyticsBatch } from './types.js';\n\nexport class Transport {\n private readonly url: string;\n private readonly webUrl: string;\n private readonly headers: Record<string, string>;\n private readonly debug: boolean;\n\n constructor(baseUrl: string, apiKey: string, debug = false) {\n const base = baseUrl.replace(/\\/$/, '');\n this.url = `${base}/api/v1/ingest/batch`;\n this.webUrl = `${base}/api/v1/ingest/web-batch`;\n this.headers = {\n 'Content-Type': 'application/json',\n 'X-Api-Key': apiKey,\n };\n this.debug = debug;\n }\n\n /**\n * Send via `fetch` with `keepalive: true`.\n * `keepalive` lets the request outlive the current page — it's the\n * browser equivalent of a \"fire and forget\" POST.\n * Never rejects.\n */\n async send(batch: IngestBatch): Promise<void> {\n try {\n const body = JSON.stringify(batch);\n\n // keepalive has a 64 KiB payload limit; fall back to beacon for large batches\n if (body.length > 60_000) {\n this.beacon(batch);\n return;\n }\n\n const res = await fetch(this.url, {\n method: 'POST',\n headers: this.headers,\n body,\n keepalive: true,\n });\n\n if (this.debug && !res.ok) {\n const text = await res.text().catch(() => '');\n console.warn(`[watchup] ingest ${res.status}: ${text}`);\n }\n } catch (err) {\n if (this.debug) console.warn('[watchup] send failed:', err);\n }\n }\n\n /**\n * Send web analytics batch to the dedicated /web-batch endpoint.\n * Never rejects.\n */\n async sendWeb(batch: WebAnalyticsBatch): Promise<void> {\n try {\n const body = JSON.stringify(batch);\n\n if (body.length > 60_000) {\n this.beaconWeb(batch);\n return;\n }\n\n const res = await fetch(this.webUrl, {\n method: 'POST',\n headers: this.headers,\n body,\n keepalive: true,\n });\n\n if (this.debug && !res.ok) {\n const text = await res.text().catch(() => '');\n console.warn(`[watchup] web-batch ${res.status}: ${text}`);\n }\n } catch (err) {\n if (this.debug) console.warn('[watchup] sendWeb failed:', err);\n }\n }\n\n /**\n * Send via `navigator.sendBeacon`.\n * Returns `true` if the browser accepted the request (doesn't guarantee delivery).\n * The server must accept `application/json` from sendBeacon via a Blob.\n */\n beacon(batch: IngestBatch): boolean {\n if (typeof navigator === 'undefined' || !navigator.sendBeacon) return false;\n try {\n const blob = new Blob([JSON.stringify(batch)], { type: 'application/json' });\n return navigator.sendBeacon(this.url, blob);\n } catch {\n return false;\n }\n }\n\n /**\n * sendBeacon variant for web analytics events.\n */\n beaconWeb(batch: WebAnalyticsBatch): boolean {\n if (typeof navigator === 'undefined' || !navigator.sendBeacon) return false;\n try {\n const blob = new Blob([JSON.stringify(batch)], { type: 'application/json' });\n return navigator.sendBeacon(this.webUrl, blob);\n } catch {\n return false;\n }\n }\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// @watchupltd/browser · batcher\n//\n// Browser-specific flush strategy:\n// - Periodic interval flush via fetch(keepalive)\n// - visibilitychange 'hidden' + pagehide → sendBeacon for reliable exit delivery\n//\n// Two independent queues:\n// - telemetry queue (traces, errors, events) → /ingest/batch\n// - web queue (web page views) → /ingest/web-batch\n// ─────────────────────────────────────────────────────────────────────────────\n\nimport type {\n TracePayload,\n ErrorPayload,\n EventPayload,\n IngestBatch,\n WebAnalyticsPayload,\n WebAnalyticsBatch,\n} from './types.js';\nimport { Transport } from './transport.js';\n\nexport class Batcher {\n private traces: TracePayload[] = [];\n private errors: ErrorPayload[] = [];\n private events: EventPayload[] = [];\n private webViews: WebAnalyticsPayload[] = [];\n\n private readonly transport: Transport;\n private readonly flushInterval: number;\n private readonly maxBatchSize: number;\n\n private timer: ReturnType<typeof setInterval> | null = null;\n private flushing = false;\n\n constructor(transport: Transport, flushInterval: number, maxBatchSize: number) {\n this.transport = transport;\n this.flushInterval = flushInterval;\n this.maxBatchSize = maxBatchSize;\n }\n\n start(): void {\n if (this.timer) return;\n\n // Periodic flush\n this.timer = setInterval(() => this.flush(), this.flushInterval);\n\n // Reliable delivery on tab hide — visibilitychange fires before the page\n // is destroyed, giving sendBeacon the best chance of succeeding.\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') this.beaconFlush();\n });\n\n // Belt-and-suspenders for browsers/environments that skip visibilitychange\n window.addEventListener('pagehide', () => this.beaconFlush(), { once: true });\n }\n\n stop(): void {\n if (this.timer) { clearInterval(this.timer); this.timer = null; }\n }\n\n // ── Telemetry queue ───────────────────────────────────────────────────────\n\n addTrace(t: TracePayload): void {\n this.traces.push(t);\n if (this.traces.length >= this.maxBatchSize) this.flush();\n }\n\n addError(e: ErrorPayload): void {\n this.errors.push(e);\n // Errors are high-priority — flush at half capacity\n if (this.errors.length >= Math.ceil(this.maxBatchSize / 2)) this.flush();\n }\n\n addEvent(e: EventPayload): void {\n this.events.push(e);\n if (this.events.length >= this.maxBatchSize) this.flush();\n }\n\n // ── Web analytics queue ───────────────────────────────────────────────────\n\n addWebView(payload: WebAnalyticsPayload): void {\n this.webViews.push(payload);\n if (this.webViews.length >= this.maxBatchSize) this.flushWeb();\n }\n\n // ── Drain helpers ─────────────────────────────────────────────────────────\n\n private drainTelemetry(): IngestBatch | null {\n const traces = this.traces.splice(0);\n const errors = this.errors.splice(0);\n const events = this.events.splice(0);\n if (!traces.length && !errors.length && !events.length) return null;\n return { traces, errors, events };\n }\n\n private drainWeb(): WebAnalyticsBatch | null {\n const web = this.webViews.splice(0);\n if (!web.length) return null;\n return { web };\n }\n\n // ── Flush ─────────────────────────────────────────────────────────────────\n\n flush(): void {\n if (!this.flushing) {\n const batch = this.drainTelemetry();\n if (batch) {\n this.flushing = true;\n this.transport.send(batch).finally(() => { this.flushing = false; });\n }\n }\n this.flushWeb();\n }\n\n flushWeb(): void {\n const batch = this.drainWeb();\n if (batch) this.transport.sendWeb(batch);\n }\n\n beaconFlush(): void {\n // Telemetry\n const batch = this.drainTelemetry();\n if (batch) {\n if (!this.transport.beacon(batch)) this.transport.send(batch);\n }\n // Web analytics\n const webBatch = this.drainWeb();\n if (webBatch) {\n if (!this.transport.beaconWeb(webBatch)) this.transport.sendWeb(webBatch);\n }\n }\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// @watchupltd/browser · global error capture\n// ─────────────────────────────────────────────────────────────────────────────\n\nimport type { ErrorPayload } from './types.js';\n\ntype ErrorCallback = (error: ErrorPayload) => void;\n\n/**\n * Attaches `window.onerror` and `window.addEventListener('unhandledrejection')`\n * listeners that forward caught errors to `onError`.\n *\n * Returns a cleanup function that removes both listeners.\n */\nexport function captureGlobalErrors(onError: ErrorCallback, env?: string): () => void {\n const handleError = (event: ErrorEvent) => {\n onError({\n message: event.message || 'Unknown error',\n level: 'error',\n route: window.location.pathname,\n stack: event.error?.stack,\n context: {\n url: window.location.href,\n source: event.filename ?? undefined,\n line: event.lineno ?? undefined,\n col: event.colno ?? undefined,\n },\n timestamp: new Date().toISOString(),\n ...(env && { environment: env }),\n });\n };\n\n const handleRejection = (event: PromiseRejectionEvent) => {\n const reason = event.reason;\n const isErr = reason instanceof Error;\n onError({\n message: isErr ? reason.message : String(reason ?? 'Unhandled Promise rejection'),\n level: 'error',\n route: window.location.pathname,\n stack: isErr ? reason.stack : undefined,\n context: {\n url: window.location.href,\n type: 'unhandledrejection',\n },\n timestamp: new Date().toISOString(),\n ...(env && { environment: env }),\n });\n };\n\n window.addEventListener('error', handleError);\n window.addEventListener('unhandledrejection', handleRejection);\n\n return () => {\n window.removeEventListener('error', handleError);\n window.removeEventListener('unhandledrejection', handleRejection);\n };\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// @watchupltd/browser · Web Vitals capture\n//\n// Captures FCP, LCP, and overall page-load time via PerformanceObserver and\n// PerformanceNavigationTiming. Forwarded as traces so they appear in the\n// Watchup dashboard alongside request spans.\n//\n// Thresholds come from Google's Core Web Vitals 2024 targets:\n// FCP: good ≤ 1800 ms, needs improvement ≤ 3000 ms, poor > 3000 ms\n// LCP: good ≤ 2500 ms, needs improvement ≤ 4000 ms, poor > 4000 ms\n// ─────────────────────────────────────────────────────────────────────────────\n\nimport type { TracePayload } from './types.js';\n\ntype TraceCallback = (trace: TracePayload) => void;\n\nfunction rating(\n ms: number,\n good: number,\n needsImprovement: number,\n): TracePayload['status'] {\n if (ms <= good) return 'ok';\n if (ms <= needsImprovement) return 'warn';\n return 'err';\n}\n\nfunction statusCode(status: TracePayload['status']): number {\n return status === 'err' ? 500 : status === 'warn' ? 400 : 200;\n}\n\n// ── FCP — First Contentful Paint ─────────────────────────────────────────────\n\nexport function captureFCP(onTrace: TraceCallback, env?: string): void {\n if (typeof PerformanceObserver === 'undefined') return;\n try {\n const po = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) {\n if (entry.name !== 'first-contentful-paint') continue;\n const ms = Math.round(entry.startTime);\n const status = rating(ms, 1800, 3000);\n onTrace({\n span: 'web-vital fcp',\n ms,\n status_code: statusCode(status),\n status,\n timestamp: new Date().toISOString(),\n ...(env && { environment: env }),\n });\n po.disconnect();\n }\n });\n po.observe({ type: 'paint', buffered: true });\n } catch { /* PerformanceObserver 'paint' not supported */ }\n}\n\n// ── LCP — Largest Contentful Paint ───────────────────────────────────────────\n\nexport function captureLCP(onTrace: TraceCallback, env?: string): void {\n if (typeof PerformanceObserver === 'undefined') return;\n\n let last: PerformanceEntry | null = null;\n let reported = false;\n\n const report = () => {\n if (reported || !last) return;\n reported = true;\n try { po.disconnect(); } catch {}\n const ms = Math.round(last.startTime);\n const status = rating(ms, 2500, 4000);\n onTrace({\n span: 'web-vital lcp',\n ms,\n status_code: statusCode(status),\n status,\n timestamp: new Date().toISOString(),\n ...(env && { environment: env }),\n });\n };\n\n let po: PerformanceObserver;\n try {\n po = new PerformanceObserver((list) => {\n const entries = list.getEntries();\n if (entries.length) last = entries[entries.length - 1] ?? null;\n });\n po.observe({ type: 'largest-contentful-paint', buffered: true });\n } catch {\n return; // 'largest-contentful-paint' not supported\n }\n\n // LCP is only finalised once the user interacts or the tab hides.\n document.addEventListener('visibilitychange', report, { once: true });\n document.addEventListener('keydown', report, { once: true, capture: true });\n document.addEventListener('pointerdown', report, { once: true, capture: true });\n}\n\n// ── Page load (overall) ───────────────────────────────────────────────────────\n\nexport function capturePageLoad(onTrace: TraceCallback, env?: string): void {\n const report = () => {\n const nav = performance.getEntriesByType('navigation')[0] as\n PerformanceNavigationTiming | undefined;\n if (!nav || nav.loadEventEnd <= 0) return;\n\n const ms = Math.round(nav.loadEventEnd - nav.startTime);\n const ttfb = Math.round(nav.responseStart - nav.requestStart);\n const status = rating(ms, 2000, 4000);\n\n onTrace({\n span: 'pageload',\n ms,\n status_code: statusCode(status),\n status,\n timestamp: new Date().toISOString(),\n meta: { ttfb },\n ...(env && { environment: env }),\n });\n };\n\n if (document.readyState === 'complete') {\n // PerformanceNavigationTiming might not be fully populated yet\n setTimeout(report, 0);\n } else {\n window.addEventListener('load', () => setTimeout(report, 100), { once: true });\n }\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// @watchupltd/browser · Watchup client\n// ─────────────────────────────────────────────────────────────────────────────\n\nimport type {\n WatchupOptions,\n WatchupUser,\n TracePayload,\n ErrorPayload,\n EventPayload,\n WebAnalyticsPayload,\n} from './types.js';\nimport { Transport } from './transport.js';\nimport { Batcher } from './batcher.js';\nimport { captureGlobalErrors } from './error-capture.js';\nimport { captureFCP, captureLCP, capturePageLoad } from './perf.js';\n\nconst DEFAULTS = {\n baseUrl: 'https://api.watchup.site',\n flushInterval: 5_000,\n maxBatchSize: 100,\n debug: false,\n environment: 'production',\n release: '',\n sampleRate: 1,\n autoCapture: {\n errors: true,\n performance: true,\n pageViews: true,\n },\n} as const;\n\n// ── Storage keys ──────────────────────────────────────────────────────────────\n\nconst VISITOR_KEY = '__wup_vid';\nconst SESSION_KEY = '__wup_sid';\n\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport class Watchup {\n private readonly cfg: Required<WatchupOptions>;\n private readonly batcher: Batcher;\n private readonly cleanup: Array<() => void> = [];\n private _user: WatchupUser | null = null;\n\n /**\n * A random UUID generated on init. Stable for the lifetime of the page —\n * useful for correlating all events from one user session.\n */\n readonly sessionId: string = crypto.randomUUID();\n\n // ── Visitor / session identity ─────────────────────────────────────────────\n\n /**\n * Persistent visitor ID. Stored in localStorage so it survives browser\n * sessions. Falls back to a per-session UUID when localStorage is blocked.\n * The server hashes this value with SHA-256 before persisting.\n */\n private readonly visitorId: string;\n\n /**\n * Per-session ID stored in sessionStorage. Resets on tab close.\n * The server hashes this value before persisting.\n */\n private readonly webSessionId: string;\n\n constructor(options: WatchupOptions) {\n if (!options.apiKey) {\n throw new Error('[watchup] apiKey is required.');\n }\n\n this.cfg = {\n ...DEFAULTS,\n autoCapture: { ...DEFAULTS.autoCapture, ...options.autoCapture },\n ...options,\n } as Required<WatchupOptions>;\n\n const transport = new Transport(this.cfg.baseUrl, this.cfg.apiKey, this.cfg.debug);\n this.batcher = new Batcher(transport, this.cfg.flushInterval, this.cfg.maxBatchSize);\n this.batcher.start();\n\n // Initialise visitor & session IDs\n this.visitorId = this._getOrCreateVisitorId();\n this.webSessionId = this._getOrCreateSessionId();\n\n this._setupAutoCapture();\n }\n\n // ── Visitor / session identity helpers ─────────────────────────────────────\n\n private _getOrCreateVisitorId(): string {\n try {\n let id = localStorage.getItem(VISITOR_KEY);\n if (!id) {\n id = crypto.randomUUID();\n localStorage.setItem(VISITOR_KEY, id);\n }\n return id;\n } catch {\n // localStorage blocked (private mode, etc.) — fall back to session scope\n return crypto.randomUUID();\n }\n }\n\n private _getOrCreateSessionId(): string {\n try {\n let id = sessionStorage.getItem(SESSION_KEY);\n if (!id) {\n id = crypto.randomUUID();\n sessionStorage.setItem(SESSION_KEY, id);\n }\n return id;\n } catch {\n return this.sessionId; // fallback: correlate with SDK sessionId\n }\n }\n\n // ── User identification ───────────────────────────────────────────────────\n\n /**\n * Attach a user to all subsequent errors, traces, and events.\n * Call this after login; the context persists until `clearUser()` or page reload.\n *\n * @example\n * watchup.setUser({ id: '42', email: 'ada@example.com', name: 'Ada Lovelace' });\n */\n setUser(user: WatchupUser): void {\n this._user = { ...user };\n }\n\n /**\n * Remove the current user context (e.g. after logout).\n */\n clearUser(): void {\n this._user = null;\n }\n\n // ── Public API ────────────────────────────────────────────────────────────\n\n /**\n * Track a custom analytics event.\n *\n * @example\n * watchup.track('button.clicked', { label: 'Sign Up', variant: 'A' });\n */\n track(name: string, properties?: Record<string, unknown>): void {\n if (!name) return;\n const event: EventPayload = {\n name,\n ...(properties && Object.keys(properties).length && { properties }),\n occurred_at: new Date().toISOString(),\n };\n this.batcher.addEvent(event);\n }\n\n /**\n * Track a web analytics page view (or custom web event).\n * Enriches the payload with visitor context, UTM params, and device info.\n *\n * Normally called automatically. Call manually when you need custom event_name.\n *\n * @example\n * watchup.trackWebView({ event_name: 'conversion', path: '/checkout/success' });\n */\n trackWebView(overrides: Partial<WebAnalyticsPayload> = {}): void {\n const url = new URL(window.location.href);\n const params = url.searchParams;\n\n const payload: WebAnalyticsPayload = {\n path: url.pathname + (url.search || ''),\n hostname: url.hostname,\n referrer: document.referrer || undefined,\n title: document.title || undefined,\n screen_w: window.screen?.width,\n screen_h: window.screen?.height,\n lang: navigator.language || undefined,\n timezone: this._timezone(),\n // UTM parameters\n utm_source: params.get('utm_source') || undefined,\n utm_medium: params.get('utm_medium') || undefined,\n utm_campaign: params.get('utm_campaign') || undefined,\n utm_term: params.get('utm_term') || undefined,\n utm_content: params.get('utm_content') || undefined,\n // Identity (raw; the server hashes before storing)\n visitor_id: this.visitorId,\n session_id: this.webSessionId,\n event_name: 'pageview',\n occurred_at: new Date().toISOString(),\n // Apply caller overrides last\n ...overrides,\n };\n\n this.batcher.addWebView(payload);\n }\n\n /**\n * Manually capture an error.\n *\n * @example\n * try { ... } catch (err) {\n * watchup.captureError(err, { component: 'CheckoutForm' });\n * }\n */\n captureError(\n error: Error | string | unknown,\n context?: Record<string, unknown> & { route?: string; level?: ErrorPayload['level'] },\n ): void {\n const { route, level = 'error', ...rest } = context ?? {};\n const err = error instanceof Error ? error : new Error(String(error));\n\n const payload: ErrorPayload = {\n message: err.message,\n level,\n ...(err.stack !== undefined && { stack: err.stack }),\n route: route ?? window.location.pathname,\n ...(Object.keys(rest).length && {\n context: { ...rest, url: window.location.href },\n }),\n timestamp: new Date().toISOString(),\n environment: this.cfg.environment,\n ...(this.cfg.release && { release: this.cfg.release }),\n ...(this._user && { user: this._user }),\n };\n\n this.batcher.addError(payload);\n }\n\n /**\n * Time any async operation and record it as a trace.\n * Returns an `end()` function — call it when the operation finishes.\n *\n * @example\n * const end = watchup.startTrace('fetch /api/cart');\n * const cart = await fetch('/api/cart');\n * end({ status: cart.ok ? 'ok' : 'err' });\n */\n startTrace(\n span: string,\n ): (opts?: { status?: TracePayload['status']; meta?: Record<string, unknown> }) => void {\n const start = Date.now();\n return (opts = {}) => {\n const status = opts.status ?? 'ok';\n this.batcher.addTrace({\n span,\n ms: Date.now() - start,\n status_code: status === 'err' ? 500 : status === 'warn' ? 400 : 200,\n status,\n timestamp: new Date().toISOString(),\n environment: this.cfg.environment,\n ...(this.cfg.release && { release: this.cfg.release }),\n ...(opts.meta && { meta: opts.meta }),\n ...(this._user && { user: this._user }),\n });\n };\n }\n\n /** Immediately flush all queued items (both telemetry and web analytics). */\n flush(): void { this.batcher.flush(); }\n\n /** Stop the flush timer and release all listeners. */\n shutdown(): void {\n this.batcher.stop();\n this.batcher.flush();\n this.cleanup.forEach((fn) => fn());\n }\n\n // ── Auto-capture setup ────────────────────────────────────────────────────\n\n private _setupAutoCapture(): void {\n const { autoCapture, environment } = this.cfg;\n\n if (autoCapture.errors) {\n this.cleanup.push(\n captureGlobalErrors((e) => this.batcher.addError(e), environment),\n );\n }\n\n if (autoCapture.performance) {\n captureFCP((t) => this.batcher.addTrace(t), environment);\n captureLCP((t) => this.batcher.addTrace(t), environment);\n capturePageLoad((t) => this.batcher.addTrace(t), environment);\n }\n\n if (autoCapture.pageViews) {\n this._setupPageViewTracking();\n }\n }\n\n private _setupPageViewTracking(): void {\n const trackView = () => {\n // Small delay so the page title has settled after navigation\n setTimeout(() => this.trackWebView(), 0);\n };\n\n // Initial view\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', trackView, { once: true });\n } else {\n setTimeout(() => this.trackWebView(), 0);\n }\n\n // SPA navigation — patch History API\n const origPush = history.pushState.bind(history);\n const origReplace = history.replaceState.bind(history);\n\n history.pushState = (...args: Parameters<typeof history.pushState>) => {\n origPush(...args);\n trackView();\n };\n history.replaceState = (...args: Parameters<typeof history.replaceState>) => {\n origReplace(...args);\n // replaceState is often used for URL canonicalisation — don't track.\n };\n\n const onPopState = () => trackView();\n window.addEventListener('popstate', onPopState);\n\n this.cleanup.push(() => {\n history.pushState = origPush;\n history.replaceState = origReplace;\n window.removeEventListener('popstate', onPopState);\n });\n }\n\n // ── Helpers ───────────────────────────────────────────────────────────────\n\n private _timezone(): string | undefined {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || undefined;\n } catch {\n return undefined;\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@watchupltd/browser",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Official Watchup SDK for browsers — analytics, errors, and performance",
5
5
  "license": "MIT",
6
6
  "author": "Watchup Ltd",
@@ -9,20 +9,23 @@
9
9
  "types": "./dist/index.d.ts",
10
10
  "exports": {
11
11
  ".": {
12
- "types": "./dist/index.d.ts",
13
- "import": "./dist/index.mjs",
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.mjs",
14
14
  "require": "./dist/index.js"
15
15
  }
16
16
  },
17
- "files": ["dist", "README.md"],
17
+ "files": [
18
+ "dist",
19
+ "README.md"
20
+ ],
18
21
  "sideEffects": false,
19
22
  "scripts": {
20
- "build": "tsup",
23
+ "build": "tsup",
21
24
  "typecheck": "tsc --noEmit",
22
- "dev": "tsup --watch"
25
+ "dev": "tsup --watch"
23
26
  },
24
27
  "devDependencies": {
25
- "tsup": "^8.0.2",
28
+ "tsup": "^8.0.2",
26
29
  "typescript": "^5.4.5"
27
30
  }
28
31
  }