@levo-so/insights 0.1.78 → 0.1.80

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,583 @@
1
+ import { getLevoError as V } from "@levo-so/core";
2
+ import { map as B, computed as K, atom as b } from "nanostores";
3
+ import { onUserActivity as fe } from "@analytics/activity-utils";
4
+ import { debounce as G } from "lodash-es";
5
+ const T = B({
6
+ workspace: null,
7
+ page_id: null,
8
+ site_id: null,
9
+ debug: !1
10
+ }), U = () => T.get(), Ve = (e) => T.set({ ...U(), ...e }), Qe = (e, t) => T.setKey(e, t), ge = ({
11
+ deviceToken: e,
12
+ sessionToken: t,
13
+ mode: n
14
+ }) => {
15
+ const i = {};
16
+ return n === "direct" && (e && (i["Levo-Audience-Device"] = e), t && (i["Levo-Audience-Session"] = t)), i;
17
+ }, y = {
18
+ /** Legacy: Lock key for identify operation (no longer used internally) */
19
+ identify: "lock:lv_aud_identify",
20
+ /** Key for tracking open tab count */
21
+ open_tabs: "lv_insights_ot",
22
+ /** Key for current tab ID (sessionStorage) */
23
+ current_tab: "lv_insights_ct",
24
+ /** Key for all tabs registry */
25
+ all_tabs: "lv_insights_at",
26
+ /** Device JWT for direct mode (1yr expiry, rotated on /welcome, analytics-only scope) */
27
+ device_token: "lv_aud_device",
28
+ /** Session JWT for direct mode (1yr expiry, rotated on /welcome, analytics-only scope) */
29
+ session_token: "lv_aud_session",
30
+ /** Cached insights mode ('proxy' | 'direct') */
31
+ mode: "lv_aud_mode",
32
+ /** Key to store session data **/
33
+ session: "lv_insights_session"
34
+ }, pe = () => {
35
+ if (typeof window > "u" || !("localStorage" in window))
36
+ return !1;
37
+ try {
38
+ const e = "__levo_test__";
39
+ return window.localStorage.setItem(e, "test"), window.localStorage.removeItem(e), !0;
40
+ } catch {
41
+ return !1;
42
+ }
43
+ }, M = {
44
+ isIdentified: !1,
45
+ isIdentifying: !1,
46
+ sessionId: null,
47
+ deviceId: null,
48
+ deviceToken: null,
49
+ sessionToken: null,
50
+ allTabs: [],
51
+ mode: "proxy",
52
+ insightsBaseUrl: null,
53
+ identity: null
54
+ }, he = JSON.stringify, Q = (e) => {
55
+ if (!e) return M;
56
+ try {
57
+ return JSON.parse(e);
58
+ } catch {
59
+ return M;
60
+ }
61
+ }, p = b(M), v = p.set;
62
+ let L = !1;
63
+ const O = [], k = () => {
64
+ L || (L = !0, O.forEach((e) => {
65
+ e();
66
+ }), O.length = 0);
67
+ }, We = (e) => {
68
+ L ? e() : O.push(e);
69
+ };
70
+ if (pe()) {
71
+ const e = localStorage.getItem(y.session);
72
+ e && v(Q(e)), k(), p.set = (t) => {
73
+ v(t);
74
+ try {
75
+ localStorage.setItem(y.session, he(t));
76
+ } catch {
77
+ }
78
+ }, window.addEventListener("storage", (t) => {
79
+ t.key === y.session && v(Q(t.newValue));
80
+ });
81
+ } else if (typeof BroadcastChannel < "u") {
82
+ const e = new BroadcastChannel(y.session);
83
+ e.onmessage = (t) => {
84
+ const { type: n, value: i } = t.data;
85
+ n === "UPDATE" && i ? v(i) : n === "QUERY" ? L && e.postMessage({ type: "RESPONSE", value: p.get() }) : n === "RESPONSE" && i && (v(i), k());
86
+ }, p.set = (t) => {
87
+ v(t), e.postMessage({ type: "UPDATE", value: t });
88
+ }, e.postMessage({ type: "QUERY" }), setTimeout(() => {
89
+ k();
90
+ }, 150);
91
+ } else
92
+ k();
93
+ const H = () => p.get(), W = (e) => {
94
+ p.set({ ...H(), ...e });
95
+ }, Je = K(
96
+ p,
97
+ (e) => e.insightsBaseUrl !== null && e.identity !== null
98
+ ), me = 10, be = 2e3, J = 500, m = b([]), N = b(0), ve = K(m, (e) => e.length ?? 0), S = b(null), Ke = () => {
99
+ let e = !1;
100
+ return p.subscribe((t) => {
101
+ if (t.isIdentified && !e) {
102
+ e = !0;
103
+ const n = m.get();
104
+ n.length > 0 && x(n);
105
+ }
106
+ });
107
+ }, I = () => m.get(), ye = () => ve.get(), x = (e) => {
108
+ const { workspace: t, debug: n, site_id: i, page_id: o } = U(), { isIdentified: r, mode: c, sessionId: u, deviceId: a, sessionToken: s, deviceToken: d, insightsBaseUrl: f } = H();
109
+ if (e.length === 0 || !r || !f || !t)
110
+ return;
111
+ const h = e.map(
112
+ (g) => ({
113
+ // Default values from stores
114
+ workspace_id: t,
115
+ site_id: i ?? void 0,
116
+ session_id: u ?? void 0,
117
+ device_id: a ?? void 0,
118
+ identifier: o ?? void 0,
119
+ hostname: window.location.hostname,
120
+ pathname: window.location.pathname,
121
+ page_title: document.title,
122
+ url: window.location.href,
123
+ tab_id: "",
124
+ tab_count: 0,
125
+ // Event values override defaults (includes tab_id, tab_count captured at track time)
126
+ ...g,
127
+ // Ensure required fields have values
128
+ event: g.event,
129
+ created_at: g.created_at,
130
+ resource: g.resource ?? "page",
131
+ properties: g.properties ?? {}
132
+ })
133
+ );
134
+ if (m.set([]), n) {
135
+ console.log("[@levo-so/insights] Debug mode enabled. Events batch:", h);
136
+ return;
137
+ }
138
+ const C = `${f}/v1/insights/event/bulk?workspace=${t}`, R = {
139
+ "Content-Type": "application/json",
140
+ ...ge({ deviceToken: d, sessionToken: s, mode: c })
141
+ };
142
+ c === "proxy" && navigator.sendBeacon && navigator.sendBeacon(C, JSON.stringify(h)) || fetch(C, {
143
+ method: "POST",
144
+ body: JSON.stringify(h),
145
+ headers: R,
146
+ keepalive: !0,
147
+ credentials: c === "proxy" ? "include" : "omit"
148
+ }).catch(() => {
149
+ });
150
+ }, we = () => {
151
+ if (S.get()) return;
152
+ const e = setTimeout(() => {
153
+ x(I()), S.set(null);
154
+ }, be);
155
+ S.set(e);
156
+ }, X = () => {
157
+ const e = S.get();
158
+ e && (clearTimeout(e), S.set(null));
159
+ }, Ge = (e) => {
160
+ const { debug: t } = U(), n = N.get();
161
+ if (n >= J) {
162
+ t && console.warn(`[@levo-so/core] Event limit (${J}) reached for this page`);
163
+ return;
164
+ }
165
+ N.set(n + 1);
166
+ const i = m.get();
167
+ m.set([...i, e]);
168
+ const { isIdentified: o } = H();
169
+ ye() >= me ? (X(), x(I())) : o && we();
170
+ }, Xe = () => N.set(0), Ze = () => {
171
+ m.set([]), N.set(0), X();
172
+ }, _ = B({
173
+ status: "active",
174
+ seconds: 0
175
+ }), et = (e) => {
176
+ if (typeof window > "u") return () => {
177
+ };
178
+ const i = fe({
179
+ timeout: 6e4,
180
+ throttle: 1e3,
181
+ onIdle: (r) => {
182
+ _.set({ status: "idle", seconds: r });
183
+ },
184
+ onWakeUp: (r) => {
185
+ _.set({ status: "active", seconds: r });
186
+ }
187
+ }), o = _.listen((r) => {
188
+ r.seconds > 0 && (r.status === "idle" ? e.track("user.idle", {
189
+ seconds_active: r.seconds
190
+ }) : e.track("user.active", {
191
+ seconds_idle: r.seconds
192
+ }));
193
+ });
194
+ return () => {
195
+ o(), i.disable(), _.set({ status: "active", seconds: 0 });
196
+ };
197
+ }, Ee = () => _.get(), E = b(
198
+ "active"
199
+ /* ACTIVE */
200
+ ), _e = () => typeof document > "u" ? "active" : document.visibilityState === "hidden" ? "hidden" : document.hasFocus() ? "active" : "passive", tt = (e) => {
201
+ if (typeof window > "u") return () => {
202
+ };
203
+ let t = !1;
204
+ const n = (s) => {
205
+ if (t) return;
206
+ t = !0;
207
+ const d = Ee(), f = {};
208
+ d.seconds > 0 && (d.status === "idle" ? f.seconds_idle = d.seconds : f.seconds_active = d.seconds);
209
+ try {
210
+ e.track("page.bounce", {
211
+ resource: "page",
212
+ ...f,
213
+ ...s
214
+ }), x(I());
215
+ } catch (h) {
216
+ console.error("[insights] Failed to send bounce event", V(h));
217
+ }
218
+ }, i = () => {
219
+ const s = performance.getEntriesByType("navigation")?.[0];
220
+ let d = s?.type === "navigate";
221
+ if (!d)
222
+ try {
223
+ const f = document.activeElement;
224
+ f?.tagName === "A" && f.href && new URL(f.href).origin !== window.location.origin && (d = !0);
225
+ } catch (f) {
226
+ console.warn("[insights] Failed to parse link destination", V(f));
227
+ }
228
+ n({
229
+ is_navigating_away: d,
230
+ navigation_type: s?.type,
231
+ trigger: "beforeunload"
232
+ });
233
+ }, o = (s) => {
234
+ switch (s.type) {
235
+ case "pageshow":
236
+ case "resume":
237
+ case "blur":
238
+ case "focus":
239
+ case "visibilitychange":
240
+ E.set(_e());
241
+ break;
242
+ case "freeze":
243
+ E.set(
244
+ "frozen"
245
+ /* FROZEN */
246
+ );
247
+ break;
248
+ case "pagehide":
249
+ E.set(
250
+ s.persisted ? "frozen" : "terminated"
251
+ /* TERMINATED */
252
+ );
253
+ break;
254
+ }
255
+ }, r = ["pageshow", "pagehide", "focus", "blur", "visibilitychange", "resume", "freeze"];
256
+ r.forEach((s) => {
257
+ window.addEventListener(s, o, { capture: !0 });
258
+ }), window.addEventListener("beforeunload", i);
259
+ const c = E.listen((s) => {
260
+ s === "frozen" || s === "terminated" ? n({
261
+ state: s,
262
+ trigger: "lifecycle"
263
+ }) : s === "hidden" && x(I());
264
+ });
265
+ let u = T.get().page_id;
266
+ const a = T.listen((s) => {
267
+ s.page_id !== u && (t = !1, u = s.page_id);
268
+ });
269
+ return () => {
270
+ r.forEach((s) => {
271
+ window.removeEventListener(s, o, { capture: !0 });
272
+ }), window.removeEventListener("beforeunload", i), c(), a(), t = !1, E.set(
273
+ "active"
274
+ /* ACTIVE */
275
+ );
276
+ };
277
+ }, A = (e) => Object.prototype.toString.call(e) == "[object String]", Se = (e, t) => e.indexOf(t) !== -1, w = (e) => e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ""), Z = (e) => e === void 0, Te = (e) => e === null, ee = (e) => Z(e) || Te(e), te = (e) => !!e && e?.nodeType === 3;
278
+ function xe(e) {
279
+ return !!e && e?.nodeType === 1;
280
+ }
281
+ function Ce(e, t) {
282
+ return !!e && !!e?.tagName && e?.tagName.toLowerCase() === t.toLowerCase();
283
+ }
284
+ function ke(e) {
285
+ return e ? w(e).split(/\s+/) : [];
286
+ }
287
+ function Le(e) {
288
+ let t = "";
289
+ switch (typeof e?.className) {
290
+ case "string":
291
+ t = e?.className;
292
+ break;
293
+ // TODO: when is this ever used?
294
+ case "object":
295
+ t = (e?.className && "baseVal" in e.className ? (e?.className).baseVal : null) || e?.getAttribute("class") || "";
296
+ break;
297
+ default:
298
+ t = "";
299
+ }
300
+ return ke(t);
301
+ }
302
+ const l = (e, t = 255) => ee(e) ? "" : w(e).split(/(\s+)/).filter((n) => Y(n)).join("").replace(/[\r\n]/g, " ").replace(/[ ]+/g, " ").substring(0, t), ne = ["span", "strong", "em", "i", "b", "mark", "code", "small", "sub", "sup", "label"], F = (e) => {
303
+ let t = "";
304
+ if (Re(e) && e?.childNodes && e?.childNodes.length) {
305
+ for (const n of e.childNodes)
306
+ te(n) && n.textContent && (t += l(n.textContent) ?? "");
307
+ if (!w(t)) {
308
+ const n = e.querySelectorAll(ne.join(", "));
309
+ for (const i of n) {
310
+ const o = i.textContent;
311
+ o && (t += `${l(o)} `);
312
+ }
313
+ }
314
+ if (!w(t) && e instanceof HTMLElement) {
315
+ const n = e.innerText;
316
+ n && (t = l(n.substring(0, 500)));
317
+ }
318
+ }
319
+ return w(t);
320
+ }, Ne = (e) => Z(e.target) ? e?.srcElement || null : e?.target?.shadowRoot ? e?.composedPath()?.[0] || null : e?.target || null, Ie = (e, t) => {
321
+ if (!window || !e || Ce(e, "html") || !xe(e))
322
+ return !1;
323
+ const n = window.getComputedStyle(e);
324
+ if (n && n.getPropertyValue("cursor") === "pointer" && t.type === "click")
325
+ return !0;
326
+ switch (e?.tagName.toLowerCase()) {
327
+ case "html":
328
+ return !1;
329
+ case "form":
330
+ return t.type === "submit";
331
+ case "input":
332
+ case "select":
333
+ case "textarea":
334
+ return ["change", "click"].includes(t.type);
335
+ default:
336
+ return t.type === "click";
337
+ }
338
+ }, Ae = /* @__PURE__ */ new Set([
339
+ "password",
340
+ "passwd",
341
+ "pwd",
342
+ "creditcard",
343
+ "cardnumber",
344
+ "ccnum",
345
+ "ccnumber",
346
+ "cvv",
347
+ "cvc",
348
+ "csc",
349
+ "securitycode",
350
+ "ssn",
351
+ "socialsecurity",
352
+ "routingnumber",
353
+ "accountnumber",
354
+ "bankaccount",
355
+ "secretkey",
356
+ "apikey",
357
+ "accesstoken"
358
+ ]);
359
+ function Re(e) {
360
+ if (Se(Le(e), "ph-include"))
361
+ return !0;
362
+ const t = e.type || "";
363
+ if (A(t))
364
+ switch (t.toLowerCase()) {
365
+ case "hidden":
366
+ return !1;
367
+ case "password":
368
+ return !1;
369
+ }
370
+ const n = e.name || e?.id || "";
371
+ if (A(n)) {
372
+ const i = n.toLowerCase().replace(/[^a-z]/g, "");
373
+ if (Ae.has(i))
374
+ return !1;
375
+ }
376
+ return !0;
377
+ }
378
+ const se = "(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11})", $e = new RegExp(`^(?:${se})$`), De = new RegExp(se), ie = "\\d{3}-?\\d{2}-?\\d{4}", Me = new RegExp(`^(${ie})$`), Oe = new RegExp(`(${ie})`), Y = (e, t = !0) => !(ee(e) || A(e) && (e = w(e), (t ? $e : De).test((e || "").replace(/[- ]/g, "")) || (t ? Me : Oe).test(e))), Pe = (e) => A(e) ? e.substring(0, 10) === "_ngcontent" || e.substring(0, 7) === "_nghost" : !1, Be = (e) => {
379
+ let t = F(e);
380
+ return t = `${t} ${oe(e)}`.trim(), Y(t) ? t : "";
381
+ };
382
+ function oe(e) {
383
+ let t = "";
384
+ if (e?.childNodes.length)
385
+ for (const n of e.childNodes) {
386
+ const i = n.tagName?.toLowerCase();
387
+ if (n && i && ne.includes(i))
388
+ try {
389
+ const o = F(n);
390
+ t = `${t} ${o}`.trim(), n?.childNodes.length && (t = `${t} ${oe(n)}`.trim());
391
+ } catch {
392
+ }
393
+ }
394
+ return t;
395
+ }
396
+ const Ue = (e) => {
397
+ const t = e.tagName?.toLowerCase(), n = t === "a" || t === "button" ? Be(e) : F(e);
398
+ if (n) return { text: n, source: "text" };
399
+ const i = e.getAttribute("aria-label");
400
+ if (i) return { text: l(i), source: "aria-label" };
401
+ const o = e.getAttribute("title");
402
+ if (o) return { text: l(o), source: "title" };
403
+ const r = e.getAttribute("data-track-label");
404
+ if (r) return { text: l(r), source: "data-track-label" };
405
+ const c = e.querySelector("img[alt], svg[aria-label]");
406
+ if (c) {
407
+ const a = c.getAttribute("alt") || c.getAttribute("aria-label");
408
+ if (a) return { text: l(a), source: "alt" };
409
+ }
410
+ const u = e.getAttribute("placeholder");
411
+ if (u) return { text: l(u), source: "placeholder" };
412
+ if (e instanceof HTMLElement && e.innerText) {
413
+ const a = e.innerText.substring(0, 500);
414
+ if (a.trim())
415
+ return { text: l(a), source: "innerText" };
416
+ }
417
+ return { text: "", source: "none" };
418
+ }, He = ["input", "textarea", "select"], Fe = (e) => {
419
+ const t = e?.tagName?.toLowerCase(), n = {
420
+ element: t
421
+ }, i = Ue(e);
422
+ n.text = i.text, n.text_source = i.source;
423
+ const o = e.getAttribute("aria-label");
424
+ o && (n.aria_label = l(o));
425
+ const r = e.getAttribute("role");
426
+ r && (n.role = r);
427
+ const c = {};
428
+ for (const a of e.attributes)
429
+ (a.name.startsWith("data-track-") || a.name.startsWith("data-analytics-")) && (c[a.name] = l(a.value));
430
+ Object.keys(c).length && (n.tracking_data = c);
431
+ const u = Array.from(e.attributes).reduce(
432
+ (a, s) => {
433
+ if (Y(s.value) && !Pe(s.name)) {
434
+ if (s.name === "class" || s.name.startsWith("data-track-") || s.name.startsWith("data-analytics-"))
435
+ return a;
436
+ a[s.name] = typeof s?.value == "string" ? l(s.value) : s.value;
437
+ }
438
+ return a;
439
+ },
440
+ {}
441
+ );
442
+ if (n.attributes = u, He.includes(t) || e?.getAttribute("contenteditable") === "true") {
443
+ let a;
444
+ e.matches('input[type="checkbox"], input[type="radio"]') ? a = e.checked : e.matches("input, select, textarea") && !e.matches('input[type="password"]') && (a = e.value), a !== void 0 && (n.value = typeof a == "string" || a === null ? l(a, 1024) : a);
445
+ let s = "";
446
+ n?.attributes.id && (s = l(
447
+ document.querySelector(`label[for="${n?.attributes.id}"]`)?.textContent?.trim() || ""
448
+ ));
449
+ const d = e.closest("label");
450
+ s || (s = l(d?.textContent?.trim() || "")), s && (n.label = s);
451
+ }
452
+ return n;
453
+ }, nt = (e, t) => {
454
+ let n = Ne(e);
455
+ te(n) && (n = n.parentNode || null);
456
+ const i = ["copy", "cut"].includes(t);
457
+ if (n && (i || Ie(n, e))) {
458
+ const o = Fe(n);
459
+ if (i) {
460
+ const r = l(window?.getSelection()?.toString()), c = e?.type || "clipboard";
461
+ o.copy_text = r ?? "", o.copy_type = c;
462
+ }
463
+ return o;
464
+ }
465
+ return null;
466
+ }, P = b(null), st = (e) => {
467
+ if (typeof window > "u") return () => {
468
+ };
469
+ let t = sessionStorage.getItem(y.current_tab);
470
+ const { allTabs: n } = p.get();
471
+ t && n.includes(t) && (t = null), t || (t = `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`, sessionStorage.setItem(y.current_tab, t));
472
+ const i = t;
473
+ P.set(i), n.includes(i) || W({ allTabs: [...n, i] });
474
+ const o = () => {
475
+ if (!i) return;
476
+ const { allTabs: r } = p.get();
477
+ if (r.includes(i)) {
478
+ const c = r.filter((u) => u !== i);
479
+ W({ allTabs: c });
480
+ }
481
+ };
482
+ return window.addEventListener("beforeunload", o), () => {
483
+ window.removeEventListener("beforeunload", o), o(), P.set(null);
484
+ };
485
+ }, it = () => P.get(), $ = B({
486
+ depth: 0,
487
+ speedCategory: "read",
488
+ direction: "down"
489
+ }), ot = (e) => {
490
+ if (typeof window > "u") return () => {
491
+ };
492
+ let t = {
493
+ prevMilestone: -1,
494
+ // Use -1 to ensure first milestone (even 0) is tracked
495
+ prevScrollY: 0,
496
+ prevTime: Date.now()
497
+ };
498
+ const n = 5, i = 300, o = 250, r = () => {
499
+ const s = window.scrollY, d = document.documentElement.scrollHeight, f = window.innerHeight, h = d - f;
500
+ if (h <= 0) return;
501
+ const C = Math.round(s / h * 100), R = Math.max(0, Math.min(100, C)), g = Math.floor(R / n) * n, { prevMilestone: j, prevScrollY: re, prevTime: ae } = t;
502
+ if (g === j) return;
503
+ const q = Date.now(), z = (q - ae) / 1e3, ce = Math.abs(s - re), le = z > 0 ? ce / z : 0, ue = g > j ? "down" : "up", de = le > i ? "scan" : "read";
504
+ $.set({
505
+ depth: g,
506
+ speedCategory: de,
507
+ direction: ue
508
+ }), t = {
509
+ prevMilestone: g,
510
+ prevScrollY: s,
511
+ prevTime: q
512
+ };
513
+ }, c = G(r, o);
514
+ window.addEventListener("scroll", c);
515
+ let u = 0;
516
+ const a = $.listen((s) => {
517
+ s.depth !== u && (u = s.depth, e.track("page.scroll", {
518
+ depth: s.depth,
519
+ speed_category: s.speedCategory,
520
+ direction: s.direction
521
+ }));
522
+ });
523
+ return typeof window.requestIdleCallback == "function" ? window.requestIdleCallback(() => r()) : setTimeout(r, 0), () => {
524
+ window.removeEventListener("scroll", c), c.cancel(), a(), $.set({
525
+ depth: 0,
526
+ speedCategory: "read",
527
+ direction: "down"
528
+ });
529
+ };
530
+ }, D = b(null), rt = (e) => {
531
+ if (typeof window > "u") return () => {
532
+ };
533
+ const n = G(() => {
534
+ const o = window.getSelection();
535
+ if (o && o.rangeCount > 0) {
536
+ const r = o.toString().trim();
537
+ r && D.set(r);
538
+ }
539
+ }, 1e3);
540
+ document.addEventListener("selectionchange", n);
541
+ const i = D.listen((o) => {
542
+ o && e.track("page.selection", {
543
+ text: l(o)
544
+ });
545
+ });
546
+ return () => {
547
+ document.removeEventListener("selectionchange", n), n.cancel(), i(), D.set(null);
548
+ };
549
+ };
550
+ export {
551
+ T as $,
552
+ et as A,
553
+ tt as B,
554
+ st as C,
555
+ ot as D,
556
+ rt as E,
557
+ m as a,
558
+ N as b,
559
+ ve as c,
560
+ Je as d,
561
+ p as e,
562
+ _ as f,
563
+ E as g,
564
+ P as h,
565
+ $ as i,
566
+ D as j,
567
+ Fe as k,
568
+ nt as l,
569
+ U as m,
570
+ H as n,
571
+ it as o,
572
+ ge as p,
573
+ Ge as q,
574
+ Xe as r,
575
+ Ve as s,
576
+ Qe as t,
577
+ W as u,
578
+ We as v,
579
+ x as w,
580
+ I as x,
581
+ Ze as y,
582
+ Ke as z
583
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@levo-so/insights",
3
- "version": "0.1.78",
3
+ "version": "0.1.80",
4
4
  "author": "Levo Engineering <devs@theinternetfolks.com>",
5
5
  "description": "Levo analytics",
6
6
  "type": "module",
@@ -21,7 +21,7 @@
21
21
  "nanostores": "0.11.4"
22
22
  },
23
23
  "peerDependencies": {
24
- "@levo-so/core": "0.1.78"
24
+ "@levo-so/core": "0.1.80"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@playwright/test": "1.58.2",
@@ -1,21 +0,0 @@
1
- const s = {
2
- /** Legacy: Lock key for identify operation (no longer used internally) */
3
- identify: "lock:lv_aud_identify",
4
- /** Key for tracking open tab count */
5
- open_tabs: "lv_insights_ot",
6
- /** Key for current tab ID (sessionStorage) */
7
- current_tab: "lv_insights_ct",
8
- /** Key for all tabs registry */
9
- all_tabs: "lv_insights_at",
10
- /** Device JWT for direct mode (1yr expiry, rotated on /welcome, analytics-only scope) */
11
- device_token: "lv_aud_device",
12
- /** Session JWT for direct mode (1yr expiry, rotated on /welcome, analytics-only scope) */
13
- session_token: "lv_aud_session",
14
- /** Cached insights mode ('proxy' | 'direct') */
15
- mode: "lv_aud_mode",
16
- /** Key to store session data **/
17
- session: "lv_insights_session"
18
- };
19
- export {
20
- s as STORAGE_KEYS
21
- };