@databuddy/sdk 2.1.76 → 2.1.77
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.d.mts +41 -1
- package/dist/core/index.d.ts +41 -1
- package/dist/core/index.mjs +3 -3
- package/dist/react/index.d.mts +4 -42
- package/dist/react/index.d.ts +4 -42
- package/dist/react/index.mjs +54 -431
- package/dist/shared/@databuddy/sdk.DsZMb6-q.mjs +465 -0
- package/dist/shared/@databuddy/{sdk.DrN7UcWM.mjs → sdk.VZOaS2Dk.mjs} +1 -1
- package/dist/shared/@databuddy/sdk.YfiY9DoZ.d.mts +64 -0
- package/dist/shared/@databuddy/sdk.YfiY9DoZ.d.ts +64 -0
- package/dist/vue/index.d.mts +33 -1
- package/dist/vue/index.d.ts +33 -1
- package/dist/vue/index.mjs +87 -3
- package/package.json +58 -58
- package/dist/shared/@databuddy/sdk.D3SKeeIX.mjs +0 -29
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
class BrowserFlagStorage {
|
|
2
|
+
ttl = 24 * 60 * 60 * 1e3;
|
|
3
|
+
// 24 hours in milliseconds
|
|
4
|
+
get(key) {
|
|
5
|
+
return this.getFromLocalStorage(key);
|
|
6
|
+
}
|
|
7
|
+
set(key, value) {
|
|
8
|
+
this.setToLocalStorage(key, value);
|
|
9
|
+
}
|
|
10
|
+
getAll() {
|
|
11
|
+
const result = {};
|
|
12
|
+
const now = Date.now();
|
|
13
|
+
const keys = Object.keys(localStorage).filter(
|
|
14
|
+
(key) => key.startsWith("db-flag-")
|
|
15
|
+
);
|
|
16
|
+
for (const key of keys) {
|
|
17
|
+
const flagKey = key.replace("db-flag-", "");
|
|
18
|
+
try {
|
|
19
|
+
const item = localStorage.getItem(key);
|
|
20
|
+
if (item) {
|
|
21
|
+
const parsed = JSON.parse(item);
|
|
22
|
+
if (parsed.expiresAt && now > parsed.expiresAt) {
|
|
23
|
+
localStorage.removeItem(key);
|
|
24
|
+
} else {
|
|
25
|
+
result[flagKey] = parsed.value || parsed;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
clear() {
|
|
34
|
+
const keys = Object.keys(localStorage).filter(
|
|
35
|
+
(key) => key.startsWith("db-flag-")
|
|
36
|
+
);
|
|
37
|
+
for (const key of keys) {
|
|
38
|
+
localStorage.removeItem(key);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
getFromLocalStorage(key) {
|
|
42
|
+
try {
|
|
43
|
+
const item = localStorage.getItem(`db-flag-${key}`);
|
|
44
|
+
if (!item) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const parsed = JSON.parse(item);
|
|
48
|
+
if (parsed.expiresAt) {
|
|
49
|
+
if (this.isExpired(parsed.expiresAt)) {
|
|
50
|
+
localStorage.removeItem(`db-flag-${key}`);
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return parsed.value;
|
|
54
|
+
}
|
|
55
|
+
return parsed;
|
|
56
|
+
} catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
setToLocalStorage(key, value) {
|
|
61
|
+
try {
|
|
62
|
+
const item = {
|
|
63
|
+
value,
|
|
64
|
+
timestamp: Date.now(),
|
|
65
|
+
expiresAt: Date.now() + this.ttl
|
|
66
|
+
};
|
|
67
|
+
localStorage.setItem(`db-flag-${key}`, JSON.stringify(item));
|
|
68
|
+
} catch {
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
isExpired(expiresAt) {
|
|
72
|
+
if (!expiresAt) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
return Date.now() > expiresAt;
|
|
76
|
+
}
|
|
77
|
+
delete(key) {
|
|
78
|
+
localStorage.removeItem(`db-flag-${key}`);
|
|
79
|
+
}
|
|
80
|
+
deleteMultiple(keys) {
|
|
81
|
+
for (const key of keys) {
|
|
82
|
+
localStorage.removeItem(`db-flag-${key}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
setAll(flags) {
|
|
86
|
+
const currentFlags = this.getAll();
|
|
87
|
+
const currentKeys = Object.keys(currentFlags);
|
|
88
|
+
const newKeys = Object.keys(flags);
|
|
89
|
+
const removedKeys = currentKeys.filter((key) => !newKeys.includes(key));
|
|
90
|
+
if (removedKeys.length > 0) {
|
|
91
|
+
this.deleteMultiple(removedKeys);
|
|
92
|
+
}
|
|
93
|
+
for (const [key, value] of Object.entries(flags)) {
|
|
94
|
+
this.set(key, value);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
cleanupExpired() {
|
|
98
|
+
const now = Date.now();
|
|
99
|
+
const keys = Object.keys(localStorage).filter(
|
|
100
|
+
(key) => key.startsWith("db-flag-")
|
|
101
|
+
);
|
|
102
|
+
for (const key of keys) {
|
|
103
|
+
try {
|
|
104
|
+
const item = localStorage.getItem(key);
|
|
105
|
+
if (item) {
|
|
106
|
+
const parsed = JSON.parse(item);
|
|
107
|
+
if (parsed.expiresAt && now > parsed.expiresAt) {
|
|
108
|
+
localStorage.removeItem(key);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
} catch {
|
|
112
|
+
localStorage.removeItem(key);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
class Logger {
|
|
119
|
+
debugEnabled = false;
|
|
120
|
+
/**
|
|
121
|
+
* Enable or disable debug logging
|
|
122
|
+
*/
|
|
123
|
+
setDebug(enabled) {
|
|
124
|
+
this.debugEnabled = enabled;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Log debug messages (only when debug is enabled)
|
|
128
|
+
*/
|
|
129
|
+
debug(...args) {
|
|
130
|
+
if (this.debugEnabled) {
|
|
131
|
+
console.log("[Databuddy]", ...args);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Log info messages (always enabled)
|
|
136
|
+
*/
|
|
137
|
+
info(...args) {
|
|
138
|
+
console.info("[Databuddy]", ...args);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Log warning messages (always enabled)
|
|
142
|
+
*/
|
|
143
|
+
warn(...args) {
|
|
144
|
+
console.warn("[Databuddy]", ...args);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Log error messages (always enabled)
|
|
148
|
+
*/
|
|
149
|
+
error(...args) {
|
|
150
|
+
console.error("[Databuddy]", ...args);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Log with table format (only when debug is enabled)
|
|
154
|
+
*/
|
|
155
|
+
table(data) {
|
|
156
|
+
if (this.debugEnabled) {
|
|
157
|
+
console.table(data);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Time a function execution (only when debug is enabled)
|
|
162
|
+
*/
|
|
163
|
+
time(label) {
|
|
164
|
+
if (this.debugEnabled) {
|
|
165
|
+
console.time(`[Databuddy] ${label}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* End timing a function execution (only when debug is enabled)
|
|
170
|
+
*/
|
|
171
|
+
timeEnd(label) {
|
|
172
|
+
if (this.debugEnabled) {
|
|
173
|
+
console.timeEnd(`[Databuddy] ${label}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Log JSON data (only when debug is enabled)
|
|
178
|
+
*/
|
|
179
|
+
json(data) {
|
|
180
|
+
if (this.debugEnabled) {
|
|
181
|
+
console.log("[Databuddy]", JSON.stringify(data, null, 2));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const logger = new Logger();
|
|
186
|
+
|
|
187
|
+
class CoreFlagsManager {
|
|
188
|
+
config;
|
|
189
|
+
storage;
|
|
190
|
+
onFlagsUpdate;
|
|
191
|
+
onConfigUpdate;
|
|
192
|
+
memoryFlags = {};
|
|
193
|
+
pendingFlags = /* @__PURE__ */ new Set();
|
|
194
|
+
constructor(options) {
|
|
195
|
+
this.config = this.withDefaults(options.config);
|
|
196
|
+
this.storage = options.storage;
|
|
197
|
+
this.onFlagsUpdate = options.onFlagsUpdate;
|
|
198
|
+
this.onConfigUpdate = options.onConfigUpdate;
|
|
199
|
+
logger.setDebug(this.config.debug ?? false);
|
|
200
|
+
logger.debug("CoreFlagsManager initialized with config:", {
|
|
201
|
+
clientId: this.config.clientId,
|
|
202
|
+
debug: this.config.debug,
|
|
203
|
+
isPending: this.config.isPending,
|
|
204
|
+
hasUser: !!this.config.user
|
|
205
|
+
});
|
|
206
|
+
this.initialize();
|
|
207
|
+
}
|
|
208
|
+
withDefaults(config) {
|
|
209
|
+
return {
|
|
210
|
+
clientId: config.clientId,
|
|
211
|
+
apiUrl: config.apiUrl ?? "https://api.databuddy.cc",
|
|
212
|
+
user: config.user,
|
|
213
|
+
disabled: config.disabled ?? false,
|
|
214
|
+
debug: config.debug ?? false,
|
|
215
|
+
skipStorage: config.skipStorage ?? false,
|
|
216
|
+
isPending: config.isPending,
|
|
217
|
+
autoFetch: config.autoFetch !== false
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
async initialize() {
|
|
221
|
+
if (!this.config.skipStorage && this.storage) {
|
|
222
|
+
this.loadCachedFlags();
|
|
223
|
+
this.storage.cleanupExpired();
|
|
224
|
+
}
|
|
225
|
+
if (this.config.autoFetch && !this.config.isPending) {
|
|
226
|
+
await this.fetchAllFlags();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
loadCachedFlags() {
|
|
230
|
+
if (!this.storage || this.config.skipStorage) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
const cachedFlags = this.storage.getAll();
|
|
235
|
+
if (Object.keys(cachedFlags).length > 0) {
|
|
236
|
+
this.memoryFlags = cachedFlags;
|
|
237
|
+
this.notifyFlagsUpdate();
|
|
238
|
+
logger.debug("Loaded cached flags:", Object.keys(cachedFlags));
|
|
239
|
+
}
|
|
240
|
+
} catch (err) {
|
|
241
|
+
logger.warn("Error loading cached flags:", err);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
async fetchAllFlags() {
|
|
245
|
+
if (this.config.isPending) {
|
|
246
|
+
logger.debug("Session pending, skipping bulk fetch");
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const params = new URLSearchParams();
|
|
250
|
+
params.set("clientId", this.config.clientId);
|
|
251
|
+
if (this.config.user?.userId) {
|
|
252
|
+
params.set("userId", this.config.user.userId);
|
|
253
|
+
}
|
|
254
|
+
if (this.config.user?.email) {
|
|
255
|
+
params.set("email", this.config.user.email);
|
|
256
|
+
}
|
|
257
|
+
if (this.config.user?.properties) {
|
|
258
|
+
params.set("properties", JSON.stringify(this.config.user.properties));
|
|
259
|
+
}
|
|
260
|
+
const url = `${this.config.apiUrl}/public/v1/flags/bulk?${params.toString()}`;
|
|
261
|
+
try {
|
|
262
|
+
const response = await fetch(url);
|
|
263
|
+
if (!response.ok) {
|
|
264
|
+
throw new Error(`HTTP ${response.status}`);
|
|
265
|
+
}
|
|
266
|
+
const result = await response.json();
|
|
267
|
+
logger.debug("Bulk fetch response:", result);
|
|
268
|
+
if (result.flags) {
|
|
269
|
+
this.memoryFlags = result.flags;
|
|
270
|
+
this.notifyFlagsUpdate();
|
|
271
|
+
if (!this.config.skipStorage && this.storage) {
|
|
272
|
+
try {
|
|
273
|
+
this.storage.setAll(result.flags);
|
|
274
|
+
logger.debug("Bulk flags synced to cache");
|
|
275
|
+
} catch (err) {
|
|
276
|
+
logger.warn("Bulk storage error:", err);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
} catch (err) {
|
|
281
|
+
logger.error("Bulk fetch error:", err);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
async getFlag(key) {
|
|
285
|
+
logger.debug(`Getting: ${key}`);
|
|
286
|
+
if (this.config.isPending) {
|
|
287
|
+
logger.debug(`Session pending for: ${key}`);
|
|
288
|
+
return {
|
|
289
|
+
enabled: false,
|
|
290
|
+
value: false,
|
|
291
|
+
payload: null,
|
|
292
|
+
reason: "SESSION_PENDING"
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
if (this.memoryFlags[key]) {
|
|
296
|
+
logger.debug(`Memory: ${key}`);
|
|
297
|
+
return this.memoryFlags[key];
|
|
298
|
+
}
|
|
299
|
+
if (this.pendingFlags.has(key)) {
|
|
300
|
+
logger.debug(`Pending: ${key}`);
|
|
301
|
+
return {
|
|
302
|
+
enabled: false,
|
|
303
|
+
value: false,
|
|
304
|
+
payload: null,
|
|
305
|
+
reason: "FETCHING"
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
if (!this.config.skipStorage && this.storage) {
|
|
309
|
+
try {
|
|
310
|
+
const cached = await this.storage.get(key);
|
|
311
|
+
if (cached) {
|
|
312
|
+
logger.debug(`Cache: ${key}`);
|
|
313
|
+
this.memoryFlags[key] = cached;
|
|
314
|
+
this.notifyFlagsUpdate();
|
|
315
|
+
return cached;
|
|
316
|
+
}
|
|
317
|
+
} catch (err) {
|
|
318
|
+
logger.warn(`Storage error: ${key}`, err);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return this.fetchFlag(key);
|
|
322
|
+
}
|
|
323
|
+
async fetchFlag(key) {
|
|
324
|
+
this.pendingFlags.add(key);
|
|
325
|
+
const params = new URLSearchParams();
|
|
326
|
+
params.set("key", key);
|
|
327
|
+
params.set("clientId", this.config.clientId);
|
|
328
|
+
if (this.config.user?.userId) {
|
|
329
|
+
params.set("userId", this.config.user.userId);
|
|
330
|
+
}
|
|
331
|
+
if (this.config.user?.email) {
|
|
332
|
+
params.set("email", this.config.user.email);
|
|
333
|
+
}
|
|
334
|
+
if (this.config.user?.properties) {
|
|
335
|
+
params.set("properties", JSON.stringify(this.config.user.properties));
|
|
336
|
+
}
|
|
337
|
+
const url = `${this.config.apiUrl}/public/v1/flags/evaluate?${params.toString()}`;
|
|
338
|
+
logger.debug(`Fetching: ${key}`);
|
|
339
|
+
try {
|
|
340
|
+
const response = await fetch(url);
|
|
341
|
+
if (!response.ok) {
|
|
342
|
+
throw new Error(`HTTP ${response.status}`);
|
|
343
|
+
}
|
|
344
|
+
const result = await response.json();
|
|
345
|
+
logger.debug(`Response for ${key}:`, result);
|
|
346
|
+
this.memoryFlags[key] = result;
|
|
347
|
+
this.notifyFlagsUpdate();
|
|
348
|
+
if (!this.config.skipStorage && this.storage) {
|
|
349
|
+
try {
|
|
350
|
+
this.storage.set(key, result);
|
|
351
|
+
logger.debug(`Cached: ${key}`);
|
|
352
|
+
} catch (err) {
|
|
353
|
+
logger.warn(`Cache error: ${key}`, err);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return result;
|
|
357
|
+
} catch (err) {
|
|
358
|
+
logger.error(`Fetch error: ${key}`, err);
|
|
359
|
+
const fallback = {
|
|
360
|
+
enabled: false,
|
|
361
|
+
value: false,
|
|
362
|
+
payload: null,
|
|
363
|
+
reason: "ERROR"
|
|
364
|
+
};
|
|
365
|
+
this.memoryFlags[key] = fallback;
|
|
366
|
+
this.notifyFlagsUpdate();
|
|
367
|
+
return fallback;
|
|
368
|
+
} finally {
|
|
369
|
+
this.pendingFlags.delete(key);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
isEnabled(key) {
|
|
373
|
+
if (this.memoryFlags[key]) {
|
|
374
|
+
return {
|
|
375
|
+
enabled: this.memoryFlags[key].enabled,
|
|
376
|
+
isLoading: false,
|
|
377
|
+
isReady: true
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
if (this.pendingFlags.has(key)) {
|
|
381
|
+
return {
|
|
382
|
+
enabled: false,
|
|
383
|
+
isLoading: true,
|
|
384
|
+
isReady: false
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
this.getFlag(key);
|
|
388
|
+
return {
|
|
389
|
+
enabled: false,
|
|
390
|
+
isLoading: true,
|
|
391
|
+
isReady: false
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
refresh(forceClear = false) {
|
|
395
|
+
logger.debug("Refreshing", { forceClear });
|
|
396
|
+
if (forceClear) {
|
|
397
|
+
this.memoryFlags = {};
|
|
398
|
+
this.notifyFlagsUpdate();
|
|
399
|
+
if (!this.config.skipStorage && this.storage) {
|
|
400
|
+
try {
|
|
401
|
+
this.storage.clear();
|
|
402
|
+
logger.debug("Storage cleared");
|
|
403
|
+
} catch (err) {
|
|
404
|
+
logger.warn("Storage clear error:", err);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
this.fetchAllFlags();
|
|
409
|
+
}
|
|
410
|
+
updateUser(user) {
|
|
411
|
+
this.config = { ...this.config, user };
|
|
412
|
+
this.onConfigUpdate?.(this.config);
|
|
413
|
+
this.refresh();
|
|
414
|
+
}
|
|
415
|
+
updateConfig(config) {
|
|
416
|
+
this.config = this.withDefaults(config);
|
|
417
|
+
this.onConfigUpdate?.(this.config);
|
|
418
|
+
if (!this.config.skipStorage && this.storage) {
|
|
419
|
+
this.loadCachedFlags();
|
|
420
|
+
this.storage.cleanupExpired();
|
|
421
|
+
}
|
|
422
|
+
if (this.config.autoFetch && !this.config.isPending) {
|
|
423
|
+
this.fetchAllFlags();
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
getMemoryFlags() {
|
|
427
|
+
return { ...this.memoryFlags };
|
|
428
|
+
}
|
|
429
|
+
getPendingFlags() {
|
|
430
|
+
return new Set(this.pendingFlags);
|
|
431
|
+
}
|
|
432
|
+
notifyFlagsUpdate() {
|
|
433
|
+
this.onFlagsUpdate?.(this.getMemoryFlags());
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const version = "2.1.76";
|
|
438
|
+
|
|
439
|
+
const INJECTED_SCRIPT_ATTRIBUTE = "data-databuddy-injected";
|
|
440
|
+
function isScriptInjected() {
|
|
441
|
+
return !!document.querySelector(`script[${INJECTED_SCRIPT_ATTRIBUTE}]`);
|
|
442
|
+
}
|
|
443
|
+
function createScript({
|
|
444
|
+
scriptUrl,
|
|
445
|
+
sdkVersion,
|
|
446
|
+
...props
|
|
447
|
+
}) {
|
|
448
|
+
const script = document.createElement("script");
|
|
449
|
+
script.src = scriptUrl || "https://cdn.databuddy.cc/databuddy.js";
|
|
450
|
+
script.async = true;
|
|
451
|
+
script.crossOrigin = "anonymous";
|
|
452
|
+
script.setAttribute(INJECTED_SCRIPT_ATTRIBUTE, "true");
|
|
453
|
+
script.setAttribute("data-sdk-version", sdkVersion || version);
|
|
454
|
+
for (const [key, value] of Object.entries(props)) {
|
|
455
|
+
const dataKey = `data-${key.replace(/([A-Z])/g, "-$1").toLowerCase()}`;
|
|
456
|
+
if (Array.isArray(value) || value && typeof value === "object") {
|
|
457
|
+
script.setAttribute(dataKey, JSON.stringify(value));
|
|
458
|
+
} else {
|
|
459
|
+
script.setAttribute(dataKey, String(value));
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return script;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export { BrowserFlagStorage as B, CoreFlagsManager as C, createScript as c, isScriptInjected as i, logger as l };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
interface FlagResult {
|
|
2
|
+
enabled: boolean;
|
|
3
|
+
value: boolean;
|
|
4
|
+
payload: any;
|
|
5
|
+
reason: string;
|
|
6
|
+
flagId?: string;
|
|
7
|
+
flagType?: 'boolean' | 'rollout';
|
|
8
|
+
}
|
|
9
|
+
interface FlagsConfig {
|
|
10
|
+
/** Client ID for flag evaluation */
|
|
11
|
+
clientId: string;
|
|
12
|
+
apiUrl?: string;
|
|
13
|
+
user?: {
|
|
14
|
+
userId?: string;
|
|
15
|
+
email?: string;
|
|
16
|
+
properties?: Record<string, any>;
|
|
17
|
+
};
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
/** Enable debug logging */
|
|
20
|
+
debug?: boolean;
|
|
21
|
+
/** Skip persistent storage */
|
|
22
|
+
skipStorage?: boolean;
|
|
23
|
+
/** Whether session is loading */
|
|
24
|
+
isPending?: boolean;
|
|
25
|
+
/** Automatically fetch all flags on initialization (default: true) */
|
|
26
|
+
autoFetch?: boolean;
|
|
27
|
+
}
|
|
28
|
+
interface FlagState {
|
|
29
|
+
enabled: boolean;
|
|
30
|
+
isLoading: boolean;
|
|
31
|
+
isReady: boolean;
|
|
32
|
+
}
|
|
33
|
+
interface FlagsContext {
|
|
34
|
+
isEnabled: (key: string) => FlagState;
|
|
35
|
+
fetchAllFlags: () => Promise<void>;
|
|
36
|
+
updateUser: (user: FlagsConfig['user']) => void;
|
|
37
|
+
refresh: (forceClear?: boolean) => Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
interface StorageInterface {
|
|
40
|
+
get(key: string): any;
|
|
41
|
+
set(key: string, value: unknown): void;
|
|
42
|
+
getAll(): Record<string, unknown>;
|
|
43
|
+
clear(): void;
|
|
44
|
+
setAll(flags: Record<string, unknown>): void;
|
|
45
|
+
cleanupExpired(): void;
|
|
46
|
+
}
|
|
47
|
+
interface FlagsManagerOptions {
|
|
48
|
+
config: FlagsConfig;
|
|
49
|
+
storage?: StorageInterface;
|
|
50
|
+
onFlagsUpdate?: (flags: Record<string, FlagResult>) => void;
|
|
51
|
+
onConfigUpdate?: (config: FlagsConfig) => void;
|
|
52
|
+
}
|
|
53
|
+
interface FlagsManager {
|
|
54
|
+
getFlag: (key: string) => Promise<FlagResult>;
|
|
55
|
+
isEnabled: (key: string) => FlagState;
|
|
56
|
+
fetchAllFlags: () => Promise<void>;
|
|
57
|
+
updateUser: (user: FlagsConfig['user']) => void;
|
|
58
|
+
refresh: (forceClear?: boolean) => void;
|
|
59
|
+
updateConfig: (config: FlagsConfig) => void;
|
|
60
|
+
getMemoryFlags: () => Record<string, FlagResult>;
|
|
61
|
+
getPendingFlags: () => Set<string>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type { FlagsManager as F, StorageInterface as S, FlagsManagerOptions as a, FlagResult as b, FlagState as c, FlagsConfig as d, FlagsContext as e };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
interface FlagResult {
|
|
2
|
+
enabled: boolean;
|
|
3
|
+
value: boolean;
|
|
4
|
+
payload: any;
|
|
5
|
+
reason: string;
|
|
6
|
+
flagId?: string;
|
|
7
|
+
flagType?: 'boolean' | 'rollout';
|
|
8
|
+
}
|
|
9
|
+
interface FlagsConfig {
|
|
10
|
+
/** Client ID for flag evaluation */
|
|
11
|
+
clientId: string;
|
|
12
|
+
apiUrl?: string;
|
|
13
|
+
user?: {
|
|
14
|
+
userId?: string;
|
|
15
|
+
email?: string;
|
|
16
|
+
properties?: Record<string, any>;
|
|
17
|
+
};
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
/** Enable debug logging */
|
|
20
|
+
debug?: boolean;
|
|
21
|
+
/** Skip persistent storage */
|
|
22
|
+
skipStorage?: boolean;
|
|
23
|
+
/** Whether session is loading */
|
|
24
|
+
isPending?: boolean;
|
|
25
|
+
/** Automatically fetch all flags on initialization (default: true) */
|
|
26
|
+
autoFetch?: boolean;
|
|
27
|
+
}
|
|
28
|
+
interface FlagState {
|
|
29
|
+
enabled: boolean;
|
|
30
|
+
isLoading: boolean;
|
|
31
|
+
isReady: boolean;
|
|
32
|
+
}
|
|
33
|
+
interface FlagsContext {
|
|
34
|
+
isEnabled: (key: string) => FlagState;
|
|
35
|
+
fetchAllFlags: () => Promise<void>;
|
|
36
|
+
updateUser: (user: FlagsConfig['user']) => void;
|
|
37
|
+
refresh: (forceClear?: boolean) => Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
interface StorageInterface {
|
|
40
|
+
get(key: string): any;
|
|
41
|
+
set(key: string, value: unknown): void;
|
|
42
|
+
getAll(): Record<string, unknown>;
|
|
43
|
+
clear(): void;
|
|
44
|
+
setAll(flags: Record<string, unknown>): void;
|
|
45
|
+
cleanupExpired(): void;
|
|
46
|
+
}
|
|
47
|
+
interface FlagsManagerOptions {
|
|
48
|
+
config: FlagsConfig;
|
|
49
|
+
storage?: StorageInterface;
|
|
50
|
+
onFlagsUpdate?: (flags: Record<string, FlagResult>) => void;
|
|
51
|
+
onConfigUpdate?: (config: FlagsConfig) => void;
|
|
52
|
+
}
|
|
53
|
+
interface FlagsManager {
|
|
54
|
+
getFlag: (key: string) => Promise<FlagResult>;
|
|
55
|
+
isEnabled: (key: string) => FlagState;
|
|
56
|
+
fetchAllFlags: () => Promise<void>;
|
|
57
|
+
updateUser: (user: FlagsConfig['user']) => void;
|
|
58
|
+
refresh: (forceClear?: boolean) => void;
|
|
59
|
+
updateConfig: (config: FlagsConfig) => void;
|
|
60
|
+
getMemoryFlags: () => Record<string, FlagResult>;
|
|
61
|
+
getPendingFlags: () => Set<string>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type { FlagsManager as F, StorageInterface as S, FlagsManagerOptions as a, FlagResult as b, FlagState as c, FlagsConfig as d, FlagsContext as e };
|
package/dist/vue/index.d.mts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
|
+
import { App, ComputedRef } from 'vue';
|
|
3
|
+
import { d as FlagsConfig, c as FlagState, b as FlagResult } from '../shared/@databuddy/sdk.YfiY9DoZ.mjs';
|
|
4
|
+
export { e as FlagsContext } from '../shared/@databuddy/sdk.YfiY9DoZ.mjs';
|
|
2
5
|
|
|
3
6
|
declare const Databuddy: vue.DefineComponent<{
|
|
4
7
|
clientId?: {
|
|
@@ -194,4 +197,33 @@ declare const Databuddy: vue.DefineComponent<{
|
|
|
194
197
|
maskPatterns?: any;
|
|
195
198
|
}>, {}>;
|
|
196
199
|
|
|
197
|
-
|
|
200
|
+
interface FlagsPluginOptions extends FlagsConfig {
|
|
201
|
+
}
|
|
202
|
+
declare function createFlagsPlugin(options: FlagsPluginOptions): {
|
|
203
|
+
install(app: App): void;
|
|
204
|
+
};
|
|
205
|
+
declare function useFlags(): {
|
|
206
|
+
isEnabled: (key: string) => FlagState;
|
|
207
|
+
fetchAllFlags: () => Promise<void>;
|
|
208
|
+
updateUser: (user: FlagsConfig["user"]) => void;
|
|
209
|
+
refresh: (forceClear?: boolean) => void;
|
|
210
|
+
updateConfig: (config: FlagsConfig) => void;
|
|
211
|
+
memoryFlags: Record<string, FlagResult>;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
interface UseFlagReturn {
|
|
215
|
+
enabled: ComputedRef<boolean>;
|
|
216
|
+
isLoading: ComputedRef<boolean>;
|
|
217
|
+
isReady: ComputedRef<boolean>;
|
|
218
|
+
state: ComputedRef<FlagState>;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Vue composable for individual flag usage with reactivity
|
|
222
|
+
*/
|
|
223
|
+
declare function useFlag(key: string): UseFlagReturn;
|
|
224
|
+
/**
|
|
225
|
+
* Vue composable for boolean flag checking
|
|
226
|
+
*/
|
|
227
|
+
declare function useBooleanFlag(key: string): ComputedRef<boolean>;
|
|
228
|
+
|
|
229
|
+
export { Databuddy, FlagResult, FlagState, FlagsConfig, createFlagsPlugin, useBooleanFlag, useFlag, useFlags };
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
|
+
import { App, ComputedRef } from 'vue';
|
|
3
|
+
import { d as FlagsConfig, c as FlagState, b as FlagResult } from '../shared/@databuddy/sdk.YfiY9DoZ.js';
|
|
4
|
+
export { e as FlagsContext } from '../shared/@databuddy/sdk.YfiY9DoZ.js';
|
|
2
5
|
|
|
3
6
|
declare const Databuddy: vue.DefineComponent<{
|
|
4
7
|
clientId?: {
|
|
@@ -194,4 +197,33 @@ declare const Databuddy: vue.DefineComponent<{
|
|
|
194
197
|
maskPatterns?: any;
|
|
195
198
|
}>, {}>;
|
|
196
199
|
|
|
197
|
-
|
|
200
|
+
interface FlagsPluginOptions extends FlagsConfig {
|
|
201
|
+
}
|
|
202
|
+
declare function createFlagsPlugin(options: FlagsPluginOptions): {
|
|
203
|
+
install(app: App): void;
|
|
204
|
+
};
|
|
205
|
+
declare function useFlags(): {
|
|
206
|
+
isEnabled: (key: string) => FlagState;
|
|
207
|
+
fetchAllFlags: () => Promise<void>;
|
|
208
|
+
updateUser: (user: FlagsConfig["user"]) => void;
|
|
209
|
+
refresh: (forceClear?: boolean) => void;
|
|
210
|
+
updateConfig: (config: FlagsConfig) => void;
|
|
211
|
+
memoryFlags: Record<string, FlagResult>;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
interface UseFlagReturn {
|
|
215
|
+
enabled: ComputedRef<boolean>;
|
|
216
|
+
isLoading: ComputedRef<boolean>;
|
|
217
|
+
isReady: ComputedRef<boolean>;
|
|
218
|
+
state: ComputedRef<FlagState>;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Vue composable for individual flag usage with reactivity
|
|
222
|
+
*/
|
|
223
|
+
declare function useFlag(key: string): UseFlagReturn;
|
|
224
|
+
/**
|
|
225
|
+
* Vue composable for boolean flag checking
|
|
226
|
+
*/
|
|
227
|
+
declare function useBooleanFlag(key: string): ComputedRef<boolean>;
|
|
228
|
+
|
|
229
|
+
export { Databuddy, FlagResult, FlagState, FlagsConfig, createFlagsPlugin, useBooleanFlag, useFlag, useFlags };
|