@databuddy/sdk 2.1.77 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,344 @@
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
+ class Databuddy {
82
+ clientId;
83
+ apiUrl;
84
+ logger;
85
+ enableBatching;
86
+ batchSize;
87
+ batchTimeout;
88
+ queue;
89
+ flushTimer = null;
90
+ constructor(config) {
91
+ if (!config.clientId || typeof config.clientId !== "string") {
92
+ throw new Error("clientId is required and must be a string");
93
+ }
94
+ this.clientId = config.clientId.trim();
95
+ this.apiUrl = config.apiUrl?.trim() || DEFAULT_API_URL;
96
+ this.enableBatching = config.enableBatching !== false;
97
+ this.batchSize = Math.min(config.batchSize || DEFAULT_BATCH_SIZE, 100);
98
+ this.batchTimeout = config.batchTimeout || DEFAULT_BATCH_TIMEOUT;
99
+ this.queue = new EventQueue(config.maxQueueSize || DEFAULT_MAX_QUEUE_SIZE);
100
+ if (config.logger) {
101
+ this.logger = config.logger;
102
+ } else if (config.debug) {
103
+ this.logger = createLogger(true);
104
+ } else {
105
+ this.logger = createNoopLogger();
106
+ }
107
+ this.logger.info("Initialized", {
108
+ clientId: this.clientId,
109
+ apiUrl: this.apiUrl,
110
+ enableBatching: this.enableBatching,
111
+ batchSize: this.batchSize,
112
+ batchTimeout: this.batchTimeout
113
+ });
114
+ }
115
+ /**
116
+ * 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
+ *
123
+ * @example
124
+ * ```typescript
125
+ * await client.track({
126
+ * name: 'user_signup',
127
+ * properties: { plan: 'pro' }
128
+ * });
129
+ * ```
130
+ */
131
+ async track(event) {
132
+ if (!event.name || typeof event.name !== "string") {
133
+ return {
134
+ success: false,
135
+ error: "Event name is required and must be a string"
136
+ };
137
+ }
138
+ const batchEvent = {
139
+ type: "custom",
140
+ name: event.name,
141
+ eventId: event.eventId,
142
+ anonymousId: event.anonymousId,
143
+ sessionId: event.sessionId,
144
+ timestamp: event.timestamp,
145
+ properties: event.properties || null
146
+ };
147
+ if (!this.enableBatching) {
148
+ return this.send(batchEvent);
149
+ }
150
+ const shouldFlush = this.queue.add(batchEvent);
151
+ this.logger.debug("Event queued", { queueSize: this.queue.size() });
152
+ this.scheduleFlush();
153
+ if (shouldFlush || this.queue.size() >= this.batchSize) {
154
+ await this.flush();
155
+ }
156
+ return { success: true };
157
+ }
158
+ async send(event) {
159
+ try {
160
+ const url = `${this.apiUrl}/?client_id=${encodeURIComponent(this.clientId)}`;
161
+ this.logger.info("\u{1F4E4} SENDING SINGLE EVENT:", {
162
+ name: event.name,
163
+ properties: JSON.stringify(event.properties, null, 2),
164
+ propertiesCount: Object.keys(event.properties || {}).length
165
+ });
166
+ const response = await fetch(url, {
167
+ method: "POST",
168
+ headers: {
169
+ "Content-Type": "application/json"
170
+ },
171
+ body: JSON.stringify(event)
172
+ });
173
+ if (!response.ok) {
174
+ const errorText = await response.text().catch(() => "Unknown error");
175
+ this.logger.error("Request failed", {
176
+ status: response.status,
177
+ statusText: response.statusText,
178
+ body: errorText
179
+ });
180
+ return {
181
+ success: false,
182
+ error: `HTTP ${response.status}: ${response.statusText}`
183
+ };
184
+ }
185
+ const data = await response.json();
186
+ this.logger.info("Response received", data);
187
+ if (data.status === "success") {
188
+ return {
189
+ success: true,
190
+ eventId: data.eventId
191
+ };
192
+ }
193
+ return {
194
+ success: false,
195
+ error: data.message || "Unknown error from server"
196
+ };
197
+ } catch (error) {
198
+ this.logger.error("Request error", {
199
+ error: error instanceof Error ? error.message : String(error)
200
+ });
201
+ return {
202
+ success: false,
203
+ error: error instanceof Error ? error.message : "Network request failed"
204
+ };
205
+ }
206
+ }
207
+ scheduleFlush() {
208
+ if (this.flushTimer) {
209
+ return;
210
+ }
211
+ this.flushTimer = setTimeout(() => {
212
+ this.flush().catch((error) => {
213
+ this.logger.error("Auto-flush error", {
214
+ error: error instanceof Error ? error.message : String(error)
215
+ });
216
+ });
217
+ }, this.batchTimeout);
218
+ }
219
+ /**
220
+ * 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
+ *
225
+ * @example
226
+ * ```typescript
227
+ * // In serverless function
228
+ * await client.track({ name: 'api_call' });
229
+ * await client.flush(); // Ensure events are sent before function exits
230
+ * ```
231
+ */
232
+ async flush() {
233
+ if (this.flushTimer) {
234
+ clearTimeout(this.flushTimer);
235
+ this.flushTimer = null;
236
+ }
237
+ if (this.queue.isEmpty()) {
238
+ return {
239
+ success: true,
240
+ processed: 0,
241
+ results: []
242
+ };
243
+ }
244
+ const events = this.queue.getAll();
245
+ this.queue.clear();
246
+ this.logger.info("Flushing events", { count: events.length });
247
+ return this.batch(events);
248
+ }
249
+ /**
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
+ *
257
+ * @example
258
+ * ```typescript
259
+ * await client.batch([
260
+ * { type: 'custom', name: 'event1', properties: { foo: 'bar' } },
261
+ * { type: 'custom', name: 'event2', properties: { baz: 'qux' } }
262
+ * ]);
263
+ * ```
264
+ */
265
+ async batch(events) {
266
+ if (!Array.isArray(events)) {
267
+ return {
268
+ success: false,
269
+ error: "Events must be an array"
270
+ };
271
+ }
272
+ if (events.length === 0) {
273
+ return {
274
+ success: false,
275
+ error: "Events array cannot be empty"
276
+ };
277
+ }
278
+ if (events.length > 100) {
279
+ return {
280
+ success: false,
281
+ error: "Batch size cannot exceed 100 events"
282
+ };
283
+ }
284
+ for (const event of events) {
285
+ if (!event.name || typeof event.name !== "string") {
286
+ return {
287
+ success: false,
288
+ error: "All events must have a valid name"
289
+ };
290
+ }
291
+ }
292
+ try {
293
+ const url = `${this.apiUrl}/batch?client_id=${encodeURIComponent(this.clientId)}`;
294
+ 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
299
+ });
300
+ const response = await fetch(url, {
301
+ method: "POST",
302
+ headers: {
303
+ "Content-Type": "application/json"
304
+ },
305
+ body: JSON.stringify(events)
306
+ });
307
+ if (!response.ok) {
308
+ const errorText = await response.text().catch(() => "Unknown error");
309
+ this.logger.error("Batch request failed", {
310
+ status: response.status,
311
+ statusText: response.statusText,
312
+ body: errorText
313
+ });
314
+ return {
315
+ success: false,
316
+ error: `HTTP ${response.status}: ${response.statusText}`
317
+ };
318
+ }
319
+ const data = await response.json();
320
+ this.logger.info("Batch response received", data);
321
+ if (data.status === "success") {
322
+ return {
323
+ success: true,
324
+ processed: data.processed,
325
+ results: data.results
326
+ };
327
+ }
328
+ return {
329
+ success: false,
330
+ error: data.message || "Unknown error from server"
331
+ };
332
+ } catch (error) {
333
+ this.logger.error("Batch request error", {
334
+ error: error instanceof Error ? error.message : String(error)
335
+ });
336
+ return {
337
+ success: false,
338
+ error: error instanceof Error ? error.message : "Network request failed"
339
+ };
340
+ }
341
+ }
342
+ }
343
+
344
+ export { Databuddy, Databuddy as db };
@@ -1,21 +1,12 @@
1
1
  export { b as Databuddy } from '../shared/@databuddy/sdk.C8T93n5r.mjs';
