@databuddy/sdk 2.1.6 → 2.1.75

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.
@@ -1,6 +1,6 @@
1
- import { D as Databuddy$1 } from '../shared/@databuddy/sdk.CG1QeYl0.mjs';
2
- export { d as detectClientId } from '../shared/@databuddy/sdk.CG1QeYl0.mjs';
3
- export { c as createScript, i as isScriptInjected } from '../shared/@databuddy/sdk.RYpOP8Ko.mjs';
1
+ import { D as Databuddy$1 } from '../shared/@databuddy/sdk.mo6tEgU3.mjs';
2
+ export { d as detectClientId } from '../shared/@databuddy/sdk.mo6tEgU3.mjs';
3
+ export { c as createScript, i as isScriptInjected } from '../shared/@databuddy/sdk.DsZP9wPD.mjs';
4
4
 
5
5
  function isTrackerAvailable() {
6
6
  return typeof window !== "undefined" && (!!window.databuddy || !!window.db);
@@ -30,9 +30,13 @@ interface FlagsConfig {
30
30
  /** Automatically fetch all flags on initialization (default: true) */
31
31
  autoFetch?: boolean;
32
32
  }
33
+ interface FlagState {
34
+ enabled: boolean;
35
+ isLoading: boolean;
36
+ isReady: boolean;
37
+ }
33
38
  interface FlagsContext {
34
- isEnabled: (key: string) => boolean | undefined;
35
- getValue: (key: string, defaultValue?: boolean) => boolean;
39
+ isEnabled: (key: string) => FlagState;
36
40
  fetchAllFlags: () => Promise<void>;
37
41
  updateUser: (user: FlagsConfig['user']) => void;
38
42
  refresh: (forceClear?: boolean) => Promise<void>;
@@ -50,12 +54,11 @@ declare function FlagsProvider({ children, ...config }: FlagsProviderProps): rea
50
54
  };
51
55
  }>;
52
56
  declare function useFlags(): {
53
- isEnabled: (key: string) => boolean | undefined;
54
- getValue: (key: string, defaultValue?: boolean) => boolean;
57
+ isEnabled: (key: string) => FlagState;
55
58
  fetchAllFlags: () => Promise<void>;
56
59
  updateUser: (user: FlagsConfig["user"]) => void;
57
- refresh: (forceClear?: boolean) => Promise<void>;
60
+ refresh: (forceClear?: boolean) => void;
58
61
  };
59
62
 
60
63
  export { FlagsProvider, useFlags };
61
- export type { FlagResult, FlagsConfig, FlagsContext };
64
+ export type { FlagResult, FlagState, FlagsConfig, FlagsContext };
@@ -30,9 +30,13 @@ interface FlagsConfig {
30
30
  /** Automatically fetch all flags on initialization (default: true) */
31
31
  autoFetch?: boolean;
32
32
  }
33
+ interface FlagState {
34
+ enabled: boolean;
35
+ isLoading: boolean;
36
+ isReady: boolean;
37
+ }
33
38
  interface FlagsContext {
34
- isEnabled: (key: string) => boolean | undefined;
35
- getValue: (key: string, defaultValue?: boolean) => boolean;
39
+ isEnabled: (key: string) => FlagState;
36
40
  fetchAllFlags: () => Promise<void>;
37
41
  updateUser: (user: FlagsConfig['user']) => void;
38
42
  refresh: (forceClear?: boolean) => Promise<void>;
@@ -50,12 +54,11 @@ declare function FlagsProvider({ children, ...config }: FlagsProviderProps): rea
50
54
  };
51
55
  }>;
52
56
  declare function useFlags(): {
53
- isEnabled: (key: string) => boolean | undefined;
54
- getValue: (key: string, defaultValue?: boolean) => boolean;
57
+ isEnabled: (key: string) => FlagState;
55
58
  fetchAllFlags: () => Promise<void>;
56
59
  updateUser: (user: FlagsConfig["user"]) => void;
57
- refresh: (forceClear?: boolean) => Promise<void>;
60
+ refresh: (forceClear?: boolean) => void;
58
61
  };
59
62
 
60
63
  export { FlagsProvider, useFlags };
