@hanzo/event 0.3.25 → 0.3.27
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/{core-DO8tBUy7.d.cts → core-usULsfUB.d.cts} +16 -4
- package/dist/{core-DO8tBUy7.d.ts → core-usULsfUB.d.ts} +16 -4
- package/dist/index.cjs +48 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +48 -9
- package/dist/index.mjs.map +1 -1
- package/dist/react.cjs +50 -14
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.mjs +51 -15
- package/dist/react.mjs.map +1 -1
- package/hz.js +19 -20
- package/package.json +10 -10
- package/src/core.ts +105 -21
- package/src/hz.test.ts +14 -3
- package/src/react.tsx +7 -7
- package/src/stream.test.ts +169 -0
- package/src/transport.test.ts +7 -1
- package/src/version.ts +1 -1
- package/src/stack.ts +0 -144
package/dist/react.cjs
CHANGED
|
@@ -309,7 +309,7 @@ function hzAnonId() {
|
|
|
309
309
|
}
|
|
310
310
|
|
|
311
311
|
// src/version.ts
|
|
312
|
-
var VERSION = "0.3.
|
|
312
|
+
var VERSION = "0.3.27";
|
|
313
313
|
|
|
314
314
|
// src/sentry.ts
|
|
315
315
|
var MAX_FRAMES = 50;
|
|
@@ -726,17 +726,18 @@ var DefaultTransport = class {
|
|
|
726
726
|
}
|
|
727
727
|
}
|
|
728
728
|
if (typeof fetch !== "function") return;
|
|
729
|
+
const simple = opts.ingestKey !== void 0 && opts.contentType === void 0;
|
|
729
730
|
const headers = {
|
|
730
|
-
"Content-Type": opts.contentType ?? "application/json"
|
|
731
|
+
"Content-Type": simple ? BEACON_CONTENT_TYPE : opts.contentType ?? "application/json"
|
|
731
732
|
};
|
|
732
|
-
const bearer = opts.ingestKey ?? opts.token;
|
|
733
|
+
const bearer = simple ? void 0 : opts.ingestKey ?? opts.token;
|
|
733
734
|
if (bearer) headers.Authorization = `Bearer ${bearer}`;
|
|
734
|
-
void fetch(url, {
|
|
735
|
+
void fetch(simple ? appendQuery(url, "ingest_key", opts.ingestKey) : url, {
|
|
735
736
|
method: "POST",
|
|
736
737
|
headers,
|
|
737
738
|
body,
|
|
738
739
|
keepalive: true,
|
|
739
|
-
credentials: "include"
|
|
740
|
+
credentials: simple ? "omit" : "include"
|
|
740
741
|
}).then((res) => {
|
|
741
742
|
if (!res.ok && opts.debug) {
|
|
742
743
|
console.warn("[event] ingest rejected", res.status, url.split("?")[0]);
|
|
@@ -785,6 +786,20 @@ var Analytics = class {
|
|
|
785
786
|
config.dsn ?? readEnvDsn() ?? dsnForProduct(this.cfg.product, this.cfg.ingestKey)
|
|
786
787
|
);
|
|
787
788
|
}
|
|
789
|
+
/** adopt gives this client a credential it does not have. The key belongs to
|
|
790
|
+
* the stream, not to whichever caller happened to ask for the handle first,
|
|
791
|
+
* so a later caller carrying one hands it over. The error plane derives from
|
|
792
|
+
* the key, so it comes up here too when it was inert for want of one.
|
|
793
|
+
* Present fields are never overwritten: the first caller's key stays. */
|
|
794
|
+
adopt(config) {
|
|
795
|
+
if (config.ingestKey && !this.cfg.ingestKey) this.cfg.ingestKey = config.ingestKey;
|
|
796
|
+
if (config.getToken && !this.cfg.getToken) this.cfg.getToken = config.getToken;
|
|
797
|
+
if (!this.dsn) {
|
|
798
|
+
this.dsn = parseDsn(
|
|
799
|
+
config.dsn ?? readEnvDsn() ?? dsnForProduct(this.cfg.product, this.cfg.ingestKey)
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
788
803
|
/** errorPlaneEnabled reports whether captured exceptions can actually reach the
|
|
789
804
|
* error host. False means a DSN was never configured — the documented
|
|
790
805
|
* fail-safe. Exposed so an app (or a test) can assert its wiring instead of
|
|
@@ -835,9 +850,14 @@ var Analytics = class {
|
|
|
835
850
|
group(groupId, traits) {
|
|
836
851
|
this.enqueue("group", void 0, { groupId, properties: traits });
|
|
837
852
|
}
|
|
838
|
-
/** pageview records a $pageview for the current (or given) location
|
|
853
|
+
/** pageview records a $pageview for the current (or given) location, once per
|
|
854
|
+
* view. A view is the path plus the full location, so a query or hash change
|
|
855
|
+
* is a new one and a repeat call for the same place is not. */
|
|
839
856
|
pageview(path, properties) {
|
|
840
857
|
const p = path ?? (isBrowser() ? window.location.pathname : void 0);
|
|
858
|
+
const view = (p ?? "") + "\0" + (isBrowser() ? window.location.href : "");
|
|
859
|
+
if (view === this.counted) return;
|
|
860
|
+
this.counted = view;
|
|
841
861
|
this.enqueue("pageview", events.PAGEVIEW, { path: p, properties });
|
|
842
862
|
}
|
|
843
863
|
/** capture records a named product event with optional properties. Commerce
|
|
@@ -898,8 +918,8 @@ var Analytics = class {
|
|
|
898
918
|
* front door POST /v1/event, body { batch: [Event…] }. beacon=true selects the
|
|
899
919
|
* unload-safe transport. Auth is orthogonal to the wire:
|
|
900
920
|
*
|
|
901
|
-
* • publishable key set → rides
|
|
902
|
-
*
|
|
921
|
+
* • publishable key set → rides ?ingest_key=pk-… on both sends, keeping each
|
|
922
|
+
* a CORS-simple request that any origin may send.
|
|
903
923
|
* • else a bearer JWT rides Authorization (fetch only — sendBeacon cannot
|
|
904
924
|
* carry a header, so token apps fall back to keepalive fetch on unload).
|
|
905
925
|
* • else a cookie app rides same-origin credentials (beacon carries the
|
|
@@ -1022,19 +1042,35 @@ var Analytics = class {
|
|
|
1022
1042
|
}
|
|
1023
1043
|
}
|
|
1024
1044
|
};
|
|
1045
|
+
var CLIENTS = /* @__PURE__ */ Symbol.for("hanzo.event.clients");
|
|
1046
|
+
function registry() {
|
|
1047
|
+
const g = globalThis;
|
|
1048
|
+
const existing = g[CLIENTS];
|
|
1049
|
+
if (existing) return existing;
|
|
1050
|
+
const fresh = /* @__PURE__ */ new Map();
|
|
1051
|
+
g[CLIENTS] = fresh;
|
|
1052
|
+
return fresh;
|
|
1053
|
+
}
|
|
1025
1054
|
function createAnalytics(config) {
|
|
1026
|
-
return new Analytics(config);
|
|
1055
|
+
if (!isBrowser()) return new Analytics(config);
|
|
1056
|
+
const key = (config.host ?? DEFAULT_HOST) + "\0" + config.product;
|
|
1057
|
+
const clients = registry();
|
|
1058
|
+
const existing = clients.get(key);
|
|
1059
|
+
if (existing) {
|
|
1060
|
+
existing.adopt(config);
|
|
1061
|
+
return existing;
|
|
1062
|
+
}
|
|
1063
|
+
const fresh = new Analytics(config);
|
|
1064
|
+
clients.set(key, fresh);
|
|
1065
|
+
return fresh;
|
|
1027
1066
|
}
|
|
1028
1067
|
|
|
1029
1068
|
// src/react.tsx
|
|
1030
1069
|
var Ctx = react.createContext(null);
|
|
1031
1070
|
function AnalyticsProvider(props) {
|
|
1032
1071
|
const { client, config, autoPageview = true, children } = props;
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
if (config) return createAnalytics(config);
|
|
1036
|
-
throw new Error("AnalyticsProvider requires `client` or `config`");
|
|
1037
|
-
}, [client]);
|
|
1072
|
+
if (!client && !config) throw new Error("AnalyticsProvider requires `client` or `config`");
|
|
1073
|
+
const instance = client ?? createAnalytics(config);
|
|
1038
1074
|
react.useEffect(() => {
|
|
1039
1075
|
instance.init();
|
|
1040
1076
|
if (autoPageview) instance.pageview();
|