@hanzo/event 0.3.14 → 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/dist/react.cjs CHANGED
@@ -206,31 +206,110 @@ function scrubText(s, capturePII = false) {
206
206
  return s;
207
207
  }
208
208
 
209
- // src/uid.ts
210
- var HEX = Array.from({ length: 256 }, (_, i) => (i + 256).toString(16).slice(1));
211
- function fill(b) {
212
- const c = typeof crypto !== "undefined" ? crypto : void 0;
213
- if (c && typeof c.getRandomValues === "function") {
214
- c.getRandomValues(b);
215
- return b;
216
- }
217
- for (let i = 0; i < b.length; i++) b[i] = Math.random() * 256 | 0;
218
- return b;
219
- }
220
- function uuidv7(now = Date.now()) {
221
- const b = fill(new Uint8Array(16));
222
- let t = Math.floor(now);
223
- for (let i = 5; i >= 0; i--) {
209
+ // src/anon.js
210
+ var HZ_ANON_KEY = "hz_anon_id";
211
+ var HZ_ANON_LEGACY_KEY = "hz_id";
212
+ var HZ_ANON_DOMAIN = "hanzo.ai";
213
+ var HZ_ANON_MAX_AGE = 2 * 365 * 24 * 60 * 60;
214
+ var hzAnonMemo;
215
+ function hzUuidv7(now) {
216
+ var b = new Uint8Array(16);
217
+ var i;
218
+ var c = typeof crypto !== "undefined" ? crypto : void 0;
219
+ if (c && typeof c.getRandomValues === "function") c.getRandomValues(b);
220
+ else for (i = 0; i < 16; i++) b[i] = Math.random() * 256 | 0;
221
+ var t = Math.floor(now === void 0 ? Date.now() : now);
222
+ for (i = 5; i >= 0; i--) {
224
223
  b[i] = t % 256;
225
224
  t = Math.floor(t / 256);
226
225
  }
227
226
  b[6] = 112 | b[6] & 15;
228
227
  b[8] = 128 | b[8] & 63;
229
- 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]];
228
+ var h = "";
229
+ for (i = 0; i < 16; i++) {
230
+ h += (b[i] + 256).toString(16).slice(1);
231
+ if (i === 3 || i === 5 || i === 7 || i === 9) h += "-";
232
+ }
233
+ return h;
234
+ }
235
+ function hzAnonJar() {
236
+ try {
237
+ if (typeof document === "undefined" || typeof document.cookie !== "string") return null;
238
+ return document;
239
+ } catch (e) {
240
+ return null;
241
+ }
242
+ }
243
+ function hzAnonStore() {
244
+ try {
245
+ if (typeof window === "undefined" || !window.localStorage) return null;
246
+ return window.localStorage;
247
+ } catch (e) {
248
+ return null;
249
+ }
250
+ }
251
+ function hzAnonItem(store, name) {
252
+ try {
253
+ return store && store.getItem(name) || "";
254
+ } catch (e) {
255
+ return "";
256
+ }
257
+ }
258
+ function hzAnonCookie(name) {
259
+ var d = hzAnonJar();
260
+ if (!d) return "";
261
+ var parts = d.cookie.split(";");
262
+ for (var i = 0; i < parts.length; i++) {
263
+ var eq = parts[i].indexOf("=");
264
+ if (eq < 0 || parts[i].slice(0, eq).trim() !== name) continue;
265
+ var v = parts[i].slice(eq + 1).trim();
266
+ if (!v) continue;
267
+ try {
268
+ return decodeURIComponent(v);
269
+ } catch (e) {
270
+ return v;
271
+ }
272
+ }
273
+ return "";
274
+ }
275
+ function hzAnonWrite(name, value) {
276
+ var d = hzAnonJar();
277
+ if (!d) return;
278
+ var host = "";
279
+ var secure = false;
280
+ try {
281
+ if (typeof window !== "undefined" && window.location) {
282
+ host = window.location.hostname || "";
283
+ secure = window.location.protocol === "https:";
284
+ }
285
+ } catch (e) {
286
+ }
287
+ var c = name + "=" + encodeURIComponent(value);
288
+ c += "; Path=/; Max-Age=" + HZ_ANON_MAX_AGE + "; SameSite=Lax";
289
+ if (("." + host).slice(-(HZ_ANON_DOMAIN.length + 1)) === "." + HZ_ANON_DOMAIN) {
290
+ c += "; Domain=" + HZ_ANON_DOMAIN;
291
+ }
292
+ if (secure) c += "; Secure";
293
+ try {
294
+ d.cookie = c;
295
+ } catch (e) {
296
+ }
297
+ }
298
+ function hzAnonId() {
299
+ if (typeof window === "undefined") return "";
300
+ var s = hzAnonStore();
301
+ var id = hzAnonCookie(HZ_ANON_KEY) || hzAnonItem(s, HZ_ANON_KEY) || hzAnonItem(s, HZ_ANON_LEGACY_KEY) || hzAnonMemo || hzUuidv7();
302
+ hzAnonMemo = id;
303
+ hzAnonWrite(HZ_ANON_KEY, id);
304
+ try {
305
+ if (s && s.getItem(HZ_ANON_KEY) !== id) s.setItem(HZ_ANON_KEY, id);
306
+ } catch (e) {
307
+ }
308
+ return id;
230
309
  }