2
- import * as react from 'react';
3
2
  import { ReactNode } from 'react';
4
- import * as jotai from 'jotai';
5
3
  import { d as FlagsConfig, c as FlagState } from '../shared/@databuddy/sdk.YfiY9DoZ.mjs';
6
4
  export { b as FlagResult, e as FlagsContext } from '../shared/@databuddy/sdk.YfiY9DoZ.mjs';
7
5
 
8
6
  interface FlagsProviderProps extends FlagsConfig {
9
7
  children: ReactNode;
10
8
  }
11
- declare function FlagsProvider({ children, ...config }: FlagsProviderProps): react.FunctionComponentElement<{
12
- children?: ReactNode;
13
- store?: {
14
- get: <Value>(atom: jotai.Atom<Value>) => Value;
15
- set: <Value, Args extends unknown[], Result>(atom: jotai.WritableAtom<Value, Args, Result>, ...args: Args) => Result;
16
- sub: (atom: jotai.Atom<unknown>, listener: () => void) => () => void;
17
- };
18
- }>;
9
+ declare function FlagsProvider({ children, ...config }: FlagsProviderProps): any;
19
10
  declare function useFlags(): {
20
11
  isEnabled: (key: string) => FlagState;
21
12
  fetchAllFlags: () => Promise<void> | undefined;
@@ -1,21 +1,12 @@
1
1
  export { b as Databuddy } from '../shared/@databuddy/sdk.C8T93n5r.js';
2
- import * as react from 'react';
3
2
  import { ReactNode } from 'react';
4
- import * as jotai from 'jotai';
5
3
  import { d as FlagsConfig, c as FlagState } from '../shared/@databuddy/sdk.YfiY9DoZ.js';
6
4
  export { b as FlagResult, e as FlagsContext } from '../shared/@databuddy/sdk.YfiY9DoZ.js';
7
5
 
8
6
  interface FlagsProviderProps extends FlagsConfig {
9
7
  children: ReactNode;
10
8
  }
11
- declare function FlagsProvider({ children, ...config }: FlagsProviderProps): react.FunctionComponentElement<{
12
- children?: ReactNode;
13
- store?: {
14
- get: <Value>(atom: jotai.Atom<Value>) => Value;
15
- set: <Value, Args extends unknown[], Result>(atom: jotai.WritableAtom<Value, Args, Result>, ...args: Args) => Result;
16
- sub: (atom: jotai.Atom<unknown>, listener: () => void) => () => void;
17
- };
18
- }>;
9
+ declare function FlagsProvider({ children, ...config }: FlagsProviderProps): any;
19
10
  declare function useFlags(): {
20
11
  isEnabled: (key: string) => FlagState;
21
12
  fetchAllFlags: () => Promise<void> | undefined;
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
 
3
- export { D as Databuddy } from '../shared/@databuddy/sdk.VZOaS2Dk.mjs';
3
+ export { D as Databuddy } from '../shared/@databuddy/sdk.aVQee-4k.mjs';
4
4
  import { createStore, atom, Provider, useAtom } from 'jotai';
5
5
  import { useRef, useEffect, createElement } from 'react';
6
- import { B as BrowserFlagStorage, C as CoreFlagsManager, l as logger } from '../shared/@databuddy/sdk.DsZMb6-q.mjs';
6
+ import { B as BrowserFlagStorage, C as CoreFlagsManager, l as logger } from '../shared/@databuddy/sdk.tFAHtL2M.mjs';
7
7
 
8
8
  const flagsStore = createStore();
9
9
  const managerAtom = atom(null);
@@ -1,4 +1,4 @@
1
- import { i as isScriptInjected, c as createScript } from './sdk.DsZMb6-q.mjs';
1
+ import { i as isScriptInjected, c as createScript } from './sdk.tFAHtL2M.mjs';
2
2
 
3
3
  function detectClientId(providedClientId) {
4
4
  if (providedClientId) {
@@ -434,7 +434,7 @@ class CoreFlagsManager {
434
434
  }
435
435
  }
436
436
 
437
- const version = "2.1.76";
437
+ const version = "2.2.0";
438
438
 
439
439
  const INJECTED_SCRIPT_ATTRIBUTE = "data-databuddy-injected";
440
440
  function isScriptInjected() {
@@ -1,201 +1,8 @@
1
- import * as vue from 'vue';
2
1
  import { App, ComputedRef } from 'vue';
3
2
  import { d as FlagsConfig, c as FlagState, b as FlagResult } from '../shared/@databuddy/sdk.YfiY9DoZ.mjs';
4
3
  export { e as FlagsContext } from '../shared/@databuddy/sdk.YfiY9DoZ.mjs';
5
4
 
6
- declare const Databuddy: vue.DefineComponent<{
7
- clientId?: {
8
- type: StringConstructor;
9
- required: false;
10
- } | undefined;
11
- clientSecret?: {
12
- type: StringConstructor;
13
- required: false;
14
- } | undefined;
15
- apiUrl?: {
16
- type: StringConstructor;
17
- required: false;
18
- } | undefined;
19
- scriptUrl?: {
20
- type: StringConstructor;
21
- required: false;
22
- } | undefined;
23
- sdk?: {
24
- type: StringConstructor;
25
- required: false;
26
- } | undefined;
27
- sdkVersion?: {
28
- type: StringConstructor;
29
- required: false;
30
- } | undefined;
31
- disabled?: {
32
- type: BooleanConstructor;
33
- required: false;
34
- } | undefined;
35
- debug?: {
36
- type: BooleanConstructor;
37
- required: false;
38
- } | undefined;
39
- waitForProfile?: {
40
- type: BooleanConstructor;
41
- required: false;
42
- } | undefined;
43
- trackScreenViews?: {
44
- type: BooleanConstructor;
45
- required: false;
46
- } | undefined;
47
- trackHashChanges?: {
48
- type: BooleanConstructor;
49
- required: false;
50
- } | undefined;
51
- trackSessions?: {
52
- type: BooleanConstructor;
53
- required: false;
54
- } | undefined;
55
- trackAttributes?: {
56
- type: BooleanConstructor;
57
- required: false;
58
- } | undefined;
59
- trackOutgoingLinks?: {
60
- type: BooleanConstructor;
61
- required: false;
62
- } | undefined;
63
- trackInteractions?: {
64
- type: BooleanConstructor;
65
- required: false;
66
- } | undefined;
67
- trackEngagement?: {
68
- type: BooleanConstructor;
69
- required: false;
70
- } | undefined;
71
- trackScrollDepth?: {
72
- type: BooleanConstructor;
73
- required: false;
74
- } | undefined;
75
- trackExitIntent?: {
76
- type: BooleanConstructor;
77
- required: false;
78
- } | undefined;
79
- trackBounceRate?: {
80
- type: BooleanConstructor;
81
- required: false;
82
- } | undefined;
83
- trackPerformance?: {
84
- type: BooleanConstructor;
85
- required: false;
86
- } | undefined;
87
- trackWebVitals?: {
88
- type: BooleanConstructor;
89
- required: false;
90
- } | undefined;
91
- trackErrors?: {
92
- type: BooleanConstructor;
93
- required: false;
94
- } | undefined;
95
- enableObservability?: {
96
- type: BooleanConstructor;
97
- required: false;
98
- } | undefined;
99
- observabilityService?: {
100
- type: StringConstructor;
101
- required: false;
102
- } | undefined;
103
- observabilityEnvironment?: {
104
- type: StringConstructor;
105
- required: false;
106
- } | undefined;
107
- observabilityVersion?: {
108
- type: StringConstructor;
109
- required: false;
110
- } | undefined;
111
- enableLogging?: {
112
- type: BooleanConstructor;
113
- required: false;
114
- } | undefined;
115
- enableTracing?: {
116
- type: BooleanConstructor;
117
- required: false;
118
- } | undefined;
119
- enableErrorTracking?: {
120
- type: BooleanConstructor;
121
- required: false;
122
- } | undefined;
123
- samplingRate?: {
124
- type: NumberConstructor;
125
- required: false;
126
- } | undefined;
127
- enableRetries?: {
128
- type: BooleanConstructor;
129
- required: false;
130
- } | undefined;
131
- maxRetries?: {
132
- type: NumberConstructor;
133
- required: false;
134
- } | undefined;
135
- initialRetryDelay?: {
136
- type: NumberConstructor;
137
- required: false;
138
- } | undefined;
139
- enableBatching?: {
140
- type: BooleanConstructor;
141
- required: false;
142
- } | undefined;
143
- batchSize?: {
144
- type: NumberConstructor;
145
- required: false;
146
- } | undefined;
147
- batchTimeout?: {
148
- type: NumberConstructor;
149
- required: false;
150
- } | undefined;
151
- skipPatterns?: {
152
- type: never;
153
- required: false;
154
- } | undefined;
155
- maskPatterns?: {
156
- type: never;
157
- required: false;
158
- } | undefined;
159
- }, () => null, unknown, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, Record<string, any>, string, vue.VNodeProps & vue.AllowedComponentProps & vue.ComponentCustomProps, Readonly<{} & {
160
- sdk?: string | undefined;
161
- clientId?: string | undefined;
162
- clientSecret?: string | undefined;
163
- apiUrl?: string | undefined;
164
- scriptUrl?: string | undefined;
165
- sdkVersion?: string | undefined;
166
- disabled?: boolean | undefined;
167
- debug?: boolean | undefined;
168
- waitForProfile?: boolean | undefined;
169
- trackScreenViews?: boolean | undefined;
170
- trackHashChanges?: boolean | undefined;
171
- trackSessions?: boolean | undefined;
172
- trackAttributes?: boolean | undefined;
173
- trackOutgoingLinks?: boolean | undefined;
174
- trackInteractions?: boolean | undefined;
175
- trackEngagement?: boolean | undefined;
176
- trackScrollDepth?: boolean | undefined;
177
- trackExitIntent?: boolean | undefined;
178
- trackBounceRate?: boolean | undefined;
179
- trackPerformance?: boolean | undefined;
180
- trackWebVitals?: boolean | undefined;
181
- trackErrors?: boolean | undefined;
182
- enableObservability?: boolean | undefined;
183
- observabilityService?: string | undefined;
184
- observabilityEnvironment?: string | undefined;
185
- observabilityVersion?: string | undefined;
186
- enableLogging?: boolean | undefined;
187
- enableTracing?: boolean | undefined;
188
- enableErrorTracking?: boolean | undefined;
189
- samplingRate?: number | undefined;
190
- enableRetries?: boolean | undefined;
191
- maxRetries?: number | undefined;
192
- initialRetryDelay?: number | undefined;
193
- enableBatching?: boolean | undefined;
194
- batchSize?: number | undefined;
195
- batchTimeout?: number | undefined;
196
- skipPatterns?: any;
197
- maskPatterns?: any;
198
- }>, {}>;
5
+ declare const Databuddy: any;
199
6
 
200
7
  interface FlagsPluginOptions extends FlagsConfig {
201
8
  }