@kitbase/events 0.1.1

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,726 @@
1
+ /**
2
+ * Configuration options for offline event queueing
3
+ */
4
+ interface OfflineConfig {
5
+ /**
6
+ * Enable offline queueing
7
+ * @default false
8
+ */
9
+ enabled?: boolean;
10
+ /**
11
+ * Maximum number of events to store in the queue
12
+ * Oldest events are dropped when limit is reached
13
+ * @default 1000
14
+ */
15
+ maxQueueSize?: number;
16
+ /**
17
+ * Interval in milliseconds to flush queued events when online
18
+ * @default 30000 (30 seconds)
19
+ */
20
+ flushInterval?: number;
21
+ /**
22
+ * Number of events to send per batch when flushing
23
+ * @default 50
24
+ */
25
+ flushBatchSize?: number;
26
+ /**
27
+ * Maximum number of retry attempts for failed events
28
+ * @default 3
29
+ */
30
+ maxRetries?: number;
31
+ /**
32
+ * Base delay in milliseconds for exponential backoff
33
+ * @default 1000 (1 second)
34
+ */
35
+ retryBaseDelay?: number;
36
+ }
37
+ /**
38
+ * A queued event stored in the database
39
+ */
40
+ interface QueuedEvent {
41
+ /**
42
+ * Auto-incremented unique identifier
43
+ */
44
+ id?: number;
45
+ /**
46
+ * The event payload to send
47
+ */
48
+ payload: LogPayload;
49
+ /**
50
+ * Timestamp when the event was queued (ms since epoch)
51
+ */
52
+ timestamp: number;
53
+ /**
54
+ * Number of retry attempts made
55
+ */
56
+ retries: number;
57
+ /**
58
+ * Timestamp of the last retry attempt (ms since epoch)
59
+ */
60
+ lastAttempt?: number;
61
+ }
62
+ /**
63
+ * Statistics about the event queue
64
+ */
65
+ interface QueueStats {
66
+ /**
67
+ * Number of events currently in the queue
68
+ */
69
+ size: number;
70
+ /**
71
+ * Oldest event timestamp in the queue
72
+ */
73
+ oldestEvent?: number;
74
+ /**
75
+ * Whether the queue is currently flushing
76
+ */
77
+ isFlushing: boolean;
78
+ }
79
+
80
+ /**
81
+ * Storage interface for anonymous ID persistence
82
+ */
83
+ interface Storage {
84
+ getItem(key: string): string | null;
85
+ setItem(key: string, value: string): void;
86
+ removeItem(key: string): void;
87
+ }
88
+
89
+ /**
90
+ * Configuration options for the Kitbase client
91
+ */
92
+ interface KitbaseConfig {
93
+ /**
94
+ * Your Kitbase API key
95
+ */
96
+ token: string;
97
+ /**
98
+ * Override the default API endpoint.
99
+ * @default 'https://api.kitbase.dev'
100
+ */
101
+ baseUrl?: string;
102
+ /**
103
+ * Custom storage for anonymous ID persistence.
104
+ * Defaults to localStorage in browser, in-memory storage otherwise.
105
+ * Set to null to disable anonymous ID persistence (will generate new ID each session).
106
+ */
107
+ storage?: Storage | null;
108
+ /**
109
+ * Storage key for the anonymous ID.
110
+ * @default 'kitbase_anonymous_id'
111
+ */
112
+ storageKey?: string;
113
+ /**
114
+ * Enable debug mode for console logging.
115
+ * @default false
116
+ */
117
+ debug?: boolean;
118
+ /**
119
+ * Offline queueing configuration.
120
+ * Events are queued locally when offline or when the API fails,
121
+ * and automatically sent when back online.
122
+ */
123
+ offline?: OfflineConfig;
124
+ /**
125
+ * Analytics tracking configuration.
126
+ * Enables session tracking, pageview tracking, and revenue tracking.
127
+ */
128
+ analytics?: AnalyticsConfig;
129
+ }
130
+ /**
131
+ * Tag values can be strings, numbers, or booleans
132
+ */
133
+ type TagValue = string | number | boolean;
134
+ /**
135
+ * Event tags for additional metadata
136
+ */
137
+ type Tags = Record<string, TagValue>;
138
+ /**
139
+ * Options for tracking an event
140
+ */
141
+ interface TrackOptions {
142
+ /**
143
+ * The channel/category for the event
144
+ * @example 'payments', 'auth', 'users'
145
+ */
146
+ channel: string;
147
+ /**
148
+ * The name of the event
149
+ * @example 'New Subscription', 'User Signed Up'
150
+ */
151
+ event: string;
152
+ /**
153
+ * Optional user identifier (set when user is identified/logged in)
154
+ */
155
+ user_id?: string;
156
+ /**
157
+ * Icon for the event (emoji or icon name)
158
+ * @example '💰', 'money_bag'
159
+ */
160
+ icon?: string;
161
+ /**
162
+ * Whether to send a notification for this event
163
+ * @default false
164
+ */
165
+ notify?: boolean;
166
+ /**
167
+ * Optional description for the event
168
+ */
169
+ description?: string;
170
+ /**
171
+ * Additional metadata tags
172
+ */
173
+ tags?: Tags;
174
+ /**
175
+ * Whether to include the anonymous ID in this event.
176
+ * @default true
177
+ */
178
+ includeAnonymousId?: boolean;
179
+ }
180
+ /**
181
+ * Response from the track API
182
+ */
183
+ interface TrackResponse {
184
+ /**
185
+ * Unique identifier for the logged event
186
+ */
187
+ id: string;
188
+ /**
189
+ * The event name
190
+ */
191
+ event: string;
192
+ /**
193
+ * Server timestamp when the event was recorded
194
+ */
195
+ timestamp: string;
196
+ }
197
+ /**
198
+ * Internal request payload sent to the API
199
+ */
200
+ interface LogPayload {
201
+ channel: string;
202
+ event: string;
203
+ user_id?: string;
204
+ anonymous_id?: string;
205
+ icon?: string;
206
+ notify?: boolean;
207
+ description?: string;
208
+ tags?: Tags;
209
+ /**
210
+ * Client-side timestamp (ms since epoch) when the event occurred.
211
+ * Used for accurate session duration calculation, especially in offline mode.
212
+ */
213
+ timestamp?: number;
214
+ }
215
+ /**
216
+ * Session data for analytics tracking
217
+ */
218
+ interface Session {
219
+ id: string;
220
+ startedAt: number;
221
+ lastActivityAt: number;
222
+ screenViewCount: number;
223
+ entryPath?: string;
224
+ entryReferrer?: string;
225
+ }
226
+ /**
227
+ * Configuration for analytics tracking
228
+ */
229
+ interface AnalyticsConfig {
230
+ /**
231
+ * Enable automatic pageview tracking on route changes
232
+ * @default false
233
+ */
234
+ autoTrackPageViews?: boolean;
235
+ /**
236
+ * Enable automatic session tracking
237
+ * @default true
238
+ */
239
+ autoTrackSessions?: boolean;
240
+ /**
241
+ * Session timeout in milliseconds (default: 30 minutes)
242
+ * @default 1800000
243
+ */
244
+ sessionTimeout?: number;
245
+ /**
246
+ * Storage key for session data
247
+ * @default 'kitbase_session'
248
+ */
249
+ sessionStorageKey?: string;
250
+ }
251
+ /**
252
+ * Options for tracking a pageview
253
+ */
254
+ interface PageViewOptions {
255
+ /**
256
+ * The page path (defaults to window.location.pathname)
257
+ */
258
+ path?: string;
259
+ /**
260
+ * The page title (defaults to document.title)
261
+ */
262
+ title?: string;
263
+ /**
264
+ * The referrer URL
265
+ */
266
+ referrer?: string;
267
+ /**
268
+ * Additional metadata tags
269
+ */
270
+ tags?: Tags;
271
+ }
272
+ /**
273
+ * Options for tracking revenue
274
+ */
275
+ interface RevenueOptions {
276
+ /**
277
+ * Revenue amount in cents (e.g., 1999 for $19.99)
278
+ */
279
+ amount: number;
280
+ /**
281
+ * Currency code (e.g., 'USD', 'EUR')
282
+ * @default 'USD'
283
+ */
284
+ currency?: string;
285
+ /**
286
+ * Optional user identifier
287
+ */
288
+ user_id?: string;
289
+ /**
290
+ * Additional metadata tags
291
+ */
292
+ tags?: Tags;
293
+ }
294
+ /**
295
+ * Options for identifying a user
296
+ */
297
+ interface IdentifyOptions {
298
+ /**
299
+ * The unique user identifier
300
+ */
301
+ userId: string;
302
+ /**
303
+ * User traits/properties
304
+ */
305
+ traits?: Tags;
306
+ }
307
+
308
+ /**
309
+ * Kitbase client for tracking events
310
+ *
311
+ * @example
312
+ * ```typescript
313
+ * import { Kitbase } from '@kitbase/sdk/events';
314
+ *
315
+ * const kitbase = new Kitbase({
316
+ * token: '<YOUR_API_KEY>',
317
+ * debug: true,
318
+ * offline: { enabled: true },
319
+ * });
320
+ *
321
+ * // Register super properties (included in all events)
322
+ * kitbase.register({ app_version: '2.1.0', platform: 'web' });
323
+ *
324
+ * // Track anonymous events (anonymous_id is automatically included)
325
+ * await kitbase.track({
326
+ * channel: 'payments',
327
+ * event: 'Page Viewed',
328
+ * icon: '👀',
329
+ * });
330
+ *
331
+ * // Time events for duration tracking
332
+ * kitbase.timeEvent('Video Watched');
333
+ * // ... later
334
+ * await kitbase.track({
335
+ * channel: 'engagement',
336
+ * event: 'Video Watched', // $duration automatically included
337
+ * });
338
+ *
339
+ * // Track events for a logged-in user (just pass user_id)
340
+ * await kitbase.track({
341
+ * channel: 'payments',
342
+ * event: 'New Subscription',
343
+ * user_id: 'user-123',
344
+ * icon: '💰',
345
+ * notify: true,
346
+ * tags: {
347
+ * plan: 'premium',
348
+ * cycle: 'monthly',
349
+ * },
350
+ * });
351
+ * ```
352
+ */
353
+ declare class Kitbase {
354
+ private readonly token;
355
+ private readonly baseUrl;
356
+ private readonly storage;
357
+ private readonly storageKey;
358
+ private anonymousId;
359
+ private superProperties;
360
+ private timedEvents;
361
+ private debugMode;
362
+ private queue;
363
+ private offlineEnabled;
364
+ private session;
365
+ private sessionTimeout;
366
+ private sessionStorageKey;
367
+ private analyticsEnabled;
368
+ private autoTrackPageViews;
369
+ private userId;
370
+ private unloadListenerAdded;
371
+ constructor(config: KitbaseConfig);
372
+ /**
373
+ * Initialize the anonymous ID from storage or generate a new one
374
+ */
375
+ private initializeAnonymousId;
376
+ /**
377
+ * Get the current anonymous ID
378
+ */
379
+ getAnonymousId(): string | null;
380
+ /**
381
+ * Enable or disable debug mode
382
+ * When enabled, all SDK operations are logged to the console
383
+ *
384
+ * @param enabled - Whether to enable debug mode
385
+ *
386
+ * @example
387
+ * ```typescript
388
+ * kitbase.setDebugMode(true);
389
+ * // All events and operations will now be logged
390
+ * ```
391
+ */
392
+ setDebugMode(enabled: boolean): void;
393
+ /**
394
+ * Check if debug mode is enabled
395
+ */
396
+ isDebugMode(): boolean;
397
+ /**
398
+ * Internal logging function
399
+ */
400
+ private log;
401
+ /**
402
+ * Register super properties that will be included with every event
403
+ * These properties are stored in memory only and reset on page reload
404
+ *
405
+ * @param properties - Properties to register
406
+ *
407
+ * @example
408
+ * ```typescript
409
+ * kitbase.register({
410
+ * app_version: '2.1.0',
411
+ * platform: 'web',
412
+ * environment: 'production',
413
+ * });
414
+ * ```
415
+ */
416
+ register(properties: Tags): void;
417
+ /**
418
+ * Register super properties only if they haven't been set yet
419
+ * Useful for setting default values that shouldn't override existing ones
420
+ *
421
+ * @param properties - Properties to register if not already set
422
+ *
423
+ * @example
424
+ * ```typescript
425
+ * kitbase.registerOnce({ first_visit: new Date().toISOString() });
426
+ * ```
427
+ */
428
+ registerOnce(properties: Tags): void;
429
+ /**
430
+ * Remove a super property
431
+ *
432
+ * @param key - The property key to remove
433
+ *
434
+ * @example
435
+ * ```typescript
436
+ * kitbase.unregister('platform');
437
+ * ```
438
+ */
439
+ unregister(key: string): void;
440
+ /**
441
+ * Get all registered super properties
442
+ *
443
+ * @returns A copy of the current super properties
444
+ *
445
+ * @example
446
+ * ```typescript
447
+ * const props = kitbase.getSuperProperties();
448
+ * console.log(props); // { app_version: '2.1.0', platform: 'web' }
449
+ * ```
450
+ */
451
+ getSuperProperties(): Tags;
452
+ /**
453
+ * Clear all super properties
454
+ *
455
+ * @example
456
+ * ```typescript
457
+ * kitbase.clearSuperProperties();
458
+ * ```
459
+ */
460
+ clearSuperProperties(): void;
461
+ /**
462
+ * Start timing an event
463
+ * When the same event is tracked later, a $duration property (in seconds)
464
+ * will automatically be included
465
+ *
466
+ * @param eventName - The name of the event to time
467
+ *
468
+ * @example
469
+ * ```typescript
470
+ * kitbase.timeEvent('Video Watched');
471
+ * // ... user watches video ...
472
+ * await kitbase.track({
473
+ * channel: 'engagement',
474
+ * event: 'Video Watched',
475
+ * tags: { video_id: '123' }
476
+ * });
477
+ * // Event will include $duration: 45.2 (seconds)
478
+ * ```
479
+ */
480
+ timeEvent(eventName: string): void;
481
+ /**
482
+ * Cancel a timed event without tracking it
483
+ *
484
+ * @param eventName - The name of the event to cancel timing for
485
+ *
486
+ * @example
487
+ * ```typescript
488
+ * kitbase.timeEvent('Checkout Flow');
489
+ * // User abandons checkout
490
+ * kitbase.cancelTimeEvent('Checkout Flow');
491
+ * ```
492
+ */
493
+ cancelTimeEvent(eventName: string): void;
494
+ /**
495
+ * Get all currently timed events
496
+ *
497
+ * @returns Array of event names that are currently being timed
498
+ *
499
+ * @example
500
+ * ```typescript
501
+ * const timedEvents = kitbase.getTimedEvents();
502
+ * console.log(timedEvents); // ['Video Watched', 'Checkout Flow']
503
+ * ```
504
+ */
505
+ getTimedEvents(): string[];
506
+ /**
507
+ * Get the duration of a timed event (without stopping it)
508
+ *
509
+ * @param eventName - The name of the event
510
+ * @returns Duration in seconds, or null if not being timed
511
+ */
512
+ getEventDuration(eventName: string): number | null;
513
+ /**
514
+ * Get offline queue statistics
515
+ *
516
+ * @returns Queue statistics including size and flush status
517
+ *
518
+ * @example
519
+ * ```typescript
520
+ * const stats = await kitbase.getQueueStats();
521
+ * console.log(stats); // { size: 5, isFlushing: false }
522
+ * ```
523
+ */
524
+ getQueueStats(): Promise<QueueStats | null>;
525
+ /**
526
+ * Manually flush the offline queue
527
+ * Events are automatically flushed on interval and when coming back online,
528
+ * but this method can be used to trigger an immediate flush
529
+ *
530
+ * @example
531
+ * ```typescript
532
+ * await kitbase.flushQueue();
533
+ * ```
534
+ */
535
+ flushQueue(): Promise<void>;
536
+ /**
537
+ * Clear all events from the offline queue
538
+ *
539
+ * @example
540
+ * ```typescript
541
+ * await kitbase.clearQueue();
542
+ * ```
543
+ */
544
+ clearQueue(): Promise<void>;
545
+ /**
546
+ * Callback for the queue to send batched events
547
+ */
548
+ private sendQueuedEvents;
549
+ /**
550
+ * Track an event
551
+ *
552
+ * When offline queueing is enabled, events are always written to the local
553
+ * database first (write-ahead), then sent to the server. This ensures no
554
+ * events are lost if the browser crashes or the network fails.
555
+ *
556
+ * @param options - Event tracking options
557
+ * @returns Promise resolving to the track response
558
+ * @throws {ValidationError} When required fields are missing
559
+ * @throws {AuthenticationError} When the API key is invalid (only when offline disabled)
560
+ * @throws {ApiError} When the API returns an error (only when offline disabled)
561
+ * @throws {TimeoutError} When the request times out (only when offline disabled)
562
+ */
563
+ track(options: TrackOptions): Promise<TrackResponse>;
564
+ private validateTrackOptions;
565
+ /**
566
+ * Send a request to the API
567
+ */
568
+ private sendRequest;
569
+ private parseResponseBody;
570
+ private getErrorMessage;
571
+ /**
572
+ * Load session from storage
573
+ */
574
+ private loadSession;
575
+ /**
576
+ * Save session to storage
577
+ */
578
+ private saveSession;
579
+ /**
580
+ * Get or create a session
581
+ */
582
+ private getOrCreateSession;
583
+ /**
584
+ * Get the current session ID (or null if no active session)
585
+ */
586
+ getSessionId(): string | null;
587
+ /**
588
+ * Get the current session data
589
+ */
590
+ getSession(): Session | null;
591
+ /**
592
+ * Track session start event
593
+ */
594
+ private trackSessionStart;
595
+ /**
596
+ * End the current session (clears local state only - server calculates metrics)
597
+ */
598
+ private endSession;
599
+ /**
600
+ * Setup listeners for session lifecycle management
601
+ */
602
+ private setupUnloadListener;
603
+ /**
604
+ * Get UTM parameters from URL
605
+ */
606
+ private getUtmParams;
607
+ /**
608
+ * Track a page view
609
+ *
610
+ * @param options - Page view options
611
+ * @returns Promise resolving to the track response
612
+ *
613
+ * @example
614
+ * ```typescript
615
+ * // Track current page
616
+ * await kitbase.trackPageView();
617
+ *
618
+ * // Track with custom path
619
+ * await kitbase.trackPageView({ path: '/products/123', title: 'Product Details' });
620
+ * ```
621
+ */
622
+ trackPageView(options?: PageViewOptions): Promise<TrackResponse>;
623
+ /**
624
+ * Enable automatic page view tracking
625
+ * Intercepts browser history changes (pushState, replaceState, popstate)
626
+ *
627
+ * @example
628
+ * ```typescript
629
+ * kitbase.enableAutoPageViews();
630
+ * // Now all route changes will automatically be tracked
631
+ * ```
632
+ */
633
+ enableAutoPageViews(): void;
634
+ /**
635
+ * Track a revenue event
636
+ *
637
+ * @param options - Revenue options
638
+ * @returns Promise resolving to the track response
639
+ *
640
+ * @example
641
+ * ```typescript
642
+ * // Track a $19.99 purchase
643
+ * await kitbase.trackRevenue({
644
+ * amount: 1999,
645
+ * currency: 'USD',
646
+ * tags: { product_id: 'prod_123', plan: 'premium' },
647
+ * });
648
+ * ```
649
+ */
650
+ trackRevenue(options: RevenueOptions): Promise<TrackResponse>;
651
+ /**
652
+ * Identify a user
653
+ * Links the current anonymous ID to a user ID for future events
654
+ *
655
+ * @param options - Identify options
656
+ *
657
+ * @example
658
+ * ```typescript
659
+ * kitbase.identify({
660
+ * userId: 'user_123',
661
+ * traits: { email: 'user@example.com', plan: 'premium' },
662
+ * });
663
+ * ```
664
+ */
665
+ identify(options: IdentifyOptions): void;
666
+ /**
667
+ * Get the current user ID (set via identify)
668
+ */
669
+ getUserId(): string | null;
670
+ /**
671
+ * Reset the user identity and session
672
+ * Call this when a user logs out
673
+ *
674
+ * @example
675
+ * ```typescript
676
+ * kitbase.reset();
677
+ * ```
678
+ */
679
+ reset(): void;
680
+ /**
681
+ * Shutdown the client and cleanup resources
682
+ * Call this when you're done using the client to stop timers and close connections
683
+ *
684
+ * @example
685
+ * ```typescript
686
+ * await kitbase.shutdown();
687
+ * ```
688
+ */
689
+ shutdown(): Promise<void>;
690
+ }
691
+
692
+ /**
693
+ * Base error class for Kitbase SDK errors
694
+ */
695
+ declare class KitbaseError extends Error {
696
+ constructor(message: string);
697
+ }
698
+ /**
699
+ * Error thrown when API authentication fails
700
+ */
701
+ declare class AuthenticationError extends KitbaseError {
702
+ constructor(message?: string);
703
+ }
704
+ /**
705
+ * Error thrown when the API request fails
706
+ */
707
+ declare class ApiError extends KitbaseError {
708
+ readonly statusCode: number;
709
+ readonly response?: unknown;
710
+ constructor(message: string, statusCode: number, response?: unknown);
711
+ }
712
+ /**
713
+ * Error thrown when request validation fails
714
+ */
715
+ declare class ValidationError extends KitbaseError {
716
+ readonly field?: string;
717
+ constructor(message: string, field?: string);
718
+ }
719
+ /**
720
+ * Error thrown when a request times out
721
+ */
722
+ declare class TimeoutError extends KitbaseError {
723
+ constructor(message?: string);
724
+ }
725
+
726
+ export { type AnalyticsConfig, ApiError, AuthenticationError, type IdentifyOptions, Kitbase, type KitbaseConfig, KitbaseError, type OfflineConfig, type PageViewOptions, type QueueStats, type QueuedEvent, type RevenueOptions, type Session, type Storage, type TagValue, type Tags, TimeoutError, type TrackOptions, type TrackResponse, ValidationError };