@tell-rs/browser 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -435,18 +435,13 @@ function generateId() {
435
435
  if (typeof crypto !== "undefined" && crypto.getRandomValues) {
436
436
  const bytes = new Uint8Array(16);
437
437
  crypto.getRandomValues(bytes);
438
- bytes[6] = bytes[6] & 15 | 64;
439
- bytes[8] = bytes[8] & 63 | 128;
440
- const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(
441
- ""
442
- );
443
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
438
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
439
+ }
440
+ let hex = "";
441
+ for (let i = 0; i < 32; i++) {
442
+ hex += (Math.random() * 16 | 0).toString(16);
444
443
  }
445
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
446
- const r = Math.random() * 16 | 0;
447
- const v = c === "x" ? r : r & 3 | 8;
448
- return v.toString(16);
449
- });
444
+ return hex;
450
445
  }
451
446
 
452
447
  // src/bot.ts
@@ -479,13 +474,19 @@ function captureContext() {
479
474
  }
480
475
  ctx.device_type = inferDeviceType(parsed.os, ua, ctx.touch);
481
476
  const conn = navigator.connection;
482
- if (conn?.effectiveType) {
483
- ctx.connection_type = conn.effectiveType;
477
+ if (conn) {
478
+ if (conn.effectiveType) ctx.connection_type = conn.effectiveType;
479
+ if (typeof conn.downlink === "number") ctx.downlink = conn.downlink;
480
+ if (typeof conn.rtt === "number") ctx.rtt = conn.rtt;
481
+ if (conn.saveData) ctx.save_data = true;
484
482
  }
483
+ if (navigator.webdriver) ctx.bot = true;
485
484
  }
486
485
  if (typeof screen !== "undefined") {
487
486
  ctx.screen_width = screen.width;
488
487
  ctx.screen_height = screen.height;
488
+ const orient = screen.orientation;
489
+ if (orient?.type) ctx.screen_orientation = orient.type;
489
490
  }
490
491
  if (typeof window !== "undefined") {
491
492
  ctx.viewport_width = window.innerWidth;
@@ -506,11 +507,18 @@ function captureContext() {
506
507
  }
507
508
  if (typeof location !== "undefined") {
508
509
  ctx.url = location.href;
510
+ if (location.pathname) ctx.path = location.pathname;
509
511
  }
510
512
  try {
511
513
  ctx.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
512
514
  } catch {
513
515
  }
516
+ if (typeof window !== "undefined" && window.matchMedia) {
517
+ try {
518
+ ctx.dark_mode = window.matchMedia("(prefers-color-scheme: dark)").matches;
519
+ } catch {
520
+ }
521
+ }
514
522
  return ctx;
515
523
  }
