@databuddy/sdk 2.3.1 → 2.3.21

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,9 +1,7 @@
1
- import { D as DatabuddyConfig } from '../shared/@databuddy/sdk.CeYE_kaj.js';
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.js';
6
- export { b as FlagResult, e as FlagsContext } from '../shared/@databuddy/sdk.OK9Nbqlf.js';
1
+ import { D as DatabuddyConfig } from '../shared/@databuddy/sdk.BsF1xr6_.js';
2
+ export { c as clear, f as flush, d as getAnonymousId, e as getSessionId, g as getTracker, h as getTrackingIds, j as getTrackingParams, i as isTrackerAvailable, t as track, b as trackError } from '../shared/@databuddy/sdk.BsF1xr6_.js';
3
+ import React, { ReactNode } from 'react';
4
+ import { F as FlagsConfig, a as FeatureState, b as FlagState, c as FlagsContext } from '../shared/@databuddy/sdk.B6nwxnPC.js';
7
5
 
8
6
  /**
9
7
  * React/Next.js component that injects the Databuddy tracking script.
@@ -56,18 +54,61 @@ export { b as FlagResult, e as FlagsContext } from '../shared/@databuddy/sdk.OK9
56
54
  */
57
55
  declare function Databuddy(props: DatabuddyConfig): null;
58
56
 
57
+ /** biome-ignore-all lint/correctness/noUnusedImports: we need to import React to use the createContext function */
58
+
59
59
  interface FlagsProviderProps extends FlagsConfig {
60
60
  children: ReactNode;
61
61
  }
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
- };
62
+ /**
63
+ * Flags provider component
64
+ * Creates a manager instance and provides flag methods to children
65
+ */
66
+ declare function FlagsProvider({ children, ...config }: FlagsProviderProps): React.JSX.Element;
67
+ /**
68
+ * Access the full flags context
69
+ * @example
70
+ * const { isOn, getFlag, refresh } = useFlags();
71
+ */
72
+ declare function useFlags(): FlagsContext;
73
+ /**
74
+ * Get a flag's full state with loading/error handling
75
+ * @example
76
+ * const flag = useFlag("my-feature");
77
+ * if (flag.loading) return <Skeleton />;
78
+ * return flag.on ? <NewFeature /> : <OldFeature />;
79
+ */
80
+ declare function useFlag(key: string): FlagState;
81
+ /**
82
+ * Simple feature check - returns { on, loading, value, variant }
83
+ * @example
84
+ * const { on, loading } = useFeature("dark-mode");
85
+ * if (loading) return <Skeleton />;
86
+ * return on ? <DarkTheme /> : <LightTheme />;
87
+ */
88
+ declare function useFeature(key: string): FeatureState;
89
+ /**
90
+ * Boolean-only feature check with default value
91
+ * Useful for SSR-safe rendering where you need a boolean immediately
92
+ * @example
93
+ * const isDarkMode = useFeatureOn("dark-mode", false);
94
+ * return isDarkMode ? <DarkTheme /> : <LightTheme />;
95
+ */
96
+ declare function useFeatureOn(key: string, defaultValue?: boolean): boolean;
97
+ /**
98
+ * Get a flag's typed value
99
+ * @example
100
+ * const maxItems = useFlagValue("max-items", 10);
101
+ * const theme = useFlagValue<"light" | "dark">("theme", "light");
102
+ */
103
+ declare function useFlagValue<T extends boolean | string | number = boolean>(key: string, defaultValue?: T): T;
104
+ /**
105
+ * Get variant for A/B testing
106
+ * @example
107
+ * const variant = useVariant("checkout-experiment");
108
+ * if (variant === "control") return <OldCheckout />;
109
+ * if (variant === "treatment-a") return <NewCheckoutA />;
110
+ * return <NewCheckoutB />;
111
+ */
112
+ declare function useVariant(key: string): string | undefined;
72
113
 
73
- export { Databuddy, FlagState, FlagsConfig, FlagsProvider, useFlags };
114
+ export { Databuddy, FlagsProvider, useFeature, useFeatureOn, useFlag, useFlagValue, useFlags, useVariant };
@@ -1,9 +1,11 @@
1
1
  'use client';
2
2
 
