@tell-rs/browser 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +32 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +32 -30
- package/dist/index.js.map +1 -1
- package/dist/tell.global.js +7 -0
- package/dist/tell.global.js.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -44,9 +44,16 @@ interface DeviceContext {
|
|
|
44
44
|
url?: string;
|
|
45
45
|
title?: string;
|
|
46
46
|
connection_type?: string;
|
|
47
|
+
downlink?: number;
|
|
48
|
+
rtt?: number;
|
|
49
|
+
save_data?: boolean;
|
|
47
50
|
cpu_cores?: number;
|
|
48
51
|
device_memory?: number;
|
|
49
52
|
touch?: boolean;
|
|
53
|
+
bot?: boolean;
|
|
54
|
+
dark_mode?: boolean;
|
|
55
|
+
path?: string;
|
|
56
|
+
screen_orientation?: string;
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
interface TellInstance {
|
package/dist/index.js
CHANGED
|
@@ -113,18 +113,13 @@ function generateId() {
|
|
|
113
113
|
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
114
114
|
const bytes = new Uint8Array(16);
|
|
115
115
|
crypto.getRandomValues(bytes);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
);
|
|
121
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
116
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
117
|
+
}
|
|
118
|
+
let hex = "";
|
|
119
|
+
for (let i = 0; i < 32; i++) {
|
|
120
|
+
hex += (Math.random() * 16 | 0).toString(16);
|
|
122
121
|
}
|
|
123
|
-
return
|
|
124
|
-
const r = Math.random() * 16 | 0;
|
|
125
|
-
const v = c === "x" ? r : r & 3 | 8;
|
|
126
|
-
return v.toString(16);
|
|
127
|
-
});
|
|
122
|
+
return hex;
|
|
128
123
|
}
|
|
129
124
|
|
|
130
125
|
// src/bot.ts
|
|
@@ -157,13 +152,19 @@ function captureContext() {
|
|
|
157
152
|
}
|
|
158
153
|
ctx.device_type = inferDeviceType(parsed.os, ua, ctx.touch);
|
|
159
154
|
const conn = navigator.connection;
|
|
160
|
-
if (conn
|
|
161
|
-
ctx.connection_type = conn.effectiveType;
|
|
155
|
+
if (conn) {
|
|
156
|
+
if (conn.effectiveType) ctx.connection_type = conn.effectiveType;
|
|
157
|
+
if (typeof conn.downlink === "number") ctx.downlink = conn.downlink;
|
|
158
|
+
if (typeof conn.rtt === "number") ctx.rtt = conn.rtt;
|
|
159
|
+
if (conn.saveData) ctx.save_data = true;
|
|
162
160
|
}
|
|
161
|
+
if (navigator.webdriver) ctx.bot = true;
|
|
163
162
|
}
|
|
164
163
|
if (typeof screen !== "undefined") {
|
|
165
164
|
ctx.screen_width = screen.width;
|
|
166
165
|
ctx.screen_height = screen.height;
|
|
166
|
+
const orient = screen.orientation;
|
|
167
|
+
if (orient?.type) ctx.screen_orientation = orient.type;
|
|
167
168
|
}
|
|
168
169
|
if (typeof window !== "undefined") {
|
|
169
170
|
ctx.viewport_width = window.innerWidth;
|
|
@@ -184,11 +185,18 @@ function captureContext() {
|
|
|
184
185
|
}
|
|
185
186
|
if (typeof location !== "undefined") {
|
|
186
187
|
ctx.url = location.href;
|
|
188
|
+
if (location.pathname) ctx.path = location.pathname;
|
|
187
189
|
}
|
|
188
190
|
try {
|
|
189
191
|
ctx.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
190
192
|
} catch {
|
|
191
193
|
}
|
|
194
|
+
if (typeof window !== "undefined" && window.matchMedia) {
|
|
195
|
+
try {
|
|
196
|
+
ctx.dark_mode = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
197
|
+
} catch {
|
|
198
|
+
}
|
|
199
|
+
}
|
|
192
200
|
return ctx;
|
|
193
201
|
}
|
|
194
202
|
function inferDeviceType(os, ua, touch) {
|
|
@@ -262,7 +270,6 @@ var SessionManager = class {
|
|
|
262
270
|
timeout;
|
|
263
271
|
onNewSession;
|
|
264
272
|
visibilityHandler;
|
|
265
|
-
checkTimer;
|
|
266
273
|
lastContextAt = {};
|
|
267
274
|
constructor(config) {
|
|
268
275
|
this.timeout = config.timeout;
|
|
@@ -274,10 +281,6 @@ var SessionManager = class {
|
|
|
274
281
|
if (typeof document !== "undefined") {
|
|
275
282
|
document.addEventListener("visibilitychange", this.visibilityHandler);
|
|
276
283
|
}
|
|
277
|
-
this.checkTimer = setInterval(() => this.checkTimeout(), 6e4);
|
|
278
|
-
if (typeof this.checkTimer.unref === "function") {
|
|
279
|
-
this.checkTimer.unref();
|
|
280
|
-
}
|
|
281
284
|
}
|
|
282
285
|
get sessionId() {
|
|
283
286
|
return this._sessionId;
|
|
@@ -285,14 +288,18 @@ var SessionManager = class {
|
|
|
285
288
|
set sessionId(id) {
|
|
286
289
|
this._sessionId = id;
|
|
287
290
|
}
|
|
291
|
+
/** Update activity timestamp; rotates session if idle longer than timeout. */
|
|
288
292
|
touch() {
|
|
289
|
-
|
|
293
|
+
const now = Date.now();
|
|
294
|
+
if (now - this.lastActivityAt > this.timeout) {
|
|
295
|
+
this.rotateSession("session_timeout");
|
|
296
|
+
}
|
|
297
|
+
this.lastActivityAt = now;
|
|
290
298
|
}
|
|
291
299
|
destroy() {
|
|
292
300
|
if (typeof document !== "undefined") {
|
|
293
301
|
document.removeEventListener("visibilitychange", this.visibilityHandler);
|
|
294
302
|
}
|
|
295
|
-
clearInterval(this.checkTimer);
|
|
296
303
|
}
|
|
297
304
|
handleVisibility() {
|
|
298
305
|
if (document.visibilityState === "hidden") {
|
|
@@ -306,11 +313,6 @@ var SessionManager = class {
|
|
|
306
313
|
this.lastHiddenAt = 0;
|
|
307
314
|
}
|
|
308
315
|
}
|
|
309
|
-
checkTimeout() {
|
|
310
|
-
if (Date.now() - this.lastActivityAt > this.timeout) {
|
|
311
|
-
this.rotateSession("session_timeout");
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
316
|
rotateSession(reason) {
|
|
315
317
|
this._sessionId = generateId();
|
|
316
318
|
this.lastActivityAt = Date.now();
|
|
@@ -699,6 +701,7 @@ var tell = {
|
|
|
699
701
|
reportError(err);
|
|
700
702
|
return;
|
|
701
703
|
}
|
|
704
|
+
sessionManager.touch();
|
|
702
705
|
let event = {
|
|
703
706
|
type: "track",
|
|
704
707
|
event: eventName,
|
|
@@ -713,7 +716,6 @@ var tell = {
|
|
|
713
716
|
event = runBeforeSend(event, beforeSend);
|
|
714
717
|
if (event === null) return;
|
|
715
718
|
}
|
|
716
|
-
sessionManager.touch();
|
|
717
719
|
eventBatcher.add(event);
|
|
718
720
|
},
|
|
719
721
|
identify(newUserId, traits) {
|
|
@@ -734,6 +736,7 @@ var tell = {
|
|
|
734
736
|
}
|
|
735
737
|
userId = newUserId;
|
|
736
738
|
storage.set(STORAGE_KEYS.USER_ID, userId);
|
|
739
|
+
sessionManager.touch();
|
|
737
740
|
let event = {
|
|
738
741
|
type: "identify",
|
|
739
742
|
device_id: deviceId,
|
|
@@ -746,7 +749,6 @@ var tell = {
|
|
|
746
749
|
event = runBeforeSend(event, beforeSend);
|
|
747
750
|
if (event === null) return;
|
|
748
751
|
}
|
|
749
|
-
sessionManager.touch();
|
|
750
752
|
eventBatcher.add(event);
|
|
751
753
|
},
|
|
752
754
|
group(groupId, properties) {
|
|
@@ -765,6 +767,7 @@ var tell = {
|
|
|
765
767
|
reportError(err);
|
|
766
768
|
return;
|
|
767
769
|
}
|
|
770
|
+
sessionManager.touch();
|
|
768
771
|
let event = {
|
|
769
772
|
type: "group",
|
|
770
773
|
device_id: deviceId,
|
|
@@ -779,7 +782,6 @@ var tell = {
|
|
|
779
782
|
event = runBeforeSend(event, beforeSend);
|
|
780
783
|
if (event === null) return;
|
|
781
784
|
}
|
|
782
|
-
sessionManager.touch();
|
|
783
785
|
eventBatcher.add(event);
|
|
784
786
|
},
|
|
785
787
|
revenue(amount, currency, orderId, properties) {
|
|
@@ -800,6 +802,7 @@ var tell = {
|
|
|
800
802
|
reportError(err);
|
|
801
803
|
return;
|
|
802
804
|
}
|
|
805
|
+
sessionManager.touch();
|
|
803
806
|
let event = {
|
|
804
807
|
type: "track",
|
|
805
808
|
event: "Order Completed",
|
|
@@ -817,7 +820,6 @@ var tell = {
|
|
|
817
820
|
event = runBeforeSend(event, beforeSend);
|
|
818
821
|
if (event === null) return;
|
|
819
822
|
}
|
|
820
|
-
sessionManager.touch();
|
|
821
823
|
eventBatcher.add(event);
|
|
822
824
|
},
|
|
823
825
|
alias(previousId, newUserId) {
|
|
@@ -838,6 +840,7 @@ var tell = {
|
|
|
838
840
|
reportError(err);
|
|
839
841
|
return;
|
|
840
842
|
}
|
|
843
|
+
sessionManager.touch();
|
|
841
844
|
let event = {
|
|
842
845
|
type: "alias",
|
|
843
846
|
device_id: deviceId,
|
|
@@ -850,7 +853,6 @@ var tell = {
|
|
|
850
853
|
event = runBeforeSend(event, beforeSend);
|
|
851
854
|
if (event === null) return;
|
|
852
855
|
}
|
|
853
|
-
sessionManager.touch();
|
|
854
856
|
eventBatcher.add(event);
|
|
855
857
|
},
|
|
856
858
|
// -----------------------------------------------------------------------
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../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","../src/index.ts"],"sourcesContent":["import type { TellError, BeforeSendFn, JsonEvent, JsonLog } from \"@tell-rs/core\";\n\nexport interface TellBrowserConfig {\n endpoint?: string;\n batchSize?: number;\n flushInterval?: number;\n maxRetries?: number;\n closeTimeout?: number;\n networkTimeout?: number;\n logLevel?: \"error\" | \"warn\" | \"info\" | \"debug\";\n source?: string;\n onError?: (error: TellError) => void;\n disabled?: boolean;\n maxQueueSize?: number;\n sessionTimeout?: number;\n persistence?: \"localStorage\" | \"memory\";\n respectDoNotTrack?: boolean;\n botDetection?: boolean;\n captureErrors?: boolean;\n beforeSend?: BeforeSendFn<JsonEvent> | BeforeSendFn<JsonEvent>[];\n beforeSendLog?: BeforeSendFn<JsonLog> | BeforeSendFn<JsonLog>[];\n}\n\nexport const DEFAULTS = {\n endpoint: \"https://collect.tell.app\",\n batchSize: 20,\n flushInterval: 5_000,\n maxRetries: 5,\n closeTimeout: 5_000,\n networkTimeout: 10_000,\n logLevel: \"error\" as const,\n source: \"browser\",\n disabled: false,\n maxQueueSize: 1000,\n sessionTimeout: 1_800_000, // 30 min\n persistence: \"localStorage\" as const,\n respectDoNotTrack: false,\n botDetection: true,\n captureErrors: false,\n} as const;\n\nexport type ResolvedBrowserConfig = Required<\n Omit<TellBrowserConfig, \"onError\" | \"beforeSend\" | \"beforeSendLog\">\n> &\n Pick<TellBrowserConfig, \"onError\" | \"beforeSend\" | \"beforeSendLog\">;\n\nexport function resolveConfig(\n options: TellBrowserConfig | undefined\n): ResolvedBrowserConfig {\n return { ...DEFAULTS, ...options } as ResolvedBrowserConfig;\n}\n\n/** Development preset: localhost, small batches, fast flush, debug logging. */\nexport function development(\n overrides?: Partial<TellBrowserConfig>\n): TellBrowserConfig {\n return {\n endpoint: \"http://localhost:8080\",\n batchSize: 5,\n flushInterval: 2_000,\n logLevel: \"debug\",\n ...overrides,\n };\n}\n\n/** Production preset: default endpoint, error-only logging. */\nexport function production(\n overrides?: Partial<TellBrowserConfig>\n): TellBrowserConfig {\n return {\n logLevel: \"error\",\n ...overrides,\n };\n}\n","export interface TellStorage {\n get(key: string): string | null;\n set(key: string, value: string): void;\n remove(key: string): void;\n}\n\nexport const STORAGE_KEYS = {\n DEVICE_ID: \"tell_device_id\",\n USER_ID: \"tell_user_id\",\n OPT_OUT: \"tell_opt_out\",\n SUPER_PROPS: \"tell_super_props\",\n} as const;\n\nclass LocalStorageStorage implements TellStorage {\n get(key: string): string | null {\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n }\n\n set(key: string, value: string): void {\n try {\n localStorage.setItem(key, value);\n } catch {\n // Safari private mode or quota exceeded\n }\n }\n\n remove(key: string): void {\n try {\n localStorage.removeItem(key);\n } catch {\n // ignore\n }\n }\n}\n\nclass MemoryStorage implements TellStorage {\n private data = new Map<string, string>();\n\n get(key: string): string | null {\n return this.data.get(key) ?? null;\n }\n\n set(key: string, value: string): void {\n this.data.set(key, value);\n }\n\n remove(key: string): void {\n this.data.delete(key);\n }\n}\n\n/** Create a storage backend. Falls back to memory if localStorage is unavailable. */\nexport function createStorage(\n persistence: \"localStorage\" | \"memory\"\n): TellStorage {\n if (persistence === \"localStorage\" && typeof localStorage !== \"undefined\") {\n try {\n const testKey = \"tell_test\";\n localStorage.setItem(testKey, \"1\");\n localStorage.removeItem(testKey);\n return new LocalStorageStorage();\n } catch {\n // probe failed — fall through to memory\n }\n }\n return new MemoryStorage();\n}\n","/** Generate a UUID v4 string using crypto.getRandomValues. */\nexport function generateId(): string {\n if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n // Set version (4) and variant (10xx)\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\n \"\"\n );\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n }\n\n // Fallback for environments without crypto (extremely rare)\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","/** Returns true if the current environment appears to be an automated bot. */\nexport function isBot(): boolean {\n if (typeof navigator === \"undefined\") return false;\n if ((navigator as any).webdriver === true) return true;\n const ua = navigator.userAgent || \"\";\n return /headless/i.test(ua);\n}\n","export interface DeviceContext {\n browser?: string;\n browser_version?: string;\n os_name?: string;\n os_version?: string;\n device_type?: string;\n screen_width?: number;\n screen_height?: number;\n viewport_width?: number;\n viewport_height?: number;\n device_pixel_ratio?: number;\n locale?: string;\n timezone?: string;\n referrer?: string;\n referrer_domain?: string;\n url?: string;\n title?: string;\n connection_type?: string;\n cpu_cores?: number;\n device_memory?: number;\n touch?: boolean;\n}\n\n/** Capture a snapshot of the current device/browser context. */\nexport function captureContext(): DeviceContext {\n const ctx: DeviceContext = {};\n\n if (typeof navigator !== \"undefined\") {\n const ua = navigator.userAgent || \"\";\n const parsed = parseUA(ua);\n ctx.browser = parsed.browser;\n ctx.browser_version = parsed.browserVersion;\n ctx.os_name = parsed.os;\n ctx.os_version = parsed.osVersion;\n ctx.locale = navigator.language;\n\n // Hardware capabilities (touch must come before device_type inference)\n if (\"hardwareConcurrency\" in navigator) {\n ctx.cpu_cores = (navigator as any).hardwareConcurrency;\n }\n if (\"deviceMemory\" in navigator) {\n ctx.device_memory = (navigator as any).deviceMemory;\n }\n if (\"maxTouchPoints\" in navigator) {\n ctx.touch = navigator.maxTouchPoints > 0;\n }\n\n ctx.device_type = inferDeviceType(parsed.os, ua, ctx.touch);\n\n // Network info (Chrome/Edge)\n const conn = (navigator as any).connection;\n if (conn?.effectiveType) {\n ctx.connection_type = conn.effectiveType;\n }\n }\n\n if (typeof screen !== \"undefined\") {\n ctx.screen_width = screen.width;\n ctx.screen_height = screen.height;\n }\n\n if (typeof window !== \"undefined\") {\n ctx.viewport_width = window.innerWidth;\n ctx.viewport_height = window.innerHeight;\n if (window.devicePixelRatio) {\n ctx.device_pixel_ratio = window.devicePixelRatio;\n }\n }\n\n if (typeof document !== \"undefined\") {\n ctx.referrer = document.referrer || undefined;\n if (ctx.referrer) {\n try {\n ctx.referrer_domain = new URL(ctx.referrer).hostname;\n } catch {\n // malformed referrer\n }\n }\n ctx.title = document.title || undefined;\n }\n\n if (typeof location !== \"undefined\") {\n ctx.url = location.href;\n }\n\n try {\n ctx.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n // Intl not available\n }\n\n return ctx;\n}\n\nfunction inferDeviceType(os?: string, ua?: string, touch?: boolean): string {\n // iPad (iPadOS 13+) reports as macOS but has touch support\n if (os === \"macOS\" && touch) return \"tablet\";\n // Android tablets have \"Android\" in UA but not \"Mobile\"\n if (os === \"Android\") return ua && !/Mobile/.test(ua) ? \"tablet\" : \"mobile\";\n if (os === \"iOS\") return \"mobile\";\n return \"desktop\";\n}\n\ninterface ParsedUA {\n browser?: string;\n browserVersion?: string;\n os?: string;\n osVersion?: string;\n}\n\nfunction parseUA(ua: string): ParsedUA {\n const result: ParsedUA = {};\n\n // Browser detection (order matters: Edge before Chrome, Chrome before Safari)\n if (/Edg\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Edge\";\n result.browserVersion = RegExp.$1;\n } else if (/OPR\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Opera\";\n result.browserVersion = RegExp.$1;\n } else if (/Chrome\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Chrome\";\n result.browserVersion = RegExp.$1;\n } else if (/Safari\\/[\\d.]+/.test(ua) && /Version\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Safari\";\n result.browserVersion = RegExp.$1;\n } else if (/Firefox\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Firefox\";\n result.browserVersion = RegExp.$1;\n }\n\n // OS detection\n if (/Windows NT ([\\d.]+)/.test(ua)) {\n result.os = \"Windows\";\n result.osVersion = RegExp.$1;\n } else if (/Mac OS X ([\\d_.]+)/.test(ua)) {\n result.os = \"macOS\";\n result.osVersion = RegExp.$1.replace(/_/g, \".\");\n } else if (/iPhone OS ([\\d_]+)/.test(ua)) {\n result.os = \"iOS\";\n result.osVersion = RegExp.$1.replace(/_/g, \".\");\n } else if (/Android ([\\d.]+)/.test(ua)) {\n result.os = \"Android\";\n result.osVersion = RegExp.$1;\n } else if (/Linux/.test(ua)) {\n result.os = \"Linux\";\n }\n\n return result;\n}\n","import type { Properties } from \"@tell-rs/core\";\n\nconst UTM_KEYS = [\n \"utm_source\",\n \"utm_medium\",\n \"utm_campaign\",\n \"utm_term\",\n \"utm_content\",\n] as const;\n\n/**\n * Extract UTM parameters from the current URL search string.\n * Returns only keys that are present and non-empty.\n */\nexport function captureUtm(): Properties {\n if (typeof window === \"undefined\" || !window.location?.search) return {};\n\n const params = new URLSearchParams(window.location.search);\n const utm: Properties = {};\n\n for (const key of UTM_KEYS) {\n const value = params.get(key);\n if (value) {\n utm[key] = value;\n }\n }\n\n return utm;\n}\n","import { generateId } from \"./id.js\";\n\nexport type SessionReason = \"session_start\" | \"session_timeout\" | \"app_foreground\";\n\nexport interface SessionManagerConfig {\n timeout: number; // ms\n onNewSession: (reason: SessionReason, sessionId: string) => void;\n}\n\nexport class SessionManager {\n private _sessionId: string;\n private lastHiddenAt = 0;\n private lastActivityAt: number;\n private readonly timeout: number;\n private readonly onNewSession: (reason: SessionReason, sessionId: string) => void;\n private readonly visibilityHandler: () => void;\n private readonly checkTimer: ReturnType<typeof setInterval>;\n private lastContextAt: Record<string, number> = {};\n\n constructor(config: SessionManagerConfig) {\n this.timeout = config.timeout;\n this.onNewSession = config.onNewSession;\n this._sessionId = generateId();\n this.lastActivityAt = Date.now();\n\n this.emitContext(\"session_start\");\n\n this.visibilityHandler = () => this.handleVisibility();\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"visibilitychange\", this.visibilityHandler);\n }\n\n this.checkTimer = setInterval(() => this.checkTimeout(), 60_000);\n if (typeof (this.checkTimer as any).unref === \"function\") {\n (this.checkTimer as any).unref();\n }\n }\n\n get sessionId(): string {\n return this._sessionId;\n }\n\n set sessionId(id: string) {\n this._sessionId = id;\n }\n\n touch(): void {\n this.lastActivityAt = Date.now();\n }\n\n destroy(): void {\n if (typeof document !== \"undefined\") {\n document.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n }\n clearInterval(this.checkTimer);\n }\n\n private handleVisibility(): void {\n if (document.visibilityState === \"hidden\") {\n this.lastHiddenAt = Date.now();\n } else if (document.visibilityState === \"visible\") {\n if (this.lastHiddenAt > 0 && Date.now() - this.lastHiddenAt > this.timeout) {\n this.rotateSession(\"session_timeout\");\n } else if (this.lastHiddenAt > 0) {\n this.emitContext(\"app_foreground\");\n }\n this.lastHiddenAt = 0;\n }\n }\n\n private checkTimeout(): void {\n if (Date.now() - this.lastActivityAt > this.timeout) {\n this.rotateSession(\"session_timeout\");\n }\n }\n\n private rotateSession(reason: SessionReason): void {\n this._sessionId = generateId();\n this.lastActivityAt = Date.now();\n this.emitContext(reason);\n }\n\n private emitContext(reason: SessionReason): void {\n const now = Date.now();\n const last = this.lastContextAt[reason] ?? 0;\n if (now - last < 1000) return; // cooldown\n this.lastContextAt[reason] = now;\n this.onNewSession(reason, this._sessionId);\n }\n}\n","import type { JsonEvent, JsonLog } from \"@tell-rs/core\";\nimport { NetworkError } from \"@tell-rs/core\";\n\nexport interface BrowserTransportConfig {\n endpoint: string;\n apiKey: string;\n maxRetries: number;\n networkTimeout: number;\n onError?: (error: Error) => void;\n onPayloadTooLarge?: () => void;\n}\n\nexport class BrowserTransport {\n private readonly endpoint: string;\n private readonly apiKey: string;\n private readonly maxRetries: number;\n private readonly networkTimeout: number;\n private readonly onError?: (error: Error) => void;\n private readonly onPayloadTooLarge?: () => void;\n\n constructor(config: BrowserTransportConfig) {\n this.endpoint = config.endpoint;\n this.apiKey = config.apiKey;\n this.maxRetries = config.maxRetries;\n this.networkTimeout = config.networkTimeout;\n this.onError = config.onError;\n this.onPayloadTooLarge = config.onPayloadTooLarge;\n }\n\n async sendEvents(events: JsonEvent[]): Promise<void> {\n if (events.length === 0) return;\n const body = events.map((e) => JSON.stringify(e)).join(\"\\n\");\n await this.send(\"/v1/events\", body);\n }\n\n async sendLogs(logs: JsonLog[]): Promise<void> {\n if (logs.length === 0) return;\n const body = logs.map((l) => JSON.stringify(l)).join(\"\\n\");\n await this.send(\"/v1/logs\", body);\n }\n\n /** Best-effort flush via sendBeacon for page unload. */\n beacon(events: JsonEvent[], logs: JsonLog[]): void {\n if (typeof navigator === \"undefined\" || !navigator.sendBeacon) return;\n\n if (events.length > 0) {\n const body = events.map((e) => JSON.stringify(e)).join(\"\\n\");\n const blob = new Blob([body], { type: \"text/plain\" });\n const url = `${this.endpoint}/v1/events?token=${encodeURIComponent(this.apiKey)}`;\n navigator.sendBeacon(url, blob);\n }\n\n if (logs.length > 0) {\n const body = logs.map((l) => JSON.stringify(l)).join(\"\\n\");\n const blob = new Blob([body], { type: \"text/plain\" });\n const url = `${this.endpoint}/v1/logs?token=${encodeURIComponent(this.apiKey)}`;\n navigator.sendBeacon(url, blob);\n }\n }\n\n private resolvePort(): string {\n try {\n const u = new URL(this.endpoint);\n if (u.port) return u.port;\n return u.protocol === \"https:\" ? \"443\" : \"80\";\n } catch {\n return \"unknown\";\n }\n }\n\n private async send(path: string, body: string): Promise<void> {\n // Auth via query param + text/plain content-type keeps this a CORS\n // \"simple request\" — no preflight OPTIONS needed. This matches the\n // pattern used by beacon() and by every major analytics SDK.\n const url = `${this.endpoint}${path}?token=${encodeURIComponent(this.apiKey)}`;\n const port = this.resolvePort();\n const headers: Record<string, string> = {\n \"Content-Type\": \"text/plain\",\n };\n\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (attempt > 0) {\n await this.backoff(attempt);\n }\n\n // Skip attempt if browser reports offline\n if (typeof navigator !== \"undefined\" && !navigator.onLine) {\n lastError = new NetworkError(`Browser is offline (endpoint: ${url}, port: ${port})`);\n continue;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(\n () => controller.abort(),\n this.networkTimeout\n );\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n signal: controller.signal,\n keepalive: true,\n });\n\n if (response.status === 202) {\n return;\n }\n\n if (response.status === 207) {\n if (this.onError) {\n this.onError(\n new NetworkError(\n `Partial success: some items rejected`,\n 207\n )\n );\n }\n return;\n }\n\n if (response.status === 413) {\n if (this.onPayloadTooLarge) {\n this.onPayloadTooLarge();\n }\n throw new NetworkError(\"Payload too large\", 413);\n }\n\n if (response.status === 401) {\n throw new NetworkError(\"Invalid API key\", 401);\n }\n\n if (response.status >= 400 && response.status < 500) {\n throw new NetworkError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status\n );\n }\n\n // 5xx — retryable\n lastError = new NetworkError(\n `HTTP ${response.status} from ${url} (port ${port}): ${response.statusText}`,\n response.status\n );\n } catch (err) {\n if (err instanceof NetworkError && err.statusCode === 413) {\n throw err;\n }\n\n if (\n err instanceof NetworkError &&\n err.statusCode &&\n err.statusCode < 500\n ) {\n if (this.onError) this.onError(err);\n return;\n }\n\n // DNS failures, connection refused, and CORS errors surface as\n // TypeError from fetch. Include the full URL so the developer can\n // verify the endpoint and port. These won't resolve by retrying.\n if (err instanceof TypeError) {\n if (this.onError)\n this.onError(\n new NetworkError(\n `Failed to connect to ${url} (port ${port}): ${err.message}`\n )\n );\n return;\n }\n\n lastError =\n err instanceof Error ? err : new NetworkError(String(err));\n } finally {\n clearTimeout(timer);\n }\n }\n\n if (lastError && this.onError) {\n this.onError(lastError);\n }\n }\n\n private backoff(attempt: number): Promise<void> {\n const base = 1000 * Math.pow(1.5, attempt - 1);\n const jitter = base * 0.2 * Math.random();\n const delay = Math.min(base + jitter, 30_000);\n return new Promise((resolve) => setTimeout(resolve, delay));\n }\n}\n","import type { LogLevel, Properties } from \"@tell-rs/core\";\n\nexport type QueuedCall =\n | { method: \"track\"; args: [string, Properties?] }\n | { method: \"identify\"; args: [string, Properties?] }\n | { method: \"group\"; args: [string, Properties?] }\n | { method: \"revenue\"; args: [number, string, string, Properties?] }\n | { method: \"alias\"; args: [string, string] }\n | { method: \"log\"; args: [LogLevel, string, string?, Properties?] }\n | { method: \"register\"; args: [Properties] }\n | { method: \"unregister\"; args: [string] }\n | { method: \"optOut\"; args: [] }\n | { method: \"optIn\"; args: [] };\n\nexport class PreInitQueue {\n private items: QueuedCall[] = [];\n readonly maxSize: number;\n\n constructor(maxSize = 1000) {\n this.maxSize = maxSize;\n }\n\n push(call: QueuedCall): void {\n if (this.items.length >= this.maxSize) {\n this.items.shift(); // drop oldest\n }\n this.items.push(call);\n }\n\n replay(target: Record<string, (...args: any[]) => any>): void {\n const calls = this.items;\n this.items = [];\n for (const call of calls) {\n try {\n target[call.method](...call.args);\n } catch {\n // continue on per-call error\n }\n }\n }\n\n get length(): number {\n return this.items.length;\n }\n\n clear(): void {\n this.items = [];\n }\n}\n","import type {\n JsonEvent,\n JsonLog,\n LogLevel,\n Properties,\n BeforeSendFn,\n} from \"@tell-rs/core\";\nimport {\n ClosedError,\n ConfigurationError,\n ValidationError,\n validateApiKey,\n validateEventName,\n validateLogMessage,\n validateUserId,\n Batcher,\n runBeforeSend,\n} from \"@tell-rs/core\";\n\nimport type { TellBrowserConfig, ResolvedBrowserConfig } from \"./config.js\";\nimport { resolveConfig } from \"./config.js\";\nimport type { TellStorage } from \"./persistence.js\";\nimport { createStorage, STORAGE_KEYS } from \"./persistence.js\";\nimport { generateId } from \"./id.js\";\nimport { isBot } from \"./bot.js\";\nimport { captureContext } from \"./context.js\";\nimport { captureUtm } from \"./utm.js\";\nimport type { SessionReason } from \"./session.js\";\nimport { SessionManager } from \"./session.js\";\nimport { BrowserTransport } from \"./transport.js\";\nimport { PreInitQueue } from \"./queue.js\";\n\n// Re-export core types and values\nexport { Events, type EventName } from \"@tell-rs/core\";\nexport type { Properties, LogLevel, JsonEvent, JsonLog, BeforeSendFn } from \"@tell-rs/core\";\nexport { redact, redactLog, SENSITIVE_PARAMS, type RedactOptions } from \"@tell-rs/core\";\nexport {\n TellError,\n ConfigurationError,\n ValidationError,\n NetworkError,\n ClosedError,\n SerializationError,\n} from \"@tell-rs/core\";\n\n// Re-export browser-specific config\nexport type { TellBrowserConfig } from \"./config.js\";\nexport { development, production } from \"./config.js\";\nexport type { DeviceContext } from \"./context.js\";\n\n// ---------------------------------------------------------------------------\n// Module-level state\n// ---------------------------------------------------------------------------\n\nlet configured = false;\nlet closed = false;\nlet _disabled = false;\nlet _optedOut = false;\n\nlet storage: TellStorage;\nlet transport: BrowserTransport;\nlet eventBatcher: Batcher<JsonEvent>;\nlet logBatcher: Batcher<JsonLog>;\nlet sessionManager: SessionManager;\nlet resolvedConfig: ResolvedBrowserConfig;\n\nlet _apiKey: string;\nlet deviceId: string;\nlet userId: string | undefined;\nlet superProperties: Properties = {};\nlet beforeSend: BeforeSendFn<JsonEvent> | BeforeSendFn<JsonEvent>[] | undefined;\nlet beforeSendLog:\n | BeforeSendFn<JsonLog>\n | BeforeSendFn<JsonLog>[]\n | undefined;\nlet sdkLogLevel: number;\n\nconst queue = new PreInitQueue(1000);\n\nlet unloadHandler: (() => void) | null = null;\nlet visibilityUnloadHandler: (() => void) | null = null;\nlet errorHandler: ((event: ErrorEvent) => void) | null = null;\nlet rejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;\n\nconst LOG_LEVELS: Record<string, number> = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction reportError(err: unknown): void {\n if (resolvedConfig?.onError && err instanceof Error) {\n resolvedConfig.onError(err);\n }\n}\n\nfunction sdkDebug(msg: string): void {\n if (sdkLogLevel >= LOG_LEVELS.debug) {\n console.debug(`[Tell] ${msg}`);\n }\n}\n\nfunction handleUnload(): void {\n const events = eventBatcher.drain();\n const logs = logBatcher.drain();\n transport.beacon(events, logs);\n}\n\nfunction handleVisibilityUnload(): void {\n if (document.visibilityState === \"hidden\") {\n handleUnload();\n }\n}\n\nfunction onNewSession(reason: SessionReason, sessionId: string): void {\n if (_disabled || _optedOut || closed) return;\n const ctx = captureContext();\n const event: JsonEvent = {\n type: \"context\",\n device_id: deviceId,\n session_id: sessionId,\n user_id: userId,\n timestamp: Date.now(),\n reason,\n ...ctx,\n };\n eventBatcher.add(event);\n}\n\nfunction persistSuperProps(): void {\n storage.set(STORAGE_KEYS.SUPER_PROPS, JSON.stringify(superProperties));\n}\n\nfunction loadSuperProps(): Properties {\n const raw = storage.get(STORAGE_KEYS.SUPER_PROPS);\n if (!raw) return {};\n try {\n return JSON.parse(raw) as Properties;\n } catch {\n storage.remove(STORAGE_KEYS.SUPER_PROPS);\n return {};\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport interface TellInstance {\n configure(apiKey: string, options?: TellBrowserConfig): void;\n track(eventName: string, properties?: Properties): void;\n identify(userId: string, traits?: Properties): void;\n group(groupId: string, properties?: Properties): void;\n revenue(\n amount: number,\n currency: string,\n orderId: string,\n properties?: Properties\n ): void;\n alias(previousId: string, userId: string): void;\n log(\n level: LogLevel,\n message: string,\n service?: string,\n data?: Properties\n ): void;\n logEmergency(message: string, service?: string, data?: Properties): void;\n logAlert(message: string, service?: string, data?: Properties): void;\n logCritical(message: string, service?: string, data?: Properties): void;\n logError(message: string, service?: string, data?: Properties): void;\n logWarning(message: string, service?: string, data?: Properties): void;\n logNotice(message: string, service?: string, data?: Properties): void;\n logInfo(message: string, service?: string, data?: Properties): void;\n logDebug(message: string, service?: string, data?: Properties): void;\n logTrace(message: string, service?: string, data?: Properties): void;\n register(properties: Properties): void;\n unregister(key: string): void;\n optOut(): void;\n optIn(): void;\n isOptedOut(): boolean;\n flush(): Promise<void>;\n close(): Promise<void>;\n reset(): void;\n enable(): void;\n disable(): void;\n /** @internal Reset all module state. Only for testing. */\n _resetForTesting(): void;\n}\n\nconst tell: TellInstance = {\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n configure(apiKey: string, options?: TellBrowserConfig): void {\n if (configured) {\n reportError(new ConfigurationError(\"Tell is already configured\"));\n return;\n }\n\n validateApiKey(apiKey);\n _apiKey = apiKey;\n resolvedConfig = resolveConfig(options);\n sdkLogLevel = LOG_LEVELS[resolvedConfig.logLevel] ?? 0;\n beforeSend = resolvedConfig.beforeSend;\n beforeSendLog = resolvedConfig.beforeSendLog;\n _disabled = resolvedConfig.disabled;\n\n // Persistence\n storage = createStorage(resolvedConfig.persistence);\n deviceId = storage.get(STORAGE_KEYS.DEVICE_ID) ?? generateId();\n storage.set(STORAGE_KEYS.DEVICE_ID, deviceId);\n userId = storage.get(STORAGE_KEYS.USER_ID) ?? undefined;\n _optedOut = storage.get(STORAGE_KEYS.OPT_OUT) === \"1\";\n superProperties = loadSuperProps();\n\n // UTM parameters — capture from URL and merge into super properties\n const utm = captureUtm();\n if (Object.keys(utm).length > 0) {\n Object.assign(superProperties, utm);\n persistSuperProps();\n }\n\n // Bot detection\n if (resolvedConfig.botDetection && isBot()) {\n _disabled = true;\n sdkDebug(\"bot detected, disabling\");\n }\n\n // Do Not Track\n if (\n resolvedConfig.respectDoNotTrack &&\n typeof navigator !== \"undefined\" &&\n navigator.doNotTrack === \"1\"\n ) {\n _disabled = true;\n sdkDebug(\"Do Not Track enabled, disabling\");\n }\n\n // Transport\n transport = new BrowserTransport({\n endpoint: resolvedConfig.endpoint,\n apiKey: _apiKey,\n maxRetries: resolvedConfig.maxRetries,\n networkTimeout: resolvedConfig.networkTimeout,\n onError: resolvedConfig.onError,\n onPayloadTooLarge: () => {\n eventBatcher.halveBatchSize();\n logBatcher.halveBatchSize();\n sdkDebug(\"413 received, halved batch size\");\n },\n });\n\n // Batchers\n eventBatcher = new Batcher<JsonEvent>({\n size: resolvedConfig.batchSize,\n interval: resolvedConfig.flushInterval,\n maxQueueSize: resolvedConfig.maxQueueSize,\n send: (items) => transport.sendEvents(items),\n onOverflow: () => sdkDebug(\"event queue overflow, dropping oldest\"),\n });\n\n logBatcher = new Batcher<JsonLog>({\n size: resolvedConfig.batchSize,\n interval: resolvedConfig.flushInterval,\n maxQueueSize: resolvedConfig.maxQueueSize,\n send: (items) => transport.sendLogs(items),\n onOverflow: () => sdkDebug(\"log queue overflow, dropping oldest\"),\n });\n\n // Session management\n sessionManager = new SessionManager({\n timeout: resolvedConfig.sessionTimeout,\n onNewSession,\n });\n\n // Unload handlers\n if (typeof window !== \"undefined\") {\n unloadHandler = handleUnload;\n window.addEventListener(\"beforeunload\", unloadHandler);\n }\n if (typeof document !== \"undefined\") {\n visibilityUnloadHandler = handleVisibilityUnload;\n document.addEventListener(\"visibilitychange\", visibilityUnloadHandler);\n }\n\n // Error auto-capture\n if (resolvedConfig.captureErrors && typeof window !== \"undefined\") {\n errorHandler = (event: ErrorEvent) => {\n if (_disabled || _optedOut || closed) return;\n const msg = event.message || \"Unknown error\";\n const data: Properties = {};\n if (event.filename) data.filename = event.filename;\n if (event.lineno) data.lineno = event.lineno;\n if (event.colno) data.colno = event.colno;\n if (event.error?.stack) data.stack = event.error.stack;\n tell.logError(msg, \"browser\", data);\n };\n rejectionHandler = (event: PromiseRejectionEvent) => {\n if (_disabled || _optedOut || closed) return;\n const reason = event.reason;\n const msg =\n reason instanceof Error\n ? reason.message\n : String(reason ?? \"Unhandled promise rejection\");\n const data: Properties = {};\n if (reason instanceof Error && reason.stack) data.stack = reason.stack;\n tell.logError(msg, \"browser\", data);\n };\n window.addEventListener(\"error\", errorHandler);\n window.addEventListener(\"unhandledrejection\", rejectionHandler);\n }\n\n configured = true;\n closed = false;\n\n sdkDebug(\n `configured (endpoint=${resolvedConfig.endpoint}, batch=${resolvedConfig.batchSize})`\n );\n\n // Replay pre-init queue\n queue.replay(tell as unknown as Record<string, (...args: any[]) => any>);\n },\n\n // -----------------------------------------------------------------------\n // Events\n // -----------------------------------------------------------------------\n\n track(eventName: string, properties?: Properties): void {\n if (!configured) {\n queue.push({ method: \"track\", args: [eventName, properties] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n validateEventName(eventName);\n } catch (err) {\n reportError(err);\n return;\n }\n\n let event: JsonEvent | null = {\n type: \"track\",\n event: eventName,\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n timestamp: Date.now(),\n ...superProperties,\n ...properties,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n sessionManager.touch();\n eventBatcher.add(event);\n },\n\n identify(newUserId: string, traits?: Properties): void {\n if (!configured) {\n queue.push({ method: \"identify\", args: [newUserId, traits] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n validateUserId(newUserId);\n } catch (err) {\n reportError(err);\n return;\n }\n\n userId = newUserId;\n storage.set(STORAGE_KEYS.USER_ID, userId);\n\n let event: JsonEvent | null = {\n type: \"identify\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n timestamp: Date.now(),\n ...traits,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n sessionManager.touch();\n eventBatcher.add(event);\n },\n\n group(groupId: string, properties?: Properties): void {\n if (!configured) {\n queue.push({ method: \"group\", args: [groupId, properties] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n if (!groupId) throw new ValidationError(\"groupId\", \"is required\");\n } catch (err) {\n reportError(err);\n return;\n }\n\n let event: JsonEvent | null = {\n type: \"group\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n group_id: groupId,\n timestamp: Date.now(),\n ...superProperties,\n ...properties,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n sessionManager.touch();\n eventBatcher.add(event);\n },\n\n revenue(\n amount: number,\n currency: string,\n orderId: string,\n properties?: Properties\n ): void {\n if (!configured) {\n queue.push({ method: \"revenue\", args: [amount, currency, orderId, properties] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n if (amount <= 0) throw new ValidationError(\"amount\", \"must be positive\");\n if (!currency) throw new ValidationError(\"currency\", \"is required\");\n if (!orderId) throw new ValidationError(\"orderId\", \"is required\");\n } catch (err) {\n reportError(err);\n return;\n }\n\n let event: JsonEvent | null = {\n type: \"track\",\n event: \"Order Completed\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n timestamp: Date.now(),\n ...superProperties,\n ...properties,\n order_id: orderId,\n amount,\n currency,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n sessionManager.touch();\n eventBatcher.add(event);\n },\n\n alias(previousId: string, newUserId: string): void {\n if (!configured) {\n queue.push({ method: \"alias\", args: [previousId, newUserId] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n if (!previousId)\n throw new ValidationError(\"previousId\", \"is required\");\n validateUserId(newUserId);\n } catch (err) {\n reportError(err);\n return;\n }\n\n let event: JsonEvent | null = {\n type: \"alias\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: newUserId,\n timestamp: Date.now(),\n previous_id: previousId,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n sessionManager.touch();\n eventBatcher.add(event);\n },\n\n // -----------------------------------------------------------------------\n // Logging\n // -----------------------------------------------------------------------\n\n log(\n level: LogLevel,\n message: string,\n service?: string,\n data?: Properties\n ): void {\n if (!configured) {\n queue.push({ method: \"log\", args: [level, message, service, data] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n validateLogMessage(message);\n } catch (err) {\n reportError(err);\n return;\n }\n\n let logEntry: JsonLog | null = {\n level,\n message,\n source: resolvedConfig.source,\n service: service ?? \"app\",\n session_id: sessionManager.sessionId,\n timestamp: Date.now(),\n data,\n };\n\n if (beforeSendLog) {\n logEntry = runBeforeSend(logEntry, beforeSendLog);\n if (logEntry === null) return;\n }\n\n logBatcher.add(logEntry);\n },\n\n logEmergency(message: string, service?: string, data?: Properties): void {\n tell.log(\"emergency\", message, service, data);\n },\n logAlert(message: string, service?: string, data?: Properties): void {\n tell.log(\"alert\", message, service, data);\n },\n logCritical(message: string, service?: string, data?: Properties): void {\n tell.log(\"critical\", message, service, data);\n },\n logError(message: string, service?: string, data?: Properties): void {\n tell.log(\"error\", message, service, data);\n },\n logWarning(message: string, service?: string, data?: Properties): void {\n tell.log(\"warning\", message, service, data);\n },\n logNotice(message: string, service?: string, data?: Properties): void {\n tell.log(\"notice\", message, service, data);\n },\n logInfo(message: string, service?: string, data?: Properties): void {\n tell.log(\"info\", message, service, data);\n },\n logDebug(message: string, service?: string, data?: Properties): void {\n tell.log(\"debug\", message, service, data);\n },\n logTrace(message: string, service?: string, data?: Properties): void {\n tell.log(\"trace\", message, service, data);\n },\n\n // -----------------------------------------------------------------------\n // Super Properties\n // -----------------------------------------------------------------------\n\n register(properties: Properties): void {\n if (!configured) {\n queue.push({ method: \"register\", args: [properties] });\n return;\n }\n Object.assign(superProperties, properties);\n persistSuperProps();\n },\n\n unregister(key: string): void {\n if (!configured) {\n queue.push({ method: \"unregister\", args: [key] });\n return;\n }\n delete superProperties[key];\n persistSuperProps();\n },\n\n // -----------------------------------------------------------------------\n // Privacy\n // -----------------------------------------------------------------------\n\n optOut(): void {\n if (!configured) {\n queue.push({ method: \"optOut\", args: [] });\n return;\n }\n _optedOut = true;\n storage.set(STORAGE_KEYS.OPT_OUT, \"1\");\n },\n\n optIn(): void {\n if (!configured) {\n queue.push({ method: \"optIn\", args: [] });\n return;\n }\n _optedOut = false;\n storage.remove(STORAGE_KEYS.OPT_OUT);\n },\n\n isOptedOut(): boolean {\n return _optedOut;\n },\n\n // -----------------------------------------------------------------------\n // Control\n // -----------------------------------------------------------------------\n\n enable(): void {\n _disabled = false;\n },\n\n disable(): void {\n _disabled = true;\n },\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n async flush(): Promise<void> {\n if (!configured) return;\n await Promise.all([eventBatcher.flush(), logBatcher.flush()]);\n },\n\n async close(): Promise<void> {\n if (!configured || closed) return;\n closed = true;\n\n if (sessionManager) sessionManager.destroy();\n\n if (typeof window !== \"undefined\" && unloadHandler) {\n window.removeEventListener(\"beforeunload\", unloadHandler);\n unloadHandler = null;\n }\n if (typeof document !== \"undefined\" && visibilityUnloadHandler) {\n document.removeEventListener(\"visibilitychange\", visibilityUnloadHandler);\n visibilityUnloadHandler = null;\n }\n if (typeof window !== \"undefined\") {\n if (errorHandler) {\n window.removeEventListener(\"error\", errorHandler);\n errorHandler = null;\n }\n if (rejectionHandler) {\n window.removeEventListener(\"unhandledrejection\", rejectionHandler);\n rejectionHandler = null;\n }\n }\n\n const work = Promise.all([eventBatcher.close(), logBatcher.close()]);\n const timeout = new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(\"close timed out\")),\n resolvedConfig.closeTimeout\n )\n );\n\n try {\n await Promise.race([work, timeout]);\n } catch (err) {\n reportError(err);\n }\n\n configured = false;\n },\n\n reset(): void {\n if (!configured) return;\n userId = undefined;\n deviceId = generateId();\n superProperties = {};\n\n storage.remove(STORAGE_KEYS.USER_ID);\n storage.set(STORAGE_KEYS.DEVICE_ID, deviceId);\n storage.remove(STORAGE_KEYS.SUPER_PROPS);\n\n if (sessionManager) {\n sessionManager.sessionId = generateId();\n }\n },\n\n // -----------------------------------------------------------------------\n // Testing helper\n // -----------------------------------------------------------------------\n\n _resetForTesting(): void {\n if (configured && !closed) {\n // Synchronously tear down timers\n if (sessionManager) sessionManager.destroy();\n if (eventBatcher) {\n eventBatcher.drain();\n eventBatcher.close().catch(() => {});\n }\n if (logBatcher) {\n logBatcher.drain();\n logBatcher.close().catch(() => {});\n }\n if (typeof window !== \"undefined\" && unloadHandler) {\n window.removeEventListener(\"beforeunload\", unloadHandler);\n }\n if (typeof document !== \"undefined\" && visibilityUnloadHandler) {\n document.removeEventListener(\n \"visibilitychange\",\n visibilityUnloadHandler\n );\n }\n if (typeof window !== \"undefined\") {\n if (errorHandler) window.removeEventListener(\"error\", errorHandler);\n if (rejectionHandler)\n window.removeEventListener(\"unhandledrejection\", rejectionHandler);\n }\n }\n\n configured = false;\n closed = false;\n _disabled = false;\n _optedOut = false;\n userId = undefined;\n deviceId = \"\";\n superProperties = {};\n beforeSend = undefined;\n beforeSendLog = undefined;\n sdkLogLevel = 0;\n unloadHandler = null;\n visibilityUnloadHandler = null;\n errorHandler = null;\n rejectionHandler = null;\n queue.clear();\n },\n};\n\nexport default tell;\nexport { tell };\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../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","../src/index.ts"],"sourcesContent":["import type { TellError, BeforeSendFn, JsonEvent, JsonLog } from \"@tell-rs/core\";\n\nexport interface TellBrowserConfig {\n endpoint?: string;\n batchSize?: number;\n flushInterval?: number;\n maxRetries?: number;\n closeTimeout?: number;\n networkTimeout?: number;\n logLevel?: \"error\" | \"warn\" | \"info\" | \"debug\";\n source?: string;\n onError?: (error: TellError) => void;\n disabled?: boolean;\n maxQueueSize?: number;\n sessionTimeout?: number;\n persistence?: \"localStorage\" | \"memory\";\n respectDoNotTrack?: boolean;\n botDetection?: boolean;\n captureErrors?: boolean;\n beforeSend?: BeforeSendFn<JsonEvent> | BeforeSendFn<JsonEvent>[];\n beforeSendLog?: BeforeSendFn<JsonLog> | BeforeSendFn<JsonLog>[];\n}\n\nexport const DEFAULTS = {\n endpoint: \"https://collect.tell.app\",\n batchSize: 20,\n flushInterval: 5_000,\n maxRetries: 5,\n closeTimeout: 5_000,\n networkTimeout: 10_000,\n logLevel: \"error\" as const,\n source: \"browser\",\n disabled: false,\n maxQueueSize: 1000,\n sessionTimeout: 1_800_000, // 30 min\n persistence: \"localStorage\" as const,\n respectDoNotTrack: false,\n botDetection: true,\n captureErrors: false,\n} as const;\n\nexport type ResolvedBrowserConfig = Required<\n Omit<TellBrowserConfig, \"onError\" | \"beforeSend\" | \"beforeSendLog\">\n> &\n Pick<TellBrowserConfig, \"onError\" | \"beforeSend\" | \"beforeSendLog\">;\n\nexport function resolveConfig(\n options: TellBrowserConfig | undefined\n): ResolvedBrowserConfig {\n return { ...DEFAULTS, ...options } as ResolvedBrowserConfig;\n}\n\n/** Development preset: localhost, small batches, fast flush, debug logging. */\nexport function development(\n overrides?: Partial<TellBrowserConfig>\n): TellBrowserConfig {\n return {\n endpoint: \"http://localhost:8080\",\n batchSize: 5,\n flushInterval: 2_000,\n logLevel: \"debug\",\n ...overrides,\n };\n}\n\n/** Production preset: default endpoint, error-only logging. */\nexport function production(\n overrides?: Partial<TellBrowserConfig>\n): TellBrowserConfig {\n return {\n logLevel: \"error\",\n ...overrides,\n };\n}\n","export interface TellStorage {\n get(key: string): string | null;\n set(key: string, value: string): void;\n remove(key: string): void;\n}\n\nexport const STORAGE_KEYS = {\n DEVICE_ID: \"tell_device_id\",\n USER_ID: \"tell_user_id\",\n OPT_OUT: \"tell_opt_out\",\n SUPER_PROPS: \"tell_super_props\",\n} as const;\n\nclass LocalStorageStorage implements TellStorage {\n get(key: string): string | null {\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n }\n\n set(key: string, value: string): void {\n try {\n localStorage.setItem(key, value);\n } catch {\n // Safari private mode or quota exceeded\n }\n }\n\n remove(key: string): void {\n try {\n localStorage.removeItem(key);\n } catch {\n // ignore\n }\n }\n}\n\nclass MemoryStorage implements TellStorage {\n private data = new Map<string, string>();\n\n get(key: string): string | null {\n return this.data.get(key) ?? null;\n }\n\n set(key: string, value: string): void {\n this.data.set(key, value);\n }\n\n remove(key: string): void {\n this.data.delete(key);\n }\n}\n\n/** Create a storage backend. Falls back to memory if localStorage is unavailable. */\nexport function createStorage(\n persistence: \"localStorage\" | \"memory\"\n): TellStorage {\n if (persistence === \"localStorage\" && typeof localStorage !== \"undefined\") {\n try {\n const testKey = \"tell_test\";\n localStorage.setItem(testKey, \"1\");\n localStorage.removeItem(testKey);\n return new LocalStorageStorage();\n } catch {\n // probe failed — fall through to memory\n }\n }\n return new MemoryStorage();\n}\n","/** Generate a 32-char hex ID (16 random bytes) using crypto.getRandomValues. */\nexport function generateId(): string {\n if (typeof crypto !== \"undefined\" && crypto.getRandomValues) {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n return Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n // Fallback for environments without crypto (extremely rare)\n let hex = \"\";\n for (let i = 0; i < 32; i++) {\n hex += ((Math.random() * 16) | 0).toString(16);\n }\n return hex;\n}\n","/** Returns true if the current environment appears to be an automated bot. */\nexport function isBot(): boolean {\n if (typeof navigator === \"undefined\") return false;\n if ((navigator as any).webdriver === true) return true;\n const ua = navigator.userAgent || \"\";\n return /headless/i.test(ua);\n}\n","export interface DeviceContext {\n browser?: string;\n browser_version?: string;\n os_name?: string;\n os_version?: string;\n device_type?: string;\n screen_width?: number;\n screen_height?: number;\n viewport_width?: number;\n viewport_height?: number;\n device_pixel_ratio?: number;\n locale?: string;\n timezone?: string;\n referrer?: string;\n referrer_domain?: string;\n url?: string;\n title?: string;\n connection_type?: string;\n downlink?: number;\n rtt?: number;\n save_data?: boolean;\n cpu_cores?: number;\n device_memory?: number;\n touch?: boolean;\n bot?: boolean;\n dark_mode?: boolean;\n path?: string;\n screen_orientation?: string;\n}\n\n/** Capture a snapshot of the current device/browser context. */\nexport function captureContext(): DeviceContext {\n const ctx: DeviceContext = {};\n\n if (typeof navigator !== \"undefined\") {\n const ua = navigator.userAgent || \"\";\n const parsed = parseUA(ua);\n ctx.browser = parsed.browser;\n ctx.browser_version = parsed.browserVersion;\n ctx.os_name = parsed.os;\n ctx.os_version = parsed.osVersion;\n ctx.locale = navigator.language;\n\n // Hardware capabilities (touch must come before device_type inference)\n if (\"hardwareConcurrency\" in navigator) {\n ctx.cpu_cores = (navigator as any).hardwareConcurrency;\n }\n if (\"deviceMemory\" in navigator) {\n ctx.device_memory = (navigator as any).deviceMemory;\n }\n if (\"maxTouchPoints\" in navigator) {\n ctx.touch = navigator.maxTouchPoints > 0;\n }\n\n ctx.device_type = inferDeviceType(parsed.os, ua, ctx.touch);\n\n // Network info (Chrome/Edge)\n const conn = (navigator as any).connection;\n if (conn) {\n if (conn.effectiveType) ctx.connection_type = conn.effectiveType;\n if (typeof conn.downlink === \"number\") ctx.downlink = conn.downlink;\n if (typeof conn.rtt === \"number\") ctx.rtt = conn.rtt;\n if (conn.saveData) ctx.save_data = true;\n }\n\n // Bot detection\n if ((navigator as any).webdriver) ctx.bot = true;\n }\n\n if (typeof screen !== \"undefined\") {\n ctx.screen_width = screen.width;\n ctx.screen_height = screen.height;\n const orient = (screen as any).orientation;\n if (orient?.type) ctx.screen_orientation = orient.type;\n }\n\n if (typeof window !== \"undefined\") {\n ctx.viewport_width = window.innerWidth;\n ctx.viewport_height = window.innerHeight;\n if (window.devicePixelRatio) {\n ctx.device_pixel_ratio = window.devicePixelRatio;\n }\n }\n\n if (typeof document !== \"undefined\") {\n ctx.referrer = document.referrer || undefined;\n if (ctx.referrer) {\n try {\n ctx.referrer_domain = new URL(ctx.referrer).hostname;\n } catch {\n // malformed referrer\n }\n }\n ctx.title = document.title || undefined;\n }\n\n if (typeof location !== \"undefined\") {\n ctx.url = location.href;\n if (location.pathname) ctx.path = location.pathname;\n }\n\n try {\n ctx.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n // Intl not available\n }\n\n if (typeof window !== \"undefined\" && window.matchMedia) {\n try {\n ctx.dark_mode = window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n } catch {\n // matchMedia not available\n }\n }\n\n return ctx;\n}\n\nfunction inferDeviceType(os?: string, ua?: string, touch?: boolean): string {\n // iPad (iPadOS 13+) reports as macOS but has touch support\n if (os === \"macOS\" && touch) return \"tablet\";\n // Android tablets have \"Android\" in UA but not \"Mobile\"\n if (os === \"Android\") return ua && !/Mobile/.test(ua) ? \"tablet\" : \"mobile\";\n if (os === \"iOS\") return \"mobile\";\n return \"desktop\";\n}\n\ninterface ParsedUA {\n browser?: string;\n browserVersion?: string;\n os?: string;\n osVersion?: string;\n}\n\nfunction parseUA(ua: string): ParsedUA {\n const result: ParsedUA = {};\n\n // Browser detection (order matters: Edge before Chrome, Chrome before Safari)\n if (/Edg\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Edge\";\n result.browserVersion = RegExp.$1;\n } else if (/OPR\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Opera\";\n result.browserVersion = RegExp.$1;\n } else if (/Chrome\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Chrome\";\n result.browserVersion = RegExp.$1;\n } else if (/Safari\\/[\\d.]+/.test(ua) && /Version\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Safari\";\n result.browserVersion = RegExp.$1;\n } else if (/Firefox\\/(\\d+[\\d.]*)/.test(ua)) {\n result.browser = \"Firefox\";\n result.browserVersion = RegExp.$1;\n }\n\n // OS detection\n if (/Windows NT ([\\d.]+)/.test(ua)) {\n result.os = \"Windows\";\n result.osVersion = RegExp.$1;\n } else if (/Mac OS X ([\\d_.]+)/.test(ua)) {\n result.os = \"macOS\";\n result.osVersion = RegExp.$1.replace(/_/g, \".\");\n } else if (/iPhone OS ([\\d_]+)/.test(ua)) {\n result.os = \"iOS\";\n result.osVersion = RegExp.$1.replace(/_/g, \".\");\n } else if (/Android ([\\d.]+)/.test(ua)) {\n result.os = \"Android\";\n result.osVersion = RegExp.$1;\n } else if (/Linux/.test(ua)) {\n result.os = \"Linux\";\n }\n\n return result;\n}\n","import type { Properties } from \"@tell-rs/core\";\n\nconst UTM_KEYS = [\n \"utm_source\",\n \"utm_medium\",\n \"utm_campaign\",\n \"utm_term\",\n \"utm_content\",\n] as const;\n\n/**\n * Extract UTM parameters from the current URL search string.\n * Returns only keys that are present and non-empty.\n */\nexport function captureUtm(): Properties {\n if (typeof window === \"undefined\" || !window.location?.search) return {};\n\n const params = new URLSearchParams(window.location.search);\n const utm: Properties = {};\n\n for (const key of UTM_KEYS) {\n const value = params.get(key);\n if (value) {\n utm[key] = value;\n }\n }\n\n return utm;\n}\n","import { generateId } from \"./id.js\";\n\nexport type SessionReason = \"session_start\" | \"session_timeout\" | \"app_foreground\";\n\nexport interface SessionManagerConfig {\n timeout: number; // ms\n onNewSession: (reason: SessionReason, sessionId: string) => void;\n}\n\nexport class SessionManager {\n private _sessionId: string;\n private lastHiddenAt = 0;\n private lastActivityAt: number;\n private readonly timeout: number;\n private readonly onNewSession: (reason: SessionReason, sessionId: string) => void;\n private readonly visibilityHandler: () => void;\n private lastContextAt: Record<string, number> = {};\n\n constructor(config: SessionManagerConfig) {\n this.timeout = config.timeout;\n this.onNewSession = config.onNewSession;\n this._sessionId = generateId();\n this.lastActivityAt = Date.now();\n\n this.emitContext(\"session_start\");\n\n this.visibilityHandler = () => this.handleVisibility();\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"visibilitychange\", this.visibilityHandler);\n }\n }\n\n get sessionId(): string {\n return this._sessionId;\n }\n\n set sessionId(id: string) {\n this._sessionId = id;\n }\n\n /** Update activity timestamp; rotates session if idle longer than timeout. */\n touch(): void {\n const now = Date.now();\n if (now - this.lastActivityAt > this.timeout) {\n this.rotateSession(\"session_timeout\");\n }\n this.lastActivityAt = now;\n }\n\n destroy(): void {\n if (typeof document !== \"undefined\") {\n document.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n }\n }\n\n private handleVisibility(): void {\n if (document.visibilityState === \"hidden\") {\n this.lastHiddenAt = Date.now();\n } else if (document.visibilityState === \"visible\") {\n if (this.lastHiddenAt > 0 && Date.now() - this.lastHiddenAt > this.timeout) {\n this.rotateSession(\"session_timeout\");\n } else if (this.lastHiddenAt > 0) {\n this.emitContext(\"app_foreground\");\n }\n this.lastHiddenAt = 0;\n }\n }\n\n private rotateSession(reason: SessionReason): void {\n this._sessionId = generateId();\n this.lastActivityAt = Date.now();\n this.emitContext(reason);\n }\n\n private emitContext(reason: SessionReason): void {\n const now = Date.now();\n const last = this.lastContextAt[reason] ?? 0;\n if (now - last < 1000) return; // cooldown\n this.lastContextAt[reason] = now;\n this.onNewSession(reason, this._sessionId);\n }\n}\n","import type { JsonEvent, JsonLog } from \"@tell-rs/core\";\nimport { NetworkError } from \"@tell-rs/core\";\n\nexport interface BrowserTransportConfig {\n endpoint: string;\n apiKey: string;\n maxRetries: number;\n networkTimeout: number;\n onError?: (error: Error) => void;\n onPayloadTooLarge?: () => void;\n}\n\nexport class BrowserTransport {\n private readonly endpoint: string;\n private readonly apiKey: string;\n private readonly maxRetries: number;\n private readonly networkTimeout: number;\n private readonly onError?: (error: Error) => void;\n private readonly onPayloadTooLarge?: () => void;\n\n constructor(config: BrowserTransportConfig) {\n this.endpoint = config.endpoint;\n this.apiKey = config.apiKey;\n this.maxRetries = config.maxRetries;\n this.networkTimeout = config.networkTimeout;\n this.onError = config.onError;\n this.onPayloadTooLarge = config.onPayloadTooLarge;\n }\n\n async sendEvents(events: JsonEvent[]): Promise<void> {\n if (events.length === 0) return;\n const body = events.map((e) => JSON.stringify(e)).join(\"\\n\");\n await this.send(\"/v1/events\", body);\n }\n\n async sendLogs(logs: JsonLog[]): Promise<void> {\n if (logs.length === 0) return;\n const body = logs.map((l) => JSON.stringify(l)).join(\"\\n\");\n await this.send(\"/v1/logs\", body);\n }\n\n /** Best-effort flush via sendBeacon for page unload. */\n beacon(events: JsonEvent[], logs: JsonLog[]): void {\n if (typeof navigator === \"undefined\" || !navigator.sendBeacon) return;\n\n if (events.length > 0) {\n const body = events.map((e) => JSON.stringify(e)).join(\"\\n\");\n const blob = new Blob([body], { type: \"text/plain\" });\n const url = `${this.endpoint}/v1/events?token=${encodeURIComponent(this.apiKey)}`;\n navigator.sendBeacon(url, blob);\n }\n\n if (logs.length > 0) {\n const body = logs.map((l) => JSON.stringify(l)).join(\"\\n\");\n const blob = new Blob([body], { type: \"text/plain\" });\n const url = `${this.endpoint}/v1/logs?token=${encodeURIComponent(this.apiKey)}`;\n navigator.sendBeacon(url, blob);\n }\n }\n\n private resolvePort(): string {\n try {\n const u = new URL(this.endpoint);\n if (u.port) return u.port;\n return u.protocol === \"https:\" ? \"443\" : \"80\";\n } catch {\n return \"unknown\";\n }\n }\n\n private async send(path: string, body: string): Promise<void> {\n // Auth via query param + text/plain content-type keeps this a CORS\n // \"simple request\" — no preflight OPTIONS needed. This matches the\n // pattern used by beacon() and by every major analytics SDK.\n const url = `${this.endpoint}${path}?token=${encodeURIComponent(this.apiKey)}`;\n const port = this.resolvePort();\n const headers: Record<string, string> = {\n \"Content-Type\": \"text/plain\",\n };\n\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n if (attempt > 0) {\n await this.backoff(attempt);\n }\n\n // Skip attempt if browser reports offline\n if (typeof navigator !== \"undefined\" && !navigator.onLine) {\n lastError = new NetworkError(`Browser is offline (endpoint: ${url}, port: ${port})`);\n continue;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(\n () => controller.abort(),\n this.networkTimeout\n );\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n signal: controller.signal,\n keepalive: true,\n });\n\n if (response.status === 202) {\n return;\n }\n\n if (response.status === 207) {\n if (this.onError) {\n this.onError(\n new NetworkError(\n `Partial success: some items rejected`,\n 207\n )\n );\n }\n return;\n }\n\n if (response.status === 413) {\n if (this.onPayloadTooLarge) {\n this.onPayloadTooLarge();\n }\n throw new NetworkError(\"Payload too large\", 413);\n }\n\n if (response.status === 401) {\n throw new NetworkError(\"Invalid API key\", 401);\n }\n\n if (response.status >= 400 && response.status < 500) {\n throw new NetworkError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status\n );\n }\n\n // 5xx — retryable\n lastError = new NetworkError(\n `HTTP ${response.status} from ${url} (port ${port}): ${response.statusText}`,\n response.status\n );\n } catch (err) {\n if (err instanceof NetworkError && err.statusCode === 413) {\n throw err;\n }\n\n if (\n err instanceof NetworkError &&\n err.statusCode &&\n err.statusCode < 500\n ) {\n if (this.onError) this.onError(err);\n return;\n }\n\n // DNS failures, connection refused, and CORS errors surface as\n // TypeError from fetch. Include the full URL so the developer can\n // verify the endpoint and port. These won't resolve by retrying.\n if (err instanceof TypeError) {\n if (this.onError)\n this.onError(\n new NetworkError(\n `Failed to connect to ${url} (port ${port}): ${err.message}`\n )\n );\n return;\n }\n\n lastError =\n err instanceof Error ? err : new NetworkError(String(err));\n } finally {\n clearTimeout(timer);\n }\n }\n\n if (lastError && this.onError) {\n this.onError(lastError);\n }\n }\n\n private backoff(attempt: number): Promise<void> {\n const base = 1000 * Math.pow(1.5, attempt - 1);\n const jitter = base * 0.2 * Math.random();\n const delay = Math.min(base + jitter, 30_000);\n return new Promise((resolve) => setTimeout(resolve, delay));\n }\n}\n","import type { LogLevel, Properties } from \"@tell-rs/core\";\n\nexport type QueuedCall =\n | { method: \"track\"; args: [string, Properties?] }\n | { method: \"identify\"; args: [string, Properties?] }\n | { method: \"group\"; args: [string, Properties?] }\n | { method: \"revenue\"; args: [number, string, string, Properties?] }\n | { method: \"alias\"; args: [string, string] }\n | { method: \"log\"; args: [LogLevel, string, string?, Properties?] }\n | { method: \"register\"; args: [Properties] }\n | { method: \"unregister\"; args: [string] }\n | { method: \"optOut\"; args: [] }\n | { method: \"optIn\"; args: [] };\n\nexport class PreInitQueue {\n private items: QueuedCall[] = [];\n readonly maxSize: number;\n\n constructor(maxSize = 1000) {\n this.maxSize = maxSize;\n }\n\n push(call: QueuedCall): void {\n if (this.items.length >= this.maxSize) {\n this.items.shift(); // drop oldest\n }\n this.items.push(call);\n }\n\n replay(target: Record<string, (...args: any[]) => any>): void {\n const calls = this.items;\n this.items = [];\n for (const call of calls) {\n try {\n target[call.method](...call.args);\n } catch {\n // continue on per-call error\n }\n }\n }\n\n get length(): number {\n return this.items.length;\n }\n\n clear(): void {\n this.items = [];\n }\n}\n","import type {\n JsonEvent,\n JsonLog,\n LogLevel,\n Properties,\n BeforeSendFn,\n} from \"@tell-rs/core\";\nimport {\n ClosedError,\n ConfigurationError,\n ValidationError,\n validateApiKey,\n validateEventName,\n validateLogMessage,\n validateUserId,\n Batcher,\n runBeforeSend,\n} from \"@tell-rs/core\";\n\nimport type { TellBrowserConfig, ResolvedBrowserConfig } from \"./config.js\";\nimport { resolveConfig } from \"./config.js\";\nimport type { TellStorage } from \"./persistence.js\";\nimport { createStorage, STORAGE_KEYS } from \"./persistence.js\";\nimport { generateId } from \"./id.js\";\nimport { isBot } from \"./bot.js\";\nimport { captureContext } from \"./context.js\";\nimport { captureUtm } from \"./utm.js\";\nimport type { SessionReason } from \"./session.js\";\nimport { SessionManager } from \"./session.js\";\nimport { BrowserTransport } from \"./transport.js\";\nimport { PreInitQueue } from \"./queue.js\";\n\n// Re-export core types and values\nexport { Events, type EventName } from \"@tell-rs/core\";\nexport type { Properties, LogLevel, JsonEvent, JsonLog, BeforeSendFn } from \"@tell-rs/core\";\nexport { redact, redactLog, SENSITIVE_PARAMS, type RedactOptions } from \"@tell-rs/core\";\nexport {\n TellError,\n ConfigurationError,\n ValidationError,\n NetworkError,\n ClosedError,\n SerializationError,\n} from \"@tell-rs/core\";\n\n// Re-export browser-specific config\nexport type { TellBrowserConfig } from \"./config.js\";\nexport { development, production } from \"./config.js\";\nexport type { DeviceContext } from \"./context.js\";\n\n// ---------------------------------------------------------------------------\n// Module-level state\n// ---------------------------------------------------------------------------\n\nlet configured = false;\nlet closed = false;\nlet _disabled = false;\nlet _optedOut = false;\n\nlet storage: TellStorage;\nlet transport: BrowserTransport;\nlet eventBatcher: Batcher<JsonEvent>;\nlet logBatcher: Batcher<JsonLog>;\nlet sessionManager: SessionManager;\nlet resolvedConfig: ResolvedBrowserConfig;\n\nlet _apiKey: string;\nlet deviceId: string;\nlet userId: string | undefined;\nlet superProperties: Properties = {};\nlet beforeSend: BeforeSendFn<JsonEvent> | BeforeSendFn<JsonEvent>[] | undefined;\nlet beforeSendLog:\n | BeforeSendFn<JsonLog>\n | BeforeSendFn<JsonLog>[]\n | undefined;\nlet sdkLogLevel: number;\n\nconst queue = new PreInitQueue(1000);\n\nlet unloadHandler: (() => void) | null = null;\nlet visibilityUnloadHandler: (() => void) | null = null;\nlet errorHandler: ((event: ErrorEvent) => void) | null = null;\nlet rejectionHandler: ((event: PromiseRejectionEvent) => void) | null = null;\n\nconst LOG_LEVELS: Record<string, number> = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n};\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction reportError(err: unknown): void {\n if (resolvedConfig?.onError && err instanceof Error) {\n resolvedConfig.onError(err);\n }\n}\n\nfunction sdkDebug(msg: string): void {\n if (sdkLogLevel >= LOG_LEVELS.debug) {\n console.debug(`[Tell] ${msg}`);\n }\n}\n\nfunction handleUnload(): void {\n const events = eventBatcher.drain();\n const logs = logBatcher.drain();\n transport.beacon(events, logs);\n}\n\nfunction handleVisibilityUnload(): void {\n if (document.visibilityState === \"hidden\") {\n handleUnload();\n }\n}\n\nfunction onNewSession(reason: SessionReason, sessionId: string): void {\n if (_disabled || _optedOut || closed) return;\n const ctx = captureContext();\n const event: JsonEvent = {\n type: \"context\",\n device_id: deviceId,\n session_id: sessionId,\n user_id: userId,\n timestamp: Date.now(),\n reason,\n ...ctx,\n };\n eventBatcher.add(event);\n}\n\nfunction persistSuperProps(): void {\n storage.set(STORAGE_KEYS.SUPER_PROPS, JSON.stringify(superProperties));\n}\n\nfunction loadSuperProps(): Properties {\n const raw = storage.get(STORAGE_KEYS.SUPER_PROPS);\n if (!raw) return {};\n try {\n return JSON.parse(raw) as Properties;\n } catch {\n storage.remove(STORAGE_KEYS.SUPER_PROPS);\n return {};\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport interface TellInstance {\n configure(apiKey: string, options?: TellBrowserConfig): void;\n track(eventName: string, properties?: Properties): void;\n identify(userId: string, traits?: Properties): void;\n group(groupId: string, properties?: Properties): void;\n revenue(\n amount: number,\n currency: string,\n orderId: string,\n properties?: Properties\n ): void;\n alias(previousId: string, userId: string): void;\n log(\n level: LogLevel,\n message: string,\n service?: string,\n data?: Properties\n ): void;\n logEmergency(message: string, service?: string, data?: Properties): void;\n logAlert(message: string, service?: string, data?: Properties): void;\n logCritical(message: string, service?: string, data?: Properties): void;\n logError(message: string, service?: string, data?: Properties): void;\n logWarning(message: string, service?: string, data?: Properties): void;\n logNotice(message: string, service?: string, data?: Properties): void;\n logInfo(message: string, service?: string, data?: Properties): void;\n logDebug(message: string, service?: string, data?: Properties): void;\n logTrace(message: string, service?: string, data?: Properties): void;\n register(properties: Properties): void;\n unregister(key: string): void;\n optOut(): void;\n optIn(): void;\n isOptedOut(): boolean;\n flush(): Promise<void>;\n close(): Promise<void>;\n reset(): void;\n enable(): void;\n disable(): void;\n /** @internal Reset all module state. Only for testing. */\n _resetForTesting(): void;\n}\n\nconst tell: TellInstance = {\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n configure(apiKey: string, options?: TellBrowserConfig): void {\n if (configured) {\n reportError(new ConfigurationError(\"Tell is already configured\"));\n return;\n }\n\n validateApiKey(apiKey);\n _apiKey = apiKey;\n resolvedConfig = resolveConfig(options);\n sdkLogLevel = LOG_LEVELS[resolvedConfig.logLevel] ?? 0;\n beforeSend = resolvedConfig.beforeSend;\n beforeSendLog = resolvedConfig.beforeSendLog;\n _disabled = resolvedConfig.disabled;\n\n // Persistence\n storage = createStorage(resolvedConfig.persistence);\n deviceId = storage.get(STORAGE_KEYS.DEVICE_ID) ?? generateId();\n storage.set(STORAGE_KEYS.DEVICE_ID, deviceId);\n userId = storage.get(STORAGE_KEYS.USER_ID) ?? undefined;\n _optedOut = storage.get(STORAGE_KEYS.OPT_OUT) === \"1\";\n superProperties = loadSuperProps();\n\n // UTM parameters — capture from URL and merge into super properties\n const utm = captureUtm();\n if (Object.keys(utm).length > 0) {\n Object.assign(superProperties, utm);\n persistSuperProps();\n }\n\n // Bot detection\n if (resolvedConfig.botDetection && isBot()) {\n _disabled = true;\n sdkDebug(\"bot detected, disabling\");\n }\n\n // Do Not Track\n if (\n resolvedConfig.respectDoNotTrack &&\n typeof navigator !== \"undefined\" &&\n navigator.doNotTrack === \"1\"\n ) {\n _disabled = true;\n sdkDebug(\"Do Not Track enabled, disabling\");\n }\n\n // Transport\n transport = new BrowserTransport({\n endpoint: resolvedConfig.endpoint,\n apiKey: _apiKey,\n maxRetries: resolvedConfig.maxRetries,\n networkTimeout: resolvedConfig.networkTimeout,\n onError: resolvedConfig.onError,\n onPayloadTooLarge: () => {\n eventBatcher.halveBatchSize();\n logBatcher.halveBatchSize();\n sdkDebug(\"413 received, halved batch size\");\n },\n });\n\n // Batchers\n eventBatcher = new Batcher<JsonEvent>({\n size: resolvedConfig.batchSize,\n interval: resolvedConfig.flushInterval,\n maxQueueSize: resolvedConfig.maxQueueSize,\n send: (items) => transport.sendEvents(items),\n onOverflow: () => sdkDebug(\"event queue overflow, dropping oldest\"),\n });\n\n logBatcher = new Batcher<JsonLog>({\n size: resolvedConfig.batchSize,\n interval: resolvedConfig.flushInterval,\n maxQueueSize: resolvedConfig.maxQueueSize,\n send: (items) => transport.sendLogs(items),\n onOverflow: () => sdkDebug(\"log queue overflow, dropping oldest\"),\n });\n\n // Session management\n sessionManager = new SessionManager({\n timeout: resolvedConfig.sessionTimeout,\n onNewSession,\n });\n\n // Unload handlers\n if (typeof window !== \"undefined\") {\n unloadHandler = handleUnload;\n window.addEventListener(\"beforeunload\", unloadHandler);\n }\n if (typeof document !== \"undefined\") {\n visibilityUnloadHandler = handleVisibilityUnload;\n document.addEventListener(\"visibilitychange\", visibilityUnloadHandler);\n }\n\n // Error auto-capture\n if (resolvedConfig.captureErrors && typeof window !== \"undefined\") {\n errorHandler = (event: ErrorEvent) => {\n if (_disabled || _optedOut || closed) return;\n const msg = event.message || \"Unknown error\";\n const data: Properties = {};\n if (event.filename) data.filename = event.filename;\n if (event.lineno) data.lineno = event.lineno;\n if (event.colno) data.colno = event.colno;\n if (event.error?.stack) data.stack = event.error.stack;\n tell.logError(msg, \"browser\", data);\n };\n rejectionHandler = (event: PromiseRejectionEvent) => {\n if (_disabled || _optedOut || closed) return;\n const reason = event.reason;\n const msg =\n reason instanceof Error\n ? reason.message\n : String(reason ?? \"Unhandled promise rejection\");\n const data: Properties = {};\n if (reason instanceof Error && reason.stack) data.stack = reason.stack;\n tell.logError(msg, \"browser\", data);\n };\n window.addEventListener(\"error\", errorHandler);\n window.addEventListener(\"unhandledrejection\", rejectionHandler);\n }\n\n configured = true;\n closed = false;\n\n sdkDebug(\n `configured (endpoint=${resolvedConfig.endpoint}, batch=${resolvedConfig.batchSize})`\n );\n\n // Replay pre-init queue\n queue.replay(tell as unknown as Record<string, (...args: any[]) => any>);\n },\n\n // -----------------------------------------------------------------------\n // Events\n // -----------------------------------------------------------------------\n\n track(eventName: string, properties?: Properties): void {\n if (!configured) {\n queue.push({ method: \"track\", args: [eventName, properties] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n validateEventName(eventName);\n } catch (err) {\n reportError(err);\n return;\n }\n\n sessionManager.touch();\n\n let event: JsonEvent | null = {\n type: \"track\",\n event: eventName,\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n timestamp: Date.now(),\n ...superProperties,\n ...properties,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n eventBatcher.add(event);\n },\n\n identify(newUserId: string, traits?: Properties): void {\n if (!configured) {\n queue.push({ method: \"identify\", args: [newUserId, traits] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n validateUserId(newUserId);\n } catch (err) {\n reportError(err);\n return;\n }\n\n userId = newUserId;\n storage.set(STORAGE_KEYS.USER_ID, userId);\n\n sessionManager.touch();\n\n let event: JsonEvent | null = {\n type: \"identify\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n timestamp: Date.now(),\n ...traits,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n eventBatcher.add(event);\n },\n\n group(groupId: string, properties?: Properties): void {\n if (!configured) {\n queue.push({ method: \"group\", args: [groupId, properties] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n if (!groupId) throw new ValidationError(\"groupId\", \"is required\");\n } catch (err) {\n reportError(err);\n return;\n }\n\n sessionManager.touch();\n\n let event: JsonEvent | null = {\n type: \"group\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n group_id: groupId,\n timestamp: Date.now(),\n ...superProperties,\n ...properties,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n eventBatcher.add(event);\n },\n\n revenue(\n amount: number,\n currency: string,\n orderId: string,\n properties?: Properties\n ): void {\n if (!configured) {\n queue.push({ method: \"revenue\", args: [amount, currency, orderId, properties] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n if (amount <= 0) throw new ValidationError(\"amount\", \"must be positive\");\n if (!currency) throw new ValidationError(\"currency\", \"is required\");\n if (!orderId) throw new ValidationError(\"orderId\", \"is required\");\n } catch (err) {\n reportError(err);\n return;\n }\n\n sessionManager.touch();\n\n let event: JsonEvent | null = {\n type: \"track\",\n event: \"Order Completed\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: userId,\n timestamp: Date.now(),\n ...superProperties,\n ...properties,\n order_id: orderId,\n amount,\n currency,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n eventBatcher.add(event);\n },\n\n alias(previousId: string, newUserId: string): void {\n if (!configured) {\n queue.push({ method: \"alias\", args: [previousId, newUserId] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n if (!previousId)\n throw new ValidationError(\"previousId\", \"is required\");\n validateUserId(newUserId);\n } catch (err) {\n reportError(err);\n return;\n }\n\n sessionManager.touch();\n\n let event: JsonEvent | null = {\n type: \"alias\",\n device_id: deviceId,\n session_id: sessionManager.sessionId,\n user_id: newUserId,\n timestamp: Date.now(),\n previous_id: previousId,\n };\n\n if (beforeSend) {\n event = runBeforeSend(event, beforeSend);\n if (event === null) return;\n }\n\n eventBatcher.add(event);\n },\n\n // -----------------------------------------------------------------------\n // Logging\n // -----------------------------------------------------------------------\n\n log(\n level: LogLevel,\n message: string,\n service?: string,\n data?: Properties\n ): void {\n if (!configured) {\n queue.push({ method: \"log\", args: [level, message, service, data] });\n return;\n }\n if (_disabled || _optedOut) return;\n if (closed) {\n reportError(new ClosedError());\n return;\n }\n try {\n validateLogMessage(message);\n } catch (err) {\n reportError(err);\n return;\n }\n\n let logEntry: JsonLog | null = {\n level,\n message,\n source: resolvedConfig.source,\n service: service ?? \"app\",\n session_id: sessionManager.sessionId,\n timestamp: Date.now(),\n data,\n };\n\n if (beforeSendLog) {\n logEntry = runBeforeSend(logEntry, beforeSendLog);\n if (logEntry === null) return;\n }\n\n logBatcher.add(logEntry);\n },\n\n logEmergency(message: string, service?: string, data?: Properties): void {\n tell.log(\"emergency\", message, service, data);\n },\n logAlert(message: string, service?: string, data?: Properties): void {\n tell.log(\"alert\", message, service, data);\n },\n logCritical(message: string, service?: string, data?: Properties): void {\n tell.log(\"critical\", message, service, data);\n },\n logError(message: string, service?: string, data?: Properties): void {\n tell.log(\"error\", message, service, data);\n },\n logWarning(message: string, service?: string, data?: Properties): void {\n tell.log(\"warning\", message, service, data);\n },\n logNotice(message: string, service?: string, data?: Properties): void {\n tell.log(\"notice\", message, service, data);\n },\n logInfo(message: string, service?: string, data?: Properties): void {\n tell.log(\"info\", message, service, data);\n },\n logDebug(message: string, service?: string, data?: Properties): void {\n tell.log(\"debug\", message, service, data);\n },\n logTrace(message: string, service?: string, data?: Properties): void {\n tell.log(\"trace\", message, service, data);\n },\n\n // -----------------------------------------------------------------------\n // Super Properties\n // -----------------------------------------------------------------------\n\n register(properties: Properties): void {\n if (!configured) {\n queue.push({ method: \"register\", args: [properties] });\n return;\n }\n Object.assign(superProperties, properties);\n persistSuperProps();\n },\n\n unregister(key: string): void {\n if (!configured) {\n queue.push({ method: \"unregister\", args: [key] });\n return;\n }\n delete superProperties[key];\n persistSuperProps();\n },\n\n // -----------------------------------------------------------------------\n // Privacy\n // -----------------------------------------------------------------------\n\n optOut(): void {\n if (!configured) {\n queue.push({ method: \"optOut\", args: [] });\n return;\n }\n _optedOut = true;\n storage.set(STORAGE_KEYS.OPT_OUT, \"1\");\n },\n\n optIn(): void {\n if (!configured) {\n queue.push({ method: \"optIn\", args: [] });\n return;\n }\n _optedOut = false;\n storage.remove(STORAGE_KEYS.OPT_OUT);\n },\n\n isOptedOut(): boolean {\n return _optedOut;\n },\n\n // -----------------------------------------------------------------------\n // Control\n // -----------------------------------------------------------------------\n\n enable(): void {\n _disabled = false;\n },\n\n disable(): void {\n _disabled = true;\n },\n\n // -----------------------------------------------------------------------\n // Lifecycle\n // -----------------------------------------------------------------------\n\n async flush(): Promise<void> {\n if (!configured) return;\n await Promise.all([eventBatcher.flush(), logBatcher.flush()]);\n },\n\n async close(): Promise<void> {\n if (!configured || closed) return;\n closed = true;\n\n if (sessionManager) sessionManager.destroy();\n\n if (typeof window !== \"undefined\" && unloadHandler) {\n window.removeEventListener(\"beforeunload\", unloadHandler);\n unloadHandler = null;\n }\n if (typeof document !== \"undefined\" && visibilityUnloadHandler) {\n document.removeEventListener(\"visibilitychange\", visibilityUnloadHandler);\n visibilityUnloadHandler = null;\n }\n if (typeof window !== \"undefined\") {\n if (errorHandler) {\n window.removeEventListener(\"error\", errorHandler);\n errorHandler = null;\n }\n if (rejectionHandler) {\n window.removeEventListener(\"unhandledrejection\", rejectionHandler);\n rejectionHandler = null;\n }\n }\n\n const work = Promise.all([eventBatcher.close(), logBatcher.close()]);\n const timeout = new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(\"close timed out\")),\n resolvedConfig.closeTimeout\n )\n );\n\n try {\n await Promise.race([work, timeout]);\n } catch (err) {\n reportError(err);\n }\n\n configured = false;\n },\n\n reset(): void {\n if (!configured) return;\n userId = undefined;\n deviceId = generateId();\n superProperties = {};\n\n storage.remove(STORAGE_KEYS.USER_ID);\n storage.set(STORAGE_KEYS.DEVICE_ID, deviceId);\n storage.remove(STORAGE_KEYS.SUPER_PROPS);\n\n if (sessionManager) {\n sessionManager.sessionId = generateId();\n }\n },\n\n // -----------------------------------------------------------------------\n // Testing helper\n // -----------------------------------------------------------------------\n\n _resetForTesting(): void {\n if (configured && !closed) {\n // Synchronously tear down timers\n if (sessionManager) sessionManager.destroy();\n if (eventBatcher) {\n eventBatcher.drain();\n eventBatcher.close().catch(() => {});\n }\n if (logBatcher) {\n logBatcher.drain();\n logBatcher.close().catch(() => {});\n }\n if (typeof window !== \"undefined\" && unloadHandler) {\n window.removeEventListener(\"beforeunload\", unloadHandler);\n }\n if (typeof document !== \"undefined\" && visibilityUnloadHandler) {\n document.removeEventListener(\n \"visibilitychange\",\n visibilityUnloadHandler\n );\n }\n if (typeof window !== \"undefined\") {\n if (errorHandler) window.removeEventListener(\"error\", errorHandler);\n if (rejectionHandler)\n window.removeEventListener(\"unhandledrejection\", rejectionHandler);\n }\n }\n\n configured = false;\n closed = false;\n _disabled = false;\n _optedOut = false;\n userId = undefined;\n deviceId = \"\";\n superProperties = {};\n beforeSend = undefined;\n beforeSendLog = undefined;\n sdkLogLevel = 0;\n unloadHandler = null;\n visibilityUnloadHandler = null;\n errorHandler = null;\n rejectionHandler = null;\n queue.clear();\n },\n};\n\nexport default tell;\nexport { tell };\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";var Tell=(()=>{var H=Object.defineProperty;var we=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var be=Object.prototype.hasOwnProperty;var Ee=(t,e)=>{for(var r in e)H(t,r,{get:e[r],enumerable:!0})},Se=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of ye(e))!be.call(t,n)&&n!==r&&H(t,n,{get:()=>e[n],enumerable:!(o=we(e,n))||o.enumerable});return t};var Pe=t=>Se(H({},"__esModule",{value:!0}),t);var Ue={};Ee(Ue,{ClosedError:()=>S,ConfigurationError:()=>C,Events:()=>Q,NetworkError:()=>f,SENSITIVE_PARAMS:()=>Y,SerializationError:()=>$,TellError:()=>x,ValidationError:()=>c,default:()=>Ae,development:()=>de,production:()=>le,redact:()=>Z,redactLog:()=>ee,tell:()=>y});var Q={UserSignedUp:"User Signed Up",UserSignedIn:"User Signed In",UserSignedOut:"User Signed Out",UserInvited:"User Invited",UserOnboarded:"User Onboarded",AuthenticationFailed:"Authentication Failed",PasswordReset:"Password Reset",TwoFactorEnabled:"Two Factor Enabled",TwoFactorDisabled:"Two Factor Disabled",OrderCompleted:"Order Completed",OrderRefunded:"Order Refunded",OrderCanceled:"Order Canceled",PaymentFailed:"Payment Failed",PaymentMethodAdded:"Payment Method Added",PaymentMethodUpdated:"Payment Method Updated",PaymentMethodRemoved:"Payment Method Removed",SubscriptionStarted:"Subscription Started",SubscriptionRenewed:"Subscription Renewed",SubscriptionPaused:"Subscription Paused",SubscriptionResumed:"Subscription Resumed",SubscriptionChanged:"Subscription Changed",SubscriptionCanceled:"Subscription Canceled",TrialStarted:"Trial Started",TrialEndingSoon:"Trial Ending Soon",TrialEnded:"Trial Ended",TrialConverted:"Trial Converted",CartViewed:"Cart Viewed",CartUpdated:"Cart Updated",CartAbandoned:"Cart Abandoned",CheckoutStarted:"Checkout Started",CheckoutCompleted:"Checkout Completed",PageViewed:"Page Viewed",FeatureUsed:"Feature Used",SearchPerformed:"Search Performed",FileUploaded:"File Uploaded",NotificationSent:"Notification Sent",NotificationClicked:"Notification Clicked",EmailSent:"Email Sent",EmailOpened:"Email Opened",EmailClicked:"Email Clicked",EmailBounced:"Email Bounced",EmailUnsubscribed:"Email Unsubscribed",SupportTicketCreated:"Support Ticket Created",SupportTicketResolved:"Support Ticket Resolved"};var x=class extends Error{constructor(e){super(e),this.name="TellError"}},C=class extends x{constructor(e){super(e),this.name="ConfigurationError"}},c=class extends x{field;constructor(e,r){super(`${e}: ${r}`),this.name="ValidationError",this.field=e}},f=class extends x{statusCode;constructor(e,r){super(e),this.name="NetworkError",this.statusCode=r}},S=class extends x{constructor(){super("Client is closed"),this.name="ClosedError"}},$=class extends x{constructor(e){super(e),this.name="SerializationError"}};var Te=/^[0-9a-fA-F]{32}$/,ie=256,se=65536;function W(t){if(!t)throw new C("apiKey is required");if(!Te.test(t))throw new C("apiKey must be exactly 32 hex characters")}function G(t){if(typeof t!="string"||t.length===0)throw new c("eventName","must be a non-empty string");if(t.length>ie)throw new c("eventName",`must be at most ${ie} characters, got ${t.length}`)}function X(t){if(typeof t!="string"||t.length===0)throw new c("message","must be a non-empty string");if(t.length>se)throw new c("message",`must be at most ${se} characters, got ${t.length}`)}function V(t){if(typeof t!="string"||t.length===0)throw new c("userId","must be a non-empty string")}var J=class{queue=[];timer=null;closed=!1;flushing=null;config;constructor(e){this.config=e,this.timer=setInterval(()=>{this.queue.length>0&&this.flush().catch(()=>{})},e.interval),this.timer&&typeof this.timer.unref=="function"&&this.timer.unref()}add(e){this.closed||(this.queue.length>=this.config.maxQueueSize&&(this.queue.shift(),this.config.onOverflow&&this.config.onOverflow()),this.queue.push(e),this.queue.length>=this.config.size&&this.flush().catch(()=>{}))}async flush(){if(this.flushing)return this.flushing;this.flushing=this.doFlush();try{await this.flushing}finally{this.flushing=null}}async close(){this.closed=!0,this.timer!==null&&(clearInterval(this.timer),this.timer=null),await this.flush()}get pending(){return this.queue.length}drain(){let e=this.queue;return this.queue=[],e}halveBatchSize(){this.config.size=Math.max(1,Math.floor(this.config.size/2))}async doFlush(){for(;this.queue.length>0;){let e=this.queue.slice(0,this.config.size);try{await this.config.send(e),this.queue.splice(0,e.length)}catch{return}}}};function I(t,e){let r=Array.isArray(e)?e:[e],o=t;for(let n of r){if(o===null)return null;o=n(o)}return o}var Y=["token","api_key","key","secret","password","access_token","refresh_token","authorization"];function _e(t,e){try{let r=new URL(t);for(let o of e)r.searchParams.delete(o);return r.toString()}catch{return t}}function xe(t,e){if(!t)return t;let r={};for(let[o,n]of Object.entries(t))r[o]=e.includes(o)?"[REDACTED]":n;return r}function Z(t){let{stripParams:e,redactKeys:r,dropRoutes:o}=t;return n=>{if(o&&o.length>0&&n.url)try{let d=new URL(String(n.url)).pathname;for(let E of o)if(d.startsWith(E))return null}catch{}let i=n;if(e&&e.length>0){for(let[d,E]of Object.entries(n))if(typeof E=="string"&&E.startsWith("http")){let N=_e(E,e);N!==E&&(i===n&&(i={...n}),i[d]=N)}}if(r&&r.length>0)for(let[d,E]of Object.entries(n))r.includes(d)&&(i===n&&(i={...n}),i[d]="[REDACTED]");return i}}function ee(t){let{redactKeys:e}=t;return r=>{if(e&&e.length>0&&r.data){let o=xe(r.data,e);if(o!==r.data)return{...r,data:o}}return r}}var Ce={endpoint:"https://collect.tell.app",batchSize:20,flushInterval:5e3,maxRetries:5,closeTimeout:5e3,networkTimeout:1e4,logLevel:"error",source:"browser",disabled:!1,maxQueueSize:1e3,sessionTimeout:18e5,persistence:"localStorage",respectDoNotTrack:!1,botDetection:!0,captureErrors:!1};function ae(t){return{...Ce,...t}}function de(t){return{endpoint:"http://localhost:8080",batchSize:5,flushInterval:2e3,logLevel:"debug",...t}}function le(t){return{logLevel:"error",...t}}var p={DEVICE_ID:"tell_device_id",USER_ID:"tell_user_id",OPT_OUT:"tell_opt_out",SUPER_PROPS:"tell_super_props"},te=class{get(e){try{return localStorage.getItem(e)}catch{return null}}set(e,r){try{localStorage.setItem(e,r)}catch{}}remove(e){try{localStorage.removeItem(e)}catch{}}},re=class{data=new Map;get(e){return this.data.get(e)??null}set(e,r){this.data.set(e,r)}remove(e){this.data.delete(e)}};function ue(t){if(t==="localStorage"&&typeof localStorage<"u")try{let e="tell_test";return localStorage.setItem(e,"1"),localStorage.removeItem(e),new te}catch{}return new re}function D(){if(typeof crypto<"u"&&crypto.getRandomValues){let e=new Uint8Array(16);return crypto.getRandomValues(e),Array.from(e,r=>r.toString(16).padStart(2,"0")).join("")}let t="";for(let e=0;e<32;e++)t+=(Math.random()*16|0).toString(16);return t}function ce(){if(typeof navigator>"u")return!1;if(navigator.webdriver===!0)return!0;let t=navigator.userAgent||"";return/headless/i.test(t)}function fe(){let t={};if(typeof navigator<"u"){let e=navigator.userAgent||"",r=Le(e);t.browser=r.browser,t.browser_version=r.browserVersion,t.os_name=r.os,t.os_version=r.osVersion,t.locale=navigator.language,"hardwareConcurrency"in navigator&&(t.cpu_cores=navigator.hardwareConcurrency),"deviceMemory"in navigator&&(t.device_memory=navigator.deviceMemory),"maxTouchPoints"in navigator&&(t.touch=navigator.maxTouchPoints>0),t.device_type=Re(r.os,e,t.touch);let o=navigator.connection;o&&(o.effectiveType&&(t.connection_type=o.effectiveType),typeof o.downlink=="number"&&(t.downlink=o.downlink),typeof o.rtt=="number"&&(t.rtt=o.rtt),o.saveData&&(t.save_data=!0)),navigator.webdriver&&(t.bot=!0)}if(typeof screen<"u"){t.screen_width=screen.width,t.screen_height=screen.height;let e=screen.orientation;e?.type&&(t.screen_orientation=e.type)}if(typeof window<"u"&&(t.viewport_width=window.innerWidth,t.viewport_height=window.innerHeight,window.devicePixelRatio&&(t.device_pixel_ratio=window.devicePixelRatio)),typeof document<"u"){if(t.referrer=document.referrer||void 0,t.referrer)try{t.referrer_domain=new URL(t.referrer).hostname}catch{}t.title=document.title||void 0}typeof location<"u"&&(t.url=location.href,location.pathname&&(t.path=location.pathname));try{t.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone}catch{}if(typeof window<"u"&&window.matchMedia)try{t.dark_mode=window.matchMedia("(prefers-color-scheme: dark)").matches}catch{}return t}function Re(t,e,r){return t==="macOS"&&r?"tablet":t==="Android"?e&&!/Mobile/.test(e)?"tablet":"mobile":t==="iOS"?"mobile":"desktop"}function Le(t){let e={};return/Edg\/(\d+[\d.]*)/.test(t)?(e.browser="Edge",e.browserVersion=RegExp.$1):/OPR\/(\d+[\d.]*)/.test(t)?(e.browser="Opera",e.browserVersion=RegExp.$1):/Chrome\/(\d+[\d.]*)/.test(t)?(e.browser="Chrome",e.browserVersion=RegExp.$1):/Safari\/[\d.]+/.test(t)&&/Version\/(\d+[\d.]*)/.test(t)?(e.browser="Safari",e.browserVersion=RegExp.$1):/Firefox\/(\d+[\d.]*)/.test(t)&&(e.browser="Firefox",e.browserVersion=RegExp.$1),/Windows NT ([\d.]+)/.test(t)?(e.os="Windows",e.osVersion=RegExp.$1):/Mac OS X ([\d_.]+)/.test(t)?(e.os="macOS",e.osVersion=RegExp.$1.replace(/_/g,".")):/iPhone OS ([\d_]+)/.test(t)?(e.os="iOS",e.osVersion=RegExp.$1.replace(/_/g,".")):/Android ([\d.]+)/.test(t)?(e.os="Android",e.osVersion=RegExp.$1):/Linux/.test(t)&&(e.os="Linux"),e}var ke=["utm_source","utm_medium","utm_campaign","utm_term","utm_content"];function ge(){if(typeof window>"u"||!window.location?.search)return{};let t=new URLSearchParams(window.location.search),e={};for(let r of ke){let o=t.get(r);o&&(e[r]=o)}return e}var z=class{_sessionId;lastHiddenAt=0;lastActivityAt;timeout;onNewSession;visibilityHandler;lastContextAt={};constructor(e){this.timeout=e.timeout,this.onNewSession=e.onNewSession,this._sessionId=D(),this.lastActivityAt=Date.now(),this.emitContext("session_start"),this.visibilityHandler=()=>this.handleVisibility(),typeof document<"u"&&document.addEventListener("visibilitychange",this.visibilityHandler)}get sessionId(){return this._sessionId}set sessionId(e){this._sessionId=e}touch(){let e=Date.now();e-this.lastActivityAt>this.timeout&&this.rotateSession("session_timeout"),this.lastActivityAt=e}destroy(){typeof document<"u"&&document.removeEventListener("visibilitychange",this.visibilityHandler)}handleVisibility(){document.visibilityState==="hidden"?this.lastHiddenAt=Date.now():document.visibilityState==="visible"&&(this.lastHiddenAt>0&&Date.now()-this.lastHiddenAt>this.timeout?this.rotateSession("session_timeout"):this.lastHiddenAt>0&&this.emitContext("app_foreground"),this.lastHiddenAt=0)}rotateSession(e){this._sessionId=D(),this.lastActivityAt=Date.now(),this.emitContext(e)}emitContext(e){let r=Date.now(),o=this.lastContextAt[e]??0;r-o<1e3||(this.lastContextAt[e]=r,this.onNewSession(e,this._sessionId))}};var M=class{endpoint;apiKey;maxRetries;networkTimeout;onError;onPayloadTooLarge;constructor(e){this.endpoint=e.endpoint,this.apiKey=e.apiKey,this.maxRetries=e.maxRetries,this.networkTimeout=e.networkTimeout,this.onError=e.onError,this.onPayloadTooLarge=e.onPayloadTooLarge}async sendEvents(e){if(e.length===0)return;let r=e.map(o=>JSON.stringify(o)).join(`
|
|
2
|
+
`);await this.send("/v1/events",r)}async sendLogs(e){if(e.length===0)return;let r=e.map(o=>JSON.stringify(o)).join(`
|
|
3
|
+
`);await this.send("/v1/logs",r)}beacon(e,r){if(!(typeof navigator>"u"||!navigator.sendBeacon)){if(e.length>0){let o=e.map(d=>JSON.stringify(d)).join(`
|
|
4
|
+
`),n=new Blob([o],{type:"text/plain"}),i=`${this.endpoint}/v1/events?token=${encodeURIComponent(this.apiKey)}`;navigator.sendBeacon(i,n)}if(r.length>0){let o=r.map(d=>JSON.stringify(d)).join(`
|
|
5
|
+
`),n=new Blob([o],{type:"text/plain"}),i=`${this.endpoint}/v1/logs?token=${encodeURIComponent(this.apiKey)}`;navigator.sendBeacon(i,n)}}}resolvePort(){try{let e=new URL(this.endpoint);return e.port?e.port:e.protocol==="https:"?"443":"80"}catch{return"unknown"}}async send(e,r){let o=`${this.endpoint}${e}?token=${encodeURIComponent(this.apiKey)}`,n=this.resolvePort(),i={"Content-Type":"text/plain"},d;for(let E=0;E<=this.maxRetries;E++){if(E>0&&await this.backoff(E),typeof navigator<"u"&&!navigator.onLine){d=new f(`Browser is offline (endpoint: ${o}, port: ${n})`);continue}let N=new AbortController,he=setTimeout(()=>N.abort(),this.networkTimeout);try{let a=await fetch(o,{method:"POST",headers:i,body:r,signal:N.signal,keepalive:!0});if(a.status===202)return;if(a.status===207){this.onError&&this.onError(new f("Partial success: some items rejected",207));return}if(a.status===413)throw this.onPayloadTooLarge&&this.onPayloadTooLarge(),new f("Payload too large",413);if(a.status===401)throw new f("Invalid API key",401);if(a.status>=400&&a.status<500)throw new f(`HTTP ${a.status}: ${a.statusText}`,a.status);d=new f(`HTTP ${a.status} from ${o} (port ${n}): ${a.statusText}`,a.status)}catch(a){if(a instanceof f&&a.statusCode===413)throw a;if(a instanceof f&&a.statusCode&&a.statusCode<500){this.onError&&this.onError(a);return}if(a instanceof TypeError){this.onError&&this.onError(new f(`Failed to connect to ${o} (port ${n}): ${a.message}`));return}d=a instanceof Error?a:new f(String(a))}finally{clearTimeout(he)}}d&&this.onError&&this.onError(d)}backoff(e){let r=1e3*Math.pow(1.5,e-1),o=r*.2*Math.random(),n=Math.min(r+o,3e4);return new Promise(i=>setTimeout(i,n))}};var j=class{items=[];maxSize;constructor(e=1e3){this.maxSize=e}push(e){this.items.length>=this.maxSize&&this.items.shift(),this.items.push(e)}replay(e){let r=this.items;this.items=[];for(let o of r)try{e[o.method](...o.args)}catch{}}get length(){return this.items.length}clear(){this.items=[]}};var l=!1,v=!1,g=!1,h=!1,b,q,w,k,u,s,pe,_,R,L={},P,K,ne,T=new j(1e3),O=null,B=null,A=null,U=null,me={error:0,warn:1,info:2,debug:3};function m(t){s?.onError&&t instanceof Error&&s.onError(t)}function F(t){ne>=me.debug&&console.debug(`[Tell] ${t}`)}function ve(){let t=w.drain(),e=k.drain();q.beacon(t,e)}function Ie(){document.visibilityState==="hidden"&&ve()}function Oe(t,e){if(g||h||v)return;let r=fe(),o={type:"context",device_id:_,session_id:e,user_id:R,timestamp:Date.now(),reason:t,...r};w.add(o)}function oe(){b.set(p.SUPER_PROPS,JSON.stringify(L))}function Be(){let t=b.get(p.SUPER_PROPS);if(!t)return{};try{return JSON.parse(t)}catch{return b.remove(p.SUPER_PROPS),{}}}var y={configure(t,e){if(l){m(new C("Tell is already configured"));return}W(t),pe=t,s=ae(e),ne=me[s.logLevel]??0,P=s.beforeSend,K=s.beforeSendLog,g=s.disabled,b=ue(s.persistence),_=b.get(p.DEVICE_ID)??D(),b.set(p.DEVICE_ID,_),R=b.get(p.USER_ID)??void 0,h=b.get(p.OPT_OUT)==="1",L=Be();let r=ge();Object.keys(r).length>0&&(Object.assign(L,r),oe()),s.botDetection&&ce()&&(g=!0,F("bot detected, disabling")),s.respectDoNotTrack&&typeof navigator<"u"&&navigator.doNotTrack==="1"&&(g=!0,F("Do Not Track enabled, disabling")),q=new M({endpoint:s.endpoint,apiKey:pe,maxRetries:s.maxRetries,networkTimeout:s.networkTimeout,onError:s.onError,onPayloadTooLarge:()=>{w.halveBatchSize(),k.halveBatchSize(),F("413 received, halved batch size")}}),w=new J({size:s.batchSize,interval:s.flushInterval,maxQueueSize:s.maxQueueSize,send:o=>q.sendEvents(o),onOverflow:()=>F("event queue overflow, dropping oldest")}),k=new J({size:s.batchSize,interval:s.flushInterval,maxQueueSize:s.maxQueueSize,send:o=>q.sendLogs(o),onOverflow:()=>F("log queue overflow, dropping oldest")}),u=new z({timeout:s.sessionTimeout,onNewSession:Oe}),typeof window<"u"&&(O=ve,window.addEventListener("beforeunload",O)),typeof document<"u"&&(B=Ie,document.addEventListener("visibilitychange",B)),s.captureErrors&&typeof window<"u"&&(A=o=>{if(g||h||v)return;let n=o.message||"Unknown error",i={};o.filename&&(i.filename=o.filename),o.lineno&&(i.lineno=o.lineno),o.colno&&(i.colno=o.colno),o.error?.stack&&(i.stack=o.error.stack),y.logError(n,"browser",i)},U=o=>{if(g||h||v)return;let n=o.reason,i=n instanceof Error?n.message:String(n??"Unhandled promise rejection"),d={};n instanceof Error&&n.stack&&(d.stack=n.stack),y.logError(i,"browser",d)},window.addEventListener("error",A),window.addEventListener("unhandledrejection",U)),l=!0,v=!1,F(`configured (endpoint=${s.endpoint}, batch=${s.batchSize})`),T.replay(y)},track(t,e){if(!l){T.push({method:"track",args:[t,e]});return}if(g||h)return;if(v){m(new S);return}try{G(t)}catch(o){m(o);return}u.touch();let r={type:"track",event:t,device_id:_,session_id:u.sessionId,user_id:R,timestamp:Date.now(),...L,...e};P&&(r=I(r,P),r===null)||w.add(r)},identify(t,e){if(!l){T.push({method:"identify",args:[t,e]});return}if(g||h)return;if(v){m(new S);return}try{V(t)}catch(o){m(o);return}R=t,b.set(p.USER_ID,R),u.touch();let r={type:"identify",device_id:_,session_id:u.sessionId,user_id:R,timestamp:Date.now(),...e};P&&(r=I(r,P),r===null)||w.add(r)},group(t,e){if(!l){T.push({method:"group",args:[t,e]});return}if(g||h)return;if(v){m(new S);return}try{if(!t)throw new c("groupId","is required")}catch(o){m(o);return}u.touch();let r={type:"group",device_id:_,session_id:u.sessionId,user_id:R,group_id:t,timestamp:Date.now(),...L,...e};P&&(r=I(r,P),r===null)||w.add(r)},revenue(t,e,r,o){if(!l){T.push({method:"revenue",args:[t,e,r,o]});return}if(g||h)return;if(v){m(new S);return}try{if(t<=0)throw new c("amount","must be positive");if(!e)throw new c("currency","is required");if(!r)throw new c("orderId","is required")}catch(i){m(i);return}u.touch();let n={type:"track",event:"Order Completed",device_id:_,session_id:u.sessionId,user_id:R,timestamp:Date.now(),...L,...o,order_id:r,amount:t,currency:e};P&&(n=I(n,P),n===null)||w.add(n)},alias(t,e){if(!l){T.push({method:"alias",args:[t,e]});return}if(g||h)return;if(v){m(new S);return}try{if(!t)throw new c("previousId","is required");V(e)}catch(o){m(o);return}u.touch();let r={type:"alias",device_id:_,session_id:u.sessionId,user_id:e,timestamp:Date.now(),previous_id:t};P&&(r=I(r,P),r===null)||w.add(r)},log(t,e,r,o){if(!l){T.push({method:"log",args:[t,e,r,o]});return}if(g||h)return;if(v){m(new S);return}try{X(e)}catch(i){m(i);return}let n={level:t,message:e,source:s.source,service:r??"app",session_id:u.sessionId,timestamp:Date.now(),data:o};K&&(n=I(n,K),n===null)||k.add(n)},logEmergency(t,e,r){y.log("emergency",t,e,r)},logAlert(t,e,r){y.log("alert",t,e,r)},logCritical(t,e,r){y.log("critical",t,e,r)},logError(t,e,r){y.log("error",t,e,r)},logWarning(t,e,r){y.log("warning",t,e,r)},logNotice(t,e,r){y.log("notice",t,e,r)},logInfo(t,e,r){y.log("info",t,e,r)},logDebug(t,e,r){y.log("debug",t,e,r)},logTrace(t,e,r){y.log("trace",t,e,r)},register(t){if(!l){T.push({method:"register",args:[t]});return}Object.assign(L,t),oe()},unregister(t){if(!l){T.push({method:"unregister",args:[t]});return}delete L[t],oe()},optOut(){if(!l){T.push({method:"optOut",args:[]});return}h=!0,b.set(p.OPT_OUT,"1")},optIn(){if(!l){T.push({method:"optIn",args:[]});return}h=!1,b.remove(p.OPT_OUT)},isOptedOut(){return h},enable(){g=!1},disable(){g=!0},async flush(){l&&await Promise.all([w.flush(),k.flush()])},async close(){if(!l||v)return;v=!0,u&&u.destroy(),typeof window<"u"&&O&&(window.removeEventListener("beforeunload",O),O=null),typeof document<"u"&&B&&(document.removeEventListener("visibilitychange",B),B=null),typeof window<"u"&&(A&&(window.removeEventListener("error",A),A=null),U&&(window.removeEventListener("unhandledrejection",U),U=null));let t=Promise.all([w.close(),k.close()]),e=new Promise((r,o)=>setTimeout(()=>o(new Error("close timed out")),s.closeTimeout));try{await Promise.race([t,e])}catch(r){m(r)}l=!1},reset(){l&&(R=void 0,_=D(),L={},b.remove(p.USER_ID),b.set(p.DEVICE_ID,_),b.remove(p.SUPER_PROPS),u&&(u.sessionId=D()))},_resetForTesting(){l&&!v&&(u&&u.destroy(),w&&(w.drain(),w.close().catch(()=>{})),k&&(k.drain(),k.close().catch(()=>{})),typeof window<"u"&&O&&window.removeEventListener("beforeunload",O),typeof document<"u"&&B&&document.removeEventListener("visibilitychange",B),typeof window<"u"&&(A&&window.removeEventListener("error",A),U&&window.removeEventListener("unhandledrejection",U))),l=!1,v=!1,g=!1,h=!1,R=void 0,_="",L={},P=void 0,K=void 0,ne=0,O=null,B=null,A=null,U=null,T.clear()}},Ae=y;return Pe(Ue);})();
|
|
6
|
+
(function(){var s=document.currentScript;if(s&&s.dataset.apiKey){Tell.tell.configure(s.dataset.apiKey,{endpoint:s.dataset.endpoint})}})();
|
|
7
|
+
//# sourceMappingURL=tell.global.js.map
|