@databuddy/sdk 2.3.28 → 2.3.29

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.
@@ -13,8 +13,14 @@ interface Logger {
13
13
  */
14
14
  type Middleware = (event: BatchEventInput) => BatchEventInput | null | Promise<BatchEventInput | null>;
15
15
  interface DatabuddyConfig {
16
- /** Client ID from Databuddy dashboard */
17
- clientId: string;
16
+ /** API key for authentication (dbdy_xxx) */
17
+ apiKey: string;
18
+ /** Optional default website ID to scope events to */
19
+ websiteId?: string;
20
+ /** Optional default namespace for logical grouping (e.g., 'billing', 'auth', 'api') */
21
+ namespace?: string;
22
+ /** Optional default source identifier for events (e.g., 'backend', 'webhook', 'cli') */
23
+ source?: string;
18
24
  /** Custom API endpoint (default: https://basket.databuddy.cc) */
19
25
  apiUrl?: string;
20
26
  /** Enable debug logging */
@@ -49,6 +55,12 @@ interface CustomEventInput {
49
55
  timestamp?: number | null;
50
56
  /** Event properties/metadata */
51
57
  properties?: Record<string, unknown> | null;
58
+ /** Website ID to scope the event to (overrides default) */
59
+ websiteId?: string | null;
60
+ /** Namespace for logical grouping (overrides default) */
61
+ namespace?: string | null;
62
+ /** Source identifier (overrides default) */
63
+ source?: string | null;
52
64
  }
53
65
  interface EventResponse {
54
66
  /** Whether the event was successfully sent */
@@ -73,6 +85,12 @@ interface BatchEventInput {
73
85
  timestamp?: number | null;
74
86
  /** Event properties/metadata */
75
87
  properties?: Record<string, unknown> | null;
88
+ /** Website ID to scope the event to */
89
+ websiteId?: string | null;
90
+ /** Namespace for logical grouping */
91
+ namespace?: string | null;
92
+ /** Source identifier */
93
+ source?: string | null;
76
94
  }
77
95
  /**
78
96
  * Global properties that will be attached to all events
@@ -207,7 +225,10 @@ declare function createServerFlagsManagerInMemory(config: FlagsConfig): ServerFl
207
225
  /** biome-ignore-all lint/performance/noBarrelFile: im a big fan of barrels */
208
226
 
209
227
  declare class Databuddy {
210
- private readonly clientId;
228
+ private readonly apiKey;
229
+ private readonly websiteId?;
230
+ private readonly namespace?;
231
+ private readonly source?;
211
232
  private readonly apiUrl;
212
233
  private readonly logger;
213
234
  private readonly enableBatching;
@@ -231,13 +252,20 @@ declare class Databuddy {
231
252
  * name: 'user_signup',
232
253
  * properties: { plan: 'pro', source: 'web' }
233
254
  * });
255
+ *
256
+ * // With website scope
257
+ * await client.track({
258
+ * name: 'page_view',
259
+ * websiteId: 'website-uuid',
260
+ * properties: { path: '/pricing' }
261
+ * });
234
262
  * ```
235
263
  */
236
264
  track(event: CustomEventInput): Promise<EventResponse>;
237
265
  /**
238
- * Convert BatchEventInput to CustomEventSpan format expected by /events endpoint
266
+ * Convert BatchEventInput to format expected by /track endpoint
239
267
  */
240
- private toCustomEventSpan;
268
+ private toTrackPayload;
241
269
  private send;
242
270
  private scheduleFlush;
243
271
  /**
@@ -13,8 +13,14 @@ interface Logger {
13
13
  */
14
14
  type Middleware = (event: BatchEventInput) => BatchEventInput | null | Promise<BatchEventInput | null>;
15
15
  interface DatabuddyConfig {
16
- /** Client ID from Databuddy dashboard */
17
- clientId: string;
16
+ /** API key for authentication (dbdy_xxx) */
17
+ apiKey: string;
18
+ /** Optional default website ID to scope events to */
19
+ websiteId?: string;
20
+ /** Optional default namespace for logical grouping (e.g., 'billing', 'auth', 'api') */
21
+ namespace?: string;
22
+ /** Optional default source identifier for events (e.g., 'backend', 'webhook', 'cli') */
23
+ source?: string;
18
24
  /** Custom API endpoint (default: https://basket.databuddy.cc) */
19
25
  apiUrl?: string;
20
26
  /** Enable debug logging */
@@ -49,6 +55,12 @@ interface CustomEventInput {
49
55
  timestamp?: number | null;
50
56
  /** Event properties/metadata */
51
57
  properties?: Record<string, unknown> | null;
58
+ /** Website ID to scope the event to (overrides default) */
59
+ websiteId?: string | null;
60
+ /** Namespace for logical grouping (overrides default) */
61
+ namespace?: string | null;
62
+ /** Source identifier (overrides default) */
63
+ source?: string | null;
52
64
  }
53
65
  interface EventResponse {
54
66
  /** Whether the event was successfully sent */
@@ -73,6 +85,12 @@ interface BatchEventInput {
73
85
  timestamp?: number | null;
74
86
  /** Event properties/metadata */
75
87
  properties?: Record<string, unknown> | null;
88
+ /** Website ID to scope the event to */
89
+ websiteId?: string | null;
90
+ /** Namespace for logical grouping */
91
+ namespace?: string | null;
92
+ /** Source identifier */
93
+ source?: string | null;
76
94
  }
77
95
  /**
78
96
  * Global properties that will be attached to all events
@@ -207,7 +225,10 @@ declare function createServerFlagsManagerInMemory(config: FlagsConfig): ServerFl
207
225
  /** biome-ignore-all lint/performance/noBarrelFile: im a big fan of barrels */
208
226
 
209
227
  declare class Databuddy {
210
- private readonly clientId;
228
+ private readonly apiKey;
229
+ private readonly websiteId?;
230
+ private readonly namespace?;
231
+ private readonly source?;
211
232
  private readonly apiUrl;
212
233
  private readonly logger;
213
234
  private readonly enableBatching;
@@ -231,13 +252,20 @@ declare class Databuddy {
231
252
  * name: 'user_signup',
232
253
  * properties: { plan: 'pro', source: 'web' }
233
254
  * });
255
+ *
256
+ * // With website scope
257
+ * await client.track({
258
+ * name: 'page_view',
259
+ * websiteId: 'website-uuid',
260
+ * properties: { path: '/pricing' }
261
+ * });
234
262
  * ```
235
263
  */
236
264
  track(event: CustomEventInput): Promise<EventResponse>;
237
265
  /**
238
- * Convert BatchEventInput to CustomEventSpan format expected by /events endpoint
266
+ * Convert BatchEventInput to format expected by /track endpoint
239
267
  */
240
- private toCustomEventSpan;
268
+ private toTrackPayload;
241
269
  private send;
242
270
  private scheduleFlush;
243
271
  /**
@@ -320,7 +320,10 @@ const DEFAULT_BATCH_TIMEOUT = 2e3;
320
320
  const DEFAULT_MAX_QUEUE_SIZE = 1e3;
321
321
  const DEFAULT_MAX_DEDUPLICATION_CACHE_SIZE = 1e4;
322
322
  class Databuddy {
323
- clientId;
323
+ apiKey;
324
+ websiteId;
325
+ namespace;
326
+ source;
324
327
  apiUrl;
325
328
  logger;
326
329
  enableBatching;
@@ -334,10 +337,13 @@ class Databuddy {
334
337
  deduplicationCache = /* @__PURE__ */ new Set();
335
338
  maxDeduplicationCacheSize;
336
339
  constructor(config) {
337
- if (!config.clientId || typeof config.clientId !== "string") {
338
- throw new Error("clientId is required and must be a string");
340
+ if (!config.apiKey || typeof config.apiKey !== "string") {
341
+ throw new Error("apiKey is required and must be a string");
339
342
  }
340
- this.clientId = config.clientId.trim();
343
+ this.apiKey = config.apiKey.trim();
344
+ this.websiteId = config.websiteId?.trim();
345
+ this.namespace = config.namespace?.trim();
346
+ this.source = config.source?.trim();
341
347
  this.apiUrl = config.apiUrl?.trim() || DEFAULT_API_URL;
342
348
  this.enableBatching = config.enableBatching !== false;
343
349
  this.batchSize = Math.min(config.batchSize || DEFAULT_BATCH_SIZE, 100);
@@ -354,7 +360,10 @@ class Databuddy {
354
360
  this.logger = createNoopLogger();
355
361
  }
356
362
  this.logger.info("Initialized", {
357
- clientId: this.clientId,
363
+ hasApiKey: true,
364
+ websiteId: this.websiteId,
365
+ namespace: this.namespace,
366
+ source: this.source,
358
367
  apiUrl: this.apiUrl,
359
368
  enableBatching: this.enableBatching,
360
369
  batchSize: this.batchSize,
@@ -373,6 +382,13 @@ class Databuddy {
373
382
  * name: 'user_signup',
374
383
  * properties: { plan: 'pro', source: 'web' }
375
384
  * });
385
+ *
386
+ * // With website scope
387
+ * await client.track({
388
+ * name: 'page_view',
389
+ * websiteId: 'website-uuid',
390
+ * properties: { path: '/pricing' }
391
+ * });
376
392
  * ```
377
393
  */
378
394
  async track(event) {
@@ -392,7 +408,10 @@ class Databuddy {
392
408
  properties: {
393
409
  ...this.globalProperties,
394
410
  ...event.properties || {}
395
- }
411
+ },
412
+ websiteId: event.websiteId ?? this.websiteId,
413
+ namespace: event.namespace ?? this.namespace,
414
+ source: event.source ?? this.source
396
415
  };
397
416
  const processedEvent = await this.applyMiddleware(batchEvent);
398
417
  if (!processedEvent) {
@@ -420,34 +439,38 @@ class Databuddy {
420
439
  return { success: true };
421
440
  }
422
441
  /**
423
- * Convert BatchEventInput to CustomEventSpan format expected by /events endpoint
442
+ * Convert BatchEventInput to format expected by /track endpoint
424
443
  */
425
- toCustomEventSpan(event) {
444
+ toTrackPayload(event) {
426
445
  const timestamp = event.timestamp ? Math.floor(event.timestamp) : Date.now();
427
446
  return {
447
+ name: event.name,
448
+ namespace: event.namespace ?? void 0,
428
449
  timestamp,
429
- path: "",
430
- eventName: event.name,
431
- anonymousId: event.anonymousId ?? null,
432
- sessionId: event.sessionId ?? null,
433
- properties: event.properties ?? null
450
+ properties: event.properties ?? void 0,
451
+ anonymousId: event.anonymousId ?? void 0,
452
+ sessionId: event.sessionId ?? void 0,
453
+ websiteId: event.websiteId ?? void 0,
454
+ source: event.source ?? void 0
434
455
  };
435
456
  }
436
457
  async send(event) {
437
458
  try {
438
- const url = `${this.apiUrl}/events?client_id=${encodeURIComponent(this.clientId)}`;
439
- const customEventSpan = this.toCustomEventSpan(event);
459
+ const url = `${this.apiUrl}/track`;
460
+ const payload = this.toTrackPayload(event);
440
461
  this.logger.info("\u{1F4E4} SENDING SINGLE EVENT:", {
441
- eventName: customEventSpan.eventName,
442
- properties: JSON.stringify(customEventSpan.properties, null, 2),
443
- propertiesCount: Object.keys(customEventSpan.properties || {}).length
462
+ name: payload.name,
463
+ websiteId: payload.websiteId,
464
+ source: payload.source,
465
+ properties: JSON.stringify(payload.properties, null, 2)
444
466
  });
445
467
  const response = await fetch(url, {
446
468
  method: "POST",
447
469
  headers: {
448
- "Content-Type": "application/json"
470
+ "Content-Type": "application/json",
471
+ Authorization: `Bearer ${this.apiKey}`
449
472
  },
450
- body: JSON.stringify([customEventSpan])
473
+ body: JSON.stringify(payload)
451
474
  });
452
475
  if (!response.ok) {
453
476
  const errorText = await response.text().catch(() => "Unknown error");
@@ -566,7 +589,10 @@ class Databuddy {
566
589
  properties: {
567
590
  ...this.globalProperties,
568
591
  ...event.properties || {}
569
- }
592
+ },
593
+ websiteId: event.websiteId ?? this.websiteId,
594
+ namespace: event.namespace ?? this.namespace,
595
+ source: event.source ?? this.source
570
596
  }));
571
597
  const processedEvents = [];
572
598
  for (const event of enrichedEvents) {
@@ -593,28 +619,23 @@ class Databuddy {
593
619
  };
594
620
  }
595
621
  try {
596
- const url = `${this.apiUrl}/events?client_id=${encodeURIComponent(this.clientId)}`;
597
- const customEventSpans = processedEvents.map(
598
- (event) => this.toCustomEventSpan(event)
622
+ const url = `${this.apiUrl}/track`;
623
+ const payloads = processedEvents.map(
624
+ (event) => this.toTrackPayload(event)
599
625
  );
600
626
  this.logger.info("\u{1F4E6} SENDING BATCH EVENTS:", {
601
- count: customEventSpans.length,
602
- firstEventName: customEventSpans[0]?.eventName,
603
- firstEventProperties: JSON.stringify(
604
- customEventSpans[0]?.properties,
605
- null,
606
- 2
607
- ),
608
- firstEventPropertiesCount: Object.keys(
609
- customEventSpans[0]?.properties || {}
610
- ).length
627
+ count: payloads.length,
628
+ firstEventName: payloads[0]?.name,
629
+ firstWebsiteId: payloads[0]?.websiteId,
630
+ firstSource: payloads[0]?.source
611
631
  });
612
632
  const response = await fetch(url, {
613
633
  method: "POST",
614
634
  headers: {
615
- "Content-Type": "application/json"
635
+ "Content-Type": "application/json",
636
+ Authorization: `Bearer ${this.apiKey}`
616
637
  },
617
- body: JSON.stringify(customEventSpans)
638
+ body: JSON.stringify(payloads)
618
639
  });
619
640
  if (!response.ok) {
620
641
  const errorText = await response.text().catch(() => "Unknown error");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@databuddy/sdk",
3
- "version": "2.3.28",
3
+ "version": "2.3.29",
4
4
  "description": "Official Databuddy Analytics SDK",
5
5
  "main": "./dist/core/index.mjs",
6
6
  "types": "./dist/core/index.d.ts",