61
- export type { FlagResult, FlagsConfig, FlagsContext };
64
+ export type { FlagResult, FlagState, FlagsConfig, FlagsContext };
@@ -1,23 +1,95 @@
1
1
  'use client';
2
2
 
3
- export { D as Databuddy } from '../shared/@databuddy/sdk.CG1QeYl0.mjs';
3
+ export { D as Databuddy } from '../shared/@databuddy/sdk.mo6tEgU3.mjs';
4
4
  import { createStore, atom, Provider, useAtom } from 'jotai';
5
5
  import { useEffect, createElement } from 'react';
6
- import '../shared/@databuddy/sdk.RYpOP8Ko.mjs';
6
+ import '../shared/@databuddy/sdk.DsZP9wPD.mjs';
7
+
8
+ class Logger {
9
+ debugEnabled = false;
10
+ /**
11
+ * Enable or disable debug logging
12
+ */
13
+ setDebug(enabled) {
14
+ this.debugEnabled = enabled;
15
+ }
16
+ /**
17
+ * Log debug messages (only when debug is enabled)
18
+ */
19
+ debug(...args) {
20
+ if (this.debugEnabled) {
21
+ console.log("[Databuddy]", ...args);
22
+ }
23
+ }
24
+ /**
25
+ * Log info messages (always enabled)
26
+ */
27
+ info(...args) {
28
+ console.info("[Databuddy]", ...args);
29
+ }
30
+ /**
31
+ * Log warning messages (always enabled)
32
+ */
33
+ warn(...args) {
34
+ console.warn("[Databuddy]", ...args);
35
+ }
36
+ /**
37
+ * Log error messages (always enabled)
38
+ */
39
+ error(...args) {
40
+ console.error("[Databuddy]", ...args);
41
+ }
42
+ /**
43
+ * Log with table format (only when debug is enabled)
44
+ */
45
+ table(data) {
46
+ if (this.debugEnabled) {
47
+ console.table(data);
48
+ }
49
+ }
50
+ /**
51
+ * Time a function execution (only when debug is enabled)
52
+ */
53
+ time(label) {
54
+ if (this.debugEnabled) {
55
+ console.time(`[Databuddy] ${label}`);
56
+ }
57
+ }
58
+ /**
59
+ * End timing a function execution (only when debug is enabled)
60
+ */
61
+ timeEnd(label) {
62
+ if (this.debugEnabled) {
63
+ console.timeEnd(`[Databuddy] ${label}`);
64
+ }
65
+ }
66
+ /**
67
+ * Log JSON data (only when debug is enabled)
68
+ */
69
+ json(data) {
70
+ if (this.debugEnabled) {
71
+ console.log("[Databuddy]", JSON.stringify(data, null, 2));
72
+ }
73
+ }
74
+ }
75
+ const logger = new Logger();
7
76
 
