@hanzo/event 0.3.13 → 0.3.15
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/LICENSE.md +21 -0
- package/dist/index.cjs +124 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.mjs +124 -30
- package/dist/index.mjs.map +1 -1
- package/dist/react.cjs +121 -29
- package/dist/react.cjs.map +1 -1
- package/dist/react.mjs +121 -29
- package/dist/react.mjs.map +1 -1
- package/hz.js +188 -27
- package/package.json +10 -10
- package/src/anon.d.ts +14 -0
- package/src/anon.js +199 -0
- package/src/anon.test.ts +80 -0
- package/src/hz.test.ts +67 -12
- package/src/storage.test.ts +285 -0
- package/src/storage.ts +18 -10
- package/src/uid.ts +9 -35
- package/src/version.ts +1 -1
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 hanzo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.cjs
CHANGED
|
@@ -259,34 +259,115 @@ function scrubText(s2, capturePII = false) {
|
|
|
259
259
|
return s2;
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
-
// src/
|
|
263
|
-
var
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
for (let i = 5; i >= 0; i--) {
|
|
262
|
+
// src/anon.js
|
|
263
|
+
var HZ_ANON_KEY = "hz_anon_id";
|
|
264
|
+
var HZ_ANON_LEGACY_KEY = "hz_id";
|
|
265
|
+
var HZ_ANON_DOMAIN = "hanzo.ai";
|
|
266
|
+
var HZ_ANON_MAX_AGE = 2 * 365 * 24 * 60 * 60;
|
|
267
|
+
var hzAnonMemo;
|
|
268
|
+
function hzUuidv7(now) {
|
|
269
|
+
var b = new Uint8Array(16);
|
|
270
|
+
var i;
|
|
271
|
+
var c = typeof crypto !== "undefined" ? crypto : void 0;
|
|
272
|
+
if (c && typeof c.getRandomValues === "function") c.getRandomValues(b);
|
|
273
|
+
else for (i = 0; i < 16; i++) b[i] = Math.random() * 256 | 0;
|
|
274
|
+
var t = Math.floor(now === void 0 ? Date.now() : now);
|
|
275
|
+
for (i = 5; i >= 0; i--) {
|
|
277
276
|
b[i] = t % 256;
|
|
278
277
|
t = Math.floor(t / 256);
|
|
279
278
|
}
|
|
280
279
|
b[6] = 112 | b[6] & 15;
|
|
281
280
|
b[8] = 128 | b[8] & 63;
|
|
282
|
-
|
|
281
|
+
var h = "";
|
|
282
|
+
for (i = 0; i < 16; i++) {
|
|
283
|
+
h += (b[i] + 256).toString(16).slice(1);
|
|
284
|
+
if (i === 3 || i === 5 || i === 7 || i === 9) h += "-";
|
|
285
|
+
}
|
|
286
|
+
return h;
|
|
283
287
|
}
|
|
288
|
+
function hzAnonJar() {
|
|
289
|
+
try {
|
|
290
|
+
if (typeof document === "undefined" || typeof document.cookie !== "string") return null;
|
|
291
|
+
return document;
|
|
292
|
+
} catch (e) {
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
function hzAnonStore() {
|
|
297
|
+
try {
|
|
298
|
+
if (typeof window === "undefined" || !window.localStorage) return null;
|
|
299
|
+
return window.localStorage;
|
|
300
|
+
} catch (e) {
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function hzAnonItem(store, name) {
|
|
305
|
+
try {
|
|
306
|
+
return store && store.getItem(name) || "";
|
|
307
|
+
} catch (e) {
|
|
308
|
+
return "";
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function hzAnonCookie(name) {
|
|
312
|
+
var d = hzAnonJar();
|
|
313
|
+
if (!d) return "";
|
|
314
|
+
var parts = d.cookie.split(";");
|
|
315
|
+
for (var i = 0; i < parts.length; i++) {
|
|
316
|
+
var eq = parts[i].indexOf("=");
|
|
317
|
+
if (eq < 0 || parts[i].slice(0, eq).trim() !== name) continue;
|
|
318
|
+
var v = parts[i].slice(eq + 1).trim();
|
|
319
|
+
if (!v) continue;
|
|
320
|
+
try {
|
|
321
|
+
return decodeURIComponent(v);
|
|
322
|
+
} catch (e) {
|
|
323
|
+
return v;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return "";
|
|
327
|
+
}
|
|
328
|
+
function hzAnonWrite(name, value) {
|
|
329
|
+
var d = hzAnonJar();
|
|
330
|
+
if (!d) return;
|
|
331
|
+
var host = "";
|
|
332
|
+
var secure = false;
|
|
333
|
+
try {
|
|
334
|
+
if (typeof window !== "undefined" && window.location) {
|
|
335
|
+
host = window.location.hostname || "";
|
|
336
|
+
secure = window.location.protocol === "https:";
|
|
337
|
+
}
|
|
338
|
+
} catch (e) {
|
|
339
|
+
}
|
|
340
|
+
var c = name + "=" + encodeURIComponent(value);
|
|
341
|
+
c += "; Path=/; Max-Age=" + HZ_ANON_MAX_AGE + "; SameSite=Lax";
|
|
342
|
+
if (("." + host).slice(-(HZ_ANON_DOMAIN.length + 1)) === "." + HZ_ANON_DOMAIN) {
|
|
343
|
+
c += "; Domain=" + HZ_ANON_DOMAIN;
|
|
344
|
+
}
|
|
345
|
+
if (secure) c += "; Secure";
|
|
346
|
+
try {
|
|
347
|
+
d.cookie = c;
|
|
348
|
+
} catch (e) {
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function hzAnonId() {
|
|
352
|
+
if (typeof window === "undefined") return "";
|
|
353
|
+
var s2 = hzAnonStore();
|
|
354
|
+
var id = hzAnonCookie(HZ_ANON_KEY) || hzAnonItem(s2, HZ_ANON_KEY) || hzAnonItem(s2, HZ_ANON_LEGACY_KEY) || hzAnonMemo || hzUuidv7();
|
|
355
|
+
hzAnonMemo = id;
|
|
356
|
+
hzAnonWrite(HZ_ANON_KEY, id);
|
|
357
|
+
try {
|
|
358
|
+
if (s2 && s2.getItem(HZ_ANON_KEY) !== id) s2.setItem(HZ_ANON_KEY, id);
|
|
359
|
+
} catch (e) {
|
|
360
|
+
}
|
|
361
|
+
return id;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// src/uid.ts
|
|
284
365
|
function uuidv7Time(id) {
|
|
285
366
|
return parseInt(id.slice(0, 8) + id.slice(9, 13), 16);
|
|
286
367
|
}
|
|
287
368
|
|
|
288
369
|
// src/version.ts
|
|
289
|
-
var VERSION = "0.3.
|
|
370
|
+
var VERSION = "0.3.15";
|
|
290
371
|
|
|
291
372
|
// src/sentry.ts
|
|
292
373
|
var MAX_FRAMES = 50;
|
|
@@ -295,7 +376,7 @@ var MAX_LINE_LEN = 2048;
|
|
|
295
376
|
var MAX_TAG_LEN = 1024;
|
|
296
377
|
var MAX_TAGS = 50;
|
|
297
378
|
function eventId() {
|
|
298
|
-
return
|
|
379
|
+
return hzUuidv7().replace(/-/g, "");
|
|
299
380
|
}
|
|
300
381
|
function byteLen(s2) {
|
|
301
382
|
if (typeof TextEncoder !== "undefined") return new TextEncoder().encode(s2).length;
|
|
@@ -481,7 +562,6 @@ ${payload}
|
|
|
481
562
|
|
|
482
563
|
// src/storage.ts
|
|
483
564
|
var KEY = {
|
|
484
|
-
anon: "hz_anon_id",
|
|
485
565
|
session: "hz_session",
|
|
486
566
|
firstTouch: "hz_first_touch",
|
|
487
567
|
cohort: "hz_cohort"
|
|
@@ -496,14 +576,7 @@ function ls() {
|
|
|
496
576
|
}
|
|
497
577
|
}
|
|
498
578
|
function anonId() {
|
|
499
|
-
|
|
500
|
-
if (!s2) return void 0;
|
|
501
|
-
let v = s2.getItem(KEY.anon);
|
|
502
|
-
if (!v) {
|
|
503
|
-
v = uuidv7();
|
|
504
|
-
s2.setItem(KEY.anon, v);
|
|
505
|
-
}
|
|
506
|
-
return v;
|
|
579
|
+
return hzAnonId() || void 0;
|
|
507
580
|
}
|
|
508
581
|
function sessionId(now = Date.now()) {
|
|
509
582
|
const s2 = ls();
|
|
@@ -515,7 +588,7 @@ function sessionId(now = Date.now()) {
|
|
|
515
588
|
state = null;
|
|
516
589
|
}
|
|
517
590
|
if (!state || now - state.last > SESSION_TTL_MS) {
|
|
518
|
-
state = { id:
|
|
591
|
+
state = { id: hzUuidv7(now), last: now };
|
|
519
592
|
} else {
|
|
520
593
|
state.last = now;
|
|
521
594
|
}
|
|
@@ -851,7 +924,7 @@ var Analytics = class {
|
|
|
851
924
|
build(kind, event, extra) {
|
|
852
925
|
const anon = anonId();
|
|
853
926
|
const wire = {
|
|
854
|
-
messageId:
|
|
927
|
+
messageId: hzUuidv7(),
|
|
855
928
|
type: kind,
|
|
856
929
|
event,
|
|
857
930
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -1047,6 +1120,27 @@ var COHORTS = {
|
|
|
1047
1120
|
channel: { field: "channel", label: "Acquisition channel" },
|
|
1048
1121
|
refCode: { field: "ref_code", label: "Referral code" }
|
|
1049
1122
|
};
|
|
1123
|
+
/*! anon.js — THE anonymous-identity chain. ONE implementation, three distributions.
|
|
1124
|
+
*
|
|
1125
|
+
* One browser is ONE person on every Hanzo surface, whichever client a page
|
|
1126
|
+
* happens to have loaded. There were three implementations writing TWO keys —
|
|
1127
|
+
* `hz_anon_id` (the npm client, the hosted tag) and `hz_id` (hz.js) — so the same
|
|
1128
|
+
* visitor was several people depending on which snippet the surface shipped.
|
|
1129
|
+
*
|
|
1130
|
+
* The three call sites:
|
|
1131
|
+
* 1. src/storage.ts — the bundled npm client; IMPORTS this file.
|
|
1132
|
+
* 2. hz.js — the no-build script tag; INLINES the marked region.
|
|
1133
|
+
* 3. hanzoai/cloud apps/analytics/tag.js — the tag the door hosts at
|
|
1134
|
+
* /v1/event.js; vendors this file and its tag.go serves the marked region
|
|
1135
|
+
* with the tag as one asset, so the door holds no second copy either.
|
|
1136
|
+
*
|
|
1137
|
+
* (2) and (3) have no bundler and cannot import anything, which is why the chain
|
|
1138
|
+
* lives in a file that is plain ES5 rather than in a .ts: the region between the
|
|
1139
|
+
* BEGIN and END markers is COPIED VERBATIM, and src/anon.test.ts fails if hz.js's
|
|
1140
|
+
* copy is so much as a byte different. Keep the region ES5, dependency-free,
|
|
1141
|
+
* `hz`-prefixed (it is spliced into other people's scopes) and unformatted — a
|
|
1142
|
+
* reformat of one copy is a diff against the other.
|
|
1143
|
+
*/
|
|
1050
1144
|
|
|
1051
1145
|
exports.Analytics = Analytics;
|
|
1052
1146
|
exports.COHORTS = COHORTS;
|
|
@@ -1074,7 +1168,7 @@ exports.parseDsn = parseDsn;
|
|
|
1074
1168
|
exports.redactSecrets = redactSecrets;
|
|
1075
1169
|
exports.scrubPII = scrubPII;
|
|
1076
1170
|
exports.scrubText = scrubText;
|
|
1077
|
-
exports.uuidv7 =
|
|
1171
|
+
exports.uuidv7 = hzUuidv7;
|
|
1078
1172
|
exports.uuidv7Time = uuidv7Time;
|
|
1079
1173
|
//# sourceMappingURL=index.cjs.map
|
|
1080
1174
|
//# sourceMappingURL=index.cjs.map
|