@databuddy/sdk 2.1.78 → 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 +31 -9
- package/dist/node/index.d.mts +237 -0
- package/dist/node/index.d.ts +237 -0
- package/dist/node/index.mjs +512 -0
- 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.CHuEu0ou.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/shared/@databuddy/{sdk.ItWNeH-Y.mjs → sdk.tFAHtL2M.mjs} +1 -1
- package/dist/vue/index.d.mts +80 -1
- package/dist/vue/index.d.ts +80 -1
- package/dist/vue/index.mjs +1 -1
- package/package.json +40 -6
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
function createLogger(debug = false) {
|
|
2
|
+
try {
|
|
3
|
+
const pino = require("pino");
|
|
4
|
+
return pino({
|
|
5
|
+
level: debug ? "debug" : "info",
|
|
6
|
+
name: "databuddy"
|
|
7
|
+
});
|
|
8
|
+
} catch {
|
|
9
|
+
return createConsoleLogger(debug);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function createConsoleLogger(debug) {
|
|
13
|
+
const noop = () => {
|
|
14
|
+
};
|
|
15
|
+
return {
|
|
16
|
+
info(msg, data) {
|
|
17
|
+
if (debug) {
|
|
18
|
+
console.info(`[Databuddy] ${msg}`, data ? JSON.stringify(data) : "");
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
error(msg, data) {
|
|
22
|
+
if (debug) {
|
|
23
|
+
console.error(
|
|
24
|
+
`[Databuddy] ${msg}`,
|
|
25
|
+
data ? JSON.stringify(data) : ""
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
warn(msg, data) {
|
|
30
|
+
if (debug) {
|
|
31
|
+
console.warn(`[Databuddy] ${msg}`, data ? JSON.stringify(data) : "");
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
debug: debug ? (msg, data) => {
|
|
35
|
+
console.debug(
|
|
36
|
+
`[Databuddy] ${msg}`,
|
|
37
|
+
data ? JSON.stringify(data) : ""
|
|
38
|
+
);
|
|
39
|
+
} : noop
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function createNoopLogger() {
|
|
43
|
+
const noop = () => {
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
info: noop,
|
|
47
|
+
error: noop,
|
|
48
|
+
warn: noop,
|
|
49
|
+
debug: noop
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
class EventQueue {
|
|
54
|
+
queue = [];
|
|
55
|
+
maxSize;
|
|
56
|
+
constructor(maxSize) {
|
|
57
|
+
this.maxSize = maxSize;
|
|
58
|
+
}
|
|
59
|
+
add(event) {
|
|
60
|
+
this.queue.push(event);
|
|
61
|
+
return this.queue.length >= this.maxSize;
|
|
62
|
+
}
|
|
63
|
+
getAll() {
|
|
64
|
+
return [...this.queue];
|
|
65
|
+
}
|
|
66
|
+
clear() {
|
|
67
|
+
this.queue = [];
|
|
68
|
+
}
|
|
69
|
+
size() {
|
|
70
|
+
return this.queue.length;
|
|
71
|
+
}
|
|
72
|
+
isEmpty() {
|
|
73
|
+
return this.queue.length === 0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const DEFAULT_API_URL = "https://basket.databuddy.cc";
|
|
78
|
+
const DEFAULT_BATCH_SIZE = 10;
|
|
79
|
+
const DEFAULT_BATCH_TIMEOUT = 2e3;
|
|
80
|
+
const DEFAULT_MAX_QUEUE_SIZE = 1e3;
|
|
81
|
+
const DEFAULT_MAX_DEDUPLICATION_CACHE_SIZE = 1e4;
|
|
82
|
+
class Databuddy {
|
|
83
|
+
clientId;
|
|
84
|
+
apiUrl;
|
|
85
|
+
logger;
|
|
86
|
+
enableBatching;
|
|
87
|
+
batchSize;
|
|
88
|
+
batchTimeout;
|
|
89
|
+
queue;
|
|
90
|
+
flushTimer = null;
|
|
91
|
+
globalProperties = {};
|
|
92
|
+
middleware = [];
|
|
93
|
+
enableDeduplication;
|
|
94
|
+
deduplicationCache = /* @__PURE__ */ new Set();
|
|
95
|
+
maxDeduplicationCacheSize;
|
|
96
|
+
constructor(config) {
|
|
97
|
+
if (!config.clientId || typeof config.clientId !== "string") {
|
|
98
|
+
throw new Error("clientId is required and must be a string");
|
|
99
|
+
}
|
|
100
|
+
this.clientId = config.clientId.trim();
|
|
101
|
+
this.apiUrl = config.apiUrl?.trim() || DEFAULT_API_URL;
|
|
102
|
+
this.enableBatching = config.enableBatching !== false;
|
|
103
|
+
this.batchSize = Math.min(config.batchSize || DEFAULT_BATCH_SIZE, 100);
|
|
104
|
+
this.batchTimeout = config.batchTimeout || DEFAULT_BATCH_TIMEOUT;
|
|
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;
|
|
109
|
+
if (config.logger) {
|
|
110
|
+
this.logger = config.logger;
|
|
111
|
+
} else if (config.debug) {
|
|
112
|
+
this.logger = createLogger(true);
|
|
113
|
+
} else {
|
|
114
|
+
this.logger = createNoopLogger();
|
|
115
|
+
}
|
|
116
|
+
this.logger.info("Initialized", {
|
|
117
|
+
clientId: this.clientId,
|
|
118
|
+
apiUrl: this.apiUrl,
|
|
119
|
+
enableBatching: this.enableBatching,
|
|
120
|
+
batchSize: this.batchSize,
|
|
121
|
+
batchTimeout: this.batchTimeout,
|
|
122
|
+
middlewareCount: this.middleware.length,
|
|
123
|
+
enableDeduplication: this.enableDeduplication
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Track a custom event
|
|
128
|
+
* @param event - Event data to track
|
|
129
|
+
* @returns Promise with success/error response
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* await client.track({
|
|
133
|
+
* name: 'user_signup',
|
|
134
|
+
* properties: { plan: 'pro', source: 'web' }
|
|
135
|
+
* });
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
async track(event) {
|
|
139
|
+
if (!event.name || typeof event.name !== "string") {
|
|
140
|
+
return {
|
|
141
|
+
success: false,
|
|
142
|
+
error: "Event name is required and must be a string"
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const batchEvent = {
|
|
146
|
+
type: "custom",
|
|
147
|
+
name: event.name,
|
|
148
|
+
eventId: event.eventId,
|
|
149
|
+
anonymousId: event.anonymousId,
|
|
150
|
+
sessionId: event.sessionId,
|
|
151
|
+
timestamp: event.timestamp,
|
|
152
|
+
properties: {
|
|
153
|
+
...this.globalProperties,
|
|
154
|
+
...event.properties || {}
|
|
155
|
+
}
|
|
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
|
+
}
|
|
169
|
+
if (!this.enableBatching) {
|
|
170
|
+
return this.send(processedEvent);
|
|
171
|
+
}
|
|
172
|
+
const shouldFlush = this.queue.add(processedEvent);
|
|
173
|
+
this.logger.debug("Event queued", { queueSize: this.queue.size() });
|
|
174
|
+
this.scheduleFlush();
|
|
175
|
+
if (shouldFlush || this.queue.size() >= this.batchSize) {
|
|
176
|
+
await this.flush();
|
|
177
|
+
}
|
|
178
|
+
return { success: true };
|
|
179
|
+
}
|
|
180
|
+
async send(event) {
|
|
181
|
+
try {
|
|
182
|
+
const url = `${this.apiUrl}/?client_id=${encodeURIComponent(this.clientId)}`;
|
|
183
|
+
this.logger.info("\u{1F4E4} SENDING SINGLE EVENT:", {
|
|
184
|
+
name: event.name,
|
|
185
|
+
properties: JSON.stringify(event.properties, null, 2),
|
|
186
|
+
propertiesCount: Object.keys(event.properties || {}).length
|
|
187
|
+
});
|
|
188
|
+
const response = await fetch(url, {
|
|
189
|
+
method: "POST",
|
|
190
|
+
headers: {
|
|
191
|
+
"Content-Type": "application/json"
|
|
192
|
+
},
|
|
193
|
+
body: JSON.stringify(event)
|
|
194
|
+
});
|
|
195
|
+
if (!response.ok) {
|
|
196
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
197
|
+
this.logger.error("Request failed", {
|
|
198
|
+
status: response.status,
|
|
199
|
+
statusText: response.statusText,
|
|
200
|
+
body: errorText
|
|
201
|
+
});
|
|
202
|
+
return {
|
|
203
|
+
success: false,
|
|
204
|
+
error: `HTTP ${response.status}: ${response.statusText}`
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
const data = await response.json();
|
|
208
|
+
this.logger.info("Response received", data);
|
|
209
|
+
if (data.status === "success") {
|
|
210
|
+
return {
|
|
211
|
+
success: true,
|
|
212
|
+
eventId: data.eventId
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
success: false,
|
|
217
|
+
error: data.message || "Unknown error from server"
|
|
218
|
+
};
|
|
219
|
+
} catch (error) {
|
|
220
|
+
this.logger.error("Request error", {
|
|
221
|
+
error: error instanceof Error ? error.message : String(error)
|
|
222
|
+
});
|
|
223
|
+
return {
|
|
224
|
+
success: false,
|
|
225
|
+
error: error instanceof Error ? error.message : "Network request failed"
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
scheduleFlush() {
|
|
230
|
+
if (this.flushTimer) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
this.flushTimer = setTimeout(() => {
|
|
234
|
+
this.flush().catch((error) => {
|
|
235
|
+
this.logger.error("Auto-flush error", {
|
|
236
|
+
error: error instanceof Error ? error.message : String(error)
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
}, this.batchTimeout);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Manually flush all queued events
|
|
243
|
+
* Useful in serverless environments to ensure events are sent before process exits
|
|
244
|
+
* @returns Promise with batch results
|
|
245
|
+
* @example
|
|
246
|
+
* ```typescript
|
|
247
|
+
* await client.track({ name: 'api_call' });
|
|
248
|
+
* await client.flush(); // Ensure events are sent
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
async flush() {
|
|
252
|
+
if (this.flushTimer) {
|
|
253
|
+
clearTimeout(this.flushTimer);
|
|
254
|
+
this.flushTimer = null;
|
|
255
|
+
}
|
|
256
|
+
if (this.queue.isEmpty()) {
|
|
257
|
+
return {
|
|
258
|
+
success: true,
|
|
259
|
+
processed: 0,
|
|
260
|
+
results: []
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
const events = this.queue.getAll();
|
|
264
|
+
this.queue.clear();
|
|
265
|
+
this.logger.info("Flushing events", { count: events.length });
|
|
266
|
+
return this.batch(events);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
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
|
|
272
|
+
* @example
|
|
273
|
+
* ```typescript
|
|
274
|
+
* await client.batch([
|
|
275
|
+
* { type: 'custom', name: 'event1', properties: { foo: 'bar' } },
|
|
276
|
+
* { type: 'custom', name: 'event2', properties: { baz: 'qux' } }
|
|
277
|
+
* ]);
|
|
278
|
+
* ```
|
|
279
|
+
*/
|
|
280
|
+
async batch(events) {
|
|
281
|
+
if (!Array.isArray(events)) {
|
|
282
|
+
return {
|
|
283
|
+
success: false,
|
|
284
|
+
error: "Events must be an array"
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
if (events.length === 0) {
|
|
288
|
+
return {
|
|
289
|
+
success: false,
|
|
290
|
+
error: "Events array cannot be empty"
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
if (events.length > 100) {
|
|
294
|
+
return {
|
|
295
|
+
success: false,
|
|
296
|
+
error: "Batch size cannot exceed 100 events"
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
for (const event of events) {
|
|
300
|
+
if (!event.name || typeof event.name !== "string") {
|
|
301
|
+
return {
|
|
302
|
+
success: false,
|
|
303
|
+
error: "All events must have a valid name"
|
|
304
|
+
};
|
|
305
|
+
}
|
|
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
|
+
}
|
|
336
|
+
try {
|
|
337
|
+
const url = `${this.apiUrl}/batch?client_id=${encodeURIComponent(this.clientId)}`;
|
|
338
|
+
this.logger.info("\u{1F4E6} SENDING BATCH EVENTS:", {
|
|
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
|
|
343
|
+
});
|
|
344
|
+
const response = await fetch(url, {
|
|
345
|
+
method: "POST",
|
|
346
|
+
headers: {
|
|
347
|
+
"Content-Type": "application/json"
|
|
348
|
+
},
|
|
349
|
+
body: JSON.stringify(processedEvents)
|
|
350
|
+
});
|
|
351
|
+
if (!response.ok) {
|
|
352
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
353
|
+
this.logger.error("Batch request failed", {
|
|
354
|
+
status: response.status,
|
|
355
|
+
statusText: response.statusText,
|
|
356
|
+
body: errorText
|
|
357
|
+
});
|
|
358
|
+
return {
|
|
359
|
+
success: false,
|
|
360
|
+
error: `HTTP ${response.status}: ${response.statusText}`
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
const data = await response.json();
|
|
364
|
+
this.logger.info("Batch response received", data);
|
|
365
|
+
if (data.status === "success") {
|
|
366
|
+
return {
|
|
367
|
+
success: true,
|
|
368
|
+
processed: data.processed || processedEvents.length,
|
|
369
|
+
results: data.results
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
success: false,
|
|
374
|
+
error: data.message || "Unknown error from server"
|
|
375
|
+
};
|
|
376
|
+
} catch (error) {
|
|
377
|
+
this.logger.error("Batch request error", {
|
|
378
|
+
error: error instanceof Error ? error.message : String(error)
|
|
379
|
+
});
|
|
380
|
+
return {
|
|
381
|
+
success: false,
|
|
382
|
+
error: error instanceof Error ? error.message : "Network request failed"
|
|
383
|
+
};
|
|
384
|
+
}
|
|
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
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
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 };
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { i as isScriptInjected, c as createScript } from './sdk.ItWNeH-Y.mjs';
|
|
2
|
-
|
|
3
1
|
function detectClientId(providedClientId) {
|
|
4
2
|
if (providedClientId) {
|
|
5
3
|
return providedClientId;
|
|
@@ -24,21 +22,4 @@ function detectClientId(providedClientId) {
|
|
|
24
22
|
return;
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
const clientId = detectClientId(props.clientId);
|
|
29
|
-
if (!clientId) {
|
|
30
|
-
if (typeof window !== "undefined" && !props.disabled && props.debug) {
|
|
31
|
-
console.warn(
|
|
32
|
-
"Databuddy: No client ID found. Please provide clientId prop or set NEXT_PUBLIC_DATABUDDY_CLIENT_ID environment variable."
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
if (typeof window !== "undefined" && !props.disabled && !isScriptInjected()) {
|
|
38
|
-
const script = createScript({ ...props, clientId });
|
|
39
|
-
document.head.appendChild(script);
|
|
40
|
-
}
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export { Databuddy as D, detectClientId as d };
|
|
25
|
+
export { detectClientId as d };
|
|
@@ -276,6 +276,14 @@ type PropertiesForEvent<T extends EventName> = T extends keyof EventTypeMap ? Ev
|
|
|
276
276
|
* Databuddy tracker instance interface
|
|
277
277
|
*/
|
|
278
278
|
interface DatabuddyTracker {
|
|
279
|
+
/**
|
|
280
|
+
* Current anonymous user ID
|
|
281
|
+
*/
|
|
282
|
+
anonymousId: string;
|
|
283
|
+
/**
|
|
284
|
+
* Current session ID
|
|
285
|
+
*/
|
|
286
|
+
sessionId: string;
|
|
279
287
|
/**
|
|
280
288
|
* Track a custom event
|
|
281
289
|
*/
|
|
@@ -333,13 +341,4 @@ type TrackFunction = <T extends EventName>(eventName: T, properties?: Properties
|
|
|
333
341
|
type ScreenViewFunction = (path?: string, properties?: EventProperties) => void;
|
|
334
342
|
type SetGlobalPropertiesFunction = (properties: EventProperties) => void;
|
|
335
343
|
|
|
336
|
-
|
|
337
|
-
* <Databuddy /> component for Next.js/React apps
|
|
338
|
-
* Injects the databuddy.js script with all config as data attributes
|
|
339
|
-
* Usage: <Databuddy clientId="..." trackScreenViews trackPerformance ... />
|
|
340
|
-
* Or simply: <Databuddy /> (auto-detects clientId from environment variables)
|
|
341
|
-
*/
|
|
342
|
-
declare function Databuddy(props: DatabuddyConfig): null;
|
|
343
|
-
|
|
344
|
-
export { Databuddy as b };
|
|
345
|
-
export type { BaseEventProperties as B, DatabuddyConfig as D, EventProperties as E, PropertiesForEvent as P, ScreenViewFunction as S, TrackFunction as T, DatabuddyTracker as a, EventTypeMap as c, EventName as d, DataAttributes as e, SetGlobalPropertiesFunction as f };
|
|
344
|
+
export type { BaseEventProperties as B, DatabuddyConfig as D, EventProperties as E, PropertiesForEvent as P, ScreenViewFunction as S, TrackFunction as T, DatabuddyTracker as a, EventTypeMap as b, EventName as c, DataAttributes as d, SetGlobalPropertiesFunction as e };
|
|
@@ -276,6 +276,14 @@ type PropertiesForEvent<T extends EventName> = T extends keyof EventTypeMap ? Ev
|
|
|
276
276
|
* Databuddy tracker instance interface
|
|
277
277
|
*/
|
|
278
278
|
interface DatabuddyTracker {
|
|
279
|
+
/**
|
|
280
|
+
* Current anonymous user ID
|
|
281
|
+
*/
|
|
282
|
+
anonymousId: string;
|
|
283
|
+
/**
|
|
284
|
+
* Current session ID
|
|
285
|
+
*/
|
|
286
|
+
sessionId: string;
|
|
279
287
|
/**
|
|
280
288
|
* Track a custom event
|
|
281
289
|
*/
|
|
@@ -333,13 +341,4 @@ type TrackFunction = <T extends EventName>(eventName: T, properties?: Properties
|
|
|
333
341
|
type ScreenViewFunction = (path?: string, properties?: EventProperties) => void;
|
|
334
342
|
type SetGlobalPropertiesFunction = (properties: EventProperties) => void;
|
|
335
343
|
|
|
336
|
-
|
|
337
|
-
* <Databuddy /> component for Next.js/React apps
|
|
338
|
-
* Injects the databuddy.js script with all config as data attributes
|
|
339
|
-
* Usage: <Databuddy clientId="..." trackScreenViews trackPerformance ... />
|
|
340
|
-
* Or simply: <Databuddy /> (auto-detects clientId from environment variables)
|
|
341
|
-
*/
|
|
342
|
-
declare function Databuddy(props: DatabuddyConfig): null;
|
|
343
|
-
|
|
344
|
-
export { Databuddy as b };
|
|
345
|
-
export type { BaseEventProperties as B, DatabuddyConfig as D, EventProperties as E, PropertiesForEvent as P, ScreenViewFunction as S, TrackFunction as T, DatabuddyTracker as a, EventTypeMap as c, EventName as d, DataAttributes as e, SetGlobalPropertiesFunction as f };
|
|
344
|
+
export type { BaseEventProperties as B, DatabuddyConfig as D, EventProperties as E, PropertiesForEvent as P, ScreenViewFunction as S, TrackFunction as T, DatabuddyTracker as a, EventTypeMap as b, EventName as c, DataAttributes as d, SetGlobalPropertiesFunction as e };
|