8
77
  class FlagStorage {
9
78
  ttl = 24 * 60 * 60 * 1e3;
10
79
  // 24 hours in milliseconds
11
- async get(key) {
80
+ get(key) {
12
81
  return this.getFromLocalStorage(key);
13
82
  }
14
- async set(key, value) {
83
+ set(key, value) {
15
84
  this.setToLocalStorage(key, value);
16
85
  }
17
- async getAll() {
86
+ getAll() {
18
87
  const result = {};
19
88
  const now = Date.now();
20
- Object.keys(localStorage).filter((key) => key.startsWith("db-flag-")).forEach((key) => {
89
+ const keys = Object.keys(localStorage).filter(
90
+ (key) => key.startsWith("db-flag-")
91
+ );
92
+ for (const key of keys) {
21
93
  const flagKey = key.replace("db-flag-", "");
22
94
  try {
23
95
  const item = localStorage.getItem(key);
@@ -31,13 +103,16 @@ class FlagStorage {
31
103
  }
32
104
  } catch {
33
105
  }
34
- });
106
+ }
35
107
  return result;
36
108
  }
37
- async clear() {
38
- Object.keys(localStorage).filter((key) => key.startsWith("db-flag-")).forEach((key) => {
109
+ clear() {
110
+ const keys = Object.keys(localStorage).filter(
111
+ (key) => key.startsWith("db-flag-")
112
+ );
113
+ for (const key of keys) {
39
114
  localStorage.removeItem(key);
40
- });
115
+ }
41
116
  }
42
117
  getFromLocalStorage(key) {
43
118
  try {
@@ -75,29 +150,32 @@ class FlagStorage {
75
150
  }
76
151
  return Date.now() > expiresAt;
77
152
  }
78
- async delete(key) {
153
+ delete(key) {
79
154
  localStorage.removeItem(`db-flag-${key}`);
80
155
  }
81
- async deleteMultiple(keys) {
156
+ deleteMultiple(keys) {
82
157
  for (const key of keys) {
83
158
  localStorage.removeItem(`db-flag-${key}`);
84
159
  }
85
160
  }
86
- async setAll(flags) {
87
- const currentFlags = await this.getAll();
161
+ setAll(flags) {
162
+ const currentFlags = this.getAll();
88
163
  const currentKeys = Object.keys(currentFlags);
89
164
  const newKeys = Object.keys(flags);
90
165
  const removedKeys = currentKeys.filter((key) => !newKeys.includes(key));
91
166
  if (removedKeys.length > 0) {
92
- await this.deleteMultiple(removedKeys);
167
+ this.deleteMultiple(removedKeys);
93
168
  }
94
169
  for (const [key, value] of Object.entries(flags)) {
95
- await this.set(key, value);
170
+ this.set(key, value);
96
171
  }
97
172
  }
98
- async cleanupExpired() {
173
+ cleanupExpired() {
99
174
  const now = Date.now();
100
- Object.keys(localStorage).filter((key) => key.startsWith("db-flag-")).forEach((key) => {
175
+ const keys = Object.keys(localStorage).filter(
176
+ (key) => key.startsWith("db-flag-")
177
+ );
178
+ for (const key of keys) {
101
179
  try {
102
180
  const item = localStorage.getItem(key);
103
181
  if (item) {
@@ -109,7 +187,7 @@ class FlagStorage {
109
187
  } catch {
110
188
  localStorage.removeItem(key);
111
189
  }
112
- });
190
+ }
113
191
  }
114
192
  }
115
193
  const flagStorage = new FlagStorage();
@@ -120,14 +198,13 @@ const memoryFlagsAtom = atom({});
120
198
  const pendingFlagsAtom = atom(/* @__PURE__ */ new Set());
121
199
  function FlagsProvider({ children, ...config }) {
122
200
  const debug = config.debug ?? false;
123
- if (debug) {
124
- console.log("[Databuddy Flags] Provider rendering with config:", {
125
- clientId: config.clientId,
126
- debug,
127
- isPending: config.isPending,
128
- hasUser: !!config.user
129
- });
130
- }
201
+ logger.setDebug(debug);
202
+ logger.debug("Provider rendering with config:", {
203
+ clientId: config.clientId,
204
+ debug,
205
+ isPending: config.isPending,
206
+ hasUser: !!config.user
207
+ });
131
208
  useEffect(() => {
132
209
  const configWithDefaults = {
133
210
  clientId: config.clientId,
@@ -140,19 +217,16 @@ function FlagsProvider({ children, ...config }) {
140
217
  autoFetch: config.autoFetch !== false
141
218
  };
142
219
  flagsStore.set(configAtom, configWithDefaults);
143
- if (debug) {
144
- console.log("[Databuddy Flags] Config set on store", {
145
- clientId: config.clientId,
146
- apiUrl: configWithDefaults.apiUrl,
147
- user: config.user,
148
- isPending: config.isPending,
149
- skipStorage: config.skipStorage ?? false
150
- });
151
- }
220
+ logger.debug("Config set on store", {
221
+ clientId: config.clientId,
222
+ apiUrl: configWithDefaults.apiUrl,
223
+ user: config.user,
224
+ isPending: config.isPending,
225
+ skipStorage: config.skipStorage ?? false
226
+ });
152
227
  if (!(config.skipStorage ?? false)) {
153
228
  loadCachedFlagsImmediate(configWithDefaults);
154
- flagStorage.cleanupExpired().catch(() => {
155
- });
229
+ flagStorage.cleanupExpired();
156
230
  }
157
231
  }, [
158
232
  config.clientId,
@@ -169,24 +243,18 @@ function FlagsProvider({ children, ...config }) {
169
243
  if (config2.skipStorage) {
170
244
  return;
171
245
  }
172
- flagStorage.getAll().then((cachedFlags) => {
246
+ try {
247
+ const cachedFlags = flagStorage.getAll();
173
248
  if (Object.keys(cachedFlags).length > 0) {
174
249
  flagsStore.set(
175
250
  memoryFlagsAtom,
176
251
  cachedFlags
177
252
  );
178
- if (config2.debug) {
179
- console.log(
180
- "[Databuddy Flags] Loaded cached flags:",
181
- Object.keys(cachedFlags)
182
- );
183
- }
184
- }
185
- }).catch((err) => {
186
- if (config2.debug) {
187
- console.warn("[Databuddy Flags] Error loading cached flags:", err);
253
+ logger.debug("Loaded cached flags:", Object.keys(cachedFlags));
188
254
  }
189
- });
255
+ } catch (err) {
256
+ logger.warn("Error loading cached flags:", err);
257
+ }
190
258
  };
191
259
  return createElement(Provider, { store: flagsStore }, children);
192
260
  }
@@ -198,26 +266,22 @@ function useFlags() {
198
266
  const [pendingFlags, setPendingFlags] = useAtom(pendingFlagsAtom, {
199
267
  store: flagsStore
200
268
  });
201
- if (config?.debug) {
202
- console.log("[Databuddy Flags] useFlags called with config:", {
203
- hasConfig: !!config,
204
- clientId: config?.clientId,
205
- isPending: config?.isPending,
206
- debug: config?.debug,
207
- skipStorage: config?.skipStorage,
208
- memoryFlagsCount: Object.keys(memoryFlags).length,
209
- memoryFlags: Object.keys(memoryFlags)
210
- });
211
- }
269
+ logger.debug("useFlags called with config:", {
270
+ hasConfig: !!config,
271
+ clientId: config?.clientId,
272
+ isPending: config?.isPending,
273
+ debug: config?.debug,
274
+ skipStorage: config?.skipStorage,
275
+ memoryFlagsCount: Object.keys(memoryFlags).length,
276
+ memoryFlags: Object.keys(memoryFlags)
277
+ });
212
278
  const fetchAllFlags = async () => {
213
279
  if (!config) {
214
- console.warn("[Databuddy Flags] No config for bulk fetch");
280
+ logger.warn("No config for bulk fetch");
215
281
  return;
216
282
  }
217
283
  if (config.isPending) {
218
- if (config.debug) {
219
- console.log("[Databuddy Flags] Session pending, skipping bulk fetch");
220
- }
284
+ logger.debug("Session pending, skipping bulk fetch");
221
285
  return;
222
286
  }
223
287
  const params = new URLSearchParams();
@@ -238,33 +302,25 @@ function useFlags() {
238
302
  throw new Error(`HTTP ${response.status}`);
239
303
  }
240
304
  const result = await response.json();
241
- if (config.debug) {
242
- console.log("[Databuddy Flags] Bulk fetch response:", result);
243
- }
305
+ logger.debug("Bulk fetch response:", result);
244
306
  if (result.flags) {
245
307
  setMemoryFlags(result.flags);
246
308
  if (!config.skipStorage) {
247
309
  try {
248
- await flagStorage.setAll(result.flags);
249
- if (config.debug) {
250
- console.log("[Databuddy Flags] Bulk flags synced to cache");
251
- }
310
+ flagStorage.setAll(result.flags);
311
+ logger.debug("Bulk flags synced to cache");
252
312
  } catch (err) {
253
- if (config.debug) {
254
- console.warn("[Databuddy Flags] Bulk storage error:", err);
255
- }
313
+ logger.warn("Bulk storage error:", err);
256
314
  }
257
315
  }
258
316
  }
259
317
  } catch (err) {
260
- if (config.debug) {
261
- console.error("[Databuddy Flags] Bulk fetch error:", err);
262
- }
318
+ logger.error("Bulk fetch error:", err);
263
319
  }
264
320
  };
265
321
  const fetchFlag = async (key) => {
266
322
  if (!config) {
267
- console.warn(`[Databuddy Flags] No config for flag: ${key}`);
323
+ logger.warn(`No config for flag: ${key}`);
268
324
  return {
269
325
  enabled: false,
270
326
  value: false,
@@ -286,36 +342,26 @@ function useFlags() {
286
342
  params.set("properties", JSON.stringify(config.user.properties));
287
343
  }
288
344
  const url = `${config.apiUrl}/public/v1/flags/evaluate?${params.toString()}`;
289
- if (config.debug) {
290
- console.log(`[Databuddy Flags] Fetching: ${key}`);
291
- }
345
+ logger.debug(`Fetching: ${key}`);
292
346
  try {
293
347
  const response = await fetch(url);
294
348
  if (!response.ok) {
295
349
  throw new Error(`HTTP ${response.status}`);
296
350
  }
297
351
  const result = await response.json();
298
- if (config.debug) {
299
- console.log(`[Databuddy Flags] Response for ${key}:`, result);
300
- }
352
+ logger.debug(`Response for ${key}:`, result);
301
353
  setMemoryFlags((prev) => ({ ...prev, [key]: result }));
302
354
  if (!config.skipStorage) {
303
355
  try {
304
- await flagStorage.set(key, result);
305
- if (config.debug) {
306
- console.log(`[Databuddy Flags] Cached: ${key}`);
307
- }
356
+ flagStorage.set(key, result);
357
+ logger.debug(`Cached: ${key}`);
308
358
  } catch (err) {
309
- if (config.debug) {
310
- console.warn(`[Databuddy Flags] Cache error: ${key}`, err);
311
- }
359
+ logger.warn(`Cache error: ${key}`, err);
312
360
  }
313
361
  }
314
362
  return result;
315
363
  } catch (err) {
316
- if (config.debug) {
317
- console.error(`[Databuddy Flags] Fetch error: ${key}`, err);
318
- }
364
+ logger.error(`Fetch error: ${key}`, err);
319
365
  const fallback = {
320
366
  enabled: false,
321
367
  value: false,
@@ -333,13 +379,9 @@ function useFlags() {
333
379
  }
334
380
  };
335
381
  const getFlag = async (key) => {
336
- if (config?.debug) {
337
- console.log(`[Databuddy Flags] Getting: ${key}`);
338
- }
382
+ logger.debug(`Getting: ${key}`);
339
383
  if (config?.isPending) {
340
- if (config?.debug) {
341
- console.log(`[Databuddy Flags] Session pending for: ${key}`);
342
- }
384
+ logger.debug(`Session pending for: ${key}`);
343
385
  return {
344
386
  enabled: false,
345
387
  value: false,
@@ -348,15 +390,11 @@ function useFlags() {
348
390
  };
349
391
  }
350
392
  if (memoryFlags[key]) {
351
- if (config?.debug) {
352
- console.log(`[Databuddy Flags] Memory: ${key}`);
353
- }
393
+ logger.debug(`Memory: ${key}`);
354
394
  return memoryFlags[key];
355
395
  }
356
396
  if (pendingFlags.has(key)) {
357
- if (config?.debug) {
358
- console.log(`[Databuddy Flags] Pending: ${key}`);
359
- }
397
+ logger.debug(`Pending: ${key}`);
360
398
  return {
361
399
  enabled: false,
362
400
  value: false,
@@ -368,54 +406,52 @@ function useFlags() {
368
406
  try {
369
407
  const cached = await flagStorage.get(key);
370
408
  if (cached) {
371
- if (config?.debug) {
372
- console.log(`[Databuddy Flags] Cache: ${key}`);
373
- }
409
+ logger.debug(`Cache: ${key}`);
374
410
  setMemoryFlags((prev) => ({ ...prev, [key]: cached }));
375
411
  return cached;
376
412
  }
377
413
  } catch (err) {
378
- if (config?.debug) {
379
- console.warn(`[Databuddy Flags] Storage error: ${key}`, err);
380
- }
414
+ logger.warn(`Storage error: ${key}`, err);
381
415
  }
382
416
  }
383
417
  return fetchFlag(key);
384
418
  };
385
419
  const isEnabled = (key) => {
386
420
  if (memoryFlags[key]) {
387
- return memoryFlags[key].enabled;
421
+ return {
422
+ enabled: memoryFlags[key].enabled,
423
+ isLoading: false,
424
+ isReady: true
425
+ };
388
426
  }
389
- getFlag(key);
390
- return;
391
- };
392
- const getValue = (key, defaultValue = false) => {
393
- if (memoryFlags[key]) {
394
- return memoryFlags[key].value ?? defaultValue;
427
+ if (pendingFlags.has(key)) {
428
+ return {
429
+ enabled: false,
430
+ isLoading: true,
431
+ isReady: false
432
+ };
395
433
  }
396
434
  getFlag(key);
397
- return defaultValue;
435
+ return {
436
+ enabled: false,
437
+ isLoading: true,
438
+ isReady: false
439
+ };
398
440
  };
399
- const refresh = async (forceClear = false) => {
400
- if (config?.debug) {
401
- console.log("[Databuddy Flags] Refreshing", { forceClear });
402
- }
441
+ const refresh = (forceClear = false) => {
442
+ logger.debug("Refreshing", { forceClear });
403
443
  if (forceClear) {
404
444
  setMemoryFlags({});
405
445
  if (!config?.skipStorage) {
406
446
  try {
407
- await flagStorage.clear();
408
- if (config?.debug) {
409
- console.log("[Databuddy Flags] Storage cleared");
410
- }
447
+ flagStorage.clear();
448
+ logger.debug("Storage cleared");
411
449
  } catch (err) {
412
- if (config?.debug) {
413
- console.warn("[Databuddy Flags] Storage clear error:", err);
414
- }
450
+ logger.warn("Storage clear error:", err);
415
451
  }
416
452
  }
417
453
  }
418
- await fetchAllFlags();
454
+ fetchAllFlags();
419
455
  };
420
456
  const updateUser = (user) => {
421
457
  if (config) {
@@ -425,9 +461,7 @@ function useFlags() {
425
461
  };
426
462
  useEffect(() => {
427
463
  if (config && !config.isPending && config.autoFetch !== false) {
428
- if (config.debug) {
429
- console.log("[Databuddy Flags] Auto-fetching");
430
- }
464
+ logger.debug("Auto-fetching");
431
465
  fetchAllFlags();
432
466
  }
433
467
  }, [
@@ -439,7 +473,6 @@ function useFlags() {
439
473
  ]);
440
474
  return {
441
475
  isEnabled,
442
- getValue,
443
476
  fetchAllFlags,
444
477
  updateUser,
445
478
  refresh
@@ -1,4 +1,4 @@
1
- const version = "2.1.5";
1
+ const version = "2.1.7";
2
2
 
3
3
  const INJECTED_SCRIPT_ATTRIBUTE = "data-databuddy-injected";
4
4
  function isScriptInjected() {
@@ -1,4 +1,4 @@
1
- import { i as isScriptInjected, c as createScript } from './sdk.RYpOP8Ko.mjs';
1
+ import { i as isScriptInjected, c as createScript } from './sdk.DsZP9wPD.mjs';
2
2
 
3
3
  function detectClientId(providedClientId) {
4
4
  if (providedClientId) {
@@ -1,5 +1,5 @@
1
1
  import { defineComponent, ref, onMounted, onUnmounted, watch } from 'vue';
2
- import { i as isScriptInjected, c as createScript } from '../shared/@databuddy/sdk.RYpOP8Ko.mjs';
2
+ import { i as isScriptInjected, c as createScript } from '../shared/@databuddy/sdk.DsZP9wPD.mjs';
3
3
 
4
4
  const Databuddy = defineComponent({
5
5
  props: {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@databuddy/sdk",
3
- "version": "2.1.6",
3
+ "version": "2.1.75",
4
4
  "description": "Official Databuddy Analytics SDK",
5
5
  "main": "./dist/core/index.mjs",
6
6
  "types": "./dist/core/index.d.ts",