@stacksee/analytics 0.13.1 → 0.13.2

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.
@@ -130,7 +130,7 @@ export declare class ServerAnalytics<TEventMap extends Record<string, Record<str
130
130
  * }
131
131
  * ```
132
132
  */
133
- identify(userId: string, traits?: Record<string, unknown>): void;
133
+ identify(userId: string, traits?: Record<string, unknown>): Promise<void>;
134
134
  /**
135
135
  * Tracks a custom event with properties and optional context.
136
136
  *
@@ -320,7 +320,7 @@ export declare class ServerAnalytics<TEventMap extends Record<string, Record<str
320
320
  */
321
321
  pageView(properties?: Record<string, unknown>, options?: {
322
322
  context?: EventContext<TUserTraits>;
323
- }): void;
323
+ }): Promise<void>;
324
324
  /**
325
325
  * Tracks when a user leaves a page from the server side.
326
326
  *
@@ -50,9 +50,9 @@ export declare class BentoServerProvider extends BaseAnalyticsProvider {
50
50
  private currentUserEmail?;
51
51
  constructor(config: BentoServerConfig);
52
52
  initialize(): Promise<void>;
53
- identify(userId: string, traits?: Record<string, unknown>): void;
53
+ identify(userId: string, traits?: Record<string, unknown>): Promise<void>;
54
54
  track(event: BaseEvent, context?: EventContext): Promise<void>;
55
- pageView(properties?: Record<string, unknown>, context?: EventContext): void;
55
+ pageView(properties?: Record<string, unknown>, context?: EventContext): Promise<void>;
56
56
  reset(): Promise<void>;
57
57
  shutdown(): Promise<void>;
58
58
  }
@@ -66,9 +66,9 @@ export declare class EmitKitServerProvider extends BaseAnalyticsProvider {
66
66
  private currentUserEmail?;
67
67
  constructor(config: EmitKitServerConfig);
68
68
  initialize(): Promise<void>;
69
- identify(userId: string, traits?: Record<string, unknown>): void;
69
+ identify(userId: string, traits?: Record<string, unknown>): Promise<void>;
70
70
  track(event: BaseEvent, context?: EventContext): Promise<void>;
71
- pageView(properties?: Record<string, unknown>, context?: EventContext): void;
71
+ pageView(properties?: Record<string, unknown>, context?: EventContext): Promise<void>;
72
72
  reset(): Promise<void>;
73
73
  shutdown(): Promise<void>;
74
74
  /**
@@ -74,9 +74,9 @@ export declare class PirschServerProvider extends BaseAnalyticsProvider {
74
74
  * Build a Pirsch hit from context
75
75
  */
76
76
  private buildHit;
77
- identify(userId: string, traits?: Record<string, unknown>): void;
77
+ identify(userId: string, traits?: Record<string, unknown>): Promise<void>;
78
78
  track(event: BaseEvent, context?: EventContext): Promise<void>;
79
- pageView(properties?: Record<string, unknown>, context?: EventContext): void;
79
+ pageView(properties?: Record<string, unknown>, context?: EventContext): Promise<void>;
80
80
  reset(): Promise<void>;
81
81
  shutdown(): Promise<void>;
82
82
  }
@@ -23,8 +23,8 @@ class O extends y {
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: r } = await import("../bento-node-sdk.esm-CT4oS3Kp.js"), { debug: s, enabled: a, ...t } = this.config;
27
- this.client = new r(t), this.initialized = !0, this.log("Initialized successfully", {
26
+ const { Analytics: r } = await import("../bento-node-sdk.esm-CT4oS3Kp.js"), { debug: s, enabled: n, ...a } = this.config;
27
+ this.client = new r(a), this.initialized = !0, this.log("Initialized successfully", {
28
28
  siteUuid: this.config.siteUuid
29
29
  });
30
30
  } catch (r) {
@@ -35,7 +35,7 @@ class O extends y {
35
35
  }
36
36
  }
37
37
  }
38
- identify(i, e) {
38
+ async identify(i, e) {
39
39
  if (!this.isEnabled() || !this.initialized || !this.client) return;
40
40
  const r = (e == null ? void 0 : e.email) || i;
41
41
  if (!r || !r.includes("@")) {
@@ -47,17 +47,17 @@ class O extends y {
47
47
  }
48
48
  this.currentUserEmail = r;
49
49
  const s = e ? { ...e } : {};
50
- s.email = void 0, this.client.V1.addSubscriber({
51
- email: r,
52
- fields: s
53
- }).catch((a) => {
54
- console.error("[Bento-Server] Failed to identify user:", a);
55
- }), this.log("Identified user", { userId: i, email: r, traits: e });
50
+ s.email = void 0;
51
+ try {
52
+ await this.client.V1.addSubscriber({ email: r, fields: s }), this.log("Identified user", { userId: i, email: r, traits: e });
53
+ } catch (n) {
54
+ console.error("[Bento-Server] Failed to identify user:", n);
55
+ }
56
56
  }
57
57
  async track(i, e) {
58
- var t, h, l, n;
58
+ var a, h, l, o;
59
59
  if (!this.isEnabled() || !this.initialized || !this.client) return;
60
- const r = ((t = e == null ? void 0 : e.user) == null ? void 0 : t.email) || this.currentUserEmail || ((h = e == null ? void 0 : e.user) == null ? void 0 : h.userId) || i.userId;
60
+ const r = ((a = e == null ? void 0 : e.user) == null ? void 0 : a.email) || this.currentUserEmail || ((h = e == null ? void 0 : e.user) == null ? void 0 : h.userId) || i.userId;
61
61
  if (!r || !r.includes("@")) {
62
62
  console.warn(
63
63
  "[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."
@@ -84,22 +84,22 @@ class O extends y {
84
84
  ...(e == null ? void 0 : e.utm) && { utm: e.utm },
85
85
  site: this.config.siteUuid,
86
86
  ...((l = e == null ? void 0 : e.user) == null ? void 0 : l.userId) && { visitor: e.user.userId }
87
- }, a = ((n = e == null ? void 0 : e.user) == null ? void 0 : n.traits) || {};
87
+ }, n = ((o = e == null ? void 0 : e.user) == null ? void 0 : o.traits) || {};
88
88
  try {
89
89
  await this.client.V1.track({
90
90
  email: r,
91
91
  type: `$${i.action}`,
92
92
  details: s,
93
- fields: a
93
+ fields: n
94
94
  }), this.log("Tracked event", { event: i, context: e });
95
- } catch (o) {
96
- console.error("[Bento-Server] Failed to track event:", o);
95
+ } catch (t) {
96
+ console.error("[Bento-Server] Failed to track event:", t);
97
97
  }
98
98
  }
99
- pageView(i, e) {
100
- var t, h, l;
99
+ async pageView(i, e) {
100
+ var a, h, l;
101
101
  if (!this.isEnabled() || !this.initialized || !this.client) return;
102
- const r = ((t = e == null ? void 0 : e.user) == null ? void 0 : t.email) || this.currentUserEmail;
102
+ const r = ((a = e == null ? void 0 : e.user) == null ? void 0 : a.email) || this.currentUserEmail;
103
103
  if (!r || !r.includes("@")) {
104
104
  console.warn(
105
105
  "[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."
@@ -122,15 +122,12 @@ class O extends y {
122
122
  },
123
123
  site: this.config.siteUuid,
124
124
  ...((h = e == null ? void 0 : e.user) == null ? void 0 : h.userId) && { visitor: e.user.userId }
125
- }, a = ((l = e == null ? void 0 : e.user) == null ? void 0 : l.traits) || {};
126
- this.client.V1.track({
127
- email: r,
128
- type: "$view",
129
- details: s,
130
- fields: a
131
- }).catch((n) => {
132
- console.error("[Bento-Server] Failed to track page view:", n);
133
- }), this.log("Tracked page view", { properties: i, context: e });
125
+ }, n = ((l = e == null ? void 0 : e.user) == null ? void 0 : l.traits) || {};
126
+ try {
127
+ await this.client.V1.track({ email: r, type: "$view", details: s, fields: n }), this.log("Tracked page view", { properties: i, context: e });
128
+ } catch (o) {
129
+ console.error("[Bento-Server] Failed to track page view:", o);
130
+ }
134
131
  }
135
132
  async reset() {
136
133
  !this.isEnabled() || !this.initialized || !this.client || (this.currentUserEmail = void 0, this.log("Reset user session"));
@@ -171,14 +168,14 @@ class j extends y {
171
168
  * Fetch with timeout using AbortController
172
169
  */
173
170
  async fetchWithTimeout(i, e, r) {
174
- const s = new AbortController(), a = r ?? this.config.timeout ?? K, t = setTimeout(() => s.abort(), a);
171
+ const s = new AbortController(), n = r ?? this.config.timeout ?? K, a = setTimeout(() => s.abort(), n);
175
172
  try {
176
173
  return await fetch(i, {
177
174
  ...e,
178
175
  signal: s.signal
179
176
  });
180
177
  } finally {
181
- clearTimeout(t);
178
+ clearTimeout(a);
182
179
  }
183
180
  }
184
181
  /**
@@ -217,7 +214,7 @@ class j extends y {
217
214
  async request(i, e, r = !0) {
218
215
  const s = await this.ensureToken();
219
216
  try {
220
- const a = await this.fetchWithTimeout(
217
+ const n = await this.fetchWithTimeout(
221
218
  `${T}${i}`,
222
219
  {
223
220
  method: "POST",
@@ -228,16 +225,16 @@ class j extends y {
228
225
  body: JSON.stringify(e)
229
226
  }
230
227
  );
231
- if (a.status === 401 && r && !this.isAccessKey)
228
+ if (n.status === 401 && r && !this.isAccessKey)
232
229
  return this.accessToken = "", this.tokenExpiresAt = null, this.request(i, e, !1);
233
- if (!a.ok) {
234
- const t = await a.text();
235
- throw new Error(`Pirsch API error: ${a.status} ${t}`);
230
+ if (!n.ok) {
231
+ const a = await n.text();
232
+ throw new Error(`Pirsch API error: ${n.status} ${a}`);
236
233
  }
237
- } catch (a) {
238
- throw a instanceof Error && a.name === "AbortError" ? new Error(
234
+ } catch (n) {
235
+ throw n instanceof Error && n.name === "AbortError" ? new Error(
239
236
  `Pirsch request timeout after ${this.config.timeout ?? K}ms`
240
- ) : a;
237
+ ) : n;
241
238
  }
242
239
  }
243
240
  /**
@@ -265,10 +262,10 @@ class j extends y {
265
262
  * Build a Pirsch hit from context
266
263
  */
267
264
  buildHit(i) {
268
- var t, h, l, n, o, p, g, f, m, v, w, b, k, E, _, S, I, A, z, P;
269
- const e = i, r = ((t = e == null ? void 0 : e.device) == null ? void 0 : t.ip) || ((h = e == null ? void 0 : e.server) == null ? void 0 : h.ip), s = ((l = e == null ? void 0 : e.server) == null ? void 0 : l.userAgent) || ((n = e == null ? void 0 : e.device) == null ? void 0 : n.userAgent);
265
+ var a, h, l, o, t, p, g, f, m, v, w, b, k, E, _, S, I, A, z, P;
266
+ const e = i, r = ((a = e == null ? void 0 : e.device) == null ? void 0 : a.ip) || ((h = e == null ? void 0 : e.server) == null ? void 0 : h.ip), s = ((l = e == null ? void 0 : e.server) == null ? void 0 : l.userAgent) || ((o = e == null ? void 0 : e.device) == null ? void 0 : o.userAgent);
270
267
  return !r || !s ? null : {
271
- url: ((o = i == null ? void 0 : i.page) == null ? void 0 : o.url) || ((p = i == null ? void 0 : i.page) != null && p.protocol && ((g = i == null ? void 0 : i.page) != null && g.host) && ((f = i == null ? void 0 : i.page) != null && f.path) ? `${i.page.protocol}://${i.page.host}${i.page.path}` : (m = i == null ? void 0 : i.page) != null && m.path ? `https://${this.config.hostname}${i.page.path}` : `https://${this.config.hostname}`),
268
+ url: ((t = i == null ? void 0 : i.page) == null ? void 0 : t.url) || ((p = i == null ? void 0 : i.page) != null && p.protocol && ((g = i == null ? void 0 : i.page) != null && g.host) && ((f = i == null ? void 0 : i.page) != null && f.path) ? `${i.page.protocol}://${i.page.host}${i.page.path}` : (m = i == null ? void 0 : i.page) != null && m.path ? `https://${this.config.hostname}${i.page.path}` : `https://${this.config.hostname}`),
272
269
  ip: r,
