vantmetry 0.0.3 → 0.0.4
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/core/tracker.d.ts +1 -0
- package/core/transport.d.ts +3 -0
- package/core/types.d.ts +1 -0
- package/index.js +8 -5
- package/{init-DdlNmKDT.js → init-BfWOgJup.js} +84 -71
- package/next/index.js +1 -1
- package/package.json +1 -1
- package/react/index.js +1 -1
- package/src/core/listeners.ts +7 -2
- package/src/core/tracker.ts +9 -0
- package/src/core/transport.ts +18 -2
- package/src/core/types.ts +1 -0
- package/src/index.ts +3 -0
package/core/tracker.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare class VantmetryTracker implements VantmetryInstance {
|
|
|
15
15
|
info(message: string, details?: LogDetails): void;
|
|
16
16
|
debug(message: string, details?: LogDetails): void;
|
|
17
17
|
flush(): Promise<void>;
|
|
18
|
+
destroy(): Promise<void>;
|
|
18
19
|
private addToBuffer;
|
|
19
20
|
captureAutoError(payload: LogPayload): void;
|
|
20
21
|
private getSignature;
|
package/core/transport.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { VantmetryConfig } from './types';
|
|
2
2
|
export declare class TransportManager {
|
|
3
3
|
private wtSession;
|
|
4
|
+
private wtInitPromise;
|
|
4
5
|
private readonly endpoint;
|
|
5
6
|
private readonly wtEndpoint;
|
|
6
7
|
private readonly debug;
|
|
7
8
|
constructor(config: VantmetryConfig);
|
|
8
9
|
private initWT;
|
|
10
|
+
private connectWT;
|
|
9
11
|
send(payload: string): Promise<void>;
|
|
12
|
+
close(): void;
|
|
10
13
|
}
|
package/core/types.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export interface VantmetryInstance {
|
|
|
13
13
|
info: (message: string, details?: LogDetails) => void;
|
|
14
14
|
debug: (message: string, details?: LogDetails) => void;
|
|
15
15
|
flush: () => Promise<void>;
|
|
16
|
+
destroy: () => Promise<void>;
|
|
16
17
|
}
|
|
17
18
|
declare global {
|
|
18
19
|
interface Window {
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { g as t } from "./init-
|
|
2
|
-
import { V as i, i as g, a as
|
|
3
|
-
const
|
|
1
|
+
import { g as t } from "./init-BfWOgJup.js";
|
|
2
|
+
import { V as i, i as g, a as u } from "./init-BfWOgJup.js";
|
|
3
|
+
const o = {
|
|
4
4
|
get isReady() {
|
|
5
5
|
return t().isReady;
|
|
6
6
|
},
|
|
@@ -18,11 +18,14 @@ const n = {
|
|
|
18
18
|
},
|
|
19
19
|
flush() {
|
|
20
20
|
return t().flush();
|
|
21
|
+
},
|
|
22
|
+
destroy() {
|
|
23
|
+
return t().destroy();
|
|
21
24
|
}
|
|
22
25
|
};
|
|
23
26
|
export {
|
|
24
27
|
i as VantmetryTracker,
|
|
25
28
|
g as init,
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
u as initGlobalListeners,
|
|
30
|
+
o as logger
|
|
28
31
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
let f = null;
|
|
2
|
-
function
|
|
3
|
-
f =
|
|
2
|
+
function T(i) {
|
|
3
|
+
f = i;
|
|
4
4
|
}
|
|
5
5
|
function A() {
|
|
6
6
|
if (!f)
|
|
7
7
|
throw new Error("[Vantmetry] Not initialized. Call init() before using logger.");
|
|
8
8
|
return f;
|
|
9
9
|
}
|
|
10
|
-
function
|
|
10
|
+
function E() {
|
|
11
11
|
return f !== null;
|
|
12
12
|
}
|
|
13
13
|
const c = {
|
|
@@ -15,23 +15,26 @@ const c = {
|
|
|
15
15
|
INFO: "INFO",
|
|
16
16
|
WARN: "WARN",
|
|
17
17
|
DEBUG: "DEBUG"
|
|
18
|
-
},
|
|
19
|
-
class
|
|
18
|
+
}, S = "https://ingestor.vantmetry.com:4433";
|
|
19
|
+
class b {
|
|
20
20
|
wtSession = null;
|
|
21
|
+
wtInitPromise = null;
|
|
21
22
|
endpoint;
|
|
22
23
|
wtEndpoint;
|
|
23
24
|
debug;
|
|
24
25
|
constructor(e) {
|
|
25
|
-
const t = (e.ingestorUrl ??
|
|
26
|
+
const t = (e.ingestorUrl ?? S).replace(/\/$/, "");
|
|
26
27
|
this.endpoint = `${t}/api/ingestor/push/tcp?public_key=${e.publicKey}`, this.wtEndpoint = `${t}/api/ingestor/push/udp?public_key=${e.publicKey}`;
|
|
27
28
|
try {
|
|
28
29
|
this.debug = typeof window < "u" && !!window.localStorage?.getItem("vantmetry_debug");
|
|
29
30
|
} catch {
|
|
30
31
|
this.debug = !1;
|
|
31
32
|
}
|
|
32
|
-
this.initWT();
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
initWT() {
|
|
35
|
+
return this.wtInitPromise ? this.wtInitPromise : (this.wtInitPromise = this.connectWT(), this.wtInitPromise);
|
|
36
|
+
}
|
|
37
|
+
async connectWT() {
|
|
35
38
|
if ("WebTransport" in window) {
|
|
36
39
|
await new Promise((e) => setTimeout(e, 200));
|
|
37
40
|
try {
|
|
@@ -42,7 +45,7 @@ class S {
|
|
|
42
45
|
}
|
|
43
46
|
}
|
|
44
47
|
async send(e) {
|
|
45
|
-
if (this.wtSession)
|
|
48
|
+
if (await this.initWT(), this.wtSession)
|
|
46
49
|
try {
|
|
47
50
|
const s = (await this.wtSession.createUnidirectionalStream()).getWriter();
|
|
48
51
|
await s.write(new TextEncoder().encode(e)), await s.close();
|
|
@@ -64,8 +67,11 @@ class S {
|
|
|
64
67
|
this.debug && console.error("Vantmetry send failed", t);
|
|
65
68
|
});
|
|
66
69
|
}
|
|
70
|
+
close() {
|
|
71
|
+
this.wtSession && (this.wtSession.close(), this.wtSession = null);
|
|
72
|
+
}
|
|
67
73
|
}
|
|
68
|
-
const
|
|
74
|
+
const u = {
|
|
69
75
|
// Matches standard email formats
|
|
70
76
|
email: /\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\b/g,
|
|
71
77
|
// Matches standard CC groupings: 4-4-4-[3-4] with required separators, or Amex 4-6-5 format.
|
|
@@ -93,41 +99,41 @@ const l = {
|
|
|
93
99
|
"client_secret",
|
|
94
100
|
"auth"
|
|
95
101
|
]);
|
|
96
|
-
function d(
|
|
97
|
-
let e =
|
|
98
|
-
return e = e.replace(
|
|
102
|
+
function d(i) {
|
|
103
|
+
let e = i;
|
|
104
|
+
return e = e.replace(u.email, (t) => {
|
|
99
105
|
const s = t.split("@");
|
|
100
106
|
if (s.length !== 2)
|
|
101
107
|
return t;
|
|
102
|
-
const [
|
|
103
|
-
return `${
|
|
104
|
-
}), e = e.replace(
|
|
105
|
-
const s = t.replace(/[-\s]/g, ""),
|
|
106
|
-
return "*".repeat(s.length - 4) +
|
|
107
|
-
}), e = e.replace(
|
|
108
|
+
const [n, a] = s;
|
|
109
|
+
return `${n.charAt(0)}***@${a}`;
|
|
110
|
+
}), e = e.replace(u.creditCard, (t) => {
|
|
111
|
+
const s = t.replace(/[-\s]/g, ""), n = s.slice(-4);
|
|
112
|
+
return "*".repeat(s.length - 4) + n;
|
|
113
|
+
}), e = e.replace(u.ssn, (t) => `***-**-${t.slice(-4)}`), e = e.replace(u.jwt, "[JWT REDACTED]"), e = e.replace(u.authHeader, "$1 [TOKEN REDACTED]"), e;
|
|
108
114
|
}
|
|
109
|
-
function h(
|
|
110
|
-
if (typeof
|
|
111
|
-
return d(
|
|
112
|
-
if (!
|
|
113
|
-
return
|
|
114
|
-
if (e.has(
|
|
115
|
+
function h(i, e = /* @__PURE__ */ new WeakSet()) {
|
|
116
|
+
if (typeof i == "string")
|
|
117
|
+
return d(i);
|
|
118
|
+
if (!i || typeof i != "object")
|
|
119
|
+
return i;
|
|
120
|
+
if (e.has(i))
|
|
115
121
|
return "[Circular]";
|
|
116
|
-
if (e.add(
|
|
117
|
-
return
|
|
122
|
+
if (e.add(i), Array.isArray(i))
|
|
123
|
+
return i.map((s) => h(s, e));
|
|
118
124
|
const t = {};
|
|
119
|
-
for (const [s,
|
|
125
|
+
for (const [s, n] of Object.entries(i)) {
|
|
120
126
|
const a = s.toLowerCase();
|
|
121
|
-
if (p.has(a) || Array.from(p).some((
|
|
127
|
+
if (p.has(a) || Array.from(p).some((r) => a.includes(r))) {
|
|
122
128
|
t[s] = "[REDACTED]";
|
|
123
129
|
continue;
|
|
124
130
|
}
|
|
125
|
-
typeof
|
|
131
|
+
typeof n == "string" ? t[s] = d(n) : typeof n == "object" && n !== null ? t[s] = h(n, e) : t[s] = n;
|
|
126
132
|
}
|
|
127
133
|
return t;
|
|
128
134
|
}
|
|
129
|
-
const R = 50,
|
|
130
|
-
class
|
|
135
|
+
const R = 50, v = 2e3;
|
|
136
|
+
class _ {
|
|
131
137
|
buffer = [];
|
|
132
138
|
flushTimer = null;
|
|
133
139
|
transport;
|
|
@@ -139,7 +145,7 @@ class v {
|
|
|
139
145
|
TTL_MS = 6e4;
|
|
140
146
|
MAX_EVENTS_PER_SEC = 100;
|
|
141
147
|
constructor(e) {
|
|
142
|
-
this.transport = new
|
|
148
|
+
this.transport = new b(e);
|
|
143
149
|
}
|
|
144
150
|
// --- Public API ---
|
|
145
151
|
error(e, t) {
|
|
@@ -155,16 +161,21 @@ class v {
|
|
|
155
161
|
this.addToBuffer({ severity: c.DEBUG, type: "manual", message: e, details: t });
|
|
156
162
|
}
|
|
157
163
|
async flush() {
|
|
158
|
-
if (this.buffer.length === 0)
|
|
164
|
+
if (this.buffer.length === 0) {
|
|
165
|
+
this.flushTimer && (clearTimeout(this.flushTimer), this.flushTimer = null);
|
|
159
166
|
return;
|
|
167
|
+
}
|
|
160
168
|
const e = Date.now();
|
|
161
169
|
for (const s of this.buffer)
|
|
162
170
|
this.sentErrors.set(this.getSignature(s), e);
|
|
163
|
-
for (const [s,
|
|
164
|
-
e -
|
|
171
|
+
for (const [s, n] of this.sentErrors.entries())
|
|
172
|
+
e - n >= this.TTL_MS && this.sentErrors.delete(s);
|
|
165
173
|
const t = JSON.stringify(this.buffer);
|
|
166
174
|
this.buffer = [], this.flushTimer && (clearTimeout(this.flushTimer), this.flushTimer = null), await this.transport.send(t);
|
|
167
175
|
}
|
|
176
|
+
async destroy() {
|
|
177
|
+
this.transport.close(), await this.flush();
|
|
178
|
+
}
|
|
168
179
|
// --- Internal Logic ---
|
|
169
180
|
addToBuffer(e) {
|
|
170
181
|
if (!this.isReady)
|
|
@@ -174,30 +185,30 @@ class v {
|
|
|
174
185
|
this.isReady = !1, console.error("[Vantmetry] Logging disabled to save browser CPU due to infinite loop detection.");
|
|
175
186
|
return;
|
|
176
187
|
}
|
|
177
|
-
const s = this.getSignature(e),
|
|
178
|
-
if (
|
|
188
|
+
const s = this.getSignature(e), n = this.sentErrors.get(s);
|
|
189
|
+
if (n && t - n < this.TTL_MS)
|
|
179
190
|
return;
|
|
180
|
-
const a = this.buffer.find((
|
|
191
|
+
const a = this.buffer.find((y) => this.getSignature(y) === s);
|
|
181
192
|
if (a) {
|
|
182
193
|
a.count = (a.count || 1) + 1;
|
|
183
194
|
return;
|
|
184
195
|
}
|
|
185
|
-
let { message:
|
|
186
|
-
const { details:
|
|
187
|
-
|
|
188
|
-
const g = typeof
|
|
196
|
+
let { message: r, stack: o } = e;
|
|
197
|
+
const { details: l } = e;
|
|
198
|
+
r instanceof Error && (o = o ?? r.stack, r = r.message || String(r));
|
|
199
|
+
const g = typeof r == "string" ? d(r) : r, w = typeof l == "object" ? h(l) : l, m = typeof o == "string" ? d(o) : o;
|
|
189
200
|
this.buffer.push({
|
|
190
201
|
...e,
|
|
191
202
|
message: g,
|
|
192
|
-
details:
|
|
193
|
-
stack:
|
|
203
|
+
details: w,
|
|
204
|
+
stack: m,
|
|
194
205
|
count: 1,
|
|
195
206
|
ts: Date.now(),
|
|
196
207
|
url: window.location.href,
|
|
197
208
|
ua: navigator.userAgent
|
|
198
209
|
}), this.buffer.length >= R ? this.flush() : this.flushTimer || (this.flushTimer = setTimeout(() => {
|
|
199
210
|
this.flush();
|
|
200
|
-
},
|
|
211
|
+
}, v));
|
|
201
212
|
}
|
|
202
213
|
captureAutoError(e) {
|
|
203
214
|
this.addToBuffer(e);
|
|
@@ -206,17 +217,17 @@ class v {
|
|
|
206
217
|
return `${e.type}:${e.severity}:${e.message}`;
|
|
207
218
|
}
|
|
208
219
|
}
|
|
209
|
-
function
|
|
220
|
+
function k(i) {
|
|
210
221
|
const e = console.error;
|
|
211
222
|
console.error = function(...t) {
|
|
212
|
-
if (e.apply(console, t), !
|
|
213
|
-
|
|
223
|
+
if (e.apply(console, t), !i._isCapturingConsoleError) {
|
|
224
|
+
i._isCapturingConsoleError = !0;
|
|
214
225
|
try {
|
|
215
|
-
let s,
|
|
216
|
-
const a = t.findIndex((o) => o instanceof Error),
|
|
217
|
-
if (
|
|
218
|
-
const o = t.slice(0, a).filter((
|
|
219
|
-
s = o ? `${o}: ${
|
|
226
|
+
let s, n;
|
|
227
|
+
const a = t.findIndex((o) => o instanceof Error), r = t[a];
|
|
228
|
+
if (r) {
|
|
229
|
+
const o = t.slice(0, a).filter((l) => typeof l == "string").join(" ");
|
|
230
|
+
s = o ? `${o}: ${r.message || String(r)}` : r.message || String(r), n = r.stack;
|
|
220
231
|
} else
|
|
221
232
|
s = t.map((o) => {
|
|
222
233
|
if (typeof o == "string") return o;
|
|
@@ -226,18 +237,18 @@ function _(n) {
|
|
|
226
237
|
return String(o);
|
|
227
238
|
}
|
|
228
239
|
}).join(" ");
|
|
229
|
-
|
|
240
|
+
i.captureAutoError({
|
|
230
241
|
type: "console.error",
|
|
231
242
|
message: s || "Unknown console.error",
|
|
232
|
-
stack:
|
|
243
|
+
stack: n,
|
|
233
244
|
severity: c.ERROR
|
|
234
245
|
});
|
|
235
246
|
} finally {
|
|
236
|
-
|
|
247
|
+
i._isCapturingConsoleError = !1;
|
|
237
248
|
}
|
|
238
249
|
}
|
|
239
250
|
}, window.addEventListener("error", function(t) {
|
|
240
|
-
|
|
251
|
+
i.captureAutoError({
|
|
241
252
|
type: "crash",
|
|
242
253
|
message: t.message || "Script error.",
|
|
243
254
|
stack: t.error?.stack,
|
|
@@ -245,26 +256,28 @@ function _(n) {
|
|
|
245
256
|
severity: c.ERROR
|
|
246
257
|
});
|
|
247
258
|
}, { capture: !0 }), window.addEventListener("unhandledrejection", function(t) {
|
|
248
|
-
const s = t.reason,
|
|
249
|
-
|
|
259
|
+
const s = t.reason, n = s instanceof Error;
|
|
260
|
+
i.captureAutoError({
|
|
250
261
|
type: "promise",
|
|
251
|
-
message:
|
|
252
|
-
stack:
|
|
262
|
+
message: n ? s.message : String(s),
|
|
263
|
+
stack: n ? s.stack : new Error(`Unhandled rejection: ${String(s)}`).stack,
|
|
253
264
|
severity: c.ERROR
|
|
254
265
|
});
|
|
255
|
-
}, { capture: !0 }),
|
|
256
|
-
document.visibilityState === "hidden" &&
|
|
266
|
+
}, { capture: !0 }), window.addEventListener("visibilitychange", function() {
|
|
267
|
+
document.visibilityState === "hidden" && i.flush();
|
|
268
|
+
}), window.addEventListener("pagehide", () => {
|
|
269
|
+
i.destroy();
|
|
257
270
|
});
|
|
258
271
|
}
|
|
259
|
-
function
|
|
260
|
-
if (
|
|
272
|
+
function I(i) {
|
|
273
|
+
if (E())
|
|
261
274
|
return;
|
|
262
|
-
const e = new
|
|
263
|
-
|
|
275
|
+
const e = new _(i);
|
|
276
|
+
T(e), k(e);
|
|
264
277
|
}
|
|
265
278
|
export {
|
|
266
|
-
|
|
267
|
-
|
|
279
|
+
_ as V,
|
|
280
|
+
k as a,
|
|
268
281
|
A as g,
|
|
269
|
-
|
|
282
|
+
I as i
|
|
270
283
|
};
|
package/next/index.js
CHANGED
package/package.json
CHANGED
package/react/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as s } from "react/jsx-runtime";
|
|
2
2
|
import { createContext as i, Component as a, useEffect as u, useContext as c } from "react";
|
|
3
3
|
import { logger as o } from "../index.js";
|
|
4
|
-
import { i as m } from "../init-
|
|
4
|
+
import { i as m } from "../init-BfWOgJup.js";
|
|
5
5
|
const n = i(null);
|
|
6
6
|
function h({ publicKey: t, ingestorUrl: r, children: e }) {
|
|
7
7
|
return u(() => {
|
package/src/core/listeners.ts
CHANGED
|
@@ -67,10 +67,15 @@ export function initGlobalListeners(tracker: VantmetryTracker) {
|
|
|
67
67
|
});
|
|
68
68
|
}, { capture: true });
|
|
69
69
|
|
|
70
|
-
// Flush on page unload
|
|
71
|
-
|
|
70
|
+
// Flush on page unload or visibility change
|
|
71
|
+
window.addEventListener('visibilitychange', function () {
|
|
72
72
|
if (document.visibilityState === 'hidden') {
|
|
73
73
|
void tracker.flush();
|
|
74
74
|
}
|
|
75
75
|
});
|
|
76
|
+
|
|
77
|
+
// Enable bfcache restoration by closing transport on navigate away
|
|
78
|
+
window.addEventListener('pagehide', () => {
|
|
79
|
+
void tracker.destroy();
|
|
80
|
+
});
|
|
76
81
|
}
|
package/src/core/tracker.ts
CHANGED
|
@@ -43,6 +43,10 @@ export class VantmetryTracker implements VantmetryInstance {
|
|
|
43
43
|
|
|
44
44
|
public async flush() {
|
|
45
45
|
if (this.buffer.length === 0) {
|
|
46
|
+
if (this.flushTimer) {
|
|
47
|
+
clearTimeout(this.flushTimer);
|
|
48
|
+
this.flushTimer = null;
|
|
49
|
+
}
|
|
46
50
|
return;
|
|
47
51
|
}
|
|
48
52
|
|
|
@@ -69,6 +73,11 @@ export class VantmetryTracker implements VantmetryInstance {
|
|
|
69
73
|
await this.transport.send(dataPayload);
|
|
70
74
|
}
|
|
71
75
|
|
|
76
|
+
public async destroy() {
|
|
77
|
+
this.transport.close();
|
|
78
|
+
await this.flush();
|
|
79
|
+
}
|
|
80
|
+
|
|
72
81
|
// --- Internal Logic ---
|
|
73
82
|
|
|
74
83
|
private addToBuffer(payload: LogPayload) {
|
package/src/core/transport.ts
CHANGED
|
@@ -4,6 +4,7 @@ const DEFAULT_INGESTOR_URL = 'https://ingestor.vantmetry.com:4433';
|
|
|
4
4
|
|
|
5
5
|
export class TransportManager {
|
|
6
6
|
private wtSession: WebTransport | null = null;
|
|
7
|
+
private wtInitPromise: Promise<void> | null = null;
|
|
7
8
|
private readonly endpoint: string;
|
|
8
9
|
private readonly wtEndpoint: string;
|
|
9
10
|
private readonly debug: boolean;
|
|
@@ -18,11 +19,17 @@ export class TransportManager {
|
|
|
18
19
|
} catch {
|
|
19
20
|
this.debug = false;
|
|
20
21
|
}
|
|
22
|
+
}
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
private initWT(): Promise<void> {
|
|
25
|
+
if (this.wtInitPromise) {
|
|
26
|
+
return this.wtInitPromise;
|
|
27
|
+
}
|
|
28
|
+
this.wtInitPromise = this.connectWT();
|
|
29
|
+
return this.wtInitPromise;
|
|
23
30
|
}
|
|
24
31
|
|
|
25
|
-
private async
|
|
32
|
+
private async connectWT(): Promise<void> {
|
|
26
33
|
if (!('WebTransport' in window)) {
|
|
27
34
|
return;
|
|
28
35
|
}
|
|
@@ -46,6 +53,8 @@ export class TransportManager {
|
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
public async send(payload: string): Promise<void> {
|
|
56
|
+
await this.initWT();
|
|
57
|
+
|
|
49
58
|
if (this.wtSession) {
|
|
50
59
|
try {
|
|
51
60
|
const stream = await this.wtSession.createUnidirectionalStream();
|
|
@@ -79,4 +88,11 @@ export class TransportManager {
|
|
|
79
88
|
}
|
|
80
89
|
});
|
|
81
90
|
}
|
|
91
|
+
|
|
92
|
+
public close() {
|
|
93
|
+
if (this.wtSession) {
|
|
94
|
+
this.wtSession.close();
|
|
95
|
+
this.wtSession = null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
82
98
|
}
|
package/src/core/types.ts
CHANGED