@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/LICENSE +21 -0
- package/README.md +724 -0
- package/dist/index.d.mts +260 -0
- package/dist/index.d.ts +260 -0
- package/dist/index.js +469 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +442 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +79 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { FeaturesWithFallbacks, FeatureValue, FeatureContext, Features as Features$1, SupaClientConfig, SupaToolbarPluginConfig, SupaClient } from '@supashiphq/javascript-sdk';
|
|
2
|
+
export { FeatureContext, FeatureValue, FeaturesWithFallbacks, SupaPlugin, SupaClientConfig as SupaProviderConfig, SupaToolbarPluginConfig, SupaToolbarPosition } from '@supashiphq/javascript-sdk';
|
|
3
|
+
import React, { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
type QueryStatus = 'idle' | 'loading' | 'success' | 'error';
|
|
6
|
+
interface BaseQueryState<TData = unknown, TError = Error> {
|
|
7
|
+
status: QueryStatus;
|
|
8
|
+
data: TData | undefined;
|
|
9
|
+
error: TError | null;
|
|
10
|
+
isLoading: boolean;
|
|
11
|
+
isSuccess: boolean;
|
|
12
|
+
isError: boolean;
|
|
13
|
+
isIdle: boolean;
|
|
14
|
+
isFetching: boolean;
|
|
15
|
+
dataUpdatedAt: number;
|
|
16
|
+
}
|
|
17
|
+
interface QueryState<TData = unknown, TError = Error> extends BaseQueryState<TData, TError> {
|
|
18
|
+
refetch: () => Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
declare function getInitialQueryState<TData, TError>(initialData?: TData, enabled?: boolean): BaseQueryState<TData, TError>;
|
|
21
|
+
interface UseQueryOptions<TData = unknown, TError = Error> {
|
|
22
|
+
enabled?: boolean;
|
|
23
|
+
retry?: number | boolean;
|
|
24
|
+
retryDelay?: number;
|
|
25
|
+
staleTime?: number;
|
|
26
|
+
cacheTime?: number;
|
|
27
|
+
refetchOnWindowFocus?: boolean;
|
|
28
|
+
initialData?: TData;
|
|
29
|
+
onSuccess?: (data: TData) => void;
|
|
30
|
+
onError?: (error: TError) => void;
|
|
31
|
+
onSettled?: (data: TData | undefined, error: TError | null) => void;
|
|
32
|
+
}
|
|
33
|
+
type QueryKey = unknown[];
|
|
34
|
+
declare class QueryCache {
|
|
35
|
+
private cache;
|
|
36
|
+
private timers;
|
|
37
|
+
private observers;
|
|
38
|
+
getQuery(queryKey: string): unknown;
|
|
39
|
+
isStale(queryKey: string, staleTime: number): boolean;
|
|
40
|
+
setQuery(queryKey: string, data: unknown, cacheTime?: number): void;
|
|
41
|
+
subscribe(queryKey: string, callback: () => void): () => void;
|
|
42
|
+
private notifyObservers;
|
|
43
|
+
invalidateQuery(queryKey: string): void;
|
|
44
|
+
invalidateQueries(queryKeyPrefix: string): void;
|
|
45
|
+
clear(): void;
|
|
46
|
+
}
|
|
47
|
+
declare const queryCache: QueryCache;
|
|
48
|
+
declare class QueryClient {
|
|
49
|
+
private cache;
|
|
50
|
+
constructor(cache?: QueryCache);
|
|
51
|
+
/**
|
|
52
|
+
* Invalidates a specific query by its query key
|
|
53
|
+
* This will remove it from cache and trigger refetch in all components using this query
|
|
54
|
+
*/
|
|
55
|
+
invalidateQueries(queryKey: QueryKey): void;
|
|
56
|
+
/**
|
|
57
|
+
* Invalidates all queries matching a partial query key
|
|
58
|
+
* For example, invalidateQueriesByPrefix(['feature']) will invalidate all feature queries
|
|
59
|
+
*/
|
|
60
|
+
invalidateQueriesByPrefix(queryKeyPrefix: QueryKey): void;
|
|
61
|
+
/**
|
|
62
|
+
* Clears all queries from the cache
|
|
63
|
+
*/
|
|
64
|
+
clear(): void;
|
|
65
|
+
}
|
|
66
|
+
declare function useQueryClient(): QueryClient;
|
|
67
|
+
declare function useQuery<TData = unknown, TError = Error>(queryKey: QueryKey, queryFn: () => Promise<TData>, options?: UseQueryOptions<TData, TError>): QueryState<TData, TError>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Helper type to infer feature types from your feature config for module augmentation.
|
|
71
|
+
*
|
|
72
|
+
* ⚠️ Remember: Define features with `satisfies FeaturesWithFallbacks`, not type annotation
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* import { FeaturesWithFallbacks, InferFeatures } from '@supashiphq/react-sdk'
|
|
77
|
+
*
|
|
78
|
+
* // ✅ Use satisfies to preserve literal types
|
|
79
|
+
* export const FEATURE_FLAGS = {
|
|
80
|
+
* 'dark-mode': false,
|
|
81
|
+
* 'ui-config': { variant: 'a' as const }
|
|
82
|
+
* } satisfies FeaturesWithFallbacks
|
|
83
|
+
*
|
|
84
|
+
* declare module '@supashiphq/react-sdk' {
|
|
85
|
+
* interface Features extends InferFeatures<typeof FEATURE_FLAGS> {}
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
type InferFeatures<T extends FeaturesWithFallbacks> = {
|
|
90
|
+
[K in keyof T]: T[K];
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Interface to be augmented by users for type-safe feature flags.
|
|
94
|
+
* Use InferFeatures helper to enable type-safe feature access.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* // lib/features.ts
|
|
99
|
+
* import { FeaturesWithFallbacks, InferFeatures } from '@supashiphq/react-sdk'
|
|
100
|
+
*
|
|
101
|
+
* export const FEATURE_FLAGS = {
|
|
102
|
+
* 'dark-mode': false,
|
|
103
|
+
* 'ui-config': {
|
|
104
|
+
* variant: 'a' as const,
|
|
105
|
+
* showWelcome: true,
|
|
106
|
+
* },
|
|
107
|
+
* } satisfies FeaturesWithFallbacks
|
|
108
|
+
*
|
|
109
|
+
* declare module '@supashiphq/react-sdk' {
|
|
110
|
+
* interface Features extends InferFeatures<typeof FEATURE_FLAGS> {}
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
interface Features {
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Return type for useFeature hook with proper typing based on feature key
|
|
118
|
+
*/
|
|
119
|
+
type TypedFeatures = keyof Features extends never ? {
|
|
120
|
+
[key: string]: Omit<QueryState<FeatureValue | null>, 'data'> & {
|
|
121
|
+
feature: FeatureValue | null;
|
|
122
|
+
};
|
|
123
|
+
} : {
|
|
124
|
+
[K in keyof Features]: Omit<QueryState<Features[K]>, 'data'> & {
|
|
125
|
+
feature: Features[K];
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
type FeatureKey = keyof Features extends never ? string : keyof Features;
|
|
129
|
+
interface UseFeatureOptions {
|
|
130
|
+
context?: FeatureContext;
|
|
131
|
+
shouldFetch?: boolean;
|
|
132
|
+
}
|
|
133
|
+
interface UseFeaturesOptions {
|
|
134
|
+
context?: FeatureContext;
|
|
135
|
+
shouldFetch?: boolean;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
interface UseFeatureResult<T extends FeatureValue> extends Omit<QueryState<T | null>, 'data'> {
|
|
139
|
+
feature: T | null;
|
|
140
|
+
}
|
|
141
|
+
interface UseFeaturesResult<T extends Record<string, FeatureValue>> extends Omit<QueryState<T>, 'data'> {
|
|
142
|
+
features: T;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Returns the state of a given feature for the current context.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* function MyComponent() {
|
|
150
|
+
* const { feature, isLoading } = useFeature('my-feature')
|
|
151
|
+
* if (isLoading) return <div>Loading...</div>
|
|
152
|
+
* return <div>Feature value: {String(feature)}</div>
|
|
153
|
+
* }
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* @remarks
|
|
157
|
+
* For type-safe feature flags, augment the Features interface:
|
|
158
|
+
* ```ts
|
|
159
|
+
* declare module '@supashiphq/react-sdk' {
|
|
160
|
+
* interface Features {
|
|
161
|
+
* 'my-feature': { value: 'variant-a' | 'variant-b' }
|
|
162
|
+
* 'dark-mode': { value: boolean }
|
|
163
|
+
* }
|
|
164
|
+
* }
|
|
165
|
+
*
|
|
166
|
+
* // Now get full type safety:
|
|
167
|
+
* const { feature } = useFeature('my-feature')
|
|
168
|
+
* // feature is typed as 'variant-a' | 'variant-b'
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
declare function useFeature<TKey extends FeatureKey>(key: TKey, options?: {
|
|
172
|
+
context?: FeatureContext;
|
|
173
|
+
shouldFetch?: boolean;
|
|
174
|
+
}): TypedFeatures[TKey];
|
|
175
|
+
/**
|
|
176
|
+
* Extract feature value type from Features interface
|
|
177
|
+
*/
|
|
178
|
+
type ExtractFeatureValue<T> = T extends {
|
|
179
|
+
value: infer V;
|
|
180
|
+
} ? V : FeatureValue;
|
|
181
|
+
/**
|
|
182
|
+
* Returns the state of multiple features for the current context.
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```ts
|
|
186
|
+
* function MyComponent() {
|
|
187
|
+
* const { features, isLoading } = useFeatures(['feature-a', 'feature-b'])
|
|
188
|
+
* if (isLoading) return <div>Loading...</div>
|
|
189
|
+
* return <div>Feature A: {String(features['feature-a'])}</div>
|
|
190
|
+
* }
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
declare function useFeatures<TKeys extends readonly FeatureKey[]>(featureNames: TKeys, options?: {
|
|
194
|
+
context?: FeatureContext;
|
|
195
|
+
shouldFetch?: boolean;
|
|
196
|
+
}): UseFeaturesResult<{
|
|
197
|
+
[K in TKeys[number]]: K extends keyof Features ? ExtractFeatureValue<Features[K]> : FeatureValue | null;
|
|
198
|
+
}>;
|
|
199
|
+
|
|
200
|
+
interface SupaContextValue<TFeatures extends Features$1<Record<string, FeatureValue>>> {
|
|
201
|
+
client: SupaClient<TFeatures>;
|
|
202
|
+
updateContext: (context: FeatureContext, mergeWithExisting?: boolean) => void;
|
|
203
|
+
getContext: () => FeatureContext | undefined;
|
|
204
|
+
}
|
|
205
|
+
interface SupaProviderProps<TFeatures extends Features$1<Record<string, FeatureValue>>> {
|
|
206
|
+
config: Omit<SupaClientConfig, 'plugins' | 'toolbar'> & {
|
|
207
|
+
features: TFeatures;
|
|
208
|
+
};
|
|
209
|
+
toolbar?: SupaToolbarPluginConfig | boolean;
|
|
210
|
+
children: ReactNode;
|
|
211
|
+
}
|
|
212
|
+
declare function SupaProvider<TFeatures extends Features$1<Record<string, FeatureValue>>>({ config, toolbar, children, }: SupaProviderProps<TFeatures>): React.JSX.Element;
|
|
213
|
+
declare function useClient<TFeatures extends Features$1<Record<string, FeatureValue>>>(): SupaClient<TFeatures>;
|
|
214
|
+
/**
|
|
215
|
+
* Hook to update the context dynamically
|
|
216
|
+
* Useful when context depends on authentication or other async operations
|
|
217
|
+
*/
|
|
218
|
+
declare function useFeatureContext(): Omit<SupaContextValue<any>, 'client'>;
|
|
219
|
+
|
|
220
|
+
interface SupaFeatureProps {
|
|
221
|
+
/**
|
|
222
|
+
* The feature flag key to evaluate
|
|
223
|
+
*/
|
|
224
|
+
feature: FeatureKey;
|
|
225
|
+
/**
|
|
226
|
+
* Context for feature evaluation
|
|
227
|
+
*/
|
|
228
|
+
context?: FeatureContext;
|
|
229
|
+
/**
|
|
230
|
+
* Whether to fetch the feature (default: true)
|
|
231
|
+
*/
|
|
232
|
+
shouldFetch?: boolean;
|
|
233
|
+
/**
|
|
234
|
+
* Variations object mapping feature values/keys to JSX elements
|
|
235
|
+
*/
|
|
236
|
+
variations: Record<string, ReactNode>;
|
|
237
|
+
/**
|
|
238
|
+
* Key in variations object to use for loading state
|
|
239
|
+
*/
|
|
240
|
+
loading?: string;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* SupaFeature component that conditionally renders variations based on feature flag values.
|
|
244
|
+
* Uses the default value defined in the client configuration.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```tsx
|
|
248
|
+
* <SupaFeature
|
|
249
|
+
* feature="new-header"
|
|
250
|
+
* variations={{
|
|
251
|
+
* "true": <NewHeader />,
|
|
252
|
+
* "false": <OldHeader />,
|
|
253
|
+
* loading: <HeaderSkeleton />
|
|
254
|
+
* }}
|
|
255
|
+
* />
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
declare function SupaFeature({ feature, context, shouldFetch, variations, loading, }: SupaFeatureProps): React.JSX.Element | null;
|
|
259
|
+
|
|
260
|
+
export { type BaseQueryState, type FeatureKey, type Features, type InferFeatures, QueryClient, type QueryKey, type QueryState, type QueryStatus, SupaFeature, type SupaFeatureProps, SupaProvider, type TypedFeatures, type UseFeatureOptions, type UseFeatureResult, type UseFeaturesOptions, type UseFeaturesResult, type UseQueryOptions, getInitialQueryState, queryCache, useClient, useFeature, useFeatureContext, useFeatures, useQuery, useQueryClient };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { FeaturesWithFallbacks, FeatureValue, FeatureContext, Features as Features$1, SupaClientConfig, SupaToolbarPluginConfig, SupaClient } from '@supashiphq/javascript-sdk';
|
|
2
|
+
export { FeatureContext, FeatureValue, FeaturesWithFallbacks, SupaPlugin, SupaClientConfig as SupaProviderConfig, SupaToolbarPluginConfig, SupaToolbarPosition } from '@supashiphq/javascript-sdk';
|
|
3
|
+
import React, { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
type QueryStatus = 'idle' | 'loading' | 'success' | 'error';
|
|
6
|
+
interface BaseQueryState<TData = unknown, TError = Error> {
|
|
7
|
+
status: QueryStatus;
|
|
8
|
+
data: TData | undefined;
|
|
9
|
+
error: TError | null;
|
|
10
|
+
isLoading: boolean;
|
|
11
|
+
isSuccess: boolean;
|
|
12
|
+
isError: boolean;
|
|
13
|
+
isIdle: boolean;
|
|
14
|
+
isFetching: boolean;
|
|
15
|
+
dataUpdatedAt: number;
|
|
16
|
+
}
|
|
17
|
+
interface QueryState<TData = unknown, TError = Error> extends BaseQueryState<TData, TError> {
|
|
18
|
+
refetch: () => Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
declare function getInitialQueryState<TData, TError>(initialData?: TData, enabled?: boolean): BaseQueryState<TData, TError>;
|
|
21
|
+
interface UseQueryOptions<TData = unknown, TError = Error> {
|
|
22
|
+
enabled?: boolean;
|
|
23
|
+
retry?: number | boolean;
|
|
24
|
+
retryDelay?: number;
|
|
25
|
+
staleTime?: number;
|
|
26
|
+
cacheTime?: number;
|
|
27
|
+
refetchOnWindowFocus?: boolean;
|
|
28
|
+
initialData?: TData;
|
|
29
|
+
onSuccess?: (data: TData) => void;
|
|
30
|
+
onError?: (error: TError) => void;
|
|
31
|
+
onSettled?: (data: TData | undefined, error: TError | null) => void;
|
|
32
|
+
}
|
|
33
|
+
type QueryKey = unknown[];
|
|
34
|
+
declare class QueryCache {
|
|
35
|
+
private cache;
|
|
36
|
+
private timers;
|
|
37
|
+
private observers;
|
|
38
|
+
getQuery(queryKey: string): unknown;
|
|
39
|
+
isStale(queryKey: string, staleTime: number): boolean;
|
|
40
|
+
setQuery(queryKey: string, data: unknown, cacheTime?: number): void;
|
|
41
|
+
subscribe(queryKey: string, callback: () => void): () => void;
|
|
42
|
+
private notifyObservers;
|
|
43
|
+
invalidateQuery(queryKey: string): void;
|
|
44
|
+
invalidateQueries(queryKeyPrefix: string): void;
|
|
45
|
+
clear(): void;
|
|
46
|
+
}
|
|
47
|
+
declare const queryCache: QueryCache;
|
|
48
|
+
declare class QueryClient {
|
|
49
|
+
private cache;
|
|
50
|
+
constructor(cache?: QueryCache);
|
|
51
|
+
/**
|
|
52
|
+
* Invalidates a specific query by its query key
|
|
53
|
+
* This will remove it from cache and trigger refetch in all components using this query
|
|
54
|
+
*/
|
|
55
|
+
invalidateQueries(queryKey: QueryKey): void;
|
|
56
|
+
/**
|
|
57
|
+
* Invalidates all queries matching a partial query key
|
|
58
|
+
* For example, invalidateQueriesByPrefix(['feature']) will invalidate all feature queries
|
|
59
|
+
*/
|
|
60
|
+
invalidateQueriesByPrefix(queryKeyPrefix: QueryKey): void;
|
|
61
|
+
/**
|
|
62
|
+
* Clears all queries from the cache
|
|
63
|
+
*/
|
|
64
|
+
clear(): void;
|
|
65
|
+
}
|
|
66
|
+
declare function useQueryClient(): QueryClient;
|
|
67
|
+
declare function useQuery<TData = unknown, TError = Error>(queryKey: QueryKey, queryFn: () => Promise<TData>, options?: UseQueryOptions<TData, TError>): QueryState<TData, TError>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Helper type to infer feature types from your feature config for module augmentation.
|
|
71
|
+
*
|
|
72
|
+
* ⚠️ Remember: Define features with `satisfies FeaturesWithFallbacks`, not type annotation
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* import { FeaturesWithFallbacks, InferFeatures } from '@supashiphq/react-sdk'
|
|
77
|
+
*
|
|
78
|
+
* // ✅ Use satisfies to preserve literal types
|
|
79
|
+
* export const FEATURE_FLAGS = {
|
|
80
|
+
* 'dark-mode': false,
|
|
81
|
+
* 'ui-config': { variant: 'a' as const }
|
|
82
|
+
* } satisfies FeaturesWithFallbacks
|
|
83
|
+
*
|
|
84
|
+
* declare module '@supashiphq/react-sdk' {
|
|
85
|
+
* interface Features extends InferFeatures<typeof FEATURE_FLAGS> {}
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
type InferFeatures<T extends FeaturesWithFallbacks> = {
|
|
90
|
+
[K in keyof T]: T[K];
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Interface to be augmented by users for type-safe feature flags.
|
|
94
|
+
* Use InferFeatures helper to enable type-safe feature access.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* // lib/features.ts
|
|
99
|
+
* import { FeaturesWithFallbacks, InferFeatures } from '@supashiphq/react-sdk'
|
|
100
|
+
*
|
|
101
|
+
* export const FEATURE_FLAGS = {
|
|
102
|
+
* 'dark-mode': false,
|
|
103
|
+
* 'ui-config': {
|
|
104
|
+
* variant: 'a' as const,
|
|
105
|
+
* showWelcome: true,
|
|
106
|
+
* },
|
|
107
|
+
* } satisfies FeaturesWithFallbacks
|
|
108
|
+
*
|
|
109
|
+
* declare module '@supashiphq/react-sdk' {
|
|
110
|
+
* interface Features extends InferFeatures<typeof FEATURE_FLAGS> {}
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
interface Features {
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Return type for useFeature hook with proper typing based on feature key
|
|
118
|
+
*/
|
|
119
|
+
type TypedFeatures = keyof Features extends never ? {
|
|
120
|
+
[key: string]: Omit<QueryState<FeatureValue | null>, 'data'> & {
|
|
121
|
+
feature: FeatureValue | null;
|
|
122
|
+
};
|
|
123
|
+
} : {
|
|
124
|
+
[K in keyof Features]: Omit<QueryState<Features[K]>, 'data'> & {
|
|
125
|
+
feature: Features[K];
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
type FeatureKey = keyof Features extends never ? string : keyof Features;
|
|
129
|
+
interface UseFeatureOptions {
|
|
130
|
+
context?: FeatureContext;
|
|
131
|
+
shouldFetch?: boolean;
|
|
132
|
+
}
|
|
133
|
+
interface UseFeaturesOptions {
|
|
134
|
+
context?: FeatureContext;
|
|
135
|
+
shouldFetch?: boolean;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
interface UseFeatureResult<T extends FeatureValue> extends Omit<QueryState<T | null>, 'data'> {
|
|
139
|
+
feature: T | null;
|
|
140
|
+
}
|
|
141
|
+
interface UseFeaturesResult<T extends Record<string, FeatureValue>> extends Omit<QueryState<T>, 'data'> {
|
|
142
|
+
features: T;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Returns the state of a given feature for the current context.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* function MyComponent() {
|
|
150
|
+
* const { feature, isLoading } = useFeature('my-feature')
|
|
151
|
+
* if (isLoading) return <div>Loading...</div>
|
|
152
|
+
* return <div>Feature value: {String(feature)}</div>
|
|
153
|
+
* }
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* @remarks
|
|
157
|
+
* For type-safe feature flags, augment the Features interface:
|
|
158
|
+
* ```ts
|
|
159
|
+
* declare module '@supashiphq/react-sdk' {
|
|
160
|
+
* interface Features {
|
|
161
|
+
* 'my-feature': { value: 'variant-a' | 'variant-b' }
|
|
162
|
+
* 'dark-mode': { value: boolean }
|
|
163
|
+
* }
|
|
164
|
+
* }
|
|
165
|
+
*
|
|
166
|
+
* // Now get full type safety:
|
|
167
|
+
* const { feature } = useFeature('my-feature')
|
|
168
|
+
* // feature is typed as 'variant-a' | 'variant-b'
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
declare function useFeature<TKey extends FeatureKey>(key: TKey, options?: {
|
|
172
|
+
context?: FeatureContext;
|
|
173
|
+
shouldFetch?: boolean;
|
|
174
|
+
}): TypedFeatures[TKey];
|
|
175
|
+
/**
|
|
176
|
+
* Extract feature value type from Features interface
|
|
177
|
+
*/
|
|
178
|
+
type ExtractFeatureValue<T> = T extends {
|
|
179
|
+
value: infer V;
|
|
180
|
+
} ? V : FeatureValue;
|
|
181
|
+
/**
|
|
182
|
+
* Returns the state of multiple features for the current context.
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```ts
|
|
186
|
+
* function MyComponent() {
|
|
187
|
+
* const { features, isLoading } = useFeatures(['feature-a', 'feature-b'])
|
|
188
|
+
* if (isLoading) return <div>Loading...</div>
|
|
189
|
+
* return <div>Feature A: {String(features['feature-a'])}</div>
|
|
190
|
+
* }
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
declare function useFeatures<TKeys extends readonly FeatureKey[]>(featureNames: TKeys, options?: {
|
|
194
|
+
context?: FeatureContext;
|
|
195
|
+
shouldFetch?: boolean;
|
|
196
|
+
}): UseFeaturesResult<{
|
|
197
|
+
[K in TKeys[number]]: K extends keyof Features ? ExtractFeatureValue<Features[K]> : FeatureValue | null;
|
|
198
|
+
}>;
|
|
199
|
+
|
|
200
|
+
interface SupaContextValue<TFeatures extends Features$1<Record<string, FeatureValue>>> {
|
|
201
|
+
client: SupaClient<TFeatures>;
|
|
202
|
+
updateContext: (context: FeatureContext, mergeWithExisting?: boolean) => void;
|
|
203
|
+
getContext: () => FeatureContext | undefined;
|
|
204
|
+
}
|
|
205
|
+
interface SupaProviderProps<TFeatures extends Features$1<Record<string, FeatureValue>>> {
|
|
206
|
+
config: Omit<SupaClientConfig, 'plugins' | 'toolbar'> & {
|
|
207
|
+
features: TFeatures;
|
|
208
|
+
};
|
|
209
|
+
toolbar?: SupaToolbarPluginConfig | boolean;
|
|
210
|
+
children: ReactNode;
|
|
211
|
+
}
|
|
212
|
+
declare function SupaProvider<TFeatures extends Features$1<Record<string, FeatureValue>>>({ config, toolbar, children, }: SupaProviderProps<TFeatures>): React.JSX.Element;
|
|
213
|
+
declare function useClient<TFeatures extends Features$1<Record<string, FeatureValue>>>(): SupaClient<TFeatures>;
|
|
214
|
+
/**
|
|
215
|
+
* Hook to update the context dynamically
|
|
216
|
+
* Useful when context depends on authentication or other async operations
|
|
217
|
+
*/
|
|
218
|
+
declare function useFeatureContext(): Omit<SupaContextValue<any>, 'client'>;
|
|
219
|
+
|
|
220
|
+
interface SupaFeatureProps {
|
|
221
|
+
/**
|
|
222
|
+
* The feature flag key to evaluate
|
|
223
|
+
*/
|
|
224
|
+
feature: FeatureKey;
|
|
225
|
+
/**
|
|
226
|
+
* Context for feature evaluation
|
|
227
|
+
*/
|
|
228
|
+
context?: FeatureContext;
|
|
229
|
+
/**
|
|
230
|
+
* Whether to fetch the feature (default: true)
|
|
231
|
+
*/
|
|
232
|
+
shouldFetch?: boolean;
|
|
233
|
+
/**
|
|
234
|
+
* Variations object mapping feature values/keys to JSX elements
|
|
235
|
+
*/
|
|
236
|
+
variations: Record<string, ReactNode>;
|
|
237
|
+
/**
|
|
238
|
+
* Key in variations object to use for loading state
|
|
239
|
+
*/
|
|
240
|
+
loading?: string;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* SupaFeature component that conditionally renders variations based on feature flag values.
|
|
244
|
+
* Uses the default value defined in the client configuration.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```tsx
|
|
248
|
+
* <SupaFeature
|
|
249
|
+
* feature="new-header"
|
|
250
|
+
* variations={{
|
|
251
|
+
* "true": <NewHeader />,
|
|
252
|
+
* "false": <OldHeader />,
|
|
253
|
+
* loading: <HeaderSkeleton />
|
|
254
|
+
* }}
|
|
255
|
+
* />
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
declare function SupaFeature({ feature, context, shouldFetch, variations, loading, }: SupaFeatureProps): React.JSX.Element | null;
|
|
259
|
+
|
|
260
|
+
export { type BaseQueryState, type FeatureKey, type Features, type InferFeatures, QueryClient, type QueryKey, type QueryState, type QueryStatus, SupaFeature, type SupaFeatureProps, SupaProvider, type TypedFeatures, type UseFeatureOptions, type UseFeatureResult, type UseFeaturesOptions, type UseFeaturesResult, type UseQueryOptions, getInitialQueryState, queryCache, useClient, useFeature, useFeatureContext, useFeatures, useQuery, useQueryClient };
|