273
270
  user_agent: s,
274
271
  ...((v = i == null ? void 0 : i.page) == null ? void 0 : v.title) && { title: i.page.title },
@@ -292,7 +289,7 @@ class j extends y {
292
289
  ...this.config.disableBotFilter && { disable_bot_filter: !0 }
293
290
  };
294
291
  }
295
- identify(i, e) {
292
+ async identify(i, e) {
296
293
  if (!this.isEnabled() || !this.initialized) return;
297
294
  const r = {
298
295
  url: `https://${this.config.hostname}/identify`,
@@ -302,7 +299,7 @@ class j extends y {
302
299
  }, s = this.toStringRecord({
303
300
  userId: i,
304
301
  ...e
305
- }), a = {
302
+ }), n = {
306
303
  ...r,
307
304
  event_name: "user_identified",
308
305
  event_duration: 0,
@@ -310,12 +307,14 @@ class j extends y {
310
307
  non_interactive: !0
311
308
  // Synthetic event shouldn't affect bounce rate
312
309
  };
313
- this.request("/api/v1/event", a).catch((t) => {
314
- console.error("[Pirsch-Server] Failed to track identify event:", t);
315
- }), this.log("Identified user via event", { userId: i, traits: e });
310
+ try {
311
+ await this.request("/api/v1/event", n), this.log("Identified user via event", { userId: i, traits: e });
312
+ } catch (a) {
313
+ console.error("[Pirsch-Server] Failed to track identify event:", a);
314
+ }
316
315
  }
317
316
  async track(i, e) {
318
- var h, l, n, o;
317
+ var h, l, o, t;
319
318
  if (!this.isEnabled() || !this.initialized) return;
320
319
  const r = this.buildHit(e);
321
320
  if (!r) {
@@ -332,21 +331,21 @@ class j extends y {
332
331
  ...i.sessionId && { sessionId: i.sessionId },
333
332
  ...((h = e == null ? void 0 : e.user) == null ? void 0 : h.email) && { user_email: e.user.email },
334
333
  ...((l = e == null ? void 0 : e.device) == null ? void 0 : l.timezone) && { timezone: e.device.timezone },
335
- ...((n = e == null ? void 0 : e.device) == null ? void 0 : n.browser) && { browser: e.device.browser }
336
- }), a = ((o = i.properties) == null ? void 0 : o.non_interactive) === !0, t = {
334
+ ...((o = e == null ? void 0 : e.device) == null ? void 0 : o.browser) && { browser: e.device.browser }
335
+ }), n = ((t = i.properties) == null ? void 0 : t.non_interactive) === !0, a = {
337
336
  ...r,
338
337
  event_name: i.action,
339
338
  event_duration: 0,
340
339
  event_meta: s,
341
- ...a && { non_interactive: !0 }
340
+ ...n && { non_interactive: !0 }
342
341
  };
343
342
  try {
344
- await this.request("/api/v1/event", t), this.log("Tracked event", { event: i.action });
343
+ await this.request("/api/v1/event", a), this.log("Tracked event", { event: i.action });
345
344
  } catch (p) {
346
345
  console.error("[Pirsch-Server] Failed to track event:", p);
347
346
  }
348
347
  }
349
- pageView(i, e) {
348
+ async pageView(i, e) {
350
349
  var s;
351
350
  if (!this.isEnabled() || !this.initialized) return;
352
351
  const r = this.buildHit(e);
@@ -354,9 +353,12 @@ class j extends y {
354
353
  this.log("Skipping pageView - missing required IP or user-agent");
355
354
  return;
356
355
  }
357
- i && Object.keys(i).length > 0 && (r.tags = this.filterScalars(i)), this.request("/api/v1/hit", r).catch((a) => {
358
- console.error("[Pirsch-Server] Failed to track page view:", a);
359
- }), this.log("Tracked page view", { path: (s = e == null ? void 0 : e.page) == null ? void 0 : s.path });
356
+ i && Object.keys(i).length > 0 && (r.tags = this.filterScalars(i));
357
+ try {
358
+ await this.request("/api/v1/hit", r), this.log("Tracked page view", { path: (s = e == null ? void 0 : e.page) == null ? void 0 : s.path });
359
+ } catch (n) {
360
+ console.error("[Pirsch-Server] Failed to track page view:", n);
361
+ }
360
362
  }
361
363
  async reset() {
362
364
  if (!this.isEnabled() || !this.initialized) return;
@@ -412,37 +414,39 @@ class N extends y {
412
414
  }
413
415
  }
414
416
  }
415
- identify(i, e) {
417
+ async identify(i, e) {
418
+ var n, a, h, l, o;
416
419
  if (!this.isEnabled() || !this.initialized || !this.client) return;
417
420
  this.currentUserId = i;
418
421
  const r = (e == null ? void 0 : e.email) || i;
419
422
  r != null && r.includes("@") && (this.currentUserEmail = r);
420
423
  const s = [];
421
- i && s.push(i), r && r !== i && s.push(r), e != null && e.username && typeof e.username == "string" && s.push(e.username), this.client.identify({
422
- user_id: i,
423
- properties: e || {},
424
- aliases: s.length > 0 ? s : void 0
425
- }).then((a) => {
426
- var t, h, l, n, o;
424
+ i && s.push(i), r && r !== i && s.push(r), e != null && e.username && typeof e.username == "string" && s.push(e.username);
425
+ try {
426
+ const t = await this.client.identify({
427
+ user_id: i,
428
+ properties: e || {},
429
+ aliases: s.length > 0 ? s : void 0
430
+ });
427
431
  this.log("Identified user", {
428
432
  userId: i,
429
433
  email: r,
430
- identityId: a.data.id,
431
- aliasesCreated: ((h = (t = a.data.aliases) == null ? void 0 : t.created) == null ? void 0 : h.length) || 0,
432
- aliasesFailed: ((n = (l = a.data.aliases) == null ? void 0 : l.failed) == null ? void 0 : n.length) || 0
433
- }), (o = a.data.aliases) != null && o.failed && a.data.aliases.failed.length > 0 && console.warn(
434
+ identityId: t.data.id,
435
+ aliasesCreated: ((a = (n = t.data.aliases) == null ? void 0 : n.created) == null ? void 0 : a.length) || 0,
436
+ aliasesFailed: ((l = (h = t.data.aliases) == null ? void 0 : h.failed) == null ? void 0 : l.length) || 0
437
+ }), (o = t.data.aliases) != null && o.failed && t.data.aliases.failed.length > 0 && console.warn(
434
438
  "[EmitKit-Server] Some aliases failed to create:",
435
- a.data.aliases.failed
439
+ t.data.aliases.failed
436
440
  );
437
- }).catch((a) => {
438
- console.error("[EmitKit-Server] Failed to identify user:", a);
439
- });
441
+ } catch (t) {
442
+ console.error("[EmitKit-Server] Failed to identify user:", t);
443
+ }
440
444
  }
441
445
  async track(i, e) {
442
- var o, p;
446
+ var t, p;
443
447
  if (!this.isEnabled() || !this.initialized || !this.client) return;
444
- const r = ((o = e == null ? void 0 : e.user) == null ? void 0 : o.email) || ((p = e == null ? void 0 : e.user) == null ? void 0 : p.userId) || i.userId || this.currentUserEmail || this.currentUserId, s = this.formatEventTitle(i.action), { __emitkit_channel: a, ...t } = i.properties || {}, h = {
445
- ...t,
448
+ const r = ((t = e == null ? void 0 : e.user) == null ? void 0 : t.email) || ((p = e == null ? void 0 : e.user) == null ? void 0 : p.userId) || i.userId || this.currentUserEmail || this.currentUserId, s = this.formatEventTitle(i.action), { __emitkit_channel: n, ...a } = i.properties || {}, h = {
449
+ ...a,
446
450
  category: i.category,
447
451
  timestamp: i.timestamp || Date.now(),
448
452
  ...i.sessionId && { sessionId: i.sessionId },
@@ -461,11 +465,11 @@ class N extends y {
461
465
  ...(e == null ? void 0 : e.utm) && { utm: e.utm },
462
466
  ...(e == null ? void 0 : e.server) && { server: e.server }
463
467
  }, l = [];
464
- i.category && l.push(i.category), t != null && t.tags && Array.isArray(t.tags) && t.tags.every((g) => typeof g == "string") && l.push(...t.tags);
465
- const n = this.resolveChannelName(i);
468
+ i.category && l.push(i.category), a != null && a.tags && Array.isArray(a.tags) && a.tags.every((g) => typeof g == "string") && l.push(...a.tags);
469
+ const o = this.resolveChannelName(i);
466
470
  try {
467
471
  const g = await this.client.events.create({
468
- channelName: n,
472
+ channelName: o,
469
473
  title: s,
470
474
  description: this.getEventDescription(i, e),
471
475
  icon: this.getEventIcon(i.category),
@@ -480,17 +484,17 @@ class N extends y {
480
484
  eventId: g.data.id,
481
485
  action: i.action,
482
486
  userId: r,
483
- channelName: n
487
+ channelName: o
484
488
  });
485
489
  } catch (g) {
486
490
  throw console.error("[EmitKit-Server] Failed to track event:", g), g;
487
491
  }
488
492
  }
489
- pageView(i, e) {
490
- var n, o, p;
493
+ async pageView(i, e) {
494
+ var o, t, p, g;
491
495
  if (!this.isEnabled() || !this.initialized || !this.client) return;
492
- const r = ((n = e == null ? void 0 : e.user) == null ? void 0 : n.email) || ((o = e == null ? void 0 : e.user) == null ? void 0 : o.userId) || this.currentUserEmail || this.currentUserId, { __emitkit_channel: s, ...a } = i || {}, t = {
493
- ...a,
496
+ const r = ((o = e == null ? void 0 : e.user) == null ? void 0 : o.email) || ((t = e == null ? void 0 : e.user) == null ? void 0 : t.userId) || this.currentUserEmail || this.currentUserId, { __emitkit_channel: s, ...n } = i || {}, a = {
497
+ ...n,
494
498
  date: (/* @__PURE__ */ new Date()).toISOString(),
495
499
  ...(e == null ? void 0 : e.page) && {
496
500
  page: {
@@ -511,29 +515,29 @@ class N extends y {
511
515
  category: "navigation",
512
516
  properties: i || {}
513
517
  }, l = this.resolveChannelName(h);
514
- this.client.events.create({
515
- channelName: l,
516
- title: "Page View",
517
- description: ((p = e == null ? void 0 : e.page) == null ? void 0 : p.path) || "User viewed a page",
518
- icon: "👁️",
519
- tags: ["page_view", "navigation"],
520
- metadata: t,
521
- userId: r || null,
522
- notify: !1,
523
- // Don't notify for page views by default
524
- displayAs: "message",
525
- source: "stacksee-analytics"
526
- }).then((g) => {
527
- var f;
518
+ try {
519
+ const f = await this.client.events.create({
520
+ channelName: l,
521
+ title: "Page View",
522
+ description: ((p = e == null ? void 0 : e.page) == null ? void 0 : p.path) || "User viewed a page",
523
+ icon: "👁️",
524
+ tags: ["page_view", "navigation"],
525
+ metadata: a,
526
+ userId: r || null,
527
+ notify: !1,
528
+ // Don't notify for page views by default
529
+ displayAs: "message",
530
+ source: "stacksee-analytics"
531
+ });
528
532
  this.log("Tracked page view", {
529
- eventId: g.data.id,
530
- path: (f = e == null ? void 0 : e.page) == null ? void 0 : f.path,
533
+ eventId: f.data.id,
534
+ path: (g = e == null ? void 0 : e.page) == null ? void 0 : g.path,
531
535
  userId: r,
532
536
  channelName: l
533
537
  });
534
- }).catch((g) => {
535
- console.error("[EmitKit-Server] Failed to track page view:", g);
536
- });
538
+ } catch (f) {
539
+ console.error("[EmitKit-Server] Failed to track page view:", f);
540
+ }
537
541
  }
538
542
  async reset() {
539
543
  !this.isEnabled() || !this.initialized || !this.client || (this.currentUserId = void 0, this.currentUserEmail = void 0, this.log("Reset user session"));
@@ -597,60 +601,60 @@ class N extends y {
597
601
  }
598
602
  }
599
603
  async function B(d, u, i) {
600
- var e, r, s, a;
604
+ var e, r, s, n;
601
605
  try {
602
- const t = await d.json();
603
- if (!t.events || !Array.isArray(t.events))
606
+ const a = await d.json();
607
+ if (!a.events || !Array.isArray(a.events))
604
608
  throw new Error("Invalid payload: missing events array");
605
- const h = i != null && i.extractIp ? i.extractIp(d) : $(d), l = d.headers.get("user-agent"), n = i != null && i.enrichContext ? i.enrichContext(d) : {};
606
- for (const o of t.events)
609
+ const h = i != null && i.extractIp ? i.extractIp(d) : $(d), l = d.headers.get("user-agent"), o = i != null && i.enrichContext ? i.enrichContext(d) : {};
610
+ for (const t of a.events)
607
611
  try {
608
- switch (o.type) {
612
+ switch (t.type) {
609
613
  case "track": {
610
614
  const p = {
611
- ...o.context,
612
- ...n,
615
+ ...t.context,
616
+ ...o,
613
617
  server: {
614
- ...(e = o.context) == null ? void 0 : e.server,
615
- ...typeof (n == null ? void 0 : n.server) == "object" && n.server !== null ? n.server : {},
618
+ ...(e = t.context) == null ? void 0 : e.server,
619
+ ...typeof (o == null ? void 0 : o.server) == "object" && o.server !== null ? o.server : {},
616
620
  ...l ? { userAgent: l } : {}
617
621
  },
618
622
  device: {
619
- ...(r = o.context) == null ? void 0 : r.device,
623
+ ...(r = t.context) == null ? void 0 : r.device,
620
624
  ...h ? { ip: h } : {}
621
625
  }
622
626
  };
623
627
  await u.track(
624
- o.event.action,
628
+ t.event.action,
625
629
  // biome-ignore lint/suspicious/noExplicitAny: Properties from JSON cannot be type-checked against TEventMap at compile time
626
- o.event.properties,
630
+ t.event.properties,
627
631
  {
628
- userId: o.event.userId,
629
- sessionId: o.event.sessionId,
632
+ userId: t.event.userId,
633
+ sessionId: t.event.sessionId,
630
634
  context: p
631
635
  }
632
636
  );
633
637
  break;
634
638
  }
635
639
  case "identify": {
636
- u.identify(o.userId, o.traits);
640
+ await u.identify(t.userId, t.traits);
637
641
  break;
638
642
  }
639
643
  case "pageView": {
640
644
  const p = {
641
- ...o.context,
642
- ...n,
645
+ ...t.context,
646
+ ...o,
643
647
  server: {
644
- ...(s = o.context) == null ? void 0 : s.server,
645
- ...typeof (n == null ? void 0 : n.server) == "object" && n.server !== null ? n.server : {},
648
+ ...(s = t.context) == null ? void 0 : s.server,
649
+ ...typeof (o == null ? void 0 : o.server) == "object" && o.server !== null ? o.server : {},
646
650
  ...l ? { userAgent: l } : {}
647
651
  },
648
652
  device: {
649
- ...(a = o.context) == null ? void 0 : a.device,
653
+ ...(n = t.context) == null ? void 0 : n.device,
650
654
  ...h ? { ip: h } : {}
651
655
  }
652
656
  };
653
- u.pageView(o.properties, {
657
+ await u.pageView(t.properties, {
654
658
  context: p
655
659
  });
656
660
  break;
@@ -658,13 +662,13 @@ async function B(d, u, i) {
658
662
  case "reset":
659
663
  break;
660
664
  default:
661
- console.warn("[Proxy] Unknown event type:", o);
665
+ console.warn("[Proxy] Unknown event type:", t);
662
666
  }
663
667
  } catch (p) {
664
668
  i != null && i.onError ? i.onError(p) : console.error("[Proxy] Failed to process event:", p);
665
669
  }
666
- } catch (t) {
667
- throw i != null && i.onError ? i.onError(t) : console.error("[Proxy] Failed to ingest events:", t), t;
670
+ } catch (a) {
671
+ throw i != null && i.onError ? i.onError(a) : console.error("[Proxy] Failed to ingest events:", a), a;
668
672
  }
669
673
  }
670
674
  function $(d) {
package/dist/server.js CHANGED
@@ -1,6 +1,6 @@
1
1
  var u = Object.defineProperty;
2
- var h = (i, e, t) => e in i ? u(i, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[e] = t;
3
- var c = (i, e, t) => h(i, typeof e != "symbol" ? e + "" : e, t);
2
+ var h = (a, e, t) => e in a ? u(a, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[e] = t;
3
+ var c = (a, e, t) => h(a, typeof e != "symbol" ? e + "" : e, t);
4
4
  import { P as w } from "./server-DjEk1fUD.js";
5
5
  import { B as y } from "./base.provider-AfFL5W_P.js";
6
6
  class f {
@@ -68,25 +68,25 @@ class f {
68
68
  ), r.excludeEvents && r.eventPatterns && console.warn(
69
69
  `[Analytics] Provider ${r.provider.name} has both 'excludeEvents' and 'eventPatterns' specified. Using 'eventPatterns' and ignoring 'excludeEvents'.`
70
70
  );
71
- let a;
72
- r.methods ? a = new Set(r.methods) : r.exclude ? a = new Set(
71
+ let i;
72
+ r.methods ? i = new Set(r.methods) : r.exclude ? i = new Set(
73
73
  t.filter(
74
- (l) => {
74
+ (o) => {
75
75
  var v;
76
- return !((v = r.exclude) != null && v.includes(l));
76
+ return !((v = r.exclude) != null && v.includes(o));
77
77
  }
78
78
  )
79
- ) : a = new Set(t);
80
- let o, d, s;
81
- return r.events && r.events.length > 0 ? o = new Set(r.events) : r.eventPatterns && r.eventPatterns.length > 0 ? s = r.eventPatterns.map((l) => {
82
- const v = l.replace(/\*/g, ".*");
79
+ ) : i = new Set(t);
80
+ let s, l, d;
81
+ return r.events && r.events.length > 0 ? s = new Set(r.events) : r.eventPatterns && r.eventPatterns.length > 0 ? d = r.eventPatterns.map((o) => {
82
+ const v = o.replace(/\*/g, ".*");
83
83
  return new RegExp(`^${v}$`);
84
- }) : r.excludeEvents && r.excludeEvents.length > 0 && (d = new Set(r.excludeEvents)), {
84
+ }) : r.excludeEvents && r.excludeEvents.length > 0 && (l = new Set(r.excludeEvents)), {
85
85
  provider: r.provider,
86
- enabledMethods: a,
87
- enabledEvents: o,
88
- excludedEvents: d,
89
- eventPatterns: s
86
+ enabledMethods: i,
87
+ enabledEvents: s,
88
+ excludedEvents: l,
89
+ eventPatterns: d
90
90
  };
91
91
  });
92
92
  }
@@ -191,9 +191,11 @@ class f {
191
191
  * }
192
192
  * ```
193
193
  */
194
- identify(e, t) {
195
- for (const n of this.providerConfigs)
196
- this.shouldCallMethod(n, "identify") && n.provider.identify(e, t);
194
+ async identify(e, t) {
195
+ const n = this.providerConfigs.filter((i) => this.shouldCallMethod(i, "identify")).map((i) => i.provider.identify(e, t)), r = await Promise.allSettled(n);
196
+ for (const i of r)
197
+ if (i.status === "rejected")
198
+ throw i.reason;
197
199
  }
198
200
  /**
199
201
  * Tracks a custom event with properties and optional context.
@@ -317,7 +319,7 @@ class f {
317
319
  * ```
318
320
  */
319
321
  async track(e, t, n) {
320
- var d;
322
+ var l;
321
323
  if (!this.initialized) {
322
324
  console.warn("[Analytics] Not initialized. Call initialize() first.");
323
325
  return;
@@ -329,23 +331,23 @@ class f {
329
331
  timestamp: Date.now(),
330
332
  userId: n == null ? void 0 : n.userId,
331
333
  sessionId: n == null ? void 0 : n.sessionId
332
- }, a = {
334
+ }, i = {
333
335
  ...this.config.defaultContext,
334
336
  ...n == null ? void 0 : n.context,
335
- user: (n == null ? void 0 : n.user) || ((d = n == null ? void 0 : n.context) == null ? void 0 : d.user)
336
- }, o = this.providerConfigs.filter(
337
- (s) => this.shouldCallMethod(s, "track") && this.shouldTrackEvent(s, e)
338
- ).map(async (s) => {
337
+ user: (n == null ? void 0 : n.user) || ((l = n == null ? void 0 : n.context) == null ? void 0 : l.user)
338
+ }, s = this.providerConfigs.filter(
339
+ (d) => this.shouldCallMethod(d, "track") && this.shouldTrackEvent(d, e)
340
+ ).map(async (d) => {
339
341
  try {
340
- await s.provider.track(r, a);
341
- } catch (l) {
342
+ await d.provider.track(r, i);
343
+ } catch (o) {
342
344
  console.error(
343
- `[Analytics] Provider ${s.provider.name} failed to track event:`,
344
- l
345
+ `[Analytics] Provider ${d.provider.name} failed to track event:`,
346
+ o
345
347
  );
346
348
  }
347
349
  });
348
- await Promise.all(o);
350
+ await Promise.all(s);
349
351
  }
350
352
  /**
351
353
  * Tracks a page view event from the server side.
@@ -407,14 +409,15 @@ class f {
407
409
  * }
408
410
  * ```
409
411
  */
410
- pageView(e, t) {
412
+ async pageView(e, t) {
411
413
  if (!this.initialized) return;
412
414
  const n = {
413
415
  ...this.config.defaultContext,
414
416
  ...t == null ? void 0 : t.context
415
- };
416
- for (const r of this.providerConfigs)
417
- this.shouldCallMethod(r, "pageView") && r.provider.pageView(e, n);
417
+ }, r = this.providerConfigs.filter((s) => this.shouldCallMethod(s, "pageView")).map((s) => s.provider.pageView(e, n)), i = await Promise.allSettled(r);
418
+ for (const s of i)
419
+ if (s.status === "rejected")
420
+ throw s.reason;
418
421
  }
419
422
  /**
420
423
  * Tracks when a user leaves a page from the server side.
@@ -577,11 +580,11 @@ class f {
577
580
  return t.length > 1 && t[0] ? t[0] : "engagement";
578
581
  }
579
582
  }
580
- function x(i) {
583
+ function m(a) {
581
584
  const e = {
582
- providers: i.providers || [],
583
- debug: i.debug,
584
- enabled: i.enabled
585
+ providers: a.providers || [],
586
+ debug: a.debug,
587
+ enabled: a.enabled
585
588
  }, t = new f(e);
586
589
  return t.initialize(), t;
587
590
  }
@@ -589,5 +592,5 @@ export {
589
592
  y as BaseAnalyticsProvider,
590
593
  w as PostHogServerProvider,
591
594
  f as ServerAnalytics,
592
- x as createServerAnalytics
595
+ m as createServerAnalytics
593
596
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stacksee/analytics",
3
- "version": "0.13.1",
3
+ "version": "0.13.2",
4
4
  "description": "A highly typed, provider-agnostic analytics library for TypeScript applications",
5
5
  "type": "module",
6
6
  "exports": {
@@ -56,6 +56,7 @@
56
56
  "@vitest/coverage-v8": "3.1.4",
57
57
  "globals": "^15.8.0",
58
58
  "jsdom": "^26.1.0",
59
+ "playwright": "^1.58.2",
59
60
  "prettier": "^3.3.3",
60
61
  "typescript": "~5.5.3",
61
62
  "vite": "^6.3.5",
@@ -76,12 +77,14 @@
76
77
  "scripts": {
77
78
  "test": "vitest run",
78
79
  "test:watch": "vitest",
80
+ "test:e2e": "node e2e/pirsch.test.js",
81
+ "test:e2e:server": "node e2e/test-app/server.js",
79
82
  "build": "vite build",
80
83
  "dev": "pnpm --filter @stacksee/docs dev",
81
84
  "build:docs": "pnpm --filter @stacksee/docs build",
82
85
  "deploy": "npm publish",
83
86
  "typecheck": "tsc --noEmit",
84
- "ci:publish": "pnpm build && changeset publish",
87
+ "ci:publish": "pnpm build && changeset publish --provenance",
85
88
  "lint": "biome lint .",
86
89
  "format": "biome format --write .",
87
90
  "biome": "biome"