@featureflare/react 0.0.5 → 0.0.6-beta.261
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 +119 -83
- package/dist/index.cjs +417 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -3
- package/dist/index.d.ts +61 -3
- package/dist/index.js +417 -68
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -31,10 +31,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
FeatureFlareProvider: () => FeatureFlareProvider,
|
|
34
|
+
resolveFeatureFlareBrowserConfig: () => resolveFeatureFlareBrowserConfig,
|
|
34
35
|
useBoolFlag: () => useBoolFlag,
|
|
35
36
|
useBoolFlags: () => useBoolFlags,
|
|
36
37
|
useFeatureFlareContext: () => useFeatureFlareContext,
|
|
37
|
-
useFeatureFlareUser: () => useFeatureFlareUser
|
|
38
|
+
useFeatureFlareUser: () => useFeatureFlareUser,
|
|
39
|
+
useFlag: () => useFlag,
|
|
40
|
+
useFlagDiagnostics: () => useFlagDiagnostics,
|
|
41
|
+
useFlags: () => useFlags
|
|
38
42
|
});
|
|
39
43
|
module.exports = __toCommonJS(index_exports);
|
|
40
44
|
|
|
@@ -42,6 +46,231 @@ module.exports = __toCommonJS(index_exports);
|
|
|
42
46
|
var import_react = __toESM(require("react"), 1);
|
|
43
47
|
var import_sdk_js = require("@featureflare/sdk-js");
|
|
44
48
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
49
|
+
function resolveFeatureFlareBrowserConfig(input) {
|
|
50
|
+
const explicitEnv = input?.envKey;
|
|
51
|
+
const envFromVars = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_FEATUREFLARE_ENV_KEY?.trim().toLowerCase() : "";
|
|
52
|
+
const resolvedEnv = explicitEnv ?? (envFromVars === "development" || envFromVars === "staging" || envFromVars === "production" ? envFromVars : void 0);
|
|
53
|
+
const apiBaseUrl = input?.apiBaseUrl ?? (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_FEATUREFLARE_API_BASE_URL?.trim() : void 0);
|
|
54
|
+
const sdkKeyDevelopment = (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_DEVELOPMENT?.trim() : "") || (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_DEV?.trim() : "") || "";
|
|
55
|
+
const sdkKeyStaging = (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_STAGING?.trim() : "") || "";
|
|
56
|
+
const sdkKeyProduction = (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_PRODUCTION?.trim() : "") || (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY_PROD?.trim() : "") || "";
|
|
57
|
+
const sdkKeyDefault = (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_FEATUREFLARE_CLIENT_KEY?.trim() : "") || "";
|
|
58
|
+
const sdkKey = (resolvedEnv === "development" ? sdkKeyDevelopment : "") || (resolvedEnv === "staging" ? sdkKeyStaging : "") || (resolvedEnv === "production" ? sdkKeyProduction : "") || sdkKeyDefault || void 0;
|
|
59
|
+
return {
|
|
60
|
+
apiBaseUrl,
|
|
61
|
+
envKey: resolvedEnv,
|
|
62
|
+
sdkKey
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function normalizeSubscriptionOptions(options) {
|
|
66
|
+
const refreshIntervalMs = Number.isFinite(options?.refreshIntervalMs) && (options?.refreshIntervalMs ?? 0) > 0 ? Number(options?.refreshIntervalMs) : 1e4;
|
|
67
|
+
const hiddenRefreshIntervalMs = Number.isFinite(options?.hiddenRefreshIntervalMs) && (options?.hiddenRefreshIntervalMs ?? 0) > 0 ? Number(options?.hiddenRefreshIntervalMs) : Math.max(refreshIntervalMs * 6, 6e4);
|
|
68
|
+
return {
|
|
69
|
+
refreshIntervalMs,
|
|
70
|
+
hiddenRefreshIntervalMs,
|
|
71
|
+
pauseWhenHidden: options?.pauseWhenHidden ?? true,
|
|
72
|
+
enabled: options?.enabled ?? true
|
|
73
|
+
};
|
|
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
|
+
}
|
|
98
|
+
function createFlagsStore(client, getUser) {
|
|
99
|
+
const entries = /* @__PURE__ */ new Map();
|
|
100
|
+
let nextSubscriberId = 1;
|
|
101
|
+
const isHidden = () => typeof document !== "undefined" && document.visibilityState === "hidden";
|
|
102
|
+
const getEntry = (defaultValue) => {
|
|
103
|
+
const key = defaultValue ? "1" : "0";
|
|
104
|
+
const existing = entries.get(key);
|
|
105
|
+
if (existing) return existing;
|
|
106
|
+
const cached = client.getCachedFlags();
|
|
107
|
+
const created = {
|
|
108
|
+
defaultValue,
|
|
109
|
+
snapshot: { flags: cached.flags, loading: !cached.hasData, error: null },
|
|
110
|
+
listeners: /* @__PURE__ */ new Map(),
|
|
111
|
+
subscribers: /* @__PURE__ */ new Map(),
|
|
112
|
+
timer: null,
|
|
113
|
+
inFlight: false
|
|
114
|
+
};
|
|
115
|
+
entries.set(key, created);
|
|
116
|
+
return created;
|
|
117
|
+
};
|
|
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
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const getEffectiveOptions = (entry) => {
|
|
126
|
+
const active = [...entry.subscribers.values()].filter((s) => s.enabled);
|
|
127
|
+
if (active.length === 0) {
|
|
128
|
+
return { enabled: false, refreshIntervalMs: 0, hiddenRefreshIntervalMs: 0, pauseWhenHidden: true };
|
|
129
|
+
}
|
|
130
|
+
const refreshIntervalMs = active.reduce((min, s) => Math.min(min, s.refreshIntervalMs), Number.POSITIVE_INFINITY);
|
|
131
|
+
const hiddenActive = active.filter((s) => !s.pauseWhenHidden);
|
|
132
|
+
const hiddenRefreshIntervalMs = hiddenActive.length > 0 ? hiddenActive.reduce((min, s) => Math.min(min, s.hiddenRefreshIntervalMs), Number.POSITIVE_INFINITY) : 0;
|
|
133
|
+
return {
|
|
134
|
+
enabled: true,
|
|
135
|
+
refreshIntervalMs: Number.isFinite(refreshIntervalMs) ? refreshIntervalMs : 1e4,
|
|
136
|
+
hiddenRefreshIntervalMs,
|
|
137
|
+
pauseWhenHidden: hiddenActive.length === 0
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
const schedule = (entry) => {
|
|
141
|
+
if (entry.timer !== null) {
|
|
142
|
+
clearTimeout(entry.timer);
|
|
143
|
+
entry.timer = null;
|
|
144
|
+
}
|
|
145
|
+
const effective = getEffectiveOptions(entry);
|
|
146
|
+
if (!effective.enabled) return;
|
|
147
|
+
if (isHidden()) {
|
|
148
|
+
if (effective.pauseWhenHidden) return;
|
|
149
|
+
entry.timer = setTimeout(() => {
|
|
150
|
+
void refresh(entry.defaultValue);
|
|
151
|
+
}, effective.hiddenRefreshIntervalMs);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
entry.timer = setTimeout(() => {
|
|
155
|
+
void refresh(entry.defaultValue);
|
|
156
|
+
}, effective.refreshIntervalMs);
|
|
157
|
+
};
|
|
158
|
+
const refresh = async (defaultValue, force = false) => {
|
|
159
|
+
const entry = getEntry(defaultValue);
|
|
160
|
+
const effective = getEffectiveOptions(entry);
|
|
161
|
+
if (!effective.enabled && !force) return;
|
|
162
|
+
if (!force && isHidden() && effective.pauseWhenHidden) {
|
|
163
|
+
schedule(entry);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (entry.inFlight) return;
|
|
167
|
+
entry.inFlight = true;
|
|
168
|
+
try {
|
|
169
|
+
const previousFlags = entry.snapshot.flags;
|
|
170
|
+
const flags = await client.flags(getUser(), defaultValue);
|
|
171
|
+
const changed = diffFlagKeys(previousFlags, flags);
|
|
172
|
+
entry.snapshot = { flags, loading: false, error: null };
|
|
173
|
+
if (changed.size > 0 || previousFlags.length === 0) {
|
|
174
|
+
emit(entry, changed);
|
|
175
|
+
}
|
|
176
|
+
} catch (error) {
|
|
177
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
178
|
+
entry.snapshot = { ...entry.snapshot, loading: false, error: message };
|
|
179
|
+
emit(entry, null);
|
|
180
|
+
} finally {
|
|
181
|
+
entry.inFlight = false;
|
|
182
|
+
schedule(entry);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
const refreshNow = (defaultValue) => {
|
|
186
|
+
const entry = getEntry(defaultValue);
|
|
187
|
+
entry.snapshot = { ...entry.snapshot, loading: true, error: null };
|
|
188
|
+
emit(entry, null);
|
|
189
|
+
void refresh(defaultValue, true);
|
|
190
|
+
};
|
|
191
|
+
const subscribe = (defaultValue, listener, options, flagKey) => {
|
|
192
|
+
const entry = getEntry(defaultValue);
|
|
193
|
+
const subscriberId = nextSubscriberId;
|
|
194
|
+
nextSubscriberId += 1;
|
|
195
|
+
entry.listeners.set(subscriberId, { listener, flagKey });
|
|
196
|
+
entry.subscribers.set(subscriberId, normalizeSubscriptionOptions(options));
|
|
197
|
+
const effective = getEffectiveOptions(entry);
|
|
198
|
+
if (effective.enabled && !entry.inFlight && entry.snapshot.loading) {
|
|
199
|
+
void refresh(defaultValue);
|
|
200
|
+
} else {
|
|
201
|
+
schedule(entry);
|
|
202
|
+
}
|
|
203
|
+
return () => {
|
|
204
|
+
entry.listeners.delete(subscriberId);
|
|
205
|
+
entry.subscribers.delete(subscriberId);
|
|
206
|
+
schedule(entry);
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
const updateUser = () => {
|
|
210
|
+
for (const entry of entries.values()) {
|
|
211
|
+
entry.snapshot = { ...entry.snapshot, loading: true, error: null };
|
|
212
|
+
emit(entry, null);
|
|
213
|
+
void refresh(entry.defaultValue);
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
const handleVisibilityChange = () => {
|
|
217
|
+
if (isHidden()) return;
|
|
218
|
+
for (const entry of entries.values()) {
|
|
219
|
+
const effective = getEffectiveOptions(entry);
|
|
220
|
+
if (!effective.enabled) continue;
|
|
221
|
+
void refresh(entry.defaultValue);
|
|
222
|
+
}
|
|
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
|
+
};
|
|
241
|
+
if (typeof document !== "undefined") {
|
|
242
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
243
|
+
}
|
|
244
|
+
const dispose = () => {
|
|
245
|
+
unsubscribeClientUpdate();
|
|
246
|
+
if (typeof document !== "undefined") {
|
|
247
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
248
|
+
}
|
|
249
|
+
for (const entry of entries.values()) {
|
|
250
|
+
if (entry.timer !== null) {
|
|
251
|
+
clearTimeout(entry.timer);
|
|
252
|
+
}
|
|
253
|
+
entry.timer = null;
|
|
254
|
+
entry.listeners.clear();
|
|
255
|
+
entry.subscribers.clear();
|
|
256
|
+
}
|
|
257
|
+
entries.clear();
|
|
258
|
+
};
|
|
259
|
+
return {
|
|
260
|
+
getState(defaultValue) {
|
|
261
|
+
return getEntry(defaultValue).snapshot;
|
|
262
|
+
},
|
|
263
|
+
refreshNow,
|
|
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
|
+
},
|
|
270
|
+
updateUser,
|
|
271
|
+
dispose
|
|
272
|
+
};
|
|
273
|
+
}
|
|
45
274
|
var FeatureFlareContext = (0, import_react.createContext)(null);
|
|
46
275
|
function FeatureFlareProvider(props) {
|
|
47
276
|
if (props.user && !props.onUserChange) {
|
|
@@ -50,20 +279,64 @@ function FeatureFlareProvider(props) {
|
|
|
50
279
|
const [internalUser, setInternalUser] = (0, import_react.useState)(props.initialUser);
|
|
51
280
|
const user = props.user ?? internalUser;
|
|
52
281
|
const setUser = props.onUserChange ?? setInternalUser;
|
|
282
|
+
const userRef = (0, import_react.useRef)(user);
|
|
53
283
|
const client = (0, import_react.useMemo)(() => {
|
|
54
284
|
return new import_sdk_js.FeatureFlareClient({
|
|
55
285
|
apiBaseUrl: props.config.apiBaseUrl,
|
|
56
286
|
sdkKey: props.config.sdkKey,
|
|
57
287
|
projectKey: props.config.projectKey,
|
|
58
|
-
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
|
|
59
299
|
});
|
|
60
300
|
}, [
|
|
61
301
|
props.config.apiBaseUrl,
|
|
302
|
+
props.config.backoffMs,
|
|
303
|
+
props.config.bootstrap,
|
|
304
|
+
props.config.cacheTtlMs,
|
|
62
305
|
props.config.envKey,
|
|
306
|
+
props.config.jitter,
|
|
307
|
+
props.config.maxRetries,
|
|
308
|
+
props.config.onMetric,
|
|
309
|
+
props.config.persistentCache,
|
|
63
310
|
props.config.projectKey,
|
|
64
|
-
props.config.
|
|
311
|
+
props.config.realtime,
|
|
312
|
+
props.config.sdkKey,
|
|
313
|
+
props.config.staleTtlMs,
|
|
314
|
+
props.config.timeoutMs
|
|
65
315
|
]);
|
|
66
|
-
const
|
|
316
|
+
const flagsStore = (0, import_react.useMemo)(() => createFlagsStore(client, () => userRef.current), [client]);
|
|
317
|
+
(0, import_react.useEffect)(() => {
|
|
318
|
+
userRef.current = user;
|
|
319
|
+
flagsStore.updateUser();
|
|
320
|
+
}, [flagsStore, user]);
|
|
321
|
+
(0, import_react.useEffect)(() => {
|
|
322
|
+
return () => {
|
|
323
|
+
flagsStore.dispose();
|
|
324
|
+
client.dispose();
|
|
325
|
+
};
|
|
326
|
+
}, [client, flagsStore]);
|
|
327
|
+
const value = (0, import_react.useMemo)(
|
|
328
|
+
() => ({
|
|
329
|
+
client,
|
|
330
|
+
user,
|
|
331
|
+
setUser,
|
|
332
|
+
getFlagsState: flagsStore.getState,
|
|
333
|
+
refreshFlags: flagsStore.refreshNow,
|
|
334
|
+
subscribeFlags: flagsStore.subscribeAll,
|
|
335
|
+
subscribeFlag: (flagKey, defaultValue, listener, options) => flagsStore.subscribeFlag(flagKey, defaultValue, listener, options),
|
|
336
|
+
getFlagDiagnostics: (flagKey) => client.getFlagDiagnostics(flagKey)
|
|
337
|
+
}),
|
|
338
|
+
[client, flagsStore, setUser, user]
|
|
339
|
+
);
|
|
67
340
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FeatureFlareContext.Provider, { value, children: props.children });
|
|
68
341
|
}
|
|
69
342
|
function useFeatureFlareContext() {
|
|
@@ -74,81 +347,159 @@ function useFeatureFlareContext() {
|
|
|
74
347
|
|
|
75
348
|
// src/hooks.ts
|
|
76
349
|
var import_react2 = require("react");
|
|
350
|
+
var EMPTY_FLAGS_STATE = { flags: [], loading: true, error: null };
|
|
351
|
+
function userFingerprint(user) {
|
|
352
|
+
if (!user) return "";
|
|
353
|
+
return JSON.stringify({
|
|
354
|
+
id: user.id ?? "",
|
|
355
|
+
key: user.key ?? "",
|
|
356
|
+
email: user.email ?? "",
|
|
357
|
+
meta: user.meta ?? {}
|
|
358
|
+
});
|
|
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
|
+
}
|
|
77
367
|
function useFeatureFlareUser() {
|
|
78
368
|
const { user, setUser } = useFeatureFlareContext();
|
|
79
369
|
return [user, setUser];
|
|
80
370
|
}
|
|
81
|
-
function
|
|
82
|
-
const {
|
|
83
|
-
const [state, setState] = (0, import_react2.useState)({ value: defaultValue, loading: true, error: null });
|
|
84
|
-
const userId = user.id ?? user.key ?? "";
|
|
85
|
-
const key = (0, import_react2.useMemo)(() => `${flagKey}:${userId}`, [flagKey, userId]);
|
|
86
|
-
const lastKey = (0, import_react2.useRef)("");
|
|
371
|
+
function useFlag(flagKey, defaultValue = false) {
|
|
372
|
+
const { subscribeFlag, getFlagsState, refreshFlags } = useFeatureFlareContext();
|
|
87
373
|
(0, import_react2.useEffect)(() => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
102
|
-
setState({ value: defaultValue, loading: false, error: msg });
|
|
103
|
-
}
|
|
104
|
-
})();
|
|
105
|
-
return () => {
|
|
106
|
-
cancelled = true;
|
|
107
|
-
};
|
|
108
|
-
}, [client, defaultValue, flagKey, key, user]);
|
|
109
|
-
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
|
+
};
|
|
110
387
|
}
|
|
111
|
-
function
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
cancelled = true;
|
|
388
|
+
function useBoolFlag(flagKey, defaultValue = false) {
|
|
389
|
+
return useFlag(flagKey, defaultValue);
|
|
390
|
+
}
|
|
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 } : {}
|
|
142
418
|
};
|
|
143
|
-
}
|
|
144
|
-
|
|
419
|
+
}
|
|
420
|
+
const parsed = (0, import_react2.useMemo)(() => {
|
|
421
|
+
if (typeof defaultValueOrInputOrKeys === "boolean") {
|
|
422
|
+
return {
|
|
423
|
+
...typeof optionsOrDefaultValue === "object" && optionsOrDefaultValue !== null ? optionsOrDefaultValue : {},
|
|
424
|
+
defaultValue: defaultValueOrInputOrKeys
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
return defaultValueOrInputOrKeys ?? {};
|
|
428
|
+
}, [defaultValueOrInputOrKeys, optionsOrDefaultValue]);
|
|
429
|
+
const defaultValue = parsed.defaultValue ?? false;
|
|
430
|
+
const normalizedOptions = (0, import_react2.useMemo)(
|
|
431
|
+
() => ({
|
|
432
|
+
enabled: parsed.enabled ?? true,
|
|
433
|
+
refreshIntervalMs: parsed.refreshIntervalMs,
|
|
434
|
+
hiddenRefreshIntervalMs: parsed.hiddenRefreshIntervalMs,
|
|
435
|
+
pauseWhenHidden: parsed.pauseWhenHidden ?? true
|
|
436
|
+
}),
|
|
437
|
+
[parsed.enabled, parsed.hiddenRefreshIntervalMs, parsed.pauseWhenHidden, parsed.refreshIntervalMs]
|
|
438
|
+
);
|
|
439
|
+
const appliedUserRef = (0, import_react2.useRef)("");
|
|
440
|
+
const parsedUserFingerprint = (0, import_react2.useMemo)(() => userFingerprint(parsed.user), [parsed.user]);
|
|
441
|
+
(0, import_react2.useEffect)(() => {
|
|
442
|
+
if (!parsed.user) return;
|
|
443
|
+
if (appliedUserRef.current === parsedUserFingerprint) return;
|
|
444
|
+
setUser(parsed.user);
|
|
445
|
+
appliedUserRef.current = parsedUserFingerprint;
|
|
446
|
+
}, [parsed.user, parsedUserFingerprint, setUser]);
|
|
447
|
+
(0, import_react2.useEffect)(() => {
|
|
448
|
+
if (normalizedOptions.enabled === false) return;
|
|
449
|
+
refreshFlags(defaultValue);
|
|
450
|
+
}, [defaultValue, normalizedOptions.enabled, parsedUserFingerprint, refreshFlags]);
|
|
451
|
+
const subscribe = (0, import_react2.useMemo)(
|
|
452
|
+
() => (onStoreChange) => subscribeFlags(defaultValue, onStoreChange, normalizedOptions),
|
|
453
|
+
[defaultValue, normalizedOptions, subscribeFlags]
|
|
454
|
+
);
|
|
455
|
+
return (0, import_react2.useSyncExternalStore)(subscribe, () => getFlagsState(defaultValue), () => EMPTY_FLAGS_STATE);
|
|
456
|
+
}
|
|
457
|
+
function useBoolFlags(flagKeysOrDefaultValue = false, optionsOrDefaultValue = {}) {
|
|
458
|
+
if (Array.isArray(flagKeysOrDefaultValue)) {
|
|
459
|
+
const defaultValue = typeof optionsOrDefaultValue === "boolean" ? optionsOrDefaultValue : false;
|
|
460
|
+
return useFlags(flagKeysOrDefaultValue, defaultValue);
|
|
461
|
+
}
|
|
462
|
+
const state = useFlags(
|
|
463
|
+
flagKeysOrDefaultValue,
|
|
464
|
+
typeof optionsOrDefaultValue === "object" && optionsOrDefaultValue !== null ? optionsOrDefaultValue : {}
|
|
465
|
+
);
|
|
466
|
+
return {
|
|
467
|
+
values: mapFlags(state.flags),
|
|
468
|
+
loading: state.loading,
|
|
469
|
+
errors: state.error ? { __global: state.error } : {}
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
function useFlagDiagnostics(flagKey, defaultValue = false) {
|
|
473
|
+
const { getFlagDiagnostics, subscribeFlag } = useFeatureFlareContext();
|
|
474
|
+
const subscribe = (0, import_react2.useMemo)(
|
|
475
|
+
() => (onStoreChange) => subscribeFlag(flagKey, defaultValue, onStoreChange),
|
|
476
|
+
[defaultValue, flagKey, subscribeFlag]
|
|
477
|
+
);
|
|
478
|
+
const metadata = (0, import_react2.useSyncExternalStore)(
|
|
479
|
+
subscribe,
|
|
480
|
+
() => getFlagDiagnostics(flagKey),
|
|
481
|
+
() => null
|
|
482
|
+
);
|
|
483
|
+
return {
|
|
484
|
+
source: metadata?.source ?? "unknown",
|
|
485
|
+
reason: metadata?.reason ?? "unknown",
|
|
486
|
+
isStale: metadata?.isStale ?? false,
|
|
487
|
+
updatedAt: metadata?.updatedAt,
|
|
488
|
+
staleAt: metadata?.staleAt,
|
|
489
|
+
expiresAt: metadata?.expiresAt,
|
|
490
|
+
latencyMs: metadata?.latencyMs
|
|
491
|
+
};
|
|
145
492
|
}
|
|
146
493
|
// Annotate the CommonJS export names for ESM import in node:
|
|
147
494
|
0 && (module.exports = {
|
|
148
495
|
FeatureFlareProvider,
|
|
496
|
+
resolveFeatureFlareBrowserConfig,
|
|
149
497
|
useBoolFlag,
|
|
150
498
|
useBoolFlags,
|
|
151
499
|
useFeatureFlareContext,
|
|
152
|
-
useFeatureFlareUser
|
|
500
|
+
useFeatureFlareUser,
|
|
501
|
+
useFlag,
|
|
502
|
+
useFlagDiagnostics,
|
|
503
|
+
useFlags
|
|
153
504
|
});
|
|
154
505
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -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, useMemo, useState } from 'react';\nimport { FeatureFlareClient, type FeatureFlareUserPayload } from '@featureflare/sdk-js';\n\ntype 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?: string;\n};\n\ntype FeatureFlareContextValue = {\n client: FeatureFlareClient;\n user: FeatureFlareUserPayload;\n setUser: (next: FeatureFlareUserPayload) => void;\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\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 value = useMemo(() => ({ client, user, setUser }), [client, user]);\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 } from 'react';\nimport type { FeatureFlareUserPayload } from '@featureflare/sdk-js';\nimport { useFeatureFlareContext } 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\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"],"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?: boolean): BoolFlagsState;\nexport function useBoolFlags(defaultValue?: boolean, options?: UseFlagsOptions): BoolFlagsState;\nexport function useBoolFlags(\n flagKeysOrDefaultValue: string[] | boolean = false,\n optionsOrDefaultValue: UseFlagsOptions | boolean = {}\n): BoolFlagsState {\n if (Array.isArray(flagKeysOrDefaultValue)) {\n const defaultValue =\n typeof optionsOrDefaultValue === 'boolean' ? optionsOrDefaultValue : false;\n return useFlags(flagKeysOrDefaultValue, defaultValue);\n }\n\n const state = useFlags(\n flagKeysOrDefaultValue,\n typeof optionsOrDefaultValue === 'object' && optionsOrDefaultValue !== null\n ? optionsOrDefaultValue\n : {}\n ) as FlagsState;\n return {\n values: mapFlags(state.flags),\n loading: state.loading,\n errors: state.error ? { __global: state.error } : {}\n };\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"]}
|