231
310
 
232
311
  // src/version.ts
233
- var VERSION = "0.3.14";
312
+ var VERSION = "0.3.15";
234
313
 
235
314
  // src/sentry.ts
236
315
  var MAX_FRAMES = 50;
@@ -239,7 +318,7 @@ var MAX_LINE_LEN = 2048;
239
318
  var MAX_TAG_LEN = 1024;
240
319
  var MAX_TAGS = 50;
241
320
  function eventId() {
242
- return uuidv7().replace(/-/g, "");
321
+ return hzUuidv7().replace(/-/g, "");
243
322
  }
244
323
  function byteLen(s) {
245
324
  if (typeof TextEncoder !== "undefined") return new TextEncoder().encode(s).length;
@@ -425,14 +504,11 @@ ${payload}
425
504
 
426
505
  // src/storage.ts
427
506
  var KEY = {
428
- anon: "hz_anon_id",
429
507
  session: "hz_session",
430
508
  firstTouch: "hz_first_touch",
431
509
  cohort: "hz_cohort"
432
510
  };
433
511
  var SESSION_TTL_MS = 30 * 60 * 1e3;
434
- var ANON_DOMAIN = "hanzo.ai";
435
- var ANON_MAX_AGE_S = 2 * 365 * 24 * 60 * 60;
436
512
  function ls() {
437
513
  try {
438
514
  if (typeof window === "undefined" || !window.localStorage) return void 0;
@@ -441,69 +517,8 @@ function ls() {
441
517
  return void 0;
442
518
  }
443
519
  }
444
- function jar() {
445
- try {
446
- if (typeof document === "undefined" || typeof document.cookie !== "string") return void 0;
447
- return document;
448
- } catch {
449
- return void 0;
450
- }
451
- }
452
- function getCookie(name) {
453
- const d = jar();
454
- if (!d) return void 0;
455
- for (const part of d.cookie.split(";")) {
456
- const eq = part.indexOf("=");
457
- if (eq < 0 || part.slice(0, eq).trim() !== name) continue;
458
- const v = part.slice(eq + 1).trim();
459
- if (!v) continue;
460
- try {
461
- return decodeURIComponent(v);
462
- } catch {
463
- return v;
464
- }
465
- }
466
- return void 0;
467
- }
468
- function setCookie(name, value) {
469
- const d = jar();
470
- if (!d) return;
471
- let host = "";
472
- let secure = false;
473
- try {
474
- if (typeof window !== "undefined" && window.location) {
475
- host = window.location.hostname || "";
476
- secure = window.location.protocol === "https:";
477
- }
478
- } catch {
479
- }
480
- const attrs = [
481
- // encodeURIComponent leaves a UUID byte-identical while making any value that
482
- // is not one unable to forge a `;` and inject an attribute.
483
- `${name}=${encodeURIComponent(value)}`,
484
- "Path=/",
485
- `Max-Age=${ANON_MAX_AGE_S}`,
486
- "SameSite=Lax"
487
- ];
488
- if (host === ANON_DOMAIN || host.endsWith(`.${ANON_DOMAIN}`)) attrs.push(`Domain=${ANON_DOMAIN}`);
489
- if (secure) attrs.push("Secure");
490
- try {
491
- d.cookie = attrs.join("; ");
492
- } catch {
493
- }
494
- }
495
- var memAnon;
496
520
  function anonId() {
497
- if (typeof window === "undefined") return void 0;
498
- const s = ls();
499
- const id = getCookie(KEY.anon) || s?.getItem(KEY.anon) || memAnon || uuidv7();
500
- memAnon = id;
501
- setCookie(KEY.anon, id);
502
- try {
503
- if (s && s.getItem(KEY.anon) !== id) s.setItem(KEY.anon, id);
504
- } catch {
505
- }
506
- return id;
521
+ return hzAnonId() || void 0;
507
522
  }
508
523
  function sessionId(now = Date.now()) {
509
524
  const s = ls();
@@ -515,7 +530,7 @@ function sessionId(now = Date.now()) {
515
530
  state = null;
516
531
  }
517
532
  if (!state || now - state.last > SESSION_TTL_MS) {
518
- state = { id: uuidv7(now), last: now };
533
+ state = { id: hzUuidv7(now), last: now };
519
534
  } else {
520
535
  state.last = now;
521
536
  }
@@ -851,7 +866,7 @@ var Analytics = class {
851
866
  build(kind, event, extra) {
852
867
  const anon = anonId();
853
868
  const wire = {
854
- messageId: uuidv7(),
869
+ messageId: hzUuidv7(),
855
870
  type: kind,
856
871
  event,
857
872
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -964,6 +979,27 @@ var ErrorBoundary = class extends react.Component {
964
979
  }
965
980
  };
966
981
  ErrorBoundary.contextType = Ctx;
982
+ /*! anon.js — THE anonymous-identity chain. ONE implementation, three distributions.
983
+ *
984
+ * One browser is ONE person on every Hanzo surface, whichever client a page
985
+ * happens to have loaded. There were three implementations writing TWO keys —
986
+ * `hz_anon_id` (the npm client, the hosted tag) and `hz_id` (hz.js) — so the same
987
+ * visitor was several people depending on which snippet the surface shipped.
988
+ *
989
+ * The three call sites:
990
+ * 1. src/storage.ts — the bundled npm client; IMPORTS this file.
991
+ * 2. hz.js — the no-build script tag; INLINES the marked region.
992
+ * 3. hanzoai/cloud apps/analytics/tag.js — the tag the door hosts at
993
+ * /v1/event.js; vendors this file and its tag.go serves the marked region
994
+ * with the tag as one asset, so the door holds no second copy either.
995
+ *
996
+ * (2) and (3) have no bundler and cannot import anything, which is why the chain
997
+ * lives in a file that is plain ES5 rather than in a .ts: the region between the
998
+ * BEGIN and END markers is COPIED VERBATIM, and src/anon.test.ts fails if hz.js's
999
+ * copy is so much as a byte different. Keep the region ES5, dependency-free,
1000
+ * `hz`-prefixed (it is spliced into other people's scopes) and unformatted — a
1001
+ * reformat of one copy is a diff against the other.
1002
+ */
967
1003
 
968
1004
  exports.AnalyticsProvider = AnalyticsProvider;
969
1005
  exports.ErrorBoundary = ErrorBoundary;