@stacksee/analytics 0.9.8 → 0.11.0

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.
@@ -0,0 +1,157 @@
1
+ var u = Object.defineProperty;
2
+ var l = (e, t, r) => t in e ? u(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
3
+ var c = (e, t, r) => l(e, typeof t != "symbol" ? t + "" : t, r);
4
+ var i = class extends Error {
5
+ constructor(e, t, r, a) {
6
+ super(e), this.statusCode = t, this.requestId = r, this.details = a, this.name = "EmitKitError";
7
+ }
8
+ }, y = class extends i {
9
+ constructor(e, t) {
10
+ super(
11
+ `Rate limit exceeded. Resets in ${Math.ceil(e.resetIn / 1e3)}s`,
12
+ 429,
13
+ t
14
+ ), this.rateLimit = e, this.name = "RateLimitError";
15
+ }
16
+ }, w = class extends i {
17
+ constructor(e, t, r) {
18
+ super(e, 400, r, t), this.validationErrors = t, this.name = "ValidationError";
19
+ }
20
+ }, I = class {
21
+ constructor(e, t) {
22
+ c(this, "config");
23
+ c(this, "lastRateLimit");
24
+ this.config = {
25
+ apiKey: e,
26
+ baseUrl: (t == null ? void 0 : t.baseUrl) || "https://api.emitkit.com",
27
+ timeout: (t == null ? void 0 : t.timeout) || 3e4,
28
+ fetch: (t == null ? void 0 : t.fetch) || globalThis.fetch
29
+ };
30
+ }
31
+ /**
32
+ * Get the last known rate limit information
33
+ */
34
+ get rateLimit() {
35
+ return this.lastRateLimit;
36
+ }
37
+ /**
38
+ * Events API
39
+ */
40
+ get events() {
41
+ return {
42
+ /**
43
+ * Create a new event
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * const result = await client.events.create({
48
+ * channelName: 'payments',
49
+ * title: 'Payment Received',
50
+ * metadata: { amount: 99.99 }
51
+ * });
52
+ * ```
53
+ */
54
+ create: async (e, t) => this.request("/v1/events", {
55
+ method: "POST",
56
+ body: JSON.stringify(e),
57
+ headers: {
58
+ "Content-Type": "application/json",
59
+ ...(t == null ? void 0 : t.idempotencyKey) && {
60
+ "Idempotency-Key": t.idempotencyKey
61
+ },
62
+ ...t == null ? void 0 : t.headers
63
+ }
64
+ })
65
+ };
66
+ }
67
+ /**
68
+ * Identify a user with properties and aliases
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * const result = await client.identify({
73
+ * user_id: 'user_123',
74
+ * properties: {
75
+ * email: 'user@example.com',
76
+ * name: 'John Doe',
77
+ * plan: 'pro'
78
+ * },
79
+ * aliases: ['user@example.com', 'johndoe']
80
+ * });
81
+ * ```
82
+ */
83
+ async identify(e, t) {
84
+ return this.request("/v1/identify", {
85
+ method: "POST",
86
+ body: JSON.stringify(e),
87
+ headers: {
88
+ "Content-Type": "application/json",
89
+ ...t == null ? void 0 : t.headers
90
+ }
91
+ });
92
+ }
93
+ /**
94
+ * Make a raw API request
95
+ */
96
+ async request(e, t) {
97
+ const r = `${this.config.baseUrl}${e}`, a = new AbortController(), n = setTimeout(() => a.abort(), this.config.timeout);
98
+ try {
99
+ const s = await this.config.fetch(r, {
100
+ ...t,
101
+ headers: {
102
+ Authorization: `Bearer ${this.config.apiKey}`,
103
+ ...t.headers
104
+ },
105
+ signal: a.signal
106
+ });
107
+ clearTimeout(n);
108
+ const o = this.extractRateLimit(s);
109
+ o && (this.lastRateLimit = o);
110
+ const d = s.headers.get("X-Idempotent-Replay") === "true";
111
+ s.ok || await this.handleErrorResponse(s, o);
112
+ const h = await s.json(), m = h.requestId || s.headers.get("X-Request-ID");
113
+ return {
114
+ data: h.success ? h.data : h,
115
+ rateLimit: o,
116
+ requestId: m || "unknown",
117
+ wasReplayed: d
118
+ };
119
+ } catch (s) {
120
+ throw clearTimeout(n), s instanceof i ? s : s instanceof Error ? s.name === "AbortError" ? new i("Request timeout", 408) : new i(
121
+ `Network error: ${s.message}`,
122
+ 0
123
+ ) : new i("Unknown error occurred", 500);
124
+ }
125
+ }
126
+ extractRateLimit(e) {
127
+ const t = e.headers.get("X-RateLimit-Limit"), r = e.headers.get("X-RateLimit-Remaining"), a = e.headers.get("X-RateLimit-Reset");
128
+ if (!t || !r || !a)
129
+ return null;
130
+ const n = parseInt(a, 10) * 1e3, s = Math.max(0, n - Date.now());
131
+ return {
132
+ limit: parseInt(t, 10),
133
+ remaining: parseInt(r, 10),
134
+ reset: parseInt(a, 10),
135
+ resetIn: s
136
+ };
137
+ }
138
+ async handleErrorResponse(e, t) {
139
+ const r = await e.json().catch(() => ({})), a = r.requestId || e.headers.get("X-Request-ID") || void 0;
140
+ throw e.status === 429 && t ? new y(t, a) : e.status === 400 && r.details ? new w(
141
+ r.error || "Validation error",
142
+ r.details,
143
+ a
144
+ ) : new i(
145
+ r.error || r.message || `HTTP ${e.status}`,
146
+ e.status,
147
+ a || void 0,
148
+ r
149
+ );
150
+ }
151
+ };
152
+ export {
153
+ I as EmitKit,
154
+ i as EmitKitError,
155
+ y as RateLimitError,
156
+ w as ValidationError
157
+ };
@@ -58,7 +58,7 @@ class w extends u {
58
58
  const s = (i == null ? void 0 : i.email) || e;
59
59
  if (this.bento.identify(s), i) {
60
60
  const t = { ...i };
61
- delete t.email, Object.keys(t).length > 0 && this.bento.updateFields(t);
61
+ t.email = void 0, Object.keys(t).length > 0 && this.bento.updateFields(t);
62
62
  }
63
63
  this.log("Identified user", { userId: e, email: s, traits: i });
64
64
  }
@@ -139,7 +139,9 @@ class w extends u {
139
139
  this.bento.track("$pageleave", s), this.log("Tracked page leave", { properties: e, context: i });
140
140
  }
141
141
  reset() {
142
- !this.isEnabled() || !this.initialized || !this.bento || !a() || this.log("Reset user session - Note: Bento doesn't have a native reset method");
142
+ !this.isEnabled() || !this.initialized || !this.bento || !a() || this.log(
143
+ "Reset user session - Note: Bento doesn't have a native reset method"
144
+ );
143
145
  }
144
146
  // ============================================================================
145
147
  // Bento-Specific Utility Methods
@@ -389,7 +391,7 @@ class v extends u {
389
391
  r(this, "retryAttempts");
390
392
  r(this, "retryBackoff");
391
393
  r(this, "retryInitialDelay");
392
- this.config = e, this.batchSize = ((i = e.batch) == null ? void 0 : i.size) ?? 10, this.batchInterval = ((s = e.batch) == null ? void 0 : s.interval) ?? 5e3, this.retryAttempts = ((t = e.retry) == null ? void 0 : t.attempts) ?? 3, this.retryBackoff = ((n = e.retry) == null ? void 0 : n.backoff) ?? "exponential", this.retryInitialDelay = ((l = e.retry) == null ? void 0 : l.initialDelay) ?? 1e3, typeof window < "u" && (window.addEventListener("beforeunload", () => {
394
+ this.config = e, this.batchSize = ((i = e.batch) == null ? void 0 : i.size) ?? 10, this.batchInterval = ((s = e.batch) == null ? void 0 : s.interval) ?? 2e3, this.retryAttempts = ((t = e.retry) == null ? void 0 : t.attempts) ?? 3, this.retryBackoff = ((n = e.retry) == null ? void 0 : n.backoff) ?? "exponential", this.retryInitialDelay = ((l = e.retry) == null ? void 0 : l.initialDelay) ?? 1e3, typeof window < "u" && (window.addEventListener("beforeunload", () => {
393
395
  this.flush(!0);
394
396
  }), document.addEventListener("visibilitychange", () => {
395
397
  document.visibilityState === "hidden" && this.flush(!0);
@@ -442,11 +444,11 @@ class v extends u {
442
444
  });
443
445
  return;
444
446
  }
445
- this.flushTimer || (this.flushTimer = setTimeout(() => {
447
+ this.flushTimer && clearTimeout(this.flushTimer), this.flushTimer = setTimeout(() => {
446
448
  this.flush().catch((i) => {
447
449
  console.error("[Proxy] Failed to flush events:", i);
448
450
  });
449
- }, this.batchInterval));
451
+ }, this.batchInterval);
450
452
  }
451
453
  async sendEvents(e, i = !1) {
452
454
  const s = { events: e };
@@ -0,0 +1,62 @@
1
+ import { BaseEvent, EventContext } from '../../core/events/types.js';
2
+ import { BaseAnalyticsProvider } from '../base.provider.js';
3
+ /**
4
+ * Configuration for EmitKit server provider
5
+ */
6
+ export interface EmitKitServerConfig {
7
+ /**
8
+ * Your EmitKit API key (starts with emitkit_)
9
+ */
10
+ apiKey: string;
11
+ /**
12
+ * Default channel name for events
13
+ * @default 'analytics'
14
+ */
15
+ channelName?: string;
16
+ /**
17
+ * Send notification for events
18
+ * @default true
19
+ */
20
+ notify?: boolean;
21
+ /**
22
+ * Display style for events
23
+ * @default 'notification'
24
+ */
25
+ displayAs?: "message" | "notification";
26
+ /**
27
+ * Enable debug logging
28
+ */
29
+ debug?: boolean;
30
+ /**
31
+ * Enable/disable the provider
32
+ */
33
+ enabled?: boolean;
34
+ }
35
+ export declare class EmitKitServerProvider extends BaseAnalyticsProvider {
36
+ name: string;
37
+ private client?;
38
+ private initialized;
39
+ private config;
40
+ private currentUserId?;
41
+ private currentUserEmail?;
42
+ constructor(config: EmitKitServerConfig);
43
+ initialize(): Promise<void>;
44
+ identify(userId: string, traits?: Record<string, unknown>): void;
45
+ track(event: BaseEvent, context?: EventContext): Promise<void>;
46
+ pageView(properties?: Record<string, unknown>, context?: EventContext): void;
47
+ reset(): Promise<void>;
48
+ shutdown(): Promise<void>;
49
+ /**
50
+ * Format event action into a human-readable title
51
+ * Converts: "user_signed_up" -> "User Signed Up"
52
+ */
53
+ private formatEventTitle;
54
+ /**
55
+ * Generate a description for the event
56
+ */
57
+ private getEventDescription;
58
+ /**
59
+ * Get an appropriate icon for the event category
60
+ */
61
+ private getEventIcon;
62
+ }
@@ -2,8 +2,10 @@ export { BaseAnalyticsProvider } from './base.provider.js';
2
2
  export { PostHogServerProvider } from './posthog/server.js';
3
3
  export type { PostHogOptions } from 'posthog-node';
4
4
  export { BentoServerProvider } from './bento/server.js';
5
- export type { BentoServerConfig, BentoAnalyticsOptions } from './bento/server.js';
5
+ export type { BentoServerConfig, BentoAnalyticsOptions, } from './bento/server.js';
6
6
  export { PirschServerProvider } from './pirsch/server.js';
7
7
  export type { PirschServerConfig } from './pirsch/server.js';
8
+ export { EmitKitServerProvider } from './emitkit/server.js';
9
+ export type { EmitKitServerConfig } from './emitkit/server.js';
8
10
  export { ingestProxyEvents, createProxyHandler } from './proxy/server.js';
9
11
  export type { IngestProxyEventsConfig } from './proxy/server.js';