@featureflare/react 0.0.24 → 0.0.26

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/README.md CHANGED
@@ -38,7 +38,15 @@ export function App() {
38
38
  }
39
39
 
40
40
  return (
41
- <FeatureFlareProvider config={config} initialUser={{ id: 'user-123', key: 'user-123' }}>
41
+ <FeatureFlareProvider
42
+ config={{
43
+ ...config,
44
+ bootstrap: {
45
+ flags: { 'new-nav': true }
46
+ }
47
+ }}
48
+ initialUser={{ id: 'user-123', key: 'user-123' }}
49
+ >
42
50
  <FlagsBootstrap />
43
51
  {/* app */}
44
52
  </FeatureFlareProvider>
@@ -49,10 +57,10 @@ export function App() {
49
57
  ### Read One Flag
50
58
 
51
59
  ```typescript
52
- import { useBoolFlag } from '@featureflare/react';
60
+ import { useFlag } from '@featureflare/react';
53
61
 
54
62
  export function NewNav() {
55
- const { value, loading, error } = useBoolFlag('new-nav', false);
63
+ const { value, loading, error } = useFlag('new-nav', false);
56
64
 
57
65
  if (loading) return <div>Loading...</div>;
58
66
  if (error) return <div>Error: {error}</div>;
@@ -61,6 +69,58 @@ export function NewNav() {
61
69
  }
62
70
  ```
63
71
 
72
+ ### SSR/HTML Bootstrap (anti-flicker working flow)
73
+
74
+ Server-side (example in Next.js `getServerSideProps`):
75
+
76
+ ```typescript
77
+ import { FeatureFlareClient } from '@featureflare/sdk-js';
78
+
79
+ export async function getServerSideProps() {
80
+ const user = { id: 'user-123', key: 'user-123' };
81
+ const sdk = new FeatureFlareClient({
82
+ apiBaseUrl: process.env.FEATUREFLARE_API_BASE_URL,
83
+ sdkKey: process.env.FEATUREFLARE_SERVER_SDK_KEY
84
+ });
85
+
86
+ const nav = await sdk.bool('new-nav', user, false);
87
+
88
+ return {
89
+ props: {
90
+ user,
91
+ ffBootstrap: {
92
+ flags: { 'new-nav': nav }
93
+ }
94
+ }
95
+ };
96
+ }
97
+ ```
98
+
99
+ Client-side provider wiring:
100
+
101
+ ```typescript
102
+ import { FeatureFlareProvider, resolveFeatureFlareBrowserConfig } from '@featureflare/react';
103
+
104
+ export default function Page({ user, ffBootstrap }) {
105
+ const config = resolveFeatureFlareBrowserConfig();
106
+
107
+ return (
108
+ <FeatureFlareProvider
109
+ config={{
110
+ ...config,
111
+ bootstrap: ffBootstrap
112
+ }}
113
+ initialUser={user}
114
+ >
115
+ {/* First render uses bootstrap synchronously; no loading flicker for these flags */}
116
+ <App />
117
+ </FeatureFlareProvider>
118
+ );
119
+ }
120
+ ```
121
+
122
+ For non-SSR apps, inject a bootstrap JSON payload into HTML before app startup and pass it to `config.bootstrap` the same way.
123
+
64
124
  ## API
65
125
 
66
126
  ### `FeatureFlareProvider`
@@ -93,6 +153,7 @@ Returns:
93
153
 
94
154
  Signatures:
95
155
 
156
+ - `useFlags(keys: string[], defaultValue?: boolean)` → `{ values, loading, errors }`
96
157
  - `useFlags(input?: { user?: FeatureFlareUserPayload; defaultValue?: boolean; refreshIntervalMs?: number; hiddenRefreshIntervalMs?: number; pauseWhenHidden?: boolean; enabled?: boolean })`
97
158
  - `useFlags(defaultValue?: boolean, options?: { refreshIntervalMs?: number; hiddenRefreshIntervalMs?: number; pauseWhenHidden?: boolean; enabled?: boolean })`
98
159
 
@@ -102,6 +163,14 @@ Returns:
102
163
  - `loading: boolean`
103
164
  - `error: string | null`
104
165
 
166
+ ### `useFlag(key, defaultValue?)`
167
+
168
+ Selector-based single-flag subscription. Components only re-render when that flag changes.
169
+
170
+ ### `useFlagDiagnostics(key)`
171
+
172
+ Returns per-flag runtime diagnostics (source, stale state, cache timestamps, latency).
173
+
105
174
  Behavior:
106
175
 
107
176
  - Immediate fetch on mount/user change.
@@ -117,3 +186,5 @@ Behavior:
117
186
  ## Security: Client-side flags are not authorization
118
187
 
119
188
  Client keys can be extracted from your frontend bundle. **Never gate truly sensitive operations solely with client-evaluated flags**—enforce authorization on your backend.
189
+ - `config.bootstrap?: { flags, killSwitches }` for SSR/HTML bootstrap to avoid first-render flicker
190
+ - `config.timeoutMs | maxRetries | backoffMs | jitter | cacheTtlMs | staleTtlMs | realtime` are forwarded to the SDK client
package/dist/index.cjs CHANGED
@@ -36,6 +36,8 @@ __export(index_exports, {
36
36
  useBoolFlags: () => useBoolFlags,
37
37
  useFeatureFlareContext: () => useFeatureFlareContext,
38
38
  useFeatureFlareUser: () => useFeatureFlareUser,
39
+ useFlag: () => useFlag,
40
+ useFlagDiagnostics: () => useFlagDiagnostics,
39
41
  useFlags: () => useFlags
40
42
  });
41
43
  module.exports = __toCommonJS(index_exports);
@@ -70,6 +72,29 @@ function normalizeSubscriptionOptions(options) {
70
72
  enabled: options?.enabled ?? true
71
73
  };
72
74
  }
75
+ function flagsToMap(flags) {
76
+ const map = /* @__PURE__ */ new Map();
77
+ for (const flag of flags) {
78
+ map.set(flag.key, flag.value);
79
+ }
80
+ return map;
81
+ }
82
+ function diffFlagKeys(prev, next) {
83
+ const changed = /* @__PURE__ */ new Set();
84
+ const prevMap = flagsToMap(prev);
85
+ const nextMap = flagsToMap(next);
86
+ for (const [key, value] of prevMap.entries()) {
87
+ if (!nextMap.has(key) || nextMap.get(key) !== value) {
88
+ changed.add(key);
89
+ }
90
+ }
91
+ for (const [key, value] of nextMap.entries()) {
92
+ if (!prevMap.has(key) || prevMap.get(key) !== value) {
93
+ changed.add(key);
94
+ }
95
+ }
96
+ return changed;
97
+ }
73
98
  function createFlagsStore(client, getUser) {
74
99
  const entries = /* @__PURE__ */ new Map();
75
100
  let nextSubscriberId = 1;
@@ -78,10 +103,11 @@ function createFlagsStore(client, getUser) {
78
103
  const key = defaultValue ? "1" : "0";
79
104
  const existing = entries.get(key);
80
105
  if (existing) return existing;
106
+ const cached = client.getCachedFlags();
81
107
  const created = {
82
108
  defaultValue,
83
- snapshot: { flags: [], loading: true, error: null },
84
- listeners: /* @__PURE__ */ new Set(),
109
+ snapshot: { flags: cached.flags, loading: !cached.hasData, error: null },
110
+ listeners: /* @__PURE__ */ new Map(),
85
111
  subscribers: /* @__PURE__ */ new Map(),
86
112
  timer: null,
87
113
  inFlight: false
@@ -89,8 +115,12 @@ function createFlagsStore(client, getUser) {
89
115
  entries.set(key, created);
90
116
  return created;
91
117
  };
92
- const emit = (entry) => {
93
- for (const listener of entry.listeners) listener();
118
+ const emit = (entry, changedKeys = null) => {
119
+ for (const { listener, flagKey } of entry.listeners.values()) {
120
+ if (!flagKey || changedKeys === null || changedKeys.has(flagKey)) {
121
+ listener();
122
+ }
123
+ }
94
124
  };
95
125
  const getEffectiveOptions = (entry) => {
96
126
  const active = [...entry.subscribers.values()].filter((s) => s.enabled);
@@ -136,13 +166,17 @@ function createFlagsStore(client, getUser) {
136
166
  if (entry.inFlight) return;
137
167
  entry.inFlight = true;
138
168
  try {
169
+ const previousFlags = entry.snapshot.flags;
139
170
  const flags = await client.flags(getUser(), defaultValue);
171
+ const changed = diffFlagKeys(previousFlags, flags);
140
172
  entry.snapshot = { flags, loading: false, error: null };
141
- emit(entry);
173
+ if (changed.size > 0 || previousFlags.length === 0) {
174
+ emit(entry, changed);
175
+ }
142
176
  } catch (error) {
143
177
  const message = error instanceof Error ? error.message : String(error);
144
178
  entry.snapshot = { ...entry.snapshot, loading: false, error: message };
145
- emit(entry);
179
+ emit(entry, null);
146
180
  } finally {
147
181
  entry.inFlight = false;
148
182
  schedule(entry);
@@ -151,14 +185,14 @@ function createFlagsStore(client, getUser) {
151
185
  const refreshNow = (defaultValue) => {
152
186
  const entry = getEntry(defaultValue);
153
187
  entry.snapshot = { ...entry.snapshot, loading: true, error: null };
154
- emit(entry);
188
+ emit(entry, null);
155
189
  void refresh(defaultValue, true);
156
190
  };
157
- const subscribe = (defaultValue, listener, options) => {
191
+ const subscribe = (defaultValue, listener, options, flagKey) => {
158
192
  const entry = getEntry(defaultValue);
159
193
  const subscriberId = nextSubscriberId;
160
194
  nextSubscriberId += 1;
161
- entry.listeners.add(listener);
195
+ entry.listeners.set(subscriberId, { listener, flagKey });
162
196
  entry.subscribers.set(subscriberId, normalizeSubscriptionOptions(options));
163
197
  const effective = getEffectiveOptions(entry);
164
198
  if (effective.enabled && !entry.inFlight && entry.snapshot.loading) {
@@ -167,7 +201,7 @@ function createFlagsStore(client, getUser) {
167
201
  schedule(entry);
168
202
  }
169
203
  return () => {
170
- entry.listeners.delete(listener);
204
+ entry.listeners.delete(subscriberId);
171
205
  entry.subscribers.delete(subscriberId);
172
206
  schedule(entry);
173
207
  };
@@ -175,7 +209,7 @@ function createFlagsStore(client, getUser) {
175
209
  const updateUser = () => {
176
210
  for (const entry of entries.values()) {
177
211
  entry.snapshot = { ...entry.snapshot, loading: true, error: null };
178
- emit(entry);
212
+ emit(entry, null);
179
213
  void refresh(entry.defaultValue);
180
214
  }
181
215
  };
@@ -187,10 +221,28 @@ function createFlagsStore(client, getUser) {
187
221
  void refresh(entry.defaultValue);
188
222
  }
189
223
  };
224
+ const unsubscribeClientUpdate = typeof client.on === "function" ? client.on(
225
+ "update",
226
+ ({ changedKeys }) => {
227
+ const changedSet = new Set(changedKeys);
228
+ for (const entry of entries.values()) {
229
+ const previous = entry.snapshot.flags;
230
+ const next = client.getCachedFlags().flags;
231
+ const diff = diffFlagKeys(previous, next);
232
+ if (diff.size === 0) continue;
233
+ const intersects = [...diff].some((key) => changedSet.has(key));
234
+ if (!intersects && changedSet.size > 0) continue;
235
+ entry.snapshot = { ...entry.snapshot, flags: next, loading: false, error: null };
236
+ emit(entry, diff);
237
+ }
238
+ }
239
+ ) : () => {
240
+ };
190
241
  if (typeof document !== "undefined") {
191
242
  document.addEventListener("visibilitychange", handleVisibilityChange);
192
243
  }
193
244
  const dispose = () => {
245
+ unsubscribeClientUpdate();
194
246
  if (typeof document !== "undefined") {
195
247
  document.removeEventListener("visibilitychange", handleVisibilityChange);
196
248
  }
@@ -209,7 +261,12 @@ function createFlagsStore(client, getUser) {
209
261
  return getEntry(defaultValue).snapshot;
210
262
  },
211
263
  refreshNow,
212
- subscribe,
264
+ subscribeAll(defaultValue, listener, options) {
265
+ return subscribe(defaultValue, listener, options);
266
+ },
267
+ subscribeFlag(flagKey, defaultValue, listener, options) {
268
+ return subscribe(defaultValue, listener, options, flagKey);
269
+ },
213
270
  updateUser,
214
271
  dispose
215
272
  };
@@ -228,13 +285,33 @@ function FeatureFlareProvider(props) {
228
285
  apiBaseUrl: props.config.apiBaseUrl,
229
286
  sdkKey: props.config.sdkKey,
230
287
  projectKey: props.config.projectKey,
231
- envKey: props.config.envKey
288
+ envKey: props.config.envKey,
289
+ timeoutMs: props.config.timeoutMs,
290
+ maxRetries: props.config.maxRetries,
291
+ backoffMs: props.config.backoffMs,
292
+ jitter: props.config.jitter,
293
+ cacheTtlMs: props.config.cacheTtlMs,
294
+ staleTtlMs: props.config.staleTtlMs,
295
+ bootstrap: props.config.bootstrap,
296
+ persistentCache: props.config.persistentCache,
297
+ onMetric: props.config.onMetric,
298
+ realtime: props.config.realtime
232
299
  });
233
300
  }, [
234
301
  props.config.apiBaseUrl,
302
+ props.config.backoffMs,
303
+ props.config.bootstrap,
304
+ props.config.cacheTtlMs,
235
305
  props.config.envKey,
306
+ props.config.jitter,
307
+ props.config.maxRetries,
308
+ props.config.onMetric,
309
+ props.config.persistentCache,
236
310
  props.config.projectKey,
237
- props.config.sdkKey
311
+ props.config.realtime,
312
+ props.config.sdkKey,
313
+ props.config.staleTtlMs,
314
+ props.config.timeoutMs
238
315
  ]);
239
316
  const flagsStore = (0, import_react.useMemo)(() => createFlagsStore(client, () => userRef.current), [client]);
240
317
  (0, import_react.useEffect)(() => {
@@ -244,8 +321,9 @@ function FeatureFlareProvider(props) {
244
321
  (0, import_react.useEffect)(() => {
245
322
  return () => {
246
323
  flagsStore.dispose();
324
+ client.dispose();
247
325
  };
248
- }, [flagsStore]);
326
+ }, [client, flagsStore]);
249
327
  const value = (0, import_react.useMemo)(
250
328
  () => ({
251
329
  client,
@@ -253,7 +331,9 @@ function FeatureFlareProvider(props) {
253
331
  setUser,
254
332
  getFlagsState: flagsStore.getState,
255
333
  refreshFlags: flagsStore.refreshNow,
256
- subscribeFlags: flagsStore.subscribe
334
+ subscribeFlags: flagsStore.subscribeAll,
335
+ subscribeFlag: (flagKey, defaultValue, listener, options) => flagsStore.subscribeFlag(flagKey, defaultValue, listener, options),
336
+ getFlagDiagnostics: (flagKey) => client.getFlagDiagnostics(flagKey)
257
337
  }),
258
338
  [client, flagsStore, setUser, user]
259
339
  );
@@ -277,83 +357,75 @@ function userFingerprint(user) {
277
357
  meta: user.meta ?? {}
278
358
  });
279
359
  }
360
+ function mapFlags(flags) {
361
+ const values = {};
362
+ for (const flag of flags) {
363
+ values[flag.key] = flag.value;
364
+ }
365
+ return values;
366
+ }
280
367
  function useFeatureFlareUser() {
281
368
  const { user, setUser } = useFeatureFlareContext();
282
369
  return [user, setUser];
283
370
  }
284
- function useBoolFlag(flagKey, defaultValue = false) {
285
- const { client, user } = useFeatureFlareContext();
286
- const [state, setState] = (0, import_react2.useState)({ value: defaultValue, loading: true, error: null });
287
- const userId = user.id ?? user.key ?? "";
288
- const key = (0, import_react2.useMemo)(() => `${flagKey}:${userId}`, [flagKey, userId]);
289
- const lastKey = (0, import_react2.useRef)("");
371
+ function useFlag(flagKey, defaultValue = false) {
372
+ const { subscribeFlag, getFlagsState, refreshFlags } = useFeatureFlareContext();
290
373
  (0, import_react2.useEffect)(() => {
291
- let cancelled = false;
292
- const nextKey = key;
293
- lastKey.current = nextKey;
294
- setState((s) => ({ ...s, loading: true, error: null }));
295
- (async () => {
296
- try {
297
- const v = await client.bool(flagKey, user, defaultValue);
298
- if (cancelled) return;
299
- if (lastKey.current !== nextKey) return;
300
- setState({ value: v, loading: false, error: null });
301
- } catch (e) {
302
- if (cancelled) return;
303
- if (lastKey.current !== nextKey) return;
304
- const msg = e instanceof Error ? e.message : String(e);
305
- setState({ value: defaultValue, loading: false, error: msg });
306
- }
307
- })();
308
- return () => {
309
- cancelled = true;
310
- };
311
- }, [client, defaultValue, flagKey, key, user]);
312
- return state;
374
+ refreshFlags(defaultValue);
375
+ }, [defaultValue, refreshFlags]);
376
+ const subscribe = (0, import_react2.useMemo)(
377
+ () => (onStoreChange) => subscribeFlag(flagKey, defaultValue, onStoreChange),
378
+ [defaultValue, flagKey, subscribeFlag]
379
+ );
380
+ const state = (0, import_react2.useSyncExternalStore)(subscribe, () => getFlagsState(defaultValue), () => EMPTY_FLAGS_STATE);
381
+ const value = state.flags.find((entry) => entry.key === flagKey)?.value ?? defaultValue;
382
+ return {
383
+ value,
384
+ loading: state.loading,
385
+ error: state.error
386
+ };
313
387
  }
314
- function useBoolFlags(flagKeys, defaultValue = false) {
315
- const { client, user } = useFeatureFlareContext();
316
- const sortedKeys = (0, import_react2.useMemo)(() => [...flagKeys].map((k) => k.trim()).filter(Boolean).sort(), [flagKeys]);
317
- const userId = user.id ?? user.key ?? "";
318
- const key = (0, import_react2.useMemo)(() => `${sortedKeys.join(",")}:${userId}`, [sortedKeys, userId]);
319
- const [state, setState] = (0, import_react2.useState)({ values: {}, loading: true, errors: {} });
320
- const lastKey = (0, import_react2.useRef)("");
321
- (0, import_react2.useEffect)(() => {
322
- let cancelled = false;
323
- const nextKey = key;
324
- lastKey.current = nextKey;
325
- setState({ values: {}, loading: true, errors: {} });
326
- (async () => {
327
- const values = {};
328
- const errors = {};
329
- await Promise.all(
330
- sortedKeys.map(async (flagKey) => {
331
- try {
332
- values[flagKey] = await client.bool(flagKey, user, defaultValue);
333
- } catch (e) {
334
- values[flagKey] = defaultValue;
335
- errors[flagKey] = e instanceof Error ? e.message : String(e);
336
- }
337
- })
338
- );
339
- if (cancelled) return;
340
- if (lastKey.current !== nextKey) return;
341
- setState({ values, loading: false, errors });
342
- })();
343
- return () => {
344
- cancelled = true;
345
- };
346
- }, [client, defaultValue, key, sortedKeys, user]);
347
- return state;
388
+ function useBoolFlag(flagKey, defaultValue = false) {
389
+ return useFlag(flagKey, defaultValue);
348
390
  }
349
- function useFlags(defaultValueOrInput = false, options = {}) {
350
- const { subscribeFlags, getFlagsState, refreshFlags, setUser } = useFeatureFlareContext();
391
+ function useFlags(defaultValueOrInputOrKeys = false, optionsOrDefaultValue = {}) {
392
+ const { subscribeFlags, subscribeFlag, getFlagsState, refreshFlags, setUser } = useFeatureFlareContext();
393
+ if (Array.isArray(defaultValueOrInputOrKeys)) {
394
+ const keys = [...defaultValueOrInputOrKeys].map((key) => key.trim()).filter(Boolean);
395
+ const defaultValue2 = typeof optionsOrDefaultValue === "boolean" ? optionsOrDefaultValue : false;
396
+ (0, import_react2.useEffect)(() => {
397
+ refreshFlags(defaultValue2);
398
+ }, [defaultValue2, refreshFlags]);
399
+ const subscribe2 = (0, import_react2.useMemo)(
400
+ () => (onStoreChange) => {
401
+ const unsubs = keys.map((key) => subscribeFlag(key, defaultValue2, onStoreChange));
402
+ return () => {
403
+ for (const unsub of unsubs) unsub();
404
+ };
405
+ },
406
+ [defaultValue2, keys, subscribeFlag]
407
+ );
408
+ const state = (0, import_react2.useSyncExternalStore)(subscribe2, () => getFlagsState(defaultValue2), () => EMPTY_FLAGS_STATE);
409
+ const values = mapFlags(state.flags);
410
+ const filtered = {};
411
+ for (const key of keys) {
412
+ filtered[key] = values[key] ?? defaultValue2;
413
+ }
414
+ return {
415
+ values: filtered,
416
+ loading: state.loading,
417
+ errors: state.error ? { __global: state.error } : {}
418
+ };
419
+ }
351
420
  const parsed = (0, import_react2.useMemo)(() => {
352
- if (typeof defaultValueOrInput === "boolean") {
353
- return { ...options, defaultValue: defaultValueOrInput };
421
+ if (typeof defaultValueOrInputOrKeys === "boolean") {
422
+ return {
423
+ ...typeof optionsOrDefaultValue === "object" && optionsOrDefaultValue !== null ? optionsOrDefaultValue : {},
424
+ defaultValue: defaultValueOrInputOrKeys
425
+ };
354
426
  }
355
- return defaultValueOrInput ?? {};
356
- }, [defaultValueOrInput, options]);
427
+ return defaultValueOrInputOrKeys ?? {};
428
+ }, [defaultValueOrInputOrKeys, optionsOrDefaultValue]);
357
429
  const defaultValue = parsed.defaultValue ?? false;
358
430
  const normalizedOptions = (0, import_react2.useMemo)(
359
431
  () => ({
@@ -382,6 +454,30 @@ function useFlags(defaultValueOrInput = false, options = {}) {
382
454
  );
383
455
  return (0, import_react2.useSyncExternalStore)(subscribe, () => getFlagsState(defaultValue), () => EMPTY_FLAGS_STATE);
384
456
  }
457
+ function useBoolFlags(flagKeys, defaultValue = false) {
458
+ return useFlags(flagKeys, defaultValue);
459
+ }
460
+ function useFlagDiagnostics(flagKey, defaultValue = false) {
461
+ const { getFlagDiagnostics, subscribeFlag } = useFeatureFlareContext();
462
+ const subscribe = (0, import_react2.useMemo)(
463
+ () => (onStoreChange) => subscribeFlag(flagKey, defaultValue, onStoreChange),
464
+ [defaultValue, flagKey, subscribeFlag]
465
+ );
466
+ const metadata = (0, import_react2.useSyncExternalStore)(
467
+ subscribe,
468
+ () => getFlagDiagnostics(flagKey),
469
+ () => null
470
+ );
471
+ return {
472
+ source: metadata?.source ?? "unknown",
473
+ reason: metadata?.reason ?? "unknown",
474
+ isStale: metadata?.isStale ?? false,
475
+ updatedAt: metadata?.updatedAt,
476
+ staleAt: metadata?.staleAt,
477
+ expiresAt: metadata?.expiresAt,
478
+ latencyMs: metadata?.latencyMs
479
+ };
480
+ }
385
481
  // Annotate the CommonJS export names for ESM import in node:
386
482
  0 && (module.exports = {
387
483
  FeatureFlareProvider,
@@ -390,6 +486,8 @@ function useFlags(defaultValueOrInput = false, options = {}) {
390
486
  useBoolFlags,
391
487
  useFeatureFlareContext,
392
488
  useFeatureFlareUser,
489
+ useFlag,
490
+ useFlagDiagnostics,
393
491
  useFlags
394
492
  });
395
493
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/hooks.ts"],"sourcesContent":["export * from './provider.js';\nexport * from './hooks.js';\nexport type { FeatureFlareUserPayload } from '@featureflare/sdk-js';\n","import React, { createContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { FeatureFlareClient, type FeatureFlareUserPayload } from '@featureflare/sdk-js';\n\nexport type FeatureFlareEnvironmentKey = 'development' | 'staging' | 'production';\n\nexport type FeatureFlareReactConfig = {\n /** Optional: explicit FeatureFlare API base URL. */\n apiBaseUrl?: string;\n /** Recommended: use a client key (featureflare_cli_...). */\n sdkKey?: string;\n /** Legacy/insecure browser mode: uses /api/v1/eval (no sdkKey). */\n projectKey?: string;\n envKey?: FeatureFlareEnvironmentKey | string;\n};\n\nexport function resolveFeatureFlareBrowserConfig(input?: {\n envKey?: FeatureFlareEnvironmentKey;\n apiBaseUrl?: string;\n}): FeatureFlareReactConfig {\n const explicitEnv = input?.envKey;\n const envFromVars =\n typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_ENV_KEY?.trim().toLowerCase() : '';\n\n const resolvedEnv: FeatureFlareEnvironmentKey | undefined =\n explicitEnv ??\n (envFromVars === 'development' || envFromVars === 'staging' || envFromVars === 'production'\n ? envFromVars\n : undefined);\n\n const apiBaseUrl =\n input?.apiBaseUrl ??\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_API_BASE_URL?.trim() : undefined);\n\n const sdkKeyDevelopment =\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_DEVELOPMENT?.trim() : '') ||\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_DEV?.trim() : '') ||\n '';\n const sdkKeyStaging =\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_STAGING?.trim() : '') || '';\n const sdkKeyProduction =\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_PRODUCTION?.trim() : '') ||\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_PROD?.trim() : '') ||\n '';\n const sdkKeyDefault =\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY?.trim() : '') || '';\n\n const sdkKey =\n (resolvedEnv === 'development' ? sdkKeyDevelopment : '') ||\n (resolvedEnv === 'staging' ? sdkKeyStaging : '') ||\n (resolvedEnv === 'production' ? sdkKeyProduction : '') ||\n sdkKeyDefault ||\n undefined;\n\n return {\n apiBaseUrl,\n envKey: resolvedEnv,\n sdkKey\n };\n}\n\ntype FeatureFlareContextValue = {\n client: FeatureFlareClient;\n user: FeatureFlareUserPayload;\n setUser: (next: FeatureFlareUserPayload) => void;\n getFlagsState: (defaultValue: boolean) => FlagsState;\n refreshFlags: (defaultValue: boolean) => void;\n subscribeFlags: (\n defaultValue: boolean,\n listener: () => void,\n options?: FlagsSubscriptionOptions\n ) => () => void;\n};\n\nexport type FlagsState = {\n flags: Array<{ key: string; value: boolean }>;\n loading: boolean;\n error: string | null;\n};\n\nexport type FlagsSubscriptionOptions = {\n refreshIntervalMs?: number;\n hiddenRefreshIntervalMs?: number;\n pauseWhenHidden?: boolean;\n enabled?: boolean;\n};\n\ntype NormalizedFlagsSubscriptionOptions = {\n refreshIntervalMs: number;\n hiddenRefreshIntervalMs: number;\n pauseWhenHidden: boolean;\n enabled: boolean;\n};\n\ntype FlagsStoreEntry = {\n defaultValue: boolean;\n snapshot: FlagsState;\n listeners: Set<() => void>;\n subscribers: Map<number, NormalizedFlagsSubscriptionOptions>;\n timer: ReturnType<typeof setTimeout> | null;\n inFlight: boolean;\n};\n\nfunction normalizeSubscriptionOptions(options?: FlagsSubscriptionOptions): NormalizedFlagsSubscriptionOptions {\n const refreshIntervalMs =\n Number.isFinite(options?.refreshIntervalMs) && (options?.refreshIntervalMs ?? 0) > 0\n ? Number(options?.refreshIntervalMs)\n : 10000;\n const hiddenRefreshIntervalMs =\n Number.isFinite(options?.hiddenRefreshIntervalMs) && (options?.hiddenRefreshIntervalMs ?? 0) > 0\n ? Number(options?.hiddenRefreshIntervalMs)\n : Math.max(refreshIntervalMs * 6, 60000);\n\n return {\n refreshIntervalMs,\n hiddenRefreshIntervalMs,\n pauseWhenHidden: options?.pauseWhenHidden ?? true,\n enabled: options?.enabled ?? true\n };\n}\n\nfunction createFlagsStore(client: FeatureFlareClient, getUser: () => FeatureFlareUserPayload) {\n const entries = new Map<string, FlagsStoreEntry>();\n let nextSubscriberId = 1;\n\n const isHidden = () => typeof document !== 'undefined' && document.visibilityState === 'hidden';\n\n const getEntry = (defaultValue: boolean): FlagsStoreEntry => {\n const key = defaultValue ? '1' : '0';\n const existing = entries.get(key);\n if (existing) return existing;\n const created: FlagsStoreEntry = {\n defaultValue,\n snapshot: { flags: [], loading: true, error: null },\n listeners: new Set(),\n subscribers: new Map(),\n timer: null,\n inFlight: false\n };\n entries.set(key, created);\n return created;\n };\n\n const emit = (entry: FlagsStoreEntry) => {\n for (const listener of entry.listeners) listener();\n };\n\n const getEffectiveOptions = (entry: FlagsStoreEntry) => {\n const active = [...entry.subscribers.values()].filter((s) => s.enabled);\n if (active.length === 0) {\n return { enabled: false as const, refreshIntervalMs: 0, hiddenRefreshIntervalMs: 0, pauseWhenHidden: true };\n }\n\n const refreshIntervalMs = active.reduce((min, s) => Math.min(min, s.refreshIntervalMs), Number.POSITIVE_INFINITY);\n const hiddenActive = active.filter((s) => !s.pauseWhenHidden);\n const hiddenRefreshIntervalMs =\n hiddenActive.length > 0\n ? hiddenActive.reduce((min, s) => Math.min(min, s.hiddenRefreshIntervalMs), Number.POSITIVE_INFINITY)\n : 0;\n\n return {\n enabled: true as const,\n refreshIntervalMs: Number.isFinite(refreshIntervalMs) ? refreshIntervalMs : 10000,\n hiddenRefreshIntervalMs,\n pauseWhenHidden: hiddenActive.length === 0\n };\n };\n\n const schedule = (entry: FlagsStoreEntry) => {\n if (entry.timer !== null) {\n clearTimeout(entry.timer);\n entry.timer = null;\n }\n\n const effective = getEffectiveOptions(entry);\n if (!effective.enabled) return;\n\n if (isHidden()) {\n if (effective.pauseWhenHidden) return;\n entry.timer = setTimeout(() => {\n void refresh(entry.defaultValue);\n }, effective.hiddenRefreshIntervalMs);\n return;\n }\n\n entry.timer = setTimeout(() => {\n void refresh(entry.defaultValue);\n }, effective.refreshIntervalMs);\n };\n\n const refresh = async (defaultValue: boolean, force = false) => {\n const entry = getEntry(defaultValue);\n const effective = getEffectiveOptions(entry);\n if (!effective.enabled && !force) return;\n\n if (!force && isHidden() && effective.pauseWhenHidden) {\n schedule(entry);\n return;\n }\n\n if (entry.inFlight) return;\n entry.inFlight = true;\n\n try {\n const flags = await client.flags(getUser(), defaultValue);\n entry.snapshot = { flags, loading: false, error: null };\n emit(entry);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n entry.snapshot = { ...entry.snapshot, loading: false, error: message };\n emit(entry);\n } finally {\n entry.inFlight = false;\n schedule(entry);\n }\n };\n\n const refreshNow = (defaultValue: boolean) => {\n const entry = getEntry(defaultValue);\n entry.snapshot = { ...entry.snapshot, loading: true, error: null };\n emit(entry);\n void refresh(defaultValue, true);\n };\n\n const subscribe = (\n defaultValue: boolean,\n listener: () => void,\n options?: FlagsSubscriptionOptions\n ): (() => void) => {\n const entry = getEntry(defaultValue);\n const subscriberId = nextSubscriberId;\n nextSubscriberId += 1;\n\n entry.listeners.add(listener);\n entry.subscribers.set(subscriberId, normalizeSubscriptionOptions(options));\n\n const effective = getEffectiveOptions(entry);\n if (effective.enabled && !entry.inFlight && entry.snapshot.loading) {\n void refresh(defaultValue);\n } else {\n schedule(entry);\n }\n\n return () => {\n entry.listeners.delete(listener);\n entry.subscribers.delete(subscriberId);\n schedule(entry);\n };\n };\n\n const updateUser = () => {\n for (const entry of entries.values()) {\n entry.snapshot = { ...entry.snapshot, loading: true, error: null };\n emit(entry);\n void refresh(entry.defaultValue);\n }\n };\n\n const handleVisibilityChange = () => {\n if (isHidden()) return;\n for (const entry of entries.values()) {\n const effective = getEffectiveOptions(entry);\n if (!effective.enabled) continue;\n void refresh(entry.defaultValue);\n }\n };\n\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', handleVisibilityChange);\n }\n\n const dispose = () => {\n if (typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n }\n for (const entry of entries.values()) {\n if (entry.timer !== null) {\n clearTimeout(entry.timer);\n }\n entry.timer = null;\n entry.listeners.clear();\n entry.subscribers.clear();\n }\n entries.clear();\n };\n\n return {\n getState(defaultValue: boolean): FlagsState {\n return getEntry(defaultValue).snapshot;\n },\n refreshNow,\n subscribe,\n updateUser,\n dispose\n };\n}\n\nconst FeatureFlareContext = createContext<FeatureFlareContextValue | null>(null);\n\nexport function FeatureFlareProvider(props: {\n config: FeatureFlareReactConfig;\n initialUser: FeatureFlareUserPayload;\n user?: FeatureFlareUserPayload;\n onUserChange?: (next: FeatureFlareUserPayload) => void;\n children: React.ReactNode;\n}) {\n if (props.user && !props.onUserChange) {\n throw new Error('FeatureFlareProvider: when providing `user`, also provide `onUserChange` (controlled mode).');\n }\n\n const [internalUser, setInternalUser] = useState<FeatureFlareUserPayload>(props.initialUser);\n const user = props.user ?? internalUser;\n const setUser = props.onUserChange ?? setInternalUser;\n const userRef = useRef<FeatureFlareUserPayload>(user);\n\n const client = useMemo(() => {\n return new FeatureFlareClient({\n apiBaseUrl: props.config.apiBaseUrl,\n sdkKey: props.config.sdkKey,\n projectKey: props.config.projectKey,\n envKey: props.config.envKey\n });\n }, [\n props.config.apiBaseUrl,\n props.config.envKey,\n props.config.projectKey,\n props.config.sdkKey\n ]);\n\n const flagsStore = useMemo(() => createFlagsStore(client, () => userRef.current), [client]);\n\n useEffect(() => {\n userRef.current = user;\n flagsStore.updateUser();\n }, [flagsStore, user]);\n\n useEffect(() => {\n return () => {\n flagsStore.dispose();\n };\n }, [flagsStore]);\n\n const value = useMemo(\n () => ({\n client,\n user,\n setUser,\n getFlagsState: flagsStore.getState,\n refreshFlags: flagsStore.refreshNow,\n subscribeFlags: flagsStore.subscribe\n }),\n [client, flagsStore, setUser, user]\n );\n return <FeatureFlareContext.Provider value={value}>{props.children}</FeatureFlareContext.Provider>;\n}\n\nexport function useFeatureFlareContext(): FeatureFlareContextValue {\n const ctx = React.useContext(FeatureFlareContext);\n if (!ctx) throw new Error('useFeatureFlareContext must be used within <FeatureFlareProvider>.');\n return ctx;\n}\n","import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport type { FeatureFlareUserPayload } from '@featureflare/sdk-js';\nimport { useFeatureFlareContext, type FlagsSubscriptionOptions } from './provider.js';\n\ntype BoolFlagState = {\n value: boolean;\n loading: boolean;\n error: string | null;\n};\n\ntype BoolFlagsState = {\n values: Record<string, boolean>;\n loading: boolean;\n errors: Record<string, string>;\n};\n\ntype FlagsState = {\n flags: Array<{ key: string; value: boolean }>;\n loading: boolean;\n error: string | null;\n};\n\ntype UseFlagsOptions = FlagsSubscriptionOptions;\n\ntype UseFlagsInput = UseFlagsOptions & {\n defaultValue?: boolean;\n user?: FeatureFlareUserPayload;\n};\n\nconst EMPTY_FLAGS_STATE: FlagsState = { flags: [], loading: true, error: null };\n\nfunction userFingerprint(user?: FeatureFlareUserPayload): string {\n if (!user) return '';\n return JSON.stringify({\n id: user.id ?? '',\n key: user.key ?? '',\n email: user.email ?? '',\n meta: user.meta ?? {}\n });\n}\n\nexport function useFeatureFlareUser(): [FeatureFlareUserPayload, (next: FeatureFlareUserPayload) => void] {\n const { user, setUser } = useFeatureFlareContext();\n return [user, setUser];\n}\n\nexport function useBoolFlag(flagKey: string, defaultValue = false): BoolFlagState {\n const { client, user } = useFeatureFlareContext();\n const [state, setState] = useState<BoolFlagState>({ value: defaultValue, loading: true, error: null });\n const userId = user.id ?? user.key ?? '';\n const key = useMemo(() => `${flagKey}:${userId}`, [flagKey, userId]);\n const lastKey = useRef<string>('');\n\n useEffect(() => {\n let cancelled = false;\n const nextKey = key;\n lastKey.current = nextKey;\n setState((s) => ({ ...s, loading: true, error: null }));\n\n (async () => {\n try {\n const v = await client.bool(flagKey, user, defaultValue);\n if (cancelled) return;\n if (lastKey.current !== nextKey) return;\n setState({ value: v, loading: false, error: null });\n } catch (e) {\n if (cancelled) return;\n if (lastKey.current !== nextKey) return;\n const msg = e instanceof Error ? e.message : String(e);\n setState({ value: defaultValue, loading: false, error: msg });\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [client, defaultValue, flagKey, key, user]);\n\n return state;\n}\n\nexport function useBoolFlags(flagKeys: string[], defaultValue = false): BoolFlagsState {\n const { client, user } = useFeatureFlareContext();\n const sortedKeys = useMemo(() => [...flagKeys].map((k) => k.trim()).filter(Boolean).sort(), [flagKeys]);\n const userId = user.id ?? user.key ?? '';\n const key = useMemo(() => `${sortedKeys.join(',')}:${userId}`, [sortedKeys, userId]);\n const [state, setState] = useState<BoolFlagsState>({ values: {}, loading: true, errors: {} });\n const lastKey = useRef<string>('');\n\n useEffect(() => {\n let cancelled = false;\n const nextKey = key;\n lastKey.current = nextKey;\n setState({ values: {}, loading: true, errors: {} });\n\n (async () => {\n const values: Record<string, boolean> = {};\n const errors: Record<string, string> = {};\n await Promise.all(\n sortedKeys.map(async (flagKey) => {\n try {\n values[flagKey] = await client.bool(flagKey, user, defaultValue);\n } catch (e) {\n values[flagKey] = defaultValue;\n errors[flagKey] = e instanceof Error ? e.message : String(e);\n }\n })\n );\n\n if (cancelled) return;\n if (lastKey.current !== nextKey) return;\n setState({ values, loading: false, errors });\n })();\n\n return () => {\n cancelled = true;\n };\n }, [client, defaultValue, key, sortedKeys, user]);\n\n return state;\n}\n\nexport function useFlags(input?: UseFlagsInput): FlagsState;\nexport function useFlags(defaultValue?: boolean, options?: UseFlagsOptions): FlagsState;\nexport function useFlags(defaultValueOrInput: boolean | UseFlagsInput = false, options: UseFlagsOptions = {}): FlagsState {\n const { subscribeFlags, getFlagsState, refreshFlags, setUser } = useFeatureFlareContext();\n\n const parsed = useMemo<UseFlagsInput>(() => {\n if (typeof defaultValueOrInput === 'boolean') {\n return { ...options, defaultValue: defaultValueOrInput };\n }\n return defaultValueOrInput ?? {};\n }, [defaultValueOrInput, options]);\n\n const defaultValue = parsed.defaultValue ?? false;\n\n const normalizedOptions = useMemo<UseFlagsOptions>(\n () => ({\n enabled: parsed.enabled ?? true,\n refreshIntervalMs: parsed.refreshIntervalMs,\n hiddenRefreshIntervalMs: parsed.hiddenRefreshIntervalMs,\n pauseWhenHidden: parsed.pauseWhenHidden ?? true\n }),\n [parsed.enabled, parsed.hiddenRefreshIntervalMs, parsed.pauseWhenHidden, parsed.refreshIntervalMs]\n );\n\n const appliedUserRef = useRef<string>('');\n const parsedUserFingerprint = useMemo(() => userFingerprint(parsed.user), [parsed.user]);\n\n useEffect(() => {\n if (!parsed.user) return;\n if (appliedUserRef.current === parsedUserFingerprint) return;\n setUser(parsed.user);\n appliedUserRef.current = parsedUserFingerprint;\n }, [parsed.user, parsedUserFingerprint, setUser]);\n\n useEffect(() => {\n if (normalizedOptions.enabled === false) return;\n refreshFlags(defaultValue);\n }, [defaultValue, normalizedOptions.enabled, parsedUserFingerprint, refreshFlags]);\n\n const subscribe = useMemo(\n () =>\n (onStoreChange: () => void) =>\n subscribeFlags(defaultValue, onStoreChange, normalizedOptions),\n [defaultValue, normalizedOptions, subscribeFlags]\n );\n\n return useSyncExternalStore(subscribe, () => getFlagsState(defaultValue), () => EMPTY_FLAGS_STATE);\n}\n"],"mappings":"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","names":["React","import_react"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/hooks.ts"],"sourcesContent":["export * from './provider.js';\nexport * from './hooks.js';\nexport type { FeatureFlareUserPayload } from '@featureflare/sdk-js';\n","import React, { createContext, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n FeatureFlareClient,\n type FeatureFlareBootstrapPayload,\n type FeatureFlareEvaluationMetadata,\n type FeatureFlareMetricName,\n type FeatureFlareMetricTags,\n type FeatureFlarePersistentCacheAdapter,\n type FeatureFlareUserPayload\n} from '@featureflare/sdk-js';\n\nexport type FeatureFlareEnvironmentKey = 'development' | 'staging' | 'production';\n\nexport type FeatureFlareReactConfig = {\n /** Optional: explicit FeatureFlare API base URL. */\n apiBaseUrl?: string;\n /** Recommended: use a client key (featureflare_cli_...). */\n sdkKey?: string;\n /** Legacy/insecure browser mode: uses /api/v1/eval (no sdkKey). */\n projectKey?: string;\n envKey?: FeatureFlareEnvironmentKey | string;\n timeoutMs?: number;\n maxRetries?: number;\n backoffMs?: number;\n jitter?: number;\n cacheTtlMs?: number;\n staleTtlMs?: number;\n bootstrap?: FeatureFlareBootstrapPayload;\n persistentCache?: FeatureFlarePersistentCacheAdapter;\n onMetric?: (metricName: FeatureFlareMetricName, value: number, tags?: FeatureFlareMetricTags) => void;\n realtime?: {\n enabled?: boolean;\n pollingIntervalMs?: number;\n ssePath?: string;\n };\n};\n\nexport function resolveFeatureFlareBrowserConfig(input?: {\n envKey?: FeatureFlareEnvironmentKey;\n apiBaseUrl?: string;\n}): FeatureFlareReactConfig {\n const explicitEnv = input?.envKey;\n const envFromVars =\n typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_ENV_KEY?.trim().toLowerCase() : '';\n\n const resolvedEnv: FeatureFlareEnvironmentKey | undefined =\n explicitEnv ??\n (envFromVars === 'development' || envFromVars === 'staging' || envFromVars === 'production'\n ? envFromVars\n : undefined);\n\n const apiBaseUrl =\n input?.apiBaseUrl ??\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_API_BASE_URL?.trim() : undefined);\n\n const sdkKeyDevelopment =\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_DEVELOPMENT?.trim() : '') ||\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_DEV?.trim() : '') ||\n '';\n const sdkKeyStaging =\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_STAGING?.trim() : '') || '';\n const sdkKeyProduction =\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_PRODUCTION?.trim() : '') ||\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_PROD?.trim() : '') ||\n '';\n const sdkKeyDefault =\n (typeof process !== 'undefined' ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY?.trim() : '') || '';\n\n const sdkKey =\n (resolvedEnv === 'development' ? sdkKeyDevelopment : '') ||\n (resolvedEnv === 'staging' ? sdkKeyStaging : '') ||\n (resolvedEnv === 'production' ? sdkKeyProduction : '') ||\n sdkKeyDefault ||\n undefined;\n\n return {\n apiBaseUrl,\n envKey: resolvedEnv,\n sdkKey\n };\n}\n\ntype FeatureFlareContextValue = {\n client: FeatureFlareClient;\n user: FeatureFlareUserPayload;\n setUser: (next: FeatureFlareUserPayload) => void;\n getFlagsState: (defaultValue: boolean) => FlagsState;\n refreshFlags: (defaultValue: boolean) => void;\n subscribeFlags: (\n defaultValue: boolean,\n listener: () => void,\n options?: FlagsSubscriptionOptions\n ) => () => void;\n subscribeFlag: (\n flagKey: string,\n defaultValue: boolean,\n listener: () => void,\n options?: FlagsSubscriptionOptions\n ) => () => void;\n getFlagDiagnostics: (flagKey: string) => FeatureFlareEvaluationMetadata | null;\n};\n\nexport type FlagsState = {\n flags: Array<{ key: string; value: boolean }>;\n loading: boolean;\n error: string | null;\n};\n\nexport type FlagsSubscriptionOptions = {\n refreshIntervalMs?: number;\n hiddenRefreshIntervalMs?: number;\n pauseWhenHidden?: boolean;\n enabled?: boolean;\n};\n\ntype NormalizedFlagsSubscriptionOptions = {\n refreshIntervalMs: number;\n hiddenRefreshIntervalMs: number;\n pauseWhenHidden: boolean;\n enabled: boolean;\n};\n\ntype ListenerEntry = {\n listener: () => void;\n flagKey?: string;\n};\n\ntype FlagsStoreEntry = {\n defaultValue: boolean;\n snapshot: FlagsState;\n listeners: Map<number, ListenerEntry>;\n subscribers: Map<number, NormalizedFlagsSubscriptionOptions>;\n timer: ReturnType<typeof setTimeout> | null;\n inFlight: boolean;\n};\n\nfunction normalizeSubscriptionOptions(options?: FlagsSubscriptionOptions): NormalizedFlagsSubscriptionOptions {\n const refreshIntervalMs =\n Number.isFinite(options?.refreshIntervalMs) && (options?.refreshIntervalMs ?? 0) > 0\n ? Number(options?.refreshIntervalMs)\n : 10000;\n const hiddenRefreshIntervalMs =\n Number.isFinite(options?.hiddenRefreshIntervalMs) && (options?.hiddenRefreshIntervalMs ?? 0) > 0\n ? Number(options?.hiddenRefreshIntervalMs)\n : Math.max(refreshIntervalMs * 6, 60000);\n\n return {\n refreshIntervalMs,\n hiddenRefreshIntervalMs,\n pauseWhenHidden: options?.pauseWhenHidden ?? true,\n enabled: options?.enabled ?? true\n };\n}\n\nfunction flagsToMap(flags: Array<{ key: string; value: boolean }>): Map<string, boolean> {\n const map = new Map<string, boolean>();\n for (const flag of flags) {\n map.set(flag.key, flag.value);\n }\n return map;\n}\n\nfunction diffFlagKeys(prev: Array<{ key: string; value: boolean }>, next: Array<{ key: string; value: boolean }>): Set<string> {\n const changed = new Set<string>();\n const prevMap = flagsToMap(prev);\n const nextMap = flagsToMap(next);\n\n for (const [key, value] of prevMap.entries()) {\n if (!nextMap.has(key) || nextMap.get(key) !== value) {\n changed.add(key);\n }\n }\n\n for (const [key, value] of nextMap.entries()) {\n if (!prevMap.has(key) || prevMap.get(key) !== value) {\n changed.add(key);\n }\n }\n\n return changed;\n}\n\nfunction createFlagsStore(client: FeatureFlareClient, getUser: () => FeatureFlareUserPayload) {\n const entries = new Map<string, FlagsStoreEntry>();\n let nextSubscriberId = 1;\n\n const isHidden = () => typeof document !== 'undefined' && document.visibilityState === 'hidden';\n\n const getEntry = (defaultValue: boolean): FlagsStoreEntry => {\n const key = defaultValue ? '1' : '0';\n const existing = entries.get(key);\n if (existing) return existing;\n\n const cached = client.getCachedFlags();\n const created: FlagsStoreEntry = {\n defaultValue,\n snapshot: { flags: cached.flags, loading: !cached.hasData, error: null },\n listeners: new Map(),\n subscribers: new Map(),\n timer: null,\n inFlight: false\n };\n entries.set(key, created);\n return created;\n };\n\n const emit = (entry: FlagsStoreEntry, changedKeys: Set<string> | null = null) => {\n for (const { listener, flagKey } of entry.listeners.values()) {\n if (!flagKey || changedKeys === null || changedKeys.has(flagKey)) {\n listener();\n }\n }\n };\n\n const getEffectiveOptions = (entry: FlagsStoreEntry) => {\n const active = [...entry.subscribers.values()].filter((s) => s.enabled);\n if (active.length === 0) {\n return { enabled: false as const, refreshIntervalMs: 0, hiddenRefreshIntervalMs: 0, pauseWhenHidden: true };\n }\n\n const refreshIntervalMs = active.reduce((min, s) => Math.min(min, s.refreshIntervalMs), Number.POSITIVE_INFINITY);\n const hiddenActive = active.filter((s) => !s.pauseWhenHidden);\n const hiddenRefreshIntervalMs =\n hiddenActive.length > 0\n ? hiddenActive.reduce((min, s) => Math.min(min, s.hiddenRefreshIntervalMs), Number.POSITIVE_INFINITY)\n : 0;\n\n return {\n enabled: true as const,\n refreshIntervalMs: Number.isFinite(refreshIntervalMs) ? refreshIntervalMs : 10000,\n hiddenRefreshIntervalMs,\n pauseWhenHidden: hiddenActive.length === 0\n };\n };\n\n const schedule = (entry: FlagsStoreEntry) => {\n if (entry.timer !== null) {\n clearTimeout(entry.timer);\n entry.timer = null;\n }\n\n const effective = getEffectiveOptions(entry);\n if (!effective.enabled) return;\n\n if (isHidden()) {\n if (effective.pauseWhenHidden) return;\n entry.timer = setTimeout(() => {\n void refresh(entry.defaultValue);\n }, effective.hiddenRefreshIntervalMs);\n return;\n }\n\n entry.timer = setTimeout(() => {\n void refresh(entry.defaultValue);\n }, effective.refreshIntervalMs);\n };\n\n const refresh = async (defaultValue: boolean, force = false) => {\n const entry = getEntry(defaultValue);\n const effective = getEffectiveOptions(entry);\n if (!effective.enabled && !force) return;\n\n if (!force && isHidden() && effective.pauseWhenHidden) {\n schedule(entry);\n return;\n }\n\n if (entry.inFlight) return;\n entry.inFlight = true;\n\n try {\n const previousFlags = entry.snapshot.flags;\n const flags = await client.flags(getUser(), defaultValue);\n const changed = diffFlagKeys(previousFlags, flags);\n entry.snapshot = { flags, loading: false, error: null };\n if (changed.size > 0 || previousFlags.length === 0) {\n emit(entry, changed);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n entry.snapshot = { ...entry.snapshot, loading: false, error: message };\n emit(entry, null);\n } finally {\n entry.inFlight = false;\n schedule(entry);\n }\n };\n\n const refreshNow = (defaultValue: boolean) => {\n const entry = getEntry(defaultValue);\n entry.snapshot = { ...entry.snapshot, loading: true, error: null };\n emit(entry, null);\n void refresh(defaultValue, true);\n };\n\n const subscribe = (\n defaultValue: boolean,\n listener: () => void,\n options?: FlagsSubscriptionOptions,\n flagKey?: string\n ): (() => void) => {\n const entry = getEntry(defaultValue);\n const subscriberId = nextSubscriberId;\n nextSubscriberId += 1;\n\n entry.listeners.set(subscriberId, { listener, flagKey });\n entry.subscribers.set(subscriberId, normalizeSubscriptionOptions(options));\n\n const effective = getEffectiveOptions(entry);\n if (effective.enabled && !entry.inFlight && entry.snapshot.loading) {\n void refresh(defaultValue);\n } else {\n schedule(entry);\n }\n\n return () => {\n entry.listeners.delete(subscriberId);\n entry.subscribers.delete(subscriberId);\n schedule(entry);\n };\n };\n\n const updateUser = () => {\n for (const entry of entries.values()) {\n entry.snapshot = { ...entry.snapshot, loading: true, error: null };\n emit(entry, null);\n void refresh(entry.defaultValue);\n }\n };\n\n const handleVisibilityChange = () => {\n if (isHidden()) return;\n for (const entry of entries.values()) {\n const effective = getEffectiveOptions(entry);\n if (!effective.enabled) continue;\n void refresh(entry.defaultValue);\n }\n };\n\n const unsubscribeClientUpdate =\n typeof (client as { on?: unknown }).on === 'function'\n ? (client as { on: (event: 'update', listener: (payload: { changedKeys: string[] }) => void) => () => void }).on(\n 'update',\n ({ changedKeys }) => {\n const changedSet = new Set(changedKeys);\n for (const entry of entries.values()) {\n const previous = entry.snapshot.flags;\n const next = client.getCachedFlags().flags;\n const diff = diffFlagKeys(previous, next);\n if (diff.size === 0) continue;\n const intersects = [...diff].some((key) => changedSet.has(key));\n if (!intersects && changedSet.size > 0) continue;\n entry.snapshot = { ...entry.snapshot, flags: next, loading: false, error: null };\n emit(entry, diff);\n }\n }\n )\n : () => {};\n\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', handleVisibilityChange);\n }\n\n const dispose = () => {\n unsubscribeClientUpdate();\n if (typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n }\n for (const entry of entries.values()) {\n if (entry.timer !== null) {\n clearTimeout(entry.timer);\n }\n entry.timer = null;\n entry.listeners.clear();\n entry.subscribers.clear();\n }\n entries.clear();\n };\n\n return {\n getState(defaultValue: boolean): FlagsState {\n return getEntry(defaultValue).snapshot;\n },\n refreshNow,\n subscribeAll(defaultValue: boolean, listener: () => void, options?: FlagsSubscriptionOptions) {\n return subscribe(defaultValue, listener, options);\n },\n subscribeFlag(flagKey: string, defaultValue: boolean, listener: () => void, options?: FlagsSubscriptionOptions) {\n return subscribe(defaultValue, listener, options, flagKey);\n },\n updateUser,\n dispose\n };\n}\n\nconst FeatureFlareContext = createContext<FeatureFlareContextValue | null>(null);\n\nexport function FeatureFlareProvider(props: {\n config: FeatureFlareReactConfig;\n initialUser: FeatureFlareUserPayload;\n user?: FeatureFlareUserPayload;\n onUserChange?: (next: FeatureFlareUserPayload) => void;\n children: React.ReactNode;\n}) {\n if (props.user && !props.onUserChange) {\n throw new Error('FeatureFlareProvider: when providing `user`, also provide `onUserChange` (controlled mode).');\n }\n\n const [internalUser, setInternalUser] = useState<FeatureFlareUserPayload>(props.initialUser);\n const user = props.user ?? internalUser;\n const setUser = props.onUserChange ?? setInternalUser;\n const userRef = useRef<FeatureFlareUserPayload>(user);\n\n const client = useMemo(() => {\n return new FeatureFlareClient({\n apiBaseUrl: props.config.apiBaseUrl,\n sdkKey: props.config.sdkKey,\n projectKey: props.config.projectKey,\n envKey: props.config.envKey,\n timeoutMs: props.config.timeoutMs,\n maxRetries: props.config.maxRetries,\n backoffMs: props.config.backoffMs,\n jitter: props.config.jitter,\n cacheTtlMs: props.config.cacheTtlMs,\n staleTtlMs: props.config.staleTtlMs,\n bootstrap: props.config.bootstrap,\n persistentCache: props.config.persistentCache,\n onMetric: props.config.onMetric,\n realtime: props.config.realtime\n });\n }, [\n props.config.apiBaseUrl,\n props.config.backoffMs,\n props.config.bootstrap,\n props.config.cacheTtlMs,\n props.config.envKey,\n props.config.jitter,\n props.config.maxRetries,\n props.config.onMetric,\n props.config.persistentCache,\n props.config.projectKey,\n props.config.realtime,\n props.config.sdkKey,\n props.config.staleTtlMs,\n props.config.timeoutMs\n ]);\n\n const flagsStore = useMemo(() => createFlagsStore(client, () => userRef.current), [client]);\n\n useEffect(() => {\n userRef.current = user;\n flagsStore.updateUser();\n }, [flagsStore, user]);\n\n useEffect(() => {\n return () => {\n flagsStore.dispose();\n client.dispose();\n };\n }, [client, flagsStore]);\n\n const value = useMemo(\n () => ({\n client,\n user,\n setUser,\n getFlagsState: flagsStore.getState,\n refreshFlags: flagsStore.refreshNow,\n subscribeFlags: flagsStore.subscribeAll,\n subscribeFlag: (flagKey: string, defaultValue: boolean, listener: () => void, options?: FlagsSubscriptionOptions) =>\n flagsStore.subscribeFlag(flagKey, defaultValue, listener, options),\n getFlagDiagnostics: (flagKey: string) => client.getFlagDiagnostics(flagKey)\n }),\n [client, flagsStore, setUser, user]\n );\n return <FeatureFlareContext.Provider value={value}>{props.children}</FeatureFlareContext.Provider>;\n}\n\nexport function useFeatureFlareContext(): FeatureFlareContextValue {\n const ctx = React.useContext(FeatureFlareContext);\n if (!ctx) throw new Error('useFeatureFlareContext must be used within <FeatureFlareProvider>.');\n return ctx;\n}\n","import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport type { FeatureFlareEvaluationMetadata, FeatureFlareUserPayload } from '@featureflare/sdk-js';\nimport { useFeatureFlareContext, type FlagsState, type FlagsSubscriptionOptions } from './provider.js';\n\ntype BoolFlagState = {\n value: boolean;\n loading: boolean;\n error: string | null;\n};\n\ntype BoolFlagsState = {\n values: Record<string, boolean>;\n loading: boolean;\n errors: Record<string, string>;\n};\n\ntype UseFlagsOptions = FlagsSubscriptionOptions;\n\ntype UseFlagsInput = UseFlagsOptions & {\n defaultValue?: boolean;\n user?: FeatureFlareUserPayload;\n};\n\nexport type FlagDiagnostics = {\n source: FeatureFlareEvaluationMetadata['source'] | 'unknown';\n reason: FeatureFlareEvaluationMetadata['reason'] | 'unknown';\n isStale: boolean;\n updatedAt?: number;\n staleAt?: number;\n expiresAt?: number;\n latencyMs?: number;\n};\n\nconst EMPTY_FLAGS_STATE: FlagsState = { flags: [], loading: true, error: null };\n\nfunction userFingerprint(user?: FeatureFlareUserPayload): string {\n if (!user) return '';\n return JSON.stringify({\n id: user.id ?? '',\n key: user.key ?? '',\n email: user.email ?? '',\n meta: user.meta ?? {}\n });\n}\n\nfunction mapFlags(flags: Array<{ key: string; value: boolean }>): Record<string, boolean> {\n const values: Record<string, boolean> = {};\n for (const flag of flags) {\n values[flag.key] = flag.value;\n }\n return values;\n}\n\nexport function useFeatureFlareUser(): [FeatureFlareUserPayload, (next: FeatureFlareUserPayload) => void] {\n const { user, setUser } = useFeatureFlareContext();\n return [user, setUser];\n}\n\nexport function useFlag(flagKey: string, defaultValue = false): BoolFlagState {\n const { subscribeFlag, getFlagsState, refreshFlags } = useFeatureFlareContext();\n\n useEffect(() => {\n refreshFlags(defaultValue);\n }, [defaultValue, refreshFlags]);\n\n const subscribe = useMemo(\n () =>\n (onStoreChange: () => void) =>\n subscribeFlag(flagKey, defaultValue, onStoreChange),\n [defaultValue, flagKey, subscribeFlag]\n );\n\n const state = useSyncExternalStore(subscribe, () => getFlagsState(defaultValue), () => EMPTY_FLAGS_STATE);\n const value = state.flags.find((entry) => entry.key === flagKey)?.value ?? defaultValue;\n\n return {\n value,\n loading: state.loading,\n error: state.error\n };\n}\n\nexport function useBoolFlag(flagKey: string, defaultValue = false): BoolFlagState {\n return useFlag(flagKey, defaultValue);\n}\n\nexport function useFlags(flagKeys: string[], defaultValue?: boolean): BoolFlagsState;\nexport function useFlags(input?: UseFlagsInput): FlagsState;\nexport function useFlags(defaultValue?: boolean, options?: UseFlagsOptions): FlagsState;\nexport function useFlags(\n defaultValueOrInputOrKeys: boolean | UseFlagsInput | string[] = false,\n optionsOrDefaultValue: UseFlagsOptions | boolean = {}\n): FlagsState | BoolFlagsState {\n const { subscribeFlags, subscribeFlag, getFlagsState, refreshFlags, setUser } = useFeatureFlareContext();\n\n if (Array.isArray(defaultValueOrInputOrKeys)) {\n const keys = [...defaultValueOrInputOrKeys].map((key) => key.trim()).filter(Boolean);\n const defaultValue =\n typeof optionsOrDefaultValue === 'boolean' ? optionsOrDefaultValue : false;\n\n useEffect(() => {\n refreshFlags(defaultValue);\n }, [defaultValue, refreshFlags]);\n\n const subscribe = useMemo(\n () =>\n (onStoreChange: () => void) => {\n const unsubs = keys.map((key) => subscribeFlag(key, defaultValue, onStoreChange));\n return () => {\n for (const unsub of unsubs) unsub();\n };\n },\n [defaultValue, keys, subscribeFlag]\n );\n\n const state = useSyncExternalStore(subscribe, () => getFlagsState(defaultValue), () => EMPTY_FLAGS_STATE);\n const values = mapFlags(state.flags);\n const filtered: Record<string, boolean> = {};\n for (const key of keys) {\n filtered[key] = values[key] ?? defaultValue;\n }\n\n return {\n values: filtered,\n loading: state.loading,\n errors: state.error ? { __global: state.error } : {}\n };\n }\n\n const parsed = useMemo<UseFlagsInput>(() => {\n if (typeof defaultValueOrInputOrKeys === 'boolean') {\n return {\n ...(typeof optionsOrDefaultValue === 'object' && optionsOrDefaultValue !== null ? optionsOrDefaultValue : {}),\n defaultValue: defaultValueOrInputOrKeys\n };\n }\n return defaultValueOrInputOrKeys ?? {};\n }, [defaultValueOrInputOrKeys, optionsOrDefaultValue]);\n\n const defaultValue = parsed.defaultValue ?? false;\n\n const normalizedOptions = useMemo<UseFlagsOptions>(\n () => ({\n enabled: parsed.enabled ?? true,\n refreshIntervalMs: parsed.refreshIntervalMs,\n hiddenRefreshIntervalMs: parsed.hiddenRefreshIntervalMs,\n pauseWhenHidden: parsed.pauseWhenHidden ?? true\n }),\n [parsed.enabled, parsed.hiddenRefreshIntervalMs, parsed.pauseWhenHidden, parsed.refreshIntervalMs]\n );\n\n const appliedUserRef = useRef<string>('');\n const parsedUserFingerprint = useMemo(() => userFingerprint(parsed.user), [parsed.user]);\n\n useEffect(() => {\n if (!parsed.user) return;\n if (appliedUserRef.current === parsedUserFingerprint) return;\n setUser(parsed.user);\n appliedUserRef.current = parsedUserFingerprint;\n }, [parsed.user, parsedUserFingerprint, setUser]);\n\n useEffect(() => {\n if (normalizedOptions.enabled === false) return;\n refreshFlags(defaultValue);\n }, [defaultValue, normalizedOptions.enabled, parsedUserFingerprint, refreshFlags]);\n\n const subscribe = useMemo(\n () =>\n (onStoreChange: () => void) =>\n subscribeFlags(defaultValue, onStoreChange, normalizedOptions),\n [defaultValue, normalizedOptions, subscribeFlags]\n );\n\n return useSyncExternalStore(subscribe, () => getFlagsState(defaultValue), () => EMPTY_FLAGS_STATE);\n}\n\nexport function useBoolFlags(flagKeys: string[], defaultValue = false): BoolFlagsState {\n return useFlags(flagKeys, defaultValue);\n}\n\nexport function useFlagDiagnostics(flagKey: string, defaultValue = false): FlagDiagnostics {\n const { getFlagDiagnostics, subscribeFlag } = useFeatureFlareContext();\n\n const subscribe = useMemo(\n () =>\n (onStoreChange: () => void) =>\n subscribeFlag(flagKey, defaultValue, onStoreChange),\n [defaultValue, flagKey, subscribeFlag]\n );\n\n const metadata = useSyncExternalStore(\n subscribe,\n () => getFlagDiagnostics(flagKey),\n () => null\n );\n\n return {\n source: metadata?.source ?? 'unknown',\n reason: metadata?.reason ?? 'unknown',\n isStale: metadata?.isStale ?? false,\n updatedAt: metadata?.updatedAt,\n staleAt: metadata?.staleAt,\n expiresAt: metadata?.expiresAt,\n latencyMs: metadata?.latencyMs\n };\n}\n"],"mappings":"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","names":["React","import_react","defaultValue","subscribe"]}