pishoniq-tracker 0.0.0-stage → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,625 @@
1
+ 'use strict';
2
+
3
+ // src/session.ts
4
+ var SESSION_ID_KEY = "pishoniq_session_id";
5
+ var SESSION_LAST_ACTIVE_KEY = "pishoniq_session_last_active";
6
+ var SESSION_STARTED_KEY = "pishoniq_session_started";
7
+ var INACTIVITY_MS = 30 * 60 * 1e3;
8
+ var TOUCH_WRITE_THROTTLE_MS = 1e3;
9
+ var cachedSessionId = null;
10
+ var cachedLastActive = 0;
11
+ var cachedStartedAt = 0;
12
+ var lastTouchWrite = 0;
13
+ function isBrowser() {
14
+ return typeof window !== "undefined" && typeof localStorage !== "undefined";
15
+ }
16
+ function generateUUID() {
17
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
18
+ return crypto.randomUUID();
19
+ }
20
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
21
+ const r = Math.random() * 16 | 0;
22
+ const v = c === "x" ? r : r & 3 | 8;
23
+ return v.toString(16);
24
+ });
25
+ }
26
+ function readLastActive() {
27
+ if (!isBrowser()) return 0;
28
+ if (cachedLastActive) return cachedLastActive;
29
+ const raw = localStorage.getItem(SESSION_LAST_ACTIVE_KEY);
30
+ cachedLastActive = raw ? Number(raw) : 0;
31
+ return cachedLastActive;
32
+ }
33
+ function writeSession(sessionId, startedAt) {
34
+ if (!isBrowser()) return;
35
+ const now = Date.now();
36
+ cachedSessionId = sessionId;
37
+ cachedStartedAt = startedAt;
38
+ cachedLastActive = now;
39
+ lastTouchWrite = now;
40
+ try {
41
+ localStorage.setItem(SESSION_ID_KEY, sessionId);
42
+ localStorage.setItem(SESSION_STARTED_KEY, String(startedAt));
43
+ localStorage.setItem(SESSION_LAST_ACTIVE_KEY, String(now));
44
+ } catch {
45
+ }
46
+ }
47
+ function getSessionId() {
48
+ if (!isBrowser()) return "";
49
+ const now = Date.now();
50
+ if (cachedSessionId && cachedLastActive && now - cachedLastActive < INACTIVITY_MS) {
51
+ return cachedSessionId;
52
+ }
53
+ const existingId = cachedSessionId ?? localStorage.getItem(SESSION_ID_KEY);
54
+ const lastActive = readLastActive();
55
+ if (existingId && lastActive && now - lastActive < INACTIVITY_MS) {
56
+ cachedSessionId = existingId;
57
+ return existingId;
58
+ }
59
+ const newId = generateUUID();
60
+ writeSession(newId, now);
61
+ return newId;
62
+ }
63
+ function touchSession() {
64
+ if (!isBrowser()) return;
65
+ const now = Date.now();
66
+ cachedLastActive = now;
67
+ if (now - lastTouchWrite < TOUCH_WRITE_THROTTLE_MS) return;
68
+ lastTouchWrite = now;
69
+ try {
70
+ localStorage.setItem(SESSION_LAST_ACTIVE_KEY, String(now));
71
+ } catch {
72
+ }
73
+ }
74
+ function resetSession() {
75
+ const sessionId = generateUUID();
76
+ writeSession(sessionId, Date.now());
77
+ return { sessionId, isNew: true };
78
+ }
79
+ function ensureSession() {
80
+ if (!isBrowser()) {
81
+ return { sessionId: "", isNew: false };
82
+ }
83
+ const now = Date.now();
84
+ const existingId = cachedSessionId ?? localStorage.getItem(SESSION_ID_KEY);
85
+ const lastActive = readLastActive();
86
+ if (existingId && lastActive && now - lastActive < INACTIVITY_MS) {
87
+ cachedSessionId = existingId;
88
+ touchSession();
89
+ return { sessionId: existingId, isNew: false };
90
+ }
91
+ const { sessionId } = resetSession();
92
+ return { sessionId, isNew: true };
93
+ }
94
+ function getSessionStartedAt() {
95
+ if (!isBrowser()) return Date.now();
96
+ if (cachedStartedAt) return cachedStartedAt;
97
+ const raw = localStorage.getItem(SESSION_STARTED_KEY);
98
+ cachedStartedAt = raw ? Number(raw) : Date.now();
99
+ return cachedStartedAt;
100
+ }
101
+ function getSessionDurationMs() {
102
+ return Date.now() - getSessionStartedAt();
103
+ }
104
+ function _resetSessionCache() {
105
+ cachedSessionId = null;
106
+ cachedLastActive = 0;
107
+ cachedStartedAt = 0;
108
+ lastTouchWrite = 0;
109
+ }
110
+
111
+ // src/network.ts
112
+ var DEFAULT_FLUSH_INTERVAL_MS = 2e3;
113
+ var DEFAULT_MAX_BATCH_SIZE = 100;
114
+ var DEFAULT_MAX_QUEUE_SIZE = 1e3;
115
+ var MAX_RETRIES = 3;
116
+ var MAX_PENDING_RETRIES = 3;
117
+ var RETRY_DELAYS_MS = [1e3, 2e3, 4e3];
118
+ var config = null;
119
+ var queue = [];
120
+ var flushTimer = null;
121
+ var pendingRetries = 0;
122
+ var debugMode = false;
123
+ var unloadHandlersAttached = false;
124
+ var droppedCount = 0;
125
+ var cachedUserAgent = null;
126
+ var needsSessionFill = false;
127
+ function log(...args) {
128
+ if (debugMode) console.log("[PishonIQ]", ...args);
129
+ }
130
+ function warn(...args) {
131
+ if (debugMode) console.warn("[PishonIQ]", ...args);
132
+ }
133
+ function setDebugMode(value) {
134
+ debugMode = value;
135
+ }
136
+ function isBrowser2() {
137
+ return typeof window !== "undefined";
138
+ }
139
+ function getMeta() {
140
+ if (!isBrowser2()) {
141
+ return { url: "", userAgent: "" };
142
+ }
143
+ if (cachedUserAgent === null) {
144
+ cachedUserAgent = navigator.userAgent;
145
+ }
146
+ return {
147
+ url: window.location.href,
148
+ userAgent: cachedUserAgent
149
+ };
150
+ }
151
+ function flushIntervalMs() {
152
+ return config?.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
153
+ }
154
+ function maxBatchSize() {
155
+ return config?.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE;
156
+ }
157
+ function maxQueueSize() {
158
+ return config?.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE;
159
+ }
160
+ function startFlushTimer() {
161
+ if (!isBrowser2() || flushTimer) return;
162
+ flushTimer = setInterval(() => {
163
+ void flush(false);
164
+ }, flushIntervalMs());
165
+ }
166
+ function stopFlushTimer() {
167
+ if (flushTimer) {
168
+ clearInterval(flushTimer);
169
+ flushTimer = null;
170
+ }
171
+ }
172
+ function onVisibilityChange() {
173
+ if (typeof document === "undefined") return;
174
+ if (document.visibilityState === "hidden") {
175
+ flush(true);
176
+ stopFlushTimer();
177
+ } else {
178
+ startFlushTimer();
179
+ }
180
+ }
181
+ function onBeforeUnload() {
182
+ flush(true);
183
+ }
184
+ function initNetwork(networkConfig) {
185
+ config = networkConfig;
186
+ if (!isBrowser2()) return;
187
+ stopFlushTimer();
188
+ startFlushTimer();
189
+ if (!unloadHandlersAttached) {
190
+ unloadHandlersAttached = true;
191
+ window.addEventListener("beforeunload", onBeforeUnload);
192
+ document.addEventListener("visibilitychange", onVisibilityChange);
193
+ }
194
+ log(`Network ready | endpoint: ${networkConfig.host}/api/events | flush every ${flushIntervalMs()}ms`);
195
+ }
196
+ function shutdownNetwork() {
197
+ stopFlushTimer();
198
+ if (isBrowser2() && unloadHandlersAttached) {
199
+ unloadHandlersAttached = false;
200
+ window.removeEventListener("beforeunload", onBeforeUnload);
201
+ document.removeEventListener("visibilitychange", onVisibilityChange);
202
+ }
203
+ config = null;
204
+ queue = [];
205
+ pendingRetries = 0;
206
+ droppedCount = 0;
207
+ needsSessionFill = false;
208
+ }
209
+ function enqueueEvent(event, properties) {
210
+ if (!config) {
211
+ warn("enqueueEvent called before init \u2014 event dropped:", event);
212
+ return;
213
+ }
214
+ const sampleRate = config.sampleRate ?? 1;
215
+ const isCritical = event === "identify" || event === "session_start" || event === "session_end";
216
+ if (!isCritical && sampleRate < 1 && Math.random() > sampleRate) return;
217
+ touchSession();
218
+ const payload = {
219
+ sessionId: getSessionId(),
220
+ userId: config.getUserId(),
221
+ event,
222
+ properties,
223
+ timestamp: Date.now(),
224
+ schemaVersion: 1,
225
+ ...getMeta()
226
+ };
227
+ queue.push(payload);
228
+ if (!payload.sessionId) needsSessionFill = true;
229
+ if (queue.length > maxQueueSize()) {
230
+ const overflow = queue.length - maxQueueSize();
231
+ queue.splice(0, overflow);
232
+ droppedCount += overflow;
233
+ if (debugMode) warn(`Queue full \u2014 dropped ${overflow} oldest event(s) (${droppedCount} total)`);
234
+ }
235
+ if (debugMode) log(`Event queued: "${event}" | queue size: ${queue.length}`, properties ?? "");
236
+ if (queue.length >= maxBatchSize()) {
237
+ if (debugMode) log(`Queue reached max batch size (${maxBatchSize()}) \u2014 flushing immediately`);
238
+ flush(false);
239
+ }
240
+ }
241
+ function setEnqueueSessionId(sessionId) {
242
+ if (!needsSessionFill) return;
243
+ for (const item of queue) {
244
+ if (!item.sessionId) {
245
+ item.sessionId = sessionId;
246
+ }
247
+ }
248
+ needsSessionFill = false;
249
+ }
250
+ function stampBatch(items, sessionId, userId2) {
251
+ const out = new Array(items.length);
252
+ for (let i = 0; i < items.length; i++) {
253
+ const e = items[i];
254
+ out[i] = {
255
+ ...e,
256
+ sessionId: e.sessionId || sessionId,
257
+ userId: e.userId ?? userId2
258
+ };
259
+ }
260
+ return out;
261
+ }
262
+ function getEndpoint() {
263
+ const host2 = (config?.host ?? "").replace(/\/$/, "");
264
+ return `${host2}/api/events`;
265
+ }
266
+ async function postBatch(events, useBeacon) {
267
+ if (!config || events.length === 0) return { ok: true, retryable: false };
268
+ const url = getEndpoint();
269
+ const body = { events };
270
+ try {
271
+ log(`Flushing ${events.length} event(s) \u2192 ${url}`);
272
+ const response = await fetch(url, {
273
+ method: "POST",
274
+ headers: {
275
+ "Content-Type": "application/json",
276
+ Authorization: `Bearer ${config.apiKey}`
277
+ },
278
+ body: JSON.stringify(body),
279
+ keepalive: useBeacon
280
+ });
281
+ if (response.ok) {
282
+ log(`\u2713 Sent ${events.length} event(s) successfully`);
283
+ return { ok: true, retryable: false, status: response.status };
284
+ }
285
+ warn(`\u2717 Server rejected events | HTTP ${response.status} | url: ${url}`);
286
+ if (response.status === 401) {
287
+ warn("\u2717 Invalid apiKey \u2014 events will not be retried. Check the apiKey passed to PishonIQ.init().");
288
+ return { ok: false, retryable: false, status: response.status };
289
+ }
290
+ if (response.status === 400) {
291
+ return { ok: false, retryable: false, status: response.status };
292
+ }
293
+ return { ok: false, retryable: true, status: response.status };
294
+ } catch (err) {
295
+ warn(`\u2717 Network error \u2014 backend unreachable at ${url}`, err instanceof Error ? err.message : err);
296
+ return { ok: false, retryable: true };
297
+ }
298
+ }
299
+ function scheduleRetry(events, attempt) {
300
+ if (attempt >= MAX_RETRIES) {
301
+ warn(`Gave up after ${MAX_RETRIES} retries \u2014 ${events.length} event(s) lost`);
302
+ return;
303
+ }
304
+ if (pendingRetries >= MAX_PENDING_RETRIES) {
305
+ warn(`Too many pending retries \u2014 dropping batch of ${events.length} event(s)`);
306
+ return;
307
+ }
308
+ const delay = RETRY_DELAYS_MS[attempt] ?? 4e3;
309
+ warn(`Retrying in ${delay}ms (attempt ${attempt + 1}/${MAX_RETRIES})`);
310
+ pendingRetries += 1;
311
+ setTimeout(() => {
312
+ pendingRetries -= 1;
313
+ void (async () => {
314
+ const result = await postBatch(events, false);
315
+ if (!result.ok && result.retryable) {
316
+ scheduleRetry(events, attempt + 1);
317
+ }
318
+ })();
319
+ }, delay);
320
+ }
321
+ function flush(useBeacon = false) {
322
+ if (!config || queue.length === 0) return;
323
+ const batch = queue;
324
+ queue = [];
325
+ const sessionId = batch[0]?.sessionId || (typeof window !== "undefined" ? localStorage.getItem(SESSION_ID_KEY) ?? "" : "");
326
+ if (debugMode) log(`Flushing ${batch.length} event(s) | sessionId: ${sessionId} | useBeacon: ${useBeacon}`);
327
+ const events = stampBatch(batch, sessionId, config?.getUserId());
328
+ void (async () => {
329
+ const result = await postBatch(events, useBeacon);
330
+ if (!result.ok && !useBeacon && result.retryable) {
331
+ scheduleRetry(events, 0);
332
+ }
333
+ })();
334
+ }
335
+
336
+ // src/tracker.ts
337
+ var SCROLL_MILESTONES = [25, 50, 75, 100];
338
+ var started = false;
339
+ var historyPatched = false;
340
+ var lastPageUrl = "";
341
+ var initialPageSent = false;
342
+ var reactRouterActive = false;
343
+ var sessionEndSent = false;
344
+ var captureConfig = {
345
+ clicks: true,
346
+ pageViews: true,
347
+ scrollDepth: true,
348
+ sessions: true
349
+ };
350
+ var reachedScrollDepths = /* @__PURE__ */ new Set();
351
+ function isBrowser3() {
352
+ return typeof window !== "undefined" && typeof document !== "undefined";
353
+ }
354
+ function getClickTarget(event) {
355
+ const target = event.target;
356
+ if (!(target instanceof Element)) return null;
357
+ return target.closest("[data-pishon], button, a, input[type='button'], input[type='submit']");
358
+ }
359
+ function getClickProperties(el) {
360
+ const text = (el.textContent ?? "").trim().slice(0, 200);
361
+ const props = {
362
+ tag: el.tagName,
363
+ text
364
+ };
365
+ if (el instanceof HTMLAnchorElement && el.href) {
366
+ props.href = el.href;
367
+ }
368
+ const dataPishon = el.getAttribute("data-pishon");
369
+ if (dataPishon) {
370
+ props.pishon = dataPishon;
371
+ }
372
+ return props;
373
+ }
374
+ function emitPageView(pageName, source = "auto") {
375
+ if (!isBrowser3() || !captureConfig.pageViews) return;
376
+ const url = window.location.href;
377
+ if (url === lastPageUrl && initialPageSent) {
378
+ return;
379
+ }
380
+ lastPageUrl = url;
381
+ initialPageSent = true;
382
+ reachedScrollDepths.clear();
383
+ enqueueEvent("page_view", {
384
+ pageName: pageName ?? document.title,
385
+ pathname: window.location.pathname,
386
+ search: window.location.search,
387
+ referrer: document.referrer || void 0,
388
+ source
389
+ });
390
+ }
391
+ function onHistoryChange() {
392
+ if (reactRouterActive) return;
393
+ emitPageView(void 0, "history");
394
+ }
395
+ function patchHistory() {
396
+ if (!isBrowser3() || historyPatched) return;
397
+ historyPatched = true;
398
+ const originalPushState = history.pushState.bind(history);
399
+ const originalReplaceState = history.replaceState.bind(history);
400
+ history.pushState = function(...args) {
401
+ originalPushState(...args);
402
+ onHistoryChange();
403
+ };
404
+ history.replaceState = function(...args) {
405
+ originalReplaceState(...args);
406
+ onHistoryChange();
407
+ };
408
+ window.addEventListener("popstate", onHistoryChange);
409
+ }
410
+ function onClick(event) {
411
+ if (!captureConfig.clicks) return;
412
+ const el = getClickTarget(event);
413
+ if (!el) return;
414
+ enqueueEvent("click", getClickProperties(el));
415
+ }
416
+ function getScrollPercent() {
417
+ const doc = document.documentElement;
418
+ const scrollTop = window.scrollY || doc.scrollTop;
419
+ const scrollHeight = doc.scrollHeight - doc.clientHeight;
420
+ if (scrollHeight <= 0) return 100;
421
+ return Math.min(100, Math.round(scrollTop / scrollHeight * 100));
422
+ }
423
+ var scrollScheduled = false;
424
+ function onScroll() {
425
+ if (!captureConfig.scrollDepth || scrollScheduled) return;
426
+ scrollScheduled = true;
427
+ requestAnimationFrame(() => {
428
+ scrollScheduled = false;
429
+ const percent = getScrollPercent();
430
+ for (const milestone of SCROLL_MILESTONES) {
431
+ if (percent >= milestone && !reachedScrollDepths.has(milestone)) {
432
+ reachedScrollDepths.add(milestone);
433
+ enqueueEvent("scroll_depth", { depth: milestone, percent });
434
+ }
435
+ }
436
+ });
437
+ }
438
+ function onSessionEnd() {
439
+ if (!captureConfig.sessions || sessionEndSent) return;
440
+ sessionEndSent = true;
441
+ enqueueEvent("session_end", { durationMs: getSessionDurationMs() });
442
+ flush(true);
443
+ }
444
+ function setReactRouterActive(active) {
445
+ reactRouterActive = active;
446
+ }
447
+ function startAutoCapture(options) {
448
+ if (!isBrowser3() || started) return;
449
+ if (options) {
450
+ captureConfig = {
451
+ clicks: options.clicks ?? true,
452
+ pageViews: options.pageViews ?? true,
453
+ scrollDepth: options.scrollDepth ?? true,
454
+ sessions: options.sessions ?? true
455
+ };
456
+ }
457
+ started = true;
458
+ sessionEndSent = false;
459
+ const { isNew } = ensureSession();
460
+ if (isNew && captureConfig.sessions) {
461
+ enqueueEvent("session_start", {
462
+ referrer: document.referrer || void 0
463
+ });
464
+ }
465
+ patchHistory();
466
+ emitPageView(void 0, "initial");
467
+ if (captureConfig.clicks) {
468
+ document.addEventListener("click", onClick, true);
469
+ }
470
+ if (captureConfig.scrollDepth) {
471
+ window.addEventListener("scroll", onScroll, { passive: true });
472
+ }
473
+ if (captureConfig.sessions) {
474
+ window.addEventListener("beforeunload", onSessionEnd);
475
+ window.addEventListener("pagehide", onSessionEnd);
476
+ }
477
+ }
478
+ function stopAutoCapture() {
479
+ if (!isBrowser3() || !started) return;
480
+ started = false;
481
+ sessionEndSent = false;
482
+ document.removeEventListener("click", onClick, true);
483
+ window.removeEventListener("scroll", onScroll);
484
+ window.removeEventListener("beforeunload", onSessionEnd);
485
+ window.removeEventListener("pagehide", onSessionEnd);
486
+ }
487
+ function trackPage(pageName) {
488
+ emitPageView(pageName, "manual");
489
+ }
490
+ function refreshSessionAfterIdentify() {
491
+ touchSession();
492
+ }
493
+
494
+ // src/index.ts
495
+ var USER_ID_KEY = "pishoniq_user_id";
496
+ var USER_TRAITS_KEY = "pishoniq_user_traits";
497
+ var LOCALHOST_RE = /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?\/?$/i;
498
+ var initialized = false;
499
+ var apiKey = "";
500
+ var host = "";
501
+ var userId;
502
+ var userTraits;
503
+ function isBrowser4() {
504
+ return typeof window !== "undefined";
505
+ }
506
+ function loadPersistedUser() {
507
+ if (!isBrowser4()) return;
508
+ userId = localStorage.getItem(USER_ID_KEY) ?? void 0;
509
+ const traitsRaw = localStorage.getItem(USER_TRAITS_KEY);
510
+ if (traitsRaw) {
511
+ try {
512
+ userTraits = JSON.parse(traitsRaw);
513
+ } catch {
514
+ userTraits = void 0;
515
+ }
516
+ }
517
+ }
518
+ function persistUser(id, traits) {
519
+ if (!isBrowser4()) return;
520
+ localStorage.setItem(USER_ID_KEY, id);
521
+ if (traits) {
522
+ localStorage.setItem(USER_TRAITS_KEY, JSON.stringify(traits));
523
+ }
524
+ }
525
+ function assertInitialized() {
526
+ if (!initialized) {
527
+ throw new Error("[PishonIQ] Call PishonIQ.init() before using the SDK");
528
+ }
529
+ }
530
+ var PishonIQ = class {
531
+ static isInitialized() {
532
+ return initialized;
533
+ }
534
+ static init(options) {
535
+ if (!options.apiKey) {
536
+ throw new Error("[PishonIQ] apiKey is required");
537
+ }
538
+ if (!options.host) {
539
+ throw new Error("[PishonIQ] host is required \u2014 pass the URL of your PishonIQ backend");
540
+ }
541
+ const sampleRate = options.sampleRate ?? 1;
542
+ if (!(sampleRate >= 0 && sampleRate <= 1)) {
543
+ throw new Error("[PishonIQ] sampleRate must be between 0 and 1");
544
+ }
545
+ if (initialized) {
546
+ console.warn("[PishonIQ] init() called more than once; ignoring");
547
+ return;
548
+ }
549
+ if (LOCALHOST_RE.test(options.host)) {
550
+ console.warn(
551
+ `[PishonIQ] host "${options.host}" looks like a local address \u2014 make sure to pass your production backend URL in deployed environments`
552
+ );
553
+ }
554
+ apiKey = options.apiKey;
555
+ host = options.host.replace(/\/$/, "");
556
+ initialized = true;
557
+ setDebugMode(options.debug ?? false);
558
+ if (options.debug) {
559
+ const masked = `${apiKey.slice(0, 6)}...${apiKey.slice(-4)}`;
560
+ console.log(`[PishonIQ] Initialized | apiKey: ${masked} | host: ${host} | debug: true`);
561
+ }
562
+ loadPersistedUser();
563
+ const { sessionId } = ensureSession();
564
+ initNetwork({
565
+ apiKey,
566
+ host,
567
+ getUserId: () => userId,
568
+ flushIntervalMs: options.flushIntervalMs,
569
+ maxBatchSize: options.maxBatchSize,
570
+ maxQueueSize: options.maxQueueSize,
571
+ sampleRate
572
+ });
573
+ setEnqueueSessionId(sessionId);
574
+ if (isBrowser4()) {
575
+ startAutoCapture(options.autoCapture);
576
+ }
577
+ }
578
+ static track(event, properties) {
579
+ assertInitialized();
580
+ if (!isBrowser4()) return;
581
+ touchSession();
582
+ setEnqueueSessionId(getSessionId());
583
+ enqueueEvent(event, properties);
584
+ }
585
+ static identify(id, traits) {
586
+ assertInitialized();
587
+ if (!isBrowser4()) return;
588
+ userId = id;
589
+ userTraits = traits;
590
+ persistUser(id, traits);
591
+ refreshSessionAfterIdentify();
592
+ touchSession();
593
+ setEnqueueSessionId(getSessionId());
594
+ enqueueEvent("identify", {
595
+ userId: id,
596
+ traits: traits ?? userTraits
597
+ });
598
+ }
599
+ static page(pageName) {
600
+ assertInitialized();
601
+ if (!isBrowser4()) return;
602
+ touchSession();
603
+ setEnqueueSessionId(getSessionId());
604
+ trackPage(pageName);
605
+ }
606
+ /** @internal Used by React integration to avoid duplicate page_view events */
607
+ static _setReactRouterActive(active) {
608
+ setReactRouterActive(active);
609
+ }
610
+ /** @internal Reset SDK state (testing only) */
611
+ static _reset() {
612
+ initialized = false;
613
+ apiKey = "";
614
+ host = "";
615
+ userId = void 0;
616
+ userTraits = void 0;
617
+ stopAutoCapture();
618
+ shutdownNetwork();
619
+ _resetSessionCache();
620
+ }
621
+ };
622
+ var index_default = PishonIQ;
623
+
624
+ exports.PishonIQ = PishonIQ;
625
+ exports.index_default = index_default;