@clonus/js-client 2.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/LICENSE +21 -0
- package/dist/client/autocapture.d.ts +13 -0
- package/dist/client/autocapture.d.ts.map +1 -0
- package/dist/client/client.d.ts +55 -0
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/device.d.ts +11 -0
- package/dist/client/device.d.ts.map +1 -0
- package/dist/client/event.d.ts +14 -0
- package/dist/client/event.d.ts.map +1 -0
- package/dist/client/identity.d.ts +7 -0
- package/dist/client/identity.d.ts.map +1 -0
- package/dist/client/network.d.ts +13 -0
- package/dist/client/network.d.ts.map +1 -0
- package/dist/client/options.d.ts +36 -0
- package/dist/client/options.d.ts.map +1 -0
- package/dist/client/session.d.ts +14 -0
- package/dist/client/session.d.ts.map +1 -0
- package/dist/client/storage.d.ts +19 -0
- package/dist/client/storage.d.ts.map +1 -0
- package/dist/client/user.d.ts +16 -0
- package/dist/client/user.d.ts.map +1 -0
- package/dist/clonus.umd.js +3 -0
- package/dist/clonus.umd.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +804 -0
- package/dist/index.mjs.map +1 -0
- package/dist/utils/element.d.ts +12 -0
- package/dist/utils/element.d.ts.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/logging/errors.d.ts +7 -0
- package/dist/utils/logging/errors.d.ts.map +1 -0
- package/dist/utils/logging/logger.d.ts +8 -0
- package/dist/utils/logging/logger.d.ts.map +1 -0
- package/dist/utils/storage/cookie.d.ts +7 -0
- package/dist/utils/storage/cookie.d.ts.map +1 -0
- package/dist/utils/storage/local.d.ts +7 -0
- package/dist/utils/storage/local.d.ts.map +1 -0
- package/dist/utils/user_agent.d.ts +18 -0
- package/dist/utils/user_agent.d.ts.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/client/options.ts","../src/client/network.ts","../src/client/storage.ts","../src/utils/storage/local.ts","../src/utils/storage/cookie.ts","../src/utils/logging/errors.ts","../src/client/user.ts","../src/client/identity.ts","../../../node_modules/.pnpm/uuid@13.0.0/node_modules/uuid/dist/stringify.js","../../../node_modules/.pnpm/uuid@13.0.0/node_modules/uuid/dist/rng.js","../../../node_modules/.pnpm/uuid@13.0.0/node_modules/uuid/dist/native.js","../../../node_modules/.pnpm/uuid@13.0.0/node_modules/uuid/dist/v4.js","../src/client/session.ts","../src/client/device.ts","../src/utils/user_agent.ts","../src/client/event.ts","../src/utils/element.ts","../src/client/autocapture.ts","../src/utils/logging/logger.ts","../src/client/client.ts","../src/index.ts"],"sourcesContent":["const DEFAULT_API_URL = 'https://api.clonus.io/v1';\nconst DEFAULT_FLUSH_INTERVAL = 10000;\nconst DEFAULT_FLUSH_THRESHOLD = 50;\nconst DEFAULT_SESSION_DURATION = 1800000;\n\nexport type ClonusOptions = {\n autocapture?: boolean;\n flush?: {\n interval?: number;\n threshold?: number;\n };\n session?: {\n duration?: number;\n storage?: boolean;\n };\n $sdk?: {\n version?: string;\n library?: string;\n };\n};\n\ntype BoundedNumberInput = {\n default: number;\n min: number;\n max: number;\n};\n\nexport class ClonusSDKOptions {\n private apiUrl: string;\n private autocapture: boolean;\n private flushInterval: number;\n private flushThreshold: number;\n private sessionDuration: number;\n private sessionStorageEnabled: boolean;\n private sdkVersion: string;\n private sdkLibrary: string;\n\n constructor(clonusOptions?: ClonusOptions) {\n const options = clonusOptions ?? {};\n\n this.apiUrl = DEFAULT_API_URL.endsWith('/') ? DEFAULT_API_URL : DEFAULT_API_URL + '/';\n this.autocapture = options.autocapture ?? true;\n\n this.flushInterval = this.normalizeNumberInput(options.flush?.interval, {\n default: DEFAULT_FLUSH_INTERVAL,\n min: 1000,\n max: 60000,\n });\n this.flushThreshold = this.normalizeNumberInput(options.flush?.threshold, {\n default: DEFAULT_FLUSH_THRESHOLD,\n min: 1,\n max: 500,\n });\n this.sessionDuration = this.normalizeNumberInput(options.session?.duration, {\n default: DEFAULT_SESSION_DURATION,\n min: 60000,\n max: 86400000,\n });\n this.sessionStorageEnabled = options.session?.storage ?? true;\n this.sdkVersion = options.$sdk?.version ?? '0.0.1';\n this.sdkLibrary = options.$sdk?.library ?? 'js-client';\n }\n\n getApiUrl(): string {\n return this.apiUrl;\n }\n\n getAutocapture(): boolean {\n return this.autocapture;\n }\n\n getFlushInterval(): number {\n return this.flushInterval;\n }\n\n getFlushThreshold(): number {\n return this.flushThreshold;\n }\n\n getSessionDuration(): number {\n return this.sessionDuration;\n }\n\n isSessionStorageEnabled(): boolean {\n return this.sessionStorageEnabled;\n }\n\n getSDKVersion(): string {\n return this.sdkVersion;\n }\n\n getSDKLibrary(): string {\n return this.sdkLibrary;\n }\n\n private normalizeNumberInput(input: number | undefined, bounds: BoundedNumberInput): number {\n if (input == null) return bounds.default;\n if (typeof input !== 'number' || isNaN(input) || !isFinite(input)) {\n return bounds.default;\n }\n return Math.max(Math.min(input, bounds.max), bounds.min);\n }\n}\n","const DEFAULT_TIMEOUT = 10000;\nconst DEFAULT_RETRIES = 3;\nconst DEFAULT_BACKOFF = 1000;\nconst RATE_LIMIT_THRESHOLD = 30;\n\nclass RateLimiter {\n private leakyBucket: Map<string, number> = new Map();\n private readonly threshold: number;\n\n constructor(threshold: number = 30) {\n this.threshold = threshold;\n }\n\n shouldContinue(endpoint: string): boolean {\n return this.getCount(endpoint) < this.threshold;\n }\n\n acquire(endpoint: string): void {\n this.leakyBucket.set(endpoint, this.getCount(endpoint) + 1);\n }\n\n release(endpoint: string): void {\n const count = this.getCount(endpoint);\n if (count > 0) {\n this.leakyBucket.set(endpoint, count - 1);\n }\n }\n\n private getCount(endpoint: string): number {\n return this.leakyBucket.get(endpoint) || 0;\n }\n}\n\nexport class ClonusNetwork {\n private readonly rateLimiter: RateLimiter;\n private readonly retryCodes = [408, 500, 502, 503, 504, 522, 524, 599];\n private readonly apiKey: string;\n private readonly baseUrl: string;\n\n constructor(apiKey: string, baseUrl: string) {\n if (!apiKey || typeof apiKey !== 'string') {\n throw new Error('API key is required');\n }\n this.apiKey = apiKey;\n this.baseUrl = baseUrl;\n this.rateLimiter = new RateLimiter(RATE_LIMIT_THRESHOLD);\n }\n\n async post<T>(endpoint: string, body: unknown): Promise<T> {\n const timeout = DEFAULT_TIMEOUT;\n const retries = DEFAULT_RETRIES;\n const backoff = DEFAULT_BACKOFF;\n const url = `${this.baseUrl}${endpoint}`;\n\n if (!this.rateLimiter.shouldContinue(endpoint)) {\n throw new Error('Rate limit exceeded');\n }\n\n this.rateLimiter.acquire(endpoint);\n\n try {\n return await this.fetchWithRetry(url, body, retries, backoff, timeout);\n } finally {\n this.rateLimiter.release(endpoint);\n }\n }\n\n private async fetchWithRetry<T>(\n url: string,\n body: unknown,\n retries: number,\n backoff: number,\n timeout: number,\n attempt = 1\n ): Promise<T> {\n const requestAbortController = new AbortController();\n const requestTimeoutId = setTimeout(() => requestAbortController.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n signal: requestAbortController.signal,\n keepalive: true,\n });\n\n if (!response.ok && this.shouldRetryStatus(response.status) && attempt < retries) {\n await this.waitBeforeRetry(backoff);\n return this.fetchWithRetry(url, body, retries, backoff * 2, timeout, attempt + 1);\n }\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return response.json() as Promise<T>;\n } catch (error) {\n if (attempt < retries && this.shouldRetryError(error)) {\n await this.waitBeforeRetry(backoff);\n return this.fetchWithRetry(url, body, retries, backoff * 2, timeout, attempt + 1);\n }\n\n if (error instanceof Error && error.name === 'AbortError') {\n throw new Error(`Request timeout after ${timeout}ms`);\n }\n\n throw error;\n } finally {\n clearTimeout(requestTimeoutId);\n }\n }\n\n private shouldRetryStatus(status: number): boolean {\n return this.retryCodes.includes(status);\n }\n\n private shouldRetryError(error: unknown): boolean {\n if (error instanceof Error) {\n return error.name === 'AbortError' || error.message.includes('network');\n }\n return false;\n }\n\n private waitBeforeRetry(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}\n","export interface IStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\nexport class ClonusStorage {\n constructor(\n private localStorage: IStorage,\n private cookieStorage: IStorage\n ) {}\n\n getPersistent(key: string): string | null {\n return this.localStorage.getItem(key);\n }\n\n setPersistent(key: string, value: string): void {\n this.localStorage.setItem(key, value);\n }\n\n removePersistent(key: string): void {\n this.localStorage.removeItem(key);\n }\n\n getCookie(key: string): string | null {\n return this.cookieStorage.getItem(key);\n }\n\n setCookie(key: string, value: string): void {\n this.cookieStorage.setItem(key, value);\n }\n\n removeCookie(key: string): void {\n this.cookieStorage.removeItem(key);\n }\n\n getJSON<T>(key: string): T | null {\n const json = this.getPersistent(key);\n if (!json) return null;\n\n try {\n return JSON.parse(json) as T;\n } catch {\n return null;\n }\n }\n\n setJSON<T>(key: string, value: T): void {\n this.setPersistent(key, JSON.stringify(value));\n }\n}\n","import { IStorage } from '../../client/storage';\n\nexport class LocalStorage implements IStorage {\n getItem(key: string): string | null {\n try {\n if (typeof window === 'undefined' || !window.localStorage) {\n return null;\n }\n return window.localStorage.getItem(key);\n } catch (error) {\n return null;\n }\n }\n\n setItem(key: string, value: string): void {\n try {\n if (typeof window === 'undefined' || !window.localStorage) {\n return;\n }\n window.localStorage.setItem(key, value);\n } catch (error) {\n // Storage quota exceeded or unavailable\n }\n }\n\n removeItem(key: string): void {\n try {\n if (typeof window === 'undefined' || !window.localStorage) {\n return;\n }\n window.localStorage.removeItem(key);\n } catch (error) {\n // Storage unavailable\n }\n }\n}\n","import { IStorage } from '../../client/storage';\n\nexport class CookieStorage implements IStorage {\n getItem(key: string): string | null {\n try {\n if (typeof document === 'undefined') {\n return null;\n }\n const name = key + '=';\n const decodedCookie = decodeURIComponent(document.cookie);\n const ca = decodedCookie.split(';');\n for (let i = 0; i < ca.length; i++) {\n let c = ca[i];\n while (c.charAt(0) === ' ') {\n c = c.substring(1);\n }\n if (c.indexOf(name) === 0) {\n return c.substring(name.length, c.length);\n }\n }\n return null;\n } catch (error) {\n return null;\n }\n }\n\n setItem(key: string, value: string): void {\n try {\n if (typeof document === 'undefined') {\n return;\n }\n const expires = new Date();\n expires.setFullYear(expires.getFullYear() + 1);\n document.cookie = `${key}=${value};expires=${expires.toUTCString()};path=/`;\n } catch (error) {\n // Cookie unavailable\n }\n }\n\n removeItem(key: string): void {\n try {\n if (typeof document === 'undefined') {\n return;\n }\n document.cookie = `${key}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/`;\n } catch (error) {\n // Cookie unavailable\n }\n }\n}\n","export class ClonusUninitializedError extends Error {\n constructor(message?: string) {\n super(message ?? 'Call and wait for initializeAsync() to finish first.');\n this.name = 'ClonusUninitializedError';\n Object.setPrototypeOf(this, ClonusUninitializedError.prototype);\n }\n}\n\nexport class ClonusInvalidArgumentError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ClonusInvalidArgumentError';\n Object.setPrototypeOf(this, ClonusInvalidArgumentError.prototype);\n }\n}\n","import { ClonusInvalidArgumentError } from '../utils/logging/errors';\n\nexport interface ClonusUser {\n id: string;\n email: string;\n properties?: Record<string, unknown>;\n}\n\nexport class ClonusSDKUser {\n private email: string;\n private id: string;\n private properties: Record<string, unknown>;\n\n constructor(user: ClonusUser) {\n if (!user || typeof user !== 'object') {\n throw new ClonusInvalidArgumentError('User object is required');\n }\n\n if (!user.email || typeof user.email !== 'string' || user.email.trim().length === 0) {\n throw new ClonusInvalidArgumentError('User email is required');\n }\n\n if (!user.id || typeof user.id !== 'string' || user.id.trim().length === 0) {\n throw new ClonusInvalidArgumentError('User id is required');\n }\n\n this.email = user.email.trim().toLowerCase();\n this.id = user.id.trim();\n this.properties = user.properties ?? {};\n }\n\n getEmail(): string {\n return this.email;\n }\n\n getUserId(): string {\n return this.id;\n }\n\n getProperties(): Record<string, unknown> {\n return { ...this.properties };\n }\n\n toJSON(): ClonusUser {\n return {\n id: this.id,\n email: this.email,\n properties: this.properties,\n };\n }\n}\n","import type { IClonusSDK } from './client';\n\nexport class ClonusIdentity {\n private sdk: IClonusSDK;\n\n constructor(sdk: IClonusSDK) {\n this.sdk = sdk;\n }\n\n async initAsync(): Promise<void> {\n const user = this.sdk.getUser();\n if (user.getEmail()) {\n return Promise.resolve();\n }\n\n if (this.sdk.getBrowser()) {\n return Promise.resolve();\n }\n\n try {\n await this.sdk.getNetwork().post('/identify', {\n user_id: user.getUserId(),\n user_email: user.getEmail(),\n user_properties: user.getProperties(),\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n // Error logged by network client, no need to rethrow\n }\n }\n}\n","import validate from './validate.js';\nconst byteToHex = [];\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n return (byteToHex[arr[offset + 0]] +\n byteToHex[arr[offset + 1]] +\n byteToHex[arr[offset + 2]] +\n byteToHex[arr[offset + 3]] +\n '-' +\n byteToHex[arr[offset + 4]] +\n byteToHex[arr[offset + 5]] +\n '-' +\n byteToHex[arr[offset + 6]] +\n byteToHex[arr[offset + 7]] +\n '-' +\n byteToHex[arr[offset + 8]] +\n byteToHex[arr[offset + 9]] +\n '-' +\n byteToHex[arr[offset + 10]] +\n byteToHex[arr[offset + 11]] +\n byteToHex[arr[offset + 12]] +\n byteToHex[arr[offset + 13]] +\n byteToHex[arr[offset + 14]] +\n byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n const uuid = unsafeStringify(arr, offset);\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n return uuid;\n}\nexport default stringify;\n","let getRandomValues;\nconst rnds8 = new Uint8Array(16);\nexport default function rng() {\n if (!getRandomValues) {\n if (typeof crypto === 'undefined' || !crypto.getRandomValues) {\n throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');\n }\n getRandomValues = crypto.getRandomValues.bind(crypto);\n }\n return getRandomValues(rnds8);\n}\n","const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);\nexport default { randomUUID };\n","import native from './native.js';\nimport rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nfunction _v4(options, buf, offset) {\n options = options || {};\n const rnds = options.random ?? options.rng?.() ?? rng();\n if (rnds.length < 16) {\n throw new Error('Random bytes length must be >= 16');\n }\n rnds[6] = (rnds[6] & 0x0f) | 0x40;\n rnds[8] = (rnds[8] & 0x3f) | 0x80;\n if (buf) {\n offset = offset || 0;\n if (offset < 0 || offset + 16 > buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n }\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n return buf;\n }\n return unsafeStringify(rnds);\n}\nfunction v4(options, buf, offset) {\n if (native.randomUUID && !buf && !options) {\n return native.randomUUID();\n }\n return _v4(options, buf, offset);\n}\nexport default v4;\n","import { v4 as uuidv4 } from 'uuid';\nimport type { IClonusSDK } from './client';\n\ninterface ClientSession {\n sessionId: string;\n startTime: string;\n lastActivity: string;\n expiration: number;\n}\n\nexport class ClonusSession {\n private currentSession: ClientSession | null = null;\n private readonly storageKey = 'clonus_session';\n private sdk: IClonusSDK;\n\n constructor(sdk: IClonusSDK) {\n this.sdk = sdk;\n }\n\n getOrCreateSessionId(): string {\n const activeSession = this.getActiveSession() || this.createSession();\n return activeSession.sessionId;\n }\n\n private getActiveSession(): ClientSession | null {\n const cachedOrStoredSession = this.currentSession || this.loadFromStorage();\n if (!cachedOrStoredSession) return null;\n\n const sessionDuration = this.sdk.getOptions().getSessionDuration();\n if (cachedOrStoredSession.expiration > Date.now()) {\n return this.extendSession(cachedOrStoredSession, sessionDuration);\n }\n\n return null;\n }\n\n private createSession(): ClientSession {\n const currentTimestamp = new Date().toISOString();\n const sessionDuration = this.sdk.getOptions().getSessionDuration();\n\n const newSession: ClientSession = {\n sessionId: uuidv4(),\n startTime: currentTimestamp,\n lastActivity: currentTimestamp,\n expiration: Date.now() + sessionDuration,\n };\n\n this.currentSession = newSession;\n this.persistToStorage(newSession);\n return newSession;\n }\n\n private extendSession(session: ClientSession, duration: number): ClientSession {\n const extendedSession = {\n ...session,\n lastActivity: new Date().toISOString(),\n expiration: Date.now() + duration,\n };\n\n this.currentSession = extendedSession;\n this.persistToStorage(extendedSession);\n return extendedSession;\n }\n\n private loadFromStorage(): ClientSession | null {\n const storedSessionJson = this.sdk.getStorage().getPersistent(this.storageKey);\n if (!storedSessionJson) return null;\n\n try {\n const session = JSON.parse(storedSessionJson) as ClientSession;\n return Date.now() < session.expiration ? session : null;\n } catch {\n return null;\n }\n }\n\n private persistToStorage(session: ClientSession): void {\n if (!this.sdk.getOptions().isSessionStorageEnabled()) return;\n\n this.sdk.getStorage().setPersistent(this.storageKey, JSON.stringify(session));\n this.sdk.getStorage().setCookie(this.storageKey, session.sessionId);\n }\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport type { IClonusSDK } from './client';\n\nexport class ClonusDevice {\n private deviceId?: string;\n private readonly storageKey = 'clonus_device_id';\n private sdk: IClonusSDK;\n\n constructor(sdk: IClonusSDK) {\n this.sdk = sdk;\n }\n\n getOrCreateDeviceId(): string {\n if (this.deviceId) {\n return this.deviceId;\n }\n\n const stored = this.loadFromStorage();\n if (stored) {\n this.deviceId = stored;\n return stored;\n }\n\n const newId = uuidv4();\n this.deviceId = newId;\n this.persistToStorage(newId);\n return newId;\n }\n\n private loadFromStorage(): string | null {\n return (\n this.sdk.getStorage().getCookie(this.storageKey) ||\n this.sdk.getStorage().getPersistent(this.storageKey)\n );\n }\n\n private persistToStorage(id: string): void {\n this.sdk.getStorage().setCookie(this.storageKey, id);\n this.sdk.getStorage().setPersistent(this.storageKey, id);\n }\n}\n","/**\n * User agent parsing utilities\n */\n\nexport interface UserAgentInfo {\n browser_name: string;\n browser_version: string;\n os_name: string;\n os_version: string;\n device_brand: string;\n device_model: string;\n}\n\nexport class UserAgentParser {\n parse(userAgent: string): UserAgentInfo {\n const browser = this.browser(userAgent);\n const os = this.os(userAgent);\n const device = this.device(userAgent);\n\n return {\n browser_name: browser.name,\n browser_version: browser.version,\n os_name: os.name,\n os_version: os.version,\n device_brand: device.brand,\n device_model: device.model,\n };\n }\n\n private browser(ua: string): { name: string; version: string } {\n let name = 'Unknown';\n let version = 'Unknown';\n let match;\n\n if (ua.includes('Firefox/')) {\n name = 'Firefox';\n match = ua.match(/Firefox\\/(\\d+\\.\\d+)/);\n version = match ? match[1] : 'Unknown';\n } else if (ua.includes('Edg/')) {\n name = 'Edge';\n match = ua.match(/Edg\\/(\\d+\\.\\d+)/);\n version = match ? match[1] : 'Unknown';\n } else if (ua.includes('Chrome/')) {\n name = 'Chrome';\n match = ua.match(/Chrome\\/(\\d+\\.\\d+)/);\n version = match ? match[1] : 'Unknown';\n } else if (ua.includes('Safari/') && !ua.includes('Chrome')) {\n name = 'Safari';\n match = ua.match(/Version\\/(\\d+\\.\\d+)/);\n version = match ? match[1] : 'Unknown';\n } else if (ua.includes('Opera/') || ua.includes('OPR/')) {\n name = 'Opera';\n match = ua.match(/OPR\\/(\\d+\\.\\d+)/);\n version = match ? match[1] : 'Unknown';\n }\n\n return { name, version };\n }\n\n private os(ua: string): { name: string; version: string } {\n let name = 'Unknown';\n let version = 'Unknown';\n let match;\n\n if (ua.includes('Windows NT')) {\n name = 'Windows';\n match = ua.match(/Windows NT (\\d+\\.\\d+)/);\n if (match) {\n const ver = match[1];\n if (ver === '10.0') version = '10';\n else if (ver === '6.3') version = '8.1';\n else if (ver === '6.2') version = '8';\n else if (ver === '6.1') version = '7';\n else version = ver;\n }\n } else if (ua.includes('Mac OS X')) {\n name = 'Mac OS X';\n match = ua.match(/Mac OS X (\\d+[._]\\d+[._]?\\d*)/);\n version = match ? match[1].replace(/_/g, '.') : 'Unknown';\n } else if (ua.includes('Android')) {\n name = 'Android';\n match = ua.match(/Android (\\d+\\.\\d+)/);\n version = match ? match[1] : 'Unknown';\n } else if (ua.includes('iPhone') || ua.includes('iPad')) {\n name = 'iOS';\n match = ua.match(/OS (\\d+_\\d+)/);\n version = match ? match[1].replace(/_/g, '.') : 'Unknown';\n } else if (ua.includes('Linux')) {\n name = 'Linux';\n }\n\n return { name, version };\n }\n\n private device(ua: string): { type: string; brand: string; model: string } {\n let brand = 'Unknown';\n let model = 'Unknown';\n let match;\n\n // Apple devices\n if (ua.includes('iPhone')) {\n brand = 'Apple';\n model = 'iPhone';\n } else if (ua.includes('iPad')) {\n brand = 'Apple';\n model = 'iPad';\n } else if (ua.includes('Macintosh') || ua.includes('Mac OS X')) {\n brand = 'Apple';\n model = 'Mac';\n }\n // Samsung\n else if ((match = ua.match(/Samsung|SM-[A-Z0-9]+|GT-[A-Z0-9]+/))) {\n brand = 'Samsung';\n const modelMatch = ua.match(/SM-([A-Z0-9]+)|GT-([A-Z0-9]+)/);\n model = modelMatch ? modelMatch[1] || modelMatch[2] : 'Galaxy';\n }\n // Google Pixel\n else if (ua.includes('Pixel')) {\n brand = 'Google';\n match = ua.match(/Pixel (\\d+[a-zA-Z]*)/);\n model = match ? `Pixel ${match[1]}` : 'Pixel';\n }\n // Huawei\n else if (ua.includes('Huawei') || ua.includes('HUAWEI')) {\n brand = 'Huawei';\n match = ua.match(/([A-Z]{3}-[A-Z0-9]+)/);\n model = match ? match[1] : 'Huawei';\n }\n // Xiaomi\n else if (ua.includes('Xiaomi') || ua.includes('Mi ') || ua.includes('Redmi')) {\n brand = 'Xiaomi';\n match = ua.match(/Mi ([A-Z0-9 ]+)|Redmi ([A-Z0-9 ]+)/);\n model = match ? match[1] || match[2] || 'Mi' : 'Mi';\n }\n // OnePlus\n else if (ua.includes('OnePlus') || ua.includes('ONEPLUS')) {\n brand = 'OnePlus';\n match = ua.match(/OnePlus ([A-Z0-9]+)/);\n model = match ? match[1] : 'OnePlus';\n }\n // Windows PC\n else if (ua.includes('Windows')) {\n brand = 'PC';\n model = 'Windows';\n }\n // Linux\n else if (ua.includes('Linux') && !ua.includes('Android')) {\n brand = 'PC';\n model = 'Linux';\n }\n // Android (generic)\n else if (ua.includes('Android')) {\n brand = 'Android';\n model = 'Android Device';\n }\n\n // Determine device type\n let type = 'Desktop';\n if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) {\n type = 'Tablet';\n } else if (\n /Mobile|Android|iP(hone|od)|IEMobile|BlackBerry|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test(\n ua\n )\n ) {\n type = 'Mobile';\n }\n\n return { type, brand, model };\n }\n}\n","import type { IClonusSDK } from './client';\nimport type { ClonusStorage } from './storage';\nimport { UserAgentParser } from '../utils/user_agent';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type LogLevel = 'info' | 'warn' | 'error';\n\n// ============================================================================\n// Interfaces\n// ============================================================================\n\ninterface EventPayload {\n user_id: string;\n device_id: string;\n session_id: string;\n message: string;\n level: LogLevel;\n timestamp: string;\n properties?: Record<string, unknown>;\n metadata: {\n sdk_version: string;\n sdk_library: string;\n };\n}\n\ninterface FailedRetry {\n endpoint: string;\n body: unknown;\n timestamp: number;\n retryCount: number;\n}\n\n// ============================================================================\n// EventQueue - Manages event queue with localStorage persistence\n// ============================================================================\n\nclass EventQueue {\n private queue: EventPayload[] = [];\n private readonly storageKey = 'clonus_event_queue';\n private readonly MAX_QUEUE_SIZE = 1000;\n\n constructor(private storage: ClonusStorage) {\n this.loadFromStorage();\n }\n\n enqueue(event: EventPayload): void {\n if (this.queue.length >= this.MAX_QUEUE_SIZE) {\n this.queue.shift();\n }\n this.queue.push(event);\n this.persistToStorage();\n }\n\n getAll(): EventPayload[] {\n return [...this.queue];\n }\n\n clear(): void {\n this.queue = [];\n this.persistToStorage();\n }\n\n size(): number {\n return this.queue.length;\n }\n\n private loadFromStorage(): void {\n const queue = this.storage.getJSON<EventPayload[]>(this.storageKey);\n this.queue = queue ? queue.slice(0, this.MAX_QUEUE_SIZE) : [];\n }\n\n private persistToStorage(): void {\n this.storage.setJSON(this.storageKey, this.queue);\n }\n}\n\n// ============================================================================\n// EventRetry - Manages failed request retries with localStorage persistence\n// ============================================================================\n\nclass EventRetry {\n private failedRetries: FailedRetry[] = [];\n private readonly storageKey = 'clonus_failed_requests';\n private readonly MAX_FAILED_REQUESTS = 100;\n private readonly MAX_AGE_MS = 5 * 24 * 60 * 60 * 1000; // 5 days\n private readonly MAX_ATTEMPTS = 5;\n\n constructor(private storage: ClonusStorage) {\n this.loadFromStorage();\n }\n\n add(endpoint: string, body: unknown): void {\n const retry: FailedRetry = {\n endpoint,\n body,\n timestamp: Date.now(),\n retryCount: 0,\n };\n\n if (this.failedRetries.length >= this.MAX_FAILED_REQUESTS) {\n this.failedRetries.shift();\n }\n\n this.failedRetries.push(retry);\n this.persistToStorage();\n }\n\n getAll(): FailedRetry[] {\n if (this.failedRetries.length === 0) return [];\n\n const now = Date.now();\n return this.failedRetries.filter(\n retry => now - retry.timestamp <= this.MAX_AGE_MS && retry.retryCount < this.MAX_ATTEMPTS\n );\n }\n\n clearAll(): void {\n this.failedRetries = [];\n this.persistToStorage();\n }\n\n private loadFromStorage(): void {\n const failed = this.storage.getJSON<FailedRetry[]>(this.storageKey);\n this.failedRetries = failed ? failed.slice(0, this.MAX_FAILED_REQUESTS) : [];\n }\n\n private persistToStorage(): void {\n this.storage.setJSON(this.storageKey, this.failedRetries);\n }\n}\n\n// ============================================================================\n// ClonusEvent - Main event tracking class\n// ============================================================================\n\nexport class ClonusEvent {\n private flushTimer?: ReturnType<typeof setTimeout>;\n private sdk: IClonusSDK;\n private queue: EventQueue;\n private retry: EventRetry;\n private ua: UserAgentParser;\n\n constructor(sdk: IClonusSDK) {\n this.sdk = sdk;\n this.queue = new EventQueue(this.sdk.getStorage());\n this.retry = new EventRetry(this.sdk.getStorage());\n this.ua = new UserAgentParser();\n\n const interval = this.sdk.getOptions().getFlushInterval();\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, interval);\n }\n\n enqueue(level: LogLevel, message: string, properties?: Record<string, unknown>): void {\n this.sdk.getLogger().swallow('enqueue', () => {\n if (!this.sdk.getBrowser()) return;\n\n const uaInfo = this.ua.parse(navigator.userAgent);\n\n this.queue.enqueue({\n user_id: this.sdk.getUser().getUserId(),\n device_id: this.sdk.getDevice().getOrCreateDeviceId(),\n session_id: this.sdk.getSession().getOrCreateSessionId(),\n message,\n level,\n properties: {\n $page_url: window.location.href,\n $page_host: window.location.hostname,\n $page_path: window.location.pathname,\n $page_title: document.title,\n $page_referrer: document.referrer,\n $browser_name: uaInfo.browser_name,\n $browser_version: uaInfo.browser_version,\n $os_name: uaInfo.os_name,\n $os_version: uaInfo.os_version,\n $device_brand: uaInfo.device_brand,\n $device_model: uaInfo.device_model,\n $timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n $language: navigator.language,\n ...properties,\n },\n timestamp: new Date().toISOString(),\n metadata: {\n sdk_version: this.sdk.getOptions().getSDKVersion(),\n sdk_library: this.sdk.getOptions().getSDKLibrary(),\n },\n });\n\n const threshold = this.sdk.getOptions().getFlushThreshold();\n if (this.queue.size() >= threshold) {\n void this.flush();\n }\n });\n }\n\n async flush(): Promise<void> {\n // Retry failed requests\n const retries = this.retry.getAll();\n if (retries.length > 0) {\n this.retry.clearAll();\n\n for (const retry of retries) {\n try {\n await this.sdk.getNetwork().post(retry.endpoint, retry.body);\n } catch {\n this.retry.add(retry.endpoint, retry.body);\n }\n }\n }\n\n // Flush current queue\n const queues = this.queue.getAll();\n if (queues.length === 0) return;\n\n this.queue.clear();\n\n try {\n await this.sdk.getNetwork().post('/events', { events: queues });\n } catch {\n this.retry.add('/events', { events: queues });\n }\n }\n\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = undefined;\n }\n }\n}\n","/**\n * DOM element utilities for interaction tracking and natural language description generation\n */\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nconst CLICKABLE_TAGS = new Set(['button', 'a', 'input', 'select', 'textarea']);\nconst CLICKABLE_ROLES = new Set([\n 'button',\n 'link',\n 'menuitem',\n 'tab',\n 'checkbox',\n 'radio',\n 'switch',\n]);\nconst CLICKABLE_ATTRS = ['onclick', 'data-action'];\nconst CHANGE_TYPES = new Set(['checkbox', 'radio', 'file', 'select']);\n\nconst MAX_TEXT_LENGTH = 100;\n\n// =============================================================================\n// Element Tracking Utilities\n// =============================================================================\n\nexport function shouldTrackClick(element: HTMLElement): boolean {\n const tag = element.tagName.toLowerCase();\n const role = element.getAttribute('role');\n const cursor = window.getComputedStyle(element).cursor;\n\n return (\n CLICKABLE_TAGS.has(tag) ||\n (!!role && CLICKABLE_ROLES.has(role)) ||\n cursor === 'pointer' ||\n CLICKABLE_ATTRS.some(attr => element.hasAttribute(attr))\n );\n}\n\nexport function shouldTrackChange(element: HTMLElement): boolean {\n const tag = element.tagName.toLowerCase();\n if (CHANGE_TYPES.has(tag)) return true;\n if (tag === 'input') return CHANGE_TYPES.has((element as HTMLInputElement).type);\n return false;\n}\n\n// =============================================================================\n// Natural Language Description Generator\n// =============================================================================\n\nexport type InteractionType = 'click' | 'submit' | 'change' | 'pageview';\n\n/**\n * Generates a natural language description of a user interaction.\n * Used for semantic search and LLM-based intent analysis.\n */\nexport function describeInteraction(type: InteractionType, element?: HTMLElement): string {\n if (type === 'pageview') {\n const title = document.title?.trim();\n const path = window.location.pathname;\n if (title) {\n return `User viewed \"${title}\" page`;\n }\n return `User viewed page at ${path}`;\n }\n\n if (!element) {\n return `User performed ${type}`;\n }\n\n const tag = element.tagName.toLowerCase();\n const text = getElementText(element);\n const label = getElementLabel(element);\n const identifier = text || label || getElementIdentifier(element);\n\n switch (type) {\n case 'click':\n return describeClick(tag, identifier, element);\n case 'submit':\n return describeSubmit(element);\n case 'change':\n return describeChange(tag, identifier, element);\n default:\n return `User interacted with ${identifier || tag}`;\n }\n}\n\nfunction describeClick(tag: string, identifier: string | null, element: HTMLElement): string {\n const role = element.getAttribute('role');\n\n if (tag === 'a' || role === 'link') {\n return identifier ? `User clicked \"${identifier}\" link` : 'User clicked a link';\n }\n\n if (tag === 'button' || role === 'button') {\n return identifier ? `User clicked \"${identifier}\" button` : 'User clicked a button';\n }\n\n if (tag === 'input') {\n const type = (element as HTMLInputElement).type;\n if (type === 'submit') {\n return identifier ? `User clicked \"${identifier}\" submit button` : 'User clicked submit';\n }\n if (type === 'checkbox') {\n return identifier ? `User toggled \"${identifier}\" checkbox` : 'User toggled a checkbox';\n }\n if (type === 'radio') {\n return identifier ? `User selected \"${identifier}\" option` : 'User selected a radio option';\n }\n }\n\n return identifier ? `User clicked on \"${identifier}\"` : `User clicked on ${tag} element`;\n}\n\nfunction describeSubmit(element: HTMLElement): string {\n const formName = element.getAttribute('name') || element.getAttribute('id');\n const action = element.getAttribute('action');\n\n if (formName) {\n return `User submitted \"${formName}\" form`;\n }\n if (action) {\n const actionPath = new URL(action, window.location.origin).pathname;\n return `User submitted form to ${actionPath}`;\n }\n return 'User submitted a form';\n}\n\nfunction describeChange(tag: string, identifier: string | null, element: HTMLElement): string {\n if (tag === 'select') {\n return identifier\n ? `User changed \"${identifier}\" selection`\n : 'User changed a dropdown selection';\n }\n\n if (tag === 'input') {\n const type = (element as HTMLInputElement).type;\n if (type === 'file') {\n return identifier ? `User selected file for \"${identifier}\"` : 'User selected a file';\n }\n if (type === 'checkbox') {\n return identifier ? `User changed \"${identifier}\" checkbox` : 'User changed a checkbox';\n }\n if (type === 'radio') {\n return identifier ? `User selected \"${identifier}\" option` : 'User selected a radio option';\n }\n }\n\n return identifier ? `User changed \"${identifier}\" field` : 'User changed a form field';\n}\n\nfunction getElementText(element: HTMLElement): string | null {\n const text = element.innerText?.trim();\n if (text && text.length > 0 && text.length <= MAX_TEXT_LENGTH) {\n return text.split('\\n')[0].trim();\n }\n return null;\n}\n\nfunction getElementLabel(element: HTMLElement): string | null {\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel;\n\n const title = element.getAttribute('title');\n if (title) return title;\n\n const id = element.getAttribute('id');\n if (id) {\n const label = document.querySelector(`label[for=\"${id}\"]`);\n if (label?.textContent) return label.textContent.trim();\n }\n\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n const placeholder = element.placeholder;\n if (placeholder) return placeholder;\n }\n\n return null;\n}\n\nfunction getElementIdentifier(element: HTMLElement): string | null {\n const name = element.getAttribute('name');\n if (name) return name;\n\n const id = element.getAttribute('id');\n if (id && !id.match(/^[a-f0-9-]{20,}$/i)) {\n return id;\n }\n\n const dataTestId = element.getAttribute('data-testid') || element.getAttribute('data-test-id');\n if (dataTestId) return dataTestId;\n\n return null;\n}\n","import type { IClonusSDK } from './client';\nimport { shouldTrackClick, shouldTrackChange, describeInteraction } from '../utils/element';\n\nexport class ClonusAutoCapture {\n private sdk: IClonusSDK;\n private cleanupCallbacks: Array<() => void> = [];\n private trackedChanges = new WeakSet<HTMLElement>();\n\n constructor(sdk: IClonusSDK) {\n this.sdk = sdk;\n }\n\n public init(): void {\n this.setupAutoCapture();\n this.setupOnlineListener();\n this.setupShutdownListeners();\n }\n\n private setupAutoCapture(): void {\n if (!this.sdk.getOptions().getAutocapture()) {\n return;\n }\n\n // Interaction tracking\n const handleClick = (event: MouseEvent) => {\n const element = event.target as HTMLElement;\n if (shouldTrackClick(element)) {\n this.sdk.getLogger().swallow('click', () => {\n const message = describeInteraction('click', element);\n this.sdk.getEvent().enqueue('info', message, { $autocapture: 'click' });\n });\n }\n };\n\n const handleSubmit = (event: SubmitEvent) => {\n const element = event.target as HTMLFormElement;\n this.sdk.getLogger().swallow('submit', () => {\n const message = describeInteraction('submit', element);\n this.sdk.getEvent().enqueue('info', message, { $autocapture: 'submit' });\n });\n };\n\n const handleChange = (event: Event) => {\n const element = event.target as HTMLElement;\n\n if (shouldTrackChange(element)) {\n if (!this.trackedChanges.has(element)) {\n this.trackedChanges.add(element);\n this.sdk.getLogger().swallow('change', () => {\n const message = describeInteraction('change', element);\n this.sdk.getEvent().enqueue('info', message, { $autocapture: 'change' });\n });\n }\n }\n };\n\n const handlePage = () => {\n this.sdk.getLogger().swallow('pageview', () => {\n const message = describeInteraction('pageview');\n this.sdk.getEvent().enqueue('info', message, { $autocapture: 'pageview' });\n });\n };\n\n handlePage();\n\n const originalHistoryPushState = history.pushState;\n const originalHistoryReplaceState = history.replaceState;\n\n history.pushState = (...args) => {\n originalHistoryPushState.apply(history, args);\n handlePage();\n };\n\n history.replaceState = (...args) => {\n originalHistoryReplaceState.apply(history, args);\n handlePage();\n };\n\n window.addEventListener('popstate', handlePage);\n document.addEventListener('click', handleClick, true);\n document.addEventListener('submit', handleSubmit, true);\n document.addEventListener('change', handleChange, true);\n\n this.cleanupCallbacks.push(() => {\n history.pushState = originalHistoryPushState;\n history.replaceState = originalHistoryReplaceState;\n window.removeEventListener('popstate', handlePage);\n document.removeEventListener('click', handleClick, true);\n document.removeEventListener('submit', handleSubmit, true);\n document.removeEventListener('change', handleChange, true);\n });\n }\n\n private setupOnlineListener(): void {\n const handleNetworkOnline = () => {\n this.sdk.getLogger().swallow('flush', () => {\n void this.sdk.getEvent().flush();\n });\n };\n\n window.addEventListener('online', handleNetworkOnline);\n\n this.cleanupCallbacks.push(() => {\n window.removeEventListener('online', handleNetworkOnline);\n });\n }\n\n private setupShutdownListeners(): void {\n const flushEventsOnShutdown = () => void this.sdk.getEvent().flush();\n const handleVisibilityChange = () => {\n if (document.visibilityState === 'hidden') {\n void this.sdk.getEvent().flush();\n }\n };\n\n window.addEventListener('beforeunload', flushEventsOnShutdown);\n window.addEventListener('pagehide', flushEventsOnShutdown);\n\n if (typeof document !== 'undefined' && typeof document.addEventListener === 'function') {\n document.addEventListener('visibilitychange', handleVisibilityChange);\n }\n\n this.cleanupCallbacks.push(() => {\n window.removeEventListener('beforeunload', flushEventsOnShutdown);\n window.removeEventListener('pagehide', flushEventsOnShutdown);\n if (typeof document !== 'undefined' && typeof document.removeEventListener === 'function') {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n }\n });\n }\n\n public destroy(): void {\n this.cleanupCallbacks.forEach(cleanupFn => cleanupFn());\n this.cleanupCallbacks = [];\n }\n}\n","import { ClonusInvalidArgumentError, ClonusUninitializedError } from './errors';\n\nexport class Logger {\n private seen = new Set<string>();\n\n capture<T>(tag: string, task: () => T, recover: () => T): T {\n try {\n const result = task();\n\n if (result instanceof Promise) {\n return result.catch((error: unknown) => {\n return this.onCaught(tag, error, recover);\n }) as unknown as T;\n }\n\n return result;\n } catch (error) {\n return this.onCaught(tag, error, recover);\n }\n }\n\n swallow<T>(tag: string, task: () => T): void {\n this.capture(tag, task, () => undefined as T);\n }\n\n private logError(tag: string, error: unknown): void {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorName = error instanceof Error ? error.name : 'Error';\n\n if (this.seen.has(errorName)) return;\n this.seen.add(errorName);\n\n // eslint-disable-next-line no-console\n console.error(`[Clonus] ${tag}:`, errorMessage);\n }\n\n private onCaught<T>(tag: string, error: unknown, recover: () => T): T {\n if (error instanceof ClonusUninitializedError || error instanceof ClonusInvalidArgumentError) {\n throw error;\n }\n\n this.logError(tag, error);\n return recover();\n }\n}\n","import { ClonusOptions, ClonusSDKOptions } from './options';\nimport { ClonusNetwork } from './network';\nimport { ClonusStorage } from './storage';\nimport { LocalStorage } from '../utils/storage/local';\nimport { CookieStorage } from '../utils/storage/cookie';\nimport { ClonusUser, ClonusSDKUser } from './user';\nimport { ClonusIdentity } from './identity';\nimport { ClonusSession } from './session';\nimport { ClonusDevice } from './device';\nimport { ClonusEvent, LogLevel } from './event';\nimport { ClonusAutoCapture } from './autocapture';\nimport { Logger } from '../utils/logging/logger';\nimport { ClonusInvalidArgumentError, ClonusUninitializedError } from '../utils/logging/errors';\n\nexport interface IClonusSDK {\n initializeAsync(): Promise<void>;\n info(message: string, properties?: Record<string, unknown>): void;\n warn(message: string, properties?: Record<string, unknown>): void;\n error(message: string, properties?: Record<string, unknown>): void;\n shutdown(): Promise<void>;\n getUser(): ClonusSDKUser;\n getOptions(): ClonusSDKOptions;\n getDevice(): ClonusDevice;\n getSession(): ClonusSession;\n getEvent(): ClonusEvent;\n getNetwork(): ClonusNetwork;\n getStorage(): ClonusStorage;\n getLogger(): Logger;\n getBrowser(): boolean;\n}\n\nexport class ClonusClient implements IClonusSDK {\n private readonly logger: Logger;\n private readonly network: ClonusNetwork;\n private readonly storage: ClonusStorage;\n private readonly options: ClonusSDKOptions;\n private readonly user: ClonusSDKUser;\n private readonly identity: ClonusIdentity;\n private readonly device: ClonusDevice;\n private readonly session: ClonusSession;\n private readonly event: ClonusEvent;\n private readonly autocapture: ClonusAutoCapture;\n private readonly _browser: boolean;\n private initialized = false;\n\n getLogger(): Logger {\n return this.logger;\n }\n\n getNetwork(): ClonusNetwork {\n return this.network;\n }\n\n getStorage(): ClonusStorage {\n return this.storage;\n }\n\n getOptions(): ClonusSDKOptions {\n return this.options;\n }\n\n getUser(): ClonusSDKUser {\n return this.user;\n }\n\n getDevice(): ClonusDevice {\n return this.device;\n }\n\n getSession(): ClonusSession {\n return this.session;\n }\n\n getEvent(): ClonusEvent {\n return this.event;\n }\n\n getBrowser(): boolean {\n return this._browser;\n }\n\n constructor(apikey: string, user: ClonusUser, options?: ClonusOptions) {\n if (!apikey || typeof apikey !== 'string' || apikey.trim().length < 10) {\n throw new ClonusInvalidArgumentError(\n 'Invalid API key. Must be a non-empty string with at least 10 characters.'\n );\n }\n\n this._browser =\n typeof window !== 'undefined' &&\n typeof document !== 'undefined' &&\n typeof navigator !== 'undefined';\n\n this.logger = new Logger();\n this.user = new ClonusSDKUser(user);\n this.options = new ClonusSDKOptions(options);\n\n // Initialize all components\n this.network = new ClonusNetwork(apikey, this.options.getApiUrl());\n this.storage = new ClonusStorage(new LocalStorage(), new CookieStorage());\n\n this.identity = new ClonusIdentity(this);\n this.session = new ClonusSession(this);\n this.device = new ClonusDevice(this);\n this.event = new ClonusEvent(this);\n this.autocapture = new ClonusAutoCapture(this);\n\n // Setup browser features only if in browser environment\n if (this._browser) {\n this.autocapture.init();\n }\n }\n\n async initializeAsync(): Promise<void> {\n return this.logger.capture(\n 'initializeAsync',\n async () => {\n await this.identity.initAsync();\n this.initialized = true;\n },\n () => {\n this.initialized = true;\n return Promise.resolve();\n }\n );\n }\n\n info(message: string, properties?: Record<string, unknown>): void {\n this._log('info', message, properties);\n }\n\n warn(message: string, properties?: Record<string, unknown>): void {\n this._log('warn', message, properties);\n }\n\n error(message: string, properties?: Record<string, unknown>): void {\n this._log('error', message, properties);\n }\n\n private _log(level: LogLevel, message: string, properties?: Record<string, unknown>): void {\n this.logger.swallow('log', () => {\n if (!this.initialized) {\n throw new ClonusUninitializedError('Must call initializeAsync() before logging.');\n }\n\n if (!message || typeof message !== 'string') {\n return;\n }\n\n const normalizedMessage = message.length > 1000 ? message.substring(0, 1000) : message;\n this.event.enqueue(level, normalizedMessage, properties ?? {});\n });\n }\n\n async shutdown(): Promise<void> {\n return this.logger.capture(\n 'shutdown',\n async () => {\n this.autocapture.destroy();\n this.event.destroy();\n await this.event.flush();\n },\n async () => {}\n );\n }\n}\n","/**\n * Clonus Analytics SDK - Semantic Event Logging\n *\n * @example\n * ```typescript\n * import { ClonusClient } from '@clonus/analytics-sdk';\n *\n * // Initialize with user\n * const client = new ClonusClient('your_api_key', {\n * email: 'user@example.com',\n * properties: { name: 'John Doe', plan: 'premium' }\n * }, {\n * autocapture: { page: true, click: true }\n * });\n *\n * // Log events with natural language\n * client.info('User viewed pricing page');\n * client.info('User added premium plan to cart', { plan_id: 'premium' });\n * client.warn('User credit limit approaching', { limit: 500 });\n * client.error('Payment declined', { error_code: 'insufficient_funds' });\n * ```\n */\n\nimport { ClonusClient } from './client/client';\n\nexport { ClonusClient } from './client/client';\nexport type { IClonusSDK } from './client/client';\nexport type { ClonusUser } from './client/user';\nexport type { ClonusOptions } from './client/options';\nexport type { LogLevel } from './client/event';\n\n// Attach to window for browser usage\nif (typeof window !== 'undefined') {\n (window as typeof window & { ClonusClient: typeof ClonusClient }).ClonusClient = ClonusClient;\n}\n"],"names":["DEFAULT_API_URL","ClonusSDKOptions","clonusOptions","options","input","bounds","DEFAULT_TIMEOUT","DEFAULT_RETRIES","DEFAULT_BACKOFF","RATE_LIMIT_THRESHOLD","RateLimiter","threshold","endpoint","count","ClonusNetwork","apiKey","baseUrl","body","timeout","retries","backoff","url","attempt","requestAbortController","requestTimeoutId","response","error","status","ms","resolve","ClonusStorage","localStorage","cookieStorage","key","value","json","LocalStorage","CookieStorage","name","ca","i","c","expires","ClonusUninitializedError","message","ClonusInvalidArgumentError","ClonusSDKUser","user","ClonusIdentity","sdk","byteToHex","unsafeStringify","arr","offset","getRandomValues","rnds8","rng","randomUUID","native","_v4","buf","rnds","v4","ClonusSession","cachedOrStoredSession","sessionDuration","currentTimestamp","newSession","uuidv4","session","duration","extendedSession","storedSessionJson","ClonusDevice","stored","newId","id","UserAgentParser","userAgent","browser","os","device","ua","version","match","ver","brand","model","modelMatch","type","EventQueue","storage","event","queue","EventRetry","retry","now","failed","ClonusEvent","interval","level","properties","uaInfo","queues","CLICKABLE_TAGS","CLICKABLE_ROLES","CLICKABLE_ATTRS","CHANGE_TYPES","MAX_TEXT_LENGTH","shouldTrackClick","element","tag","role","cursor","attr","shouldTrackChange","describeInteraction","title","path","text","getElementText","label","getElementLabel","identifier","getElementIdentifier","describeClick","describeSubmit","describeChange","formName","action","ariaLabel","placeholder","dataTestId","ClonusAutoCapture","handleClick","handleSubmit","handleChange","handlePage","originalHistoryPushState","originalHistoryReplaceState","args","handleNetworkOnline","flushEventsOnShutdown","handleVisibilityChange","cleanupFn","Logger","task","recover","result","errorMessage","errorName","ClonusClient","apikey","normalizedMessage"],"mappings":"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","x_google_ignoreList":[8,9,10,11]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM element utilities for interaction tracking and natural language description generation
|
|
3
|
+
*/
|
|
4
|
+
export declare function shouldTrackClick(element: HTMLElement): boolean;
|
|
5
|
+
export declare function shouldTrackChange(element: HTMLElement): boolean;
|
|
6
|
+
export type InteractionType = 'click' | 'submit' | 'change' | 'pageview';
|
|
7
|
+
/**
|
|
8
|
+
* Generates a natural language description of a user interaction.
|
|
9
|
+
* Used for semantic search and LLM-based intent analysis.
|
|
10
|
+
*/
|
|
11
|
+
export declare function describeInteraction(type: InteractionType, element?: HTMLElement): string;
|
|
12
|
+
//# sourceMappingURL=element.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../../src/utils/element.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyBH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAW9D;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAK/D;AAMD,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CA6BxF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAExF,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/utils/logging/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,CAAC,EAAE,MAAM;CAK7B;AAED,qBAAa,0BAA2B,SAAQ,KAAK;gBACvC,OAAO,EAAE,MAAM;CAK5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logging/logger.ts"],"names":[],"mappings":"AAEA,qBAAa,MAAM;IACjB,OAAO,CAAC,IAAI,CAAqB;IAEjC,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC;IAgB3D,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,IAAI;IAI5C,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,QAAQ;CAQjB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookie.d.ts","sourceRoot":"","sources":["../../../src/utils/storage/cookie.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,qBAAa,aAAc,YAAW,QAAQ;IAC5C,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAuBnC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAazC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAU9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../../src/utils/storage/local.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,qBAAa,YAAa,YAAW,QAAQ;IAC3C,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAWnC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAWzC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAU9B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User agent parsing utilities
|
|
3
|
+
*/
|
|
4
|
+
export interface UserAgentInfo {
|
|
5
|
+
browser_name: string;
|
|
6
|
+
browser_version: string;
|
|
7
|
+
os_name: string;
|
|
8
|
+
os_version: string;
|
|
9
|
+
device_brand: string;
|
|
10
|
+
device_model: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class UserAgentParser {
|
|
13
|
+
parse(userAgent: string): UserAgentInfo;
|
|
14
|
+
private browser;
|
|
15
|
+
private os;
|
|
16
|
+
private device;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=user_agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user_agent.d.ts","sourceRoot":"","sources":["../../src/utils/user_agent.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,eAAe;IAC1B,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa;IAevC,OAAO,CAAC,OAAO;IA8Bf,OAAO,CAAC,EAAE;IAmCV,OAAO,CAAC,MAAM;CA4Ef"}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@clonus/js-client",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"description": "Clonus Analytics SDK - Simplified analytics with LLM-based event classification",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"module": "./dist/index.mjs",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"unpkg": "./dist/clonus.umd.js",
|
|
14
|
+
"jsdelivr": "./dist/clonus.umd.js",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.mjs",
|
|
19
|
+
"require": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"uuid": "^13.0.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/uuid": "^10.0.0"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "vite build && tsc -p tsconfig.json --emitDeclarationOnly --outDir dist",
|
|
30
|
+
"dev": "vite build --watch",
|
|
31
|
+
"test": "vitest",
|
|
32
|
+
"test:coverage": "vitest --coverage",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"lint": "eslint 'src/**/*.{ts,tsx}' --max-warnings 0",
|
|
35
|
+
"lint:fix": "eslint 'src/**/*.{ts,tsx}' --fix"
|
|
36
|
+
}
|
|
37
|
+
}
|