@databuddy/sdk 2.3.21 → 2.3.23
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/core/index.mjs
CHANGED
package/dist/react/index.mjs
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import { detectClientId } from '../core/index.mjs';
|
|
4
4
|
export { clear, flush, getAnonymousId, getSessionId, getTracker, getTrackingIds, getTrackingParams, isTrackerAvailable, track, trackError } from '../core/index.mjs';
|
|
5
|
-
import { i as isScriptInjected, c as createScript } from '../shared/@databuddy/sdk.
|
|
5
|
+
import { i as isScriptInjected, c as createScript } from '../shared/@databuddy/sdk.DQLu36uX.mjs';
|
|
6
6
|
import React, { useRef, useMemo, useEffect, useSyncExternalStore, createContext, useContext } from 'react';
|
|
7
|
-
import { B as BrowserFlagStorage, C as CoreFlagsManager } from '../shared/@databuddy/sdk.
|
|
7
|
+
import { B as BrowserFlagStorage, C as CoreFlagsManager } from '../shared/@databuddy/sdk.csCQ7WQR.mjs';
|
|
8
8
|
import { l as logger } from '../shared/@databuddy/sdk.DCKr2Zpd.mjs';
|
|
9
9
|
|
|
10
10
|
function Databuddy(props) {
|
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
import { l as logger, c as createCacheEntry, i as isCacheValid, b as buildQueryParams, R as RequestBatcher, a as isCacheStale, D as DEFAULT_RESULT, g as getCacheKey, f as fetchAllFlags } from './sdk.DCKr2Zpd.mjs';
|
|
2
2
|
|
|
3
|
+
const isBrowser = typeof window !== "undefined" && typeof localStorage !== "undefined";
|
|
3
4
|
class BrowserFlagStorage {
|
|
4
5
|
ttl = 24 * 60 * 60 * 1e3;
|
|
5
6
|
// 24 hours in milliseconds
|
|
6
7
|
get(key) {
|
|
8
|
+
if (!isBrowser) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
7
11
|
return this.getFromLocalStorage(key);
|
|
8
12
|
}
|
|
9
13
|
set(key, value) {
|
|
14
|
+
if (!isBrowser) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
10
17
|
this.setToLocalStorage(key, value);
|
|
11
18
|
}
|
|
12
19
|
getAll() {
|
|
20
|
+
if (!isBrowser) {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
13
23
|
const result = {};
|
|
14
24
|
const now = Date.now();
|
|
15
25
|
const keys = Object.keys(localStorage).filter(
|
|
@@ -33,6 +43,9 @@ class BrowserFlagStorage {
|
|
|
33
43
|
return result;
|
|
34
44
|
}
|
|
35
45
|
clear() {
|
|
46
|
+
if (!isBrowser) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
36
49
|
const keys = Object.keys(localStorage).filter(
|
|
37
50
|
(key) => key.startsWith("db-flag-")
|
|
38
51
|
);
|
|
@@ -77,14 +90,23 @@ class BrowserFlagStorage {
|
|
|
77
90
|
return Date.now() > expiresAt;
|
|
78
91
|
}
|
|
79
92
|
delete(key) {
|
|
93
|
+
if (!isBrowser) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
80
96
|
localStorage.removeItem(`db-flag-${key}`);
|
|
81
97
|
}
|
|
82
98
|
deleteMultiple(keys) {
|
|
99
|
+
if (!isBrowser) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
83
102
|
for (const key of keys) {
|
|
84
103
|
localStorage.removeItem(`db-flag-${key}`);
|
|
85
104
|
}
|
|
86
105
|
}
|
|
87
106
|
setAll(flags) {
|
|
107
|
+
if (!isBrowser) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
88
110
|
const currentFlags = this.getAll();
|
|
89
111
|
const currentKeys = Object.keys(currentFlags);
|
|
90
112
|
const newKeys = Object.keys(flags);
|
|
@@ -97,6 +119,9 @@ class BrowserFlagStorage {
|
|
|
97
119
|
}
|
|
98
120
|
}
|
|
99
121
|
cleanupExpired() {
|
|
122
|
+
if (!isBrowser) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
100
125
|
const now = Date.now();
|
|
101
126
|
const keys = Object.keys(localStorage).filter(
|
|
102
127
|
(key) => key.startsWith("db-flag-")
|
|
@@ -117,6 +142,7 @@ class BrowserFlagStorage {
|
|
|
117
142
|
}
|
|
118
143
|
}
|
|
119
144
|
|
|
145
|
+
const ANONYMOUS_ID_KEY = "did";
|
|
120
146
|
class CoreFlagsManager {
|
|
121
147
|
config;
|
|
122
148
|
storage;
|
|
@@ -149,11 +175,45 @@ class CoreFlagsManager {
|
|
|
149
175
|
this.setupVisibilityListener();
|
|
150
176
|
this.initialize();
|
|
151
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Get or create anonymous ID for deterministic rollouts.
|
|
180
|
+
* Uses the same storage key as the tracker ("did") for consistency.
|
|
181
|
+
*/
|
|
182
|
+
getOrCreateAnonymousId() {
|
|
183
|
+
if (typeof localStorage === "undefined") {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
let id = localStorage.getItem(ANONYMOUS_ID_KEY);
|
|
188
|
+
if (id) {
|
|
189
|
+
return id;
|
|
190
|
+
}
|
|
191
|
+
id = `anon_${crypto.randomUUID()}`;
|
|
192
|
+
localStorage.setItem(ANONYMOUS_ID_KEY, id);
|
|
193
|
+
return id;
|
|
194
|
+
} catch {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Ensure user context has an identifier for deterministic flag evaluation.
|
|
200
|
+
* If no userId/email provided, inject anonymous ID as userId.
|
|
201
|
+
*/
|
|
202
|
+
ensureUserIdentity(user) {
|
|
203
|
+
if (user?.userId || user?.email) {
|
|
204
|
+
return user;
|
|
205
|
+
}
|
|
206
|
+
const anonymousId = this.getOrCreateAnonymousId();
|
|
207
|
+
if (!anonymousId) {
|
|
208
|
+
return user;
|
|
209
|
+
}
|
|
210
|
+
return { ...user, userId: anonymousId };
|
|
211
|
+
}
|
|
152
212
|
withDefaults(config) {
|
|
153
213
|
return {
|
|
154
214
|
clientId: config.clientId,
|
|
155
215
|
apiUrl: config.apiUrl ?? "https://api.databuddy.cc",
|
|
156
|
-
user: config.user,
|
|
216
|
+
user: this.ensureUserIdentity(config.user),
|
|
157
217
|
disabled: config.disabled ?? false,
|
|
158
218
|
debug: config.debug ?? false,
|
|
159
219
|
skipStorage: config.skipStorage ?? false,
|
|
@@ -181,6 +241,16 @@ class CoreFlagsManager {
|
|
|
181
241
|
document.removeEventListener("visibilitychange", handleVisibility);
|
|
182
242
|
};
|
|
183
243
|
}
|
|
244
|
+
removeStaleKeys(validKeys, user) {
|
|
245
|
+
const ctx = user ?? this.config.user;
|
|
246
|
+
const suffix = ctx?.userId || ctx?.email ? `:${ctx.userId ?? ""}:${ctx.email ?? ""}` : "";
|
|
247
|
+
for (const key of this.cache.keys()) {
|
|
248
|
+
const belongsToUser = suffix ? key.endsWith(suffix) : !key.includes(":");
|
|
249
|
+
if (belongsToUser && !validKeys.has(key)) {
|
|
250
|
+
this.cache.delete(key);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
184
254
|
async initialize() {
|
|
185
255
|
if (!this.config.skipStorage && this.storage) {
|
|
186
256
|
this.loadFromStorage();
|
|
@@ -334,13 +404,20 @@ class CoreFlagsManager {
|
|
|
334
404
|
}
|
|
335
405
|
const apiUrl = this.config.apiUrl ?? "https://api.databuddy.cc";
|
|
336
406
|
const params = buildQueryParams(this.config, user);
|
|
407
|
+
const ttl = this.config.cacheTtl ?? 6e4;
|
|
408
|
+
const staleTime = this.config.staleTime ?? ttl / 2;
|
|
337
409
|
try {
|
|
338
410
|
const flags = await fetchAllFlags(apiUrl, params);
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
411
|
+
const flagCacheEntries = Object.entries(flags).map(([key, result]) => ({
|
|
412
|
+
cacheKey: getCacheKey(key, user ?? this.config.user),
|
|
413
|
+
cacheEntry: createCacheEntry(result, ttl, staleTime)
|
|
414
|
+
}));
|
|
415
|
+
this.removeStaleKeys(
|
|
416
|
+
new Set(flagCacheEntries.map(({ cacheKey }) => cacheKey)),
|
|
417
|
+
user
|
|
418
|
+
);
|
|
419
|
+
for (const { cacheKey, cacheEntry } of flagCacheEntries) {
|
|
420
|
+
this.cache.set(cacheKey, cacheEntry);
|
|
344
421
|
}
|
|
345
422
|
this.ready = true;
|
|
346
423
|
this.notifyUpdate();
|
|
@@ -417,7 +494,7 @@ class CoreFlagsManager {
|
|
|
417
494
|
* Update user context and refresh flags
|
|
418
495
|
*/
|
|
419
496
|
updateUser(user) {
|
|
420
|
-
this.config = { ...this.config, user };
|
|
497
|
+
this.config = { ...this.config, user: this.ensureUserIdentity(user) };
|
|
421
498
|
this.batcher?.destroy();
|
|
422
499
|
this.batcher = null;
|
|
423
500
|
this.onConfigUpdate?.(this.config);
|
package/dist/vue/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineComponent, ref, onMounted, onUnmounted, watch, reactive, watchEffect, computed } from 'vue';
|
|
2
|
-
import { i as isScriptInjected, c as createScript } from '../shared/@databuddy/sdk.
|
|
3
|
-
import { B as BrowserFlagStorage, C as CoreFlagsManager } from '../shared/@databuddy/sdk.
|
|
2
|
+
import { i as isScriptInjected, c as createScript } from '../shared/@databuddy/sdk.DQLu36uX.mjs';
|
|
3
|
+
import { B as BrowserFlagStorage, C as CoreFlagsManager } from '../shared/@databuddy/sdk.csCQ7WQR.mjs';
|
|
4
4
|
import '../shared/@databuddy/sdk.DCKr2Zpd.mjs';
|
|
5
5
|
|
|
6
6
|
const Databuddy = defineComponent({
|