@yraylabs/boring-analytics 0.1.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -402,7 +402,7 @@ function createStorage() {
|
|
|
402
402
|
}
|
|
403
403
|
|
|
404
404
|
// src/client.ts
|
|
405
|
-
var DEFAULT_ENDPOINT = "https://api.
|
|
405
|
+
var DEFAULT_ENDPOINT = "https://api.boring.yraylabs.fun";
|
|
406
406
|
var DEFAULT_FLUSH_AT = 20;
|
|
407
407
|
var DEFAULT_FLUSH_INTERVAL = 5e3;
|
|
408
408
|
var DEFAULT_MAX_RETRIES = 3;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/transport.ts","../src/queue.ts","../src/utils.ts","../src/session.ts","../src/error-handler.ts","../src/context.ts","../src/storage.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { IngestEventPayload, IngestErrorPayload } from './types';\n\nexport interface TransportConfig {\n endpoint: string;\n apiKey: string;\n maxRetries: number;\n onError?: (error: Error) => void;\n}\n\nexport class Transport {\n private config: TransportConfig;\n\n constructor(config: TransportConfig) {\n this.config = config;\n }\n\n async sendEvents(events: IngestEventPayload[]): Promise<void> {\n await this.post('/ingest/events', { events });\n }\n\n async sendErrors(errors: IngestErrorPayload[]): Promise<void> {\n await this.post('/ingest/errors', { errors });\n }\n\n private async post(path: string, body: unknown): Promise<void> {\n const url = this.config.endpoint.replace(/\\/+$/, '') + path;\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.config.apiKey,\n },\n body: JSON.stringify(body),\n keepalive: true,\n });\n\n if (response.ok) return;\n\n if (response.status >= 400 && response.status < 500 && response.status !== 429) {\n const text = await response.text().catch(() => '');\n throw new Error(`HTTP ${response.status}: ${text}`);\n }\n\n lastError = new Error(`HTTP ${response.status}`);\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (err instanceof Error && err.message.startsWith('HTTP 4')) {\n break;\n }\n }\n\n if (attempt < this.config.maxRetries) {\n await this.backoff(attempt);\n }\n }\n\n if (lastError) {\n this.config.onError?.(lastError);\n }\n }\n\n private backoff(attempt: number): Promise<void> {\n const delay = Math.min(1000 * 2 ** attempt, 30000);\n const jitter = delay * (0.5 + Math.random() * 0.5);\n return new Promise((resolve) => setTimeout(resolve, jitter));\n }\n}\n","import type { QueueItem, IngestEventPayload, IngestErrorPayload } from './types';\nimport type { Transport } from './transport';\n\nexport interface QueueConfig {\n flushAt: number;\n flushInterval: number;\n debug: ReturnType<typeof import('./utils').createDebugLogger>;\n}\n\nexport class EventQueue {\n private items: QueueItem[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private transport: Transport;\n private config: QueueConfig;\n private flushing = false;\n\n constructor(transport: Transport, config: QueueConfig) {\n this.transport = transport;\n this.config = config;\n this.startTimer();\n }\n\n add(item: QueueItem): void {\n this.items.push(item);\n this.config.debug.log(`Queued ${item.kind}:`, item.kind === 'event' ? item.payload.name : item.payload.message);\n\n if (this.items.length >= this.config.flushAt) {\n void this.flush();\n }\n }\n\n async flush(): Promise<void> {\n if (this.flushing || this.items.length === 0) return;\n\n this.flushing = true;\n const batch = this.items.splice(0);\n\n try {\n const events: IngestEventPayload[] = [];\n const errors: IngestErrorPayload[] = [];\n\n for (const item of batch) {\n if (item.kind === 'event') events.push(item.payload);\n else errors.push(item.payload);\n }\n\n const promises: Promise<void>[] = [];\n if (events.length > 0) {\n this.config.debug.log(`Flushing ${events.length} events`);\n promises.push(this.transport.sendEvents(events));\n }\n if (errors.length > 0) {\n this.config.debug.log(`Flushing ${errors.length} errors`);\n promises.push(this.transport.sendErrors(errors));\n }\n\n await Promise.all(promises);\n } catch {\n this.items.unshift(...batch);\n } finally {\n this.flushing = false;\n }\n }\n\n private startTimer(): void {\n if (this.config.flushInterval > 0) {\n this.timer = setInterval(() => {\n void this.flush();\n }, this.config.flushInterval);\n\n // Allow Node.js to exit without waiting for the timer\n if (this.timer && typeof (this.timer as NodeJS.Timeout).unref === 'function') {\n (this.timer as NodeJS.Timeout).unref();\n }\n }\n }\n\n async shutdown(): Promise<void> {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush();\n }\n\n get size(): number {\n return this.items.length;\n }\n}\n","export function generateId(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\nexport function now(): string {\n return new Date().toISOString();\n}\n\nexport function createDebugLogger(enabled: boolean) {\n return {\n log: (...args: unknown[]) => {\n if (enabled) console.log('[BoringAnalytics]', ...args);\n },\n warn: (...args: unknown[]) => {\n if (enabled) console.warn('[BoringAnalytics]', ...args);\n },\n error: (...args: unknown[]) => {\n if (enabled) console.error('[BoringAnalytics]', ...args);\n },\n };\n}\n","import type { Storage } from './storage';\nimport { generateId } from './utils';\n\nconst ANON_ID_KEY = 'anonymous_id';\nconst SESSION_ID_KEY = 'session_id';\nconst SESSION_EXPIRY_KEY = 'session_expiry';\n\n/** Session timeout: 30 minutes of inactivity */\nconst SESSION_TIMEOUT_MS = 30 * 60 * 1000;\n\nexport class SessionManager {\n private userId: string | null = null;\n private anonymousId: string;\n private sessionId: string;\n private storage: Storage;\n\n constructor(storage: Storage) {\n this.storage = storage;\n this.anonymousId = this.storage.get(ANON_ID_KEY) ?? this.createAnonymousId();\n this.sessionId = this.resolveSession();\n }\n\n private createAnonymousId(): string {\n const id = generateId();\n this.storage.set(ANON_ID_KEY, id);\n return id;\n }\n\n private resolveSession(): string {\n const existingSession = this.storage.get(SESSION_ID_KEY);\n const expiryStr = this.storage.get(SESSION_EXPIRY_KEY);\n const expiry = expiryStr ? parseInt(expiryStr, 10) : 0;\n\n if (existingSession && Date.now() < expiry) {\n this.touchSession();\n return existingSession;\n }\n\n return this.startNewSession();\n }\n\n private startNewSession(): string {\n const id = generateId();\n this.sessionId = id;\n this.storage.set(SESSION_ID_KEY, id);\n this.touchSession();\n return id;\n }\n\n private touchSession(): void {\n this.storage.set(\n SESSION_EXPIRY_KEY,\n String(Date.now() + SESSION_TIMEOUT_MS),\n );\n }\n\n setUserId(id: string): void {\n this.userId = id;\n }\n\n getUserId(): string | null {\n return this.userId;\n }\n\n getAnonymousId(): string {\n return this.anonymousId;\n }\n\n getSessionId(): string {\n this.sessionId = this.resolveSession();\n return this.sessionId;\n }\n\n reset(): void {\n this.userId = null;\n this.anonymousId = this.createAnonymousId();\n this.sessionId = this.startNewSession();\n }\n}\n","import { isBrowser } from './utils';\n\ntype ErrorCallback = (error: Error, source?: string) => void;\n\nexport class GlobalErrorHandler {\n private callback: ErrorCallback;\n private installed = false;\n private originalOnError: OnErrorEventHandler | null = null;\n private originalOnUnhandledRejection: ((ev: PromiseRejectionEvent) => void) | null = null;\n\n constructor(callback: ErrorCallback) {\n this.callback = callback;\n }\n\n install(): void {\n if (this.installed) return;\n this.installed = true;\n\n if (isBrowser()) {\n this.installBrowser();\n } else {\n this.installNode();\n }\n }\n\n uninstall(): void {\n if (!this.installed) return;\n this.installed = false;\n\n if (isBrowser()) {\n this.uninstallBrowser();\n } else {\n this.uninstallNode();\n }\n }\n\n private installBrowser(): void {\n this.originalOnError = window.onerror;\n window.onerror = (message, source, lineno, colno, error) => {\n if (error) {\n this.callback(error, source ?? undefined);\n } else if (typeof message === 'string') {\n this.callback(new Error(message), source ?? undefined);\n }\n this.originalOnError?.call(window, message, source, lineno, colno, error);\n };\n\n this.originalOnUnhandledRejection = window.onunhandledrejection as typeof this.originalOnUnhandledRejection;\n window.onunhandledrejection = (event: PromiseRejectionEvent) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n this.callback(error, 'unhandledrejection');\n (this.originalOnUnhandledRejection as ((ev: PromiseRejectionEvent) => void) | null)?.call(window, event);\n };\n }\n\n private uninstallBrowser(): void {\n window.onerror = this.originalOnError;\n window.onunhandledrejection = this.originalOnUnhandledRejection as typeof window.onunhandledrejection;\n }\n\n private installNode(): void {\n if (typeof process === 'undefined') return;\n\n process.on('uncaughtException', this.handleNodeError);\n process.on('unhandledRejection', this.handleNodeRejection);\n }\n\n private uninstallNode(): void {\n if (typeof process === 'undefined') return;\n\n process.removeListener('uncaughtException', this.handleNodeError);\n process.removeListener('unhandledRejection', this.handleNodeRejection);\n }\n\n private handleNodeError = (error: Error): void => {\n this.callback(error, 'uncaughtException');\n };\n\n private handleNodeRejection = (reason: unknown): void => {\n const error = reason instanceof Error ? reason : new Error(String(reason));\n this.callback(error, 'unhandledRejection');\n };\n}\n","import type { EventContext } from './types';\nimport { isBrowser } from './utils';\n\n/**\n * Parses a user agent string into browser, OS, and device info.\n * Lightweight — covers major browsers/platforms without a full UA parser dependency.\n */\nfunction parseUserAgent(ua: string): {\n browser: { name: string; version?: string };\n os: { name: string; version?: string };\n device: { type: string };\n} {\n const browser = { name: 'Unknown', version: undefined as string | undefined };\n const os = { name: 'Unknown', version: undefined as string | undefined };\n const device = { type: 'desktop' };\n\n // Mobile detection\n if (/Mobi|Android|iPhone|iPad|iPod/i.test(ua)) {\n device.type = /iPad|Tablet/i.test(ua) ? 'tablet' : 'mobile';\n }\n\n // Browser detection\n if (/Edg\\//i.test(ua)) {\n browser.name = 'Edge';\n browser.version = ua.match(/Edg\\/([\\d.]+)/)?.[1];\n } else if (/OPR\\//i.test(ua) || /Opera/i.test(ua)) {\n browser.name = 'Opera';\n browser.version = ua.match(/(?:OPR|Opera)\\/([\\d.]+)/)?.[1];\n } else if (/Chrome\\//i.test(ua) && !/Chromium/i.test(ua)) {\n browser.name = 'Chrome';\n browser.version = ua.match(/Chrome\\/([\\d.]+)/)?.[1];\n } else if (/Safari\\//i.test(ua) && !/Chrome/i.test(ua)) {\n browser.name = 'Safari';\n browser.version = ua.match(/Version\\/([\\d.]+)/)?.[1];\n } else if (/Firefox\\//i.test(ua)) {\n browser.name = 'Firefox';\n browser.version = ua.match(/Firefox\\/([\\d.]+)/)?.[1];\n }\n\n // OS detection\n if (/Windows NT/i.test(ua)) {\n os.name = 'Windows';\n const ntVersion = ua.match(/Windows NT ([\\d.]+)/)?.[1];\n const versionMap: Record<string, string> = {\n '10.0': '10+',\n '6.3': '8.1',\n '6.2': '8',\n '6.1': '7',\n };\n os.version = ntVersion ? (versionMap[ntVersion] ?? ntVersion) : undefined;\n } else if (/Mac OS X/i.test(ua)) {\n os.name = 'macOS';\n os.version = ua.match(/Mac OS X ([\\d_.]+)/)?.[1]?.replace(/_/g, '.');\n } else if (/Android/i.test(ua)) {\n os.name = 'Android';\n os.version = ua.match(/Android ([\\d.]+)/)?.[1];\n } else if (/iPhone OS|iPad/i.test(ua)) {\n os.name = 'iOS';\n os.version = ua.match(/OS ([\\d_]+)/)?.[1]?.replace(/_/g, '.');\n } else if (/Linux/i.test(ua)) {\n os.name = 'Linux';\n }\n\n return { browser, os, device };\n}\n\nexport function gatherContext(): EventContext {\n if (!isBrowser()) {\n return {};\n }\n\n const ua = navigator.userAgent;\n const { browser, os, device } = parseUserAgent(ua);\n\n return {\n userAgent: ua,\n locale: navigator.language,\n page: {\n url: window.location.href,\n referrer: document.referrer || undefined,\n title: document.title || undefined,\n path: window.location.pathname,\n },\n browser,\n os,\n device,\n };\n}\n\nexport function mergeContext(\n auto: EventContext,\n user?: Partial<EventContext>,\n): EventContext {\n if (!user) return auto;\n\n return {\n ...auto,\n ...user,\n page: { ...auto.page, ...user.page },\n browser: { ...auto.browser, ...user.browser },\n os: { ...auto.os, ...user.os },\n device: { ...auto.device, ...user.device },\n };\n}\n","const PREFIX = 'ba_';\n\nexport interface Storage {\n get(key: string): string | null;\n set(key: string, value: string): void;\n remove(key: string): void;\n}\n\nclass LocalStorage implements Storage {\n get(key: string): string | null {\n try {\n return localStorage.getItem(PREFIX + key);\n } catch {\n return null;\n }\n }\n\n set(key: string, value: string): void {\n try {\n localStorage.setItem(PREFIX + key, value);\n } catch {\n // localStorage unavailable or quota exceeded\n }\n }\n\n remove(key: string): void {\n try {\n localStorage.removeItem(PREFIX + key);\n } catch {\n // noop\n }\n }\n}\n\nclass MemoryStorage implements Storage {\n private store = new Map<string, string>();\n\n get(key: string): string | null {\n return this.store.get(PREFIX + key) ?? null;\n }\n\n set(key: string, value: string): void {\n this.store.set(PREFIX + key, value);\n }\n\n remove(key: string): void {\n this.store.delete(PREFIX + key);\n }\n}\n\nexport function createStorage(): Storage {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem('__ba_test__', '1');\n localStorage.removeItem('__ba_test__');\n return new LocalStorage();\n }\n } catch {\n // localStorage not available\n }\n return new MemoryStorage();\n}\n","import type {\n BoringAnalyticsConfig,\n TrackOptions,\n IdentifyOptions,\n PageOptions,\n ScreenOptions,\n GroupOptions,\n CaptureErrorOptions,\n IngestEventPayload,\n IngestErrorPayload,\n EventContext,\n} from './types';\nimport { Transport } from './transport';\nimport { EventQueue } from './queue';\nimport { SessionManager } from './session';\nimport { GlobalErrorHandler } from './error-handler';\nimport { gatherContext, mergeContext } from './context';\nimport { createStorage } from './storage';\nimport { createDebugLogger, isBrowser, now } from './utils';\n\nconst DEFAULT_ENDPOINT = 'https://api.boringanalytics.io';\nconst DEFAULT_FLUSH_AT = 20;\nconst DEFAULT_FLUSH_INTERVAL = 5000;\nconst DEFAULT_MAX_RETRIES = 3;\n\nexport class BoringAnalytics {\n private queue: EventQueue;\n private session: SessionManager;\n private errorHandler: GlobalErrorHandler | null = null;\n private debug: ReturnType<typeof createDebugLogger>;\n private config: Required<\n Pick<BoringAnalyticsConfig, 'defaultProperties'>\n > & BoringAnalyticsConfig;\n private pageViewUnsubscribe: (() => void) | null = null;\n\n constructor(config: BoringAnalyticsConfig) {\n if (!config.apiKey) {\n throw new Error('BoringAnalytics: apiKey is required');\n }\n\n this.config = {\n ...config,\n defaultProperties: config.defaultProperties ?? {},\n };\n\n this.debug = createDebugLogger(config.debug ?? false);\n this.debug.log('Initializing with endpoint:', config.endpoint ?? DEFAULT_ENDPOINT);\n\n const storage = createStorage();\n this.session = new SessionManager(storage);\n\n const transport = new Transport({\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n apiKey: config.apiKey,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n onError: config.onError,\n });\n\n this.queue = new EventQueue(transport, {\n flushAt: config.flushAt ?? DEFAULT_FLUSH_AT,\n flushInterval: config.flushInterval ?? DEFAULT_FLUSH_INTERVAL,\n debug: this.debug,\n });\n\n const autoCapture = config.autoCapture ?? {};\n\n if (autoCapture.errors !== false) {\n this.errorHandler = new GlobalErrorHandler((error, source) => {\n this.captureError(error, {\n handled: false,\n metadata: { source },\n });\n });\n this.errorHandler.install();\n }\n\n if (autoCapture.pageViews && isBrowser()) {\n this.installPageViewTracking();\n }\n }\n\n // --- Public API ---\n\n /**\n * Track a named event.\n *\n * @example\n * analytics.track('button_clicked', { properties: { buttonId: 'signup' } });\n */\n track(name: string, options: TrackOptions = {}): void {\n this.enqueueEvent('TRACK', name, options.properties, options.timestamp, options.context);\n }\n\n /**\n * Identify a user with traits.\n * Sets the userId for all subsequent calls.\n *\n * @example\n * analytics.identify('user-123', { traits: { email: 'user@example.com' } });\n */\n identify(userId: string, options: IdentifyOptions = {}): void {\n this.session.setUserId(userId);\n this.enqueueEvent('IDENTIFY', 'identify', options.traits, options.timestamp, options.context);\n }\n\n /**\n * Track a page view (typically browser).\n *\n * @example\n * analytics.page('Home');\n * analytics.page('Product', { properties: { productId: '123' } });\n */\n page(name?: string, options: PageOptions = {}): void {\n const pageName = name ?? (isBrowser() ? document.title : 'Page View');\n this.enqueueEvent('PAGE', pageName, options.properties, options.timestamp, options.context);\n }\n\n /**\n * Track a screen view (typically mobile).\n */\n screen(name: string, options: ScreenOptions = {}): void {\n this.enqueueEvent('SCREEN', name, options.properties, options.timestamp, options.context);\n }\n\n /**\n * Associate a user with a group.\n */\n group(groupId: string, options: GroupOptions = {}): void {\n this.enqueueEvent('GROUP', groupId, options.traits, options.timestamp, options.context);\n }\n\n /**\n * Create an alias between two user identities.\n */\n alias(userId: string, previousId: string): void {\n this.enqueueEvent('ALIAS', 'alias', { userId, previousId });\n }\n\n /**\n * Capture an error for error monitoring.\n *\n * @example\n * try { riskyOp(); }\n * catch (err) { analytics.captureError(err, { tags: { env: 'prod' } }); }\n */\n captureError(\n error: Error | string,\n options: CaptureErrorOptions = {},\n ): void {\n const err = typeof error === 'string' ? new Error(error) : error;\n const autoContext = gatherContext();\n\n const payload: IngestErrorPayload = {\n type: err.name || 'Error',\n message: err.message,\n stackTrace: err.stack,\n level: options.level ?? 'ERROR',\n fingerprint: options.fingerprint,\n handled: options.handled ?? true,\n metadata: options.metadata,\n tags: options.tags,\n timestamp: (options.timestamp ?? new Date()).toISOString(),\n userId: this.session.getUserId() ?? undefined,\n sessionId: this.session.getSessionId(),\n context: {\n userAgent: autoContext.userAgent,\n browser: autoContext.browser?.name,\n os: autoContext.os?.name,\n device: autoContext.device?.type,\n url: autoContext.page?.url,\n release: options.release,\n },\n };\n\n this.queue.add({ kind: 'error', payload });\n }\n\n /**\n * Flush all queued events and errors immediately.\n */\n async flush(): Promise<void> {\n await this.queue.flush();\n }\n\n /**\n * Reset the current user. Clears userId, generates new anonymousId and sessionId.\n * Call this on logout.\n */\n reset(): void {\n this.session.reset();\n this.debug.log('User reset');\n }\n\n /**\n * Gracefully shut down: flush remaining events, remove global handlers.\n */\n async shutdown(): Promise<void> {\n this.debug.log('Shutting down');\n this.errorHandler?.uninstall();\n this.pageViewUnsubscribe?.();\n await this.queue.shutdown();\n }\n\n // --- Internal ---\n\n private enqueueEvent(\n type: IngestEventPayload['type'],\n name: string,\n properties?: Record<string, unknown>,\n timestamp?: Date,\n userContext?: Partial<EventContext>,\n ): void {\n const autoContext = gatherContext();\n const context = mergeContext(autoContext, userContext);\n\n const payload: IngestEventPayload = {\n type,\n name,\n properties: { ...this.config.defaultProperties, ...properties },\n timestamp: (timestamp ?? new Date()).toISOString(),\n userId: this.session.getUserId() ?? undefined,\n sessionId: this.session.getSessionId(),\n anonymousId: this.session.getAnonymousId(),\n context,\n };\n\n this.queue.add({ kind: 'event', payload });\n }\n\n private installPageViewTracking(): void {\n if (!isBrowser()) return;\n\n let lastUrl = window.location.href;\n\n const checkUrl = () => {\n const currentUrl = window.location.href;\n if (currentUrl !== lastUrl) {\n lastUrl = currentUrl;\n this.page();\n }\n };\n\n // Patch pushState/replaceState for SPA navigation\n const origPushState = history.pushState.bind(history);\n const origReplaceState = history.replaceState.bind(history);\n\n history.pushState = (...args: Parameters<typeof history.pushState>) => {\n origPushState(...args);\n checkUrl();\n };\n\n history.replaceState = (...args: Parameters<typeof history.replaceState>) => {\n origReplaceState(...args);\n checkUrl();\n };\n\n window.addEventListener('popstate', checkUrl);\n\n this.pageViewUnsubscribe = () => {\n history.pushState = origPushState;\n history.replaceState = origReplaceState;\n window.removeEventListener('popstate', checkUrl);\n };\n\n // Track initial page view\n this.page();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/transport.ts","../src/queue.ts","../src/utils.ts","../src/session.ts","../src/error-handler.ts","../src/context.ts","../src/storage.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { IngestEventPayload, IngestErrorPayload } from './types';\n\nexport interface TransportConfig {\n endpoint: string;\n apiKey: string;\n maxRetries: number;\n onError?: (error: Error) => void;\n}\n\nexport class Transport {\n private config: TransportConfig;\n\n constructor(config: TransportConfig) {\n this.config = config;\n }\n\n async sendEvents(events: IngestEventPayload[]): Promise<void> {\n await this.post('/ingest/events', { events });\n }\n\n async sendErrors(errors: IngestErrorPayload[]): Promise<void> {\n await this.post('/ingest/errors', { errors });\n }\n\n private async post(path: string, body: unknown): Promise<void> {\n const url = this.config.endpoint.replace(/\\/+$/, '') + path;\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.config.apiKey,\n },\n body: JSON.stringify(body),\n keepalive: true,\n });\n\n if (response.ok) return;\n\n if (response.status >= 400 && response.status < 500 && response.status !== 429) {\n const text = await response.text().catch(() => '');\n throw new Error(`HTTP ${response.status}: ${text}`);\n }\n\n lastError = new Error(`HTTP ${response.status}`);\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (err instanceof Error && err.message.startsWith('HTTP 4')) {\n break;\n }\n }\n\n if (attempt < this.config.maxRetries) {\n await this.backoff(attempt);\n }\n }\n\n if (lastError) {\n this.config.onError?.(lastError);\n }\n }\n\n private backoff(attempt: number): Promise<void> {\n const delay = Math.min(1000 * 2 ** attempt, 30000);\n const jitter = delay * (0.5 + Math.random() * 0.5);\n return new Promise((resolve) => setTimeout(resolve, jitter));\n }\n}\n","import type { QueueItem, IngestEventPayload, IngestErrorPayload } from './types';\nimport type { Transport } from './transport';\n\nexport interface QueueConfig {\n flushAt: number;\n flushInterval: number;\n debug: ReturnType<typeof import('./utils').createDebugLogger>;\n}\n\nexport class EventQueue {\n private items: QueueItem[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private transport: Transport;\n private config: QueueConfig;\n private flushing = false;\n\n constructor(transport: Transport, config: QueueConfig) {\n this.transport = transport;\n this.config = config;\n this.startTimer();\n }\n\n add(item: QueueItem): void {\n this.items.push(item);\n this.config.debug.log(`Queued ${item.kind}:`, item.kind === 'event' ? item.payload.name : item.payload.message);\n\n if (this.items.length >= this.config.flushAt) {\n void this.flush();\n }\n }\n\n async flush(): Promise<void> {\n if (this.flushing || this.items.length === 0) return;\n\n this.flushing = true;\n const batch = this.items.splice(0);\n\n try {\n const events: IngestEventPayload[] = [];\n const errors: IngestErrorPayload[] = [];\n\n for (const item of batch) {\n if (item.kind === 'event') events.push(item.payload);\n else errors.push(item.payload);\n }\n\n const promises: Promise<void>[] = [];\n if (events.length > 0) {\n this.config.debug.log(`Flushing ${events.length} events`);\n promises.push(this.transport.sendEvents(events));\n }\n if (errors.length > 0) {\n this.config.debug.log(`Flushing ${errors.length} errors`);\n promises.push(this.transport.sendErrors(errors));\n }\n\n await Promise.all(promises);\n } catch {\n this.items.unshift(...batch);\n } finally {\n this.flushing = false;\n }\n }\n\n private startTimer(): void {\n if (this.config.flushInterval > 0) {\n this.timer = setInterval(() => {\n void this.flush();\n }, this.config.flushInterval);\n\n // Allow Node.js to exit without waiting for the timer\n if (this.timer && typeof (this.timer as NodeJS.Timeout).unref === 'function') {\n (this.timer as NodeJS.Timeout).unref();\n }\n }\n }\n\n async shutdown(): Promise<void> {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush();\n }\n\n get size(): number {\n return this.items.length;\n }\n}\n","export function generateId(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\nexport function now(): string {\n return new Date().toISOString();\n}\n\nexport function createDebugLogger(enabled: boolean) {\n return {\n log: (...args: unknown[]) => {\n if (enabled) console.log('[BoringAnalytics]', ...args);\n },\n warn: (...args: unknown[]) => {\n if (enabled) console.warn('[BoringAnalytics]', ...args);\n },\n error: (...args: unknown[]) => {\n if (enabled) console.error('[BoringAnalytics]', ...args);\n },\n };\n}\n","import type { Storage } from './storage';\nimport { generateId } from './utils';\n\nconst ANON_ID_KEY = 'anonymous_id';\nconst SESSION_ID_KEY = 'session_id';\nconst SESSION_EXPIRY_KEY = 'session_expiry';\n\n/** Session timeout: 30 minutes of inactivity */\nconst SESSION_TIMEOUT_MS = 30 * 60 * 1000;\n\nexport class SessionManager {\n private userId: string | null = null;\n private anonymousId: string;\n private sessionId: string;\n private storage: Storage;\n\n constructor(storage: Storage) {\n this.storage = storage;\n this.anonymousId = this.storage.get(ANON_ID_KEY) ?? this.createAnonymousId();\n this.sessionId = this.resolveSession();\n }\n\n private createAnonymousId(): string {\n const id = generateId();\n this.storage.set(ANON_ID_KEY, id);\n return id;\n }\n\n private resolveSession(): string {\n const existingSession = this.storage.get(SESSION_ID_KEY);\n const expiryStr = this.storage.get(SESSION_EXPIRY_KEY);\n const expiry = expiryStr ? parseInt(expiryStr, 10) : 0;\n\n if (existingSession && Date.now() < expiry) {\n this.touchSession();\n return existingSession;\n }\n\n return this.startNewSession();\n }\n\n private startNewSession(): string {\n const id = generateId();\n this.sessionId = id;\n this.storage.set(SESSION_ID_KEY, id);\n this.touchSession();\n return id;\n }\n\n private touchSession(): void {\n this.storage.set(\n SESSION_EXPIRY_KEY,\n String(Date.now() + SESSION_TIMEOUT_MS),\n );\n }\n\n setUserId(id: string): void {\n this.userId = id;\n }\n\n getUserId(): string | null {\n return this.userId;\n }\n\n getAnonymousId(): string {\n return this.anonymousId;\n }\n\n getSessionId(): string {\n this.sessionId = this.resolveSession();\n return this.sessionId;\n }\n\n reset(): void {\n this.userId = null;\n this.anonymousId = this.createAnonymousId();\n this.sessionId = this.startNewSession();\n }\n}\n","import { isBrowser } from './utils';\n\ntype ErrorCallback = (error: Error, source?: string) => void;\n\nexport class GlobalErrorHandler {\n private callback: ErrorCallback;\n private installed = false;\n private originalOnError: OnErrorEventHandler | null = null;\n private originalOnUnhandledRejection: ((ev: PromiseRejectionEvent) => void) | null = null;\n\n constructor(callback: ErrorCallback) {\n this.callback = callback;\n }\n\n install(): void {\n if (this.installed) return;\n this.installed = true;\n\n if (isBrowser()) {\n this.installBrowser();\n } else {\n this.installNode();\n }\n }\n\n uninstall(): void {\n if (!this.installed) return;\n this.installed = false;\n\n if (isBrowser()) {\n this.uninstallBrowser();\n } else {\n this.uninstallNode();\n }\n }\n\n private installBrowser(): void {\n this.originalOnError = window.onerror;\n window.onerror = (message, source, lineno, colno, error) => {\n if (error) {\n this.callback(error, source ?? undefined);\n } else if (typeof message === 'string') {\n this.callback(new Error(message), source ?? undefined);\n }\n this.originalOnError?.call(window, message, source, lineno, colno, error);\n };\n\n this.originalOnUnhandledRejection = window.onunhandledrejection as typeof this.originalOnUnhandledRejection;\n window.onunhandledrejection = (event: PromiseRejectionEvent) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n this.callback(error, 'unhandledrejection');\n (this.originalOnUnhandledRejection as ((ev: PromiseRejectionEvent) => void) | null)?.call(window, event);\n };\n }\n\n private uninstallBrowser(): void {\n window.onerror = this.originalOnError;\n window.onunhandledrejection = this.originalOnUnhandledRejection as typeof window.onunhandledrejection;\n }\n\n private installNode(): void {\n if (typeof process === 'undefined') return;\n\n process.on('uncaughtException', this.handleNodeError);\n process.on('unhandledRejection', this.handleNodeRejection);\n }\n\n private uninstallNode(): void {\n if (typeof process === 'undefined') return;\n\n process.removeListener('uncaughtException', this.handleNodeError);\n process.removeListener('unhandledRejection', this.handleNodeRejection);\n }\n\n private handleNodeError = (error: Error): void => {\n this.callback(error, 'uncaughtException');\n };\n\n private handleNodeRejection = (reason: unknown): void => {\n const error = reason instanceof Error ? reason : new Error(String(reason));\n this.callback(error, 'unhandledRejection');\n };\n}\n","import type { EventContext } from './types';\nimport { isBrowser } from './utils';\n\n/**\n * Parses a user agent string into browser, OS, and device info.\n * Lightweight — covers major browsers/platforms without a full UA parser dependency.\n */\nfunction parseUserAgent(ua: string): {\n browser: { name: string; version?: string };\n os: { name: string; version?: string };\n device: { type: string };\n} {\n const browser = { name: 'Unknown', version: undefined as string | undefined };\n const os = { name: 'Unknown', version: undefined as string | undefined };\n const device = { type: 'desktop' };\n\n // Mobile detection\n if (/Mobi|Android|iPhone|iPad|iPod/i.test(ua)) {\n device.type = /iPad|Tablet/i.test(ua) ? 'tablet' : 'mobile';\n }\n\n // Browser detection\n if (/Edg\\//i.test(ua)) {\n browser.name = 'Edge';\n browser.version = ua.match(/Edg\\/([\\d.]+)/)?.[1];\n } else if (/OPR\\//i.test(ua) || /Opera/i.test(ua)) {\n browser.name = 'Opera';\n browser.version = ua.match(/(?:OPR|Opera)\\/([\\d.]+)/)?.[1];\n } else if (/Chrome\\//i.test(ua) && !/Chromium/i.test(ua)) {\n browser.name = 'Chrome';\n browser.version = ua.match(/Chrome\\/([\\d.]+)/)?.[1];\n } else if (/Safari\\//i.test(ua) && !/Chrome/i.test(ua)) {\n browser.name = 'Safari';\n browser.version = ua.match(/Version\\/([\\d.]+)/)?.[1];\n } else if (/Firefox\\//i.test(ua)) {\n browser.name = 'Firefox';\n browser.version = ua.match(/Firefox\\/([\\d.]+)/)?.[1];\n }\n\n // OS detection\n if (/Windows NT/i.test(ua)) {\n os.name = 'Windows';\n const ntVersion = ua.match(/Windows NT ([\\d.]+)/)?.[1];\n const versionMap: Record<string, string> = {\n '10.0': '10+',\n '6.3': '8.1',\n '6.2': '8',\n '6.1': '7',\n };\n os.version = ntVersion ? (versionMap[ntVersion] ?? ntVersion) : undefined;\n } else if (/Mac OS X/i.test(ua)) {\n os.name = 'macOS';\n os.version = ua.match(/Mac OS X ([\\d_.]+)/)?.[1]?.replace(/_/g, '.');\n } else if (/Android/i.test(ua)) {\n os.name = 'Android';\n os.version = ua.match(/Android ([\\d.]+)/)?.[1];\n } else if (/iPhone OS|iPad/i.test(ua)) {\n os.name = 'iOS';\n os.version = ua.match(/OS ([\\d_]+)/)?.[1]?.replace(/_/g, '.');\n } else if (/Linux/i.test(ua)) {\n os.name = 'Linux';\n }\n\n return { browser, os, device };\n}\n\nexport function gatherContext(): EventContext {\n if (!isBrowser()) {\n return {};\n }\n\n const ua = navigator.userAgent;\n const { browser, os, device } = parseUserAgent(ua);\n\n return {\n userAgent: ua,\n locale: navigator.language,\n page: {\n url: window.location.href,\n referrer: document.referrer || undefined,\n title: document.title || undefined,\n path: window.location.pathname,\n },\n browser,\n os,\n device,\n };\n}\n\nexport function mergeContext(\n auto: EventContext,\n user?: Partial<EventContext>,\n): EventContext {\n if (!user) return auto;\n\n return {\n ...auto,\n ...user,\n page: { ...auto.page, ...user.page },\n browser: { ...auto.browser, ...user.browser },\n os: { ...auto.os, ...user.os },\n device: { ...auto.device, ...user.device },\n };\n}\n","const PREFIX = 'ba_';\n\nexport interface Storage {\n get(key: string): string | null;\n set(key: string, value: string): void;\n remove(key: string): void;\n}\n\nclass LocalStorage implements Storage {\n get(key: string): string | null {\n try {\n return localStorage.getItem(PREFIX + key);\n } catch {\n return null;\n }\n }\n\n set(key: string, value: string): void {\n try {\n localStorage.setItem(PREFIX + key, value);\n } catch {\n // localStorage unavailable or quota exceeded\n }\n }\n\n remove(key: string): void {\n try {\n localStorage.removeItem(PREFIX + key);\n } catch {\n // noop\n }\n }\n}\n\nclass MemoryStorage implements Storage {\n private store = new Map<string, string>();\n\n get(key: string): string | null {\n return this.store.get(PREFIX + key) ?? null;\n }\n\n set(key: string, value: string): void {\n this.store.set(PREFIX + key, value);\n }\n\n remove(key: string): void {\n this.store.delete(PREFIX + key);\n }\n}\n\nexport function createStorage(): Storage {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem('__ba_test__', '1');\n localStorage.removeItem('__ba_test__');\n return new LocalStorage();\n }\n } catch {\n // localStorage not available\n }\n return new MemoryStorage();\n}\n","import type {\n BoringAnalyticsConfig,\n TrackOptions,\n IdentifyOptions,\n PageOptions,\n ScreenOptions,\n GroupOptions,\n CaptureErrorOptions,\n IngestEventPayload,\n IngestErrorPayload,\n EventContext,\n} from './types';\nimport { Transport } from './transport';\nimport { EventQueue } from './queue';\nimport { SessionManager } from './session';\nimport { GlobalErrorHandler } from './error-handler';\nimport { gatherContext, mergeContext } from './context';\nimport { createStorage } from './storage';\nimport { createDebugLogger, isBrowser, now } from './utils';\n\nconst DEFAULT_ENDPOINT = 'https://api.boring.yraylabs.fun';\nconst DEFAULT_FLUSH_AT = 20;\nconst DEFAULT_FLUSH_INTERVAL = 5000;\nconst DEFAULT_MAX_RETRIES = 3;\n\nexport class BoringAnalytics {\n private queue: EventQueue;\n private session: SessionManager;\n private errorHandler: GlobalErrorHandler | null = null;\n private debug: ReturnType<typeof createDebugLogger>;\n private config: Required<\n Pick<BoringAnalyticsConfig, 'defaultProperties'>\n > & BoringAnalyticsConfig;\n private pageViewUnsubscribe: (() => void) | null = null;\n\n constructor(config: BoringAnalyticsConfig) {\n if (!config.apiKey) {\n throw new Error('BoringAnalytics: apiKey is required');\n }\n\n this.config = {\n ...config,\n defaultProperties: config.defaultProperties ?? {},\n };\n\n this.debug = createDebugLogger(config.debug ?? false);\n this.debug.log('Initializing with endpoint:', config.endpoint ?? DEFAULT_ENDPOINT);\n\n const storage = createStorage();\n this.session = new SessionManager(storage);\n\n const transport = new Transport({\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n apiKey: config.apiKey,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n onError: config.onError,\n });\n\n this.queue = new EventQueue(transport, {\n flushAt: config.flushAt ?? DEFAULT_FLUSH_AT,\n flushInterval: config.flushInterval ?? DEFAULT_FLUSH_INTERVAL,\n debug: this.debug,\n });\n\n const autoCapture = config.autoCapture ?? {};\n\n if (autoCapture.errors !== false) {\n this.errorHandler = new GlobalErrorHandler((error, source) => {\n this.captureError(error, {\n handled: false,\n metadata: { source },\n });\n });\n this.errorHandler.install();\n }\n\n if (autoCapture.pageViews && isBrowser()) {\n this.installPageViewTracking();\n }\n }\n\n // --- Public API ---\n\n /**\n * Track a named event.\n *\n * @example\n * analytics.track('button_clicked', { properties: { buttonId: 'signup' } });\n */\n track(name: string, options: TrackOptions = {}): void {\n this.enqueueEvent('TRACK', name, options.properties, options.timestamp, options.context);\n }\n\n /**\n * Identify a user with traits.\n * Sets the userId for all subsequent calls.\n *\n * @example\n * analytics.identify('user-123', { traits: { email: 'user@example.com' } });\n */\n identify(userId: string, options: IdentifyOptions = {}): void {\n this.session.setUserId(userId);\n this.enqueueEvent('IDENTIFY', 'identify', options.traits, options.timestamp, options.context);\n }\n\n /**\n * Track a page view (typically browser).\n *\n * @example\n * analytics.page('Home');\n * analytics.page('Product', { properties: { productId: '123' } });\n */\n page(name?: string, options: PageOptions = {}): void {\n const pageName = name ?? (isBrowser() ? document.title : 'Page View');\n this.enqueueEvent('PAGE', pageName, options.properties, options.timestamp, options.context);\n }\n\n /**\n * Track a screen view (typically mobile).\n */\n screen(name: string, options: ScreenOptions = {}): void {\n this.enqueueEvent('SCREEN', name, options.properties, options.timestamp, options.context);\n }\n\n /**\n * Associate a user with a group.\n */\n group(groupId: string, options: GroupOptions = {}): void {\n this.enqueueEvent('GROUP', groupId, options.traits, options.timestamp, options.context);\n }\n\n /**\n * Create an alias between two user identities.\n */\n alias(userId: string, previousId: string): void {\n this.enqueueEvent('ALIAS', 'alias', { userId, previousId });\n }\n\n /**\n * Capture an error for error monitoring.\n *\n * @example\n * try { riskyOp(); }\n * catch (err) { analytics.captureError(err, { tags: { env: 'prod' } }); }\n */\n captureError(\n error: Error | string,\n options: CaptureErrorOptions = {},\n ): void {\n const err = typeof error === 'string' ? new Error(error) : error;\n const autoContext = gatherContext();\n\n const payload: IngestErrorPayload = {\n type: err.name || 'Error',\n message: err.message,\n stackTrace: err.stack,\n level: options.level ?? 'ERROR',\n fingerprint: options.fingerprint,\n handled: options.handled ?? true,\n metadata: options.metadata,\n tags: options.tags,\n timestamp: (options.timestamp ?? new Date()).toISOString(),\n userId: this.session.getUserId() ?? undefined,\n sessionId: this.session.getSessionId(),\n context: {\n userAgent: autoContext.userAgent,\n browser: autoContext.browser?.name,\n os: autoContext.os?.name,\n device: autoContext.device?.type,\n url: autoContext.page?.url,\n release: options.release,\n },\n };\n\n this.queue.add({ kind: 'error', payload });\n }\n\n /**\n * Flush all queued events and errors immediately.\n */\n async flush(): Promise<void> {\n await this.queue.flush();\n }\n\n /**\n * Reset the current user. Clears userId, generates new anonymousId and sessionId.\n * Call this on logout.\n */\n reset(): void {\n this.session.reset();\n this.debug.log('User reset');\n }\n\n /**\n * Gracefully shut down: flush remaining events, remove global handlers.\n */\n async shutdown(): Promise<void> {\n this.debug.log('Shutting down');\n this.errorHandler?.uninstall();\n this.pageViewUnsubscribe?.();\n await this.queue.shutdown();\n }\n\n // --- Internal ---\n\n private enqueueEvent(\n type: IngestEventPayload['type'],\n name: string,\n properties?: Record<string, unknown>,\n timestamp?: Date,\n userContext?: Partial<EventContext>,\n ): void {\n const autoContext = gatherContext();\n const context = mergeContext(autoContext, userContext);\n\n const payload: IngestEventPayload = {\n type,\n name,\n properties: { ...this.config.defaultProperties, ...properties },\n timestamp: (timestamp ?? new Date()).toISOString(),\n userId: this.session.getUserId() ?? undefined,\n sessionId: this.session.getSessionId(),\n anonymousId: this.session.getAnonymousId(),\n context,\n };\n\n this.queue.add({ kind: 'event', payload });\n }\n\n private installPageViewTracking(): void {\n if (!isBrowser()) return;\n\n let lastUrl = window.location.href;\n\n const checkUrl = () => {\n const currentUrl = window.location.href;\n if (currentUrl !== lastUrl) {\n lastUrl = currentUrl;\n this.page();\n }\n };\n\n // Patch pushState/replaceState for SPA navigation\n const origPushState = history.pushState.bind(history);\n const origReplaceState = history.replaceState.bind(history);\n\n history.pushState = (...args: Parameters<typeof history.pushState>) => {\n origPushState(...args);\n checkUrl();\n };\n\n history.replaceState = (...args: Parameters<typeof history.replaceState>) => {\n origReplaceState(...args);\n checkUrl();\n };\n\n window.addEventListener('popstate', checkUrl);\n\n this.pageViewUnsubscribe = () => {\n history.pushState = origPushState;\n history.replaceState = origReplaceState;\n window.removeEventListener('popstate', checkUrl);\n };\n\n // Track initial page view\n this.page();\n }\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -400,7 +400,7 @@ function createStorage() {
|
|
|
400
400
|
}
|
|
401
401
|
|
|
402
402
|
// src/client.ts
|
|
403
|
-
var DEFAULT_ENDPOINT = "https://api.
|
|
403
|
+
var DEFAULT_ENDPOINT = "https://api.boring.yraylabs.fun";
|
|
404
404
|
var DEFAULT_FLUSH_AT = 20;
|
|
405
405
|
var DEFAULT_FLUSH_INTERVAL = 5e3;
|
|
406
406
|
var DEFAULT_MAX_RETRIES = 3;
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/transport.ts","../src/queue.ts","../src/utils.ts","../src/session.ts","../src/error-handler.ts","../src/context.ts","../src/storage.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { IngestEventPayload, IngestErrorPayload } from './types';\n\nexport interface TransportConfig {\n endpoint: string;\n apiKey: string;\n maxRetries: number;\n onError?: (error: Error) => void;\n}\n\nexport class Transport {\n private config: TransportConfig;\n\n constructor(config: TransportConfig) {\n this.config = config;\n }\n\n async sendEvents(events: IngestEventPayload[]): Promise<void> {\n await this.post('/ingest/events', { events });\n }\n\n async sendErrors(errors: IngestErrorPayload[]): Promise<void> {\n await this.post('/ingest/errors', { errors });\n }\n\n private async post(path: string, body: unknown): Promise<void> {\n const url = this.config.endpoint.replace(/\\/+$/, '') + path;\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.config.apiKey,\n },\n body: JSON.stringify(body),\n keepalive: true,\n });\n\n if (response.ok) return;\n\n if (response.status >= 400 && response.status < 500 && response.status !== 429) {\n const text = await response.text().catch(() => '');\n throw new Error(`HTTP ${response.status}: ${text}`);\n }\n\n lastError = new Error(`HTTP ${response.status}`);\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (err instanceof Error && err.message.startsWith('HTTP 4')) {\n break;\n }\n }\n\n if (attempt < this.config.maxRetries) {\n await this.backoff(attempt);\n }\n }\n\n if (lastError) {\n this.config.onError?.(lastError);\n }\n }\n\n private backoff(attempt: number): Promise<void> {\n const delay = Math.min(1000 * 2 ** attempt, 30000);\n const jitter = delay * (0.5 + Math.random() * 0.5);\n return new Promise((resolve) => setTimeout(resolve, jitter));\n }\n}\n","import type { QueueItem, IngestEventPayload, IngestErrorPayload } from './types';\nimport type { Transport } from './transport';\n\nexport interface QueueConfig {\n flushAt: number;\n flushInterval: number;\n debug: ReturnType<typeof import('./utils').createDebugLogger>;\n}\n\nexport class EventQueue {\n private items: QueueItem[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private transport: Transport;\n private config: QueueConfig;\n private flushing = false;\n\n constructor(transport: Transport, config: QueueConfig) {\n this.transport = transport;\n this.config = config;\n this.startTimer();\n }\n\n add(item: QueueItem): void {\n this.items.push(item);\n this.config.debug.log(`Queued ${item.kind}:`, item.kind === 'event' ? item.payload.name : item.payload.message);\n\n if (this.items.length >= this.config.flushAt) {\n void this.flush();\n }\n }\n\n async flush(): Promise<void> {\n if (this.flushing || this.items.length === 0) return;\n\n this.flushing = true;\n const batch = this.items.splice(0);\n\n try {\n const events: IngestEventPayload[] = [];\n const errors: IngestErrorPayload[] = [];\n\n for (const item of batch) {\n if (item.kind === 'event') events.push(item.payload);\n else errors.push(item.payload);\n }\n\n const promises: Promise<void>[] = [];\n if (events.length > 0) {\n this.config.debug.log(`Flushing ${events.length} events`);\n promises.push(this.transport.sendEvents(events));\n }\n if (errors.length > 0) {\n this.config.debug.log(`Flushing ${errors.length} errors`);\n promises.push(this.transport.sendErrors(errors));\n }\n\n await Promise.all(promises);\n } catch {\n this.items.unshift(...batch);\n } finally {\n this.flushing = false;\n }\n }\n\n private startTimer(): void {\n if (this.config.flushInterval > 0) {\n this.timer = setInterval(() => {\n void this.flush();\n }, this.config.flushInterval);\n\n // Allow Node.js to exit without waiting for the timer\n if (this.timer && typeof (this.timer as NodeJS.Timeout).unref === 'function') {\n (this.timer as NodeJS.Timeout).unref();\n }\n }\n }\n\n async shutdown(): Promise<void> {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush();\n }\n\n get size(): number {\n return this.items.length;\n }\n}\n","export function generateId(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\nexport function now(): string {\n return new Date().toISOString();\n}\n\nexport function createDebugLogger(enabled: boolean) {\n return {\n log: (...args: unknown[]) => {\n if (enabled) console.log('[BoringAnalytics]', ...args);\n },\n warn: (...args: unknown[]) => {\n if (enabled) console.warn('[BoringAnalytics]', ...args);\n },\n error: (...args: unknown[]) => {\n if (enabled) console.error('[BoringAnalytics]', ...args);\n },\n };\n}\n","import type { Storage } from './storage';\nimport { generateId } from './utils';\n\nconst ANON_ID_KEY = 'anonymous_id';\nconst SESSION_ID_KEY = 'session_id';\nconst SESSION_EXPIRY_KEY = 'session_expiry';\n\n/** Session timeout: 30 minutes of inactivity */\nconst SESSION_TIMEOUT_MS = 30 * 60 * 1000;\n\nexport class SessionManager {\n private userId: string | null = null;\n private anonymousId: string;\n private sessionId: string;\n private storage: Storage;\n\n constructor(storage: Storage) {\n this.storage = storage;\n this.anonymousId = this.storage.get(ANON_ID_KEY) ?? this.createAnonymousId();\n this.sessionId = this.resolveSession();\n }\n\n private createAnonymousId(): string {\n const id = generateId();\n this.storage.set(ANON_ID_KEY, id);\n return id;\n }\n\n private resolveSession(): string {\n const existingSession = this.storage.get(SESSION_ID_KEY);\n const expiryStr = this.storage.get(SESSION_EXPIRY_KEY);\n const expiry = expiryStr ? parseInt(expiryStr, 10) : 0;\n\n if (existingSession && Date.now() < expiry) {\n this.touchSession();\n return existingSession;\n }\n\n return this.startNewSession();\n }\n\n private startNewSession(): string {\n const id = generateId();\n this.sessionId = id;\n this.storage.set(SESSION_ID_KEY, id);\n this.touchSession();\n return id;\n }\n\n private touchSession(): void {\n this.storage.set(\n SESSION_EXPIRY_KEY,\n String(Date.now() + SESSION_TIMEOUT_MS),\n );\n }\n\n setUserId(id: string): void {\n this.userId = id;\n }\n\n getUserId(): string | null {\n return this.userId;\n }\n\n getAnonymousId(): string {\n return this.anonymousId;\n }\n\n getSessionId(): string {\n this.sessionId = this.resolveSession();\n return this.sessionId;\n }\n\n reset(): void {\n this.userId = null;\n this.anonymousId = this.createAnonymousId();\n this.sessionId = this.startNewSession();\n }\n}\n","import { isBrowser } from './utils';\n\ntype ErrorCallback = (error: Error, source?: string) => void;\n\nexport class GlobalErrorHandler {\n private callback: ErrorCallback;\n private installed = false;\n private originalOnError: OnErrorEventHandler | null = null;\n private originalOnUnhandledRejection: ((ev: PromiseRejectionEvent) => void) | null = null;\n\n constructor(callback: ErrorCallback) {\n this.callback = callback;\n }\n\n install(): void {\n if (this.installed) return;\n this.installed = true;\n\n if (isBrowser()) {\n this.installBrowser();\n } else {\n this.installNode();\n }\n }\n\n uninstall(): void {\n if (!this.installed) return;\n this.installed = false;\n\n if (isBrowser()) {\n this.uninstallBrowser();\n } else {\n this.uninstallNode();\n }\n }\n\n private installBrowser(): void {\n this.originalOnError = window.onerror;\n window.onerror = (message, source, lineno, colno, error) => {\n if (error) {\n this.callback(error, source ?? undefined);\n } else if (typeof message === 'string') {\n this.callback(new Error(message), source ?? undefined);\n }\n this.originalOnError?.call(window, message, source, lineno, colno, error);\n };\n\n this.originalOnUnhandledRejection = window.onunhandledrejection as typeof this.originalOnUnhandledRejection;\n window.onunhandledrejection = (event: PromiseRejectionEvent) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n this.callback(error, 'unhandledrejection');\n (this.originalOnUnhandledRejection as ((ev: PromiseRejectionEvent) => void) | null)?.call(window, event);\n };\n }\n\n private uninstallBrowser(): void {\n window.onerror = this.originalOnError;\n window.onunhandledrejection = this.originalOnUnhandledRejection as typeof window.onunhandledrejection;\n }\n\n private installNode(): void {\n if (typeof process === 'undefined') return;\n\n process.on('uncaughtException', this.handleNodeError);\n process.on('unhandledRejection', this.handleNodeRejection);\n }\n\n private uninstallNode(): void {\n if (typeof process === 'undefined') return;\n\n process.removeListener('uncaughtException', this.handleNodeError);\n process.removeListener('unhandledRejection', this.handleNodeRejection);\n }\n\n private handleNodeError = (error: Error): void => {\n this.callback(error, 'uncaughtException');\n };\n\n private handleNodeRejection = (reason: unknown): void => {\n const error = reason instanceof Error ? reason : new Error(String(reason));\n this.callback(error, 'unhandledRejection');\n };\n}\n","import type { EventContext } from './types';\nimport { isBrowser } from './utils';\n\n/**\n * Parses a user agent string into browser, OS, and device info.\n * Lightweight — covers major browsers/platforms without a full UA parser dependency.\n */\nfunction parseUserAgent(ua: string): {\n browser: { name: string; version?: string };\n os: { name: string; version?: string };\n device: { type: string };\n} {\n const browser = { name: 'Unknown', version: undefined as string | undefined };\n const os = { name: 'Unknown', version: undefined as string | undefined };\n const device = { type: 'desktop' };\n\n // Mobile detection\n if (/Mobi|Android|iPhone|iPad|iPod/i.test(ua)) {\n device.type = /iPad|Tablet/i.test(ua) ? 'tablet' : 'mobile';\n }\n\n // Browser detection\n if (/Edg\\//i.test(ua)) {\n browser.name = 'Edge';\n browser.version = ua.match(/Edg\\/([\\d.]+)/)?.[1];\n } else if (/OPR\\//i.test(ua) || /Opera/i.test(ua)) {\n browser.name = 'Opera';\n browser.version = ua.match(/(?:OPR|Opera)\\/([\\d.]+)/)?.[1];\n } else if (/Chrome\\//i.test(ua) && !/Chromium/i.test(ua)) {\n browser.name = 'Chrome';\n browser.version = ua.match(/Chrome\\/([\\d.]+)/)?.[1];\n } else if (/Safari\\//i.test(ua) && !/Chrome/i.test(ua)) {\n browser.name = 'Safari';\n browser.version = ua.match(/Version\\/([\\d.]+)/)?.[1];\n } else if (/Firefox\\//i.test(ua)) {\n browser.name = 'Firefox';\n browser.version = ua.match(/Firefox\\/([\\d.]+)/)?.[1];\n }\n\n // OS detection\n if (/Windows NT/i.test(ua)) {\n os.name = 'Windows';\n const ntVersion = ua.match(/Windows NT ([\\d.]+)/)?.[1];\n const versionMap: Record<string, string> = {\n '10.0': '10+',\n '6.3': '8.1',\n '6.2': '8',\n '6.1': '7',\n };\n os.version = ntVersion ? (versionMap[ntVersion] ?? ntVersion) : undefined;\n } else if (/Mac OS X/i.test(ua)) {\n os.name = 'macOS';\n os.version = ua.match(/Mac OS X ([\\d_.]+)/)?.[1]?.replace(/_/g, '.');\n } else if (/Android/i.test(ua)) {\n os.name = 'Android';\n os.version = ua.match(/Android ([\\d.]+)/)?.[1];\n } else if (/iPhone OS|iPad/i.test(ua)) {\n os.name = 'iOS';\n os.version = ua.match(/OS ([\\d_]+)/)?.[1]?.replace(/_/g, '.');\n } else if (/Linux/i.test(ua)) {\n os.name = 'Linux';\n }\n\n return { browser, os, device };\n}\n\nexport function gatherContext(): EventContext {\n if (!isBrowser()) {\n return {};\n }\n\n const ua = navigator.userAgent;\n const { browser, os, device } = parseUserAgent(ua);\n\n return {\n userAgent: ua,\n locale: navigator.language,\n page: {\n url: window.location.href,\n referrer: document.referrer || undefined,\n title: document.title || undefined,\n path: window.location.pathname,\n },\n browser,\n os,\n device,\n };\n}\n\nexport function mergeContext(\n auto: EventContext,\n user?: Partial<EventContext>,\n): EventContext {\n if (!user) return auto;\n\n return {\n ...auto,\n ...user,\n page: { ...auto.page, ...user.page },\n browser: { ...auto.browser, ...user.browser },\n os: { ...auto.os, ...user.os },\n device: { ...auto.device, ...user.device },\n };\n}\n","const PREFIX = 'ba_';\n\nexport interface Storage {\n get(key: string): string | null;\n set(key: string, value: string): void;\n remove(key: string): void;\n}\n\nclass LocalStorage implements Storage {\n get(key: string): string | null {\n try {\n return localStorage.getItem(PREFIX + key);\n } catch {\n return null;\n }\n }\n\n set(key: string, value: string): void {\n try {\n localStorage.setItem(PREFIX + key, value);\n } catch {\n // localStorage unavailable or quota exceeded\n }\n }\n\n remove(key: string): void {\n try {\n localStorage.removeItem(PREFIX + key);\n } catch {\n // noop\n }\n }\n}\n\nclass MemoryStorage implements Storage {\n private store = new Map<string, string>();\n\n get(key: string): string | null {\n return this.store.get(PREFIX + key) ?? null;\n }\n\n set(key: string, value: string): void {\n this.store.set(PREFIX + key, value);\n }\n\n remove(key: string): void {\n this.store.delete(PREFIX + key);\n }\n}\n\nexport function createStorage(): Storage {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem('__ba_test__', '1');\n localStorage.removeItem('__ba_test__');\n return new LocalStorage();\n }\n } catch {\n // localStorage not available\n }\n return new MemoryStorage();\n}\n","import type {\n BoringAnalyticsConfig,\n TrackOptions,\n IdentifyOptions,\n PageOptions,\n ScreenOptions,\n GroupOptions,\n CaptureErrorOptions,\n IngestEventPayload,\n IngestErrorPayload,\n EventContext,\n} from './types';\nimport { Transport } from './transport';\nimport { EventQueue } from './queue';\nimport { SessionManager } from './session';\nimport { GlobalErrorHandler } from './error-handler';\nimport { gatherContext, mergeContext } from './context';\nimport { createStorage } from './storage';\nimport { createDebugLogger, isBrowser, now } from './utils';\n\nconst DEFAULT_ENDPOINT = 'https://api.boringanalytics.io';\nconst DEFAULT_FLUSH_AT = 20;\nconst DEFAULT_FLUSH_INTERVAL = 5000;\nconst DEFAULT_MAX_RETRIES = 3;\n\nexport class BoringAnalytics {\n private queue: EventQueue;\n private session: SessionManager;\n private errorHandler: GlobalErrorHandler | null = null;\n private debug: ReturnType<typeof createDebugLogger>;\n private config: Required<\n Pick<BoringAnalyticsConfig, 'defaultProperties'>\n > & BoringAnalyticsConfig;\n private pageViewUnsubscribe: (() => void) | null = null;\n\n constructor(config: BoringAnalyticsConfig) {\n if (!config.apiKey) {\n throw new Error('BoringAnalytics: apiKey is required');\n }\n\n this.config = {\n ...config,\n defaultProperties: config.defaultProperties ?? {},\n };\n\n this.debug = createDebugLogger(config.debug ?? false);\n this.debug.log('Initializing with endpoint:', config.endpoint ?? DEFAULT_ENDPOINT);\n\n const storage = createStorage();\n this.session = new SessionManager(storage);\n\n const transport = new Transport({\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n apiKey: config.apiKey,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n onError: config.onError,\n });\n\n this.queue = new EventQueue(transport, {\n flushAt: config.flushAt ?? DEFAULT_FLUSH_AT,\n flushInterval: config.flushInterval ?? DEFAULT_FLUSH_INTERVAL,\n debug: this.debug,\n });\n\n const autoCapture = config.autoCapture ?? {};\n\n if (autoCapture.errors !== false) {\n this.errorHandler = new GlobalErrorHandler((error, source) => {\n this.captureError(error, {\n handled: false,\n metadata: { source },\n });\n });\n this.errorHandler.install();\n }\n\n if (autoCapture.pageViews && isBrowser()) {\n this.installPageViewTracking();\n }\n }\n\n // --- Public API ---\n\n /**\n * Track a named event.\n *\n * @example\n * analytics.track('button_clicked', { properties: { buttonId: 'signup' } });\n */\n track(name: string, options: TrackOptions = {}): void {\n this.enqueueEvent('TRACK', name, options.properties, options.timestamp, options.context);\n }\n\n /**\n * Identify a user with traits.\n * Sets the userId for all subsequent calls.\n *\n * @example\n * analytics.identify('user-123', { traits: { email: 'user@example.com' } });\n */\n identify(userId: string, options: IdentifyOptions = {}): void {\n this.session.setUserId(userId);\n this.enqueueEvent('IDENTIFY', 'identify', options.traits, options.timestamp, options.context);\n }\n\n /**\n * Track a page view (typically browser).\n *\n * @example\n * analytics.page('Home');\n * analytics.page('Product', { properties: { productId: '123' } });\n */\n page(name?: string, options: PageOptions = {}): void {\n const pageName = name ?? (isBrowser() ? document.title : 'Page View');\n this.enqueueEvent('PAGE', pageName, options.properties, options.timestamp, options.context);\n }\n\n /**\n * Track a screen view (typically mobile).\n */\n screen(name: string, options: ScreenOptions = {}): void {\n this.enqueueEvent('SCREEN', name, options.properties, options.timestamp, options.context);\n }\n\n /**\n * Associate a user with a group.\n */\n group(groupId: string, options: GroupOptions = {}): void {\n this.enqueueEvent('GROUP', groupId, options.traits, options.timestamp, options.context);\n }\n\n /**\n * Create an alias between two user identities.\n */\n alias(userId: string, previousId: string): void {\n this.enqueueEvent('ALIAS', 'alias', { userId, previousId });\n }\n\n /**\n * Capture an error for error monitoring.\n *\n * @example\n * try { riskyOp(); }\n * catch (err) { analytics.captureError(err, { tags: { env: 'prod' } }); }\n */\n captureError(\n error: Error | string,\n options: CaptureErrorOptions = {},\n ): void {\n const err = typeof error === 'string' ? new Error(error) : error;\n const autoContext = gatherContext();\n\n const payload: IngestErrorPayload = {\n type: err.name || 'Error',\n message: err.message,\n stackTrace: err.stack,\n level: options.level ?? 'ERROR',\n fingerprint: options.fingerprint,\n handled: options.handled ?? true,\n metadata: options.metadata,\n tags: options.tags,\n timestamp: (options.timestamp ?? new Date()).toISOString(),\n userId: this.session.getUserId() ?? undefined,\n sessionId: this.session.getSessionId(),\n context: {\n userAgent: autoContext.userAgent,\n browser: autoContext.browser?.name,\n os: autoContext.os?.name,\n device: autoContext.device?.type,\n url: autoContext.page?.url,\n release: options.release,\n },\n };\n\n this.queue.add({ kind: 'error', payload });\n }\n\n /**\n * Flush all queued events and errors immediately.\n */\n async flush(): Promise<void> {\n await this.queue.flush();\n }\n\n /**\n * Reset the current user. Clears userId, generates new anonymousId and sessionId.\n * Call this on logout.\n */\n reset(): void {\n this.session.reset();\n this.debug.log('User reset');\n }\n\n /**\n * Gracefully shut down: flush remaining events, remove global handlers.\n */\n async shutdown(): Promise<void> {\n this.debug.log('Shutting down');\n this.errorHandler?.uninstall();\n this.pageViewUnsubscribe?.();\n await this.queue.shutdown();\n }\n\n // --- Internal ---\n\n private enqueueEvent(\n type: IngestEventPayload['type'],\n name: string,\n properties?: Record<string, unknown>,\n timestamp?: Date,\n userContext?: Partial<EventContext>,\n ): void {\n const autoContext = gatherContext();\n const context = mergeContext(autoContext, userContext);\n\n const payload: IngestEventPayload = {\n type,\n name,\n properties: { ...this.config.defaultProperties, ...properties },\n timestamp: (timestamp ?? new Date()).toISOString(),\n userId: this.session.getUserId() ?? undefined,\n sessionId: this.session.getSessionId(),\n anonymousId: this.session.getAnonymousId(),\n context,\n };\n\n this.queue.add({ kind: 'event', payload });\n }\n\n private installPageViewTracking(): void {\n if (!isBrowser()) return;\n\n let lastUrl = window.location.href;\n\n const checkUrl = () => {\n const currentUrl = window.location.href;\n if (currentUrl !== lastUrl) {\n lastUrl = currentUrl;\n this.page();\n }\n };\n\n // Patch pushState/replaceState for SPA navigation\n const origPushState = history.pushState.bind(history);\n const origReplaceState = history.replaceState.bind(history);\n\n history.pushState = (...args: Parameters<typeof history.pushState>) => {\n origPushState(...args);\n checkUrl();\n };\n\n history.replaceState = (...args: Parameters<typeof history.replaceState>) => {\n origReplaceState(...args);\n checkUrl();\n };\n\n window.addEventListener('popstate', checkUrl);\n\n this.pageViewUnsubscribe = () => {\n history.pushState = origPushState;\n history.replaceState = origReplaceState;\n window.removeEventListener('popstate', checkUrl);\n };\n\n // Track initial page view\n this.page();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/transport.ts","../src/queue.ts","../src/utils.ts","../src/session.ts","../src/error-handler.ts","../src/context.ts","../src/storage.ts","../src/client.ts"],"names":[],"mappings":";AASO,IAAM,YAAN,MAAgB;AAAA,EAGrB,YAAY,MAAA,EAAyB;AACnC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA,EAEA,MAAM,WAAW,MAAA,EAA6C;AAC5D,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,gBAAA,EAAkB,EAAE,QAAQ,CAAA;AAAA,EAC9C;AAAA,EAEA,MAAM,WAAW,MAAA,EAA6C;AAC5D,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,gBAAA,EAAkB,EAAE,QAAQ,CAAA;AAAA,EAC9C;AAAA,EAEA,MAAc,IAAA,CAAK,IAAA,EAAc,IAAA,EAA8B;AAC7D,IAAA,MAAM,MAAM,IAAA,CAAK,MAAA,CAAO,SAAS,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,GAAI,IAAA;AACvD,IAAA,IAAI,SAAA;AAEJ,IAAA,KAAA,IAAS,UAAU,CAAA,EAAG,OAAA,IAAW,IAAA,CAAK,MAAA,CAAO,YAAY,OAAA,EAAA,EAAW;AAClE,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,UAChC,MAAA,EAAQ,MAAA;AAAA,UACR,OAAA,EAAS;AAAA,YACP,cAAA,EAAgB,kBAAA;AAAA,YAChB,WAAA,EAAa,KAAK,MAAA,CAAO;AAAA,WAC3B;AAAA,UACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAAA,UACzB,SAAA,EAAW;AAAA,SACZ,CAAA;AAED,QAAA,IAAI,SAAS,EAAA,EAAI;AAEjB,QAAA,IAAI,QAAA,CAAS,UAAU,GAAA,IAAO,QAAA,CAAS,SAAS,GAAA,IAAO,QAAA,CAAS,WAAW,GAAA,EAAK;AAC9E,UAAA,MAAM,OAAO,MAAM,QAAA,CAAS,MAAK,CAAE,KAAA,CAAM,MAAM,EAAE,CAAA;AACjD,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,KAAA,EAAQ,SAAS,MAAM,CAAA,EAAA,EAAK,IAAI,CAAA,CAAE,CAAA;AAAA,QACpD;AAEA,QAAA,SAAA,GAAY,IAAI,KAAA,CAAM,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,MACjD,SAAS,GAAA,EAAK;AACZ,QAAA,SAAA,GAAY,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAC9D,QAAA,IAAI,eAAe,KAAA,IAAS,GAAA,CAAI,OAAA,CAAQ,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC5D,UAAA;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY;AACpC,QAAA,MAAM,IAAA,CAAK,QAAQ,OAAO,CAAA;AAAA,MAC5B;AAAA,IACF;AAEA,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,IAAA,CAAK,MAAA,CAAO,UAAU,SAAS,CAAA;AAAA,IACjC;AAAA,EACF;AAAA,EAEQ,QAAQ,OAAA,EAAgC;AAC9C,IAAA,MAAM,QAAQ,IAAA,CAAK,GAAA,CAAI,GAAA,GAAO,CAAA,IAAK,SAAS,GAAK,CAAA;AACjD,IAAA,MAAM,MAAA,GAAS,KAAA,IAAS,GAAA,GAAM,IAAA,CAAK,QAAO,GAAI,GAAA,CAAA;AAC9C,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,MAAM,CAAC,CAAA;AAAA,EAC7D;AACF,CAAA;;;AC7DO,IAAM,aAAN,MAAiB;AAAA,EAOtB,WAAA,CAAY,WAAsB,MAAA,EAAqB;AANvD,IAAA,IAAA,CAAQ,QAAqB,EAAC;AAC9B,IAAA,IAAA,CAAQ,KAAA,GAA+C,IAAA;AAGvD,IAAA,IAAA,CAAQ,QAAA,GAAW,KAAA;AAGjB,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,UAAA,EAAW;AAAA,EAClB;AAAA,EAEA,IAAI,IAAA,EAAuB;AACzB,IAAA,IAAA,CAAK,KAAA,CAAM,KAAK,IAAI,CAAA;AACpB,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,GAAA,CAAI,CAAA,OAAA,EAAU,KAAK,IAAI,CAAA,CAAA,CAAA,EAAK,IAAA,CAAK,IAAA,KAAS,UAAU,IAAA,CAAK,OAAA,CAAQ,IAAA,GAAO,IAAA,CAAK,QAAQ,OAAO,CAAA;AAE9G,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,MAAA,IAAU,IAAA,CAAK,OAAO,OAAA,EAAS;AAC5C,MAAA,KAAK,KAAK,KAAA,EAAM;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,KAAA,CAAM,WAAW,CAAA,EAAG;AAE9C,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA;AAEjC,IAAA,IAAI;AACF,MAAA,MAAM,SAA+B,EAAC;AACtC,MAAA,MAAM,SAA+B,EAAC;AAEtC,MAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,QAAA,IAAI,KAAK,IAAA,KAAS,OAAA,EAAS,MAAA,CAAO,IAAA,CAAK,KAAK,OAAO,CAAA;AAAA,aAC9C,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,OAAO,CAAA;AAAA,MAC/B;AAEA,MAAA,MAAM,WAA4B,EAAC;AACnC,MAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,QAAA,IAAA,CAAK,OAAO,KAAA,CAAM,GAAA,CAAI,CAAA,SAAA,EAAY,MAAA,CAAO,MAAM,CAAA,OAAA,CAAS,CAAA;AACxD,QAAA,QAAA,CAAS,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,UAAA,CAAW,MAAM,CAAC,CAAA;AAAA,MACjD;AACA,MAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,QAAA,IAAA,CAAK,OAAO,KAAA,CAAM,GAAA,CAAI,CAAA,SAAA,EAAY,MAAA,CAAO,MAAM,CAAA,OAAA,CAAS,CAAA;AACxD,QAAA,QAAA,CAAS,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,UAAA,CAAW,MAAM,CAAC,CAAA;AAAA,MACjD;AAEA,MAAA,MAAM,OAAA,CAAQ,IAAI,QAAQ,CAAA;AAAA,IAC5B,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,GAAG,KAAK,CAAA;AAAA,IAC7B,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,QAAA,GAAW,KAAA;AAAA,IAClB;AAAA,EACF;AAAA,EAEQ,UAAA,GAAmB;AACzB,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,aAAA,GAAgB,CAAA,EAAG;AACjC,MAAA,IAAA,CAAK,KAAA,GAAQ,YAAY,MAAM;AAC7B,QAAA,KAAK,KAAK,KAAA,EAAM;AAAA,MAClB,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,aAAa,CAAA;AAG5B,MAAA,IAAI,KAAK,KAAA,IAAS,OAAQ,IAAA,CAAK,KAAA,CAAyB,UAAU,UAAA,EAAY;AAC5E,QAAC,IAAA,CAAK,MAAyB,KAAA,EAAM;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QAAA,GAA0B;AAC9B,IAAA,IAAI,KAAK,KAAA,EAAO;AACd,MAAA,aAAA,CAAc,KAAK,KAAK,CAAA;AACxB,MAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,IACf;AACA,IAAA,MAAM,KAAK,KAAA,EAAM;AAAA,EACnB;AAAA,EAEA,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,KAAK,KAAA,CAAM,MAAA;AAAA,EACpB;AACF,CAAA;;;ACxFO,SAAS,UAAA,GAAqB;AACnC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,MAAA,CAAO,UAAA,EAAY;AACtD,IAAA,OAAO,OAAO,UAAA,EAAW;AAAA,EAC3B;AACA,EAAA,OAAO,sCAAA,CAAuC,OAAA,CAAQ,OAAA,EAAS,CAAC,CAAA,KAAM;AACpE,IAAA,MAAM,CAAA,GAAK,IAAA,CAAK,MAAA,EAAO,GAAI,EAAA,GAAM,CAAA;AACjC,IAAA,MAAM,CAAA,GAAI,CAAA,KAAM,GAAA,GAAM,CAAA,GAAK,IAAI,CAAA,GAAO,CAAA;AACtC,IAAA,OAAO,CAAA,CAAE,SAAS,EAAE,CAAA;AAAA,EACtB,CAAC,CAAA;AACH;AAEO,SAAS,SAAA,GAAqB;AACnC,EAAA,OAAO,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,QAAA,KAAa,WAAA;AAC9D;AAMO,SAAS,kBAAkB,OAAA,EAAkB;AAClD,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,IAAI,IAAA,KAAoB;AAC3B,MAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,GAAA,CAAI,mBAAA,EAAqB,GAAG,IAAI,CAAA;AAAA,IACvD,CAAA;AAAA,IACA,IAAA,EAAM,IAAI,IAAA,KAAoB;AAC5B,MAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,IAAA,CAAK,mBAAA,EAAqB,GAAG,IAAI,CAAA;AAAA,IACxD,CAAA;AAAA,IACA,KAAA,EAAO,IAAI,IAAA,KAAoB;AAC7B,MAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,KAAA,CAAM,mBAAA,EAAqB,GAAG,IAAI,CAAA;AAAA,IACzD;AAAA,GACF;AACF;;;AC5BA,IAAM,WAAA,GAAc,cAAA;AACpB,IAAM,cAAA,GAAiB,YAAA;AACvB,IAAM,kBAAA,GAAqB,gBAAA;AAG3B,IAAM,kBAAA,GAAqB,KAAK,EAAA,GAAK,GAAA;AAE9B,IAAM,iBAAN,MAAqB;AAAA,EAM1B,YAAY,OAAA,EAAkB;AAL9B,IAAA,IAAA,CAAQ,MAAA,GAAwB,IAAA;AAM9B,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,IAAA,CAAK,cAAc,IAAA,CAAK,OAAA,CAAQ,IAAI,WAAW,CAAA,IAAK,KAAK,iBAAA,EAAkB;AAC3E,IAAA,IAAA,CAAK,SAAA,GAAY,KAAK,cAAA,EAAe;AAAA,EACvC;AAAA,EAEQ,iBAAA,GAA4B;AAClC,IAAA,MAAM,KAAK,UAAA,EAAW;AACtB,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,WAAA,EAAa,EAAE,CAAA;AAChC,IAAA,OAAO,EAAA;AAAA,EACT;AAAA,EAEQ,cAAA,GAAyB;AAC/B,IAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA;AACvD,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,kBAAkB,CAAA;AACrD,IAAA,MAAM,MAAA,GAAS,SAAA,GAAY,QAAA,CAAS,SAAA,EAAW,EAAE,CAAA,GAAI,CAAA;AAErD,IAAA,IAAI,eAAA,IAAmB,IAAA,CAAK,GAAA,EAAI,GAAI,MAAA,EAAQ;AAC1C,MAAA,IAAA,CAAK,YAAA,EAAa;AAClB,MAAA,OAAO,eAAA;AAAA,IACT;AAEA,IAAA,OAAO,KAAK,eAAA,EAAgB;AAAA,EAC9B;AAAA,EAEQ,eAAA,GAA0B;AAChC,IAAA,MAAM,KAAK,UAAA,EAAW;AACtB,IAAA,IAAA,CAAK,SAAA,GAAY,EAAA;AACjB,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,cAAA,EAAgB,EAAE,CAAA;AACnC,IAAA,IAAA,CAAK,YAAA,EAAa;AAClB,IAAA,OAAO,EAAA;AAAA,EACT;AAAA,EAEQ,YAAA,GAAqB;AAC3B,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA;AAAA,MACX,kBAAA;AAAA,MACA,MAAA,CAAO,IAAA,CAAK,GAAA,EAAI,GAAI,kBAAkB;AAAA,KACxC;AAAA,EACF;AAAA,EAEA,UAAU,EAAA,EAAkB;AAC1B,IAAA,IAAA,CAAK,MAAA,GAAS,EAAA;AAAA,EAChB;AAAA,EAEA,SAAA,GAA2B;AACzB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAEA,cAAA,GAAyB;AACvB,IAAA,OAAO,IAAA,CAAK,WAAA;AAAA,EACd;AAAA,EAEA,YAAA,GAAuB;AACrB,IAAA,IAAA,CAAK,SAAA,GAAY,KAAK,cAAA,EAAe;AACrC,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AACd,IAAA,IAAA,CAAK,WAAA,GAAc,KAAK,iBAAA,EAAkB;AAC1C,IAAA,IAAA,CAAK,SAAA,GAAY,KAAK,eAAA,EAAgB;AAAA,EACxC;AACF,CAAA;;;AC1EO,IAAM,qBAAN,MAAyB;AAAA,EAM9B,YAAY,QAAA,EAAyB;AAJrC,IAAA,IAAA,CAAQ,SAAA,GAAY,KAAA;AACpB,IAAA,IAAA,CAAQ,eAAA,GAA8C,IAAA;AACtD,IAAA,IAAA,CAAQ,4BAAA,GAA6E,IAAA;AAqErF,IAAA,IAAA,CAAQ,eAAA,GAAkB,CAAC,KAAA,KAAuB;AAChD,MAAA,IAAA,CAAK,QAAA,CAAS,OAAO,mBAAmB,CAAA;AAAA,IAC1C,CAAA;AAEA,IAAA,IAAA,CAAQ,mBAAA,GAAsB,CAAC,MAAA,KAA0B;AACvD,MAAA,MAAM,KAAA,GAAQ,kBAAkB,KAAA,GAAQ,MAAA,GAAS,IAAI,KAAA,CAAM,MAAA,CAAO,MAAM,CAAC,CAAA;AACzE,MAAA,IAAA,CAAK,QAAA,CAAS,OAAO,oBAAoB,CAAA;AAAA,IAC3C,CAAA;AAzEE,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAAA,EAClB;AAAA,EAEA,OAAA,GAAgB;AACd,IAAA,IAAI,KAAK,SAAA,EAAW;AACpB,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AAEjB,IAAA,IAAI,WAAU,EAAG;AACf,MAAA,IAAA,CAAK,cAAA,EAAe;AAAA,IACtB,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,WAAA,EAAY;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,SAAA,GAAkB;AAChB,IAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACrB,IAAA,IAAA,CAAK,SAAA,GAAY,KAAA;AAEjB,IAAA,IAAI,WAAU,EAAG;AACf,MAAA,IAAA,CAAK,gBAAA,EAAiB;AAAA,IACxB,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,aAAA,EAAc;AAAA,IACrB;AAAA,EACF;AAAA,EAEQ,cAAA,GAAuB;AAC7B,IAAA,IAAA,CAAK,kBAAkB,MAAA,CAAO,OAAA;AAC9B,IAAA,MAAA,CAAO,UAAU,CAAC,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAQ,OAAO,KAAA,KAAU;AAC1D,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,IAAA,CAAK,QAAA,CAAS,KAAA,EAAO,MAAA,IAAU,MAAS,CAAA;AAAA,MAC1C,CAAA,MAAA,IAAW,OAAO,OAAA,KAAY,QAAA,EAAU;AACtC,QAAA,IAAA,CAAK,SAAS,IAAI,KAAA,CAAM,OAAO,CAAA,EAAG,UAAU,MAAS,CAAA;AAAA,MACvD;AACA,MAAA,IAAA,CAAK,iBAAiB,IAAA,CAAK,MAAA,EAAQ,SAAS,MAAA,EAAQ,MAAA,EAAQ,OAAO,KAAK,CAAA;AAAA,IAC1E,CAAA;AAEA,IAAA,IAAA,CAAK,+BAA+B,MAAA,CAAO,oBAAA;AAC3C,IAAA,MAAA,CAAO,oBAAA,GAAuB,CAAC,KAAA,KAAiC;AAC9D,MAAA,MAAM,KAAA,GACJ,KAAA,CAAM,MAAA,YAAkB,KAAA,GACpB,KAAA,CAAM,MAAA,GACN,IAAI,KAAA,CAAM,MAAA,CAAO,KAAA,CAAM,MAAM,CAAC,CAAA;AACpC,MAAA,IAAA,CAAK,QAAA,CAAS,OAAO,oBAAoB,CAAA;AACzC,MAAC,IAAA,CAAK,4BAAA,EAA+E,IAAA,CAAK,MAAA,EAAQ,KAAK,CAAA;AAAA,IACzG,CAAA;AAAA,EACF;AAAA,EAEQ,gBAAA,GAAyB;AAC/B,IAAA,MAAA,CAAO,UAAU,IAAA,CAAK,eAAA;AACtB,IAAA,MAAA,CAAO,uBAAuB,IAAA,CAAK,4BAAA;AAAA,EACrC;AAAA,EAEQ,WAAA,GAAoB;AAC1B,IAAA,IAAI,OAAO,YAAY,WAAA,EAAa;AAEpC,IAAA,OAAA,CAAQ,EAAA,CAAG,mBAAA,EAAqB,IAAA,CAAK,eAAe,CAAA;AACpD,IAAA,OAAA,CAAQ,EAAA,CAAG,oBAAA,EAAsB,IAAA,CAAK,mBAAmB,CAAA;AAAA,EAC3D;AAAA,EAEQ,aAAA,GAAsB;AAC5B,IAAA,IAAI,OAAO,YAAY,WAAA,EAAa;AAEpC,IAAA,OAAA,CAAQ,cAAA,CAAe,mBAAA,EAAqB,IAAA,CAAK,eAAe,CAAA;AAChE,IAAA,OAAA,CAAQ,cAAA,CAAe,oBAAA,EAAsB,IAAA,CAAK,mBAAmB,CAAA;AAAA,EACvE;AAUF,CAAA;;;AC9EA,SAAS,eAAe,EAAA,EAItB;AACA,EAAA,MAAM,OAAA,GAAU,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,MAAA,EAAgC;AAC5E,EAAA,MAAM,EAAA,GAAK,EAAE,IAAA,EAAM,SAAA,EAAW,SAAS,MAAA,EAAgC;AACvE,EAAA,MAAM,MAAA,GAAS,EAAE,IAAA,EAAM,SAAA,EAAU;AAGjC,EAAA,IAAI,gCAAA,CAAiC,IAAA,CAAK,EAAE,CAAA,EAAG;AAC7C,IAAA,MAAA,CAAO,IAAA,GAAO,cAAA,CAAe,IAAA,CAAK,EAAE,IAAI,QAAA,GAAW,QAAA;AAAA,EACrD;AAGA,EAAA,IAAI,QAAA,CAAS,IAAA,CAAK,EAAE,CAAA,EAAG;AACrB,IAAA,OAAA,CAAQ,IAAA,GAAO,MAAA;AACf,IAAA,OAAA,CAAQ,OAAA,GAAU,EAAA,CAAG,KAAA,CAAM,eAAe,IAAI,CAAC,CAAA;AAAA,EACjD,CAAA,MAAA,IAAW,SAAS,IAAA,CAAK,EAAE,KAAK,QAAA,CAAS,IAAA,CAAK,EAAE,CAAA,EAAG;AACjD,IAAA,OAAA,CAAQ,IAAA,GAAO,OAAA;AACf,IAAA,OAAA,CAAQ,OAAA,GAAU,EAAA,CAAG,KAAA,CAAM,yBAAyB,IAAI,CAAC,CAAA;AAAA,EAC3D,CAAA,MAAA,IAAW,YAAY,IAAA,CAAK,EAAE,KAAK,CAAC,WAAA,CAAY,IAAA,CAAK,EAAE,CAAA,EAAG;AACxD,IAAA,OAAA,CAAQ,IAAA,GAAO,QAAA;AACf,IAAA,OAAA,CAAQ,OAAA,GAAU,EAAA,CAAG,KAAA,CAAM,kBAAkB,IAAI,CAAC,CAAA;AAAA,EACpD,CAAA,MAAA,IAAW,YAAY,IAAA,CAAK,EAAE,KAAK,CAAC,SAAA,CAAU,IAAA,CAAK,EAAE,CAAA,EAAG;AACtD,IAAA,OAAA,CAAQ,IAAA,GAAO,QAAA;AACf,IAAA,OAAA,CAAQ,OAAA,GAAU,EAAA,CAAG,KAAA,CAAM,mBAAmB,IAAI,CAAC,CAAA;AAAA,EACrD,CAAA,MAAA,IAAW,YAAA,CAAa,IAAA,CAAK,EAAE,CAAA,EAAG;AAChC,IAAA,OAAA,CAAQ,IAAA,GAAO,SAAA;AACf,IAAA,OAAA,CAAQ,OAAA,GAAU,EAAA,CAAG,KAAA,CAAM,mBAAmB,IAAI,CAAC,CAAA;AAAA,EACrD;AAGA,EAAA,IAAI,aAAA,CAAc,IAAA,CAAK,EAAE,CAAA,EAAG;AAC1B,IAAA,EAAA,CAAG,IAAA,GAAO,SAAA;AACV,IAAA,MAAM,SAAA,GAAY,EAAA,CAAG,KAAA,CAAM,qBAAqB,IAAI,CAAC,CAAA;AACrD,IAAA,MAAM,UAAA,GAAqC;AAAA,MACzC,MAAA,EAAQ,KAAA;AAAA,MACR,KAAA,EAAO,KAAA;AAAA,MACP,KAAA,EAAO,GAAA;AAAA,MACP,KAAA,EAAO;AAAA,KACT;AACA,IAAA,EAAA,CAAG,OAAA,GAAU,SAAA,GAAa,UAAA,CAAW,SAAS,KAAK,SAAA,GAAa,MAAA;AAAA,EAClE,CAAA,MAAA,IAAW,WAAA,CAAY,IAAA,CAAK,EAAE,CAAA,EAAG;AAC/B,IAAA,EAAA,CAAG,IAAA,GAAO,OAAA;AACV,IAAA,EAAA,CAAG,OAAA,GAAU,GAAG,KAAA,CAAM,oBAAoB,IAAI,CAAC,CAAA,EAAG,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA;AAAA,EACrE,CAAA,MAAA,IAAW,UAAA,CAAW,IAAA,CAAK,EAAE,CAAA,EAAG;AAC9B,IAAA,EAAA,CAAG,IAAA,GAAO,SAAA;AACV,IAAA,EAAA,CAAG,OAAA,GAAU,EAAA,CAAG,KAAA,CAAM,kBAAkB,IAAI,CAAC,CAAA;AAAA,EAC/C,CAAA,MAAA,IAAW,iBAAA,CAAkB,IAAA,CAAK,EAAE,CAAA,EAAG;AACrC,IAAA,EAAA,CAAG,IAAA,GAAO,KAAA;AACV,IAAA,EAAA,CAAG,OAAA,GAAU,GAAG,KAAA,CAAM,aAAa,IAAI,CAAC,CAAA,EAAG,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA;AAAA,EAC9D,CAAA,MAAA,IAAW,QAAA,CAAS,IAAA,CAAK,EAAE,CAAA,EAAG;AAC5B,IAAA,EAAA,CAAG,IAAA,GAAO,OAAA;AAAA,EACZ;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,EAAA,EAAI,MAAA,EAAO;AAC/B;AAEO,SAAS,aAAA,GAA8B;AAC5C,EAAA,IAAI,CAAC,WAAU,EAAG;AAChB,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,KAAK,SAAA,CAAU,SAAA;AACrB,EAAA,MAAM,EAAE,OAAA,EAAS,EAAA,EAAI,MAAA,EAAO,GAAI,eAAe,EAAE,CAAA;AAEjD,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,EAAA;AAAA,IACX,QAAQ,SAAA,CAAU,QAAA;AAAA,IAClB,IAAA,EAAM;AAAA,MACJ,GAAA,EAAK,OAAO,QAAA,CAAS,IAAA;AAAA,MACrB,QAAA,EAAU,SAAS,QAAA,IAAY,MAAA;AAAA,MAC/B,KAAA,EAAO,SAAS,KAAA,IAAS,MAAA;AAAA,MACzB,IAAA,EAAM,OAAO,QAAA,CAAS;AAAA,KACxB;AAAA,IACA,OAAA;AAAA,IACA,EAAA;AAAA,IACA;AAAA,GACF;AACF;AAEO,SAAS,YAAA,CACd,MACA,IAAA,EACc;AACd,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,EAAA,OAAO;AAAA,IACL,GAAG,IAAA;AAAA,IACH,GAAG,IAAA;AAAA,IACH,MAAM,EAAE,GAAG,KAAK,IAAA,EAAM,GAAG,KAAK,IAAA,EAAK;AAAA,IACnC,SAAS,EAAE,GAAG,KAAK,OAAA,EAAS,GAAG,KAAK,OAAA,EAAQ;AAAA,IAC5C,IAAI,EAAE,GAAG,KAAK,EAAA,EAAI,GAAG,KAAK,EAAA,EAAG;AAAA,IAC7B,QAAQ,EAAE,GAAG,KAAK,MAAA,EAAQ,GAAG,KAAK,MAAA;AAAO,GAC3C;AACF;;;ACvGA,IAAM,MAAA,GAAS,KAAA;AAQf,IAAM,eAAN,MAAsC;AAAA,EACpC,IAAI,GAAA,EAA4B;AAC9B,IAAA,IAAI;AACF,MAAA,OAAO,YAAA,CAAa,OAAA,CAAQ,MAAA,GAAS,GAAG,CAAA;AAAA,IAC1C,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAAA,EAEA,GAAA,CAAI,KAAa,KAAA,EAAqB;AACpC,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,OAAA,CAAQ,MAAA,GAAS,GAAA,EAAK,KAAK,CAAA;AAAA,IAC1C,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,OAAO,GAAA,EAAmB;AACxB,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,UAAA,CAAW,SAAS,GAAG,CAAA;AAAA,IACtC,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AACF,CAAA;AAEA,IAAM,gBAAN,MAAuC;AAAA,EAAvC,WAAA,GAAA;AACE,IAAA,IAAA,CAAQ,KAAA,uBAAY,GAAA,EAAoB;AAAA,EAAA;AAAA,EAExC,IAAI,GAAA,EAA4B;AAC9B,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,MAAA,GAAS,GAAG,CAAA,IAAK,IAAA;AAAA,EACzC;AAAA,EAEA,GAAA,CAAI,KAAa,KAAA,EAAqB;AACpC,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,MAAA,GAAS,GAAA,EAAK,KAAK,CAAA;AAAA,EACpC;AAAA,EAEA,OAAO,GAAA,EAAmB;AACxB,IAAA,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,MAAA,GAAS,GAAG,CAAA;AAAA,EAChC;AACF,CAAA;AAEO,SAAS,aAAA,GAAyB;AACvC,EAAA,IAAI;AACF,IAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACvC,MAAA,YAAA,CAAa,OAAA,CAAQ,eAAe,GAAG,CAAA;AACvC,MAAA,YAAA,CAAa,WAAW,aAAa,CAAA;AACrC,MAAA,OAAO,IAAI,YAAA,EAAa;AAAA,IAC1B;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,IAAI,aAAA,EAAc;AAC3B;;;ACzCA,IAAM,gBAAA,GAAmB,iCAAA;AACzB,IAAM,gBAAA,GAAmB,EAAA;AACzB,IAAM,sBAAA,GAAyB,GAAA;AAC/B,IAAM,mBAAA,GAAsB,CAAA;AAErB,IAAM,kBAAN,MAAsB;AAAA,EAU3B,YAAY,MAAA,EAA+B;AAP3C,IAAA,IAAA,CAAQ,YAAA,GAA0C,IAAA;AAKlD,IAAA,IAAA,CAAQ,mBAAA,GAA2C,IAAA;AAGjD,IAAA,IAAI,CAAC,OAAO,MAAA,EAAQ;AAClB,MAAA,MAAM,IAAI,MAAM,qCAAqC,CAAA;AAAA,IACvD;AAEA,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,GAAG,MAAA;AAAA,MACH,iBAAA,EAAmB,MAAA,CAAO,iBAAA,IAAqB;AAAC,KAClD;AAEA,IAAA,IAAA,CAAK,KAAA,GAAQ,iBAAA,CAAkB,MAAA,CAAO,KAAA,IAAS,KAAK,CAAA;AACpD,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,6BAAA,EAA+B,MAAA,CAAO,YAAY,gBAAgB,CAAA;AAEjF,IAAA,MAAM,UAAU,aAAA,EAAc;AAC9B,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,cAAA,CAAe,OAAO,CAAA;AAEzC,IAAA,MAAM,SAAA,GAAY,IAAI,SAAA,CAAU;AAAA,MAC9B,QAAA,EAAU,OAAO,QAAA,IAAY,gBAAA;AAAA,MAC7B,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,UAAA,EAAY,OAAO,UAAA,IAAc,mBAAA;AAAA,MACjC,SAAS,MAAA,CAAO;AAAA,KACjB,CAAA;AAED,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,UAAA,CAAW,SAAA,EAAW;AAAA,MACrC,OAAA,EAAS,OAAO,OAAA,IAAW,gBAAA;AAAA,MAC3B,aAAA,EAAe,OAAO,aAAA,IAAiB,sBAAA;AAAA,MACvC,OAAO,IAAA,CAAK;AAAA,KACb,CAAA;AAED,IAAA,MAAM,WAAA,GAAc,MAAA,CAAO,WAAA,IAAe,EAAC;AAE3C,IAAA,IAAI,WAAA,CAAY,WAAW,KAAA,EAAO;AAChC,MAAA,IAAA,CAAK,YAAA,GAAe,IAAI,kBAAA,CAAmB,CAAC,OAAO,MAAA,KAAW;AAC5D,QAAA,IAAA,CAAK,aAAa,KAAA,EAAO;AAAA,UACvB,OAAA,EAAS,KAAA;AAAA,UACT,QAAA,EAAU,EAAE,MAAA;AAAO,SACpB,CAAA;AAAA,MACH,CAAC,CAAA;AACD,MAAA,IAAA,CAAK,aAAa,OAAA,EAAQ;AAAA,IAC5B;AAEA,IAAA,IAAI,WAAA,CAAY,SAAA,IAAa,SAAA,EAAU,EAAG;AACxC,MAAA,IAAA,CAAK,uBAAA,EAAwB;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,KAAA,CAAM,IAAA,EAAc,OAAA,GAAwB,EAAC,EAAS;AACpD,IAAA,IAAA,CAAK,YAAA,CAAa,SAAS,IAAA,EAAM,OAAA,CAAQ,YAAY,OAAA,CAAQ,SAAA,EAAW,QAAQ,OAAO,CAAA;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,QAAA,CAAS,MAAA,EAAgB,OAAA,GAA2B,EAAC,EAAS;AAC5D,IAAA,IAAA,CAAK,OAAA,CAAQ,UAAU,MAAM,CAAA;AAC7B,IAAA,IAAA,CAAK,YAAA,CAAa,YAAY,UAAA,EAAY,OAAA,CAAQ,QAAQ,OAAA,CAAQ,SAAA,EAAW,QAAQ,OAAO,CAAA;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAA,CAAK,IAAA,EAAe,OAAA,GAAuB,EAAC,EAAS;AACnD,IAAA,MAAM,QAAA,GAAW,IAAA,KAAS,SAAA,EAAU,GAAI,SAAS,KAAA,GAAQ,WAAA,CAAA;AACzD,IAAA,IAAA,CAAK,YAAA,CAAa,QAAQ,QAAA,EAAU,OAAA,CAAQ,YAAY,OAAA,CAAQ,SAAA,EAAW,QAAQ,OAAO,CAAA;AAAA,EAC5F;AAAA;AAAA;AAAA;AAAA,EAKA,MAAA,CAAO,IAAA,EAAc,OAAA,GAAyB,EAAC,EAAS;AACtD,IAAA,IAAA,CAAK,YAAA,CAAa,UAAU,IAAA,EAAM,OAAA,CAAQ,YAAY,OAAA,CAAQ,SAAA,EAAW,QAAQ,OAAO,CAAA;AAAA,EAC1F;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,CAAM,OAAA,EAAiB,OAAA,GAAwB,EAAC,EAAS;AACvD,IAAA,IAAA,CAAK,YAAA,CAAa,SAAS,OAAA,EAAS,OAAA,CAAQ,QAAQ,OAAA,CAAQ,SAAA,EAAW,QAAQ,OAAO,CAAA;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,CAAM,QAAgB,UAAA,EAA0B;AAC9C,IAAA,IAAA,CAAK,aAAa,OAAA,EAAS,OAAA,EAAS,EAAE,MAAA,EAAQ,YAAY,CAAA;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YAAA,CACE,KAAA,EACA,OAAA,GAA+B,EAAC,EAC1B;AACN,IAAA,MAAM,MAAM,OAAO,KAAA,KAAU,WAAW,IAAI,KAAA,CAAM,KAAK,CAAA,GAAI,KAAA;AAC3D,IAAA,MAAM,cAAc,aAAA,EAAc;AAElC,IAAA,MAAM,OAAA,GAA8B;AAAA,MAClC,IAAA,EAAM,IAAI,IAAA,IAAQ,OAAA;AAAA,MAClB,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,YAAY,GAAA,CAAI,KAAA;AAAA,MAChB,KAAA,EAAO,QAAQ,KAAA,IAAS,OAAA;AAAA,MACxB,aAAa,OAAA,CAAQ,WAAA;AAAA,MACrB,OAAA,EAAS,QAAQ,OAAA,IAAW,IAAA;AAAA,MAC5B,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,MAAM,OAAA,CAAQ,IAAA;AAAA,MACd,YAAY,OAAA,CAAQ,SAAA,oBAAa,IAAI,IAAA,IAAQ,WAAA,EAAY;AAAA,MACzD,MAAA,EAAQ,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAU,IAAK,MAAA;AAAA,MACpC,SAAA,EAAW,IAAA,CAAK,OAAA,CAAQ,YAAA,EAAa;AAAA,MACrC,OAAA,EAAS;AAAA,QACP,WAAW,WAAA,CAAY,SAAA;AAAA,QACvB,OAAA,EAAS,YAAY,OAAA,EAAS,IAAA;AAAA,QAC9B,EAAA,EAAI,YAAY,EAAA,EAAI,IAAA;AAAA,QACpB,MAAA,EAAQ,YAAY,MAAA,EAAQ,IAAA;AAAA,QAC5B,GAAA,EAAK,YAAY,IAAA,EAAM,GAAA;AAAA,QACvB,SAAS,OAAA,CAAQ;AAAA;AACnB,KACF;AAEA,IAAA,IAAA,CAAK,MAAM,GAAA,CAAI,EAAE,IAAA,EAAM,OAAA,EAAS,SAAS,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAA,GAAuB;AAC3B,IAAA,MAAM,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AACnB,IAAA,IAAA,CAAK,KAAA,CAAM,IAAI,YAAY,CAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAA,GAA0B;AAC9B,IAAA,IAAA,CAAK,KAAA,CAAM,IAAI,eAAe,CAAA;AAC9B,IAAA,IAAA,CAAK,cAAc,SAAA,EAAU;AAC7B,IAAA,IAAA,CAAK,mBAAA,IAAsB;AAC3B,IAAA,MAAM,IAAA,CAAK,MAAM,QAAA,EAAS;AAAA,EAC5B;AAAA;AAAA,EAIQ,YAAA,CACN,IAAA,EACA,IAAA,EACA,UAAA,EACA,WACA,WAAA,EACM;AACN,IAAA,MAAM,cAAc,aAAA,EAAc;AAClC,IAAA,MAAM,OAAA,GAAU,YAAA,CAAa,WAAA,EAAa,WAAW,CAAA;AAErD,IAAA,MAAM,OAAA,GAA8B;AAAA,MAClC,IAAA;AAAA,MACA,IAAA;AAAA,MACA,YAAY,EAAE,GAAG,KAAK,MAAA,CAAO,iBAAA,EAAmB,GAAG,UAAA,EAAW;AAAA,MAC9D,SAAA,EAAA,CAAY,SAAA,oBAAa,IAAI,IAAA,IAAQ,WAAA,EAAY;AAAA,MACjD,MAAA,EAAQ,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAU,IAAK,MAAA;AAAA,MACpC,SAAA,EAAW,IAAA,CAAK,OAAA,CAAQ,YAAA,EAAa;AAAA,MACrC,WAAA,EAAa,IAAA,CAAK,OAAA,CAAQ,cAAA,EAAe;AAAA,MACzC;AAAA,KACF;AAEA,IAAA,IAAA,CAAK,MAAM,GAAA,CAAI,EAAE,IAAA,EAAM,OAAA,EAAS,SAAS,CAAA;AAAA,EAC3C;AAAA,EAEQ,uBAAA,GAAgC;AACtC,IAAA,IAAI,CAAC,WAAU,EAAG;AAElB,IAAA,IAAI,OAAA,GAAU,OAAO,QAAA,CAAS,IAAA;AAE9B,IAAA,MAAM,WAAW,MAAM;AACrB,MAAA,MAAM,UAAA,GAAa,OAAO,QAAA,CAAS,IAAA;AACnC,MAAA,IAAI,eAAe,OAAA,EAAS;AAC1B,QAAA,OAAA,GAAU,UAAA;AACV,QAAA,IAAA,CAAK,IAAA,EAAK;AAAA,MACZ;AAAA,IACF,CAAA;AAGA,IAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA;AACpD,IAAA,MAAM,gBAAA,GAAmB,OAAA,CAAQ,YAAA,CAAa,IAAA,CAAK,OAAO,CAAA;AAE1D,IAAA,OAAA,CAAQ,SAAA,GAAY,IAAI,IAAA,KAA+C;AACrE,MAAA,aAAA,CAAc,GAAG,IAAI,CAAA;AACrB,MAAA,QAAA,EAAS;AAAA,IACX,CAAA;AAEA,IAAA,OAAA,CAAQ,YAAA,GAAe,IAAI,IAAA,KAAkD;AAC3E,MAAA,gBAAA,CAAiB,GAAG,IAAI,CAAA;AACxB,MAAA,QAAA,EAAS;AAAA,IACX,CAAA;AAEA,IAAA,MAAA,CAAO,gBAAA,CAAiB,YAAY,QAAQ,CAAA;AAE5C,IAAA,IAAA,CAAK,sBAAsB,MAAM;AAC/B,MAAA,OAAA,CAAQ,SAAA,GAAY,aAAA;AACpB,MAAA,OAAA,CAAQ,YAAA,GAAe,gBAAA;AACvB,MAAA,MAAA,CAAO,mBAAA,CAAoB,YAAY,QAAQ,CAAA;AAAA,IACjD,CAAA;AAGA,IAAA,IAAA,CAAK,IAAA,EAAK;AAAA,EACZ;AACF","file":"index.mjs","sourcesContent":["import type { IngestEventPayload, IngestErrorPayload } from './types';\n\nexport interface TransportConfig {\n endpoint: string;\n apiKey: string;\n maxRetries: number;\n onError?: (error: Error) => void;\n}\n\nexport class Transport {\n private config: TransportConfig;\n\n constructor(config: TransportConfig) {\n this.config = config;\n }\n\n async sendEvents(events: IngestEventPayload[]): Promise<void> {\n await this.post('/ingest/events', { events });\n }\n\n async sendErrors(errors: IngestErrorPayload[]): Promise<void> {\n await this.post('/ingest/errors', { errors });\n }\n\n private async post(path: string, body: unknown): Promise<void> {\n const url = this.config.endpoint.replace(/\\/+$/, '') + path;\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.config.apiKey,\n },\n body: JSON.stringify(body),\n keepalive: true,\n });\n\n if (response.ok) return;\n\n if (response.status >= 400 && response.status < 500 && response.status !== 429) {\n const text = await response.text().catch(() => '');\n throw new Error(`HTTP ${response.status}: ${text}`);\n }\n\n lastError = new Error(`HTTP ${response.status}`);\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (err instanceof Error && err.message.startsWith('HTTP 4')) {\n break;\n }\n }\n\n if (attempt < this.config.maxRetries) {\n await this.backoff(attempt);\n }\n }\n\n if (lastError) {\n this.config.onError?.(lastError);\n }\n }\n\n private backoff(attempt: number): Promise<void> {\n const delay = Math.min(1000 * 2 ** attempt, 30000);\n const jitter = delay * (0.5 + Math.random() * 0.5);\n return new Promise((resolve) => setTimeout(resolve, jitter));\n }\n}\n","import type { QueueItem, IngestEventPayload, IngestErrorPayload } from './types';\nimport type { Transport } from './transport';\n\nexport interface QueueConfig {\n flushAt: number;\n flushInterval: number;\n debug: ReturnType<typeof import('./utils').createDebugLogger>;\n}\n\nexport class EventQueue {\n private items: QueueItem[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private transport: Transport;\n private config: QueueConfig;\n private flushing = false;\n\n constructor(transport: Transport, config: QueueConfig) {\n this.transport = transport;\n this.config = config;\n this.startTimer();\n }\n\n add(item: QueueItem): void {\n this.items.push(item);\n this.config.debug.log(`Queued ${item.kind}:`, item.kind === 'event' ? item.payload.name : item.payload.message);\n\n if (this.items.length >= this.config.flushAt) {\n void this.flush();\n }\n }\n\n async flush(): Promise<void> {\n if (this.flushing || this.items.length === 0) return;\n\n this.flushing = true;\n const batch = this.items.splice(0);\n\n try {\n const events: IngestEventPayload[] = [];\n const errors: IngestErrorPayload[] = [];\n\n for (const item of batch) {\n if (item.kind === 'event') events.push(item.payload);\n else errors.push(item.payload);\n }\n\n const promises: Promise<void>[] = [];\n if (events.length > 0) {\n this.config.debug.log(`Flushing ${events.length} events`);\n promises.push(this.transport.sendEvents(events));\n }\n if (errors.length > 0) {\n this.config.debug.log(`Flushing ${errors.length} errors`);\n promises.push(this.transport.sendErrors(errors));\n }\n\n await Promise.all(promises);\n } catch {\n this.items.unshift(...batch);\n } finally {\n this.flushing = false;\n }\n }\n\n private startTimer(): void {\n if (this.config.flushInterval > 0) {\n this.timer = setInterval(() => {\n void this.flush();\n }, this.config.flushInterval);\n\n // Allow Node.js to exit without waiting for the timer\n if (this.timer && typeof (this.timer as NodeJS.Timeout).unref === 'function') {\n (this.timer as NodeJS.Timeout).unref();\n }\n }\n }\n\n async shutdown(): Promise<void> {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush();\n }\n\n get size(): number {\n return this.items.length;\n }\n}\n","export function generateId(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\nexport function now(): string {\n return new Date().toISOString();\n}\n\nexport function createDebugLogger(enabled: boolean) {\n return {\n log: (...args: unknown[]) => {\n if (enabled) console.log('[BoringAnalytics]', ...args);\n },\n warn: (...args: unknown[]) => {\n if (enabled) console.warn('[BoringAnalytics]', ...args);\n },\n error: (...args: unknown[]) => {\n if (enabled) console.error('[BoringAnalytics]', ...args);\n },\n };\n}\n","import type { Storage } from './storage';\nimport { generateId } from './utils';\n\nconst ANON_ID_KEY = 'anonymous_id';\nconst SESSION_ID_KEY = 'session_id';\nconst SESSION_EXPIRY_KEY = 'session_expiry';\n\n/** Session timeout: 30 minutes of inactivity */\nconst SESSION_TIMEOUT_MS = 30 * 60 * 1000;\n\nexport class SessionManager {\n private userId: string | null = null;\n private anonymousId: string;\n private sessionId: string;\n private storage: Storage;\n\n constructor(storage: Storage) {\n this.storage = storage;\n this.anonymousId = this.storage.get(ANON_ID_KEY) ?? this.createAnonymousId();\n this.sessionId = this.resolveSession();\n }\n\n private createAnonymousId(): string {\n const id = generateId();\n this.storage.set(ANON_ID_KEY, id);\n return id;\n }\n\n private resolveSession(): string {\n const existingSession = this.storage.get(SESSION_ID_KEY);\n const expiryStr = this.storage.get(SESSION_EXPIRY_KEY);\n const expiry = expiryStr ? parseInt(expiryStr, 10) : 0;\n\n if (existingSession && Date.now() < expiry) {\n this.touchSession();\n return existingSession;\n }\n\n return this.startNewSession();\n }\n\n private startNewSession(): string {\n const id = generateId();\n this.sessionId = id;\n this.storage.set(SESSION_ID_KEY, id);\n this.touchSession();\n return id;\n }\n\n private touchSession(): void {\n this.storage.set(\n SESSION_EXPIRY_KEY,\n String(Date.now() + SESSION_TIMEOUT_MS),\n );\n }\n\n setUserId(id: string): void {\n this.userId = id;\n }\n\n getUserId(): string | null {\n return this.userId;\n }\n\n getAnonymousId(): string {\n return this.anonymousId;\n }\n\n getSessionId(): string {\n this.sessionId = this.resolveSession();\n return this.sessionId;\n }\n\n reset(): void {\n this.userId = null;\n this.anonymousId = this.createAnonymousId();\n this.sessionId = this.startNewSession();\n }\n}\n","import { isBrowser } from './utils';\n\ntype ErrorCallback = (error: Error, source?: string) => void;\n\nexport class GlobalErrorHandler {\n private callback: ErrorCallback;\n private installed = false;\n private originalOnError: OnErrorEventHandler | null = null;\n private originalOnUnhandledRejection: ((ev: PromiseRejectionEvent) => void) | null = null;\n\n constructor(callback: ErrorCallback) {\n this.callback = callback;\n }\n\n install(): void {\n if (this.installed) return;\n this.installed = true;\n\n if (isBrowser()) {\n this.installBrowser();\n } else {\n this.installNode();\n }\n }\n\n uninstall(): void {\n if (!this.installed) return;\n this.installed = false;\n\n if (isBrowser()) {\n this.uninstallBrowser();\n } else {\n this.uninstallNode();\n }\n }\n\n private installBrowser(): void {\n this.originalOnError = window.onerror;\n window.onerror = (message, source, lineno, colno, error) => {\n if (error) {\n this.callback(error, source ?? undefined);\n } else if (typeof message === 'string') {\n this.callback(new Error(message), source ?? undefined);\n }\n this.originalOnError?.call(window, message, source, lineno, colno, error);\n };\n\n this.originalOnUnhandledRejection = window.onunhandledrejection as typeof this.originalOnUnhandledRejection;\n window.onunhandledrejection = (event: PromiseRejectionEvent) => {\n const error =\n event.reason instanceof Error\n ? event.reason\n : new Error(String(event.reason));\n this.callback(error, 'unhandledrejection');\n (this.originalOnUnhandledRejection as ((ev: PromiseRejectionEvent) => void) | null)?.call(window, event);\n };\n }\n\n private uninstallBrowser(): void {\n window.onerror = this.originalOnError;\n window.onunhandledrejection = this.originalOnUnhandledRejection as typeof window.onunhandledrejection;\n }\n\n private installNode(): void {\n if (typeof process === 'undefined') return;\n\n process.on('uncaughtException', this.handleNodeError);\n process.on('unhandledRejection', this.handleNodeRejection);\n }\n\n private uninstallNode(): void {\n if (typeof process === 'undefined') return;\n\n process.removeListener('uncaughtException', this.handleNodeError);\n process.removeListener('unhandledRejection', this.handleNodeRejection);\n }\n\n private handleNodeError = (error: Error): void => {\n this.callback(error, 'uncaughtException');\n };\n\n private handleNodeRejection = (reason: unknown): void => {\n const error = reason instanceof Error ? reason : new Error(String(reason));\n this.callback(error, 'unhandledRejection');\n };\n}\n","import type { EventContext } from './types';\nimport { isBrowser } from './utils';\n\n/**\n * Parses a user agent string into browser, OS, and device info.\n * Lightweight — covers major browsers/platforms without a full UA parser dependency.\n */\nfunction parseUserAgent(ua: string): {\n browser: { name: string; version?: string };\n os: { name: string; version?: string };\n device: { type: string };\n} {\n const browser = { name: 'Unknown', version: undefined as string | undefined };\n const os = { name: 'Unknown', version: undefined as string | undefined };\n const device = { type: 'desktop' };\n\n // Mobile detection\n if (/Mobi|Android|iPhone|iPad|iPod/i.test(ua)) {\n device.type = /iPad|Tablet/i.test(ua) ? 'tablet' : 'mobile';\n }\n\n // Browser detection\n if (/Edg\\//i.test(ua)) {\n browser.name = 'Edge';\n browser.version = ua.match(/Edg\\/([\\d.]+)/)?.[1];\n } else if (/OPR\\//i.test(ua) || /Opera/i.test(ua)) {\n browser.name = 'Opera';\n browser.version = ua.match(/(?:OPR|Opera)\\/([\\d.]+)/)?.[1];\n } else if (/Chrome\\//i.test(ua) && !/Chromium/i.test(ua)) {\n browser.name = 'Chrome';\n browser.version = ua.match(/Chrome\\/([\\d.]+)/)?.[1];\n } else if (/Safari\\//i.test(ua) && !/Chrome/i.test(ua)) {\n browser.name = 'Safari';\n browser.version = ua.match(/Version\\/([\\d.]+)/)?.[1];\n } else if (/Firefox\\//i.test(ua)) {\n browser.name = 'Firefox';\n browser.version = ua.match(/Firefox\\/([\\d.]+)/)?.[1];\n }\n\n // OS detection\n if (/Windows NT/i.test(ua)) {\n os.name = 'Windows';\n const ntVersion = ua.match(/Windows NT ([\\d.]+)/)?.[1];\n const versionMap: Record<string, string> = {\n '10.0': '10+',\n '6.3': '8.1',\n '6.2': '8',\n '6.1': '7',\n };\n os.version = ntVersion ? (versionMap[ntVersion] ?? ntVersion) : undefined;\n } else if (/Mac OS X/i.test(ua)) {\n os.name = 'macOS';\n os.version = ua.match(/Mac OS X ([\\d_.]+)/)?.[1]?.replace(/_/g, '.');\n } else if (/Android/i.test(ua)) {\n os.name = 'Android';\n os.version = ua.match(/Android ([\\d.]+)/)?.[1];\n } else if (/iPhone OS|iPad/i.test(ua)) {\n os.name = 'iOS';\n os.version = ua.match(/OS ([\\d_]+)/)?.[1]?.replace(/_/g, '.');\n } else if (/Linux/i.test(ua)) {\n os.name = 'Linux';\n }\n\n return { browser, os, device };\n}\n\nexport function gatherContext(): EventContext {\n if (!isBrowser()) {\n return {};\n }\n\n const ua = navigator.userAgent;\n const { browser, os, device } = parseUserAgent(ua);\n\n return {\n userAgent: ua,\n locale: navigator.language,\n page: {\n url: window.location.href,\n referrer: document.referrer || undefined,\n title: document.title || undefined,\n path: window.location.pathname,\n },\n browser,\n os,\n device,\n };\n}\n\nexport function mergeContext(\n auto: EventContext,\n user?: Partial<EventContext>,\n): EventContext {\n if (!user) return auto;\n\n return {\n ...auto,\n ...user,\n page: { ...auto.page, ...user.page },\n browser: { ...auto.browser, ...user.browser },\n os: { ...auto.os, ...user.os },\n device: { ...auto.device, ...user.device },\n };\n}\n","const PREFIX = 'ba_';\n\nexport interface Storage {\n get(key: string): string | null;\n set(key: string, value: string): void;\n remove(key: string): void;\n}\n\nclass LocalStorage implements Storage {\n get(key: string): string | null {\n try {\n return localStorage.getItem(PREFIX + key);\n } catch {\n return null;\n }\n }\n\n set(key: string, value: string): void {\n try {\n localStorage.setItem(PREFIX + key, value);\n } catch {\n // localStorage unavailable or quota exceeded\n }\n }\n\n remove(key: string): void {\n try {\n localStorage.removeItem(PREFIX + key);\n } catch {\n // noop\n }\n }\n}\n\nclass MemoryStorage implements Storage {\n private store = new Map<string, string>();\n\n get(key: string): string | null {\n return this.store.get(PREFIX + key) ?? null;\n }\n\n set(key: string, value: string): void {\n this.store.set(PREFIX + key, value);\n }\n\n remove(key: string): void {\n this.store.delete(PREFIX + key);\n }\n}\n\nexport function createStorage(): Storage {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem('__ba_test__', '1');\n localStorage.removeItem('__ba_test__');\n return new LocalStorage();\n }\n } catch {\n // localStorage not available\n }\n return new MemoryStorage();\n}\n","import type {\n BoringAnalyticsConfig,\n TrackOptions,\n IdentifyOptions,\n PageOptions,\n ScreenOptions,\n GroupOptions,\n CaptureErrorOptions,\n IngestEventPayload,\n IngestErrorPayload,\n EventContext,\n} from './types';\nimport { Transport } from './transport';\nimport { EventQueue } from './queue';\nimport { SessionManager } from './session';\nimport { GlobalErrorHandler } from './error-handler';\nimport { gatherContext, mergeContext } from './context';\nimport { createStorage } from './storage';\nimport { createDebugLogger, isBrowser, now } from './utils';\n\nconst DEFAULT_ENDPOINT = 'https://api.boring.yraylabs.fun';\nconst DEFAULT_FLUSH_AT = 20;\nconst DEFAULT_FLUSH_INTERVAL = 5000;\nconst DEFAULT_MAX_RETRIES = 3;\n\nexport class BoringAnalytics {\n private queue: EventQueue;\n private session: SessionManager;\n private errorHandler: GlobalErrorHandler | null = null;\n private debug: ReturnType<typeof createDebugLogger>;\n private config: Required<\n Pick<BoringAnalyticsConfig, 'defaultProperties'>\n > & BoringAnalyticsConfig;\n private pageViewUnsubscribe: (() => void) | null = null;\n\n constructor(config: BoringAnalyticsConfig) {\n if (!config.apiKey) {\n throw new Error('BoringAnalytics: apiKey is required');\n }\n\n this.config = {\n ...config,\n defaultProperties: config.defaultProperties ?? {},\n };\n\n this.debug = createDebugLogger(config.debug ?? false);\n this.debug.log('Initializing with endpoint:', config.endpoint ?? DEFAULT_ENDPOINT);\n\n const storage = createStorage();\n this.session = new SessionManager(storage);\n\n const transport = new Transport({\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n apiKey: config.apiKey,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n onError: config.onError,\n });\n\n this.queue = new EventQueue(transport, {\n flushAt: config.flushAt ?? DEFAULT_FLUSH_AT,\n flushInterval: config.flushInterval ?? DEFAULT_FLUSH_INTERVAL,\n debug: this.debug,\n });\n\n const autoCapture = config.autoCapture ?? {};\n\n if (autoCapture.errors !== false) {\n this.errorHandler = new GlobalErrorHandler((error, source) => {\n this.captureError(error, {\n handled: false,\n metadata: { source },\n });\n });\n this.errorHandler.install();\n }\n\n if (autoCapture.pageViews && isBrowser()) {\n this.installPageViewTracking();\n }\n }\n\n // --- Public API ---\n\n /**\n * Track a named event.\n *\n * @example\n * analytics.track('button_clicked', { properties: { buttonId: 'signup' } });\n */\n track(name: string, options: TrackOptions = {}): void {\n this.enqueueEvent('TRACK', name, options.properties, options.timestamp, options.context);\n }\n\n /**\n * Identify a user with traits.\n * Sets the userId for all subsequent calls.\n *\n * @example\n * analytics.identify('user-123', { traits: { email: 'user@example.com' } });\n */\n identify(userId: string, options: IdentifyOptions = {}): void {\n this.session.setUserId(userId);\n this.enqueueEvent('IDENTIFY', 'identify', options.traits, options.timestamp, options.context);\n }\n\n /**\n * Track a page view (typically browser).\n *\n * @example\n * analytics.page('Home');\n * analytics.page('Product', { properties: { productId: '123' } });\n */\n page(name?: string, options: PageOptions = {}): void {\n const pageName = name ?? (isBrowser() ? document.title : 'Page View');\n this.enqueueEvent('PAGE', pageName, options.properties, options.timestamp, options.context);\n }\n\n /**\n * Track a screen view (typically mobile).\n */\n screen(name: string, options: ScreenOptions = {}): void {\n this.enqueueEvent('SCREEN', name, options.properties, options.timestamp, options.context);\n }\n\n /**\n * Associate a user with a group.\n */\n group(groupId: string, options: GroupOptions = {}): void {\n this.enqueueEvent('GROUP', groupId, options.traits, options.timestamp, options.context);\n }\n\n /**\n * Create an alias between two user identities.\n */\n alias(userId: string, previousId: string): void {\n this.enqueueEvent('ALIAS', 'alias', { userId, previousId });\n }\n\n /**\n * Capture an error for error monitoring.\n *\n * @example\n * try { riskyOp(); }\n * catch (err) { analytics.captureError(err, { tags: { env: 'prod' } }); }\n */\n captureError(\n error: Error | string,\n options: CaptureErrorOptions = {},\n ): void {\n const err = typeof error === 'string' ? new Error(error) : error;\n const autoContext = gatherContext();\n\n const payload: IngestErrorPayload = {\n type: err.name || 'Error',\n message: err.message,\n stackTrace: err.stack,\n level: options.level ?? 'ERROR',\n fingerprint: options.fingerprint,\n handled: options.handled ?? true,\n metadata: options.metadata,\n tags: options.tags,\n timestamp: (options.timestamp ?? new Date()).toISOString(),\n userId: this.session.getUserId() ?? undefined,\n sessionId: this.session.getSessionId(),\n context: {\n userAgent: autoContext.userAgent,\n browser: autoContext.browser?.name,\n os: autoContext.os?.name,\n device: autoContext.device?.type,\n url: autoContext.page?.url,\n release: options.release,\n },\n };\n\n this.queue.add({ kind: 'error', payload });\n }\n\n /**\n * Flush all queued events and errors immediately.\n */\n async flush(): Promise<void> {\n await this.queue.flush();\n }\n\n /**\n * Reset the current user. Clears userId, generates new anonymousId and sessionId.\n * Call this on logout.\n */\n reset(): void {\n this.session.reset();\n this.debug.log('User reset');\n }\n\n /**\n * Gracefully shut down: flush remaining events, remove global handlers.\n */\n async shutdown(): Promise<void> {\n this.debug.log('Shutting down');\n this.errorHandler?.uninstall();\n this.pageViewUnsubscribe?.();\n await this.queue.shutdown();\n }\n\n // --- Internal ---\n\n private enqueueEvent(\n type: IngestEventPayload['type'],\n name: string,\n properties?: Record<string, unknown>,\n timestamp?: Date,\n userContext?: Partial<EventContext>,\n ): void {\n const autoContext = gatherContext();\n const context = mergeContext(autoContext, userContext);\n\n const payload: IngestEventPayload = {\n type,\n name,\n properties: { ...this.config.defaultProperties, ...properties },\n timestamp: (timestamp ?? new Date()).toISOString(),\n userId: this.session.getUserId() ?? undefined,\n sessionId: this.session.getSessionId(),\n anonymousId: this.session.getAnonymousId(),\n context,\n };\n\n this.queue.add({ kind: 'event', payload });\n }\n\n private installPageViewTracking(): void {\n if (!isBrowser()) return;\n\n let lastUrl = window.location.href;\n\n const checkUrl = () => {\n const currentUrl = window.location.href;\n if (currentUrl !== lastUrl) {\n lastUrl = currentUrl;\n this.page();\n }\n };\n\n // Patch pushState/replaceState for SPA navigation\n const origPushState = history.pushState.bind(history);\n const origReplaceState = history.replaceState.bind(history);\n\n history.pushState = (...args: Parameters<typeof history.pushState>) => {\n origPushState(...args);\n checkUrl();\n };\n\n history.replaceState = (...args: Parameters<typeof history.replaceState>) => {\n origReplaceState(...args);\n checkUrl();\n };\n\n window.addEventListener('popstate', checkUrl);\n\n this.pageViewUnsubscribe = () => {\n history.pushState = origPushState;\n history.replaceState = origReplaceState;\n window.removeEventListener('popstate', checkUrl);\n };\n\n // Track initial page view\n this.page();\n }\n}\n"]}
|
package/package.json
CHANGED