@hanzo/event 0.3.6 → 0.3.9
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/README.md +22 -4
- package/dist/index.cjs +40 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.mjs +39 -23
- package/dist/index.mjs.map +1 -1
- package/dist/react.cjs +35 -22
- package/dist/react.cjs.map +1 -1
- package/dist/react.mjs +35 -22
- package/dist/react.mjs.map +1 -1
- package/hz.js +328 -0
- package/package.json +2 -1
- package/src/core.test.ts +102 -0
- package/src/core.ts +35 -10
- package/src/hz.test.ts +96 -0
- package/src/index.ts +1 -0
- package/src/sentry.ts +4 -6
- package/src/storage.ts +11 -9
- package/src/uid.test.ts +73 -0
- package/src/uid.ts +70 -0
- package/src/version.ts +1 -1
package/README.md
CHANGED
|
@@ -27,10 +27,28 @@ starve the other:
|
|
|
27
27
|
> plane is **inert**: nothing is sent, nothing throws, analytics is unaffected.
|
|
28
28
|
> Assert `client.errorPlaneEnabled` if you want to know which you have.
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
### No bundler? Use the `hz.js` tag — same client, same wire
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<script async src="https://unpkg.com/@hanzo/event/hz.js"
|
|
34
|
+
data-product="hanzo.ai"
|
|
35
|
+
data-capture="1"></script>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`hz.js` (in this package) is the **script-tag distribution** of this client, for
|
|
39
|
+
surfaces with no build step. It posts the SAME `{ batch: [WireEvent, …] }` to the
|
|
40
|
+
SAME `POST {host}/v1/event`, and adds DOM **autocapture** — `$click` (with an
|
|
41
|
+
element locator), `$outbound`, `$scroll`, `$form`, `$vitals` — which a bundled app
|
|
42
|
+
does not need and a plain page cannot get. Manual API: `window.hanzo.track()` /
|
|
43
|
+
`identify()` / `page()`.
|
|
44
|
+
|
|
45
|
+
> The tag used to live in `hanzoai/analytics` and post a **bare JSON array** of
|
|
46
|
+
> `{site, ts, type, path, …}` to `analytics.hanzo.ai/v1/event` — a second protocol
|
|
47
|
+
> behind an identical path spelling, served by a second collector with its own
|
|
48
|
+
> database. `POST api.hanzo.ai/v1/event {"batch":[]}` answered 200 while
|
|
49
|
+
> `POST analytics.hanzo.ai/v1/event []` answered 204, and a client pointed at the
|
|
50
|
+
> wrong host failed silently. Both the second door and the second collector are
|
|
51
|
+
> deleted. One wire, one door, one client home — this package.
|
|
34
52
|
|
|
35
53
|
- **Batched** with a size + interval flush, and **beacon-on-unload**
|
|
36
54
|
(`sendBeacon` for cookie/publishable-key apps, `fetch(keepalive)` for token apps).
|
package/dist/index.cjs
CHANGED
|
@@ -219,8 +219,34 @@ function scrubText(s2, capturePII = false) {
|
|
|
219
219
|
return s2;
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
+
// src/uid.ts
|
|
223
|
+
var HEX = Array.from({ length: 256 }, (_, i) => (i + 256).toString(16).slice(1));
|
|
224
|
+
function fill(b) {
|
|
225
|
+
const c = typeof crypto !== "undefined" ? crypto : void 0;
|
|
226
|
+
if (c && typeof c.getRandomValues === "function") {
|
|
227
|
+
c.getRandomValues(b);
|
|
228
|
+
return b;
|
|
229
|
+
}
|
|
230
|
+
for (let i = 0; i < b.length; i++) b[i] = Math.random() * 256 | 0;
|
|
231
|
+
return b;
|
|
232
|
+
}
|
|
233
|
+
function uuidv7(now = Date.now()) {
|
|
234
|
+
const b = fill(new Uint8Array(16));
|
|
235
|
+
let t = Math.floor(now);
|
|
236
|
+
for (let i = 5; i >= 0; i--) {
|
|
237
|
+
b[i] = t % 256;
|
|
238
|
+
t = Math.floor(t / 256);
|
|
239
|
+
}
|
|
240
|
+
b[6] = 112 | b[6] & 15;
|
|
241
|
+
b[8] = 128 | b[8] & 63;
|
|
242
|
+
return HEX[b[0]] + HEX[b[1]] + HEX[b[2]] + HEX[b[3]] + "-" + HEX[b[4]] + HEX[b[5]] + "-" + HEX[b[6]] + HEX[b[7]] + "-" + HEX[b[8]] + HEX[b[9]] + "-" + HEX[b[10]] + HEX[b[11]] + HEX[b[12]] + HEX[b[13]] + HEX[b[14]] + HEX[b[15]];
|
|
243
|
+
}
|
|
244
|
+
function uuidv7Time(id) {
|
|
245
|
+
return parseInt(id.slice(0, 8) + id.slice(9, 13), 16);
|
|
246
|
+
}
|
|
247
|
+
|
|
222
248
|
// src/version.ts
|
|
223
|
-
var VERSION = "0.3.
|
|
249
|
+
var VERSION = "0.3.9";
|
|
224
250
|
|
|
225
251
|
// src/sentry.ts
|
|
226
252
|
var MAX_FRAMES = 50;
|
|
@@ -229,11 +255,7 @@ var MAX_LINE_LEN = 2048;
|
|
|
229
255
|
var MAX_TAG_LEN = 1024;
|
|
230
256
|
var MAX_TAGS = 50;
|
|
231
257
|
function eventId() {
|
|
232
|
-
|
|
233
|
-
if (c && "randomUUID" in c) return c.randomUUID().replace(/-/g, "");
|
|
234
|
-
let s2 = "";
|
|
235
|
-
for (let i = 0; i < 32; i++) s2 += Math.floor(Math.random() * 16).toString(16);
|
|
236
|
-
return s2;
|
|
258
|
+
return uuidv7().replace(/-/g, "");
|
|
237
259
|
}
|
|
238
260
|
function byteLen(s2) {
|
|
239
261
|
if (typeof TextEncoder !== "undefined") return new TextEncoder().encode(s2).length;
|
|
@@ -433,17 +455,12 @@ function ls() {
|
|
|
433
455
|
return void 0;
|
|
434
456
|
}
|
|
435
457
|
}
|
|
436
|
-
function uid() {
|
|
437
|
-
const c = typeof crypto !== "undefined" ? crypto : void 0;
|
|
438
|
-
if (c && "randomUUID" in c) return c.randomUUID();
|
|
439
|
-
return "a-" + Date.now().toString(36) + Math.random().toString(36).slice(2, 10);
|
|
440
|
-
}
|
|
441
458
|
function anonId() {
|
|
442
459
|
const s2 = ls();
|
|
443
460
|
if (!s2) return void 0;
|
|
444
461
|
let v = s2.getItem(KEY.anon);
|
|
445
462
|
if (!v) {
|
|
446
|
-
v =
|
|
463
|
+
v = uuidv7();
|
|
447
464
|
s2.setItem(KEY.anon, v);
|
|
448
465
|
}
|
|
449
466
|
return v;
|
|
@@ -458,7 +475,7 @@ function sessionId(now = Date.now()) {
|
|
|
458
475
|
state = null;
|
|
459
476
|
}
|
|
460
477
|
if (!state || now - state.last > SESSION_TTL_MS) {
|
|
461
|
-
state = { id:
|
|
478
|
+
state = { id: uuidv7(now), last: now };
|
|
462
479
|
} else {
|
|
463
480
|
state.last = now;
|
|
464
481
|
}
|
|
@@ -527,11 +544,6 @@ function readEnv(name) {
|
|
|
527
544
|
function appendQuery(url, key, value) {
|
|
528
545
|
return url + (url.includes("?") ? "&" : "?") + key + "=" + encodeURIComponent(value);
|
|
529
546
|
}
|
|
530
|
-
function uid2() {
|
|
531
|
-
const c = typeof crypto !== "undefined" ? crypto : void 0;
|
|
532
|
-
if (c && "randomUUID" in c) return c.randomUUID();
|
|
533
|
-
return "m-" + Date.now().toString(36) + Math.random().toString(36).slice(2, 10);
|
|
534
|
-
}
|
|
535
547
|
function normalizeError2(err) {
|
|
536
548
|
const n = normalizeError(err);
|
|
537
549
|
return { type: n.name, message: n.message, stack: n.stack };
|
|
@@ -661,9 +673,8 @@ var Analytics = class {
|
|
|
661
673
|
}
|
|
662
674
|
/** pageview records a $pageview for the current (or given) location. */
|
|
663
675
|
pageview(path, properties) {
|
|
664
|
-
const url = isBrowser() ? window.location.href : void 0;
|
|
665
676
|
const p = path ?? (isBrowser() ? window.location.pathname : void 0);
|
|
666
|
-
this.enqueue("pageview", PAGEVIEW, {
|
|
677
|
+
this.enqueue("pageview", PAGEVIEW, { path: p, properties });
|
|
667
678
|
}
|
|
668
679
|
/** capture records a named product event with optional properties. Commerce
|
|
669
680
|
* fields (productId/quantity/revenue/currency) may be passed for order events. */
|
|
@@ -783,8 +794,8 @@ var Analytics = class {
|
|
|
783
794
|
}
|
|
784
795
|
build(kind, event, extra) {
|
|
785
796
|
const anon = anonId();
|
|
786
|
-
|
|
787
|
-
messageId:
|
|
797
|
+
const wire = {
|
|
798
|
+
messageId: uuidv7(),
|
|
788
799
|
type: kind,
|
|
789
800
|
event,
|
|
790
801
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -816,6 +827,11 @@ var Analytics = class {
|
|
|
816
827
|
libraryVersion: VERSION,
|
|
817
828
|
...extra
|
|
818
829
|
};
|
|
830
|
+
const capturePII = this.cfg.capturePII ?? false;
|
|
831
|
+
if (wire.url) wire.url = scrubText(wire.url, capturePII);
|
|
832
|
+
if (wire.path) wire.path = scrubText(wire.path, capturePII);
|
|
833
|
+
if (wire.referrer) wire.referrer = scrubText(wire.referrer, capturePII);
|
|
834
|
+
return wire;
|
|
819
835
|
}
|
|
820
836
|
schedule() {
|
|
821
837
|
if (this.timer || !this.cfg.enabled) return;
|
|
@@ -1002,5 +1018,7 @@ exports.parseDsn = parseDsn;
|
|
|
1002
1018
|
exports.redactSecrets = redactSecrets;
|
|
1003
1019
|
exports.scrubPII = scrubPII;
|
|
1004
1020
|
exports.scrubText = scrubText;
|
|
1021
|
+
exports.uuidv7 = uuidv7;
|
|
1022
|
+
exports.uuidv7Time = uuidv7Time;
|
|
1005
1023
|
//# sourceMappingURL=index.cjs.map
|
|
1006
1024
|
//# sourceMappingURL=index.cjs.map
|