@tell-rs/browser 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/index.cjs +53 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +53 -16
- package/dist/index.js.map +1 -1
- package/dist/tell.global.js +3 -3
- package/dist/tell.global.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,6 +57,7 @@ tell.configure("feed1e11feed1e11feed1e11feed1e11", {
|
|
|
57
57
|
disabled: false, // disable all tracking
|
|
58
58
|
maxQueueSize: 1000, // max queued items
|
|
59
59
|
sessionTimeout: 1_800_000, // 30 min session timeout
|
|
60
|
+
maxSessionLength: 86_400_000, // 24 hour max session length
|
|
60
61
|
persistence: "localStorage", // "localStorage" | "memory"
|
|
61
62
|
respectDoNotTrack: false, // honor browser DNT setting
|
|
62
63
|
botDetection: true, // auto-disable for bots
|
|
@@ -129,7 +130,7 @@ tell.configure("feed1e11feed1e11feed1e11feed1e11", production()); // defaults,
|
|
|
129
130
|
|
|
130
131
|
## Features
|
|
131
132
|
|
|
132
|
-
- **Automatic sessions** — rotated on 30-min inactivity or
|
|
133
|
+
- **Automatic sessions** — persisted across page loads, rotated on 30-min inactivity or 24-hour max lifetime
|
|
133
134
|
- **Pre-init queue** — events called before `configure()` are buffered and replayed
|
|
134
135
|
- **sendBeacon flush** — events are flushed via `navigator.sendBeacon` on page unload
|
|
135
136
|
- **Bot detection** — auto-disables for headless browsers and bots
|
package/dist/index.cjs
CHANGED
|
@@ -353,6 +353,8 @@ var DEFAULTS = {
|
|
|
353
353
|
maxQueueSize: 1e3,
|
|
354
354
|
sessionTimeout: 18e5,
|
|
355
355
|
// 30 min
|
|
356
|
+
maxSessionLength: 864e5,
|
|
357
|
+
// 24 hours
|
|
356
358
|
persistence: "localStorage",
|
|
357
359
|
respectDoNotTrack: false,
|
|
358
360
|
botDetection: true,
|
|
@@ -585,20 +587,41 @@ function captureUtm() {
|
|
|
585
587
|
}
|
|
586
588
|
|
|
587
589
|
// src/session.ts
|
|
590
|
+
var SESSION_ID_KEY = "tell_session_id";
|
|
591
|
+
var SESSION_TS_KEY = "tell_session_ts";
|
|
592
|
+
var SESSION_START_KEY = "tell_session_start";
|
|
593
|
+
var PERSIST_INTERVAL = 6e4;
|
|
588
594
|
var SessionManager = class {
|
|
589
595
|
_sessionId;
|
|
590
596
|
lastHiddenAt = 0;
|
|
591
597
|
lastActivityAt;
|
|
598
|
+
sessionStartedAt;
|
|
599
|
+
lastPersistedAt = 0;
|
|
592
600
|
timeout;
|
|
601
|
+
maxLength;
|
|
602
|
+
storage;
|
|
593
603
|
onNewSession;
|
|
594
604
|
visibilityHandler;
|
|
595
|
-
lastContextAt = {};
|
|
596
605
|
constructor(config) {
|
|
597
606
|
this.timeout = config.timeout;
|
|
607
|
+
this.maxLength = config.maxLength;
|
|
608
|
+
this.storage = config.storage;
|
|
598
609
|
this.onNewSession = config.onNewSession;
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
this.
|
|
610
|
+
const now = Date.now();
|
|
611
|
+
const storedId = this.storage.get(SESSION_ID_KEY);
|
|
612
|
+
const storedTs = Number(this.storage.get(SESSION_TS_KEY) || 0);
|
|
613
|
+
const storedStart = Number(this.storage.get(SESSION_START_KEY) || 0);
|
|
614
|
+
if (storedId && storedTs > 0 && storedStart > 0 && now - storedTs < this.timeout && now - storedStart < this.maxLength) {
|
|
615
|
+
this._sessionId = storedId;
|
|
616
|
+
this.lastActivityAt = storedTs;
|
|
617
|
+
this.sessionStartedAt = storedStart;
|
|
618
|
+
} else {
|
|
619
|
+
this._sessionId = generateId();
|
|
620
|
+
this.lastActivityAt = now;
|
|
621
|
+
this.sessionStartedAt = now;
|
|
622
|
+
this.persist();
|
|
623
|
+
this.onNewSession("session_start", this._sessionId);
|
|
624
|
+
}
|
|
602
625
|
this.visibilityHandler = () => this.handleVisibility();
|
|
603
626
|
if (typeof document !== "undefined") {
|
|
604
627
|
document.addEventListener("visibilitychange", this.visibilityHandler);
|
|
@@ -609,14 +632,21 @@ var SessionManager = class {
|
|
|
609
632
|
}
|
|
610
633
|
set sessionId(id) {
|
|
611
634
|
this._sessionId = id;
|
|
635
|
+
const now = Date.now();
|
|
636
|
+
this.lastActivityAt = now;
|
|
637
|
+
this.sessionStartedAt = now;
|
|
638
|
+
this.persist();
|
|
612
639
|
}
|
|
613
|
-
/** Update activity timestamp; rotates session if idle longer than timeout. */
|
|
640
|
+
/** Update activity timestamp; rotates session if idle longer than timeout or exceeds max length. */
|
|
614
641
|
touch() {
|
|
615
642
|
const now = Date.now();
|
|
616
|
-
if (now - this.lastActivityAt > this.timeout) {
|
|
643
|
+
if (now - this.lastActivityAt > this.timeout || now - this.sessionStartedAt > this.maxLength) {
|
|
617
644
|
this.rotateSession("session_timeout");
|
|
618
645
|
}
|
|
619
646
|
this.lastActivityAt = now;
|
|
647
|
+
if (now - this.lastPersistedAt >= PERSIST_INTERVAL) {
|
|
648
|
+
this.persistActivity();
|
|
649
|
+
}
|
|
620
650
|
}
|
|
621
651
|
destroy() {
|
|
622
652
|
if (typeof document !== "undefined") {
|
|
@@ -627,26 +657,31 @@ var SessionManager = class {
|
|
|
627
657
|
if (document.visibilityState === "hidden") {
|
|
628
658
|
this.lastHiddenAt = Date.now();
|
|
629
659
|
} else if (document.visibilityState === "visible") {
|
|
630
|
-
|
|
660
|
+
const now = Date.now();
|
|
661
|
+
if (this.lastHiddenAt > 0 && (now - this.lastHiddenAt > this.timeout || now - this.sessionStartedAt > this.maxLength)) {
|
|
631
662
|
this.rotateSession("session_timeout");
|
|
632
|
-
} else if (this.lastHiddenAt > 0) {
|
|
633
|
-
this.emitContext("app_foreground");
|
|
634
663
|
}
|
|
635
664
|
this.lastHiddenAt = 0;
|
|
636
665
|
}
|
|
637
666
|
}
|
|
638
667
|
rotateSession(reason) {
|
|
639
668
|
this._sessionId = generateId();
|
|
640
|
-
this.lastActivityAt = Date.now();
|
|
641
|
-
this.emitContext(reason);
|
|
642
|
-
}
|
|
643
|
-
emitContext(reason) {
|
|
644
669
|
const now = Date.now();
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
this.
|
|
670
|
+
this.lastActivityAt = now;
|
|
671
|
+
this.sessionStartedAt = now;
|
|
672
|
+
this.persist();
|
|
648
673
|
this.onNewSession(reason, this._sessionId);
|
|
649
674
|
}
|
|
675
|
+
persist() {
|
|
676
|
+
this.storage.set(SESSION_ID_KEY, this._sessionId);
|
|
677
|
+
this.storage.set(SESSION_TS_KEY, String(this.lastActivityAt));
|
|
678
|
+
this.storage.set(SESSION_START_KEY, String(this.sessionStartedAt));
|
|
679
|
+
this.lastPersistedAt = Date.now();
|
|
680
|
+
}
|
|
681
|
+
persistActivity() {
|
|
682
|
+
this.storage.set(SESSION_TS_KEY, String(this.lastActivityAt));
|
|
683
|
+
this.lastPersistedAt = Date.now();
|
|
684
|
+
}
|
|
650
685
|
};
|
|
651
686
|
|
|
652
687
|
// src/transport.ts
|
|
@@ -968,6 +1003,8 @@ var tell = {
|
|
|
968
1003
|
});
|
|
969
1004
|
sessionManager = new SessionManager({
|
|
970
1005
|
timeout: resolvedConfig.sessionTimeout,
|
|
1006
|
+
maxLength: resolvedConfig.maxSessionLength,
|
|
1007
|
+
storage,
|
|
971
1008
|
onNewSession
|
|
972
1009
|
});
|
|
973
1010
|
if (typeof window !== "undefined") {
|
package/dist/index.cjs.map
CHANGED
|
@@ -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 resolvedService: 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 service: resolvedService,\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(level: LogLevel, message: string, data?: Properties): void;\n logEmergency(message: string, data?: Properties): void;\n logAlert(message: string, data?: Properties): void;\n logCritical(message: string, data?: Properties): void;\n logError(message: string, data?: Properties): void;\n logWarning(message: string, data?: Properties): void;\n logNotice(message: string, data?: Properties): void;\n logInfo(message: string, data?: Properties): void;\n logDebug(message: string, data?: Properties): void;\n logTrace(message: 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 resolvedService =\n options?.service ??\n (typeof window !== \"undefined\" ? window.location?.hostname : undefined) ??\n \"browser\";\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, 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, 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 service: resolvedService,\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 service: resolvedService,\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 service: resolvedService,\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 service: resolvedService,\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 service: resolvedService,\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(level: LogLevel, message: string, data?: Properties): void {\n if (!configured) {\n queue.push({ method: \"log\", args: [level, message, 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: resolvedService,\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, data?: Properties): void {\n tell.log(\"emergency\", message, data);\n },\n logAlert(message: string, data?: Properties): void {\n tell.log(\"alert\", message, data);\n },\n logCritical(message: string, data?: Properties): void {\n tell.log(\"critical\", message, data);\n },\n logError(message: string, data?: Properties): void {\n tell.log(\"error\", message, data);\n },\n logWarning(message: string, data?: Properties): void {\n tell.log(\"warning\", message, data);\n },\n logNotice(message: string, data?: Properties): void {\n tell.log(\"notice\", message, data);\n },\n logInfo(message: string, data?: Properties): void {\n tell.log(\"info\", message, data);\n },\n logDebug(message: string, data?: Properties): void {\n tell.log(\"debug\", message, data);\n },\n logTrace(message: string, data?: Properties): void {\n tell.log(\"trace\", message, 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 /** Service name stamped on every event and log. Defaults to window.location.hostname. */\n service?: string;\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, 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 resolvedService: 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 service: resolvedService,\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(level: LogLevel, message: string, data?: Properties): void;\n logEmergency(message: string, data?: Properties): void;\n logAlert(message: string, data?: Properties): void;\n logCritical(message: string, data?: Properties): void;\n logError(message: string, data?: Properties): void;\n logWarning(message: string, data?: Properties): void;\n logNotice(message: string, data?: Properties): void;\n logInfo(message: string, data?: Properties): void;\n logDebug(message: string, data?: Properties): void;\n logTrace(message: 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 resolvedService =\n options?.service ??\n (typeof window !== \"undefined\" ? window.location?.hostname : undefined) ??\n \"browser\";\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 maxLength: resolvedConfig.maxSessionLength,\n storage,\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, 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, 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 service: resolvedService,\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 service: resolvedService,\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 service: resolvedService,\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 service: resolvedService,\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 service: resolvedService,\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(level: LogLevel, message: string, data?: Properties): void {\n if (!configured) {\n queue.push({ method: \"log\", args: [level, message, 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: resolvedService,\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, data?: Properties): void {\n tell.log(\"emergency\", message, data);\n },\n logAlert(message: string, data?: Properties): void {\n tell.log(\"alert\", message, data);\n },\n logCritical(message: string, data?: Properties): void {\n tell.log(\"critical\", message, data);\n },\n logError(message: string, data?: Properties): void {\n tell.log(\"error\", message, data);\n },\n logWarning(message: string, data?: Properties): void {\n tell.log(\"warning\", message, data);\n },\n logNotice(message: string, data?: Properties): void {\n tell.log(\"notice\", message, data);\n },\n logInfo(message: string, data?: Properties): void {\n tell.log(\"info\", message, data);\n },\n logDebug(message: string, data?: Properties): void {\n tell.log(\"debug\", message, data);\n },\n logTrace(message: string, data?: Properties): void {\n tell.log(\"trace\", message, 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 /** Service name stamped on every event and log. Defaults to window.location.hostname. */\n service?: string;\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 maxSessionLength?: 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 maxSessionLength: 86_400_000, // 24 hours\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\";\nimport type { TellStorage } from \"./persistence.js\";\n\nexport type SessionReason = \"session_start\" | \"session_timeout\";\n\nexport interface SessionManagerConfig {\n timeout: number; // idle timeout in ms (default 30 min)\n maxLength: number; // max session length in ms (default 24 hours)\n storage: TellStorage;\n onNewSession: (reason: SessionReason, sessionId: string) => void;\n}\n\nconst SESSION_ID_KEY = \"tell_session_id\";\nconst SESSION_TS_KEY = \"tell_session_ts\";\nconst SESSION_START_KEY = \"tell_session_start\";\nconst PERSIST_INTERVAL = 60_000;\n\nexport class SessionManager {\n private _sessionId: string;\n private lastHiddenAt = 0;\n private lastActivityAt: number;\n private sessionStartedAt: number;\n private lastPersistedAt = 0;\n private readonly timeout: number;\n private readonly maxLength: number;\n private readonly storage: TellStorage;\n private readonly onNewSession: (reason: SessionReason, sessionId: string) => void;\n private readonly visibilityHandler: () => void;\n\n constructor(config: SessionManagerConfig) {\n this.timeout = config.timeout;\n this.maxLength = config.maxLength;\n this.storage = config.storage;\n this.onNewSession = config.onNewSession;\n\n const now = Date.now();\n const storedId = this.storage.get(SESSION_ID_KEY);\n const storedTs = Number(this.storage.get(SESSION_TS_KEY) || 0);\n const storedStart = Number(this.storage.get(SESSION_START_KEY) || 0);\n\n if (\n storedId &&\n storedTs > 0 &&\n storedStart > 0 &&\n now - storedTs < this.timeout &&\n now - storedStart < this.maxLength\n ) {\n this._sessionId = storedId;\n this.lastActivityAt = storedTs;\n this.sessionStartedAt = storedStart;\n } else {\n this._sessionId = generateId();\n this.lastActivityAt = now;\n this.sessionStartedAt = now;\n this.persist();\n this.onNewSession(\"session_start\", this._sessionId);\n }\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 const now = Date.now();\n this.lastActivityAt = now;\n this.sessionStartedAt = now;\n this.persist();\n }\n\n /** Update activity timestamp; rotates session if idle longer than timeout or exceeds max length. */\n touch(): void {\n const now = Date.now();\n if (\n now - this.lastActivityAt > this.timeout ||\n now - this.sessionStartedAt > this.maxLength\n ) {\n this.rotateSession(\"session_timeout\");\n }\n this.lastActivityAt = now;\n if (now - this.lastPersistedAt >= PERSIST_INTERVAL) {\n this.persistActivity();\n }\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 const now = Date.now();\n if (\n this.lastHiddenAt > 0 &&\n (now - this.lastHiddenAt > this.timeout ||\n now - this.sessionStartedAt > this.maxLength)\n ) {\n this.rotateSession(\"session_timeout\");\n }\n this.lastHiddenAt = 0;\n }\n }\n\n private rotateSession(reason: SessionReason): void {\n this._sessionId = generateId();\n const now = Date.now();\n this.lastActivityAt = now;\n this.sessionStartedAt = now;\n this.persist();\n this.onNewSession(reason, this._sessionId);\n }\n\n private persist(): void {\n this.storage.set(SESSION_ID_KEY, this._sessionId);\n this.storage.set(SESSION_TS_KEY, String(this.lastActivityAt));\n this.storage.set(SESSION_START_KEY, String(this.sessionStartedAt));\n this.lastPersistedAt = Date.now();\n }\n\n private persistActivity(): void {\n this.storage.set(SESSION_TS_KEY, String(this.lastActivityAt));\n this.lastPersistedAt = Date.now();\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, 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
package/dist/index.d.ts
CHANGED