@databuddy/sdk 2.3.0 → 2.3.2

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,5 +1,5 @@
1
1
  export { d as detectClientId } from '../shared/@databuddy/sdk.BUsPV0LH.mjs';
2
- export { B as BrowserFlagStorage, C as CoreFlagsManager, c as createScript, i as isScriptInjected } from '../shared/@databuddy/sdk.Cn2tDA8H.mjs';
2
+ export { c as createScript, i as isScriptInjected } from '../shared/@databuddy/sdk.F8Xt1uF7.mjs';
3
3
 
4
4
  function isTrackerAvailable() {
5
5
  return typeof window !== "undefined" && (!!window.databuddy || !!window.db);
@@ -1,3 +1,5 @@
1
+ import { e as FlagsManager, f as FlagsManagerOptions, U as UserContext, d as FlagResult, b as FlagState, F as FlagsConfig } from '../shared/@databuddy/sdk.B6nwxnPC.mjs';
2
+
1
3
  interface Logger {
2
4
  info(msg: string, data?: Record<string, unknown>): void;
3
5
  error(msg: string, data?: Record<string, unknown>): void;
@@ -95,20 +97,129 @@ interface BatchEventResponse {
95
97
  error?: string;
96
98
  }
97
99
 
100
+ /**
101
+ * Server-side flags manager
102
+ * Optimized for server environments with:
103
+ * - Request-level deduplication
104
+ * - Request batching
105
+ * - Stale-while-revalidate caching
106
+ * - No persistent storage (stateless)
107
+ */
108
+ declare class ServerFlagsManager implements FlagsManager {
109
+ private config;
110
+ private readonly onFlagsUpdate?;
111
+ private readonly onConfigUpdate?;
112
+ /** In-memory cache with stale tracking */
113
+ private readonly cache;
114
+ /** In-flight requests for deduplication */
115
+ private readonly inFlight;
116
+ /** Request batcher */
117
+ private batcher;
118
+ /** Ready state */
119
+ private ready;
120
+ /** Init promise for awaiting */
121
+ private readonly initPromise;
122
+ constructor(options: FlagsManagerOptions);
123
+ private withDefaults;
124
+ private initialize;
125
+ /**
126
+ * Wait for initialization to complete
127
+ */
128
+ waitForInit(): Promise<void>;
129
+ private getFromCache;
130
+ private getBatcher;
131
+ /**
132
+ * Get a flag with deduplication, batching, and SWR caching
133
+ */
134
+ getFlag(key: string, user?: UserContext): Promise<FlagResult>;
135
+ private revalidateFlag;
136
+ /**
137
+ * Fetch all flags for a user
138
+ */
139
+ fetchAllFlags(user?: UserContext): Promise<void>;
140
+ /**
141
+ * Check if flag is enabled (synchronous)
142
+ */
143
+ isEnabled(key: string): FlagState;
144
+ /**
145
+ * Get flag value (synchronous)
146
+ */
147
+ getValue<T = boolean | string | number>(key: string, defaultValue?: T): T;
148
+ /**
149
+ * Update user context
150
+ */
151
+ updateUser(user: UserContext): void;
152
+ /**
153
+ * Refresh flags
154
+ */
155
+ refresh(forceClear?: boolean): Promise<void>;
156
+ /**
157
+ * Update config
158
+ */
159
+ updateConfig(config: FlagsConfig): void;
160
+ /**
161
+ * Get all cached flags
162
+ */
163
+ getMemoryFlags(): Record<string, FlagResult>;
164
+ /**
165
+ * Check if ready
166
+ */
167
+ isReady(): boolean;
168
+ /**
169
+ * Cleanup resources
170
+ */
171
+ destroy(): void;
172
+ }
173
+
174
+ /**
175
+ * Create a ServerFlagsManager with in-memory caching
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * import { createServerFlagsManager } from '@databuddy/sdk/node';
180
+ *
181
+ * const manager = createServerFlagsManager({
182
+ * clientId: process.env.DATABUDDY_CLIENT_ID!,
183
+ * });
184
+ *
185
+ * await manager.waitForInit();
186
+ * const flag = await manager.getFlag('my-feature');
187
+ * ```
188
+ */
189
+ declare function createServerFlagsManager(config: FlagsConfig): ServerFlagsManager;
190
+ /**
191
+ * Alias for createServerFlagsManager (for backwards compatibility)
192
+ *
193
+ * @example
194
+ * ```typescript
195
+ * import { createServerFlagsManagerInMemory } from '@databuddy/sdk/node';
196
+ *
197
+ * const manager = createServerFlagsManagerInMemory({
198
+ * clientId: process.env.DATABUDDY_CLIENT_ID!,
199
+ * });
200
+ *
201
+ * await manager.waitForInit();
202
+ * const flag = await manager.getFlag('my-feature');
203
+ * ```
204
+ */
205
+ declare function createServerFlagsManagerInMemory(config: FlagsConfig): ServerFlagsManager;
206
+
207
+ /** biome-ignore-all lint/performance/noBarrelFile: im a big fan of barrels */
208
+
98
209
  declare class Databuddy {
99
210
  private readonly clientId;
100
- private apiUrl;
101
- private logger;
102
- private enableBatching;
103
- private batchSize;
104
- private batchTimeout;
105
- private queue;
211
+ private readonly apiUrl;
212
+ private readonly logger;
213
+ private readonly enableBatching;
214
+ private readonly batchSize;
215
+ private readonly batchTimeout;
216
+ private readonly queue;
106
217
  private flushTimer;
107
218
  private globalProperties;
108
219
  private middleware;
109
- private enableDeduplication;
110
- private deduplicationCache;
111
- private maxDeduplicationCacheSize;
220
+ private readonly enableDeduplication;
221
+ private readonly deduplicationCache;
222
+ private readonly maxDeduplicationCacheSize;
112
223
  constructor(config: DatabuddyConfig);
113
224
  /**
114
225
  * Track a custom event
@@ -233,5 +344,5 @@ declare class Databuddy {
233
344
  private addToDeduplicationCache;
234
345
  }
235
346
 
236
- export { Databuddy, Databuddy as db };
347
+ export { Databuddy, ServerFlagsManager, createServerFlagsManager, createServerFlagsManagerInMemory, Databuddy as db };
237
348
  export type { BatchEventInput, BatchEventResponse, CustomEventInput, DatabuddyConfig, EventResponse, GlobalProperties, Logger, Middleware };
@@ -1,3 +1,5 @@
1
+ import { e as FlagsManager, f as FlagsManagerOptions, U as UserContext, d as FlagResult, b as FlagState, F as FlagsConfig } from '../shared/@databuddy/sdk.B6nwxnPC.js';
2
+
1
3
  interface Logger {
2
4
  info(msg: string, data?: Record<string, unknown>): void;
3
5
  error(msg: string, data?: Record<string, unknown>): void;
@@ -95,20 +97,129 @@ interface BatchEventResponse {
95
97
  error?: string;
96
98
  }
97
99
 
100
+ /**
101
+ * Server-side flags manager
102
+ * Optimized for server environments with:
103
+ * - Request-level deduplication
104
+ * - Request batching
105
+ * - Stale-while-revalidate caching
106
+ * - No persistent storage (stateless)
107
+ */
108
+ declare class ServerFlagsManager implements FlagsManager {
109
+ private config;
110
+ private readonly onFlagsUpdate?;
111
+ private readonly onConfigUpdate?;
112
+ /** In-memory cache with stale tracking */
113
+ private readonly cache;
114
+ /** In-flight requests for deduplication */
115
+ private readonly inFlight;
116
+ /** Request batcher */
117
+ private batcher;
118
+ /** Ready state */
119
+ private ready;
120
+ /** Init promise for awaiting */
121
+ private readonly initPromise;
122
+ constructor(options: FlagsManagerOptions);
123
+ private withDefaults;
124
+ private initialize;
125
+ /**
126
+ * Wait for initialization to complete
127
+ */
128
+ waitForInit(): Promise<void>;
129
+ private getFromCache;
130
+ private getBatcher;
131
+ /**
132
+ * Get a flag with deduplication, batching, and SWR caching
133
+ */
134
+ getFlag(key: string, user?: UserContext): Promise<FlagResult>;
135
+ private revalidateFlag;
136
+ /**
137
+ * Fetch all flags for a user
138
+ */
139
+ fetchAllFlags(user?: UserContext): Promise<void>;
140
+ /**
141
+ * Check if flag is enabled (synchronous)
142
+ */
143
+ isEnabled(key: string): FlagState;
144
+ /**
145
+ * Get flag value (synchronous)
146
+ */
147
+ getValue<T = boolean | string | number>(key: string, defaultValue?: T): T;
148
+ /**
149
+ * Update user context
150
+ */
151
+ updateUser(user: UserContext): void;
152
+ /**
153
+ * Refresh flags
154
+ */
155
+ refresh(forceClear?: boolean): Promise<void>;
156
+ /**
157
+ * Update config
158
+ */
159
+ updateConfig(config: FlagsConfig): void;
160
+ /**
161
+ * Get all cached flags
162
+ */
163
+ getMemoryFlags(): Record<string, FlagResult>;
164
+ /**
165
+ * Check if ready
166
+ */
167
+ isReady(): boolean;
168
+ /**
169
+ * Cleanup resources
170
+ */
171
+ destroy(): void;
172
+ }
173
+
174
+ /**
175
+ * Create a ServerFlagsManager with in-memory caching
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * import { createServerFlagsManager } from '@databuddy/sdk/node';
180
+ *
181
+ * const manager = createServerFlagsManager({
182
+ * clientId: process.env.DATABUDDY_CLIENT_ID!,
183
+ * });
184
+ *
185
+ * await manager.waitForInit();
186
+ * const flag = await manager.getFlag('my-feature');
187
+ * ```
188
+ */
189
+ declare function createServerFlagsManager(config: FlagsConfig): ServerFlagsManager;
190
+ /**
191
+ * Alias for createServerFlagsManager (for backwards compatibility)
192
+ *
193
+ * @example
194
+ * ```typescript
195
+ * import { createServerFlagsManagerInMemory } from '@databuddy/sdk/node';
196
+ *
197
+ * const manager = createServerFlagsManagerInMemory({
198
+ * clientId: process.env.DATABUDDY_CLIENT_ID!,
199
+ * });
200
+ *
201
+ * await manager.waitForInit();
202
+ * const flag = await manager.getFlag('my-feature');
203
+ * ```
204
+ */
205
+ declare function createServerFlagsManagerInMemory(config: FlagsConfig): ServerFlagsManager;
206
+
207
+ /** biome-ignore-all lint/performance/noBarrelFile: im a big fan of barrels */
208
+
98
209
  declare class Databuddy {
99
210
  private readonly clientId;
100
- private apiUrl;
101
- private logger;
102
- private enableBatching;
103
- private batchSize;
104
- private batchTimeout;
105
- private queue;
211
+ private readonly apiUrl;
212
+ private readonly logger;
213
+ private readonly enableBatching;
214
+ private readonly batchSize;
215
+ private readonly batchTimeout;
216
+ private readonly queue;
106
217
  private flushTimer;
107
218
  private globalProperties;
108
219
  private middleware;
109
- private enableDeduplication;
110
- private deduplicationCache;
111
- private maxDeduplicationCacheSize;
220
+ private readonly enableDeduplication;
221
+ private readonly deduplicationCache;
222
+ private readonly maxDeduplicationCacheSize;
112
223
  constructor(config: DatabuddyConfig);
113
224
  /**
114
225
  * Track a custom event
@@ -233,5 +344,5 @@ declare class Databuddy {
233
344
  private addToDeduplicationCache;
234
345
  }
235
346
 
236
- export { Databuddy, Databuddy as db };
347
+ export { Databuddy, ServerFlagsManager, createServerFlagsManager, createServerFlagsManagerInMemory, Databuddy as db };
237
348
  export type { BatchEventInput, BatchEventResponse, CustomEventInput, DatabuddyConfig, EventResponse, GlobalProperties, Logger, Middleware };
@@ -1,13 +1,7 @@
1
+ import { l as logger, i as isCacheValid, b as buildQueryParams, R as RequestBatcher, D as DEFAULT_RESULT, g as getCacheKey, a as isCacheStale, c as createCacheEntry, f as fetchAllFlags } from '../shared/@databuddy/sdk.3kaCzyfu.mjs';
2
+
1
3
  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
- }
4
+ return createConsoleLogger(debug);
11
5
  }
12
6
  function createConsoleLogger(debug) {
13
7
  const noop = () => {
@@ -68,6 +62,258 @@ class EventQueue {
68
62
  }
69
63
  }
70
64
 
65
+ class ServerFlagsManager {
66
+ config;
67
+ onFlagsUpdate;
68
+ onConfigUpdate;
69
+ /** In-memory cache with stale tracking */
70
+ cache = /* @__PURE__ */ new Map();
71
+ /** In-flight requests for deduplication */
72
+ inFlight = /* @__PURE__ */ new Map();
73
+ /** Request batcher */
74
+ batcher = null;
75
+ /** Ready state */
76
+ ready = false;
77
+ /** Init promise for awaiting */
78
+ initPromise;
79
+ constructor(options) {
80
+ this.config = this.withDefaults(options.config);
81
+ this.onFlagsUpdate = options.onFlagsUpdate;
82
+ this.onConfigUpdate = options.onConfigUpdate;
83
+ logger.setDebug(this.config.debug ?? false);
84
+ logger.debug("ServerFlagsManager initialized", {
85
+ clientId: this.config.clientId,
86
+ hasUser: Boolean(this.config.user)
87
+ });
88
+ this.initPromise = this.initialize();
89
+ }
90
+ withDefaults(config) {
91
+ return {
92
+ clientId: config.clientId,
93
+ apiUrl: config.apiUrl ?? "https://api.databuddy.cc",
94
+ user: config.user,
95
+ disabled: config.disabled ?? false,
96
+ debug: config.debug ?? false,
97
+ skipStorage: true,
98
+ // Always skip storage on server
99
+ isPending: config.isPending,
100
+ autoFetch: config.autoFetch ?? false,
101
+ environment: config.environment,
102
+ cacheTtl: config.cacheTtl ?? 6e4,
103
+ // 1 minute
104
+ staleTime: config.staleTime ?? 3e4
105
+ // 30 seconds
106
+ };
107
+ }
108
+ async initialize() {
109
+ if (this.config.autoFetch && !this.config.isPending) {
110
+ await this.fetchAllFlags();
111
+ }
112
+ this.ready = true;
113
+ }
114
+ /**
115
+ * Wait for initialization to complete
116
+ */
117
+ async waitForInit() {
118
+ await this.initPromise;
119
+ }
120
+ getFromCache(key) {
121
+ const cached = this.cache.get(key);
122
+ if (isCacheValid(cached)) {
123
+ return cached;
124
+ }
125
+ if (cached) {
126
+ this.cache.delete(key);
127
+ }
128
+ return null;
129
+ }
130
+ getBatcher() {
131
+ if (!this.batcher) {
132
+ const apiUrl = this.config.apiUrl ?? "https://api.databuddy.cc";
133
+ const params = buildQueryParams(this.config);
134
+ this.batcher = new RequestBatcher(apiUrl, params, 5);
135
+ }
136
+ return this.batcher;
137
+ }
138
+ /**
139
+ * Get a flag with deduplication, batching, and SWR caching
140
+ */
141
+ async getFlag(key, user) {
142
+ if (this.config.disabled) {
143
+ return DEFAULT_RESULT;
144
+ }
145
+ if (this.config.isPending) {
146
+ return { ...DEFAULT_RESULT, reason: "SESSION_PENDING" };
147
+ }
148
+ const cacheKey = getCacheKey(key, user ?? this.config.user);
149
+ const cached = this.getFromCache(cacheKey);
150
+ if (cached) {
151
+ if (isCacheStale(cached)) {
152
+ this.revalidateFlag(key, cacheKey);
153
+ }
154
+ return cached.result;
155
+ }
156
+ const existing = this.inFlight.get(cacheKey);
157
+ if (existing) {
158
+ logger.debug(`Deduplicating request: ${key}`);
159
+ return existing;
160
+ }
161
+ const promise = this.getBatcher().request(key);
162
+ this.inFlight.set(cacheKey, promise);
163
+ try {
164
+ const result = await promise;
165
+ const ttl = this.config.cacheTtl ?? 6e4;
166
+ const staleTime = this.config.staleTime ?? ttl / 2;
167
+ this.cache.set(cacheKey, createCacheEntry(result, ttl, staleTime));
168
+ return result;
169
+ } finally {
170
+ this.inFlight.delete(cacheKey);
171
+ }
172
+ }
173
+ async revalidateFlag(key, cacheKey) {
174
+ if (this.inFlight.has(cacheKey)) {
175
+ return;
176
+ }
177
+ const promise = this.getBatcher().request(key);
178
+ this.inFlight.set(cacheKey, promise);
179
+ try {
180
+ const result = await promise;
181
+ const ttl = this.config.cacheTtl ?? 6e4;
182
+ const staleTime = this.config.staleTime ?? ttl / 2;
183
+ this.cache.set(cacheKey, createCacheEntry(result, ttl, staleTime));
184
+ logger.debug(`Revalidated flag: ${key}`);
185
+ } catch (err) {
186
+ logger.error(`Revalidation error: ${key}`, err);
187
+ } finally {
188
+ this.inFlight.delete(cacheKey);
189
+ }
190
+ }
191
+ /**
192
+ * Fetch all flags for a user
193
+ */
194
+ async fetchAllFlags(user) {
195
+ if (this.config.disabled || this.config.isPending) {
196
+ return;
197
+ }
198
+ const apiUrl = this.config.apiUrl ?? "https://api.databuddy.cc";
199
+ const params = buildQueryParams(this.config, user);
200
+ try {
201
+ const flags = await fetchAllFlags(apiUrl, params);
202
+ const ttl = this.config.cacheTtl ?? 6e4;
203
+ const staleTime = this.config.staleTime ?? ttl / 2;
204
+ for (const [key, result] of Object.entries(flags)) {
205
+ const cacheKey = getCacheKey(key, user ?? this.config.user);
206
+ this.cache.set(cacheKey, createCacheEntry(result, ttl, staleTime));
207
+ }
208
+ this.ready = true;
209
+ this.onFlagsUpdate?.(flags);
210
+ logger.debug(`Fetched ${Object.keys(flags).length} flags`);
211
+ } catch (err) {
212
+ logger.error("Bulk fetch error:", err);
213
+ }
214
+ }
215
+ /**
216
+ * Check if flag is enabled (synchronous)
217
+ */
218
+ isEnabled(key) {
219
+ const cacheKey = getCacheKey(key, this.config.user);
220
+ const cached = this.getFromCache(cacheKey);
221
+ if (cached) {
222
+ return {
223
+ on: cached.result.enabled,
224
+ enabled: cached.result.enabled,
225
+ status: cached.result.reason === "ERROR" ? "error" : "ready",
226
+ loading: false,
227
+ isLoading: false,
228
+ isReady: true,
229
+ value: cached.result.value,
230
+ variant: cached.result.variant
231
+ };
232
+ }
233
+ const loading = this.inFlight.has(cacheKey);
234
+ return {
235
+ on: false,
236
+ enabled: false,
237
+ status: "loading",
238
+ loading,
239
+ isLoading: loading,
240
+ isReady: false
241
+ };
242
+ }
243
+ /**
244
+ * Get flag value (synchronous)
245
+ */
246
+ getValue(key, defaultValue) {
247
+ const cacheKey = getCacheKey(key, this.config.user);
248
+ const cached = this.getFromCache(cacheKey);
249
+ if (cached) {
250
+ return cached.result.value;
251
+ }
252
+ return defaultValue ?? false;
253
+ }
254
+ /**
255
+ * Update user context
256
+ */
257
+ updateUser(user) {
258
+ this.config = { ...this.config, user };
259
+ this.batcher?.destroy();
260
+ this.batcher = null;
261
+ this.onConfigUpdate?.(this.config);
262
+ }
263
+ /**
264
+ * Refresh flags
265
+ */
266
+ async refresh(forceClear = false) {
267
+ if (forceClear) {
268
+ this.cache.clear();
269
+ }
270
+ await this.fetchAllFlags();
271
+ }
272
+ /**
273
+ * Update config
274
+ */
275
+ updateConfig(config) {
276
+ this.config = this.withDefaults(config);
277
+ this.batcher?.destroy();
278
+ this.batcher = null;
279
+ this.onConfigUpdate?.(this.config);
280
+ }
281
+ /**
282
+ * Get all cached flags
283
+ */
284
+ getMemoryFlags() {
285
+ const flags = {};
286
+ for (const [key, entry] of this.cache) {
287
+ const flagKey = key.split(":")[0];
288
+ flags[flagKey] = entry.result;
289
+ }
290
+ return flags;
291
+ }
292
+ /**
293
+ * Check if ready
294
+ */
295
+ isReady() {
296
+ return this.ready;
297
+ }
298
+ /**
299
+ * Cleanup resources
300
+ */
301
+ destroy() {
302
+ this.batcher?.destroy();
303
+ this.cache.clear();
304
+ this.inFlight.clear();
305
+ }
306
+ }
307
+
308
+ function createServerFlagsManager(config) {
309
+ return new ServerFlagsManager({
310
+ config
311
+ });
312
+ }
313
+ function createServerFlagsManagerInMemory(config) {
314
+ return createServerFlagsManager(config);
315
+ }
316
+
71
317
  const DEFAULT_API_URL = "https://basket.databuddy.cc";
72
318
  const DEFAULT_BATCH_SIZE = 10;
73
319
  const DEFAULT_BATCH_TIMEOUT = 2e3;
@@ -259,7 +505,7 @@ class Databuddy {
259
505
  const events = this.queue.getAll();
260
506
  this.queue.clear();
261
507
  this.logger.info("Flushing events", { count: events.length });
262
- return this.batch(events);
508
+ return await this.batch(events);
263
509
  }
264
510
  /**
265
511
  * Send multiple events in a single batch request
@@ -515,4 +761,4 @@ class Databuddy {
515
761
  }
516
762
  }
517
763
 
518
- export { Databuddy, Databuddy as db };
764
+ export { Databuddy, ServerFlagsManager, createServerFlagsManager, createServerFlagsManagerInMemory, Databuddy as db };
@@ -1,9 +1,6 @@
1
- import { D as DatabuddyConfig } from '../shared/@databuddy/sdk.CeYE_kaj.mjs';
2
- import * as react from 'react';
3
- import { ReactNode } from 'react';
4
- import * as jotai_vanilla_internals from 'jotai/vanilla/internals';
5
- import { d as FlagsConfig, c as FlagState } from '../shared/@databuddy/sdk.OK9Nbqlf.mjs';
6
- export { b as FlagResult, e as FlagsContext } from '../shared/@databuddy/sdk.OK9Nbqlf.mjs';
1
+ import { D as DatabuddyConfig } from '../shared/@databuddy/sdk.C9b3SVYK.mjs';
2
+ import React, { ReactNode } from 'react';
3
+ import { F as FlagsConfig, a as FeatureState, b as FlagState, c as FlagsContext } from '../shared/@databuddy/sdk.B6nwxnPC.mjs';
7
4
 
8
5
  /**
9
6
  * React/Next.js component that injects the Databuddy tracking script.
@@ -56,18 +53,61 @@ export { b as FlagResult, e as FlagsContext } from '../shared/@databuddy/sdk.OK9
56
53
  */
57
54
  declare function Databuddy(props: DatabuddyConfig): null;
58
55
 
56
+ /** biome-ignore-all lint/correctness/noUnusedImports: we need to import React to use the createContext function */
57
+
59
58
  interface FlagsProviderProps extends FlagsConfig {
60
59
  children: ReactNode;
61
60
  }
62
- declare function FlagsProvider({ children, ...config }: FlagsProviderProps): react.FunctionComponentElement<{
63
- children?: ReactNode;
64
- store?: jotai_vanilla_internals.INTERNAL_Store;
65
- }>;
66
- declare function useFlags(): {
67
- isEnabled: (key: string) => FlagState;
68
- fetchAllFlags: () => Promise<void> | undefined;
69
- updateUser: (user: FlagsConfig["user"]) => void;
70
- refresh: (forceClear?: boolean) => void;
71
- };
61
+ /**
62
+ * Flags provider component
63
+ * Creates a manager instance and provides flag methods to children
64
+ */
65
+ declare function FlagsProvider({ children, ...config }: FlagsProviderProps): React.JSX.Element;
66
+ /**
67
+ * Access the full flags context
68
+ * @example
69
+ * const { isOn, getFlag, refresh } = useFlags();
70
+ */
71
+ declare function useFlags(): FlagsContext;
72
+ /**
73
+ * Get a flag's full state with loading/error handling
74
+ * @example
75
+ * const flag = useFlag("my-feature");
76
+ * if (flag.loading) return <Skeleton />;
77
+ * return flag.on ? <NewFeature /> : <OldFeature />;
78
+ */
79
+ declare function useFlag(key: string): FlagState;
80
+ /**
81
+ * Simple feature check - returns { on, loading, value, variant }
82
+ * @example
83
+ * const { on, loading } = useFeature("dark-mode");
84
+ * if (loading) return <Skeleton />;
85
+ * return on ? <DarkTheme /> : <LightTheme />;
86
+ */
87
+ declare function useFeature(key: string): FeatureState;
88
+ /**
89
+ * Boolean-only feature check with default value
90
+ * Useful for SSR-safe rendering where you need a boolean immediately
91
+ * @example
92
+ * const isDarkMode = useFeatureOn("dark-mode", false);
93
+ * return isDarkMode ? <DarkTheme /> : <LightTheme />;
94
+ */
95
+ declare function useFeatureOn(key: string, defaultValue?: boolean): boolean;
96
+ /**
97
+ * Get a flag's typed value
98
+ * @example
99
+ * const maxItems = useFlagValue("max-items", 10);
100
+ * const theme = useFlagValue<"light" | "dark">("theme", "light");
101
+ */
102
+ declare function useFlagValue<T extends boolean | string | number = boolean>(key: string, defaultValue?: T): T;
103
+ /**
104
+ * Get variant for A/B testing
105
+ * @example
106
+ * const variant = useVariant("checkout-experiment");
107
+ * if (variant === "control") return <OldCheckout />;
108
+ * if (variant === "treatment-a") return <NewCheckoutA />;
109
+ * return <NewCheckoutB />;
110
+ */
111
+ declare function useVariant(key: string): string | undefined;
72
112
 
73
- export { Databuddy, FlagState, FlagsConfig, FlagsProvider, useFlags };
113
+ export { Databuddy, FlagsProvider, useFeature, useFeatureOn, useFlag, useFlagValue, useFlags, useVariant };