@supashiphq/react-sdk 0.7.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,469 @@
1
+ "use strict";
2
+ "use client";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.ts
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ QueryClient: () => QueryClient,
25
+ SupaFeature: () => SupaFeature,
26
+ SupaProvider: () => SupaProvider,
27
+ getInitialQueryState: () => getInitialQueryState,
28
+ queryCache: () => queryCache,
29
+ useClient: () => useClient,
30
+ useFeature: () => useFeature,
31
+ useFeatureContext: () => useFeatureContext,
32
+ useFeatures: () => useFeatures,
33
+ useQuery: () => useQuery,
34
+ useQueryClient: () => useQueryClient
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+
38
+ // src/provider.tsx
39
+ var import_react2 = require("react");
40
+ var import_javascript_sdk = require("@supashiphq/javascript-sdk");
41
+
42
+ // src/query.ts
43
+ var import_react = require("react");
44
+ function getInitialQueryState(initialData, enabled = true) {
45
+ return {
46
+ status: !enabled ? "idle" : initialData !== void 0 ? "success" : "idle",
47
+ data: initialData,
48
+ error: null,
49
+ isLoading: enabled && initialData === void 0,
50
+ isSuccess: initialData !== void 0,
51
+ isError: false,
52
+ isIdle: !enabled || initialData === void 0,
53
+ isFetching: false,
54
+ dataUpdatedAt: initialData !== void 0 ? Date.now() : 0
55
+ };
56
+ }
57
+ function queryReducer(state, action) {
58
+ switch (action.type) {
59
+ case "FETCH_START":
60
+ return {
61
+ ...state,
62
+ status: state.data === void 0 ? "loading" : state.status,
63
+ isLoading: state.data === void 0,
64
+ isIdle: false,
65
+ isFetching: true
66
+ };
67
+ case "FETCH_SUCCESS":
68
+ return {
69
+ ...state,
70
+ status: "success",
71
+ data: action.payload.data,
72
+ error: null,
73
+ isLoading: false,
74
+ isSuccess: true,
75
+ isError: false,
76
+ isIdle: false,
77
+ isFetching: false,
78
+ dataUpdatedAt: Date.now()
79
+ };
80
+ case "FETCH_ERROR":
81
+ return {
82
+ ...state,
83
+ status: "error",
84
+ error: action.payload.error,
85
+ isLoading: false,
86
+ isSuccess: !!state.data,
87
+ isError: true,
88
+ isIdle: false,
89
+ isFetching: false
90
+ };
91
+ default:
92
+ return state;
93
+ }
94
+ }
95
+ var QueryCache = class {
96
+ constructor() {
97
+ this.cache = /* @__PURE__ */ new Map();
98
+ this.timers = /* @__PURE__ */ new Map();
99
+ this.observers = /* @__PURE__ */ new Map();
100
+ }
101
+ getQuery(queryKey) {
102
+ const entry = this.cache.get(queryKey);
103
+ return entry ? entry.data : void 0;
104
+ }
105
+ isStale(queryKey, staleTime) {
106
+ const entry = this.cache.get(queryKey);
107
+ if (!entry) return true;
108
+ return Date.now() - entry.timestamp > staleTime;
109
+ }
110
+ setQuery(queryKey, data, cacheTime = 5 * 60 * 1e3) {
111
+ this.cache.set(queryKey, { data, timestamp: Date.now() });
112
+ if (this.timers.has(queryKey)) {
113
+ clearTimeout(this.timers.get(queryKey));
114
+ }
115
+ const timer = setTimeout(() => {
116
+ this.cache.delete(queryKey);
117
+ this.timers.delete(queryKey);
118
+ }, cacheTime);
119
+ this.timers.set(queryKey, timer);
120
+ }
121
+ subscribe(queryKey, callback) {
122
+ if (!this.observers.has(queryKey)) {
123
+ this.observers.set(queryKey, /* @__PURE__ */ new Set());
124
+ }
125
+ this.observers.get(queryKey).add(callback);
126
+ return () => {
127
+ const callbacks = this.observers.get(queryKey);
128
+ if (callbacks) {
129
+ callbacks.delete(callback);
130
+ if (callbacks.size === 0) {
131
+ this.observers.delete(queryKey);
132
+ }
133
+ }
134
+ };
135
+ }
136
+ notifyObservers(queryKey) {
137
+ const callbacks = this.observers.get(queryKey);
138
+ if (callbacks) {
139
+ callbacks.forEach((callback) => callback());
140
+ }
141
+ }
142
+ invalidateQuery(queryKey) {
143
+ this.cache.delete(queryKey);
144
+ if (this.timers.has(queryKey)) {
145
+ clearTimeout(this.timers.get(queryKey));
146
+ this.timers.delete(queryKey);
147
+ }
148
+ this.notifyObservers(queryKey);
149
+ }
150
+ invalidateQueries(queryKeyPrefix) {
151
+ for (const [key] of this.cache) {
152
+ if (key.startsWith(queryKeyPrefix)) {
153
+ this.invalidateQuery(key);
154
+ }
155
+ }
156
+ }
157
+ clear() {
158
+ this.cache.clear();
159
+ this.timers.forEach((timer) => clearTimeout(timer));
160
+ this.timers.clear();
161
+ this.observers.clear();
162
+ }
163
+ };
164
+ var queryCache = new QueryCache();
165
+ var QueryClient = class {
166
+ constructor(cache = queryCache) {
167
+ this.cache = cache;
168
+ }
169
+ /**
170
+ * Invalidates a specific query by its query key
171
+ * This will remove it from cache and trigger refetch in all components using this query
172
+ */
173
+ invalidateQueries(queryKey) {
174
+ const stringifiedKey = stableStringifyQueryKey(queryKey);
175
+ this.cache.invalidateQuery(stringifiedKey);
176
+ }
177
+ /**
178
+ * Invalidates all queries matching a partial query key
179
+ * For example, invalidateQueriesByPrefix(['feature']) will invalidate all feature queries
180
+ */
181
+ invalidateQueriesByPrefix(queryKeyPrefix) {
182
+ const stringifiedPrefix = stableStringifyQueryKey(queryKeyPrefix);
183
+ this.cache.invalidateQueries(stringifiedPrefix.slice(0, -1));
184
+ }
185
+ /**
186
+ * Clears all queries from the cache
187
+ */
188
+ clear() {
189
+ this.cache.clear();
190
+ }
191
+ };
192
+ var queryClient = new QueryClient();
193
+ function useQueryClient() {
194
+ return queryClient;
195
+ }
196
+ function stableStringifyQueryKey(queryKey) {
197
+ return JSON.stringify(queryKey, (_, val) => typeof val === "function" ? val.toString() : val);
198
+ }
199
+ function useQuery(queryKey, queryFn, options = {}) {
200
+ const {
201
+ enabled = true,
202
+ retry = 3,
203
+ retryDelay = 1e3,
204
+ staleTime = 0,
205
+ cacheTime = 5 * 60 * 1e3,
206
+ refetchOnWindowFocus = true,
207
+ initialData
208
+ } = options;
209
+ const stringifiedQueryKey = stableStringifyQueryKey(queryKey);
210
+ const queryFnRef = (0, import_react.useRef)(queryFn);
211
+ const optionsRef = (0, import_react.useRef)(options);
212
+ (0, import_react.useEffect)(() => {
213
+ queryFnRef.current = queryFn;
214
+ optionsRef.current = options;
215
+ }, [queryFn, options]);
216
+ const cachedData = queryCache.getQuery(stringifiedQueryKey);
217
+ const isStale = queryCache.isStale(stringifiedQueryKey, staleTime);
218
+ const initialStateData = cachedData !== void 0 ? cachedData : initialData;
219
+ const initialState = getInitialQueryState(initialStateData, enabled);
220
+ const [state, dispatch] = (0, import_react.useReducer)(queryReducer, initialState);
221
+ const executeFetch = (0, import_react.useCallback)(async () => {
222
+ if (!enabled) return;
223
+ dispatch({ type: "FETCH_START" });
224
+ let retryCount = 0;
225
+ const maxRetries = typeof retry === "boolean" ? retry ? 3 : 0 : retry;
226
+ const runQuery = async () => {
227
+ try {
228
+ const data = await queryFnRef.current();
229
+ queryCache.setQuery(stringifiedQueryKey, data, cacheTime);
230
+ dispatch({ type: "FETCH_SUCCESS", payload: { data } });
231
+ if (optionsRef.current.onSuccess) {
232
+ optionsRef.current.onSuccess(data);
233
+ }
234
+ if (optionsRef.current.onSettled) {
235
+ optionsRef.current.onSettled(data, null);
236
+ }
237
+ } catch (err) {
238
+ const error = err;
239
+ if (retryCount < maxRetries) {
240
+ retryCount++;
241
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
242
+ return runQuery();
243
+ }
244
+ dispatch({ type: "FETCH_ERROR", payload: { error } });
245
+ if (optionsRef.current.onError) {
246
+ optionsRef.current.onError(error);
247
+ }
248
+ if (optionsRef.current.onSettled) {
249
+ optionsRef.current.onSettled(void 0, error);
250
+ }
251
+ }
252
+ };
253
+ await runQuery();
254
+ }, [enabled, stringifiedQueryKey, retry, retryDelay, cacheTime]);
255
+ (0, import_react.useEffect)(() => {
256
+ if (enabled && (isStale || state.data === void 0)) {
257
+ executeFetch();
258
+ }
259
+ }, [enabled, isStale, executeFetch, state.data]);
260
+ (0, import_react.useEffect)(() => {
261
+ if (!refetchOnWindowFocus) return;
262
+ const handleFocus = () => {
263
+ if (enabled && isStale) {
264
+ executeFetch();
265
+ }
266
+ };
267
+ window.addEventListener("focus", handleFocus);
268
+ return () => window.removeEventListener("focus", handleFocus);
269
+ }, [enabled, isStale, executeFetch, refetchOnWindowFocus]);
270
+ (0, import_react.useEffect)(() => {
271
+ const unsubscribe = queryCache.subscribe(stringifiedQueryKey, () => {
272
+ executeFetch();
273
+ });
274
+ return unsubscribe;
275
+ }, [stringifiedQueryKey, executeFetch]);
276
+ const refetch = (0, import_react.useCallback)(async () => {
277
+ await executeFetch();
278
+ }, [executeFetch]);
279
+ return {
280
+ ...state,
281
+ refetch
282
+ };
283
+ }
284
+
285
+ // src/provider.tsx
286
+ var import_jsx_runtime = require("react/jsx-runtime");
287
+ var SupaContext = (0, import_react2.createContext)(null);
288
+ var DEFAULT_TOOLBAR_CONFIG = { enabled: "auto" };
289
+ function SupaProvider({
290
+ config,
291
+ toolbar,
292
+ children
293
+ }) {
294
+ const queryClient2 = useQueryClient();
295
+ const effectiveToolbar = toolbar ?? DEFAULT_TOOLBAR_CONFIG;
296
+ const handleOverrideChange = (0, import_react2.useCallback)(
297
+ (featureOverride, allOverrides) => {
298
+ if (typeof effectiveToolbar === "object" && effectiveToolbar.onOverrideChange) {
299
+ effectiveToolbar.onOverrideChange(featureOverride, allOverrides);
300
+ }
301
+ if (featureOverride.feature) {
302
+ queryClient2.invalidateQueriesByPrefix(["feature", featureOverride.feature]);
303
+ queryClient2.invalidateQueriesByPrefix(["features"]);
304
+ }
305
+ },
306
+ [effectiveToolbar, queryClient2]
307
+ );
308
+ const clientRef = (0, import_react2.useRef)(null);
309
+ if (!clientRef.current) {
310
+ const toolbarConfig = effectiveToolbar === false ? false : {
311
+ ...typeof effectiveToolbar === "object" ? effectiveToolbar : {},
312
+ onOverrideChange: handleOverrideChange
313
+ };
314
+ clientRef.current = new import_javascript_sdk.SupaClient({
315
+ ...config,
316
+ toolbar: toolbarConfig
317
+ });
318
+ }
319
+ const client = clientRef.current;
320
+ (0, import_react2.useEffect)(() => {
321
+ return () => {
322
+ if (clientRef.current) {
323
+ const client2 = clientRef.current;
324
+ if (client2.plugins && Array.isArray(client2.plugins)) {
325
+ client2.plugins.forEach((plugin) => {
326
+ if (plugin.cleanup) {
327
+ plugin.cleanup();
328
+ }
329
+ });
330
+ }
331
+ clientRef.current = null;
332
+ }
333
+ };
334
+ }, []);
335
+ const updateContext = (0, import_react2.useCallback)(
336
+ (context, mergeWithExisting = true) => {
337
+ client.updateContext(context, mergeWithExisting);
338
+ },
339
+ [client]
340
+ );
341
+ const getContext = (0, import_react2.useCallback)(() => {
342
+ return client.getContext();
343
+ }, [client]);
344
+ const contextValue = (0, import_react2.useMemo)(
345
+ () => ({
346
+ client,
347
+ updateContext,
348
+ getContext
349
+ }),
350
+ [client, updateContext, getContext]
351
+ );
352
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SupaContext.Provider, { value: contextValue, children });
353
+ }
354
+ function useClient() {
355
+ const context = (0, import_react2.useContext)(SupaContext);
356
+ if (!context) {
357
+ throw new Error("useClient must be used within a SupaProvider");
358
+ }
359
+ return context.client;
360
+ }
361
+ function useFeatureContext() {
362
+ const context = (0, import_react2.useContext)(SupaContext);
363
+ if (!context) {
364
+ throw new Error("useFeatureContext must be used within a SupaProvider");
365
+ }
366
+ return {
367
+ updateContext: context.updateContext,
368
+ getContext: context.getContext
369
+ };
370
+ }
371
+
372
+ // src/hooks.ts
373
+ var STALE_TIME = 5 * 60 * 1e3;
374
+ var CACHE_TIME = 10 * 60 * 1e3;
375
+ function useFeature(key, options) {
376
+ const client = useClient();
377
+ const { context, shouldFetch = true } = options ?? {};
378
+ const fallbackValue = client.getFeatureFallback(key);
379
+ const result = useQuery(
380
+ ["feature", key, context],
381
+ async () => {
382
+ return await client.getFeature(key, { context });
383
+ },
384
+ {
385
+ enabled: shouldFetch,
386
+ staleTime: STALE_TIME,
387
+ cacheTime: CACHE_TIME,
388
+ refetchOnWindowFocus: false
389
+ // Feature flags shouldn't refetch on focus
390
+ }
391
+ );
392
+ const { data, ...rest } = result;
393
+ return {
394
+ ...rest,
395
+ feature: data ?? fallbackValue
396
+ };
397
+ }
398
+ function useFeatures(featureNames, options) {
399
+ const client = useClient();
400
+ const { context, shouldFetch = true } = options ?? {};
401
+ const result = useQuery(
402
+ ["features", featureNames.join(","), context],
403
+ async () => {
404
+ const features = await client.getFeatures([...featureNames], { context });
405
+ return features;
406
+ },
407
+ {
408
+ enabled: shouldFetch,
409
+ staleTime: STALE_TIME,
410
+ cacheTime: CACHE_TIME,
411
+ refetchOnWindowFocus: false
412
+ // Feature flags shouldn't refetch on focus
413
+ }
414
+ );
415
+ const { data, ...rest } = result;
416
+ return {
417
+ ...rest,
418
+ features: data ?? {}
419
+ };
420
+ }
421
+
422
+ // src/utils.ts
423
+ function hasValue(value) {
424
+ return value !== void 0 && value !== null;
425
+ }
426
+
427
+ // src/components.tsx
428
+ var import_jsx_runtime2 = require("react/jsx-runtime");
429
+ function SupaFeature({
430
+ feature,
431
+ context,
432
+ shouldFetch = true,
433
+ variations,
434
+ loading
435
+ }) {
436
+ const { feature: featureValue, isLoading } = useFeature(feature, {
437
+ context,
438
+ shouldFetch
439
+ });
440
+ if (isLoading && loading && variations[loading]) {
441
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: variations[loading] });
442
+ }
443
+ if (isLoading) {
444
+ return null;
445
+ }
446
+ if (!hasValue(featureValue)) {
447
+ return null;
448
+ }
449
+ const valueKey = String(featureValue);
450
+ if (variations[valueKey]) {
451
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: variations[valueKey] });
452
+ }
453
+ return null;
454
+ }
455
+ // Annotate the CommonJS export names for ESM import in node:
456
+ 0 && (module.exports = {
457
+ QueryClient,
458
+ SupaFeature,
459
+ SupaProvider,
460
+ getInitialQueryState,
461
+ queryCache,
462
+ useClient,
463
+ useFeature,
464
+ useFeatureContext,
465
+ useFeatures,
466
+ useQuery,
467
+ useQueryClient
468
+ });
469
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/query.ts","../src/hooks.ts","../src/utils.ts","../src/components.tsx"],"sourcesContent":["'use client'\n\nexport * from './types'\nexport * from './hooks'\nexport * from './provider'\nexport * from './query'\nexport * from './components'\n","'use client'\n\nimport React, {\n createContext,\n useContext,\n ReactNode,\n useMemo,\n useCallback,\n useRef,\n useEffect,\n} from 'react'\nimport {\n SupaClient,\n SupaClientConfig as SupaProviderConfig,\n FeatureContext,\n FeatureValue,\n Features,\n SupaToolbarOverrideChange,\n SupaToolbarPluginConfig,\n} from '@supashiphq/javascript-sdk'\nimport { useQueryClient } from './query'\n\ninterface SupaContextValue<TFeatures extends Features<Record<string, FeatureValue>>> {\n client: SupaClient<TFeatures>\n updateContext: (context: FeatureContext, mergeWithExisting?: boolean) => void\n getContext: () => FeatureContext | undefined\n}\n\nconst SupaContext = createContext<SupaContextValue<any> | null>(null)\n\ninterface SupaProviderProps<TFeatures extends Features<Record<string, FeatureValue>>> {\n config: Omit<SupaProviderConfig, 'plugins' | 'toolbar'> & { features: TFeatures }\n toolbar?: SupaToolbarPluginConfig | boolean\n children: ReactNode\n}\n\n// Default toolbar config (stable reference)\nconst DEFAULT_TOOLBAR_CONFIG: SupaToolbarPluginConfig = { enabled: 'auto' }\n\nexport function SupaProvider<TFeatures extends Features<Record<string, FeatureValue>>>({\n config,\n toolbar,\n children,\n}: SupaProviderProps<TFeatures>): React.JSX.Element {\n const queryClient = useQueryClient()\n\n // Use default if toolbar not provided\n const effectiveToolbar = toolbar ?? DEFAULT_TOOLBAR_CONFIG\n\n // Stable callback for toolbar override changes\n const handleOverrideChange = useCallback(\n (\n featureOverride: SupaToolbarOverrideChange,\n allOverrides: Record<string, FeatureValue>\n ): void => {\n // Call user's onOverrideChange if provided\n if (typeof effectiveToolbar === 'object' && effectiveToolbar.onOverrideChange) {\n effectiveToolbar.onOverrideChange(featureOverride, allOverrides)\n }\n\n // Invalidate the query cache for the changed feature to trigger refetch\n if (featureOverride.feature) {\n // Invalidate single feature queries (useFeature)\n queryClient.invalidateQueriesByPrefix(['feature', featureOverride.feature])\n // Invalidate multi-feature queries (useFeatures) that include this feature\n queryClient.invalidateQueriesByPrefix(['features'])\n }\n },\n [effectiveToolbar, queryClient]\n )\n\n // Use ref to persist client across StrictMode double-renders in development\n const clientRef = useRef<SupaClient<TFeatures> | null>(null)\n\n // Initialize client only once to prevent duplicate toolbars in StrictMode\n if (!clientRef.current) {\n // Merge toolbar config with React Query cache invalidation\n const toolbarConfig =\n effectiveToolbar === false\n ? false\n : {\n ...(typeof effectiveToolbar === 'object' ? effectiveToolbar : {}),\n onOverrideChange: handleOverrideChange,\n }\n\n clientRef.current = new SupaClient<TFeatures>({\n ...config,\n toolbar: toolbarConfig,\n })\n }\n\n const client = clientRef.current\n\n // Cleanup client on unmount\n useEffect(() => {\n return () => {\n if (clientRef.current) {\n // Cleanup plugins (which includes toolbar cleanup)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const client = clientRef.current as any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (client.plugins && Array.isArray(client.plugins)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n client.plugins.forEach((plugin: any) => {\n if (plugin.cleanup) {\n plugin.cleanup()\n }\n })\n }\n clientRef.current = null\n }\n }\n }, [])\n\n // Memoized context update function\n const updateContext = useCallback(\n (context: FeatureContext, mergeWithExisting: boolean = true) => {\n client.updateContext(context, mergeWithExisting)\n },\n [client]\n )\n\n // Memoized context getter function\n const getContext = useCallback(() => {\n return client.getContext()\n }, [client])\n\n const contextValue = useMemo(\n () => ({\n client,\n updateContext,\n getContext,\n }),\n [client, updateContext, getContext]\n )\n\n return <SupaContext.Provider value={contextValue}>{children}</SupaContext.Provider>\n}\n\nexport function useClient<\n TFeatures extends Features<Record<string, FeatureValue>>,\n>(): SupaClient<TFeatures> {\n const context = useContext(SupaContext)\n if (!context) {\n throw new Error('useClient must be used within a SupaProvider')\n }\n return context.client as SupaClient<TFeatures>\n}\n\n/**\n * Hook to update the context dynamically\n * Useful when context depends on authentication or other async operations\n */\nexport function useFeatureContext(): Omit<SupaContextValue<any>, 'client'> {\n const context = useContext(SupaContext)\n if (!context) {\n throw new Error('useFeatureContext must be used within a SupaProvider')\n }\n return {\n updateContext: context.updateContext,\n getContext: context.getContext,\n }\n}\n","'use client'\n\nimport { useCallback, useEffect, useReducer, useRef } from 'react'\n\n// Query status types\nexport type QueryStatus = 'idle' | 'loading' | 'success' | 'error'\n\n// Base query state (managed by reducer)\nexport interface BaseQueryState<TData = unknown, TError = Error> {\n status: QueryStatus\n data: TData | undefined\n error: TError | null\n isLoading: boolean\n isSuccess: boolean\n isError: boolean\n isIdle: boolean\n isFetching: boolean\n dataUpdatedAt: number\n}\n\n// Query state with refetch method (returned by useQuery)\nexport interface QueryState<TData = unknown, TError = Error> extends BaseQueryState<TData, TError> {\n refetch: () => Promise<void>\n}\n\n// Initial state factory for queries\nexport function getInitialQueryState<TData, TError>(\n initialData?: TData,\n enabled: boolean = true\n): BaseQueryState<TData, TError> {\n return {\n status: !enabled ? 'idle' : initialData !== undefined ? 'success' : 'idle',\n data: initialData,\n error: null,\n isLoading: enabled && initialData === undefined,\n isSuccess: initialData !== undefined,\n isError: false,\n isIdle: !enabled || initialData === undefined,\n isFetching: false,\n dataUpdatedAt: initialData !== undefined ? Date.now() : 0,\n }\n}\n\n// Query options\nexport interface UseQueryOptions<TData = unknown, TError = Error> {\n enabled?: boolean\n retry?: number | boolean\n retryDelay?: number\n staleTime?: number\n cacheTime?: number\n refetchOnWindowFocus?: boolean\n initialData?: TData\n onSuccess?: (data: TData) => void\n onError?: (error: TError) => void\n onSettled?: (data: TData | undefined, error: TError | null) => void\n}\n\n// Query key type\nexport type QueryKey = unknown[]\n\n// Actions for the query reducer\ntype QueryAction<TData, TError> =\n | { type: 'FETCH_START' }\n | { type: 'FETCH_SUCCESS'; payload: { data: TData } }\n | { type: 'FETCH_ERROR'; payload: { error: TError } }\n\n// Reducer for query state\nfunction queryReducer<TData, TError>(\n state: BaseQueryState<TData, TError>,\n action: QueryAction<TData, TError>\n): BaseQueryState<TData, TError> {\n switch (action.type) {\n case 'FETCH_START':\n return {\n ...state,\n status: state.data === undefined ? 'loading' : state.status,\n isLoading: state.data === undefined,\n isIdle: false,\n isFetching: true,\n }\n case 'FETCH_SUCCESS':\n return {\n ...state,\n status: 'success',\n data: action.payload.data,\n error: null,\n isLoading: false,\n isSuccess: true,\n isError: false,\n isIdle: false,\n isFetching: false,\n dataUpdatedAt: Date.now(),\n }\n case 'FETCH_ERROR':\n return {\n ...state,\n status: 'error',\n error: action.payload.error,\n isLoading: false,\n isSuccess: !!state.data,\n isError: true,\n isIdle: false,\n isFetching: false,\n }\n default:\n return state\n }\n}\n\n// Cache implementation\nclass QueryCache {\n private cache: Map<string, { data: unknown; timestamp: number }> = new Map()\n private timers: Map<string, ReturnType<typeof setTimeout>> = new Map()\n private observers: Map<string, Set<() => void>> = new Map()\n\n getQuery(queryKey: string): unknown {\n const entry = this.cache.get(queryKey)\n return entry ? entry.data : undefined\n }\n\n isStale(queryKey: string, staleTime: number): boolean {\n const entry = this.cache.get(queryKey)\n if (!entry) return true\n return Date.now() - entry.timestamp > staleTime\n }\n\n setQuery(queryKey: string, data: unknown, cacheTime: number = 5 * 60 * 1000): void {\n this.cache.set(queryKey, { data, timestamp: Date.now() })\n\n // Clear previous timer if it exists\n if (this.timers.has(queryKey)) {\n clearTimeout(this.timers.get(queryKey)!)\n }\n\n // Set new timer for cache expiration\n const timer = setTimeout(() => {\n this.cache.delete(queryKey)\n this.timers.delete(queryKey)\n }, cacheTime)\n\n this.timers.set(queryKey, timer)\n }\n\n subscribe(queryKey: string, callback: () => void): () => void {\n if (!this.observers.has(queryKey)) {\n this.observers.set(queryKey, new Set())\n }\n this.observers.get(queryKey)!.add(callback)\n\n // Return unsubscribe function\n return () => {\n const callbacks = this.observers.get(queryKey)\n if (callbacks) {\n callbacks.delete(callback)\n if (callbacks.size === 0) {\n this.observers.delete(queryKey)\n }\n }\n }\n }\n\n private notifyObservers(queryKey: string): void {\n const callbacks = this.observers.get(queryKey)\n if (callbacks) {\n callbacks.forEach(callback => callback())\n }\n }\n\n invalidateQuery(queryKey: string): void {\n this.cache.delete(queryKey)\n if (this.timers.has(queryKey)) {\n clearTimeout(this.timers.get(queryKey)!)\n this.timers.delete(queryKey)\n }\n this.notifyObservers(queryKey)\n }\n\n invalidateQueries(queryKeyPrefix: string): void {\n for (const [key] of this.cache) {\n if (key.startsWith(queryKeyPrefix)) {\n this.invalidateQuery(key)\n }\n }\n }\n\n clear(): void {\n this.cache.clear()\n this.timers.forEach(timer => clearTimeout(timer))\n this.timers.clear()\n this.observers.clear()\n }\n}\n\n// Singleton instance of QueryCache\nexport const queryCache = new QueryCache()\n\n// Query Client class for managing queries\nexport class QueryClient {\n private cache: QueryCache\n\n constructor(cache: QueryCache = queryCache) {\n this.cache = cache\n }\n\n /**\n * Invalidates a specific query by its query key\n * This will remove it from cache and trigger refetch in all components using this query\n */\n invalidateQueries(queryKey: QueryKey): void {\n const stringifiedKey = stableStringifyQueryKey(queryKey)\n this.cache.invalidateQuery(stringifiedKey)\n }\n\n /**\n * Invalidates all queries matching a partial query key\n * For example, invalidateQueriesByPrefix(['feature']) will invalidate all feature queries\n */\n invalidateQueriesByPrefix(queryKeyPrefix: QueryKey): void {\n const stringifiedPrefix = stableStringifyQueryKey(queryKeyPrefix)\n this.cache.invalidateQueries(stringifiedPrefix.slice(0, -1)) // Remove closing bracket\n }\n\n /**\n * Clears all queries from the cache\n */\n clear(): void {\n this.cache.clear()\n }\n}\n\n// Singleton instance of QueryClient\nconst queryClient = new QueryClient()\n\n// Hook to access the query client\nexport function useQueryClient(): QueryClient {\n return queryClient\n}\n\n// Stable stringify for query keys\nfunction stableStringifyQueryKey(queryKey: QueryKey): string {\n return JSON.stringify(queryKey, (_, val) => (typeof val === 'function' ? val.toString() : val))\n}\n\n// The useQuery hook\nexport function useQuery<TData = unknown, TError = Error>(\n queryKey: QueryKey,\n queryFn: () => Promise<TData>,\n options: UseQueryOptions<TData, TError> = {}\n): QueryState<TData, TError> {\n const {\n enabled = true,\n retry = 3,\n retryDelay = 1000,\n staleTime = 0,\n cacheTime = 5 * 60 * 1000,\n refetchOnWindowFocus = true,\n initialData,\n } = options\n\n const stringifiedQueryKey = stableStringifyQueryKey(queryKey)\n const queryFnRef = useRef(queryFn)\n const optionsRef = useRef(options)\n\n // Update refs when dependencies change\n useEffect(() => {\n queryFnRef.current = queryFn\n optionsRef.current = options\n }, [queryFn, options])\n\n // Initialize state from cache or with default\n const cachedData = queryCache.getQuery(stringifiedQueryKey)\n const isStale = queryCache.isStale(stringifiedQueryKey, staleTime)\n\n // Use cached data for initial state even if stale to prevent unnecessary loading states\n const initialStateData = cachedData !== undefined ? (cachedData as TData) : initialData\n const initialState = getInitialQueryState<TData, TError>(initialStateData, enabled)\n const [state, dispatch] = useReducer(queryReducer<TData, TError>, initialState)\n\n const executeFetch = useCallback(async (): Promise<void> => {\n if (!enabled) return\n\n dispatch({ type: 'FETCH_START' })\n\n let retryCount = 0\n const maxRetries = typeof retry === 'boolean' ? (retry ? 3 : 0) : retry\n\n const runQuery = async (): Promise<void> => {\n try {\n const data = await queryFnRef.current()\n\n // Update cache\n queryCache.setQuery(stringifiedQueryKey, data, cacheTime)\n\n dispatch({ type: 'FETCH_SUCCESS', payload: { data } })\n\n if (optionsRef.current.onSuccess) {\n optionsRef.current.onSuccess(data)\n }\n\n if (optionsRef.current.onSettled) {\n optionsRef.current.onSettled(data, null)\n }\n } catch (err) {\n const error = err as TError\n\n if (retryCount < maxRetries) {\n retryCount++\n await new Promise(resolve => setTimeout(resolve, retryDelay))\n return runQuery()\n }\n\n dispatch({ type: 'FETCH_ERROR', payload: { error } })\n\n if (optionsRef.current.onError) {\n optionsRef.current.onError(error)\n }\n\n if (optionsRef.current.onSettled) {\n optionsRef.current.onSettled(undefined, error)\n }\n }\n }\n\n await runQuery()\n }, [enabled, stringifiedQueryKey, retry, retryDelay, cacheTime])\n\n // Execute query on mount and when dependencies change\n useEffect(() => {\n if (enabled && (isStale || state.data === undefined)) {\n executeFetch()\n }\n }, [enabled, isStale, executeFetch, state.data])\n\n // Handle window focus\n useEffect(() => {\n if (!refetchOnWindowFocus) return\n\n const handleFocus = (): void => {\n if (enabled && isStale) {\n executeFetch()\n }\n }\n\n window.addEventListener('focus', handleFocus)\n return () => window.removeEventListener('focus', handleFocus)\n }, [enabled, isStale, executeFetch, refetchOnWindowFocus])\n\n // Subscribe to cache invalidations\n useEffect(() => {\n const unsubscribe = queryCache.subscribe(stringifiedQueryKey, () => {\n // When query is invalidated, refetch\n executeFetch()\n })\n\n return unsubscribe\n }, [stringifiedQueryKey, executeFetch])\n\n // Memoize refetch function\n const refetch = useCallback(async () => {\n await executeFetch()\n }, [executeFetch])\n\n return {\n ...state,\n refetch,\n }\n}\n","'use client'\n\nimport { useClient } from './provider'\nimport { useQuery, QueryState } from './query'\nimport { FeatureValue, FeatureContext } from '@supashiphq/javascript-sdk'\nimport { FeatureKey, TypedFeatures, Features } from './types'\n\n// Custom return types for hooks with generics\nexport interface UseFeatureResult<T extends FeatureValue>\n extends Omit<QueryState<T | null>, 'data'> {\n feature: T | null\n}\n\nexport interface UseFeaturesResult<T extends Record<string, FeatureValue>>\n extends Omit<QueryState<T>, 'data'> {\n features: T\n}\n\nconst STALE_TIME = 5 * 60 * 1000 // 5 minutes\nconst CACHE_TIME = 10 * 60 * 1000 // 10 minutes\n\n/**\n * Returns the state of a given feature for the current context.\n *\n * @example\n * ```ts\n * function MyComponent() {\n * const { feature, isLoading } = useFeature('my-feature')\n * if (isLoading) return <div>Loading...</div>\n * return <div>Feature value: {String(feature)}</div>\n * }\n * ```\n *\n * @remarks\n * For type-safe feature flags, augment the Features interface:\n * ```ts\n * declare module '@supashiphq/react-sdk' {\n * interface Features {\n * 'my-feature': { value: 'variant-a' | 'variant-b' }\n * 'dark-mode': { value: boolean }\n * }\n * }\n *\n * // Now get full type safety:\n * const { feature } = useFeature('my-feature')\n * // feature is typed as 'variant-a' | 'variant-b'\n * ```\n */\nexport function useFeature<TKey extends FeatureKey>(\n key: TKey,\n options?: { context?: FeatureContext; shouldFetch?: boolean }\n): TypedFeatures[TKey] {\n const client = useClient()\n const { context, shouldFetch = true } = options ?? {}\n\n // Get the fallback value from feature definitions\n const fallbackValue = client.getFeatureFallback(key as string)\n\n const result = useQuery(\n ['feature', key, context],\n async (): Promise<FeatureValue> => {\n return await client.getFeature(key as string, { context })\n },\n {\n enabled: shouldFetch,\n staleTime: STALE_TIME,\n cacheTime: CACHE_TIME,\n refetchOnWindowFocus: false, // Feature flags shouldn't refetch on focus\n }\n )\n\n const { data, ...rest } = result\n return {\n ...rest,\n feature: data ?? fallbackValue,\n } as TypedFeatures[TKey]\n}\n\n/**\n * Extract feature value type from Features interface\n */\ntype ExtractFeatureValue<T> = T extends { value: infer V } ? V : FeatureValue\n\n/**\n * Returns the state of multiple features for the current context.\n *\n * @example\n * ```ts\n * function MyComponent() {\n * const { features, isLoading } = useFeatures(['feature-a', 'feature-b'])\n * if (isLoading) return <div>Loading...</div>\n * return <div>Feature A: {String(features['feature-a'])}</div>\n * }\n * ```\n */\nexport function useFeatures<TKeys extends readonly FeatureKey[]>(\n featureNames: TKeys,\n options?: {\n context?: FeatureContext\n shouldFetch?: boolean\n }\n): UseFeaturesResult<{\n [K in TKeys[number]]: K extends keyof Features\n ? ExtractFeatureValue<Features[K]>\n : FeatureValue | null\n}> {\n const client = useClient()\n const { context, shouldFetch = true } = options ?? {}\n\n type ResultType = {\n [K in TKeys[number]]: K extends keyof Features\n ? ExtractFeatureValue<Features[K]>\n : FeatureValue | null\n }\n\n const result = useQuery(\n ['features', featureNames.join(','), context],\n async (): Promise<ResultType> => {\n const features = await client.getFeatures([...featureNames] as string[], { context })\n return features as ResultType\n },\n {\n enabled: shouldFetch,\n staleTime: STALE_TIME,\n cacheTime: CACHE_TIME,\n refetchOnWindowFocus: false, // Feature flags shouldn't refetch on focus\n }\n )\n\n const { data, ...rest } = result\n return {\n ...rest,\n features: data ?? ({} as ResultType),\n }\n}\n","export function hasValue(value: unknown): boolean {\n return value !== undefined && value !== null\n}\n","'use client'\n\nimport React, { ReactNode } from 'react'\nimport { useFeature } from './hooks'\nimport { FeatureKey, FeatureContext } from './types'\nimport { hasValue } from './utils'\n\nexport interface SupaFeatureProps {\n /**\n * The feature flag key to evaluate\n */\n feature: FeatureKey\n\n /**\n * Context for feature evaluation\n */\n context?: FeatureContext\n\n /**\n * Whether to fetch the feature (default: true)\n */\n shouldFetch?: boolean\n\n /**\n * Variations object mapping feature values/keys to JSX elements\n */\n variations: Record<string, ReactNode>\n\n /**\n * Key in variations object to use for loading state\n */\n loading?: string\n}\n\n/**\n * SupaFeature component that conditionally renders variations based on feature flag values.\n * Uses the default value defined in the client configuration.\n *\n * @example\n * ```tsx\n * <SupaFeature\n * feature=\"new-header\"\n * variations={{\n * \"true\": <NewHeader />,\n * \"false\": <OldHeader />,\n * loading: <HeaderSkeleton />\n * }}\n * />\n * ```\n */\nexport function SupaFeature({\n feature,\n context,\n shouldFetch = true,\n variations,\n loading,\n}: SupaFeatureProps): React.JSX.Element | null {\n const { feature: featureValue, isLoading } = useFeature(feature, {\n context,\n shouldFetch,\n })\n\n // Show loading state if provided and currently loading\n if (isLoading && loading && variations[loading]) {\n return <>{variations[loading]}</>\n }\n\n // Don't render anything if still loading and no loader provided\n if (isLoading) {\n return null\n }\n\n // Don't render anything if no feature value (client config should provide defaults)\n if (!hasValue(featureValue)) {\n return null\n }\n\n // Convert feature value to string for object key lookup\n const valueKey = String(featureValue)\n\n // Find matching variation by exact key match\n if (variations[valueKey]) {\n return <>{variations[valueKey]}</>\n }\n\n // Don't render anything if no variation matches\n return null\n}\n"],"mappings":"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","names":["import_react","queryClient","client","import_jsx_runtime"]}