@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.
- package/dist/ai/vercel/index.d.mts +12 -0
- package/dist/ai/vercel/index.d.ts +12 -0
- package/dist/ai/vercel/index.mjs +45 -0
- package/dist/core/index.d.mts +24 -7
- package/dist/core/index.d.ts +24 -7
- package/dist/core/index.mjs +30 -8
- package/dist/node/index.d.mts +142 -37
- package/dist/node/index.d.ts +142 -37
- package/dist/node/index.mjs +198 -30
- package/dist/react/index.d.mts +16 -3
- package/dist/react/index.d.ts +16 -3
- package/dist/react/index.mjs +20 -3
- package/dist/shared/@databuddy/{sdk.aVQee-4k.mjs → sdk.BUsPV0LH.mjs} +1 -20
- package/dist/shared/@databuddy/{sdk.C8T93n5r.d.mts → sdk.DNing6--.d.mts} +9 -10
- package/dist/shared/@databuddy/{sdk.C8T93n5r.d.ts → sdk.DNing6--.d.ts} +9 -10
- package/dist/vue/index.d.mts +80 -1
- package/dist/vue/index.d.ts +80 -1
- package/package.json +34 -8
package/dist/node/index.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
82
|
-
*
|
|
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
|
-
*
|
|
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
|
|
135
|
+
* await client.flush(); // Ensure events are sent
|
|
109
136
|
* ```
|
|
110
137
|
*/
|
|
111
138
|
flush(): Promise<BatchEventResponse>;
|
|
112
139
|
/**
|
|
113
|
-
* Send multiple
|
|
114
|
-
*
|
|
115
|
-
*
|
|
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 };
|
package/dist/node/index.mjs
CHANGED
|
@@ -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
|
-
*
|
|
118
|
-
*
|
|
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:
|
|
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(
|
|
170
|
+
return this.send(processedEvent);
|
|
149
171
|
}
|
|
150
|
-
const shouldFlush = this.queue.add(
|
|
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
|
-
*
|
|
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
|
|
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
|
|
251
|
-
*
|
|
252
|
-
*
|
|
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:
|
|
296
|
-
firstEventName:
|
|
297
|
-
firstEventProperties: JSON.stringify(
|
|
298
|
-
firstEventPropertiesCount: Object.keys(
|
|
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(
|
|
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 };
|
package/dist/react/index.d.mts
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
|
-
|
|
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):
|
|
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 };
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
|
-
|
|
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):
|
|
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 };
|
package/dist/react/index.mjs
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
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 };
|