@levo-so/insights 0.1.109 → 0.1.111
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/constants/storageKeys.d.ts +10 -3
- package/dist/index.js +197 -157
- package/dist/stores/session.d.ts +0 -1
- package/dist/stores.js +2 -2
- package/dist/{textSelection-eSp_MmZH.js → textSelection-D9P2LBjT.js} +151 -120
- package/dist/tracking/currentTab.d.ts +3 -2
- package/dist/utils/getReferrer.d.ts +17 -11
- package/package.json +4 -4
|
@@ -5,12 +5,10 @@
|
|
|
5
5
|
export declare const STORAGE_KEYS: {
|
|
6
6
|
/** Legacy: Lock key for identify operation (no longer used internally) */
|
|
7
7
|
readonly identify: "lock:lv_aud_identify";
|
|
8
|
-
/**
|
|
8
|
+
/** Namespace prefix for per-tab heartbeat keys (`${open_tabs}:${tabId}`) — see tracking/currentTab.ts */
|
|
9
9
|
readonly open_tabs: "lv_insights_ot";
|
|
10
10
|
/** Key for current tab ID (sessionStorage) */
|
|
11
11
|
readonly current_tab: "lv_insights_ct";
|
|
12
|
-
/** Key for all tabs registry */
|
|
13
|
-
readonly all_tabs: "lv_insights_at";
|
|
14
12
|
/** Device JWT for direct mode (1yr expiry, rotated on /welcome, analytics-only scope) */
|
|
15
13
|
readonly device_token: "lv_aud_device";
|
|
16
14
|
/** Session JWT for direct mode (1yr expiry, rotated on /welcome, analytics-only scope) */
|
|
@@ -25,4 +23,13 @@ export declare const STORAGE_KEYS: {
|
|
|
25
23
|
* ends, preventing stale isIdentified from blocking /welcome across restarts.
|
|
26
24
|
*/
|
|
27
25
|
readonly session_flags: "lv_insights_sf";
|
|
26
|
+
/**
|
|
27
|
+
* sessionStorage key for the last non-direct attribution (channel/referrer/UTM)
|
|
28
|
+
* of the CURRENT browsing session. Used to carry the original source forward when
|
|
29
|
+
* the visitor-source library would otherwise report "internalLink" for same-site
|
|
30
|
+
* continued browsing after the server cuts a session at its 30-min idle threshold.
|
|
31
|
+
* Session-scoped on purpose — see utils/getReferrer.ts (a long-lived store would
|
|
32
|
+
* mis-attribute a fresh visit days later).
|
|
33
|
+
*/
|
|
34
|
+
readonly attribution: "lv_insights_attr";
|
|
28
35
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { A as e, C as t, D as n, E as r, F as i,
|
|
2
|
-
import { AnalyticsEvents as
|
|
3
|
-
import { getVisitorSource as
|
|
4
|
-
import
|
|
5
|
-
import { Analytics as
|
|
1
|
+
import { A as e, C as t, D as n, E as r, F as i, I as a, L as o, M as s, N as c, O as l, P as u, T as d, _ as f, c as p, d as m, g as h, h as g, i as _, j as v, l as y, n as b, o as x, p as S, s as C, u as w, v as T, w as E, y as ee } from "./textSelection-D9P2LBjT.js";
|
|
2
|
+
import { AnalyticsEvents as D, getLevoError as O } from "@levo-so/core";
|
|
3
|
+
import { getVisitorSource as k } from "@analytics/visitor-source";
|
|
4
|
+
import A from "get-user-locale";
|
|
5
|
+
import { Analytics as j } from "analytics";
|
|
6
6
|
//#region src/utils/rageclick.ts
|
|
7
|
-
var
|
|
8
|
-
let r =
|
|
9
|
-
if (r && Math.abs(e - r.x) + Math.abs(t - r.y) <
|
|
10
|
-
if (
|
|
7
|
+
var M = 30, N = 1e3, P = 3, F = [], I = (e, t, n) => {
|
|
8
|
+
let r = F[F.length - 1];
|
|
9
|
+
if (r && Math.abs(e - r.x) + Math.abs(t - r.y) < M && n - r.timestamp < N) {
|
|
10
|
+
if (F.push({
|
|
11
11
|
x: e,
|
|
12
12
|
y: t,
|
|
13
13
|
timestamp: n
|
|
14
|
-
}),
|
|
15
|
-
} else
|
|
14
|
+
}), F.length >= P) return F = [], !0;
|
|
15
|
+
} else F = [{
|
|
16
16
|
x: e,
|
|
17
17
|
y: t,
|
|
18
18
|
timestamp: n
|
|
19
19
|
}];
|
|
20
20
|
return !1;
|
|
21
|
-
},
|
|
21
|
+
}, L = (e) => {
|
|
22
22
|
let t = e, n = 0;
|
|
23
23
|
for (; t && n < 10;) {
|
|
24
24
|
let e = t.getAttribute?.("href");
|
|
@@ -26,8 +26,8 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
26
26
|
t = t.parentElement, n++;
|
|
27
27
|
}
|
|
28
28
|
return null;
|
|
29
|
-
},
|
|
30
|
-
let t = e.closest("a[href]"), n = t?.getAttribute("href") ||
|
|
29
|
+
}, R = (e) => {
|
|
30
|
+
let t = e.closest("a[href]"), n = t?.getAttribute("href") || L(e);
|
|
31
31
|
if (!n) return {
|
|
32
32
|
type: null,
|
|
33
33
|
href: null
|
|
@@ -54,15 +54,15 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
54
54
|
href: n
|
|
55
55
|
};
|
|
56
56
|
} catch (e) {
|
|
57
|
-
return console.warn("[insights] Failed to classify link",
|
|
57
|
+
return console.warn("[insights] Failed to classify link", O(e)), {
|
|
58
58
|
type: "internal",
|
|
59
59
|
href: n
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
|
-
},
|
|
62
|
+
}, z = (e) => {
|
|
63
63
|
if (typeof window > "u") return () => {};
|
|
64
64
|
let t = 0, n = null, r = (e, t = !1, n) => {
|
|
65
|
-
let r = n ??
|
|
65
|
+
let r = n ?? w(e), i = "clientX" in e ? e.clientX : e.changedTouches?.[0]?.clientX ?? 0, a = "clientY" in e ? e.clientY : e.changedTouches?.[0]?.clientY ?? 0, o = {
|
|
66
66
|
hostname: window.location.hostname,
|
|
67
67
|
pathname: window.location.pathname,
|
|
68
68
|
page_title: document.title,
|
|
@@ -71,9 +71,9 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
71
71
|
event_type: t ? "dblclick" : "click",
|
|
72
72
|
button_type: "button" in e ? e.button : 0
|
|
73
73
|
};
|
|
74
|
-
return r instanceof HTMLElement && (o.rage_click =
|
|
74
|
+
return r instanceof HTMLElement && (o.rage_click = I(i, a, Date.now()), o = {
|
|
75
75
|
...o,
|
|
76
|
-
...
|
|
76
|
+
...y(r)
|
|
77
77
|
}), o;
|
|
78
78
|
}, i = (n, i, a) => {
|
|
79
79
|
try {
|
|
@@ -86,25 +86,25 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
86
86
|
is_navigation: !0
|
|
87
87
|
});
|
|
88
88
|
} catch (e) {
|
|
89
|
-
console.error("[insights] Failed to track navigation click",
|
|
89
|
+
console.error("[insights] Failed to track navigation click", O(e));
|
|
90
90
|
}
|
|
91
91
|
}, a = (n, i = !1, a) => {
|
|
92
92
|
try {
|
|
93
|
-
let o = a ??
|
|
93
|
+
let o = a ?? w(n);
|
|
94
94
|
if (!o || Date.now() - t < 300) return;
|
|
95
|
-
let s = r(n, i, o), c =
|
|
95
|
+
let s = r(n, i, o), c = R(o);
|
|
96
96
|
e.track("page.click", {
|
|
97
97
|
...s,
|
|
98
98
|
href: c.href || void 0,
|
|
99
99
|
link_type: c.type || void 0
|
|
100
100
|
});
|
|
101
101
|
} catch (e) {
|
|
102
|
-
console.error("[insights] Failed to track click",
|
|
102
|
+
console.error("[insights] Failed to track click", O(e));
|
|
103
103
|
}
|
|
104
104
|
}, o = (e) => {
|
|
105
|
-
let t =
|
|
105
|
+
let t = w(e);
|
|
106
106
|
if (!t) return;
|
|
107
|
-
let r =
|
|
107
|
+
let r = R(t);
|
|
108
108
|
if (r.type === "external" || r.type === "download") {
|
|
109
109
|
i(e, r, t);
|
|
110
110
|
return;
|
|
@@ -117,13 +117,13 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
117
117
|
a(e, !1, t), n = null;
|
|
118
118
|
}, 250);
|
|
119
119
|
}, s = (e) => {
|
|
120
|
-
n &&= (clearTimeout(n), null), a(e, !0,
|
|
120
|
+
n &&= (clearTimeout(n), null), a(e, !0, w(e) ?? void 0);
|
|
121
121
|
}, c = (n) => {
|
|
122
122
|
try {
|
|
123
|
-
let i =
|
|
123
|
+
let i = w(n);
|
|
124
124
|
if (!i) return;
|
|
125
125
|
t = Date.now();
|
|
126
|
-
let a =
|
|
126
|
+
let a = R(i);
|
|
127
127
|
if (a.type === "external" || a.type === "download") {
|
|
128
128
|
let t = r(n, !1, i);
|
|
129
129
|
e.track("page.click", {
|
|
@@ -143,52 +143,52 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
143
143
|
is_touch: !0
|
|
144
144
|
});
|
|
145
145
|
} catch (e) {
|
|
146
|
-
console.error("[insights] Failed to track touch",
|
|
146
|
+
console.error("[insights] Failed to track touch", O(e));
|
|
147
147
|
}
|
|
148
148
|
};
|
|
149
149
|
return document.addEventListener("click", o), document.addEventListener("dblclick", s), document.addEventListener("touchend", c, { passive: !0 }), () => {
|
|
150
150
|
document.removeEventListener("click", o), document.removeEventListener("dblclick", s), document.removeEventListener("touchend", c), n && clearTimeout(n);
|
|
151
151
|
};
|
|
152
|
-
},
|
|
152
|
+
}, B = (e) => {
|
|
153
153
|
if (typeof window > "u") return () => {};
|
|
154
154
|
let t = (t) => (n) => {
|
|
155
155
|
try {
|
|
156
|
-
let r =
|
|
156
|
+
let r = m(n, t);
|
|
157
157
|
r && e.track("page.copy", r);
|
|
158
158
|
} catch (e) {
|
|
159
|
-
console.error(`[insights] Failed to track clipboard ${t}`,
|
|
159
|
+
console.error(`[insights] Failed to track clipboard ${t}`, O(e));
|
|
160
160
|
}
|
|
161
161
|
}, n = t("copy"), r = t("cut");
|
|
162
162
|
return document.addEventListener("copy", n, { capture: !0 }), document.addEventListener("cut", r, { capture: !0 }), () => {
|
|
163
163
|
document.removeEventListener("copy", n, { capture: !0 }), document.removeEventListener("cut", r, { capture: !0 });
|
|
164
164
|
};
|
|
165
|
-
},
|
|
165
|
+
}, V = (e) => {
|
|
166
166
|
if (typeof window > "u") return () => {};
|
|
167
167
|
let t = (t) => (n) => {
|
|
168
168
|
try {
|
|
169
|
-
let r =
|
|
169
|
+
let r = m(n, t);
|
|
170
170
|
if (r) {
|
|
171
171
|
let n = t === "submit" ? "form.submit" : "form.change";
|
|
172
172
|
e.track(n, r);
|
|
173
173
|
}
|
|
174
174
|
} catch (e) {
|
|
175
|
-
console.error(`[insights] Failed to track form ${t}`,
|
|
175
|
+
console.error(`[insights] Failed to track form ${t}`, O(e));
|
|
176
176
|
}
|
|
177
177
|
}, n = t("change"), r = t("submit");
|
|
178
178
|
return document.addEventListener("change", n, { capture: !0 }), document.addEventListener("submit", r, { capture: !0 }), () => {
|
|
179
179
|
document.removeEventListener("change", n, { capture: !0 }), document.removeEventListener("submit", r, { capture: !0 });
|
|
180
180
|
};
|
|
181
|
-
},
|
|
181
|
+
}, H = (e) => {
|
|
182
182
|
if (typeof window > "u") return () => {};
|
|
183
|
-
let { page_id: t } =
|
|
183
|
+
let { page_id: t } = u.get(), n = t || "", r = typeof window < "u" ? window.location.href : "", i = () => {
|
|
184
184
|
try {
|
|
185
185
|
e.page({ resource: "page" });
|
|
186
186
|
} catch (e) {
|
|
187
|
-
console.error("[insights] Failed to send page view",
|
|
187
|
+
console.error("[insights] Failed to send page view", O(e));
|
|
188
188
|
}
|
|
189
189
|
};
|
|
190
190
|
if (t) {
|
|
191
|
-
let e =
|
|
191
|
+
let e = u.listen((e, t, r) => {
|
|
192
192
|
let { page_id: a } = e;
|
|
193
193
|
r === "page_id" && a && n !== a && (n = a, i());
|
|
194
194
|
});
|
|
@@ -209,7 +209,7 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
209
209
|
window.removeEventListener("popstate", e), window.history.pushState = t;
|
|
210
210
|
};
|
|
211
211
|
}
|
|
212
|
-
},
|
|
212
|
+
}, U = async (e, t) => {
|
|
213
213
|
let n = null;
|
|
214
214
|
try {
|
|
215
215
|
let r = new AbortController();
|
|
@@ -223,7 +223,7 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
223
223
|
} finally {
|
|
224
224
|
n && clearTimeout(n);
|
|
225
225
|
}
|
|
226
|
-
},
|
|
226
|
+
}, W = async (e) => {
|
|
227
227
|
let { mode: t = "auto", insightsUrl: n, directInsightsUrl: r, pingTimeout: i = 1e3, debug: a = !1 } = e;
|
|
228
228
|
if (a) return {
|
|
229
229
|
mode: "proxy",
|
|
@@ -238,7 +238,7 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
238
238
|
mode: "proxy",
|
|
239
239
|
url: n ?? null
|
|
240
240
|
};
|
|
241
|
-
let [s, c] = await Promise.all([n ?
|
|
241
|
+
let [s, c] = await Promise.all([n ? U(`${n}/ping`, o) : Promise.resolve(!1), r ? U(`${r}/ping`, o) : Promise.resolve(!1)]);
|
|
242
242
|
return s ? {
|
|
243
243
|
mode: "proxy",
|
|
244
244
|
url: n ?? null
|
|
@@ -249,21 +249,61 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
249
249
|
mode: "proxy",
|
|
250
250
|
url: n ?? null
|
|
251
251
|
};
|
|
252
|
-
},
|
|
253
|
-
|
|
254
|
-
|
|
252
|
+
}, G = () => {
|
|
253
|
+
try {
|
|
254
|
+
let e = window.sessionStorage.getItem(s.attribution);
|
|
255
|
+
if (!e) return;
|
|
256
|
+
let t = JSON.parse(e);
|
|
257
|
+
return {
|
|
258
|
+
type: t.type,
|
|
259
|
+
referrer: t.referrer,
|
|
260
|
+
data: t.data
|
|
261
|
+
};
|
|
262
|
+
} catch {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
}, K = (e) => {
|
|
266
|
+
try {
|
|
267
|
+
window.sessionStorage.setItem(s.attribution, JSON.stringify(e));
|
|
268
|
+
} catch {}
|
|
269
|
+
}, q = () => {
|
|
270
|
+
if (typeof document > "u") return {
|
|
271
|
+
type: "",
|
|
272
|
+
referrer: {},
|
|
273
|
+
data: {},
|
|
274
|
+
raw: ""
|
|
275
|
+
};
|
|
276
|
+
let { type: e, referrer: t, data: n = {} } = k({
|
|
255
277
|
referrer: document.referrer,
|
|
256
278
|
currentUrl: window.location.href,
|
|
257
279
|
mapper: null
|
|
258
280
|
}), r = Object.keys(n);
|
|
259
281
|
for (let e of r) n[e] && Array.isArray(n[e]) && n[e].length > 0 && (n[e] = n[e]?.[0]);
|
|
260
|
-
|
|
282
|
+
if (e === "internalLink") {
|
|
283
|
+
let e = G();
|
|
284
|
+
return e ? {
|
|
285
|
+
type: e.type,
|
|
286
|
+
referrer: e.referrer ?? {},
|
|
287
|
+
data: e.data ?? {},
|
|
288
|
+
raw: document.referrer
|
|
289
|
+
} : {
|
|
290
|
+
type: "direct",
|
|
291
|
+
referrer: t ?? {},
|
|
292
|
+
data: n,
|
|
293
|
+
raw: document.referrer
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
return e && e !== "direct" && K({
|
|
261
297
|
type: e,
|
|
262
298
|
referrer: t,
|
|
299
|
+
data: n
|
|
300
|
+
}), {
|
|
301
|
+
type: e,
|
|
302
|
+
referrer: t ?? {},
|
|
263
303
|
data: n,
|
|
264
304
|
raw: document.referrer
|
|
265
305
|
};
|
|
266
|
-
},
|
|
306
|
+
}, J = () => new Promise((e, t) => {
|
|
267
307
|
let n = "Unknown";
|
|
268
308
|
function r(t) {
|
|
269
309
|
e({
|
|
@@ -360,12 +400,12 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
360
400
|
o() ? (n = "Safari", f()) : s() ? (n = i(), g()) : c() ? (n = "Firefox", _()) : l() ? (n = "Internet Explorer", v()) : t(/* @__PURE__ */ Error("detectIncognito cannot determine the browser"));
|
|
361
401
|
}
|
|
362
402
|
y();
|
|
363
|
-
}),
|
|
403
|
+
}), Y = () => {
|
|
364
404
|
let e = document.createElement("canvas"), t = e?.getContext("webgl") || e?.getContext("experimental-webgl");
|
|
365
405
|
if (!t) return null;
|
|
366
406
|
let n = t?.getExtension("WEBGL_debug_renderer_info");
|
|
367
407
|
return n ? t?.getParameter(n.UNMASKED_RENDERER_WEBGL) : null;
|
|
368
|
-
},
|
|
408
|
+
}, te = async () => {
|
|
369
409
|
let e = "", t = "", n = !1, r = !1, i = {};
|
|
370
410
|
if (!window) return {
|
|
371
411
|
locale: e,
|
|
@@ -375,7 +415,7 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
375
415
|
properties: i
|
|
376
416
|
};
|
|
377
417
|
let [a, o, s] = await Promise.allSettled([
|
|
378
|
-
|
|
418
|
+
J(),
|
|
379
419
|
navigator.getBattery?.() ?? Promise.reject(),
|
|
380
420
|
"mediaDevices" in navigator ? navigator.mediaDevices.enumerateDevices() : Promise.reject()
|
|
381
421
|
]);
|
|
@@ -387,7 +427,7 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
387
427
|
t = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
388
428
|
} catch {}
|
|
389
429
|
try {
|
|
390
|
-
e =
|
|
430
|
+
e = A();
|
|
391
431
|
} catch {}
|
|
392
432
|
let c = navigator, l = c.connection ?? c.mozConnection ?? c.webkitConnection;
|
|
393
433
|
if (l && (i.network_type = l.effectiveType), i.width = window?.innerWidth, i.height = window?.innerHeight, i.pixel_ratio = window?.devicePixelRatio, screen && (i.screen_width = screen?.width, i.screen_height = screen?.height, i.color_depth = screen?.colorDepth, i.orientation = screen?.orientation?.type), o.status === "fulfilled") {
|
|
@@ -398,129 +438,129 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
398
438
|
let e = s.value;
|
|
399
439
|
i.camera_supported = e.some((e) => e?.kind === "videoinput"), i.microphone_supported = e.some((e) => e?.kind === "audioinput");
|
|
400
440
|
}
|
|
401
|
-
return i.gpu =
|
|
441
|
+
return i.gpu = Y(), {
|
|
402
442
|
locale: e,
|
|
403
443
|
timezone: t,
|
|
404
444
|
dark_mode: n,
|
|
405
445
|
private_mode: r,
|
|
406
446
|
properties: i
|
|
407
447
|
};
|
|
408
|
-
},
|
|
448
|
+
}, X = (e, t) => {
|
|
409
449
|
if (e.get()) return t(), () => {};
|
|
410
450
|
let n = e.listen((e) => {
|
|
411
451
|
e && (n(), t());
|
|
412
452
|
});
|
|
413
453
|
return n;
|
|
414
|
-
},
|
|
415
|
-
let { debug:
|
|
416
|
-
if (!
|
|
417
|
-
let
|
|
418
|
-
name:
|
|
454
|
+
}, ne = (t, r, a) => {
|
|
455
|
+
let { debug: o } = i();
|
|
456
|
+
if (!t) return null;
|
|
457
|
+
let s = {
|
|
458
|
+
name: t.workspace,
|
|
419
459
|
track: ({ payload: e }) => {
|
|
420
460
|
if (!a()) return;
|
|
421
461
|
let t = e?.properties || {};
|
|
422
|
-
|
|
462
|
+
r(e.event, t);
|
|
423
463
|
},
|
|
424
464
|
page: ({ payload: e }) => {
|
|
425
|
-
a() && (
|
|
465
|
+
a() && (n(), r("page.view", {
|
|
426
466
|
...e?.properties || {},
|
|
427
467
|
resource: "page"
|
|
428
468
|
}));
|
|
429
469
|
},
|
|
430
|
-
identify: ({ payload:
|
|
470
|
+
identify: ({ payload: n }) => {
|
|
431
471
|
if (!a()) return;
|
|
432
|
-
let { workspace:
|
|
433
|
-
if (!
|
|
472
|
+
let { workspace: r, site_id: o, debug: s } = i(), { mode: l, isIdentified: u, isIdentifying: f, sessionToken: p, deviceToken: m, insightsBaseUrl: h, identity: g } = e(), _ = x(), y = C();
|
|
473
|
+
if (!h || !g) return;
|
|
434
474
|
let b = {
|
|
435
|
-
private_mode:
|
|
436
|
-
dark_mode:
|
|
437
|
-
timezone:
|
|
438
|
-
locale:
|
|
439
|
-
referrer:
|
|
475
|
+
private_mode: n.traits?.private_mode ?? g.privateMode ?? !1,
|
|
476
|
+
dark_mode: n.traits?.dark_mode ?? g.darkMode ?? !1,
|
|
477
|
+
timezone: n.traits?.timezone ?? g.timezone ?? "",
|
|
478
|
+
locale: n.traits?.locale ?? g.locale ?? "",
|
|
479
|
+
referrer: n.traits?.referrer ?? g.referrer ?? {
|
|
440
480
|
type: "",
|
|
441
481
|
referrer: {},
|
|
442
482
|
data: {}
|
|
443
483
|
},
|
|
444
484
|
properties: {
|
|
445
|
-
...
|
|
446
|
-
...
|
|
485
|
+
...g.properties,
|
|
486
|
+
...n.traits?.properties
|
|
447
487
|
},
|
|
448
|
-
workspace_id:
|
|
449
|
-
site_id:
|
|
488
|
+
workspace_id: r ?? "",
|
|
489
|
+
site_id: o ?? void 0,
|
|
450
490
|
hostname: window.location.hostname,
|
|
451
491
|
pathname: window.location.pathname,
|
|
452
492
|
page_title: document.title,
|
|
453
493
|
url: window.location.href,
|
|
454
494
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
455
|
-
tab_id:
|
|
495
|
+
tab_id: _ ?? "",
|
|
456
496
|
tab_count: y ?? 0
|
|
457
497
|
};
|
|
458
|
-
if (
|
|
498
|
+
if (s && console.log("[@levo-so/insights] Identification triggered:", {
|
|
459
499
|
isIdentified: u,
|
|
460
|
-
isIdentifying:
|
|
500
|
+
isIdentifying: f,
|
|
461
501
|
welcomeInput: b
|
|
462
|
-
}), u ||
|
|
463
|
-
if (
|
|
464
|
-
console.log("[@levo-so/insights] Debug mode enabled. Mocking session identification."),
|
|
502
|
+
}), u || f) return;
|
|
503
|
+
if (v({ isIdentifying: !0 }), s) {
|
|
504
|
+
console.log("[@levo-so/insights] Debug mode enabled. Mocking session identification."), v({
|
|
465
505
|
isIdentified: !0,
|
|
466
506
|
isIdentifying: !1,
|
|
467
507
|
sessionId: "debug-session",
|
|
468
508
|
deviceId: "debug-device"
|
|
469
|
-
}),
|
|
509
|
+
}), E(d());
|
|
470
510
|
return;
|
|
471
511
|
}
|
|
472
512
|
let S = {
|
|
473
513
|
Accept: "application/json",
|
|
474
514
|
"Content-Type": "application/json",
|
|
475
|
-
...
|
|
476
|
-
sessionToken:
|
|
477
|
-
deviceToken:
|
|
515
|
+
...c({
|
|
516
|
+
sessionToken: p,
|
|
517
|
+
deviceToken: m,
|
|
478
518
|
mode: l
|
|
479
519
|
})
|
|
480
520
|
};
|
|
481
|
-
|
|
521
|
+
t.fetch.url(h, !0).url("/v1/insights/event/welcome").options({
|
|
482
522
|
keepalive: !0,
|
|
483
523
|
credentials: l === "proxy" ? "include" : "omit"
|
|
484
|
-
}).headers(S).post(b).json().then((
|
|
524
|
+
}).headers(S).post(b).json().then((t) => {
|
|
485
525
|
if (!a()) {
|
|
486
|
-
|
|
526
|
+
v({ isIdentifying: !1 });
|
|
487
527
|
return;
|
|
488
528
|
}
|
|
489
|
-
let { isIdentified:
|
|
490
|
-
if (
|
|
529
|
+
let { isIdentified: n } = e();
|
|
530
|
+
if (n) v({ isIdentifying: !1 });
|
|
491
531
|
else {
|
|
492
|
-
let
|
|
532
|
+
let e = {
|
|
493
533
|
isIdentified: !0,
|
|
494
534
|
isIdentifying: !1
|
|
495
535
|
};
|
|
496
|
-
if (
|
|
497
|
-
let
|
|
498
|
-
|
|
536
|
+
if (t?.content?.data?.session && (e.sessionId = t?.content?.data?.session), t?.content?.data?.device && (e.deviceId = t?.content?.data?.device), l === "direct" && t?.content?.meta) {
|
|
537
|
+
let n = t.content.meta;
|
|
538
|
+
n.device_token && (e.deviceToken = n.device_token), n.session_token && (e.sessionToken = n.session_token);
|
|
499
539
|
}
|
|
500
|
-
e
|
|
540
|
+
v(e), E(d());
|
|
501
541
|
}
|
|
502
|
-
}).catch((
|
|
503
|
-
|
|
542
|
+
}).catch((n) => {
|
|
543
|
+
e().isIdentified || t.logger?.error("/welcome failed with error", { exception: O(n) }), v({ isIdentifying: !1 });
|
|
504
544
|
});
|
|
505
545
|
}
|
|
506
546
|
};
|
|
507
|
-
return
|
|
508
|
-
app:
|
|
509
|
-
debug: !!
|
|
510
|
-
plugins: [
|
|
547
|
+
return j({
|
|
548
|
+
app: t.workspace || "",
|
|
549
|
+
debug: !!o,
|
|
550
|
+
plugins: [s]
|
|
511
551
|
});
|
|
512
|
-
},
|
|
513
|
-
let { insightsUrl:
|
|
514
|
-
|
|
515
|
-
workspace:
|
|
516
|
-
debug:
|
|
517
|
-
site_id:
|
|
518
|
-
insightsUrl:
|
|
552
|
+
}, Z = null, Q = !1, $ = [], re = (n, s) => {
|
|
553
|
+
let { insightsUrl: c = null, debug: u = !1, site: m = null } = s;
|
|
554
|
+
a({
|
|
555
|
+
workspace: n.workspace,
|
|
556
|
+
debug: u,
|
|
557
|
+
site_id: m,
|
|
558
|
+
insightsUrl: c ?? null
|
|
519
559
|
});
|
|
520
|
-
let
|
|
560
|
+
let y = async (e, t) => {
|
|
521
561
|
if (typeof window > "u") return;
|
|
522
|
-
let { page_id: n } =
|
|
523
|
-
|
|
562
|
+
let { page_id: n } = i(), a = x(), o = C();
|
|
563
|
+
r({
|
|
524
564
|
event: e,
|
|
525
565
|
version: t?.version || 1,
|
|
526
566
|
properties: {
|
|
@@ -534,82 +574,82 @@ var j = 30, M = 1e3, N = 3, P = [], F = (e, t, n) => {
|
|
|
534
574
|
page_title: void 0,
|
|
535
575
|
created_at: void 0
|
|
536
576
|
},
|
|
537
|
-
hostname: window.location.hostname,
|
|
538
|
-
pathname: window.location.pathname,
|
|
539
577
|
url: t?.url ?? window.location.href,
|
|
540
578
|
page_title: t?.page_title ?? document.title,
|
|
541
579
|
resource: t?.resource ?? "page",
|
|
542
|
-
identifier: t?.
|
|
580
|
+
identifier: t?.identifier || n || void 0,
|
|
543
581
|
created_at: t?.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
544
|
-
|
|
545
|
-
|
|
582
|
+
hostname: window.location.hostname,
|
|
583
|
+
pathname: window.location.pathname,
|
|
584
|
+
tab_id: a ?? "",
|
|
585
|
+
tab_count: o
|
|
546
586
|
});
|
|
547
|
-
},
|
|
548
|
-
!
|
|
587
|
+
}, w = (e) => {
|
|
588
|
+
!Z || !Q || Z.identify("", { withLock: e?.withLock ?? !0 });
|
|
549
589
|
}, D = (e) => {
|
|
550
|
-
let { page_id: t } =
|
|
551
|
-
t !== e &&
|
|
552
|
-
}, O = () => Promise.allSettled([
|
|
553
|
-
let
|
|
554
|
-
type:
|
|
555
|
-
referrer:
|
|
556
|
-
data:
|
|
557
|
-
raw:
|
|
590
|
+
let { page_id: t } = i();
|
|
591
|
+
t !== e && o("page_id", e);
|
|
592
|
+
}, O = () => Promise.allSettled([te(), Promise.resolve().then(() => q())]).then(([e, t]) => {
|
|
593
|
+
let n = e.status === "fulfilled" ? e.value : null, r = t.status === "fulfilled" ? t.value : null, i = r?.type ? {
|
|
594
|
+
type: r.type,
|
|
595
|
+
referrer: r.referrer,
|
|
596
|
+
data: r.data,
|
|
597
|
+
raw: r.raw ?? ""
|
|
558
598
|
} : null;
|
|
559
|
-
|
|
560
|
-
locale:
|
|
561
|
-
timezone:
|
|
562
|
-
darkMode:
|
|
563
|
-
privateMode:
|
|
564
|
-
referrer:
|
|
565
|
-
properties:
|
|
599
|
+
v({ identity: {
|
|
600
|
+
locale: n?.locale ?? null,
|
|
601
|
+
timezone: n?.timezone ?? null,
|
|
602
|
+
darkMode: n?.dark_mode ?? null,
|
|
603
|
+
privateMode: n?.private_mode ?? null,
|
|
604
|
+
referrer: i,
|
|
605
|
+
properties: n?.properties ?? null
|
|
566
606
|
} });
|
|
567
607
|
}), k = () => {
|
|
568
|
-
let { insightsBaseUrl: t } =
|
|
569
|
-
return t ? Promise.resolve() :
|
|
570
|
-
|
|
571
|
-
mode:
|
|
572
|
-
insightsBaseUrl:
|
|
608
|
+
let { insightsBaseUrl: t } = e();
|
|
609
|
+
return t ? Promise.resolve() : W(s).then(({ mode: e, url: t }) => {
|
|
610
|
+
Q && t && v({
|
|
611
|
+
mode: e,
|
|
612
|
+
insightsBaseUrl: t
|
|
573
613
|
});
|
|
574
614
|
}).catch(() => {
|
|
575
|
-
|
|
615
|
+
Q && c && v({
|
|
576
616
|
mode: "proxy",
|
|
577
|
-
insightsBaseUrl:
|
|
617
|
+
insightsBaseUrl: c
|
|
578
618
|
});
|
|
579
619
|
});
|
|
580
620
|
};
|
|
581
621
|
return {
|
|
582
622
|
init: (t = {}) => {
|
|
583
623
|
if (typeof window > "u") throw Error("[@levo-so/insights] init() should only be called on the client side.");
|
|
584
|
-
let { pageId:
|
|
585
|
-
|
|
586
|
-
if (!
|
|
587
|
-
let t =
|
|
588
|
-
t.mode === "direct" && t.isIdentified && (!t.sessionToken || !t.deviceToken) &&
|
|
589
|
-
|
|
624
|
+
let { pageId: r } = t;
|
|
625
|
+
r && D(r), !Q && (n.NODE_ENV === "development" && !u || (Q = !0, $.push(X(l, () => {
|
|
626
|
+
if (!Q) return;
|
|
627
|
+
let t = e();
|
|
628
|
+
t.mode === "direct" && t.isIdentified && (!t.sessionToken || !t.deviceToken) && v({ isIdentified: !1 }), O().finally(() => {
|
|
629
|
+
Q && T.set(!0);
|
|
590
630
|
});
|
|
591
|
-
})),
|
|
592
|
-
|
|
593
|
-
|
|
631
|
+
})), c && $.push(X(l, () => {
|
|
632
|
+
Q && k().finally(() => {
|
|
633
|
+
Q && h.set(!0);
|
|
594
634
|
});
|
|
595
|
-
})),
|
|
596
|
-
if (!
|
|
597
|
-
let e =
|
|
598
|
-
e && (
|
|
599
|
-
})),
|
|
600
|
-
!
|
|
635
|
+
})), $.push(X(f, () => {
|
|
636
|
+
if (!Q || Z) return;
|
|
637
|
+
let e = ne(n, y, () => Z === e);
|
|
638
|
+
e && (Z = e, $.push(g(e), S(e), z(e), B(e), p(e), V(e), H(e), _(e), b(e)));
|
|
639
|
+
})), $.push(X(ee, () => {
|
|
640
|
+
!Q || !Z || (w(), Z.page({ resource: "page" }));
|
|
601
641
|
}))));
|
|
602
642
|
},
|
|
603
643
|
destroy: () => {
|
|
604
|
-
|
|
644
|
+
Q && (E(d()), t(), $.forEach((e) => {
|
|
605
645
|
e();
|
|
606
|
-
}),
|
|
646
|
+
}), $.length = 0, Z = null, Q = !1, T.set(!1), h.set(!1));
|
|
607
647
|
},
|
|
608
|
-
track:
|
|
648
|
+
track: y,
|
|
609
649
|
get instance() {
|
|
610
|
-
return
|
|
650
|
+
return Z;
|
|
611
651
|
}
|
|
612
652
|
};
|
|
613
653
|
};
|
|
614
654
|
//#endregion
|
|
615
|
-
export {
|
|
655
|
+
export { D as AnalyticsEvents, re as createLevoInsights };
|
package/dist/stores/session.d.ts
CHANGED
|
@@ -18,7 +18,6 @@ interface ISession {
|
|
|
18
18
|
deviceToken: string | null;
|
|
19
19
|
/** Direct-mode JWT. Stored in localStorage; survives browser restarts. */
|
|
20
20
|
sessionToken: string | null;
|
|
21
|
-
allTabs: string[];
|
|
22
21
|
mode: "proxy" | "direct";
|
|
23
22
|
insightsBaseUrl: string | null;
|
|
24
23
|
identity: IIdentity | null;
|
package/dist/stores.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { P as e, S as t, _ as n, a as r, b as i, f as a, k as o, m as s, r as c, t as l, x as u } from "./textSelection-D9P2LBjT.js";
|
|
2
|
+
export { s as $activity, e as $config, r as $currentTab, i as $eventQueue, n as $isIdentityContextReady, u as $lifetimePageCount, a as $pageLifecycle, c as $scrollBehavior, l as $selectedText, o as $session, t as $totalEventCount };
|
|
@@ -19,12 +19,12 @@ var o = n({
|
|
|
19
19
|
identify: "lock:lv_aud_identify",
|
|
20
20
|
open_tabs: "lv_insights_ot",
|
|
21
21
|
current_tab: "lv_insights_ct",
|
|
22
|
-
all_tabs: "lv_insights_at",
|
|
23
22
|
device_token: "lv_aud_device",
|
|
24
23
|
session_token: "lv_aud_session",
|
|
25
24
|
mode: "lv_aud_mode",
|
|
26
25
|
session: "lv_insights_session",
|
|
27
|
-
session_flags: "lv_insights_sf"
|
|
26
|
+
session_flags: "lv_insights_sf",
|
|
27
|
+
attribution: "lv_insights_attr"
|
|
28
28
|
}, f = () => {
|
|
29
29
|
if (typeof window > "u" || !("localStorage" in window)) return !1;
|
|
30
30
|
try {
|
|
@@ -40,7 +40,6 @@ var o = n({
|
|
|
40
40
|
deviceId: null,
|
|
41
41
|
deviceToken: null,
|
|
42
42
|
sessionToken: null,
|
|
43
|
-
allTabs: [],
|
|
44
43
|
mode: "proxy",
|
|
45
44
|
insightsBaseUrl: null,
|
|
46
45
|
identity: null
|
|
@@ -106,12 +105,12 @@ if (f()) {
|
|
|
106
105
|
y();
|
|
107
106
|
}, 150);
|
|
108
107
|
} else y();
|
|
109
|
-
var b = () => g.get(),
|
|
108
|
+
var b = () => g.get(), ee = (e) => {
|
|
110
109
|
g.set({
|
|
111
110
|
...b(),
|
|
112
111
|
...e
|
|
113
112
|
});
|
|
114
|
-
},
|
|
113
|
+
}, te = 10, ne = 2e3, x = 1e3, S = e([]), C = e(0), w = t(S, (e) => e.length ?? 0), T = e(null), E = () => S.get(), re = () => w.get(), D = (e) => {
|
|
115
114
|
let { workspace: t, debug: n, site_id: r, page_id: i } = s(), { isIdentified: a, mode: o, sessionId: c, deviceId: l, sessionToken: d, deviceToken: f, insightsBaseUrl: p } = b();
|
|
116
115
|
if (e.length === 0 || !a || !p || !t) return;
|
|
117
116
|
let m = e.map((e) => ({
|
|
@@ -132,7 +131,7 @@ var b = () => g.get(), x = (e) => {
|
|
|
132
131
|
resource: e.resource ?? "page",
|
|
133
132
|
properties: e.properties ?? {}
|
|
134
133
|
}));
|
|
135
|
-
if (
|
|
134
|
+
if (S.set([]), n) {
|
|
136
135
|
console.log("[@levo-so/insights] Debug mode enabled. Events batch:", m);
|
|
137
136
|
return;
|
|
138
137
|
}
|
|
@@ -157,16 +156,16 @@ var b = () => g.get(), x = (e) => {
|
|
|
157
156
|
}).catch((e) => {
|
|
158
157
|
console.warn("[@levo-so/insights] Event flush failed, batch lost:", e);
|
|
159
158
|
});
|
|
160
|
-
},
|
|
161
|
-
if (
|
|
159
|
+
}, O = () => {
|
|
160
|
+
if (T.get()) return;
|
|
162
161
|
let e = setTimeout(() => {
|
|
163
|
-
|
|
164
|
-
},
|
|
165
|
-
|
|
166
|
-
},
|
|
167
|
-
let e =
|
|
168
|
-
e && (clearTimeout(e),
|
|
169
|
-
},
|
|
162
|
+
D(E()), T.set(null);
|
|
163
|
+
}, ne);
|
|
164
|
+
T.set(e);
|
|
165
|
+
}, k = () => {
|
|
166
|
+
let e = T.get();
|
|
167
|
+
e && (clearTimeout(e), T.set(null));
|
|
168
|
+
}, ie = (e) => {
|
|
170
169
|
let { debug: t, insightsUrl: n } = s();
|
|
171
170
|
if (!n) {
|
|
172
171
|
t && console.warn("[@levo-so/insights] Event dropped — insightsUrl not configured.", {
|
|
@@ -175,70 +174,70 @@ var b = () => g.get(), x = (e) => {
|
|
|
175
174
|
});
|
|
176
175
|
return;
|
|
177
176
|
}
|
|
178
|
-
let r =
|
|
179
|
-
if (r >=
|
|
180
|
-
t && console.warn(`[@levo-so/core] Event limit (${
|
|
177
|
+
let r = C.get();
|
|
178
|
+
if (r >= x) {
|
|
179
|
+
t && console.warn(`[@levo-so/core] Event limit (${x}) reached for this page`);
|
|
181
180
|
return;
|
|
182
181
|
}
|
|
183
|
-
|
|
184
|
-
let i =
|
|
185
|
-
|
|
182
|
+
C.set(r + 1);
|
|
183
|
+
let i = S.get();
|
|
184
|
+
S.set([...i, e]);
|
|
186
185
|
let { isIdentified: a } = b();
|
|
187
|
-
|
|
188
|
-
},
|
|
186
|
+
re() >= te ? (k(), D(E())) : a && O();
|
|
187
|
+
}, ae = () => C.set(0), oe = g.get().isIdentified;
|
|
189
188
|
g.subscribe((e) => {
|
|
190
|
-
e.isIdentified && !
|
|
189
|
+
e.isIdentified && !oe && S.get().length > 0 && (e.insightsBaseUrl ? D(E()) : O()), oe = e.isIdentified;
|
|
191
190
|
});
|
|
192
|
-
var
|
|
191
|
+
var se = g.get().insightsBaseUrl;
|
|
193
192
|
g.subscribe((e) => {
|
|
194
|
-
e.insightsBaseUrl && !
|
|
193
|
+
e.insightsBaseUrl && !se && e.isIdentified && S.get().length > 0 && D(E()), se = e.insightsBaseUrl;
|
|
195
194
|
});
|
|
196
|
-
var
|
|
197
|
-
|
|
198
|
-
},
|
|
195
|
+
var ce = () => {
|
|
196
|
+
S.set([]), C.set(0), k();
|
|
197
|
+
}, le = e(!1), A = e(!1), j = t([v, le], (e, t) => e && t), ue = t([j, A], (e, t) => e && t), M = n({
|
|
199
198
|
status: "active",
|
|
200
199
|
seconds: 0
|
|
201
|
-
}),
|
|
200
|
+
}), de = (e) => {
|
|
202
201
|
if (typeof window > "u") return () => {};
|
|
203
202
|
let t = r({
|
|
204
203
|
timeout: 6e4,
|
|
205
204
|
throttle: 1e3,
|
|
206
205
|
onIdle: (e) => {
|
|
207
|
-
|
|
206
|
+
M.set({
|
|
208
207
|
status: "idle",
|
|
209
208
|
seconds: e
|
|
210
209
|
});
|
|
211
210
|
},
|
|
212
211
|
onWakeUp: (e) => {
|
|
213
|
-
|
|
212
|
+
M.set({
|
|
214
213
|
status: "active",
|
|
215
214
|
seconds: e
|
|
216
215
|
});
|
|
217
216
|
}
|
|
218
|
-
}), n =
|
|
217
|
+
}), n = M.listen((t) => {
|
|
219
218
|
t.seconds > 0 && (t.status === "idle" ? e.track("user.idle", { seconds_active: t.seconds }) : e.track("user.active", { seconds_idle: t.seconds }));
|
|
220
219
|
});
|
|
221
220
|
return () => {
|
|
222
|
-
n(), t.disable(),
|
|
221
|
+
n(), t.disable(), M.set({
|
|
223
222
|
status: "active",
|
|
224
223
|
seconds: 0
|
|
225
224
|
});
|
|
226
225
|
};
|
|
227
|
-
},
|
|
226
|
+
}, fe = () => M.get(), N = /* @__PURE__ */ function(e) {
|
|
228
227
|
return e.ACTIVE = "active", e.PASSIVE = "passive", e.HIDDEN = "hidden", e.FROZEN = "frozen", e.TERMINATED = "terminated", e;
|
|
229
|
-
}(
|
|
228
|
+
}(N || {}), P = e(N.ACTIVE), pe = () => typeof document > "u" ? N.ACTIVE : document.visibilityState === "hidden" ? N.HIDDEN : document.hasFocus() ? N.ACTIVE : N.PASSIVE, me = (e) => {
|
|
230
229
|
if (typeof window > "u") return () => {};
|
|
231
230
|
let t = !1, n = (n) => {
|
|
232
231
|
if (t) return;
|
|
233
232
|
t = !0;
|
|
234
|
-
let r =
|
|
235
|
-
r.seconds > 0 && (r.status === "idle" ? a.
|
|
233
|
+
let r = fe(), a = {};
|
|
234
|
+
r.seconds > 0 && (r.status === "idle" ? a.seconds_active = r.seconds : a.seconds_idle = r.seconds);
|
|
236
235
|
try {
|
|
237
236
|
e.track("page.bounce", {
|
|
238
237
|
resource: "page",
|
|
239
238
|
...a,
|
|
240
239
|
...n
|
|
241
|
-
}, {}, () =>
|
|
240
|
+
}, {}, () => D(E()));
|
|
242
241
|
} catch (e) {
|
|
243
242
|
console.error("[insights] Failed to send bounce event", i(e));
|
|
244
243
|
}
|
|
@@ -262,13 +261,13 @@ var ae = () => {
|
|
|
262
261
|
case "blur":
|
|
263
262
|
case "focus":
|
|
264
263
|
case "visibilitychange":
|
|
265
|
-
|
|
264
|
+
P.set(pe());
|
|
266
265
|
break;
|
|
267
266
|
case "freeze":
|
|
268
|
-
|
|
267
|
+
P.set(N.FROZEN);
|
|
269
268
|
break;
|
|
270
269
|
case "pagehide":
|
|
271
|
-
|
|
270
|
+
P.set(e.persisted ? N.FROZEN : N.TERMINATED);
|
|
272
271
|
break;
|
|
273
272
|
}
|
|
274
273
|
}, s = [
|
|
@@ -283,32 +282,32 @@ var ae = () => {
|
|
|
283
282
|
s.forEach((e) => {
|
|
284
283
|
window.addEventListener(e, a, { capture: !0 });
|
|
285
284
|
}), window.addEventListener("beforeunload", r);
|
|
286
|
-
let c =
|
|
287
|
-
e ===
|
|
285
|
+
let c = P.listen((e) => {
|
|
286
|
+
e === N.FROZEN || e === N.TERMINATED ? n({
|
|
288
287
|
state: e,
|
|
289
288
|
trigger: "lifecycle"
|
|
290
|
-
}) : e ===
|
|
289
|
+
}) : e === N.HIDDEN && D(E());
|
|
291
290
|
}), l = o.get().page_id, u = o.listen((e) => {
|
|
292
291
|
e.page_id !== l && (t = !1, l = e.page_id);
|
|
293
|
-
}), d =
|
|
292
|
+
}), d = C.listen((e) => {
|
|
294
293
|
e === 0 && (t = !1);
|
|
295
294
|
});
|
|
296
295
|
return () => {
|
|
297
296
|
s.forEach((e) => {
|
|
298
297
|
window.removeEventListener(e, a, { capture: !0 });
|
|
299
|
-
}), window.removeEventListener("beforeunload", r), c(), u(), d(), t = !1,
|
|
298
|
+
}), window.removeEventListener("beforeunload", r), c(), u(), d(), t = !1, P.set(N.ACTIVE);
|
|
300
299
|
};
|
|
301
|
-
},
|
|
302
|
-
function
|
|
300
|
+
}, F = (e) => Object.prototype.toString.call(e) == "[object String]", he = (e, t) => e.indexOf(t) !== -1, I = (e) => e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ""), L = (e) => e === void 0, ge = (e) => e === null, R = (e) => L(e) || ge(e), z = (e) => !!e && e?.nodeType === 3;
|
|
301
|
+
function _e(e) {
|
|
303
302
|
return !!e && e?.nodeType === 1;
|
|
304
303
|
}
|
|
305
|
-
function
|
|
304
|
+
function ve(e, t) {
|
|
306
305
|
return !!e && !!e?.tagName && e?.tagName.toLowerCase() === t.toLowerCase();
|
|
307
306
|
}
|
|
308
|
-
function
|
|
309
|
-
return e ?
|
|
307
|
+
function ye(e) {
|
|
308
|
+
return e ? I(e).split(/\s+/) : [];
|
|
310
309
|
}
|
|
311
|
-
function
|
|
310
|
+
function be(e) {
|
|
312
311
|
let t = "";
|
|
313
312
|
switch (typeof e?.className) {
|
|
314
313
|
case "string":
|
|
@@ -319,9 +318,9 @@ function ve(e) {
|
|
|
319
318
|
break;
|
|
320
319
|
default: t = "";
|
|
321
320
|
}
|
|
322
|
-
return
|
|
321
|
+
return ye(t);
|
|
323
322
|
}
|
|
324
|
-
var
|
|
323
|
+
var B = (e, t = 255) => R(e) ? "" : I(e).split(/(\s+)/).filter((e) => K(e)).join("").replace(/[\r\n]/g, " ").replace(/[ ]+/g, " ").substring(0, t), V = [
|
|
325
324
|
"span",
|
|
326
325
|
"strong",
|
|
327
326
|
"em",
|
|
@@ -333,25 +332,25 @@ var H = (e, t = 255) => B(e) ? "" : R(e).split(/(\s+)/).filter((e) => J(e)).join
|
|
|
333
332
|
"sub",
|
|
334
333
|
"sup",
|
|
335
334
|
"label"
|
|
336
|
-
],
|
|
335
|
+
], H = (e) => {
|
|
337
336
|
let t = "";
|
|
338
|
-
if (
|
|
339
|
-
for (let n of e.childNodes)
|
|
340
|
-
if (!
|
|
341
|
-
let n = e.querySelectorAll(
|
|
337
|
+
if (Ce(e) && e?.childNodes && e?.childNodes.length) {
|
|
338
|
+
for (let n of e.childNodes) z(n) && n.textContent && (t += B(n.textContent) ?? "");
|
|
339
|
+
if (!I(t)) {
|
|
340
|
+
let n = e.querySelectorAll(V.join(", "));
|
|
342
341
|
for (let e of n) {
|
|
343
342
|
let n = e.textContent;
|
|
344
|
-
n && (t += `${
|
|
343
|
+
n && (t += `${B(n)} `);
|
|
345
344
|
}
|
|
346
345
|
}
|
|
347
|
-
if (!
|
|
346
|
+
if (!I(t) && e instanceof HTMLElement) {
|
|
348
347
|
let n = e.innerText;
|
|
349
|
-
n && (t =
|
|
348
|
+
n && (t = B(n.substring(0, 500)));
|
|
350
349
|
}
|
|
351
350
|
}
|
|
352
|
-
return
|
|
353
|
-
},
|
|
354
|
-
if (!window || !e ||
|
|
351
|
+
return I(t);
|
|
352
|
+
}, U = (e) => L(e.target) ? e?.srcElement || null : e?.composedPath?.()[0] || e?.target || null, xe = (e, t) => {
|
|
353
|
+
if (!window || !e || ve(e, "html") || !_e(e)) return !1;
|
|
355
354
|
let n = window.getComputedStyle(e);
|
|
356
355
|
if (n && n.getPropertyValue("cursor") === "pointer" && t.type === "click") return !0;
|
|
357
356
|
switch (e?.tagName.toLowerCase()) {
|
|
@@ -362,7 +361,7 @@ var H = (e, t = 255) => B(e) ? "" : R(e).split(/(\s+)/).filter((e) => J(e)).join
|
|
|
362
361
|
case "textarea": return ["change", "click"].includes(t.type);
|
|
363
362
|
default: return t.type === "click";
|
|
364
363
|
}
|
|
365
|
-
},
|
|
364
|
+
}, Se = new Set([
|
|
366
365
|
"password",
|
|
367
366
|
"passwd",
|
|
368
367
|
"pwd",
|
|
@@ -383,73 +382,73 @@ var H = (e, t = 255) => B(e) ? "" : R(e).split(/(\s+)/).filter((e) => J(e)).join
|
|
|
383
382
|
"apikey",
|
|
384
383
|
"accesstoken"
|
|
385
384
|
]);
|
|
386
|
-
function
|
|
387
|
-
if (
|
|
385
|
+
function Ce(e) {
|
|
386
|
+
if (he(be(e), "ph-include")) return !0;
|
|
388
387
|
let t = e.type || "";
|
|
389
|
-
if (
|
|
388
|
+
if (F(t)) switch (t.toLowerCase()) {
|
|
390
389
|
case "hidden": return !1;
|
|
391
390
|
case "password": return !1;
|
|
392
391
|
}
|
|
393
392
|
let n = e.name || e?.id || "";
|
|
394
|
-
if (
|
|
393
|
+
if (F(n)) {
|
|
395
394
|
let e = n.toLowerCase().replace(/[^a-z]/g, "");
|
|
396
|
-
if (
|
|
395
|
+
if (Se.has(e)) return !1;
|
|
397
396
|
}
|
|
398
397
|
return !0;
|
|
399
398
|
}
|
|
400
|
-
var
|
|
401
|
-
let t =
|
|
402
|
-
return t = `${t} ${
|
|
399
|
+
var W = "(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})", we = RegExp(`^(?:${W})$`), Te = new RegExp(W), G = "\\d{3}-?\\d{2}-?\\d{4}", Ee = RegExp(`^(${G})$`), De = RegExp(`(${G})`), K = (e, t = !0) => !(R(e) || F(e) && (e = I(e), (t ? we : Te).test((e || "").replace(/[- ]/g, "")) || (t ? Ee : De).test(e))), Oe = (e) => F(e) ? e.substring(0, 10) === "_ngcontent" || e.substring(0, 7) === "_nghost" : !1, ke = (e) => {
|
|
400
|
+
let t = H(e);
|
|
401
|
+
return t = `${t} ${q(e)}`.trim(), K(t) ? t : "";
|
|
403
402
|
};
|
|
404
|
-
function
|
|
403
|
+
function q(e) {
|
|
405
404
|
let t = "";
|
|
406
405
|
if (e?.childNodes.length) for (let n of e.childNodes) {
|
|
407
406
|
let e = n.tagName?.toLowerCase();
|
|
408
|
-
if (n && e &&
|
|
409
|
-
let e =
|
|
410
|
-
t = `${t} ${e}`.trim(), n?.childNodes.length && (t = `${t} ${
|
|
407
|
+
if (n && e && V.includes(e)) try {
|
|
408
|
+
let e = H(n);
|
|
409
|
+
t = `${t} ${e}`.trim(), n?.childNodes.length && (t = `${t} ${q(n)}`.trim());
|
|
411
410
|
} catch {}
|
|
412
411
|
}
|
|
413
412
|
return t;
|
|
414
413
|
}
|
|
415
|
-
var
|
|
416
|
-
let t = e.tagName?.toLowerCase(), n = t === "a" || t === "button" ?
|
|
414
|
+
var Ae = (e) => {
|
|
415
|
+
let t = e.tagName?.toLowerCase(), n = t === "a" || t === "button" ? ke(e) : H(e);
|
|
417
416
|
if (n) return {
|
|
418
417
|
text: n,
|
|
419
418
|
source: "text"
|
|
420
419
|
};
|
|
421
420
|
let r = e.getAttribute("aria-label");
|
|
422
421
|
if (r) return {
|
|
423
|
-
text:
|
|
422
|
+
text: B(r),
|
|
424
423
|
source: "aria-label"
|
|
425
424
|
};
|
|
426
425
|
let i = e.getAttribute("title");
|
|
427
426
|
if (i) return {
|
|
428
|
-
text:
|
|
427
|
+
text: B(i),
|
|
429
428
|
source: "title"
|
|
430
429
|
};
|
|
431
430
|
let a = e.getAttribute("data-track-label");
|
|
432
431
|
if (a) return {
|
|
433
|
-
text:
|
|
432
|
+
text: B(a),
|
|
434
433
|
source: "data-track-label"
|
|
435
434
|
};
|
|
436
435
|
let o = e.querySelector("img[alt], svg[aria-label]");
|
|
437
436
|
if (o) {
|
|
438
437
|
let e = o.getAttribute("alt") || o.getAttribute("aria-label");
|
|
439
438
|
if (e) return {
|
|
440
|
-
text:
|
|
439
|
+
text: B(e),
|
|
441
440
|
source: "alt"
|
|
442
441
|
};
|
|
443
442
|
}
|
|
444
443
|
let s = e.getAttribute("placeholder");
|
|
445
444
|
if (s) return {
|
|
446
|
-
text:
|
|
445
|
+
text: B(s),
|
|
447
446
|
source: "placeholder"
|
|
448
447
|
};
|
|
449
448
|
if (e instanceof HTMLElement && e.innerText) {
|
|
450
449
|
let t = e.innerText.substring(0, 500);
|
|
451
450
|
if (t.trim()) return {
|
|
452
|
-
text:
|
|
451
|
+
text: B(t),
|
|
453
452
|
source: "innerText"
|
|
454
453
|
};
|
|
455
454
|
}
|
|
@@ -457,76 +456,108 @@ var Oe = (e) => {
|
|
|
457
456
|
text: "",
|
|
458
457
|
source: "none"
|
|
459
458
|
};
|
|
460
|
-
},
|
|
459
|
+
}, je = [
|
|
461
460
|
"input",
|
|
462
461
|
"textarea",
|
|
463
462
|
"select"
|
|
464
|
-
],
|
|
465
|
-
let t = e?.tagName?.toLowerCase(), n = { element: t }, r =
|
|
463
|
+
], J = (e) => {
|
|
464
|
+
let t = e?.tagName?.toLowerCase(), n = { element: t }, r = Ae(e);
|
|
466
465
|
n.text = r.text, n.text_source = r.source;
|
|
467
466
|
let i = e.getAttribute("aria-label");
|
|
468
|
-
i && (n.aria_label =
|
|
467
|
+
i && (n.aria_label = B(i));
|
|
469
468
|
let a = e.getAttribute("role");
|
|
470
469
|
a && (n.role = a);
|
|
471
470
|
let o = {};
|
|
472
|
-
for (let t of e.attributes) (t.name.startsWith("data-track-") || t.name.startsWith("data-analytics-")) && (o[t.name] =
|
|
471
|
+
for (let t of e.attributes) (t.name.startsWith("data-track-") || t.name.startsWith("data-analytics-")) && (o[t.name] = B(t.value));
|
|
473
472
|
if (Object.keys(o).length && (n.tracking_data = o), n.attributes = Array.from(e.attributes).reduce((e, t) => {
|
|
474
|
-
if (
|
|
473
|
+
if (K(t.value) && !Oe(t.name)) {
|
|
475
474
|
if (t.name === "class" || t.name.startsWith("data-track-") || t.name.startsWith("data-analytics-")) return e;
|
|
476
|
-
e[t.name] = typeof t?.value == "string" ?
|
|
475
|
+
e[t.name] = typeof t?.value == "string" ? B(t.value) : t.value;
|
|
477
476
|
}
|
|
478
477
|
return e;
|
|
479
|
-
}, {}),
|
|
478
|
+
}, {}), je.includes(t) || e?.getAttribute("contenteditable") === "true") {
|
|
480
479
|
let t;
|
|
481
|
-
e.matches("input[type=\"checkbox\"], input[type=\"radio\"]") ? t = e.checked : e.matches("input, select, textarea") && !e.matches("input[type=\"password\"]") && (t = e.value), t !== void 0 && (n.value = typeof t == "string" || t === null ?
|
|
480
|
+
e.matches("input[type=\"checkbox\"], input[type=\"radio\"]") ? t = e.checked : e.matches("input, select, textarea") && !e.matches("input[type=\"password\"]") && (t = e.value), t !== void 0 && (n.value = typeof t == "string" || t === null ? B(t, 1024) : t);
|
|
482
481
|
let r = "";
|
|
483
|
-
n?.attributes.id && (r =
|
|
482
|
+
n?.attributes.id && (r = B(document.querySelector(`label[for="${n?.attributes.id}"]`)?.textContent?.trim() || ""));
|
|
484
483
|
let i = e.closest("label");
|
|
485
|
-
r ||=
|
|
484
|
+
r ||= B(i?.textContent?.trim() || ""), r && (n.label = r);
|
|
486
485
|
}
|
|
487
486
|
return n;
|
|
488
|
-
},
|
|
489
|
-
let n =
|
|
490
|
-
|
|
487
|
+
}, Me = (e, t) => {
|
|
488
|
+
let n = U(e);
|
|
489
|
+
z(n) && (n = n.parentNode || null);
|
|
491
490
|
let r = ["copy", "cut"].includes(t);
|
|
492
|
-
if (n && (r ||
|
|
493
|
-
let t =
|
|
491
|
+
if (n && (r || xe(n, e))) {
|
|
492
|
+
let t = J(n);
|
|
494
493
|
if (r) {
|
|
495
|
-
let n =
|
|
494
|
+
let n = B(window?.getSelection()?.toString()), r = e?.type || "clipboard";
|
|
496
495
|
t.copy_text = n ?? "", t.copy_type = r ?? "";
|
|
497
496
|
}
|
|
498
497
|
return t;
|
|
499
498
|
}
|
|
500
499
|
return null;
|
|
501
|
-
},
|
|
500
|
+
}, Y = e(null), Ne = 3e3, Pe = 1e4, Fe = `${d.open_tabs}:`, X = (e) => `${Fe}${e}`, Ie = (e) => {
|
|
501
|
+
try {
|
|
502
|
+
localStorage.setItem(X(e), String(Date.now()));
|
|
503
|
+
} catch {}
|
|
504
|
+
}, Z = (e) => {
|
|
505
|
+
try {
|
|
506
|
+
localStorage.removeItem(X(e));
|
|
507
|
+
} catch {}
|
|
508
|
+
}, Le = (e) => {
|
|
509
|
+
try {
|
|
510
|
+
let t = Number(localStorage.getItem(X(e)));
|
|
511
|
+
return Number.isFinite(t) && Date.now() - t <= Pe;
|
|
512
|
+
} catch {
|
|
513
|
+
return !1;
|
|
514
|
+
}
|
|
515
|
+
}, Re = () => {
|
|
516
|
+
try {
|
|
517
|
+
let e = Date.now(), t = 0, n = [];
|
|
518
|
+
for (let r = 0; r < localStorage.length; r++) {
|
|
519
|
+
let i = localStorage.key(r);
|
|
520
|
+
if (!i || !i.startsWith(Fe)) continue;
|
|
521
|
+
let a = Number(localStorage.getItem(i));
|
|
522
|
+
Number.isFinite(a) && e - a <= Pe ? t += 1 : n.push(i);
|
|
523
|
+
}
|
|
524
|
+
for (let e of n) try {
|
|
525
|
+
localStorage.removeItem(e);
|
|
526
|
+
} catch {}
|
|
527
|
+
return Math.max(1, t);
|
|
528
|
+
} catch {
|
|
529
|
+
return 1;
|
|
530
|
+
}
|
|
531
|
+
}, ze = 1, Be = () => {
|
|
532
|
+
ze = Re();
|
|
533
|
+
}, Ve = (e) => {
|
|
502
534
|
if (typeof window > "u") return () => {};
|
|
503
535
|
let t = null;
|
|
504
536
|
try {
|
|
505
537
|
t = sessionStorage.getItem(d.current_tab);
|
|
506
538
|
} catch {}
|
|
507
|
-
|
|
508
|
-
if (t && n.includes(t) && (t = null), !t) {
|
|
539
|
+
if (t && Le(t) && (t = null), !t) {
|
|
509
540
|
t = `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
510
541
|
try {
|
|
511
542
|
sessionStorage.setItem(d.current_tab, t);
|
|
512
543
|
} catch {}
|
|
513
544
|
}
|
|
514
|
-
let
|
|
515
|
-
|
|
516
|
-
let
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
e.
|
|
545
|
+
let n = t;
|
|
546
|
+
Y.set(n), Ie(n), Be();
|
|
547
|
+
let r = window.setInterval(() => {
|
|
548
|
+
Ie(n), Be();
|
|
549
|
+
}, Ne), i = (e) => {
|
|
550
|
+
e.persisted || Z(n);
|
|
520
551
|
};
|
|
521
|
-
return window.addEventListener("beforeunload", i), () => {
|
|
522
|
-
window.removeEventListener("beforeunload", i), i(),
|
|
552
|
+
return window.addEventListener("beforeunload", i), window.addEventListener("pagehide", i), () => {
|
|
553
|
+
window.clearInterval(r), window.removeEventListener("beforeunload", i), window.removeEventListener("pagehide", i), Z(n), Y.set(null);
|
|
523
554
|
};
|
|
524
|
-
},
|
|
555
|
+
}, He = () => Y.get(), Ue = () => ze, Q = n({
|
|
525
556
|
depth: 0,
|
|
526
557
|
milestone: 0,
|
|
527
558
|
speedCategory: "read",
|
|
528
559
|
direction: "down"
|
|
529
|
-
}),
|
|
560
|
+
}), We = (e) => {
|
|
530
561
|
if (typeof window > "u") return () => {};
|
|
531
562
|
let t = {
|
|
532
563
|
prevMilestone: -1,
|
|
@@ -563,7 +594,7 @@ var Oe = (e) => {
|
|
|
563
594
|
direction: "down"
|
|
564
595
|
});
|
|
565
596
|
};
|
|
566
|
-
}, $ = e(null),
|
|
597
|
+
}, $ = e(null), Ge = (e) => {
|
|
567
598
|
if (typeof window > "u") return () => {};
|
|
568
599
|
let t = a(() => {
|
|
569
600
|
let e = window.getSelection();
|
|
@@ -574,11 +605,11 @@ var Oe = (e) => {
|
|
|
574
605
|
}, 1e3);
|
|
575
606
|
document.addEventListener("selectionchange", t);
|
|
576
607
|
let n = $.listen((t) => {
|
|
577
|
-
t && e.track("page.selection", { text:
|
|
608
|
+
t && e.track("page.selection", { text: B(t) });
|
|
578
609
|
});
|
|
579
610
|
return () => {
|
|
580
611
|
document.removeEventListener("selectionchange", t), t.cancel(), n(), $.set(null);
|
|
581
612
|
};
|
|
582
613
|
};
|
|
583
614
|
//#endregion
|
|
584
|
-
export {
|
|
615
|
+
export { b as A, ce as C, ae as D, ie as E, s as F, c as I, l as L, d as M, u as N, v as O, o as P, w as S, E as T, j as _, Y as a, S as b, Ve as c, Me as d, P as f, A as g, de as h, We as i, ee as j, g as k, J as l, M as m, Ge as n, He as o, me as p, Q as r, Ue as s, $ as t, U as u, le as v, D as w, C as x, ue as y };
|
|
@@ -6,11 +6,12 @@ import { AnalyticsInstance } from 'analytics';
|
|
|
6
6
|
declare const $currentTab: import('nanostores').PreinitializedWritableAtom<string | null> & object;
|
|
7
7
|
/**
|
|
8
8
|
* Initialize current tab tracking.
|
|
9
|
-
* Assumes the session store is already synchronized (isReady).
|
|
10
9
|
*
|
|
11
10
|
* @param _instance - Analytics instance
|
|
12
11
|
* @returns Cleanup function
|
|
13
12
|
*/
|
|
14
13
|
declare const initCurrentTabTracker: (_instance: AnalyticsInstance) => () => void;
|
|
15
14
|
declare const getCurrentTab: () => string | null;
|
|
16
|
-
|
|
15
|
+
/** Number of tabs currently open for this site (live heartbeats, cached snapshot). */
|
|
16
|
+
declare const getTabCount: () => number;
|
|
17
|
+
export { $currentTab, initCurrentTabTracker, getCurrentTab, getTabCount };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IIdentityReferrer } from '../types/identity';
|
|
1
2
|
/**
|
|
2
3
|
* Extract referrer information for the current page.
|
|
3
4
|
*
|
|
@@ -9,16 +10,21 @@
|
|
|
9
10
|
* Handles array-to-string conversion for UTM params that may come
|
|
10
11
|
* as arrays from the parser.
|
|
11
12
|
*
|
|
13
|
+
* GA-parity (last-non-direct-click): getVisitorSource returns `internalLink` whenever
|
|
14
|
+
* document.referrer is the SAME site — which happens when the server cuts a session
|
|
15
|
+
* (30-min inactivity) and the visitor keeps browsing. Google Analytics has no
|
|
16
|
+
* `internalLink` channel; it carries the ORIGINAL source forward. So we remember the
|
|
17
|
+
* last real (non-direct, non-internal) channel and restore it in place of
|
|
18
|
+
* `internalLink`, falling back to `direct` when there is no prior source.
|
|
19
|
+
*
|
|
20
|
+
* Example: land via google (`search`) → idle 31 min → keep clicking → the server cuts
|
|
21
|
+
* a new session and document.referrer is the prior same-site page (`internalLink`).
|
|
22
|
+
* We report `search` (matching GA) instead of inventing an `internalLink` channel.
|
|
23
|
+
*
|
|
24
|
+
* Returns one concrete shape for every branch (SSR early-return, internalLink
|
|
25
|
+
* restore, normal). `type` is "" when there is no referrer, so the consumer's
|
|
26
|
+
* `referrer?.type` guard still treats it as "no referrer".
|
|
27
|
+
*
|
|
12
28
|
* @returns Referrer information object
|
|
13
29
|
*/
|
|
14
|
-
export declare const getReferrer: () =>
|
|
15
|
-
type?: undefined;
|
|
16
|
-
referrer?: undefined;
|
|
17
|
-
data?: undefined;
|
|
18
|
-
raw?: undefined;
|
|
19
|
-
} | {
|
|
20
|
-
type: string;
|
|
21
|
-
referrer: Record<string, string>;
|
|
22
|
-
data: Record<string, string>;
|
|
23
|
-
raw: string;
|
|
24
|
-
};
|
|
30
|
+
export declare const getReferrer: () => IIdentityReferrer;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@levo-so/insights",
|
|
3
3
|
"description": "Levo analytics",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.111",
|
|
5
5
|
"author": "Levo Engineering <devs@theinternetfolks.com>",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@analytics/activity-utils": "0.2.2",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"typescript": "5.9.3",
|
|
18
18
|
"vite": "8.0.8",
|
|
19
19
|
"vite-plugin-dts": "4.5.4",
|
|
20
|
-
"@levo-
|
|
21
|
-
"@levo/
|
|
20
|
+
"@levo/ts-config": "0.0.0",
|
|
21
|
+
"@levo-so/core": "0.1.111"
|
|
22
22
|
},
|
|
23
23
|
"exports": {
|
|
24
24
|
".": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"main": "./dist/index.js",
|
|
39
39
|
"module": "./dist/index.js",
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@levo-so/core": "0.1.
|
|
41
|
+
"@levo-so/core": "0.1.111"
|
|
42
42
|
},
|
|
43
43
|
"publishConfig": {
|
|
44
44
|
"access": "public"
|