3
- import { i as isScriptInjected, c as createScript, B as BrowserFlagStorage, C as CoreFlagsManager, l as logger } from '../shared/@databuddy/sdk.ByNF_UxE.mjs';
4
- import { d as detectClientId } from '../shared/@databuddy/sdk.BUsPV0LH.mjs';
5
- import { createStore, atom, Provider, useAtom } from 'jotai';
6
- import { useRef, useEffect, createElement } from 'react';
3
+ import { detectClientId } from '../core/index.mjs';
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.C8vEu9Y4.mjs';
6
+ import React, { useRef, useMemo, useEffect, useSyncExternalStore, createContext, useContext } from 'react';
7
+ import { B as BrowserFlagStorage, C as CoreFlagsManager } from '../shared/@databuddy/sdk.D0dyEsAb.mjs';
8
+ import { l as logger } from '../shared/@databuddy/sdk.DCKr2Zpd.mjs';
7
9
 
8
10
  function Databuddy(props) {
9
11
  const clientId = detectClientId(props.clientId);
@@ -22,101 +24,192 @@ function Databuddy(props) {
22
24
  return null;
23
25
  }
24
26
 
25
- const flagsStore = createStore();
26
- const managerAtom = atom(null);
27
- const memoryFlagsAtom = atom({});
27
+ const FlagsReactContext = createContext(null);
28
+ function createFlagState(result, isLoading, isPending) {
29
+ if (isPending) {
30
+ return {
31
+ on: false,
32
+ enabled: false,
33
+ status: "pending",
34
+ loading: true,
35
+ isLoading: true,
36
+ isReady: false
37
+ };
38
+ }
39
+ if (isLoading || !result) {
40
+ return {
41
+ on: false,
42
+ enabled: false,
43
+ status: "loading",
44
+ loading: true,
45
+ isLoading: true,
46
+ isReady: false
47
+ };
48
+ }
49
+ const status = result.reason === "ERROR" ? "error" : "ready";
50
+ return {
51
+ on: result.enabled,
52
+ enabled: result.enabled,
53
+ status,
54
+ loading: false,
55
+ isLoading: false,
56
+ isReady: true,
57
+ value: result.value,
58
+ variant: result.variant
59
+ };
60
+ }
28
61
  function FlagsProvider({ children, ...config }) {
29
- const managerRef = useRef(null);
30
- useEffect(() => {
62
+ const storeRef = useRef({ flags: {}, isReady: false });
63
+ const listenersRef = useRef(/* @__PURE__ */ new Set());
64
+ const manager = useMemo(() => {
31
65
  const storage = config.skipStorage ? void 0 : new BrowserFlagStorage();
32
- const manager = new CoreFlagsManager({
66
+ return new CoreFlagsManager({
33
67
  config,
34
68
  storage,
35
69
  onFlagsUpdate: (flags) => {
36
- flagsStore.set(memoryFlagsAtom, flags);
70
+ storeRef.current = { ...storeRef.current, flags };
71
+ for (const listener of listenersRef.current) {
72
+ listener();
73
+ }
74
+ },
75
+ onReady: () => {
76
+ storeRef.current = { ...storeRef.current, isReady: true };
77
+ for (const listener of listenersRef.current) {
78
+ listener();
79
+ }
37
80
  }
38
81
  });
39
- managerRef.current = manager;
40
- flagsStore.set(managerAtom, manager);
41
- return () => {
42
- managerRef.current = null;
43
- flagsStore.set(managerAtom, null);
44
- };
45
- }, [
46
- config.clientId,
47
- config.apiUrl,
48
- config.user?.userId,
49
- config.user?.email,
50
- config.disabled,
51
- config.debug,
52
- config.skipStorage,
53
- config.isPending,
54
- config.autoFetch
55
- ]);
82
+ }, [config.clientId]);
83
+ const prevConfigRef = useRef(config);
56
84
  useEffect(() => {
57
- if (managerRef.current) {
58
- managerRef.current.updateConfig(config);
85
+ const prevConfig = prevConfigRef.current;
86
+ const configChanged = prevConfig.apiUrl !== config.apiUrl || prevConfig.isPending !== config.isPending || prevConfig.user?.userId !== config.user?.userId || prevConfig.user?.email !== config.user?.email || prevConfig.environment !== config.environment || prevConfig.disabled !== config.disabled || prevConfig.autoFetch !== config.autoFetch || prevConfig.cacheTtl !== config.cacheTtl || prevConfig.staleTime !== config.staleTime;
87
+ if (configChanged) {
88
+ prevConfigRef.current = config;
89
+ manager.updateConfig(config);
59
90
  }
60
- }, [
61
- config.clientId,
62
- config.apiUrl,
63
- config.user?.userId,
64
- config.user?.email,
65
- config.disabled,
66
- config.debug,
67
- config.skipStorage,
68
- config.isPending,
69
- config.autoFetch
70
- ]);
71
- return createElement(Provider, { store: flagsStore }, children);
91
+ }, [manager, config]);
92
+ useEffect(() => {
93
+ return () => {
94
+ manager.destroy();
95
+ };
96
+ }, [manager]);
97
+ const subscribe = useMemo(
98
+ () => (callback) => {
99
+ listenersRef.current.add(callback);
100
+ return () => {
101
+ listenersRef.current.delete(callback);
102
+ };
103
+ },
104
+ []
105
+ );
106
+ const getSnapshot = useMemo(() => () => storeRef.current, []);
107
+ const store = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
108
+ const contextValue = useMemo(
109
+ () => ({
110
+ // Cleaner API: getFlag returns FlagState
111
+ getFlag: (key) => {
112
+ const result = store.flags[key];
113
+ const managerState = manager.isEnabled(key);
114
+ return createFlagState(
115
+ result,
116
+ managerState.isLoading,
117
+ config.isPending ?? false
118
+ );
119
+ },
120
+ // Simple boolean check
121
+ isOn: (key) => {
122
+ const result = store.flags[key];
123
+ if (result) {
124
+ return result.enabled;
125
+ }
126
+ const state = manager.isEnabled(key);
127
+ return state.enabled;
128
+ },
129
+ // Get typed value
130
+ getValue: (key, defaultValue) => {
131
+ const result = store.flags[key];
132
+ if (result) {
133
+ return result.value;
134
+ }
135
+ return manager.getValue(key, defaultValue);
136
+ },
137
+ // Async fetch
138
+ fetchFlag: (key) => manager.getFlag(key),
139
+ fetchAllFlags: () => manager.fetchAllFlags(),
140
+ updateUser: (user) => manager.updateUser(user),
141
+ refresh: (forceClear = false) => manager.refresh(forceClear),
142
+ isReady: store.isReady,
143
+ // Deprecated: kept for backwards compatibility
144
+ isEnabled: (key) => {
145
+ const result = store.flags[key];
146
+ const managerState = manager.isEnabled(key);
147
+ return createFlagState(
148
+ result,
149
+ managerState.isLoading,
150
+ config.isPending ?? false
151
+ );
152
+ }
153
+ }),
154
+ [manager, store, config.isPending]
155
+ );
156
+ return /* @__PURE__ */ React.createElement(FlagsReactContext.Provider, { value: contextValue }, children);
72
157
  }
73
158
  function useFlags() {
74
- const [manager] = useAtom(managerAtom, { store: flagsStore });
75
- const [memoryFlags] = useAtom(memoryFlagsAtom, {
76
- store: flagsStore
77
- });
78
- logger.debug("useFlags called with manager:", {
79
- hasManager: !!manager,
80
- memoryFlagsCount: Object.keys(memoryFlags).length,
81
- memoryFlags: Object.keys(memoryFlags)
82
- });
83
- const isEnabled = (key) => {
84
- if (!manager) {
85
- return {
159
+ const context = useContext(FlagsReactContext);
160
+ if (!context) {
161
+ logger.warn("useFlags called outside FlagsProvider");
162
+ return {
163
+ isEnabled: () => createFlagState(void 0, false, false),
164
+ getFlag: () => createFlagState(void 0, false, false),
165
+ isOn: () => false,
166
+ getValue: (_key, defaultValue) => defaultValue ?? false,
167
+ fetchFlag: async () => ({
86
168
  enabled: false,
87
- isLoading: false,
88
- isReady: false
89
- };
90
- }
91
- return manager.isEnabled(key);
92
- };
93
- const fetchAllFlags = () => {
94
- if (!manager) {
95
- logger.warn("No manager for bulk fetch");
96
- return;
97
- }
98
- return manager.fetchAllFlags();
99
- };
100
- const updateUser = (user) => {
101
- if (!manager) {
102
- logger.warn("No manager for user update");
103
- return;
104
- }
105
- manager.updateUser(user);
106
- };
107
- const refresh = (forceClear = false) => {
108
- if (!manager) {
109
- logger.warn("No manager for refresh");
110
- return;
111
- }
112
- manager.refresh(forceClear);
113
- };
169
+ value: false,
170
+ payload: null,
171
+ reason: "NO_PROVIDER"
172
+ }),
173
+ fetchAllFlags: async () => {
174
+ },
175
+ updateUser: () => {
176
+ },
177
+ refresh: async () => {
178
+ },
179
+ isReady: false
180
+ };
181
+ }
182
+ return context;
183
+ }
184
+ function useFlag(key) {
185
+ const { getFlag } = useFlags();
186
+ return getFlag(key);
187
+ }
188
+ function useFeature(key) {
189
+ const flag = useFlag(key);
114
190
  return {
115
- isEnabled,
116
- fetchAllFlags,
117
- updateUser,
118
- refresh
191
+ on: flag.on,
192
+ loading: flag.loading,
193
+ status: flag.status,
194
+ value: flag.value,
195
+ variant: flag.variant
119
196
  };
120
197
  }
198
+ function useFeatureOn(key, defaultValue = false) {
199
+ const { isOn, isReady } = useFlags();
200
+ const flag = useFlag(key);
201
+ if (flag.loading || !isReady) {
202
+ return defaultValue;
203
+ }
204
+ return isOn(key);
205
+ }
206
+ function useFlagValue(key, defaultValue) {
207
+ const { getValue } = useFlags();
208
+ return getValue(key, defaultValue);
209
+ }
210
+ function useVariant(key) {
211
+ const flag = useFlag(key);
212
+ return flag.variant;
213
+ }
121
214
 
122
- export { Databuddy, FlagsProvider, useFlags };
215
+ export { Databuddy, FlagsProvider, useFeature, useFeatureOn, useFlag, useFlagValue, useFlags, useVariant };
@@ -0,0 +1,128 @@
1
+ /** Flag evaluation result from API */
2
+ interface FlagResult {
3
+ enabled: boolean;
4
+ value: boolean | string | number;
5
+ payload: Record<string, unknown> | null;
6
+ reason: string;
7
+ variant?: string;
8
+ }
9
+ /** User context for flag evaluation */
10
+ interface UserContext {
11
+ userId?: string;
12
+ email?: string;
13
+ properties?: Record<string, unknown>;
14
+ }
15
+ /** SDK configuration */
16
+ interface FlagsConfig {
17
+ /** Client ID (website or organization ID) */
18
+ clientId: string;
19
+ /** API URL (default: https://api.databuddy.cc) */
20
+ apiUrl?: string;
21
+ /** User context for evaluation */
22
+ user?: UserContext;
23
+ /** Disable flag evaluation entirely */
24
+ disabled?: boolean;
25
+ /** Enable debug logging */
26
+ debug?: boolean;
27
+ /** Skip persistent storage (browser only) */
28
+ skipStorage?: boolean;
29
+ /** Session is loading - defer evaluation */
30
+ isPending?: boolean;
31
+ /** Auto-fetch all flags on init (default: true) */
32
+ autoFetch?: boolean;
33
+ /** Environment name */
34
+ environment?: string;
35
+ /** Cache TTL in ms - after this, cache is invalid (default: 60000) */
36
+ cacheTtl?: number;
37
+ /** Stale time in ms - after this, revalidate in background (default: cacheTtl/2) */
38
+ staleTime?: number;
39
+ }
40
+ /** Flag status for clear state management */
41
+ type FlagStatus = "loading" | "ready" | "error" | "pending";
42
+ /** Synchronous flag state for React hooks */
43
+ interface FlagState {
44
+ /** Whether the flag is enabled (true/false) */
45
+ on: boolean;
46
+ /** @deprecated Use `on` instead */
47
+ enabled: boolean;
48
+ /** Current status: loading, ready, error, or pending */
49
+ status: FlagStatus;
50
+ /** Whether the flag is still loading */
51
+ loading: boolean;
52
+ /** @deprecated Use `status === 'ready'` instead */
53
+ isLoading: boolean;
54
+ /** @deprecated Use `status === 'ready'` instead */
55
+ isReady: boolean;
56
+ /** The flag's value (boolean, string, or number) */
57
+ value?: boolean | string | number;
58
+ /** Variant name for multivariate flags */
59
+ variant?: string;
60
+ }
61
+ /** Feature state returned by useFeature hook */
62
+ interface FeatureState {
63
+ /** Whether the feature is enabled */
64
+ on: boolean;
65
+ /** Whether the flag is loading */
66
+ loading: boolean;
67
+ /** Current status */
68
+ status: FlagStatus;
69
+ /** The flag's value */
70
+ value?: boolean | string | number;
71
+ /** Variant for A/B tests */
72
+ variant?: string;
73
+ }
74
+ /** Context returned by useFlags hook */
75
+ interface FlagsContext {
76
+ /** @deprecated Use getFlag instead - confusing name */
77
+ isEnabled: (key: string) => FlagState;
78
+ /** Get a flag's full state */
79
+ getFlag: (key: string) => FlagState;
80
+ /** Get a flag's value with type safety */
81
+ getValue: <T extends boolean | string | number = boolean>(key: string, defaultValue?: T) => T;
82
+ /** Check if a flag is on (simple boolean) */
83
+ isOn: (key: string) => boolean;
84
+ /** Async fetch a specific flag */
85
+ fetchFlag: (key: string) => Promise<FlagResult>;
86
+ /** Fetch all flags */
87
+ fetchAllFlags: () => Promise<void>;
88
+ /** Update user context */
89
+ updateUser: (user: UserContext) => void;
90
+ /** Refresh all flags */
91
+ refresh: (forceClear?: boolean) => Promise<void>;
92
+ /** Whether the SDK is ready */
93
+ isReady: boolean;
94
+ }
95
+ /** Storage interface for persistence */
96
+ interface StorageInterface {
97
+ get(key: string): FlagResult | null;
98
+ set(key: string, value: FlagResult): void;
99
+ getAll(): Record<string, FlagResult>;
100
+ setAll(flags: Record<string, FlagResult>): void;
101
+ delete?(key: string): void;
102
+ deleteMultiple?(keys: string[]): void;
103
+ clear(): void;
104
+ cleanupExpired(): void;
105
+ }
106
+ /** Manager constructor options */
107
+ interface FlagsManagerOptions {
108
+ config: FlagsConfig;
109
+ storage?: StorageInterface;
110
+ onFlagsUpdate?: (flags: Record<string, FlagResult>) => void;
111
+ onConfigUpdate?: (config: FlagsConfig) => void;
112
+ onReady?: () => void;
113
+ }
114
+ /** Flags manager interface */
115
+ interface FlagsManager {
116
+ getFlag: (key: string, user?: UserContext) => Promise<FlagResult>;
117
+ isEnabled: (key: string) => FlagState;
118
+ getValue: <T = boolean | string | number>(key: string, defaultValue?: T) => T;
119
+ fetchAllFlags: (user?: UserContext) => Promise<void>;
120
+ updateUser: (user: UserContext) => void;
121
+ refresh: (forceClear?: boolean) => Promise<void>;
122
+ updateConfig: (config: FlagsConfig) => void;
123
+ getMemoryFlags: () => Record<string, FlagResult>;
124
+ isReady: () => boolean;
125
+ destroy?: () => void;
126
+ }
127
+
128
+ export type { FlagsConfig as F, UserContext as U, FeatureState as a, FlagState as b, FlagsContext as c, FlagResult as d, FlagsManager as e, FlagsManagerOptions as f };
@@ -0,0 +1,128 @@
1
+ /** Flag evaluation result from API */
2
+ interface FlagResult {
3
+ enabled: boolean;
4
+ value: boolean | string | number;
5
+ payload: Record<string, unknown> | null;
6
+ reason: string;
7
+ variant?: string;
8
+ }
9
+ /** User context for flag evaluation */
10
+ interface UserContext {
11
+ userId?: string;
12
+ email?: string;
13
+ properties?: Record<string, unknown>;
14
+ }
15
+ /** SDK configuration */
16
+ interface FlagsConfig {
17
+ /** Client ID (website or organization ID) */
18
+ clientId: string;
19
+ /** API URL (default: https://api.databuddy.cc) */
20
+ apiUrl?: string;
21
+ /** User context for evaluation */
22
+ user?: UserContext;
23
+ /** Disable flag evaluation entirely */
24
+ disabled?: boolean;
25
+ /** Enable debug logging */
26
+ debug?: boolean;
27
+ /** Skip persistent storage (browser only) */
28
+ skipStorage?: boolean;
29
+ /** Session is loading - defer evaluation */
30
+ isPending?: boolean;
31
+ /** Auto-fetch all flags on init (default: true) */
32
+ autoFetch?: boolean;
33
+ /** Environment name */
34
+ environment?: string;
35
+ /** Cache TTL in ms - after this, cache is invalid (default: 60000) */
36
+ cacheTtl?: number;
37
+ /** Stale time in ms - after this, revalidate in background (default: cacheTtl/2) */
38
+ staleTime?: number;
39
+ }
40
+ /** Flag status for clear state management */
41
+ type FlagStatus = "loading" | "ready" | "error" | "pending";
42
+ /** Synchronous flag state for React hooks */
43
+ interface FlagState {
44
+ /** Whether the flag is enabled (true/false) */
45
+ on: boolean;
46
+ /** @deprecated Use `on` instead */
47
+ enabled: boolean;
48
+ /** Current status: loading, ready, error, or pending */
49
+ status: FlagStatus;
50
+ /** Whether the flag is still loading */
51
+ loading: boolean;
52
+ /** @deprecated Use `status === 'ready'` instead */
53
+ isLoading: boolean;
54
+ /** @deprecated Use `status === 'ready'` instead */
55
+ isReady: boolean;
56
+ /** The flag's value (boolean, string, or number) */
57
+ value?: boolean | string | number;
58
+ /** Variant name for multivariate flags */
59
+ variant?: string;
60
+ }
61
+ /** Feature state returned by useFeature hook */
62
+ interface FeatureState {
63
+ /** Whether the feature is enabled */
64
+ on: boolean;
65
+ /** Whether the flag is loading */
66
+ loading: boolean;
67
+ /** Current status */
68
+ status: FlagStatus;
69
+ /** The flag's value */
70
+ value?: boolean | string | number;
71
+ /** Variant for A/B tests */
72
+ variant?: string;
73
+ }
74
+ /** Context returned by useFlags hook */
75
+ interface FlagsContext {
76
+ /** @deprecated Use getFlag instead - confusing name */
77
+ isEnabled: (key: string) => FlagState;
78
+ /** Get a flag's full state */
79
+ getFlag: (key: string) => FlagState;
80
+ /** Get a flag's value with type safety */
81
+ getValue: <T extends boolean | string | number = boolean>(key: string, defaultValue?: T) => T;
82
+ /** Check if a flag is on (simple boolean) */
83
+ isOn: (key: string) => boolean;
84
+ /** Async fetch a specific flag */
85
+ fetchFlag: (key: string) => Promise<FlagResult>;
86
+ /** Fetch all flags */
87
+ fetchAllFlags: () => Promise<void>;
88
+ /** Update user context */
89
+ updateUser: (user: UserContext) => void;
90
+ /** Refresh all flags */
91
+ refresh: (forceClear?: boolean) => Promise<void>;
92
+ /** Whether the SDK is ready */
93
+ isReady: boolean;
94
+ }
95
+ /** Storage interface for persistence */
96
+ interface StorageInterface {
97
+ get(key: string): FlagResult | null;
98
+ set(key: string, value: FlagResult): void;
99
+ getAll(): Record<string, FlagResult>;
100
+ setAll(flags: Record<string, FlagResult>): void;
101
+ delete?(key: string): void;
102
+ deleteMultiple?(keys: string[]): void;
103
+ clear(): void;
104
+ cleanupExpired(): void;
105
+ }
106
+ /** Manager constructor options */
107
+ interface FlagsManagerOptions {
108
+ config: FlagsConfig;
109
+ storage?: StorageInterface;
110
+ onFlagsUpdate?: (flags: Record<string, FlagResult>) => void;
111
+ onConfigUpdate?: (config: FlagsConfig) => void;
112
+ onReady?: () => void;
113
+ }
114
+ /** Flags manager interface */
115
+ interface FlagsManager {
116
+ getFlag: (key: string, user?: UserContext) => Promise<FlagResult>;
117
+ isEnabled: (key: string) => FlagState;
118
+ getValue: <T = boolean | string | number>(key: string, defaultValue?: T) => T;
119
+ fetchAllFlags: (user?: UserContext) => Promise<void>;
120
+ updateUser: (user: UserContext) => void;
121
+ refresh: (forceClear?: boolean) => Promise<void>;
122
+ updateConfig: (config: FlagsConfig) => void;
123
+ getMemoryFlags: () => Record<string, FlagResult>;
124
+ isReady: () => boolean;
125
+ destroy?: () => void;
126
+ }
127
+
128
+ export type { FlagsConfig as F, UserContext as U, FeatureState as a, FlagState as b, FlagsContext as c, FlagResult as d, FlagsManager as e, FlagsManagerOptions as f };