@databuddy/sdk 2.2.0 → 2.2.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.
@@ -5,57 +5,85 @@ interface Logger {
5
5
  debug(msg: string, data?: Record<string, unknown>): void;
6
6
  }
7
7
 
8
+ /**
9
+ * Middleware function that can transform or filter events
10
+ * Return null to drop the event, or return a modified event
11
+ */
12
+ type Middleware = (event: BatchEventInput) => BatchEventInput | null | Promise<BatchEventInput | null>;
8
13
  interface DatabuddyConfig {
14
+ /** Client ID from Databuddy dashboard */
9
15
  clientId: string;
16
+ /** Custom API endpoint (default: https://basket.databuddy.cc) */
10
17
  apiUrl?: string;
18
+ /** Enable debug logging */
11
19
  debug?: boolean;
20
+ /** Custom logger instance */
12
21
  logger?: Logger;
13
- /**
14
- * Enable automatic batching of events
15
- * Default: true
16
- */
22
+ /** Enable automatic batching (default: true) */
17
23
  enableBatching?: boolean;
18
- /**
19
- * Number of events to batch before auto-flushing
20
- * Default: 10, Max: 100
21
- */
24
+ /** Number of events to batch before flushing (default: 10, max: 100) */
22
25
  batchSize?: number;
23
- /**
24
- * Time in milliseconds before auto-flushing batched events
25
- * Default: 2000ms (2 seconds)
26
- */
26
+ /** Time in ms before auto-flushing batched events (default: 2000) */
27
27
  batchTimeout?: number;
28
- /**
29
- * Maximum number of events to queue before auto-flushing
30
- * Default: 1000
31
- */
28
+ /** Maximum number of events to queue (default: 1000) */
32
29
  maxQueueSize?: number;
30
+ /** Middleware functions to transform events */
31
+ middleware?: Middleware[];
32
+ /** Enable event deduplication based on eventId (default: true) */
33
+ enableDeduplication?: boolean;
34
+ /** Maximum deduplication cache size (default: 10000) */
35
+ maxDeduplicationCacheSize?: number;
33
36
  }
34
37
  interface CustomEventInput {
38
+ /** Event name (required) */
35
39
  name: string;
40
+ /** Unique event ID for deduplication */
36
41
  eventId?: string;
42
+ /** Anonymous user ID */
37
43
  anonymousId?: string | null;
44
+ /** Session ID */
38
45
  sessionId?: string | null;
46
+ /** Event timestamp in milliseconds */
39
47
  timestamp?: number | null;
48
+ /** Event properties/metadata */
40
49
  properties?: Record<string, unknown> | null;
41
50
  }
42
51
  interface EventResponse {
52
+ /** Whether the event was successfully sent */
43
53
  success: boolean;
54
+ /** Server-assigned event ID */
44
55
  eventId?: string;
56
+ /** Error message if failed */
45
57
  error?: string;
46
58
  }
47
59
  interface BatchEventInput {
60
+ /** Event type */
48
61
  type: 'custom';
62
+ /** Event name */
49
63
  name: string;
64
+ /** Unique event ID for deduplication */
50
65
  eventId?: string;
66
+ /** Anonymous user ID */
51
67
  anonymousId?: string | null;
68
+ /** Session ID */
52
69
  sessionId?: string | null;
70
+ /** Event timestamp in milliseconds */
53
71
  timestamp?: number | null;
72
+ /** Event properties/metadata */
54
73
  properties?: Record<string, unknown> | null;
55
74
  }
