@stacksee/analytics 0.9.0 → 0.9.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.
@@ -1,9 +1,9 @@
1
1
  var f = Object.defineProperty;
2
2
  var y = (l, n, i) => n in l ? f(l, n, { enumerable: !0, configurable: !0, writable: !0, value: i }) : l[n] = i;
3
3
  var d = (l, n, i) => y(l, typeof n != "symbol" ? n + "" : n, i);
4
- import { B as p } from "../base.provider-AfFL5W_P.js";
5
- import { P as z } from "../server-DjEk1fUD.js";
6
- class v extends p {
4
+ import { B as c } from "../base.provider-AfFL5W_P.js";
5
+ import { P } from "../server-DjEk1fUD.js";
6
+ class w extends c {
7
7
  constructor(i) {
8
8
  super({ debug: i.debug, enabled: i.enabled });
9
9
  d(this, "name", "Bento-Server");
@@ -23,77 +23,110 @@ class v extends p {
23
23
  if (!((e = this.config.authentication) != null && e.secretKey) || typeof this.config.authentication.secretKey != "string")
24
24
  throw new Error("Bento requires authentication.secretKey");
25
25
  try {
26
- const { Analytics: s } = await import("../bento-node-sdk.esm-C4HG7SVz.js"), { debug: a, enabled: t, ...o } = this.config;
27
- this.client = new s(o), this.initialized = !0, this.log("Initialized successfully", {
26
+ const { Analytics: r } = await import("../bento-node-sdk.esm-CWEAoj97.js"), { debug: t, enabled: a, ...o } = this.config;
27
+ this.client = new r(o), this.initialized = !0, this.log("Initialized successfully", {
28
28
  siteUuid: this.config.siteUuid
29
29
  });
30
- } catch (s) {
30
+ } catch (r) {
31
31
  throw console.error(
32
32
  "[Bento-Server] Failed to initialize. Make sure @bentonow/bento-node-sdk is installed:",
33
- s
34
- ), s;
33
+ r
34
+ ), r;
35
35
  }
36
36
  }
37
37
  }
38
38
  identify(i, e) {
39
39
  if (!this.isEnabled() || !this.initialized || !this.client) return;
40
- const s = (e == null ? void 0 : e.email) || i;
41
- this.currentUserEmail = s;
42
- const a = e ? { ...e } : {};
43
- delete a.email, this.client.V1.addSubscriber({
44
- email: s,
45
- fields: a
46
- }).catch((t) => {
47
- console.error("[Bento-Server] Failed to identify user:", t);
48
- }), this.log("Identified user", { userId: i, email: s, traits: e });
40
+ const r = (e == null ? void 0 : e.email) || i;
41
+ if (!r || !r.includes("@")) {
42
+ this.log("Skipping identify - invalid or missing email", { userId: i, traits: e });
43
+ return;
44
+ }
45
+ this.currentUserEmail = r;
46
+ const t = e ? { ...e } : {};
47
+ delete t.email, this.client.V1.addSubscriber({
48
+ email: r,
49
+ fields: t
50
+ }).catch((a) => {
51
+ console.error("[Bento-Server] Failed to identify user:", a);
52
+ }), this.log("Identified user", { userId: i, email: r, traits: e });
49
53
  }
50
54
  async track(i, e) {
51
- var o, r, h;
55
+ var o, s, h, u;
52
56
  if (!this.isEnabled() || !this.initialized || !this.client) return;
53
- const s = ((o = e == null ? void 0 : e.user) == null ? void 0 : o.email) || this.currentUserEmail || ((r = e == null ? void 0 : e.user) == null ? void 0 : r.userId) || i.userId || "anonymous@unknown.com", a = {
57
+ const r = ((o = e == null ? void 0 : e.user) == null ? void 0 : o.email) || this.currentUserEmail || ((s = e == null ? void 0 : e.user) == null ? void 0 : s.userId) || i.userId;
58
+ if (!r || !r.includes("@")) {
59
+ console.warn(
60
+ "[Bento-Server] Skipping event - Bento requires an email address. Anonymous events are not currently supported by the Bento Node SDK. For now, use the Bento client provider for anonymous tracking. If you're using a proxy, use the hybrid pattern as described in the docs. For identified users, call identify() with a valid email before tracking events."
61
+ );
62
+ return;
63
+ }
64
+ const t = {
54
65
  ...i.properties,
55
66
  category: i.category,
56
67
  timestamp: i.timestamp || Date.now(),
57
68
  ...i.sessionId && { sessionId: i.sessionId },
58
69
  ...(e == null ? void 0 : e.page) && {
59
70
  page: {
71
+ url: e.page.url,
72
+ host: e.page.host,
60
73
  path: e.page.path,
61
74
  title: e.page.title,
62
- referrer: e.page.referrer
75
+ protocol: e.page.protocol,
76
+ referrer: e.page.referrer,
77
+ ...e.page.search && { search: e.page.search }
63
78
  }
64
79
  },
65
80
  ...(e == null ? void 0 : e.device) && { device: e.device },
66
- ...(e == null ? void 0 : e.utm) && { utm: e.utm }
67
- }, t = ((h = e == null ? void 0 : e.user) == null ? void 0 : h.traits) || {};
81
+ ...(e == null ? void 0 : e.utm) && { utm: e.utm },
82
+ site: this.config.siteUuid,
83
+ ...((h = e == null ? void 0 : e.user) == null ? void 0 : h.userId) && { visitor: e.user.userId }
84
+ }, a = ((u = e == null ? void 0 : e.user) == null ? void 0 : u.traits) || {};
68
85
  try {
69
86
  await this.client.V1.track({
70
- email: s,
87
+ email: r,
71
88
  type: `$${i.action}`,
72
- details: a,
73
- fields: t
89
+ details: t,
90
+ fields: a
74
91
  }), this.log("Tracked event", { event: i, context: e });
75
- } catch (u) {
76
- console.error("[Bento-Server] Failed to track event:", u);
92
+ } catch (p) {
93
+ console.error("[Bento-Server] Failed to track event:", p);
77
94
  }
78
95
  }
79
96
  pageView(i, e) {
80
- var o, r;
97
+ var o, s, h;
81
98
  if (!this.isEnabled() || !this.initialized || !this.client) return;
82
- const s = ((o = e == null ? void 0 : e.user) == null ? void 0 : o.email) || this.currentUserEmail || "anonymous@unknown.com", a = {
99
+ const r = ((o = e == null ? void 0 : e.user) == null ? void 0 : o.email) || this.currentUserEmail;
100
+ if (!r || !r.includes("@")) {
101
+ console.warn(
102
+ "[Bento-Server] Skipping pageView - Bento requires an email address. Anonymous events are not currently supported by the Bento Node SDK. For now, use the Bento client provider for anonymous tracking. If you're using a proxy, use the hybrid pattern as described in the docs. For identified users, call identify() with a valid email before tracking events."
103
+ );
104
+ return;
105
+ }
106
+ const t = {
83
107
  ...i,
108
+ date: (/* @__PURE__ */ new Date()).toISOString(),
84
109
  ...(e == null ? void 0 : e.page) && {
85
- path: e.page.path,
86
- title: e.page.title,
87
- referrer: e.page.referrer
88
- }
89
- }, t = ((r = e == null ? void 0 : e.user) == null ? void 0 : r.traits) || {};
110
+ page: {
111
+ url: e.page.url,
112
+ host: e.page.host,
113
+ path: e.page.path,
114
+ title: e.page.title,
115
+ protocol: e.page.protocol,
116
+ referrer: e.page.referrer,
117
+ ...e.page.search && { search: e.page.search }
118
+ }
119
+ },
120
+ site: this.config.siteUuid,
121
+ ...((s = e == null ? void 0 : e.user) == null ? void 0 : s.userId) && { visitor: e.user.userId }
122
+ }, a = ((h = e == null ? void 0 : e.user) == null ? void 0 : h.traits) || {};
90
123
  this.client.V1.track({
91
- email: s,
124
+ email: r,
92
125
  type: "$view",
93
- details: a,
94
- fields: t
95
- }).catch((h) => {
96
- console.error("[Bento-Server] Failed to track page view:", h);
126
+ details: t,
127
+ fields: a
128
+ }).catch((u) => {
129
+ console.error("[Bento-Server] Failed to track page view:", u);
97
130
  }), this.log("Tracked page view", { properties: i, context: e });
98
131
  }
99
132
  async reset() {
@@ -103,7 +136,7 @@ class v extends p {
103
136
  this.client = void 0, this.initialized = !1, this.log("Shutdown complete");
104
137
  }
105
138
  }
106
- class E extends p {
139
+ class k extends c {
107
140
  constructor(i) {
108
141
  super({ debug: i.debug, enabled: i.enabled });
109
142
  d(this, "name", "Pirsch-Server");
@@ -119,8 +152,8 @@ class E extends p {
119
152
  if (!this.config.clientSecret || typeof this.config.clientSecret != "string")
120
153
  throw new Error("Pirsch requires a clientSecret (or access key)");
121
154
  try {
122
- const { Pirsch: i } = await import("../index-bgxxv-IJ.js").then((t) => t.i), { debug: e, enabled: s, ...a } = this.config;
123
- this.client = new i(a), this.initialized = !0, this.log("Initialized successfully", {
155
+ const { Pirsch: i } = await import("../index-zS7gy63J.js").then((a) => a.i), { debug: e, enabled: r, ...t } = this.config;
156
+ this.client = new i(t), this.initialized = !0, this.log("Initialized successfully", {
124
157
  hostname: this.config.hostname
125
158
  });
126
159
  } catch (i) {
@@ -133,37 +166,37 @@ class E extends p {
133
166
  }
134
167
  identify(i, e) {
135
168
  if (!this.isEnabled() || !this.initialized || !this.client) return;
136
- const s = {
169
+ const r = {
137
170
  url: "https://identify",
138
171
  ip: "0.0.0.0",
139
172
  user_agent: "analytics-library"
140
- }, a = {
173
+ }, t = {
141
174
  userId: i,
142
175
  ...e && Object.fromEntries(
143
176
  Object.entries(e).filter(
144
- ([, t]) => typeof t == "string" || typeof t == "number" || typeof t == "boolean"
177
+ ([, a]) => typeof a == "string" || typeof a == "number" || typeof a == "boolean"
145
178
  )
146
179
  )
147
180
  };
148
- this.client.event("user_identified", s, 0, a).catch((t) => {
149
- console.error("[Pirsch-Server] Failed to track identify event:", t);
181
+ this.client.event("user_identified", r, 0, t).catch((a) => {
182
+ console.error("[Pirsch-Server] Failed to track identify event:", a);
150
183
  }), this.log("Identified user via event", { userId: i, traits: e });
151
184
  }
152
185
  async track(i, e) {
153
- var o, r, h, u;
186
+ var o, s, h, u;
154
187
  if (!this.isEnabled() || !this.initialized || !this.client) return;
155
- const s = {
188
+ const r = {
156
189
  url: ((o = e == null ? void 0 : e.page) == null ? void 0 : o.path) || "https://event",
157
190
  ip: "0.0.0.0",
158
191
  // Server-side should provide real IP if available
159
192
  user_agent: "analytics-library",
160
193
  // Server-side should provide real UA if available
161
- ...((r = e == null ? void 0 : e.page) == null ? void 0 : r.title) && { title: e.page.title },
194
+ ...((s = e == null ? void 0 : e.page) == null ? void 0 : s.title) && { title: e.page.title },
162
195
  ...((h = e == null ? void 0 : e.page) == null ? void 0 : h.referrer) && { referrer: e.page.referrer }
163
- }, t = {
196
+ }, a = {
164
197
  ...Object.fromEntries(
165
198
  Object.entries(i.properties).filter(
166
- ([, c]) => typeof c == "string" || typeof c == "number" || typeof c == "boolean"
199
+ ([, p]) => typeof p == "string" || typeof p == "number" || typeof p == "boolean"
167
200
  )
168
201
  ),
169
202
  category: i.category,
@@ -173,32 +206,32 @@ class E extends p {
173
206
  ...((u = e == null ? void 0 : e.user) == null ? void 0 : u.email) && { user_email: e.user.email }
174
207
  };
175
208
  try {
176
- await this.client.event(i.action, s, 0, t), this.log("Tracked event", { event: i, context: e });
177
- } catch (c) {
178
- console.error("[Pirsch-Server] Failed to track event:", c);
209
+ await this.client.event(i.action, r, 0, a), this.log("Tracked event", { event: i, context: e });
210
+ } catch (p) {
211
+ console.error("[Pirsch-Server] Failed to track event:", p);
179
212
  }
180
213
  }
181
214
  pageView(i, e) {
182
- var a, t, o;
215
+ var t, a, o;
183
216
  if (!this.isEnabled() || !this.initialized || !this.client) return;
184
- const s = {
185
- url: ((a = e == null ? void 0 : e.page) == null ? void 0 : a.path) || "https://pageview",
217
+ const r = {
218
+ url: ((t = e == null ? void 0 : e.page) == null ? void 0 : t.path) || "https://pageview",
186
219
  ip: "0.0.0.0",
187
220
  // Server-side should provide real IP if available
188
221
  user_agent: "analytics-library",
189
222
  // Server-side should provide real UA if available
190
- ...((t = e == null ? void 0 : e.page) == null ? void 0 : t.title) && { title: e.page.title },
223
+ ...((a = e == null ? void 0 : e.page) == null ? void 0 : a.title) && { title: e.page.title },
191
224
  ...((o = e == null ? void 0 : e.page) == null ? void 0 : o.referrer) && { referrer: e.page.referrer },
192
225
  ...i && {
193
226
  tags: Object.fromEntries(
194
227
  Object.entries(i).filter(
195
- ([, r]) => typeof r == "string" || typeof r == "number" || typeof r == "boolean"
228
+ ([, s]) => typeof s == "string" || typeof s == "number" || typeof s == "boolean"
196
229
  )
197
230
  )
198
231
  }
199
232
  };
200
- this.client.hit(s).catch((r) => {
201
- console.error("[Pirsch-Server] Failed to track page view:", r);
233
+ this.client.hit(r).catch((s) => {
234
+ console.error("[Pirsch-Server] Failed to track page view:", s);
202
235
  }), this.log("Tracked page view", { properties: i, context: e });
203
236
  }
204
237
  async reset() {
@@ -217,65 +250,65 @@ class E extends p {
217
250
  }
218
251
  }
219
252
  async function g(l, n, i) {
220
- var e, s;
253
+ var e, r;
221
254
  try {
222
- const a = await l.json();
223
- if (!a.events || !Array.isArray(a.events))
255
+ const t = await l.json();
256
+ if (!t.events || !Array.isArray(t.events))
224
257
  throw new Error("Invalid payload: missing events array");
225
- const t = i != null && i.extractIp ? i.extractIp(l) : m(l), o = i != null && i.enrichContext ? i.enrichContext(l) : {};
226
- for (const r of a.events)
258
+ const a = i != null && i.extractIp ? i.extractIp(l) : b(l), o = i != null && i.enrichContext ? i.enrichContext(l) : {};
259
+ for (const s of t.events)
227
260
  try {
228
- switch (r.type) {
261
+ switch (s.type) {
229
262
  case "track": {
230
263
  const h = {
231
- ...r.context,
264
+ ...s.context,
232
265
  ...o,
233
266
  device: {
234
- ...(e = r.context) == null ? void 0 : e.device,
267
+ ...(e = s.context) == null ? void 0 : e.device,
235
268
  // Add IP (using type assertion for extended fields)
236
269
  // biome-ignore lint/suspicious/noExplicitAny: IP field not in base device type
237
- ...t ? { ip: t } : {}
270
+ ...a ? { ip: a } : {}
238
271
  }
239
272
  };
240
- await n.track(r.event.action, r.event.properties, {
241
- userId: r.event.userId,
242
- sessionId: r.event.sessionId,
273
+ await n.track(s.event.action, s.event.properties, {
274
+ userId: s.event.userId,
275
+ sessionId: s.event.sessionId,
243
276
  // biome-ignore lint/suspicious/noExplicitAny: Generic context forwarding requires type assertion
244
277
  context: h
245
278
  });
246
279
  break;
247
280
  }
248
281
  case "identify": {
249
- n.identify(r.userId, r.traits);
282
+ n.identify(s.userId, s.traits);
250
283
  break;
251
284
  }
252
285
  case "pageView": {
253
286
  const h = {
254
- ...r.context,
287
+ ...s.context,
255
288
  ...o,
256
289
  device: {
257
- ...(s = r.context) == null ? void 0 : s.device,
290
+ ...(r = s.context) == null ? void 0 : r.device,
258
291
  // biome-ignore lint/suspicious/noExplicitAny: IP field not in base device type
259
292
  // Add IP (using type assertion for extended fields)
260
- ...t ? { ip: t } : {}
293
+ ...a ? { ip: a } : {}
261
294
  }
262
295
  };
263
- n.pageView(r.properties, h);
296
+ n.pageView(s.properties, h);
264
297
  break;
265
298
  }
266
299
  case "reset":
267
300
  break;
268
301
  default:
269
- console.warn("[Proxy] Unknown event type:", r);
302
+ console.warn("[Proxy] Unknown event type:", s);
270
303
  }
271
304
  } catch (h) {
272
305
  i != null && i.onError ? i.onError(h) : console.error("[Proxy] Failed to process event:", h);
273
306
  }
274
- } catch (a) {
275
- throw i != null && i.onError ? i.onError(a) : console.error("[Proxy] Failed to ingest events:", a), a;
307
+ } catch (t) {
308
+ throw i != null && i.onError ? i.onError(t) : console.error("[Proxy] Failed to ingest events:", t), t;
276
309
  }
277
310
  }
278
- function m(l) {
311
+ function b(l) {
279
312
  var i;
280
313
  const n = [
281
314
  "x-forwarded-for",
@@ -286,12 +319,12 @@ function m(l) {
286
319
  "x-cluster-client-ip"
287
320
  ];
288
321
  for (const e of n) {
289
- const s = l.headers.get(e);
290
- if (s)
291
- return (i = s.split(",")[0]) == null ? void 0 : i.trim();
322
+ const r = l.headers.get(e);
323
+ if (r)
324
+ return (i = r.split(",")[0]) == null ? void 0 : i.trim();
292
325
  }
293
326
  }
294
- function k(l, n) {
327
+ function S(l, n) {
295
328
  return async (i) => {
296
329
  try {
297
330
  return await g(i, l, n), new Response("OK", { status: 200 });
@@ -301,10 +334,10 @@ function k(l, n) {
301
334
  };
302
335
  }
303
336
  export {
304
- p as BaseAnalyticsProvider,
305
- v as BentoServerProvider,
306
- E as PirschServerProvider,
307
- z as PostHogServerProvider,
308
- k as createProxyHandler,
337
+ c as BaseAnalyticsProvider,
338
+ w as BentoServerProvider,
339
+ k as PirschServerProvider,
340
+ P as PostHogServerProvider,
341
+ S as createProxyHandler,
309
342
  g as ingestProxyEvents
310
343
  };
@@ -1,4 +1,4 @@
1
- import { r as O, a as P, b as E } from "./axios-gULqh8dv.js";
1
+ import { r as O, a as P, b as E } from "./axios-0_CwElpL.js";
2
2
  function j(f, p) {
3
3
  for (var d = 0; d < p.length; d++) {
4
4
  const o = p[d];
@@ -19,19 +19,19 @@ var r = {}, w;
19
19
  function C() {
20
20
  if (w) return r;
21
21
  w = 1;
22
- var f = r && r.__createBinding || (Object.create ? function(c, e, t, n) {
22
+ var f = r && r.__createBinding || (Object.create ? (function(c, e, t, n) {
23
23
  n === void 0 && (n = t);
24
24
  var i = Object.getOwnPropertyDescriptor(e, t);
25
25
  (!i || ("get" in i ? !e.__esModule : i.writable || i.configurable)) && (i = { enumerable: !0, get: function() {
26
26
  return e[t];
27
27
  } }), Object.defineProperty(c, n, i);
28
- } : function(c, e, t, n) {
28
+ }) : (function(c, e, t, n) {
29
29
  n === void 0 && (n = t), c[n] = e[t];
30
- }), p = r && r.__setModuleDefault || (Object.create ? function(c, e) {
30
+ })), p = r && r.__setModuleDefault || (Object.create ? (function(c, e) {
31
31
  Object.defineProperty(c, "default", { enumerable: !0, value: e });
32
- } : function(c, e) {
32
+ }) : function(c, e) {
33
33
  c.default = e;
34
- }), d = r && r.__importStar || /* @__PURE__ */ function() {
34
+ }), d = r && r.__importStar || /* @__PURE__ */ (function() {
35
35
  var c = function(e) {
36
36
  return c = Object.getOwnPropertyNames || function(t) {
37
37
  var n = [];
@@ -45,7 +45,7 @@ function C() {
45
45
  if (e != null) for (var n = c(e), i = 0; i < n.length; i++) n[i] !== "default" && f(t, e, n[i]);
46
46
  return p(t, e), t;
47
47
  };
48
- }(), o = r && r.__awaiter || function(c, e, t, n) {
48
+ })(), o = r && r.__awaiter || function(c, e, t, n) {
49
49
  function i(s) {
50
50
  return s instanceof t ? s : new t(function(l) {
51
51
  l(s);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stacksee/analytics",
3
- "version": "0.9.0",
3
+ "version": "0.9.4",
4
4
  "description": "A highly typed, provider-agnostic analytics library for TypeScript applications",
5
5
  "type": "module",
6
6
  "exports": {
@@ -36,6 +36,8 @@
36
36
  "analytics",
37
37
  "typescript",
38
38
  "posthog",
39
+ "bento",
40
+ "pirsch",
39
41
  "tracking",
40
42
  "events",
41
43
  "type-safe"
@@ -70,14 +72,12 @@
70
72
  "pnpm": ">=9.0.0",
71
73
  "node": ">=20"
72
74
  },
73
- "dependencies": {
74
- "@tailwindcss/vite": "^4.1.16",
75
- "tailwindcss": "^4.1.16"
76
- },
77
75
  "scripts": {
78
76
  "test": "vitest run",
79
77
  "test:watch": "vitest",
80
78
  "build": "vite build",
79
+ "dev": "pnpm --filter @stacksee/docs dev",
80
+ "build:docs": "pnpm --filter @stacksee/docs build",
81
81
  "deploy": "npm publish",
82
82
  "typecheck": "tsc --noEmit",
83
83
  "ci:publish": "pnpm build && changeset publish",