516
524
  function inferDeviceType(os, ua, touch) {
@@ -584,7 +592,6 @@ var SessionManager = class {
584
592
  timeout;
585
593
  onNewSession;
586
594
  visibilityHandler;
587
- checkTimer;
588
595
  lastContextAt = {};
589
596
  constructor(config) {
590
597
  this.timeout = config.timeout;
@@ -596,10 +603,6 @@ var SessionManager = class {
596
603
  if (typeof document !== "undefined") {
597
604
  document.addEventListener("visibilitychange", this.visibilityHandler);
598
605
  }
599
- this.checkTimer = setInterval(() => this.checkTimeout(), 6e4);
600
- if (typeof this.checkTimer.unref === "function") {
601
- this.checkTimer.unref();
602
- }
603
606
  }
604
607
  get sessionId() {
605
608
  return this._sessionId;
@@ -607,14 +610,18 @@ var SessionManager = class {
607
610
  set sessionId(id) {
608
611
  this._sessionId = id;
609
612
  }
613
+ /** Update activity timestamp; rotates session if idle longer than timeout. */
610
614
  touch() {
611
- this.lastActivityAt = Date.now();
615
+ const now = Date.now();
616
+ if (now - this.lastActivityAt > this.timeout) {
617
+ this.rotateSession("session_timeout");
618
+ }
619
+ this.lastActivityAt = now;
612
620
  }
613
621
  destroy() {
614
622
  if (typeof document !== "undefined") {
615
623
  document.removeEventListener("visibilitychange", this.visibilityHandler);
616
624
  }
617
- clearInterval(this.checkTimer);
618
625
  }
619
626
  handleVisibility() {
620
627
  if (document.visibilityState === "hidden") {
@@ -628,11 +635,6 @@ var SessionManager = class {
628
635
  this.lastHiddenAt = 0;
629
636
  }
630
637
  }
631
- checkTimeout() {
632
- if (Date.now() - this.lastActivityAt > this.timeout) {
633
- this.rotateSession("session_timeout");
634
- }
635
- }
636
638
  rotateSession(reason) {
637
639
  this._sessionId = generateId();
638
640
  this.lastActivityAt = Date.now();
@@ -1021,6 +1023,7 @@ var tell = {
1021
1023
  reportError(err);
1022
1024
  return;
1023
1025
  }
1026
+ sessionManager.touch();
1024
1027
  let event = {
1025
1028
  type: "track",
1026
1029
  event: eventName,
@@ -1035,7 +1038,6 @@ var tell = {
1035
1038
  event = runBeforeSend(event, beforeSend);
1036
1039
  if (event === null) return;
1037
1040
  }
1038
- sessionManager.touch();
1039
1041
  eventBatcher.add(event);
1040
1042
  },
1041
1043
  identify(newUserId, traits) {
@@ -1056,6 +1058,7 @@ var tell = {
1056
1058
  }
1057
1059
  userId = newUserId;
1058
1060
  storage.set(STORAGE_KEYS.USER_ID, userId);
1061
+ sessionManager.touch();
1059
1062
  let event = {
1060
1063
  type: "identify",
1061
1064
  device_id: deviceId,
@@ -1068,7 +1071,6 @@ var tell = {
1068
1071
  event = runBeforeSend(event, beforeSend);
1069
1072
  if (event === null) return;
1070
1073
  }
1071
- sessionManager.touch();
1072
1074
  eventBatcher.add(event);
1073
1075
  },
1074
1076
  group(groupId, properties) {
@@ -1087,6 +1089,7 @@ var tell = {
1087
1089
  reportError(err);
1088
1090
  return;
1089
1091
  }
1092
+ sessionManager.touch();
1090
1093
  let event = {
1091
1094
  type: "group",
1092
1095
  device_id: deviceId,
@@ -1101,7 +1104,6 @@ var tell = {
1101
1104
  event = runBeforeSend(event, beforeSend);
1102
1105
  if (event === null) return;
1103
1106
  }
1104
- sessionManager.touch();
1105
1107
  eventBatcher.add(event);
1106
1108
  },
1107
1109
  revenue(amount, currency, orderId, properties) {
@@ -1122,6 +1124,7 @@ var tell = {
1122
1124
  reportError(err);
1123
1125
  return;
1124
1126
  }
1127
+ sessionManager.touch();
1125
1128
  let event = {
1126
1129
  type: "track",
1127
1130
  event: "Order Completed",
@@ -1139,7 +1142,6 @@ var tell = {
1139
1142
  event = runBeforeSend(event, beforeSend);
1140
1143
  if (event === null) return;
1141
1144
  }
1142
- sessionManager.touch();
1143
1145
  eventBatcher.add(event);
1144
1146
  },
1145
1147
  alias(previousId, newUserId) {
@@ -1160,6 +1162,7 @@ var tell = {
1160
1162
  reportError(err);
1161
1163
  return;
1162
1164
  }
1165
+ sessionManager.touch();
1163
1166
  let event = {
1164
1167
  type: "alias",
1165
1168
  device_id: deviceId,
@@ -1172,7 +1175,6 @@ var tell = {
1172
1175
  event = runBeforeSend(event, beforeSend);
1173
1176
  if (event === null) return;
1174
1177
  }
1175
- sessionManager.touch();
1176
1178
  eventBatcher.add(event);
1177
1179
  },
1178
1180
  // -----------------------------------------------------------------------
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../../core/src/constants.ts","../../core/src/errors.ts","../../core/src/validation.ts","../../core/src/batcher.ts","../../core/src/before-send.ts","../../core/src/redact.ts","../src/config.ts","../src/persistence.ts","../src/id.ts","../src/bot.ts","../src/context.ts","../src/utm.ts","../src/session.ts","../src/transport.ts","../src/queue.ts"],"sourcesContent":["import type {\n JsonEvent,\n JsonLog,\n LogLevel,\n Properties,\n BeforeSendFn,\n} from \"@tell-rs/core\";\nimport {\n ClosedError,\n ConfigurationError,\n ValidationError,\n validateApiKey,\n validateEventName,\n validateLogMessage,\n validateUserId,\n Batcher,\n runBeforeSend,\n} from \"@tell-rs/core\";\n\nimport type { TellBrowserConfig, ResolvedBrowserConfig } from \"./config.js\";\nimport { resolveConfig } from \"./config.js\";\nimport type { TellStorage } from \"./persistence.js\";\nimport { createStorage, STORAGE_KEYS } from \"./persistence.js\";\nimport { generateId } from \"./id.js\";\nimport { isBot } from \"./bot.js\";\nimport { captureContext } from \"./context.js\";\nimport { captureUtm } from \"./utm.js\";\nimport type { SessionReason } from \"./session.js\";\nimport { SessionManager } from \"./session.js\";\nimport { BrowserTransport } from \"./transport.js\";\nimport { PreInitQueue } from \"./queue.js\";\n\n// Re-export core types and values\nexport { Events, type EventName } from \"@tell-rs/core\";\nexport type { Properties, LogLevel, JsonEvent, JsonLog, BeforeSendFn } from \"@tell-rs/core\";\nexport { redact, redactLog, SENSITIVE_PARAMS, type RedactOptions } from \"@tell-rs/core\";\nexport {\n TellError,\n ConfigurationError,\n ValidationError,\n NetworkError,\n ClosedError,\n SerializationError,\n} from \"@tell-rs/core\";\n\n// Re-export browser-specific config\nexport type { TellBrowserConfig } from \"./config.js\";\nexport { development, production } from \"./config.js\";\nexport type { DeviceContext } from \"./context.js\";\n\n// ---------------------------------------------------------------------------\n// Module-level state\n// ---------------------------------------------------------------------------\n\nlet configured = false;\nlet closed = false;\nlet _disabled = false;\nlet _optedOut = false;\n\nlet storage: TellStorage;\nlet transport: BrowserTransport;\nlet eventBatcher: Batcher<JsonEvent>;\nlet logBatcher: Batcher<JsonLog>;\nlet sessionManager: SessionManager;\nlet resolvedConfig: ResolvedBrowserConfig;\n\nlet _apiKey: string;\nlet deviceId: string;\nlet userId: string | undefined;\nlet superProperties: Properties = {};\nlet beforeSend: BeforeSendFn<JsonEvent> | BeforeSendFn<JsonEvent>[] | undefined;\nlet beforeSendLog:\n | BeforeSendFn<JsonLog>\n | BeforeSendFn<JsonLog>[]\n | undefined;\nlet sdkLogLevel: number;\n\nconst queue = new PreInitQueue(1000);\n\nlet unloadHandler: (() => void) | null = null;\nlet visibilityUnloadHandler: (() => void) | null = null;\nlet errorHandler: ((event: ErrorEvent) => void) | null = null;\nlet rejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;\n\nconst LOG_LEVELS: Record<string, number> = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction reportError(err: unknown): void {\n if (resolvedConfig?.onError && err instanceof Error) {\n resolvedConfig.onError(err);\n }\n}\n\nfunction sdkDebug(msg: string): void {\n if (sdkLogLevel >= LOG_LEVELS.debug) {\n console.debug(`[Tell] ${msg}`);\n }\n}\n\nfunction handleUnload(): void {\n const events = eventBatcher.drain();\n const logs = logBatcher.drain();\n transport.beacon(events, logs);\n}\n\nfunction handleVisibilityUnload(): void {\n if (document.visibilityState === \"hidden\") {\n handleUnload();\n }\n}\n\nfunction onNewSession(reason: SessionReason, sessionId: string): void {\n if (_disabled || _optedOut || closed) return;\n const ctx = captureContext();\n const event: JsonEvent = {\n type: \"context\",\n device_id: deviceId,\n session_id: sessionId,\n user_id: userId,\n timestamp: Date.now(),\n reason,\n ...ctx,\n };\n eventBatcher.add(event);\n}\n\nfunction persistSuperProps(): void {\n storage.set(STORAGE_KEYS.SUPER_PROPS, JSON.stringify(superProperties));\n}\n\nfunction loadSuperProps(): Properties {\n const raw = storage.get(STORAGE_KEYS.SUPER_PROPS);\n if (!raw) return {};\n try {\n return JSON.parse(raw) as Properties;\n } catch {\n storage.remove(STORAGE_KEYS.SUPER_PROPS);\n return {};\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport interface TellInstance {\n configure(apiKey: string, options?: TellBrowserConfig): void;\n track(eventName: string, properties?: Properties): void;\n identify(userId: string, traits?: Properties): void;\n group(groupId: string, properties?: Properties): void;\n revenue(\n amount: number,\n currency: string,\n orderId: string,\n properties?: Properties\n ): void;\n alias(previousId: string, userId: string): void;\n log(\n level: LogLevel,\n message: string,\n service?: string,\n data?: Properties\n ): void;\n logEmergency(message: string, service?: string, data?: Properties): void;\n logAlert(message: string, service?: string, data?: Properties): void;\n logCritical(message: string, service?: string, data?: Properties): void;\n logError(message: string, service?: string, data?: Properties): void;\n logWarning(message: string, service?: string, data?: Properties): void;\n logNotice(message: string, service?: string, data?: Properties): void;\n logInfo(message: string, service?: string, data?: Properties): void;\n logDebug(message: string, service?: string, data?: Properties): void;\n logTrace(message: string, service?: string, data?: Properties): void;\n register(properties: Properties): void;\n unregister(key: string): void;\n optOut(): void;\n optIn(): void;\n isOptedOut(): boolean;\n flush(): Promise<void>;\n close(): Promise<void>;\n reset(): void;\n enable(): void;\n disable(): void;\n /** @internal Reset all module state. Only for testing. */\n _resetForTesting(): void;\n}\n\nconst tell: TellInstance = {\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n configure(apiKey: string, options?: TellBrowserConfig): void {\n if (configured) {\n reportError(new ConfigurationError(\"Tell is already configured\"));\n return;\n }\n\n validateApiKey(apiKey);\n _apiKey = apiKey;\n resolvedConfig = resolveConfig(options);\n sdkLogLevel = LOG_LEVELS[resolvedConfig.logLevel] ?? 0;\n beforeSend = resolvedConfig.beforeSend;\n beforeSendLog = resolvedConfig.beforeSendLog;\n _disabled = resolvedConfig.disabled;\n\n // Persistence\n storage = createStorage(resolvedConfig.persistence);\n deviceId = storage.get(STORAGE_KEYS.DEVICE_ID) ?? generateId();\n storage.set(STORAGE_KEYS.DEVICE_ID, deviceId);\n userId = storage.get(STORAGE_KEYS.USER_ID) ?? undefined;\n _optedOut = storage.get(STORAGE_KEYS.OPT_OUT) === \"1\";\n superProperties = loadSuperProps();\n\n // UTM parameters — capture from URL and merge into super properties\n const utm = captureUtm();\n if (Object.keys(utm).length > 0) {\n Object.assign(superProperties, utm);\n persistSuperProps();\n }\n\n // Bot detection\n if (resolvedConfig.botDetection && isBot()) {\n _disabled = true;\n sdkDebug(\"bot detected, disabling\");\n }\n\n // Do Not Track\n if (\n resolvedConfig.respectDoNotTrack &&\n typeof navigator !== \"undefined\" &&\n navigator.doNotTrack === \"1\"\n ) {\n _disabled = true;\n sdkDebug(\"Do Not Track enabled, disabling\");\n }\n\n // Transport\n transport = new BrowserTransport({\n endpoint: resolvedConfig.endpoint,\n apiKey: _apiKey,\n maxRetries: resolvedConfig.maxRetries,\n networkTimeout: resolvedConfig.networkTimeout,\n onError: resolvedConfig.onError,\n onPayloadTooLarge: () => {\n eventBatcher.halveBatchSize();\n logBatcher.halveBatchSize();\n sdkDebug(\"413 received, halved batch size\");\n },\n });\n\n // Batchers\n eventBatcher = new Batcher<JsonEvent>({\n size: resolvedConfig.batchSize,\n interval: resolvedConfig.flushInterval,\n maxQueueSize: resolvedConfig.maxQueueSize,\n send: (items) => transport.sendEvents(items),\n onOverflow: () => sdkDebug(\"event queue overflow, dropping oldest\"),\n });\n\n logBatcher = new Batcher<JsonLog>({\n size: resolvedConfig.batchSize,\n interval: resolvedConfig.flushInterval,\n maxQueueSize: resolvedConfig.maxQueueSize,\n send: (items) => transport.sendLogs(items),\n onOverflow: () => sdkDebug(\"log queue overflow, dropping oldest\"),\n });\n\n // Session management\n sessionManager = new SessionManager({\n timeout: resolvedConfig.sessionTimeout,\n onNewSession,\n });\n\n // Unload handlers\n if (typeof window !== \"undefined\") {\n unloadHandler = handleUnload;\n window.addEventListener(\"beforeunload\", unloadHandler);\n }\n if (typeof document !== \"undefined\") {\n visibilityUnloadHandler = handleVisibilityUnload;\n document.addEventListener(\"visibilitychange\", visibilityUnloadHandler);\n }\n\n // Error auto-capture\n if (resolvedConfig.captureErrors && typeof window !== \"undefined\") {\n errorHandler = (event: ErrorEvent) => {\n if (_disabled || _optedOut || closed) return;\n const msg = event.message || \"Unknown error\";\n const data: Properties = {};\n if (event.filename) data.filename = event.filename;\n if (event.lineno) data.lineno = event.lineno;\n if (event.colno) data.colno = event.colno;\n if (event.error?.stack) data.stack = event.error.stack;\n tell.logError(msg, \"browser\", data);\n };\n rejectionHandler = (event: PromiseRejectionEvent) => {\n if (_disabled || _optedOut || closed) return;\n const reason = event.reason;\n const msg =\n reason instanceof Error\n ? reason.message\n : String(reason ?? \"Unhandled promise rejection\");\n const data: Properties = {};\n if (reason instanceof Error && reason.stack) data.stack = reason.stack;\n tell.logError(msg, \"browser\", data);\n };\n window.addEventListener(\"error\", errorHandler);\n window.addEventListener(\"unhandledrejection\", rejectionHandler);\n }\n\n configured = true;\n closed = false;\n\n sdkDebug(\n `configured (endpoint=${resolvedConfig.endpoint}, batch=${resolvedConfig.batchSize})`\n );\n\n // Replay pre-init queue\n queue.replay(tell as unknown as Record<string, (...args: any[]) => any>);\n },\n\n // -----------------------------------------------------------------------\n // Events\n // -----------------------------------------------------------------------\n\n track(eventName: string, properties?: Properties): void {\n if (!configured) {\n queue.push({ method: \"track\", args: [eventName, properties] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n validateEventName(eventName);\n } catch (err) {\n reportError(err);\n return;\n }\n\n let event: JsonEvent | null = {\n type: \"track\",\n event: eventName,\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n timestamp: Date.now(),\n ...superProperties,\n ...properties,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n sessionManager.touch();\n eventBatcher.add(event);\n },\n\n identify(newUserId: string, traits?: Properties): void {\n if (!configured) {\n queue.push({ method: \"identify\", args: [newUserId, traits] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n validateUserId(newUserId);\n } catch (err) {\n reportError(err);\n return;\n }\n\n userId = newUserId;\n storage.set(STORAGE_KEYS.USER_ID, userId);\n\n let event: JsonEvent | null = {\n type: \"identify\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n timestamp: Date.now(),\n ...traits,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n sessionManager.touch();\n eventBatcher.add(event);\n },\n\n group(groupId: string, properties?: Properties): void {\n if (!configured) {\n queue.push({ method: \"group\", args: [groupId, properties] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n if (!groupId) throw new ValidationError(\"groupId\", \"is required\");\n } catch (err) {\n reportError(err);\n return;\n }\n\n let event: JsonEvent | null = {\n type: \"group\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n group_id: groupId,\n timestamp: Date.now(),\n ...superProperties,\n ...properties,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n sessionManager.touch();\n eventBatcher.add(event);\n },\n\n revenue(\n amount: number,\n currency: string,\n orderId: string,\n properties?: Properties\n ): void {\n if (!configured) {\n queue.push({ method: \"revenue\", args: [amount, currency, orderId, properties] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n if (amount <= 0) throw new ValidationError(\"amount\", \"must be positive\");\n if (!currency) throw new ValidationError(\"currency\", \"is required\");\n if (!orderId) throw new ValidationError(\"orderId\", \"is required\");\n } catch (err) {\n reportError(err);\n return;\n }\n\n let event: JsonEvent | null = {\n type: \"track\",\n event: \"Order Completed\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n timestamp: Date.now(),\n ...superProperties,\n ...properties,\n order_id: orderId,\n amount,\n currency,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n sessionManager.touch();\n eventBatcher.add(event);\n },\n\n alias(previousId: string, newUserId: string): void {\n if (!configured) {\n queue.push({ method: \"alias\", args: [previousId, newUserId] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n if (!previousId)\n throw new ValidationError(\"previousId\", \"is required\");\n validateUserId(newUserId);\n } catch (err) {\n reportError(err);\n return;\n }\n\n let event: JsonEvent | null = {\n type: \"alias\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: newUserId,\n timestamp: Date.now(),\n previous_id: previousId,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n sessionManager.touch();\n eventBatcher.add(event);\n },\n\n // -----------------------------------------------------------------------\n // Logging\n // -----------------------------------------------------------------------\n\n log(\n level: LogLevel,\n message: string,\n service?: string,\n data?: Properties\n ): void {\n if (!configured) {\n queue.push({ method: \"log\", args: [level, message, service, data] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n validateLogMessage(message);\n } catch (err) {\n reportError(err);\n return;\n }\n\n let logEntry: JsonLog | null = {\n level,\n message,\n source: resolvedConfig.source,\n service: service ?? \"app\",\n session_id: sessionManager.sessionId,\n timestamp: Date.now(),\n data,\n };\n\n if (beforeSendLog) {\n logEntry = runBeforeSend(logEntry, beforeSendLog);\n if (logEntry === null) return;\n }\n\n logBatcher.add(logEntry);\n },\n\n logEmergency(message: string, service?: string, data?: Properties): void {\n tell.log(\"emergency\", message, service, data);\n },\n logAlert(message: string, service?: string, data?: Properties): void {\n tell.log(\"alert\", message, service, data);\n },\n logCritical(message: string, service?: string, data?: Properties): void {\n tell.log(\"critical\", message, service, data);\n },\n logError(message: string, service?: string, data?: Properties): void {\n tell.log(\"error\", message, service, data);\n },\n logWarning(message: string, service?: string, data?: Properties): void {\n tell.log(\"warning\", message, service, data);\n },\n logNotice(message: string, service?: string, data?: Properties): void {\n tell.log(\"notice\", message, service, data);\n },\n logInfo(message: string, service?: string, data?: Properties): void {\n tell.log(\"info\", message, service, data);\n },\n logDebug(message: string, service?: string, data?: Properties): void {\n tell.log(\"debug\", message, service, data);\n },\n logTrace(message: string, service?: string, data?: Properties): void {\n tell.log(\"trace\", message, service, data);\n },\n\n // -----------------------------------------------------------------------\n // Super Properties\n // -----------------------------------------------------------------------\n\n register(properties: Properties): void {\n if (!configured) {\n queue.push({ method: \"register\", args: [properties] });\n return;\n }\n Object.assign(superProperties, properties);\n persistSuperProps();\n },\n\n unregister(key: string): void {\n if (!configured) {\n queue.push({ method: \"unregister\", args: [key] });\n return;\n }\n delete superProperties[key];\n persistSuperProps();\n },\n\n // -----------------------------------------------------------------------\n // Privacy\n // -----------------------------------------------------------------------\n\n optOut(): void {\n if (!configured) {\n queue.push({ method: \"optOut\", args: [] });\n return;\n }\n _optedOut = true;\n storage.set(STORAGE_KEYS.OPT_OUT, \"1\");\n },\n\n optIn(): void {\n if (!configured) {\n queue.push({ method: \"optIn\", args: [] });\n return;\n }\n _optedOut = false;\n storage.remove(STORAGE_KEYS.OPT_OUT);\n },\n\n isOptedOut(): boolean {\n return _optedOut;\n },\n\n // -----------------------------------------------------------------------\n // Control\n // -----------------------------------------------------------------------\n\n enable(): void {\n _disabled = false;\n },\n\n disable(): void {\n _disabled = true;\n },\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n async flush(): Promise<void> {\n if (!configured) return;\n await Promise.all([eventBatcher.flush(), logBatcher.flush()]);\n },\n\n async close(): Promise<void> {\n if (!configured || closed) return;\n closed = true;\n\n if (sessionManager) sessionManager.destroy();\n\n if (typeof window !== \"undefined\" && unloadHandler) {\n window.removeEventListener(\"beforeunload\", unloadHandler);\n unloadHandler = null;\n }\n if (typeof document !== \"undefined\" && visibilityUnloadHandler) {\n document.removeEventListener(\"visibilitychange\", visibilityUnloadHandler);\n visibilityUnloadHandler = null;\n }\n if (typeof window !== \"undefined\") {\n if (errorHandler) {\n window.removeEventListener(\"error\", errorHandler);\n errorHandler = null;\n }\n if (rejectionHandler) {\n window.removeEventListener(\"unhandledrejection\", rejectionHandler);\n rejectionHandler = null;\n }\n }\n\n const work = Promise.all([eventBatcher.close(), logBatcher.close()]);\n const timeout = new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(\"close timed out\")),\n resolvedConfig.closeTimeout\n )\n );\n\n try {\n await Promise.race([work, timeout]);\n } catch (err) {\n reportError(err);\n }\n\n configured = false;\n },\n\n reset(): void {\n if (!configured) return;\n userId = undefined;\n deviceId = generateId();\n superProperties = {};\n\n storage.remove(STORAGE_KEYS.USER_ID);\n storage.set(STORAGE_KEYS.DEVICE_ID, deviceId);\n storage.remove(STORAGE_KEYS.SUPER_PROPS);\n\n if (sessionManager) {\n sessionManager.sessionId = generateId();\n }\n },\n\n // -----------------------------------------------------------------------\n // Testing helper\n // -----------------------------------------------------------------------\n\n _resetForTesting(): void {\n if (configured && !closed) {\n // Synchronously tear down timers\n if (sessionManager) sessionManager.destroy();\n if (eventBatcher) {\n eventBatcher.drain();\n eventBatcher.close().catch(() => {});\n }\n if (logBatcher) {\n logBatcher.drain();\n logBatcher.close().catch(() => {});\n }\n if (typeof window !== \"undefined\" && unloadHandler) {\n window.removeEventListener(\"beforeunload\", unloadHandler);\n }\n if (typeof document !== \"undefined\" && visibilityUnloadHandler) {\n document.removeEventListener(\n \"visibilitychange\",\n visibilityUnloadHandler\n );\n }\n if (typeof window !== \"undefined\") {\n if (errorHandler) window.removeEventListener(\"error\", errorHandler);\n if (rejectionHandler)\n window.removeEventListener(\"unhandledrejection\", rejectionHandler);\n }\n }\n\n configured = false;\n closed = false;\n _disabled = false;\n _optedOut = false;\n userId = undefined;\n deviceId = \"\";\n superProperties = {};\n beforeSend = undefined;\n beforeSendLog = undefined;\n sdkLogLevel = 0;\n unloadHandler = null;\n visibilityUnloadHandler = null;\n errorHandler = null;\n rejectionHandler = null;\n queue.clear();\n },\n};\n\nexport default tell;\nexport { tell };\n","// Standard event names — typed constants matching the spec appendix A\n\nexport const Events = {\n // User Lifecycle\n UserSignedUp: \"User Signed Up\",\n UserSignedIn: \"User Signed In\",\n UserSignedOut: \"User Signed Out\",\n UserInvited: \"User Invited\",\n UserOnboarded: \"User Onboarded\",\n AuthenticationFailed: \"Authentication Failed\",\n PasswordReset: \"Password Reset\",\n TwoFactorEnabled: \"Two Factor Enabled\",\n TwoFactorDisabled: \"Two Factor Disabled\",\n\n // Revenue & Billing\n OrderCompleted: \"Order Completed\",\n OrderRefunded: \"Order Refunded\",\n OrderCanceled: \"Order Canceled\",\n PaymentFailed: \"Payment Failed\",\n PaymentMethodAdded: \"Payment Method Added\",\n PaymentMethodUpdated: \"Payment Method Updated\",\n PaymentMethodRemoved: \"Payment Method Removed\",\n\n // Subscription\n SubscriptionStarted: \"Subscription Started\",\n SubscriptionRenewed: \"Subscription Renewed\",\n SubscriptionPaused: \"Subscription Paused\",\n SubscriptionResumed: \"Subscription Resumed\",\n SubscriptionChanged: \"Subscription Changed\",\n SubscriptionCanceled: \"Subscription Canceled\",\n\n // Trial\n TrialStarted: \"Trial Started\",\n TrialEndingSoon: \"Trial Ending Soon\",\n TrialEnded: \"Trial Ended\",\n TrialConverted: \"Trial Converted\",\n\n // Shopping\n CartViewed: \"Cart Viewed\",\n CartUpdated: \"Cart Updated\",\n CartAbandoned: \"Cart Abandoned\",\n CheckoutStarted: \"Checkout Started\",\n CheckoutCompleted: \"Checkout Completed\",\n\n // Engagement\n PageViewed: \"Page Viewed\",\n FeatureUsed: \"Feature Used\",\n SearchPerformed: \"Search Performed\",\n FileUploaded: \"File Uploaded\",\n NotificationSent: \"Notification Sent\",\n NotificationClicked: \"Notification Clicked\",\n\n // Communication\n EmailSent: \"Email Sent\",\n EmailOpened: \"Email Opened\",\n EmailClicked: \"Email Clicked\",\n EmailBounced: \"Email Bounced\",\n EmailUnsubscribed: \"Email Unsubscribed\",\n SupportTicketCreated: \"Support Ticket Created\",\n SupportTicketResolved: \"Support Ticket Resolved\",\n} as const;\n\nexport type EventName = (typeof Events)[keyof typeof Events];\n","export class TellError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TellError\";\n }\n}\n\nexport class ConfigurationError extends TellError {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigurationError\";\n }\n}\n\nexport class ValidationError extends TellError {\n public readonly field: string;\n\n constructor(field: string, message: string) {\n super(`${field}: ${message}`);\n this.name = \"ValidationError\";\n this.field = field;\n }\n}\n\nexport class NetworkError extends TellError {\n public readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.name = \"NetworkError\";\n this.statusCode = statusCode;\n }\n}\n\nexport class ClosedError extends TellError {\n constructor() {\n super(\"Client is closed\");\n this.name = \"ClosedError\";\n }\n}\n\nexport class SerializationError extends TellError {\n constructor(message: string) {\n super(message);\n this.name = \"SerializationError\";\n }\n}\n","import { ConfigurationError, ValidationError } from \"./errors.js\";\n\nconst HEX_RE = /^[0-9a-fA-F]{32}$/;\nconst MAX_EVENT_NAME = 256;\nconst MAX_LOG_MESSAGE = 65_536;\n\nexport function validateApiKey(key: string): void {\n if (!key) {\n throw new ConfigurationError(\"apiKey is required\");\n }\n if (!HEX_RE.test(key)) {\n throw new ConfigurationError(\n \"apiKey must be exactly 32 hex characters\"\n );\n }\n}\n\nexport function validateEventName(name: unknown): void {\n if (typeof name !== \"string\" || name.length === 0) {\n throw new ValidationError(\"eventName\", \"must be a non-empty string\");\n }\n if (name.length > MAX_EVENT_NAME) {\n throw new ValidationError(\n \"eventName\",\n `must be at most ${MAX_EVENT_NAME} characters, got ${name.length}`\n );\n }\n}\n\nexport function validateLogMessage(message: unknown): void {\n if (typeof message !== \"string\" || message.length === 0) {\n throw new ValidationError(\"message\", \"must be a non-empty string\");\n }\n if (message.length > MAX_LOG_MESSAGE) {\n throw new ValidationError(\n \"message\",\n `must be at most ${MAX_LOG_MESSAGE} characters, got ${message.length}`\n );\n }\n}\n\nexport function validateUserId(id: unknown): void {\n if (typeof id !== \"string\" || id.length === 0) {\n throw new ValidationError(\"userId\", \"must be a non-empty string\");\n }\n}\n","export interface BatcherConfig<T> {\n size: number;\n interval: number; // ms\n maxQueueSize: number;\n send: (items: T[]) => Promise<void>;\n onOverflow?: () => void;\n}\n\nexport class Batcher<T> {\n private queue: T[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private closed = false;\n private flushing: Promise<void> | null = null;\n private config: BatcherConfig<T>;\n\n constructor(config: BatcherConfig<T>) {\n this.config = config;\n this.timer = setInterval(() => {\n if (this.queue.length > 0) {\n this.flush().catch(() => {});\n }\n }, config.interval);\n // Don't keep Node.js process alive just for flush timer\n if (this.timer && typeof (this.timer as any).unref === \"function\") {\n (this.timer as any).unref();\n }\n }\n\n add(item: T): void {\n if (this.closed) return;\n\n if (this.queue.length >= this.config.maxQueueSize) {\n this.queue.shift(); // drop oldest\n if (this.config.onOverflow) {\n this.config.onOverflow();\n }\n }\n\n this.queue.push(item);\n\n if (this.queue.length >= this.config.size) {\n this.flush().catch(() => {});\n }\n }\n\n async flush(): Promise<void> {\n // Prevent concurrent flushes\n if (this.flushing) {\n return this.flushing;\n }\n this.flushing = this.doFlush();\n try {\n await this.flushing;\n } finally {\n this.flushing = null;\n }\n }\n\n async close(): Promise<void> {\n this.closed = true;\n if (this.timer !== null) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush();\n }\n\n get pending(): number {\n return this.queue.length;\n }\n\n drain(): T[] {\n const items = this.queue;\n this.queue = [];\n return items;\n }\n\n halveBatchSize(): void {\n this.config.size = Math.max(1, Math.floor(this.config.size / 2));\n }\n\n private async doFlush(): Promise<void> {\n while (this.queue.length > 0) {\n const batch = this.queue.slice(0, this.config.size);\n try {\n await this.config.send(batch);\n this.queue.splice(0, batch.length); // remove only on success\n } catch {\n return; // items stay in queue (e.g. 413 — batch size already halved)\n }\n }\n }\n}\n","/**\n * A function that transforms or drops an item before it is queued.\n * Return the (possibly modified) item, or null to drop it.\n */\nexport type BeforeSendFn<T> = (item: T) => T | null;\n\n/**\n * Run an item through a pipeline of beforeSend functions.\n * Returns the transformed item, or null if any function in the chain drops it.\n */\nexport function runBeforeSend<T>(\n item: T,\n fns: BeforeSendFn<T> | BeforeSendFn<T>[]\n): T | null {\n const pipeline = Array.isArray(fns) ? fns : [fns];\n let current: T | null = item;\n\n for (const fn of pipeline) {\n if (current === null) return null;\n current = fn(current);\n }\n\n return current;\n}\n","import type { BeforeSendFn } from \"./before-send.js\";\nimport type { JsonEvent, JsonLog, Properties } from \"./types.js\";\n\n/**\n * Common query-parameter names that often carry secrets or tokens.\n * Pass these (or a subset) to `stripParams` for quick sanitization.\n */\nexport const SENSITIVE_PARAMS: readonly string[] = [\n \"token\",\n \"api_key\",\n \"key\",\n \"secret\",\n \"password\",\n \"access_token\",\n \"refresh_token\",\n \"authorization\",\n] as const;\n\nexport interface RedactOptions {\n /** Query-parameter names to strip from URL-shaped values. */\n stripParams?: string[];\n /** Keys whose values should be replaced with \"[REDACTED]\". */\n redactKeys?: string[];\n /** URL pathname prefixes — events whose url matches are dropped entirely. */\n dropRoutes?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction stripUrlParams(url: string, params: string[]): string {\n try {\n const u = new URL(url);\n for (const p of params) u.searchParams.delete(p);\n return u.toString();\n } catch {\n return url; // not a valid URL — leave as-is\n }\n}\n\nfunction redactKeysInProperties(\n props: Properties | undefined,\n keys: string[],\n): Properties | undefined {\n if (!props) return props;\n const out: Properties = {};\n for (const [k, v] of Object.entries(props)) {\n out[k] = keys.includes(k) ? \"[REDACTED]\" : v;\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Factory that returns a `beforeSend` hook for events.\n *\n * - `dropRoutes` — drops events whose `url` pathname starts with a prefix.\n * - `stripParams` — removes query params from URL-shaped string values.\n * - `redactKeys` — replaces matching keys with `\"[REDACTED]\"`.\n *\n * The returned function never mutates the input event.\n */\nexport function redact(options: RedactOptions): BeforeSendFn<JsonEvent> {\n const { stripParams, redactKeys, dropRoutes } = options;\n\n return (event: JsonEvent): JsonEvent | null => {\n // --- dropRoutes ---\n if (dropRoutes && dropRoutes.length > 0 && event.url) {\n try {\n const pathname = new URL(String(event.url)).pathname;\n for (const prefix of dropRoutes) {\n if (pathname.startsWith(prefix)) return null;\n }\n } catch {\n // not a valid URL — skip drop check\n }\n }\n\n let result: JsonEvent = event;\n\n // --- stripParams ---\n if (stripParams && stripParams.length > 0) {\n for (const [k, v] of Object.entries(event)) {\n if (typeof v === \"string\" && v.startsWith(\"http\")) {\n const stripped = stripUrlParams(v, stripParams);\n if (stripped !== v) {\n if (result === event) result = { ...event };\n result[k] = stripped;\n }\n }\n }\n }\n\n // --- redactKeys ---\n if (redactKeys && redactKeys.length > 0) {\n for (const [k, v] of Object.entries(event)) {\n if (redactKeys.includes(k)) {\n if (result === event) result = { ...event };\n result[k] = \"[REDACTED]\";\n }\n }\n }\n\n return result;\n };\n}\n\n/**\n * Factory that returns a `beforeSend` hook for log entries.\n *\n * - `redactKeys` — replaces matching keys in `log.data` with `\"[REDACTED]\"`.\n *\n * The returned function never mutates the input log.\n */\nexport function redactLog(\n options: Pick<RedactOptions, \"redactKeys\">,\n): BeforeSendFn<JsonLog> {\n const { redactKeys } = options;\n\n return (log: JsonLog): JsonLog | null => {\n if (redactKeys && redactKeys.length > 0 && log.data) {\n const data = redactKeysInProperties(log.data, redactKeys);\n if (data !== log.data) {\n return { ...log, data };\n }\n }\n return log;\n };\n}\n","import type { TellError, BeforeSendFn, JsonEvent, JsonLog } from \"@tell-rs/core\";\n\nexport interface TellBrowserConfig {\n endpoint?: string;\n batchSize?: number;\n flushInterval?: number;\n maxRetries?: number;\n closeTimeout?: number;\n networkTimeout?: number;\n logLevel?: \"error\" | \"warn\" | \"info\" | \"debug\";\n source?: string;\n onError?: (error: TellError) => void;\n disabled?: boolean;\n maxQueueSize?: number;\n sessionTimeout?: number;\n persistence?: \"localStorage\" | \"memory\";\n respectDoNotTrack?: boolean;\n botDetection?: boolean;\n captureErrors?: boolean;\n beforeSend?: BeforeSendFn<JsonEvent> | BeforeSendFn<JsonEvent>[];\n beforeSendLog?: BeforeSendFn<JsonLog> | BeforeSendFn<JsonLog>[];\n}\n\nexport const DEFAULTS = {\n endpoint: \"https://collect.tell.app\",\n batchSize: 20,\n flushInterval: 5_000,\n maxRetries: 5,\n closeTimeout: 5_000,\n networkTimeout: 10_000,\n logLevel: \"error\" as const,\n source: \"browser\",\n disabled: false,\n maxQueueSize: 1000,\n sessionTimeout: 1_800_000, // 30 min\n persistence: \"localStorage\" as const,\n respectDoNotTrack: false,\n botDetection: true,\n captureErrors: false,\n} as const;\n\nexport type ResolvedBrowserConfig = Required<\n Omit<TellBrowserConfig, \"onError\" | \"beforeSend\" | \"beforeSendLog\">\n> &\n Pick<TellBrowserConfig, \"onError\" | \"beforeSend\" | \"beforeSendLog\">;\n\nexport function resolveConfig(\n options: TellBrowserConfig | undefined\n): ResolvedBrowserConfig {\n return { ...DEFAULTS, ...options } as ResolvedBrowserConfig;\n}\n\n/** Development preset: localhost, small batches, fast flush, debug logging. */\nexport function development(\n overrides?: Partial<TellBrowserConfig>\n): TellBrowserConfig {\n return {\n endpoint: \"http://localhost:8080\",\n batchSize: 5,\n flushInterval: 2_000,\n logLevel: \"debug\",\n ...overrides,\n };\n}\n\n/** Production preset: default endpoint, error-only logging. */\nexport function production(\n overrides?: Partial<TellBrowserConfig>\n): TellBrowserConfig {\n return {\n logLevel: \"error\",\n ...overrides,\n };\n}\n","export interface TellStorage {\n get(key: string): string | null;\n set(key: string, value: string): void;\n remove(key: string): void;\n}\n\nexport const STORAGE_KEYS = {\n DEVICE_ID: \"tell_device_id\",\n USER_ID: \"tell_user_id\",\n OPT_OUT: \"tell_opt_out\",\n SUPER_PROPS: \"tell_super_props\",\n} as const;\n\nclass LocalStorageStorage implements TellStorage {\n get(key: string): string | null {\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n }\n\n set(key: string, value: string): void {\n try {\n localStorage.setItem(key, value);\n } catch {\n // Safari private mode or quota exceeded\n }\n }\n\n remove(key: string): void {\n try {\n localStorage.removeItem(key);\n } catch {\n // ignore\n }\n }\n}\n\nclass MemoryStorage implements TellStorage {\n private data = new Map<string, string>();\n\n get(key: string): string | null {\n return this.data.get(key) ?? null;\n }\n\n set(key: string, value: string): void {\n this.data.set(key, value);\n }\n\n remove(key: string): void {\n this.data.delete(key);\n }\n}\n\n/** Create a storage backend. Falls back to memory if localStorage is unavailable. */\nexport function createStorage(\n persistence: \"localStorage\" | \"memory\"\n): TellStorage {\n if (persistence === \"localStorage\" && typeof localStorage !== \"undefined\") {\n try {\n const testKey = \"tell_test\";\n localStorage.setItem(testKey, \"1\");\n localStorage.removeItem(testKey);\n return new LocalStorageStorage();\n } catch {\n // probe failed — fall through to memory\n }\n }\n return new MemoryStorage();\n}\n","/** Generate a UUID v4 string using crypto.getRandomValues. */\nexport function generateId(): string {\n if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n // Set version (4) and variant (10xx)\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\n \"\"\n );\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n }\n\n // Fallback for environments without crypto (extremely rare)\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","/** Returns true if the current environment appears to be an automated bot. */\nexport function isBot(): boolean {\n if (typeof navigator === \"undefined\") return false;\n if ((navigator as any).webdriver === true) return true;\n const ua = navigator.userAgent || \"\";\n return /headless/i.test(ua);\n}\n","export interface DeviceContext {\n browser?: string;\n browser_version?: string;\n os_name?: string;\n os_version?: string;\n device_type?: string;\n screen_width?: number;\n screen_height?: number;\n viewport_width?: number;\n viewport_height?: number;\n device_pixel_ratio?: number;\n locale?: string;\n timezone?: string;\n referrer?: string;\n referrer_domain?: string;\n url?: string;\n title?: string;\n connection_type?: string;\n cpu_cores?: number;\n device_memory?: number;\n touch?: boolean;\n}\n\n/** Capture a snapshot of the current device/browser context. */\nexport function captureContext(): DeviceContext {\n const ctx: DeviceContext = {};\n\n if (typeof navigator !== \"undefined\") {\n const ua = navigator.userAgent || \"\";\n const parsed = parseUA(ua);\n ctx.browser = parsed.browser;\n ctx.browser_version = parsed.browserVersion;\n ctx.os_name = parsed.os;\n ctx.os_version = parsed.osVersion;\n ctx.locale = navigator.language;\n\n // Hardware capabilities (touch must come before device_type inference)\n if (\"hardwareConcurrency\" in navigator) {\n ctx.cpu_cores = (navigator as any).hardwareConcurrency;\n }\n if (\"deviceMemory\" in navigator) {\n ctx.device_memory = (navigator as any).deviceMemory;\n }\n if (\"maxTouchPoints\" in navigator) {\n ctx.touch = navigator.maxTouchPoints > 0;\n }\n\n ctx.device_type = inferDeviceType(parsed.os, ua, ctx.touch);\n\n // Network info (Chrome/Edge)\n const conn = (navigator as any).connection;\n if (conn?.effectiveType) {\n ctx.connection_type = conn.effectiveType;\n }\n }\n\n if (typeof screen !== \"undefined\") {\n ctx.screen_width = screen.width;\n ctx.screen_height = screen.height;\n }\n\n if (typeof window !== \"undefined\") {\n ctx.viewport_width = window.innerWidth;\n ctx.viewport_height = window.innerHeight;\n if (window.devicePixelRatio) {\n ctx.device_pixel_ratio = window.devicePixelRatio;\n }\n }\n\n if (typeof document !== \"undefined\") {\n ctx.referrer = document.referrer || undefined;\n if (ctx.referrer) {\n try {\n ctx.referrer_domain = new URL(ctx.referrer).hostname;\n } catch {\n // malformed referrer\n }\n }\n ctx.title = document.title || undefined;\n }\n\n if (typeof location !== \"undefined\") {\n ctx.url = location.href;\n }\n\n try {\n ctx.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n // Intl not available\n }\n\n return ctx;\n}\n\nfunction inferDeviceType(os?: string, ua?: string, touch?: boolean): string {\n // iPad (iPadOS 13+) reports as macOS but has touch support\n if (os === \"macOS\" && touch) return \"tablet\";\n // Android tablets have \"Android\" in UA but not \"Mobile\"\n if (os === \"Android\") return ua && !/Mobile/.test(ua) ? \"tablet\" : \"mobile\";\n if (os === \"iOS\") return \"mobile\";\n return \"desktop\";\n}\n\ninterface ParsedUA {\n browser?: string;\n browserVersion?: string;\n os?: string;\n osVersion?: string;\n}\n\nfunction parseUA(ua: string): ParsedUA {\n const result: ParsedUA = {};\n\n // Browser detection (order matters: Edge before Chrome, Chrome before Safari)\n if (/Edg\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Edge\";\n result.browserVersion = RegExp.$1;\n } else if (/OPR\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Opera\";\n result.browserVersion = RegExp.$1;\n } else if (/Chrome\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Chrome\";\n result.browserVersion = RegExp.$1;\n } else if (/Safari\\/[\\d.]+/.test(ua) && /Version\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Safari\";\n result.browserVersion = RegExp.$1;\n } else if (/Firefox\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Firefox\";\n result.browserVersion = RegExp.$1;\n }\n\n // OS detection\n if (/Windows NT ([\\d.]+)/.test(ua)) {\n result.os = \"Windows\";\n result.osVersion = RegExp.$1;\n } else if (/Mac OS X ([\\d_.]+)/.test(ua)) {\n result.os = \"macOS\";\n result.osVersion = RegExp.$1.replace(/_/g, \".\");\n } else if (/iPhone OS ([\\d_]+)/.test(ua)) {\n result.os = \"iOS\";\n result.osVersion = RegExp.$1.replace(/_/g, \".\");\n } else if (/Android ([\\d.]+)/.test(ua)) {\n result.os = \"Android\";\n result.osVersion = RegExp.$1;\n } else if (/Linux/.test(ua)) {\n result.os = \"Linux\";\n }\n\n return result;\n}\n","import type { Properties } from \"@tell-rs/core\";\n\nconst UTM_KEYS = [\n \"utm_source\",\n \"utm_medium\",\n \"utm_campaign\",\n \"utm_term\",\n \"utm_content\",\n] as const;\n\n/**\n * Extract UTM parameters from the current URL search string.\n * Returns only keys that are present and non-empty.\n */\nexport function captureUtm(): Properties {\n if (typeof window === \"undefined\" || !window.location?.search) return {};\n\n const params = new URLSearchParams(window.location.search);\n const utm: Properties = {};\n\n for (const key of UTM_KEYS) {\n const value = params.get(key);\n if (value) {\n utm[key] = value;\n }\n }\n\n return utm;\n}\n","import { generateId } from \"./id.js\";\n\nexport type SessionReason = \"session_start\" | \"session_timeout\" | \"app_foreground\";\n\nexport interface SessionManagerConfig {\n timeout: number; // ms\n onNewSession: (reason: SessionReason, sessionId: string) => void;\n}\n\nexport class SessionManager {\n private _sessionId: string;\n private lastHiddenAt = 0;\n private lastActivityAt: number;\n private readonly timeout: number;\n private readonly onNewSession: (reason: SessionReason, sessionId: string) => void;\n private readonly visibilityHandler: () => void;\n private readonly checkTimer: ReturnType<typeof setInterval>;\n private lastContextAt: Record<string, number> = {};\n\n constructor(config: SessionManagerConfig) {\n this.timeout = config.timeout;\n this.onNewSession = config.onNewSession;\n this._sessionId = generateId();\n this.lastActivityAt = Date.now();\n\n this.emitContext(\"session_start\");\n\n this.visibilityHandler = () => this.handleVisibility();\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"visibilitychange\", this.visibilityHandler);\n }\n\n this.checkTimer = setInterval(() => this.checkTimeout(), 60_000);\n if (typeof (this.checkTimer as any).unref === \"function\") {\n (this.checkTimer as any).unref();\n }\n }\n\n get sessionId(): string {\n return this._sessionId;\n }\n\n set sessionId(id: string) {\n this._sessionId = id;\n }\n\n touch(): void {\n this.lastActivityAt = Date.now();\n }\n\n destroy(): void {\n if (typeof document !== \"undefined\") {\n document.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n }\n clearInterval(this.checkTimer);\n }\n\n private handleVisibility(): void {\n if (document.visibilityState === \"hidden\") {\n this.lastHiddenAt = Date.now();\n } else if (document.visibilityState === \"visible\") {\n if (this.lastHiddenAt > 0 && Date.now() - this.lastHiddenAt > this.timeout) {\n this.rotateSession(\"session_timeout\");\n } else if (this.lastHiddenAt > 0) {\n this.emitContext(\"app_foreground\");\n }\n this.lastHiddenAt = 0;\n }\n }\n\n private checkTimeout(): void {\n if (Date.now() - this.lastActivityAt > this.timeout) {\n this.rotateSession(\"session_timeout\");\n }\n }\n\n private rotateSession(reason: SessionReason): void {\n this._sessionId = generateId();\n this.lastActivityAt = Date.now();\n this.emitContext(reason);\n }\n\n private emitContext(reason: SessionReason): void {\n const now = Date.now();\n const last = this.lastContextAt[reason] ?? 0;\n if (now - last < 1000) return; // cooldown\n this.lastContextAt[reason] = now;\n this.onNewSession(reason, this._sessionId);\n }\n}\n","import type { JsonEvent, JsonLog } from \"@tell-rs/core\";\nimport { NetworkError } from \"@tell-rs/core\";\n\nexport interface BrowserTransportConfig {\n endpoint: string;\n apiKey: string;\n maxRetries: number;\n networkTimeout: number;\n onError?: (error: Error) => void;\n onPayloadTooLarge?: () => void;\n}\n\nexport class BrowserTransport {\n private readonly endpoint: string;\n private readonly apiKey: string;\n private readonly maxRetries: number;\n private readonly networkTimeout: number;\n private readonly onError?: (error: Error) => void;\n private readonly onPayloadTooLarge?: () => void;\n\n constructor(config: BrowserTransportConfig) {\n this.endpoint = config.endpoint;\n this.apiKey = config.apiKey;\n this.maxRetries = config.maxRetries;\n this.networkTimeout = config.networkTimeout;\n this.onError = config.onError;\n this.onPayloadTooLarge = config.onPayloadTooLarge;\n }\n\n async sendEvents(events: JsonEvent[]): Promise<void> {\n if (events.length === 0) return;\n const body = events.map((e) => JSON.stringify(e)).join(\"\\n\");\n await this.send(\"/v1/events\", body);\n }\n\n async sendLogs(logs: JsonLog[]): Promise<void> {\n if (logs.length === 0) return;\n const body = logs.map((l) => JSON.stringify(l)).join(\"\\n\");\n await this.send(\"/v1/logs\", body);\n }\n\n /** Best-effort flush via sendBeacon for page unload. */\n beacon(events: JsonEvent[], logs: JsonLog[]): void {\n if (typeof navigator === \"undefined\" || !navigator.sendBeacon) return;\n\n if (events.length > 0) {\n const body = events.map((e) => JSON.stringify(e)).join(\"\\n\");\n const blob = new Blob([body], { type: \"text/plain\" });\n const url = `${this.endpoint}/v1/events?token=${encodeURIComponent(this.apiKey)}`;\n navigator.sendBeacon(url, blob);\n }\n\n if (logs.length > 0) {\n const body = logs.map((l) => JSON.stringify(l)).join(\"\\n\");\n const blob = new Blob([body], { type: \"text/plain\" });\n const url = `${this.endpoint}/v1/logs?token=${encodeURIComponent(this.apiKey)}`;\n navigator.sendBeacon(url, blob);\n }\n }\n\n private resolvePort(): string {\n try {\n const u = new URL(this.endpoint);\n if (u.port) return u.port;\n return u.protocol === \"https:\" ? \"443\" : \"80\";\n } catch {\n return \"unknown\";\n }\n }\n\n private async send(path: string, body: string): Promise<void> {\n // Auth via query param + text/plain content-type keeps this a CORS\n // \"simple request\" — no preflight OPTIONS needed. This matches the\n // pattern used by beacon() and by every major analytics SDK.\n const url = `${this.endpoint}${path}?token=${encodeURIComponent(this.apiKey)}`;\n const port = this.resolvePort();\n const headers: Record<string, string> = {\n \"Content-Type\": \"text/plain\",\n };\n\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (attempt > 0) {\n await this.backoff(attempt);\n }\n\n // Skip attempt if browser reports offline\n if (typeof navigator !== \"undefined\" && !navigator.onLine) {\n lastError = new NetworkError(`Browser is offline (endpoint: ${url}, port: ${port})`);\n continue;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(\n () => controller.abort(),\n this.networkTimeout\n );\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n signal: controller.signal,\n keepalive: true,\n });\n\n if (response.status === 202) {\n return;\n }\n\n if (response.status === 207) {\n if (this.onError) {\n this.onError(\n new NetworkError(\n `Partial success: some items rejected`,\n 207\n )\n );\n }\n return;\n }\n\n if (response.status === 413) {\n if (this.onPayloadTooLarge) {\n this.onPayloadTooLarge();\n }\n throw new NetworkError(\"Payload too large\", 413);\n }\n\n if (response.status === 401) {\n throw new NetworkError(\"Invalid API key\", 401);\n }\n\n if (response.status >= 400 && response.status < 500) {\n throw new NetworkError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status\n );\n }\n\n // 5xx — retryable\n lastError = new NetworkError(\n `HTTP ${response.status} from ${url} (port ${port}): ${response.statusText}`,\n response.status\n );\n } catch (err) {\n if (err instanceof NetworkError && err.statusCode === 413) {\n throw err;\n }\n\n if (\n err instanceof NetworkError &&\n err.statusCode &&\n err.statusCode < 500\n ) {\n if (this.onError) this.onError(err);\n return;\n }\n\n // DNS failures, connection refused, and CORS errors surface as\n // TypeError from fetch. Include the full URL so the developer can\n // verify the endpoint and port. These won't resolve by retrying.\n if (err instanceof TypeError) {\n if (this.onError)\n this.onError(\n new NetworkError(\n `Failed to connect to ${url} (port ${port}): ${err.message}`\n )\n );\n return;\n }\n\n lastError =\n err instanceof Error ? err : new NetworkError(String(err));\n } finally {\n clearTimeout(timer);\n }\n }\n\n if (lastError && this.onError) {\n this.onError(lastError);\n }\n }\n\n private backoff(attempt: number): Promise<void> {\n const base = 1000 * Math.pow(1.5, attempt - 1);\n const jitter = base * 0.2 * Math.random();\n const delay = Math.min(base + jitter, 30_000);\n return new Promise((resolve) => setTimeout(resolve, delay));\n }\n}\n","import type { LogLevel, Properties } from \"@tell-rs/core\";\n\nexport type QueuedCall =\n | { method: \"track\"; args: [string, Properties?] }\n | { method: \"identify\"; args: [string, Properties?] }\n | { method: \"group\"; args: [string, Properties?] }\n | { method: \"revenue\"; args: [number, string, string, Properties?] }\n | { method: \"alias\"; args: [string, string] }\n | { method: \"log\"; args: [LogLevel, string, string?, Properties?] }\n | { method: \"register\"; args: [Properties] }\n | { method: \"unregister\"; args: [string] }\n | { method: \"optOut\"; args: [] }\n | { method: \"optIn\"; args: [] };\n\nexport class PreInitQueue {\n private items: QueuedCall[] = [];\n readonly maxSize: number;\n\n constructor(maxSize = 1000) {\n this.maxSize = maxSize;\n }\n\n push(call: QueuedCall): void {\n if (this.items.length >= this.maxSize) {\n this.items.shift(); // drop oldest\n }\n this.items.push(call);\n }\n\n replay(target: Record<string, (...args: any[]) => any>): void {\n const calls = this.items;\n this.items = [];\n for (const call of calls) {\n try {\n target[call.method](...call.args);\n } catch {\n // continue on per-call error\n }\n }\n }\n\n get length(): number {\n return this.items.length;\n }\n\n clear(): void {\n this.items = [];\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../../core/src/constants.ts","../../core/src/errors.ts","../../core/src/validation.ts","../../core/src/batcher.ts","../../core/src/before-send.ts","../../core/src/redact.ts","../src/config.ts","../src/persistence.ts","../src/id.ts","../src/bot.ts","../src/context.ts","../src/utm.ts","../src/session.ts","../src/transport.ts","../src/queue.ts"],"sourcesContent":["import type {\n JsonEvent,\n JsonLog,\n LogLevel,\n Properties,\n BeforeSendFn,\n} from \"@tell-rs/core\";\nimport {\n ClosedError,\n ConfigurationError,\n ValidationError,\n validateApiKey,\n validateEventName,\n validateLogMessage,\n validateUserId,\n Batcher,\n runBeforeSend,\n} from \"@tell-rs/core\";\n\nimport type { TellBrowserConfig, ResolvedBrowserConfig } from \"./config.js\";\nimport { resolveConfig } from \"./config.js\";\nimport type { TellStorage } from \"./persistence.js\";\nimport { createStorage, STORAGE_KEYS } from \"./persistence.js\";\nimport { generateId } from \"./id.js\";\nimport { isBot } from \"./bot.js\";\nimport { captureContext } from \"./context.js\";\nimport { captureUtm } from \"./utm.js\";\nimport type { SessionReason } from \"./session.js\";\nimport { SessionManager } from \"./session.js\";\nimport { BrowserTransport } from \"./transport.js\";\nimport { PreInitQueue } from \"./queue.js\";\n\n// Re-export core types and values\nexport { Events, type EventName } from \"@tell-rs/core\";\nexport type { Properties, LogLevel, JsonEvent, JsonLog, BeforeSendFn } from \"@tell-rs/core\";\nexport { redact, redactLog, SENSITIVE_PARAMS, type RedactOptions } from \"@tell-rs/core\";\nexport {\n TellError,\n ConfigurationError,\n ValidationError,\n NetworkError,\n ClosedError,\n SerializationError,\n} from \"@tell-rs/core\";\n\n// Re-export browser-specific config\nexport type { TellBrowserConfig } from \"./config.js\";\nexport { development, production } from \"./config.js\";\nexport type { DeviceContext } from \"./context.js\";\n\n// ---------------------------------------------------------------------------\n// Module-level state\n// ---------------------------------------------------------------------------\n\nlet configured = false;\nlet closed = false;\nlet _disabled = false;\nlet _optedOut = false;\n\nlet storage: TellStorage;\nlet transport: BrowserTransport;\nlet eventBatcher: Batcher<JsonEvent>;\nlet logBatcher: Batcher<JsonLog>;\nlet sessionManager: SessionManager;\nlet resolvedConfig: ResolvedBrowserConfig;\n\nlet _apiKey: string;\nlet deviceId: string;\nlet userId: string | undefined;\nlet superProperties: Properties = {};\nlet beforeSend: BeforeSendFn<JsonEvent> | BeforeSendFn<JsonEvent>[] | undefined;\nlet beforeSendLog:\n | BeforeSendFn<JsonLog>\n | BeforeSendFn<JsonLog>[]\n | undefined;\nlet sdkLogLevel: number;\n\nconst queue = new PreInitQueue(1000);\n\nlet unloadHandler: (() => void) | null = null;\nlet visibilityUnloadHandler: (() => void) | null = null;\nlet errorHandler: ((event: ErrorEvent) => void) | null = null;\nlet rejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;\n\nconst LOG_LEVELS: Record<string, number> = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction reportError(err: unknown): void {\n if (resolvedConfig?.onError && err instanceof Error) {\n resolvedConfig.onError(err);\n }\n}\n\nfunction sdkDebug(msg: string): void {\n if (sdkLogLevel >= LOG_LEVELS.debug) {\n console.debug(`[Tell] ${msg}`);\n }\n}\n\nfunction handleUnload(): void {\n const events = eventBatcher.drain();\n const logs = logBatcher.drain();\n transport.beacon(events, logs);\n}\n\nfunction handleVisibilityUnload(): void {\n if (document.visibilityState === \"hidden\") {\n handleUnload();\n }\n}\n\nfunction onNewSession(reason: SessionReason, sessionId: string): void {\n if (_disabled || _optedOut || closed) return;\n const ctx = captureContext();\n const event: JsonEvent = {\n type: \"context\",\n device_id: deviceId,\n session_id: sessionId,\n user_id: userId,\n timestamp: Date.now(),\n reason,\n ...ctx,\n };\n eventBatcher.add(event);\n}\n\nfunction persistSuperProps(): void {\n storage.set(STORAGE_KEYS.SUPER_PROPS, JSON.stringify(superProperties));\n}\n\nfunction loadSuperProps(): Properties {\n const raw = storage.get(STORAGE_KEYS.SUPER_PROPS);\n if (!raw) return {};\n try {\n return JSON.parse(raw) as Properties;\n } catch {\n storage.remove(STORAGE_KEYS.SUPER_PROPS);\n return {};\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport interface TellInstance {\n configure(apiKey: string, options?: TellBrowserConfig): void;\n track(eventName: string, properties?: Properties): void;\n identify(userId: string, traits?: Properties): void;\n group(groupId: string, properties?: Properties): void;\n revenue(\n amount: number,\n currency: string,\n orderId: string,\n properties?: Properties\n ): void;\n alias(previousId: string, userId: string): void;\n log(\n level: LogLevel,\n message: string,\n service?: string,\n data?: Properties\n ): void;\n logEmergency(message: string, service?: string, data?: Properties): void;\n logAlert(message: string, service?: string, data?: Properties): void;\n logCritical(message: string, service?: string, data?: Properties): void;\n logError(message: string, service?: string, data?: Properties): void;\n logWarning(message: string, service?: string, data?: Properties): void;\n logNotice(message: string, service?: string, data?: Properties): void;\n logInfo(message: string, service?: string, data?: Properties): void;\n logDebug(message: string, service?: string, data?: Properties): void;\n logTrace(message: string, service?: string, data?: Properties): void;\n register(properties: Properties): void;\n unregister(key: string): void;\n optOut(): void;\n optIn(): void;\n isOptedOut(): boolean;\n flush(): Promise<void>;\n close(): Promise<void>;\n reset(): void;\n enable(): void;\n disable(): void;\n /** @internal Reset all module state. Only for testing. */\n _resetForTesting(): void;\n}\n\nconst tell: TellInstance = {\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n configure(apiKey: string, options?: TellBrowserConfig): void {\n if (configured) {\n reportError(new ConfigurationError(\"Tell is already configured\"));\n return;\n }\n\n validateApiKey(apiKey);\n _apiKey = apiKey;\n resolvedConfig = resolveConfig(options);\n sdkLogLevel = LOG_LEVELS[resolvedConfig.logLevel] ?? 0;\n beforeSend = resolvedConfig.beforeSend;\n beforeSendLog = resolvedConfig.beforeSendLog;\n _disabled = resolvedConfig.disabled;\n\n // Persistence\n storage = createStorage(resolvedConfig.persistence);\n deviceId = storage.get(STORAGE_KEYS.DEVICE_ID) ?? generateId();\n storage.set(STORAGE_KEYS.DEVICE_ID, deviceId);\n userId = storage.get(STORAGE_KEYS.USER_ID) ?? undefined;\n _optedOut = storage.get(STORAGE_KEYS.OPT_OUT) === \"1\";\n superProperties = loadSuperProps();\n\n // UTM parameters — capture from URL and merge into super properties\n const utm = captureUtm();\n if (Object.keys(utm).length > 0) {\n Object.assign(superProperties, utm);\n persistSuperProps();\n }\n\n // Bot detection\n if (resolvedConfig.botDetection && isBot()) {\n _disabled = true;\n sdkDebug(\"bot detected, disabling\");\n }\n\n // Do Not Track\n if (\n resolvedConfig.respectDoNotTrack &&\n typeof navigator !== \"undefined\" &&\n navigator.doNotTrack === \"1\"\n ) {\n _disabled = true;\n sdkDebug(\"Do Not Track enabled, disabling\");\n }\n\n // Transport\n transport = new BrowserTransport({\n endpoint: resolvedConfig.endpoint,\n apiKey: _apiKey,\n maxRetries: resolvedConfig.maxRetries,\n networkTimeout: resolvedConfig.networkTimeout,\n onError: resolvedConfig.onError,\n onPayloadTooLarge: () => {\n eventBatcher.halveBatchSize();\n logBatcher.halveBatchSize();\n sdkDebug(\"413 received, halved batch size\");\n },\n });\n\n // Batchers\n eventBatcher = new Batcher<JsonEvent>({\n size: resolvedConfig.batchSize,\n interval: resolvedConfig.flushInterval,\n maxQueueSize: resolvedConfig.maxQueueSize,\n send: (items) => transport.sendEvents(items),\n onOverflow: () => sdkDebug(\"event queue overflow, dropping oldest\"),\n });\n\n logBatcher = new Batcher<JsonLog>({\n size: resolvedConfig.batchSize,\n interval: resolvedConfig.flushInterval,\n maxQueueSize: resolvedConfig.maxQueueSize,\n send: (items) => transport.sendLogs(items),\n onOverflow: () => sdkDebug(\"log queue overflow, dropping oldest\"),\n });\n\n // Session management\n sessionManager = new SessionManager({\n timeout: resolvedConfig.sessionTimeout,\n onNewSession,\n });\n\n // Unload handlers\n if (typeof window !== \"undefined\") {\n unloadHandler = handleUnload;\n window.addEventListener(\"beforeunload\", unloadHandler);\n }\n if (typeof document !== \"undefined\") {\n visibilityUnloadHandler = handleVisibilityUnload;\n document.addEventListener(\"visibilitychange\", visibilityUnloadHandler);\n }\n\n // Error auto-capture\n if (resolvedConfig.captureErrors && typeof window !== \"undefined\") {\n errorHandler = (event: ErrorEvent) => {\n if (_disabled || _optedOut || closed) return;\n const msg = event.message || \"Unknown error\";\n const data: Properties = {};\n if (event.filename) data.filename = event.filename;\n if (event.lineno) data.lineno = event.lineno;\n if (event.colno) data.colno = event.colno;\n if (event.error?.stack) data.stack = event.error.stack;\n tell.logError(msg, \"browser\", data);\n };\n rejectionHandler = (event: PromiseRejectionEvent) => {\n if (_disabled || _optedOut || closed) return;\n const reason = event.reason;\n const msg =\n reason instanceof Error\n ? reason.message\n : String(reason ?? \"Unhandled promise rejection\");\n const data: Properties = {};\n if (reason instanceof Error && reason.stack) data.stack = reason.stack;\n tell.logError(msg, \"browser\", data);\n };\n window.addEventListener(\"error\", errorHandler);\n window.addEventListener(\"unhandledrejection\", rejectionHandler);\n }\n\n configured = true;\n closed = false;\n\n sdkDebug(\n `configured (endpoint=${resolvedConfig.endpoint}, batch=${resolvedConfig.batchSize})`\n );\n\n // Replay pre-init queue\n queue.replay(tell as unknown as Record<string, (...args: any[]) => any>);\n },\n\n // -----------------------------------------------------------------------\n // Events\n // -----------------------------------------------------------------------\n\n track(eventName: string, properties?: Properties): void {\n if (!configured) {\n queue.push({ method: \"track\", args: [eventName, properties] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n validateEventName(eventName);\n } catch (err) {\n reportError(err);\n return;\n }\n\n sessionManager.touch();\n\n let event: JsonEvent | null = {\n type: \"track\",\n event: eventName,\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n timestamp: Date.now(),\n ...superProperties,\n ...properties,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n eventBatcher.add(event);\n },\n\n identify(newUserId: string, traits?: Properties): void {\n if (!configured) {\n queue.push({ method: \"identify\", args: [newUserId, traits] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n validateUserId(newUserId);\n } catch (err) {\n reportError(err);\n return;\n }\n\n userId = newUserId;\n storage.set(STORAGE_KEYS.USER_ID, userId);\n\n sessionManager.touch();\n\n let event: JsonEvent | null = {\n type: \"identify\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n timestamp: Date.now(),\n ...traits,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n eventBatcher.add(event);\n },\n\n group(groupId: string, properties?: Properties): void {\n if (!configured) {\n queue.push({ method: \"group\", args: [groupId, properties] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n if (!groupId) throw new ValidationError(\"groupId\", \"is required\");\n } catch (err) {\n reportError(err);\n return;\n }\n\n sessionManager.touch();\n\n let event: JsonEvent | null = {\n type: \"group\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n group_id: groupId,\n timestamp: Date.now(),\n ...superProperties,\n ...properties,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n eventBatcher.add(event);\n },\n\n revenue(\n amount: number,\n currency: string,\n orderId: string,\n properties?: Properties\n ): void {\n if (!configured) {\n queue.push({ method: \"revenue\", args: [amount, currency, orderId, properties] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n if (amount <= 0) throw new ValidationError(\"amount\", \"must be positive\");\n if (!currency) throw new ValidationError(\"currency\", \"is required\");\n if (!orderId) throw new ValidationError(\"orderId\", \"is required\");\n } catch (err) {\n reportError(err);\n return;\n }\n\n sessionManager.touch();\n\n let event: JsonEvent | null = {\n type: \"track\",\n event: \"Order Completed\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n timestamp: Date.now(),\n ...superProperties,\n ...properties,\n order_id: orderId,\n amount,\n currency,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n eventBatcher.add(event);\n },\n\n alias(previousId: string, newUserId: string): void {\n if (!configured) {\n queue.push({ method: \"alias\", args: [previousId, newUserId] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n if (!previousId)\n throw new ValidationError(\"previousId\", \"is required\");\n validateUserId(newUserId);\n } catch (err) {\n reportError(err);\n return;\n }\n\n sessionManager.touch();\n\n let event: JsonEvent | null = {\n type: \"alias\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: newUserId,\n timestamp: Date.now(),\n previous_id: previousId,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n eventBatcher.add(event);\n },\n\n // -----------------------------------------------------------------------\n // Logging\n // -----------------------------------------------------------------------\n\n log(\n level: LogLevel,\n message: string,\n service?: string,\n data?: Properties\n ): void {\n if (!configured) {\n queue.push({ method: \"log\", args: [level, message, service, data] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n validateLogMessage(message);\n } catch (err) {\n reportError(err);\n return;\n }\n\n let logEntry: JsonLog | null = {\n level,\n message,\n source: resolvedConfig.source,\n service: service ?? \"app\",\n session_id: sessionManager.sessionId,\n timestamp: Date.now(),\n data,\n };\n\n if (beforeSendLog) {\n logEntry = runBeforeSend(logEntry, beforeSendLog);\n if (logEntry === null) return;\n }\n\n logBatcher.add(logEntry);\n },\n\n logEmergency(message: string, service?: string, data?: Properties): void {\n tell.log(\"emergency\", message, service, data);\n },\n logAlert(message: string, service?: string, data?: Properties): void {\n tell.log(\"alert\", message, service, data);\n },\n logCritical(message: string, service?: string, data?: Properties): void {\n tell.log(\"critical\", message, service, data);\n },\n logError(message: string, service?: string, data?: Properties): void {\n tell.log(\"error\", message, service, data);\n },\n logWarning(message: string, service?: string, data?: Properties): void {\n tell.log(\"warning\", message, service, data);\n },\n logNotice(message: string, service?: string, data?: Properties): void {\n tell.log(\"notice\", message, service, data);\n },\n logInfo(message: string, service?: string, data?: Properties): void {\n tell.log(\"info\", message, service, data);\n },\n logDebug(message: string, service?: string, data?: Properties): void {\n tell.log(\"debug\", message, service, data);\n },\n logTrace(message: string, service?: string, data?: Properties): void {\n tell.log(\"trace\", message, service, data);\n },\n\n // -----------------------------------------------------------------------\n // Super Properties\n // -----------------------------------------------------------------------\n\n register(properties: Properties): void {\n if (!configured) {\n queue.push({ method: \"register\", args: [properties] });\n return;\n }\n Object.assign(superProperties, properties);\n persistSuperProps();\n },\n\n unregister(key: string): void {\n if (!configured) {\n queue.push({ method: \"unregister\", args: [key] });\n return;\n }\n delete superProperties[key];\n persistSuperProps();\n },\n\n // -----------------------------------------------------------------------\n // Privacy\n // -----------------------------------------------------------------------\n\n optOut(): void {\n if (!configured) {\n queue.push({ method: \"optOut\", args: [] });\n return;\n }\n _optedOut = true;\n storage.set(STORAGE_KEYS.OPT_OUT, \"1\");\n },\n\n optIn(): void {\n if (!configured) {\n queue.push({ method: \"optIn\", args: [] });\n return;\n }\n _optedOut = false;\n storage.remove(STORAGE_KEYS.OPT_OUT);\n },\n\n isOptedOut(): boolean {\n return _optedOut;\n },\n\n // -----------------------------------------------------------------------\n // Control\n // -----------------------------------------------------------------------\n\n enable(): void {\n _disabled = false;\n },\n\n disable(): void {\n _disabled = true;\n },\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n async flush(): Promise<void> {\n if (!configured) return;\n await Promise.all([eventBatcher.flush(), logBatcher.flush()]);\n },\n\n async close(): Promise<void> {\n if (!configured || closed) return;\n closed = true;\n\n if (sessionManager) sessionManager.destroy();\n\n if (typeof window !== \"undefined\" && unloadHandler) {\n window.removeEventListener(\"beforeunload\", unloadHandler);\n unloadHandler = null;\n }\n if (typeof document !== \"undefined\" && visibilityUnloadHandler) {\n document.removeEventListener(\"visibilitychange\", visibilityUnloadHandler);\n visibilityUnloadHandler = null;\n }\n if (typeof window !== \"undefined\") {\n if (errorHandler) {\n window.removeEventListener(\"error\", errorHandler);\n errorHandler = null;\n }\n if (rejectionHandler) {\n window.removeEventListener(\"unhandledrejection\", rejectionHandler);\n rejectionHandler = null;\n }\n }\n\n const work = Promise.all([eventBatcher.close(), logBatcher.close()]);\n const timeout = new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(\"close timed out\")),\n resolvedConfig.closeTimeout\n )\n );\n\n try {\n await Promise.race([work, timeout]);\n } catch (err) {\n reportError(err);\n }\n\n configured = false;\n },\n\n reset(): void {\n if (!configured) return;\n userId = undefined;\n deviceId = generateId();\n superProperties = {};\n\n storage.remove(STORAGE_KEYS.USER_ID);\n storage.set(STORAGE_KEYS.DEVICE_ID, deviceId);\n storage.remove(STORAGE_KEYS.SUPER_PROPS);\n\n if (sessionManager) {\n sessionManager.sessionId = generateId();\n }\n },\n\n // -----------------------------------------------------------------------\n // Testing helper\n // -----------------------------------------------------------------------\n\n _resetForTesting(): void {\n if (configured && !closed) {\n // Synchronously tear down timers\n if (sessionManager) sessionManager.destroy();\n if (eventBatcher) {\n eventBatcher.drain();\n eventBatcher.close().catch(() => {});\n }\n if (logBatcher) {\n logBatcher.drain();\n logBatcher.close().catch(() => {});\n }\n if (typeof window !== \"undefined\" && unloadHandler) {\n window.removeEventListener(\"beforeunload\", unloadHandler);\n }\n if (typeof document !== \"undefined\" && visibilityUnloadHandler) {\n document.removeEventListener(\n \"visibilitychange\",\n visibilityUnloadHandler\n );\n }\n if (typeof window !== \"undefined\") {\n if (errorHandler) window.removeEventListener(\"error\", errorHandler);\n if (rejectionHandler)\n window.removeEventListener(\"unhandledrejection\", rejectionHandler);\n }\n }\n\n configured = false;\n closed = false;\n _disabled = false;\n _optedOut = false;\n userId = undefined;\n deviceId = \"\";\n superProperties = {};\n beforeSend = undefined;\n beforeSendLog = undefined;\n sdkLogLevel = 0;\n unloadHandler = null;\n visibilityUnloadHandler = null;\n errorHandler = null;\n rejectionHandler = null;\n queue.clear();\n },\n};\n\nexport default tell;\nexport { tell };\n","// Standard event names — typed constants matching the spec appendix A\n\nexport const Events = {\n // User Lifecycle\n UserSignedUp: \"User Signed Up\",\n UserSignedIn: \"User Signed In\",\n UserSignedOut: \"User Signed Out\",\n UserInvited: \"User Invited\",\n UserOnboarded: \"User Onboarded\",\n AuthenticationFailed: \"Authentication Failed\",\n PasswordReset: \"Password Reset\",\n TwoFactorEnabled: \"Two Factor Enabled\",\n TwoFactorDisabled: \"Two Factor Disabled\",\n\n // Revenue & Billing\n OrderCompleted: \"Order Completed\",\n OrderRefunded: \"Order Refunded\",\n OrderCanceled: \"Order Canceled\",\n PaymentFailed: \"Payment Failed\",\n PaymentMethodAdded: \"Payment Method Added\",\n PaymentMethodUpdated: \"Payment Method Updated\",\n PaymentMethodRemoved: \"Payment Method Removed\",\n\n // Subscription\n SubscriptionStarted: \"Subscription Started\",\n SubscriptionRenewed: \"Subscription Renewed\",\n SubscriptionPaused: \"Subscription Paused\",\n SubscriptionResumed: \"Subscription Resumed\",\n SubscriptionChanged: \"Subscription Changed\",\n SubscriptionCanceled: \"Subscription Canceled\",\n\n // Trial\n TrialStarted: \"Trial Started\",\n TrialEndingSoon: \"Trial Ending Soon\",\n TrialEnded: \"Trial Ended\",\n TrialConverted: \"Trial Converted\",\n\n // Shopping\n CartViewed: \"Cart Viewed\",\n CartUpdated: \"Cart Updated\",\n CartAbandoned: \"Cart Abandoned\",\n CheckoutStarted: \"Checkout Started\",\n CheckoutCompleted: \"Checkout Completed\",\n\n // Engagement\n PageViewed: \"Page Viewed\",\n FeatureUsed: \"Feature Used\",\n SearchPerformed: \"Search Performed\",\n FileUploaded: \"File Uploaded\",\n NotificationSent: \"Notification Sent\",\n NotificationClicked: \"Notification Clicked\",\n\n // Communication\n EmailSent: \"Email Sent\",\n EmailOpened: \"Email Opened\",\n EmailClicked: \"Email Clicked\",\n EmailBounced: \"Email Bounced\",\n EmailUnsubscribed: \"Email Unsubscribed\",\n SupportTicketCreated: \"Support Ticket Created\",\n SupportTicketResolved: \"Support Ticket Resolved\",\n} as const;\n\nexport type EventName = (typeof Events)[keyof typeof Events];\n","export class TellError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TellError\";\n }\n}\n\nexport class ConfigurationError extends TellError {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigurationError\";\n }\n}\n\nexport class ValidationError extends TellError {\n public readonly field: string;\n\n constructor(field: string, message: string) {\n super(`${field}: ${message}`);\n this.name = \"ValidationError\";\n this.field = field;\n }\n}\n\nexport class NetworkError extends TellError {\n public readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.name = \"NetworkError\";\n this.statusCode = statusCode;\n }\n}\n\nexport class ClosedError extends TellError {\n constructor() {\n super(\"Client is closed\");\n this.name = \"ClosedError\";\n }\n}\n\nexport class SerializationError extends TellError {\n constructor(message: string) {\n super(message);\n this.name = \"SerializationError\";\n }\n}\n","import { ConfigurationError, ValidationError } from \"./errors.js\";\n\nconst HEX_RE = /^[0-9a-fA-F]{32}$/;\nconst MAX_EVENT_NAME = 256;\nconst MAX_LOG_MESSAGE = 65_536;\n\nexport function validateApiKey(key: string): void {\n if (!key) {\n throw new ConfigurationError(\"apiKey is required\");\n }\n if (!HEX_RE.test(key)) {\n throw new ConfigurationError(\n \"apiKey must be exactly 32 hex characters\"\n );\n }\n}\n\nexport function validateEventName(name: unknown): void {\n if (typeof name !== \"string\" || name.length === 0) {\n throw new ValidationError(\"eventName\", \"must be a non-empty string\");\n }\n if (name.length > MAX_EVENT_NAME) {\n throw new ValidationError(\n \"eventName\",\n `must be at most ${MAX_EVENT_NAME} characters, got ${name.length}`\n );\n }\n}\n\nexport function validateLogMessage(message: unknown): void {\n if (typeof message !== \"string\" || message.length === 0) {\n throw new ValidationError(\"message\", \"must be a non-empty string\");\n }\n if (message.length > MAX_LOG_MESSAGE) {\n throw new ValidationError(\n \"message\",\n `must be at most ${MAX_LOG_MESSAGE} characters, got ${message.length}`\n );\n }\n}\n\nexport function validateUserId(id: unknown): void {\n if (typeof id !== \"string\" || id.length === 0) {\n throw new ValidationError(\"userId\", \"must be a non-empty string\");\n }\n}\n","export interface BatcherConfig<T> {\n size: number;\n interval: number; // ms\n maxQueueSize: number;\n send: (items: T[]) => Promise<void>;\n onOverflow?: () => void;\n}\n\nexport class Batcher<T> {\n private queue: T[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private closed = false;\n private flushing: Promise<void> | null = null;\n private config: BatcherConfig<T>;\n\n constructor(config: BatcherConfig<T>) {\n this.config = config;\n this.timer = setInterval(() => {\n if (this.queue.length > 0) {\n this.flush().catch(() => {});\n }\n }, config.interval);\n // Don't keep Node.js process alive just for flush timer\n if (this.timer && typeof (this.timer as any).unref === \"function\") {\n (this.timer as any).unref();\n }\n }\n\n add(item: T): void {\n if (this.closed) return;\n\n if (this.queue.length >= this.config.maxQueueSize) {\n this.queue.shift(); // drop oldest\n if (this.config.onOverflow) {\n this.config.onOverflow();\n }\n }\n\n this.queue.push(item);\n\n if (this.queue.length >= this.config.size) {\n this.flush().catch(() => {});\n }\n }\n\n async flush(): Promise<void> {\n // Prevent concurrent flushes\n if (this.flushing) {\n return this.flushing;\n }\n this.flushing = this.doFlush();\n try {\n await this.flushing;\n } finally {\n this.flushing = null;\n }\n }\n\n async close(): Promise<void> {\n this.closed = true;\n if (this.timer !== null) {\n clearInterval(this.timer);\n this.timer = null;\n }\n await this.flush();\n }\n\n get pending(): number {\n return this.queue.length;\n }\n\n drain(): T[] {\n const items = this.queue;\n this.queue = [];\n return items;\n }\n\n halveBatchSize(): void {\n this.config.size = Math.max(1, Math.floor(this.config.size / 2));\n }\n\n private async doFlush(): Promise<void> {\n while (this.queue.length > 0) {\n const batch = this.queue.slice(0, this.config.size);\n try {\n await this.config.send(batch);\n this.queue.splice(0, batch.length); // remove only on success\n } catch {\n return; // items stay in queue (e.g. 413 — batch size already halved)\n }\n }\n }\n}\n","/**\n * A function that transforms or drops an item before it is queued.\n * Return the (possibly modified) item, or null to drop it.\n */\nexport type BeforeSendFn<T> = (item: T) => T | null;\n\n/**\n * Run an item through a pipeline of beforeSend functions.\n * Returns the transformed item, or null if any function in the chain drops it.\n */\nexport function runBeforeSend<T>(\n item: T,\n fns: BeforeSendFn<T> | BeforeSendFn<T>[]\n): T | null {\n const pipeline = Array.isArray(fns) ? fns : [fns];\n let current: T | null = item;\n\n for (const fn of pipeline) {\n if (current === null) return null;\n current = fn(current);\n }\n\n return current;\n}\n","import type { BeforeSendFn } from \"./before-send.js\";\nimport type { JsonEvent, JsonLog, Properties } from \"./types.js\";\n\n/**\n * Common query-parameter names that often carry secrets or tokens.\n * Pass these (or a subset) to `stripParams` for quick sanitization.\n */\nexport const SENSITIVE_PARAMS: readonly string[] = [\n \"token\",\n \"api_key\",\n \"key\",\n \"secret\",\n \"password\",\n \"access_token\",\n \"refresh_token\",\n \"authorization\",\n] as const;\n\nexport interface RedactOptions {\n /** Query-parameter names to strip from URL-shaped values. */\n stripParams?: string[];\n /** Keys whose values should be replaced with \"[REDACTED]\". */\n redactKeys?: string[];\n /** URL pathname prefixes — events whose url matches are dropped entirely. */\n dropRoutes?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction stripUrlParams(url: string, params: string[]): string {\n try {\n const u = new URL(url);\n for (const p of params) u.searchParams.delete(p);\n return u.toString();\n } catch {\n return url; // not a valid URL — leave as-is\n }\n}\n\nfunction redactKeysInProperties(\n props: Properties | undefined,\n keys: string[],\n): Properties | undefined {\n if (!props) return props;\n const out: Properties = {};\n for (const [k, v] of Object.entries(props)) {\n out[k] = keys.includes(k) ? \"[REDACTED]\" : v;\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Factory that returns a `beforeSend` hook for events.\n *\n * - `dropRoutes` — drops events whose `url` pathname starts with a prefix.\n * - `stripParams` — removes query params from URL-shaped string values.\n * - `redactKeys` — replaces matching keys with `\"[REDACTED]\"`.\n *\n * The returned function never mutates the input event.\n */\nexport function redact(options: RedactOptions): BeforeSendFn<JsonEvent> {\n const { stripParams, redactKeys, dropRoutes } = options;\n\n return (event: JsonEvent): JsonEvent | null => {\n // --- dropRoutes ---\n if (dropRoutes && dropRoutes.length > 0 && event.url) {\n try {\n const pathname = new URL(String(event.url)).pathname;\n for (const prefix of dropRoutes) {\n if (pathname.startsWith(prefix)) return null;\n }\n } catch {\n // not a valid URL — skip drop check\n }\n }\n\n let result: JsonEvent = event;\n\n // --- stripParams ---\n if (stripParams && stripParams.length > 0) {\n for (const [k, v] of Object.entries(event)) {\n if (typeof v === \"string\" && v.startsWith(\"http\")) {\n const stripped = stripUrlParams(v, stripParams);\n if (stripped !== v) {\n if (result === event) result = { ...event };\n result[k] = stripped;\n }\n }\n }\n }\n\n // --- redactKeys ---\n if (redactKeys && redactKeys.length > 0) {\n for (const [k, v] of Object.entries(event)) {\n if (redactKeys.includes(k)) {\n if (result === event) result = { ...event };\n result[k] = \"[REDACTED]\";\n }\n }\n }\n\n return result;\n };\n}\n\n/**\n * Factory that returns a `beforeSend` hook for log entries.\n *\n * - `redactKeys` — replaces matching keys in `log.data` with `\"[REDACTED]\"`.\n *\n * The returned function never mutates the input log.\n */\nexport function redactLog(\n options: Pick<RedactOptions, \"redactKeys\">,\n): BeforeSendFn<JsonLog> {\n const { redactKeys } = options;\n\n return (log: JsonLog): JsonLog | null => {\n if (redactKeys && redactKeys.length > 0 && log.data) {\n const data = redactKeysInProperties(log.data, redactKeys);\n if (data !== log.data) {\n return { ...log, data };\n }\n }\n return log;\n };\n}\n","import type { TellError, BeforeSendFn, JsonEvent, JsonLog } from \"@tell-rs/core\";\n\nexport interface TellBrowserConfig {\n endpoint?: string;\n batchSize?: number;\n flushInterval?: number;\n maxRetries?: number;\n closeTimeout?: number;\n networkTimeout?: number;\n logLevel?: \"error\" | \"warn\" | \"info\" | \"debug\";\n source?: string;\n onError?: (error: TellError) => void;\n disabled?: boolean;\n maxQueueSize?: number;\n sessionTimeout?: number;\n persistence?: \"localStorage\" | \"memory\";\n respectDoNotTrack?: boolean;\n botDetection?: boolean;\n captureErrors?: boolean;\n beforeSend?: BeforeSendFn<JsonEvent> | BeforeSendFn<JsonEvent>[];\n beforeSendLog?: BeforeSendFn<JsonLog> | BeforeSendFn<JsonLog>[];\n}\n\nexport const DEFAULTS = {\n endpoint: \"https://collect.tell.app\",\n batchSize: 20,\n flushInterval: 5_000,\n maxRetries: 5,\n closeTimeout: 5_000,\n networkTimeout: 10_000,\n logLevel: \"error\" as const,\n source: \"browser\",\n disabled: false,\n maxQueueSize: 1000,\n sessionTimeout: 1_800_000, // 30 min\n persistence: \"localStorage\" as const,\n respectDoNotTrack: false,\n botDetection: true,\n captureErrors: false,\n} as const;\n\nexport type ResolvedBrowserConfig = Required<\n Omit<TellBrowserConfig, \"onError\" | \"beforeSend\" | \"beforeSendLog\">\n> &\n Pick<TellBrowserConfig, \"onError\" | \"beforeSend\" | \"beforeSendLog\">;\n\nexport function resolveConfig(\n options: TellBrowserConfig | undefined\n): ResolvedBrowserConfig {\n return { ...DEFAULTS, ...options } as ResolvedBrowserConfig;\n}\n\n/** Development preset: localhost, small batches, fast flush, debug logging. */\nexport function development(\n overrides?: Partial<TellBrowserConfig>\n): TellBrowserConfig {\n return {\n endpoint: \"http://localhost:8080\",\n batchSize: 5,\n flushInterval: 2_000,\n logLevel: \"debug\",\n ...overrides,\n };\n}\n\n/** Production preset: default endpoint, error-only logging. */\nexport function production(\n overrides?: Partial<TellBrowserConfig>\n): TellBrowserConfig {\n return {\n logLevel: \"error\",\n ...overrides,\n };\n}\n","export interface TellStorage {\n get(key: string): string | null;\n set(key: string, value: string): void;\n remove(key: string): void;\n}\n\nexport const STORAGE_KEYS = {\n DEVICE_ID: \"tell_device_id\",\n USER_ID: \"tell_user_id\",\n OPT_OUT: \"tell_opt_out\",\n SUPER_PROPS: \"tell_super_props\",\n} as const;\n\nclass LocalStorageStorage implements TellStorage {\n get(key: string): string | null {\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n }\n\n set(key: string, value: string): void {\n try {\n localStorage.setItem(key, value);\n } catch {\n // Safari private mode or quota exceeded\n }\n }\n\n remove(key: string): void {\n try {\n localStorage.removeItem(key);\n } catch {\n // ignore\n }\n }\n}\n\nclass MemoryStorage implements TellStorage {\n private data = new Map<string, string>();\n\n get(key: string): string | null {\n return this.data.get(key) ?? null;\n }\n\n set(key: string, value: string): void {\n this.data.set(key, value);\n }\n\n remove(key: string): void {\n this.data.delete(key);\n }\n}\n\n/** Create a storage backend. Falls back to memory if localStorage is unavailable. */\nexport function createStorage(\n persistence: \"localStorage\" | \"memory\"\n): TellStorage {\n if (persistence === \"localStorage\" && typeof localStorage !== \"undefined\") {\n try {\n const testKey = \"tell_test\";\n localStorage.setItem(testKey, \"1\");\n localStorage.removeItem(testKey);\n return new LocalStorageStorage();\n } catch {\n // probe failed — fall through to memory\n }\n }\n return new MemoryStorage();\n}\n","/** Generate a 32-char hex ID (16 random bytes) using crypto.getRandomValues. */\nexport function generateId(): string {\n if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n return Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n // Fallback for environments without crypto (extremely rare)\n let hex = \"\";\n for (let i = 0; i < 32; i++) {\n hex += ((Math.random() * 16) | 0).toString(16);\n }\n return hex;\n}\n","/** Returns true if the current environment appears to be an automated bot. */\nexport function isBot(): boolean {\n if (typeof navigator === \"undefined\") return false;\n if ((navigator as any).webdriver === true) return true;\n const ua = navigator.userAgent || \"\";\n return /headless/i.test(ua);\n}\n","export interface DeviceContext {\n browser?: string;\n browser_version?: string;\n os_name?: string;\n os_version?: string;\n device_type?: string;\n screen_width?: number;\n screen_height?: number;\n viewport_width?: number;\n viewport_height?: number;\n device_pixel_ratio?: number;\n locale?: string;\n timezone?: string;\n referrer?: string;\n referrer_domain?: string;\n url?: string;\n title?: string;\n connection_type?: string;\n downlink?: number;\n rtt?: number;\n save_data?: boolean;\n cpu_cores?: number;\n device_memory?: number;\n touch?: boolean;\n bot?: boolean;\n dark_mode?: boolean;\n path?: string;\n screen_orientation?: string;\n}\n\n/** Capture a snapshot of the current device/browser context. */\nexport function captureContext(): DeviceContext {\n const ctx: DeviceContext = {};\n\n if (typeof navigator !== \"undefined\") {\n const ua = navigator.userAgent || \"\";\n const parsed = parseUA(ua);\n ctx.browser = parsed.browser;\n ctx.browser_version = parsed.browserVersion;\n ctx.os_name = parsed.os;\n ctx.os_version = parsed.osVersion;\n ctx.locale = navigator.language;\n\n // Hardware capabilities (touch must come before device_type inference)\n if (\"hardwareConcurrency\" in navigator) {\n ctx.cpu_cores = (navigator as any).hardwareConcurrency;\n }\n if (\"deviceMemory\" in navigator) {\n ctx.device_memory = (navigator as any).deviceMemory;\n }\n if (\"maxTouchPoints\" in navigator) {\n ctx.touch = navigator.maxTouchPoints > 0;\n }\n\n ctx.device_type = inferDeviceType(parsed.os, ua, ctx.touch);\n\n // Network info (Chrome/Edge)\n const conn = (navigator as any).connection;\n if (conn) {\n if (conn.effectiveType) ctx.connection_type = conn.effectiveType;\n if (typeof conn.downlink === \"number\") ctx.downlink = conn.downlink;\n if (typeof conn.rtt === \"number\") ctx.rtt = conn.rtt;\n if (conn.saveData) ctx.save_data = true;\n }\n\n // Bot detection\n if ((navigator as any).webdriver) ctx.bot = true;\n }\n\n if (typeof screen !== \"undefined\") {\n ctx.screen_width = screen.width;\n ctx.screen_height = screen.height;\n const orient = (screen as any).orientation;\n if (orient?.type) ctx.screen_orientation = orient.type;\n }\n\n if (typeof window !== \"undefined\") {\n ctx.viewport_width = window.innerWidth;\n ctx.viewport_height = window.innerHeight;\n if (window.devicePixelRatio) {\n ctx.device_pixel_ratio = window.devicePixelRatio;\n }\n }\n\n if (typeof document !== \"undefined\") {\n ctx.referrer = document.referrer || undefined;\n if (ctx.referrer) {\n try {\n ctx.referrer_domain = new URL(ctx.referrer).hostname;\n } catch {\n // malformed referrer\n }\n }\n ctx.title = document.title || undefined;\n }\n\n if (typeof location !== \"undefined\") {\n ctx.url = location.href;\n if (location.pathname) ctx.path = location.pathname;\n }\n\n try {\n ctx.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n // Intl not available\n }\n\n if (typeof window !== \"undefined\" && window.matchMedia) {\n try {\n ctx.dark_mode = window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n } catch {\n // matchMedia not available\n }\n }\n\n return ctx;\n}\n\nfunction inferDeviceType(os?: string, ua?: string, touch?: boolean): string {\n // iPad (iPadOS 13+) reports as macOS but has touch support\n if (os === \"macOS\" && touch) return \"tablet\";\n // Android tablets have \"Android\" in UA but not \"Mobile\"\n if (os === \"Android\") return ua && !/Mobile/.test(ua) ? \"tablet\" : \"mobile\";\n if (os === \"iOS\") return \"mobile\";\n return \"desktop\";\n}\n\ninterface ParsedUA {\n browser?: string;\n browserVersion?: string;\n os?: string;\n osVersion?: string;\n}\n\nfunction parseUA(ua: string): ParsedUA {\n const result: ParsedUA = {};\n\n // Browser detection (order matters: Edge before Chrome, Chrome before Safari)\n if (/Edg\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Edge\";\n result.browserVersion = RegExp.$1;\n } else if (/OPR\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Opera\";\n result.browserVersion = RegExp.$1;\n } else if (/Chrome\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Chrome\";\n result.browserVersion = RegExp.$1;\n } else if (/Safari\\/[\\d.]+/.test(ua) && /Version\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Safari\";\n result.browserVersion = RegExp.$1;\n } else if (/Firefox\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Firefox\";\n result.browserVersion = RegExp.$1;\n }\n\n // OS detection\n if (/Windows NT ([\\d.]+)/.test(ua)) {\n result.os = \"Windows\";\n result.osVersion = RegExp.$1;\n } else if (/Mac OS X ([\\d_.]+)/.test(ua)) {\n result.os = \"macOS\";\n result.osVersion = RegExp.$1.replace(/_/g, \".\");\n } else if (/iPhone OS ([\\d_]+)/.test(ua)) {\n result.os = \"iOS\";\n result.osVersion = RegExp.$1.replace(/_/g, \".\");\n } else if (/Android ([\\d.]+)/.test(ua)) {\n result.os = \"Android\";\n result.osVersion = RegExp.$1;\n } else if (/Linux/.test(ua)) {\n result.os = \"Linux\";\n }\n\n return result;\n}\n","import type { Properties } from \"@tell-rs/core\";\n\nconst UTM_KEYS = [\n \"utm_source\",\n \"utm_medium\",\n \"utm_campaign\",\n \"utm_term\",\n \"utm_content\",\n] as const;\n\n/**\n * Extract UTM parameters from the current URL search string.\n * Returns only keys that are present and non-empty.\n */\nexport function captureUtm(): Properties {\n if (typeof window === \"undefined\" || !window.location?.search) return {};\n\n const params = new URLSearchParams(window.location.search);\n const utm: Properties = {};\n\n for (const key of UTM_KEYS) {\n const value = params.get(key);\n if (value) {\n utm[key] = value;\n }\n }\n\n return utm;\n}\n","import { generateId } from \"./id.js\";\n\nexport type SessionReason = \"session_start\" | \"session_timeout\" | \"app_foreground\";\n\nexport interface SessionManagerConfig {\n timeout: number; // ms\n onNewSession: (reason: SessionReason, sessionId: string) => void;\n}\n\nexport class SessionManager {\n private _sessionId: string;\n private lastHiddenAt = 0;\n private lastActivityAt: number;\n private readonly timeout: number;\n private readonly onNewSession: (reason: SessionReason, sessionId: string) => void;\n private readonly visibilityHandler: () => void;\n private lastContextAt: Record<string, number> = {};\n\n constructor(config: SessionManagerConfig) {\n this.timeout = config.timeout;\n this.onNewSession = config.onNewSession;\n this._sessionId = generateId();\n this.lastActivityAt = Date.now();\n\n this.emitContext(\"session_start\");\n\n this.visibilityHandler = () => this.handleVisibility();\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"visibilitychange\", this.visibilityHandler);\n }\n }\n\n get sessionId(): string {\n return this._sessionId;\n }\n\n set sessionId(id: string) {\n this._sessionId = id;\n }\n\n /** Update activity timestamp; rotates session if idle longer than timeout. */\n touch(): void {\n const now = Date.now();\n if (now - this.lastActivityAt > this.timeout) {\n this.rotateSession(\"session_timeout\");\n }\n this.lastActivityAt = now;\n }\n\n destroy(): void {\n if (typeof document !== \"undefined\") {\n document.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n }\n }\n\n private handleVisibility(): void {\n if (document.visibilityState === \"hidden\") {\n this.lastHiddenAt = Date.now();\n } else if (document.visibilityState === \"visible\") {\n if (this.lastHiddenAt > 0 && Date.now() - this.lastHiddenAt > this.timeout) {\n this.rotateSession(\"session_timeout\");\n } else if (this.lastHiddenAt > 0) {\n this.emitContext(\"app_foreground\");\n }\n this.lastHiddenAt = 0;\n }\n }\n\n private rotateSession(reason: SessionReason): void {\n this._sessionId = generateId();\n this.lastActivityAt = Date.now();\n this.emitContext(reason);\n }\n\n private emitContext(reason: SessionReason): void {\n const now = Date.now();\n const last = this.lastContextAt[reason] ?? 0;\n if (now - last < 1000) return; // cooldown\n this.lastContextAt[reason] = now;\n this.onNewSession(reason, this._sessionId);\n }\n}\n","import type { JsonEvent, JsonLog } from \"@tell-rs/core\";\nimport { NetworkError } from \"@tell-rs/core\";\n\nexport interface BrowserTransportConfig {\n endpoint: string;\n apiKey: string;\n maxRetries: number;\n networkTimeout: number;\n onError?: (error: Error) => void;\n onPayloadTooLarge?: () => void;\n}\n\nexport class BrowserTransport {\n private readonly endpoint: string;\n private readonly apiKey: string;\n private readonly maxRetries: number;\n private readonly networkTimeout: number;\n private readonly onError?: (error: Error) => void;\n private readonly onPayloadTooLarge?: () => void;\n\n constructor(config: BrowserTransportConfig) {\n this.endpoint = config.endpoint;\n this.apiKey = config.apiKey;\n this.maxRetries = config.maxRetries;\n this.networkTimeout = config.networkTimeout;\n this.onError = config.onError;\n this.onPayloadTooLarge = config.onPayloadTooLarge;\n }\n\n async sendEvents(events: JsonEvent[]): Promise<void> {\n if (events.length === 0) return;\n const body = events.map((e) => JSON.stringify(e)).join(\"\\n\");\n await this.send(\"/v1/events\", body);\n }\n\n async sendLogs(logs: JsonLog[]): Promise<void> {\n if (logs.length === 0) return;\n const body = logs.map((l) => JSON.stringify(l)).join(\"\\n\");\n await this.send(\"/v1/logs\", body);\n }\n\n /** Best-effort flush via sendBeacon for page unload. */\n beacon(events: JsonEvent[], logs: JsonLog[]): void {\n if (typeof navigator === \"undefined\" || !navigator.sendBeacon) return;\n\n if (events.length > 0) {\n const body = events.map((e) => JSON.stringify(e)).join(\"\\n\");\n const blob = new Blob([body], { type: \"text/plain\" });\n const url = `${this.endpoint}/v1/events?token=${encodeURIComponent(this.apiKey)}`;\n navigator.sendBeacon(url, blob);\n }\n\n if (logs.length > 0) {\n const body = logs.map((l) => JSON.stringify(l)).join(\"\\n\");\n const blob = new Blob([body], { type: \"text/plain\" });\n const url = `${this.endpoint}/v1/logs?token=${encodeURIComponent(this.apiKey)}`;\n navigator.sendBeacon(url, blob);\n }\n }\n\n private resolvePort(): string {\n try {\n const u = new URL(this.endpoint);\n if (u.port) return u.port;\n return u.protocol === \"https:\" ? \"443\" : \"80\";\n } catch {\n return \"unknown\";\n }\n }\n\n private async send(path: string, body: string): Promise<void> {\n // Auth via query param + text/plain content-type keeps this a CORS\n // \"simple request\" — no preflight OPTIONS needed. This matches the\n // pattern used by beacon() and by every major analytics SDK.\n const url = `${this.endpoint}${path}?token=${encodeURIComponent(this.apiKey)}`;\n const port = this.resolvePort();\n const headers: Record<string, string> = {\n \"Content-Type\": \"text/plain\",\n };\n\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (attempt > 0) {\n await this.backoff(attempt);\n }\n\n // Skip attempt if browser reports offline\n if (typeof navigator !== \"undefined\" && !navigator.onLine) {\n lastError = new NetworkError(`Browser is offline (endpoint: ${url}, port: ${port})`);\n continue;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(\n () => controller.abort(),\n this.networkTimeout\n );\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n signal: controller.signal,\n keepalive: true,\n });\n\n if (response.status === 202) {\n return;\n }\n\n if (response.status === 207) {\n if (this.onError) {\n this.onError(\n new NetworkError(\n `Partial success: some items rejected`,\n 207\n )\n );\n }\n return;\n }\n\n if (response.status === 413) {\n if (this.onPayloadTooLarge) {\n this.onPayloadTooLarge();\n }\n throw new NetworkError(\"Payload too large\", 413);\n }\n\n if (response.status === 401) {\n throw new NetworkError(\"Invalid API key\", 401);\n }\n\n if (response.status >= 400 && response.status < 500) {\n throw new NetworkError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status\n );\n }\n\n // 5xx — retryable\n lastError = new NetworkError(\n `HTTP ${response.status} from ${url} (port ${port}): ${response.statusText}`,\n response.status\n );\n } catch (err) {\n if (err instanceof NetworkError && err.statusCode === 413) {\n throw err;\n }\n\n if (\n err instanceof NetworkError &&\n err.statusCode &&\n err.statusCode < 500\n ) {\n if (this.onError) this.onError(err);\n return;\n }\n\n // DNS failures, connection refused, and CORS errors surface as\n // TypeError from fetch. Include the full URL so the developer can\n // verify the endpoint and port. These won't resolve by retrying.\n if (err instanceof TypeError) {\n if (this.onError)\n this.onError(\n new NetworkError(\n `Failed to connect to ${url} (port ${port}): ${err.message}`\n )\n );\n return;\n }\n\n lastError =\n err instanceof Error ? err : new NetworkError(String(err));\n } finally {\n clearTimeout(timer);\n }\n }\n\n if (lastError && this.onError) {\n this.onError(lastError);\n }\n }\n\n private backoff(attempt: number): Promise<void> {\n const base = 1000 * Math.pow(1.5, attempt - 1);\n const jitter = base * 0.2 * Math.random();\n const delay = Math.min(base + jitter, 30_000);\n return new Promise((resolve) => setTimeout(resolve, delay));\n }\n}\n","import type { LogLevel, Properties } from \"@tell-rs/core\";\n\nexport type QueuedCall =\n | { method: \"track\"; args: [string, Properties?] }\n | { method: \"identify\"; args: [string, Properties?] }\n | { method: \"group\"; args: [string, Properties?] }\n | { method: \"revenue\"; args: [number, string, string, Properties?] }\n | { method: \"alias\"; args: [string, string] }\n | { method: \"log\"; args: [LogLevel, string, string?, Properties?] }\n | { method: \"register\"; args: [Properties] }\n | { method: \"unregister\"; args: [string] }\n | { method: \"optOut\"; args: [] }\n | { method: \"optIn\"; args: [] };\n\nexport class PreInitQueue {\n private items: QueuedCall[] = [];\n readonly maxSize: number;\n\n constructor(maxSize = 1000) {\n this.maxSize = maxSize;\n }\n\n push(call: QueuedCall): void {\n if (this.items.length >= this.maxSize) {\n this.items.shift(); // drop oldest\n }\n this.items.push(call);\n }\n\n replay(target: Record<string, (...args: any[]) => any>): void {\n const calls = this.items;\n this.items = [];\n for (const call of calls) {\n try {\n target[call.method](...call.args);\n } catch {\n // continue on per-call error\n }\n }\n }\n\n get length(): number {\n return this.items.length;\n }\n\n clear(): void {\n this.items = [];\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -44,9 +44,16 @@ interface DeviceContext {
44
44
  url?: string;
45
45
  title?: string;
46
46
  connection_type?: string;
47
+ downlink?: number;
48
+ rtt?: number;
49
+ save_data?: boolean;
47
50
  cpu_cores?: number;
48
51
  device_memory?: number;
49
52
  touch?: boolean;
53
+ bot?: boolean;
54
+ dark_mode?: boolean;
55
+ path?: string;
56
+ screen_orientation?: string;
50
57
  }
51
58
 
52
59
  interface TellInstance {