75
+ /**
76
+ * Global properties that will be attached to all events
77
+ */
78
+ interface GlobalProperties {
79
+ [key: string]: unknown;
80
+ }
56
81
  interface BatchEventResponse {
82
+ /** Whether the batch was successfully sent */
57
83
  success: boolean;
84
+ /** Number of events processed */
58
85
  processed?: number;
86
+ /** Results for each event in the batch */
59
87
  results?: Array<{
60
88
  status: string;
61
89
  type?: string;
@@ -63,6 +91,7 @@ interface BatchEventResponse {
63
91
  message?: string;
64
92
  error?: string;
65
93
  }>;
94
+ /** Error message if batch failed */
66
95
  error?: string;
67
96
  }
68
97
 
@@ -75,20 +104,21 @@ declare class Databuddy {
75
104
  private batchTimeout;
76
105
  private queue;
77
106
  private flushTimer;
107
+ private globalProperties;
108
+ private middleware;
109
+ private enableDeduplication;
110
+ private deduplicationCache;
111
+ private maxDeduplicationCacheSize;
78
112
  constructor(config: DatabuddyConfig);
79
113
  /**
80
114
  * Track a custom event
81
- * If batching is enabled, queues the event and auto-flushes when batch size is reached or timeout expires
82
- * If batching is disabled, sends the event immediately
83
- *
84
- * @param event - Custom event data
85
- * @returns Response indicating success or failure
86
- *
115
+ * @param event - Event data to track
116
+ * @returns Promise with success/error response
87
117
  * @example
88
118
  * ```typescript
89
119
  * await client.track({
90
120
  * name: 'user_signup',
91
- * properties: { plan: 'pro' }
121
+ * properties: { plan: 'pro', source: 'web' }
92
122
  * });
93
123
  * ```
94
124
  */
@@ -97,26 +127,19 @@ declare class Databuddy {
97
127
  private scheduleFlush;
98
128
  /**
99
129
  * Manually flush all queued events
100
- * Important for serverless/stateless environments where you need to ensure events are sent before the process exits
101
- *
102
- * @returns Response with batch results
103
- *
130
+ * Useful in serverless environments to ensure events are sent before process exits
131
+ * @returns Promise with batch results
104
132
  * @example
105
133
  * ```typescript
106
- * // In serverless function
107
134
  * await client.track({ name: 'api_call' });
108
- * await client.flush(); // Ensure events are sent before function exits
135
+ * await client.flush(); // Ensure events are sent
109
136
  * ```
110
137
  */
111
138
  flush(): Promise<BatchEventResponse>;
112
139
  /**
113
- * Send multiple custom events in a single batch request
114
- * Max 100 events per batch
115
- * Note: Usually you don't need to call this directly - use track() with batching enabled instead
116
- *
117
- * @param events - Array of custom events
118
- * @returns Response with results for each event
119
- *
140
+ * Send multiple events in a single batch request
141
+ * @param events - Array of events to batch (max 100)
142
+ * @returns Promise with batch results
120
143
  * @example
121
144
  * ```typescript
122
145
  * await client.batch([
@@ -126,7 +149,89 @@ declare class Databuddy {
126
149
  * ```
127
150
  */
128
151
  batch(events: BatchEventInput[]): Promise<BatchEventResponse>;
152
+ /**
153
+ * Set global properties attached to all events
154
+ * Properties are merged with existing globals; event properties override globals
155
+ * @param properties - Properties to merge with existing globals
156
+ * @example
157
+ * ```typescript
158
+ * client.setGlobalProperties({ environment: 'production', version: '1.0.0' });
159
+ * // All subsequent events will include these properties
160
+ * ```
161
+ */
162
+ setGlobalProperties(properties: GlobalProperties): void;
163
+ /**
164
+ * Get current global properties
165
+ * @returns Copy of current global properties
166
+ * @example
167
+ * ```typescript
168
+ * const globals = client.getGlobalProperties();
169
+ * console.log(globals); // { environment: 'production', version: '1.0.0' }
170
+ * ```
171
+ */
172
+ getGlobalProperties(): GlobalProperties;
173
+ /**
174
+ * Clear all global properties
175
+ * @example
176
+ * ```typescript
177
+ * client.clearGlobalProperties();
178
+ * // No more global properties will be attached to events
179
+ * ```
180
+ */
181
+ clearGlobalProperties(): void;
182
+ /**
183
+ * Add middleware to transform events
184
+ * Middleware runs before deduplication and is executed in order
185
+ * Return null to drop the event, or return a modified event
186
+ * @param middleware - Middleware function
187
+ * @example
188
+ * ```typescript
189
+ * client.addMiddleware((event) => {
190
+ * // Add custom field
191
+ * event.properties = { ...event.properties, processed: true };
192
+ * return event;
193
+ * });
194
+ *
195
+ * // Drop events matching a condition
196
+ * client.addMiddleware((event) => {
197
+ * if (event.name === 'unwanted_event') return null;
198
+ * return event;
199
+ * });
200
+ * ```
201
+ */
202
+ addMiddleware(middleware: Middleware): void;
203
+ /**
204
+ * Remove all middleware functions
205
+ * @example
206
+ * ```typescript
207
+ * client.clearMiddleware();
208
+ * // All middleware transformations removed
209
+ * ```
210
+ */
211
+ clearMiddleware(): void;
212
+ /**
213
+ * Get current deduplication cache size
214
+ * @returns Number of event IDs in cache
215
+ * @example
216
+ * ```typescript
217
+ * const size = client.getDeduplicationCacheSize();
218
+ * console.log(`Cache size: ${size}`);
219
+ * ```
220
+ */
221
+ getDeduplicationCacheSize(): number;
222
+ /**
223
+ * Clear the deduplication cache
224
+ * Useful for testing or resetting duplicate detection
225
+ * @example
226
+ * ```typescript
227
+ * client.clearDeduplicationCache();
228
+ * // All cached event IDs cleared
229
+ * ```
230
+ */
231
+ clearDeduplicationCache(): void;
232
+ private applyMiddleware;
233
+ private addToDeduplicationCache;
129
234
  }
130
235
 
131
236
  export { Databuddy, Databuddy as db };
132
- export type { BatchEventInput, BatchEventResponse, CustomEventInput, DatabuddyConfig, EventResponse, Logger };
237
+ export type { BatchEventInput, BatchEventResponse, CustomEventInput, DatabuddyConfig, EventResponse, GlobalProperties, Logger, Middleware };
@@ -78,6 +78,7 @@ const DEFAULT_API_URL = "https://basket.databuddy.cc";
78
78
  const DEFAULT_BATCH_SIZE = 10;
79
79
  const DEFAULT_BATCH_TIMEOUT = 2e3;
80
80
  const DEFAULT_MAX_QUEUE_SIZE = 1e3;
81
+ const DEFAULT_MAX_DEDUPLICATION_CACHE_SIZE = 1e4;
81
82
  class Databuddy {
82
83
  clientId;
83
84
  apiUrl;
@@ -87,6 +88,11 @@ class Databuddy {
87
88
  batchTimeout;
88
89
  queue;
89
90
  flushTimer = null;
91
+ globalProperties = {};
92
+ middleware = [];
93
+ enableDeduplication;
94
+ deduplicationCache = /* @__PURE__ */ new Set();
95
+ maxDeduplicationCacheSize;
90
96
  constructor(config) {
91
97
  if (!config.clientId || typeof config.clientId !== "string") {
92
98
  throw new Error("clientId is required and must be a string");
@@ -97,6 +103,9 @@ class Databuddy {
97
103
  this.batchSize = Math.min(config.batchSize || DEFAULT_BATCH_SIZE, 100);
98
104
  this.batchTimeout = config.batchTimeout || DEFAULT_BATCH_TIMEOUT;
99
105
  this.queue = new EventQueue(config.maxQueueSize || DEFAULT_MAX_QUEUE_SIZE);
106
+ this.middleware = config.middleware || [];
107
+ this.enableDeduplication = config.enableDeduplication !== false;
108
+ this.maxDeduplicationCacheSize = config.maxDeduplicationCacheSize || DEFAULT_MAX_DEDUPLICATION_CACHE_SIZE;
100
109
  if (config.logger) {
101
110
  this.logger = config.logger;
102
111
  } else if (config.debug) {
@@ -109,22 +118,20 @@ class Databuddy {
109
118
  apiUrl: this.apiUrl,
110
119
  enableBatching: this.enableBatching,
111
120
  batchSize: this.batchSize,
112
- batchTimeout: this.batchTimeout
121
+ batchTimeout: this.batchTimeout,
122
+ middlewareCount: this.middleware.length,
123
+ enableDeduplication: this.enableDeduplication
113
124
  });
114
125
  }
115
126
  /**
116
127
  * Track a custom event
117
- * If batching is enabled, queues the event and auto-flushes when batch size is reached or timeout expires
118
- * If batching is disabled, sends the event immediately
119
- *
120
- * @param event - Custom event data
121
- * @returns Response indicating success or failure
122
- *
128
+ * @param event - Event data to track
129
+ * @returns Promise with success/error response
123
130
  * @example
124
131
  * ```typescript
125
132
  * await client.track({
126
133
  * name: 'user_signup',
127
- * properties: { plan: 'pro' }
134
+ * properties: { plan: 'pro', source: 'web' }
128
135
  * });
129
136
  * ```
130
137
  */
@@ -142,12 +149,27 @@ class Databuddy {
142
149
  anonymousId: event.anonymousId,
143
150
  sessionId: event.sessionId,
144
151
  timestamp: event.timestamp,
145
- properties: event.properties || null
152
+ properties: {
153
+ ...this.globalProperties,
154
+ ...event.properties || {}
155
+ }
146
156
  };
157
+ const processedEvent = await this.applyMiddleware(batchEvent);
158
+ if (!processedEvent) {
159
+ this.logger.debug("Event dropped by middleware", { name: event.name });
160
+ return { success: true };
161
+ }
162
+ if (this.enableDeduplication && processedEvent.eventId) {
163
+ if (this.deduplicationCache.has(processedEvent.eventId)) {
164
+ this.logger.debug("Event deduplicated", { eventId: processedEvent.eventId });
165
+ return { success: true };
166
+ }
167
+ this.addToDeduplicationCache(processedEvent.eventId);
168
+ }
147
169
  if (!this.enableBatching) {
148
- return this.send(batchEvent);
170
+ return this.send(processedEvent);
149
171
  }
150
- const shouldFlush = this.queue.add(batchEvent);
172
+ const shouldFlush = this.queue.add(processedEvent);
151
173
  this.logger.debug("Event queued", { queueSize: this.queue.size() });
152
174
  this.scheduleFlush();
153
175
  if (shouldFlush || this.queue.size() >= this.batchSize) {
@@ -218,15 +240,12 @@ class Databuddy {
218
240
  }
219
241
  /**
220
242
  * Manually flush all queued events
221
- * Important for serverless/stateless environments where you need to ensure events are sent before the process exits
222
- *
223
- * @returns Response with batch results
224
- *
243
+ * Useful in serverless environments to ensure events are sent before process exits
244
+ * @returns Promise with batch results
225
245
  * @example
226
246
  * ```typescript
227
- * // In serverless function
228
247
  * await client.track({ name: 'api_call' });
229
- * await client.flush(); // Ensure events are sent before function exits
248
+ * await client.flush(); // Ensure events are sent
230
249
  * ```
231
250
  */
232
251
  async flush() {
@@ -247,13 +266,9 @@ class Databuddy {
247
266
  return this.batch(events);
248
267
  }
249
268
  /**
250
- * Send multiple custom events in a single batch request
251
- * Max 100 events per batch
252
- * Note: Usually you don't need to call this directly - use track() with batching enabled instead
253
- *
254
- * @param events - Array of custom events
255
- * @returns Response with results for each event
256
- *
269
+ * Send multiple events in a single batch request
270
+ * @param events - Array of events to batch (max 100)
271
+ * @returns Promise with batch results
257
272
  * @example
258
273
  * ```typescript
259
274
  * await client.batch([
@@ -289,20 +304,49 @@ class Databuddy {
289
304
  };
290
305
  }
291
306
  }
307
+ const enrichedEvents = events.map((event) => ({
308
+ ...event,
309
+ properties: {
310
+ ...this.globalProperties,
311
+ ...event.properties || {}
312
+ }
313
+ }));
314
+ const processedEvents = [];
315
+ for (const event of enrichedEvents) {
316
+ const processedEvent = await this.applyMiddleware(event);
317
+ if (!processedEvent) {
318
+ continue;
319
+ }
320
+ if (this.enableDeduplication && processedEvent.eventId) {
321
+ if (this.deduplicationCache.has(processedEvent.eventId)) {
322
+ this.logger.debug("Event deduplicated in batch", { eventId: processedEvent.eventId });
323
+ continue;
324
+ }
325
+ this.addToDeduplicationCache(processedEvent.eventId);
326
+ }
327
+ processedEvents.push(processedEvent);
328
+ }
329
+ if (processedEvents.length === 0) {
330
+ return {
331
+ success: true,
332
+ processed: 0,
333
+ results: []
334
+ };
335
+ }
292
336
  try {
293
337
  const url = `${this.apiUrl}/batch?client_id=${encodeURIComponent(this.clientId)}`;
294
338
  this.logger.info("\u{1F4E6} SENDING BATCH EVENTS:", {
295
- count: events.length,
296
- firstEventName: events[0]?.name,
297
- firstEventProperties: JSON.stringify(events[0]?.properties, null, 2),
298
- firstEventPropertiesCount: Object.keys(events[0]?.properties || {}).length
339
+ count: processedEvents.length,
340
+ firstEventName: processedEvents[0]?.name,
341
+ firstEventProperties: JSON.stringify(processedEvents[0]?.properties, null, 2),
342
+ firstEventPropertiesCount: Object.keys(processedEvents[0]?.properties || {}).length
299
343
  });
300
344
  const response = await fetch(url, {
301
345
  method: "POST",
302
346
  headers: {
303
347
  "Content-Type": "application/json"
304
348
  },
305
- body: JSON.stringify(events)
349
+ body: JSON.stringify(processedEvents)
306
350
  });
307
351
  if (!response.ok) {
308
352
  const errorText = await response.text().catch(() => "Unknown error");
@@ -321,7 +365,7 @@ class Databuddy {
321
365
  if (data.status === "success") {
322
366
  return {
323
367
  success: true,
324
- processed: data.processed,
368
+ processed: data.processed || processedEvents.length,
325
369
  results: data.results
326
370
  };
327
371
  }
@@ -339,6 +383,130 @@ class Databuddy {
339
383
  };
340
384
  }
341
385
  }
386
+ /**
387
+ * Set global properties attached to all events
388
+ * Properties are merged with existing globals; event properties override globals
389
+ * @param properties - Properties to merge with existing globals
390
+ * @example
391
+ * ```typescript
392
+ * client.setGlobalProperties({ environment: 'production', version: '1.0.0' });
393
+ * // All subsequent events will include these properties
394
+ * ```
395
+ */
396
+ setGlobalProperties(properties) {
397
+ this.globalProperties = { ...this.globalProperties, ...properties };
398
+ this.logger.debug("Global properties updated", { properties });
399
+ }
400
+ /**
401
+ * Get current global properties
402
+ * @returns Copy of current global properties
403
+ * @example
404
+ * ```typescript
405
+ * const globals = client.getGlobalProperties();
406
+ * console.log(globals); // { environment: 'production', version: '1.0.0' }
407
+ * ```
408
+ */
409
+ getGlobalProperties() {
410
+ return { ...this.globalProperties };
411
+ }
412
+ /**
413
+ * Clear all global properties
414
+ * @example
415
+ * ```typescript
416
+ * client.clearGlobalProperties();
417
+ * // No more global properties will be attached to events
418
+ * ```
419
+ */
420
+ clearGlobalProperties() {
421
+ this.globalProperties = {};
422
+ this.logger.debug("Global properties cleared");
423
+ }
424
+ /**
425
+ * Add middleware to transform events
426
+ * Middleware runs before deduplication and is executed in order
427
+ * Return null to drop the event, or return a modified event
428
+ * @param middleware - Middleware function
429
+ * @example
430
+ * ```typescript
431
+ * client.addMiddleware((event) => {
432
+ * // Add custom field
433
+ * event.properties = { ...event.properties, processed: true };
434
+ * return event;
435
+ * });
436
+ *
437
+ * // Drop events matching a condition
438
+ * client.addMiddleware((event) => {
439
+ * if (event.name === 'unwanted_event') return null;
440
+ * return event;
441
+ * });
442
+ * ```
443
+ */
444
+ addMiddleware(middleware) {
445
+ this.middleware.push(middleware);
446
+ this.logger.debug("Middleware added", { totalMiddleware: this.middleware.length });
447
+ }
448
+ /**
449
+ * Remove all middleware functions
450
+ * @example
451
+ * ```typescript
452
+ * client.clearMiddleware();
453
+ * // All middleware transformations removed
454
+ * ```
455
+ */
456
+ clearMiddleware() {
457
+ this.middleware = [];
458
+ this.logger.debug("Middleware cleared");
459
+ }
460
+ /**
461
+ * Get current deduplication cache size
462
+ * @returns Number of event IDs in cache
463
+ * @example
464
+ * ```typescript
465
+ * const size = client.getDeduplicationCacheSize();
466
+ * console.log(`Cache size: ${size}`);
467
+ * ```
468
+ */
469
+ getDeduplicationCacheSize() {
470
+ return this.deduplicationCache.size;
471
+ }
472
+ /**
473
+ * Clear the deduplication cache
474
+ * Useful for testing or resetting duplicate detection
475
+ * @example
476
+ * ```typescript
477
+ * client.clearDeduplicationCache();
478
+ * // All cached event IDs cleared
479
+ * ```
480
+ */
481
+ clearDeduplicationCache() {
482
+ this.deduplicationCache.clear();
483
+ this.logger.debug("Deduplication cache cleared");
484
+ }
485
+ async applyMiddleware(event) {
486
+ let processedEvent = event;
487
+ for (const middleware of this.middleware) {
488
+ if (!processedEvent) {
489
+ break;
490
+ }
491
+ try {
492
+ processedEvent = await middleware(processedEvent);
493
+ } catch (error) {
494
+ this.logger.error("Middleware error", {
495
+ error: error instanceof Error ? error.message : String(error)
496
+ });
497
+ }
498
+ }
499
+ return processedEvent;
500
+ }
501
+ addToDeduplicationCache(eventId) {
502
+ if (this.deduplicationCache.size >= this.maxDeduplicationCacheSize) {
503
+ const oldest = this.deduplicationCache.values().next().value;
504
+ if (oldest) {
505
+ this.deduplicationCache.delete(oldest);
506
+ }
507
+ }
508
+ this.deduplicationCache.add(eventId);
509
+ }
342
510
  }
343
511
 
344
512
  export { Databuddy, Databuddy as db };
@@ -1,12 +1,25 @@
1
- export { b as Databuddy } from '../shared/@databuddy/sdk.C8T93n5r.mjs';
1
+ import { D as DatabuddyConfig } from '../shared/@databuddy/sdk.DNing6--.mjs';
2
+ import * as react from 'react';
2
3
  import { ReactNode } from 'react';
4
+ import * as jotai_vanilla_internals from 'jotai/vanilla/internals';
3
5
  import { d as FlagsConfig, c as FlagState } from '../shared/@databuddy/sdk.YfiY9DoZ.mjs';
4
6
  export { b as FlagResult, e as FlagsContext } from '../shared/@databuddy/sdk.YfiY9DoZ.mjs';
5
7
 
8
+ /**
9
+ * <Databuddy /> component for Next.js/React apps
10
+ * Injects the databuddy.js script with all config as data attributes
11
+ * Usage: <Databuddy clientId="..." trackScreenViews trackPerformance ... />
12
+ * Or simply: <Databuddy /> (auto-detects clientId from environment variables)
13
+ */
14
+ declare function Databuddy(props: DatabuddyConfig): null;
15
+
6
16
  interface FlagsProviderProps extends FlagsConfig {
7
17
  children: ReactNode;
8
18
  }
9
- declare function FlagsProvider({ children, ...config }: FlagsProviderProps): any;
19
+ declare function FlagsProvider({ children, ...config }: FlagsProviderProps): react.FunctionComponentElement<{
20
+ children?: ReactNode;
21
+ store?: jotai_vanilla_internals.INTERNAL_Store;
22
+ }>;
10
23
  declare function useFlags(): {
11
24
  isEnabled: (key: string) => FlagState;
12
25
  fetchAllFlags: () => Promise<void> | undefined;
@@ -14,4 +27,4 @@ declare function useFlags(): {
14
27
  refresh: (forceClear?: boolean) => void;
15
28
  };
16
29
 
17
- export { FlagState, FlagsConfig, FlagsProvider, useFlags };
30
+ export { Databuddy, FlagState, FlagsConfig, FlagsProvider, useFlags };
@@ -1,12 +1,25 @@
1
- export { b as Databuddy } from '../shared/@databuddy/sdk.C8T93n5r.js';
1
+ import { D as DatabuddyConfig } from '../shared/@databuddy/sdk.DNing6--.js';
2
+ import * as react from 'react';
2
3
  import { ReactNode } from 'react';
4
+ import * as jotai_vanilla_internals from 'jotai/vanilla/internals';
3
5
  import { d as FlagsConfig, c as FlagState } from '../shared/@databuddy/sdk.YfiY9DoZ.js';
4
6
  export { b as FlagResult, e as FlagsContext } from '../shared/@databuddy/sdk.YfiY9DoZ.js';
5
7
 
8
+ /**
9
+ * <Databuddy /> component for Next.js/React apps
10
+ * Injects the databuddy.js script with all config as data attributes
11
+ * Usage: <Databuddy clientId="..." trackScreenViews trackPerformance ... />
12
+ * Or simply: <Databuddy /> (auto-detects clientId from environment variables)
13
+ */
14
+ declare function Databuddy(props: DatabuddyConfig): null;
15
+
6
16
  interface FlagsProviderProps extends FlagsConfig {
7
17
  children: ReactNode;
8
18
  }
9
- declare function FlagsProvider({ children, ...config }: FlagsProviderProps): any;
19
+ declare function FlagsProvider({ children, ...config }: FlagsProviderProps): react.FunctionComponentElement<{
20
+ children?: ReactNode;
21
+ store?: jotai_vanilla_internals.INTERNAL_Store;
22
+ }>;
10
23
  declare function useFlags(): {
11
24
  isEnabled: (key: string) => FlagState;
12
25
  fetchAllFlags: () => Promise<void> | undefined;
@@ -14,4 +27,4 @@ declare function useFlags(): {
14
27
  refresh: (forceClear?: boolean) => void;
15
28
  };
16
29
 
17
- export { FlagState, FlagsConfig, FlagsProvider, useFlags };
30
+ export { Databuddy, FlagState, FlagsConfig, FlagsProvider, useFlags };
@@ -1,9 +1,26 @@
1
1
  'use client';
2
2
 
3
- export { D as Databuddy } from '../shared/@databuddy/sdk.aVQee-4k.mjs';
3
+ import { i as isScriptInjected, c as createScript, B as BrowserFlagStorage, C as CoreFlagsManager, l as logger } from '../shared/@databuddy/sdk.tFAHtL2M.mjs';
4
+ import { d as detectClientId } from '../shared/@databuddy/sdk.BUsPV0LH.mjs';
4
5
  import { createStore, atom, Provider, useAtom } from 'jotai';
5
6
  import { useRef, useEffect, createElement } from 'react';
6
- import { B as BrowserFlagStorage, C as CoreFlagsManager, l as logger } from '../shared/@databuddy/sdk.tFAHtL2M.mjs';
7
+
8
+ function Databuddy(props) {
9
+ const clientId = detectClientId(props.clientId);
10
+ if (!clientId) {
11
+ if (typeof window !== "undefined" && !props.disabled && props.debug) {
12
+ console.warn(
13
+ "Databuddy: No client ID found. Please provide clientId prop or set NEXT_PUBLIC_DATABUDDY_CLIENT_ID environment variable."
14
+ );
15
+ }
16
+ return null;
17
+ }
18
+ if (typeof window !== "undefined" && !props.disabled && !isScriptInjected()) {
19
+ const script = createScript({ ...props, clientId });
20
+ document.head.appendChild(script);
21
+ }
22
+ return null;
23
+ }
7
24
 
8
25
  const flagsStore = createStore();
9
26
  const managerAtom = atom(null);
@@ -102,4 +119,4 @@ function useFlags() {
102
119
  };
103
120
  }
104
121
 
105
- export { FlagsProvider, useFlags };
122
+ export { Databuddy, FlagsProvider, useFlags };