@fluxbase/sdk-react 2026.1.22 → 2026.2.1
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.d.mts +33 -2
- package/dist/index.d.ts +33 -2
- package/dist/index.js +33 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +33 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +20 -10
- package/src/context.test.tsx +147 -0
- package/src/index.test.ts +255 -0
- package/src/test-setup.ts +22 -0
- package/src/test-utils.tsx +215 -0
- package/src/use-admin-auth.test.ts +175 -0
- package/src/use-admin-auth.ts +10 -2
- package/src/use-admin-hooks.test.ts +457 -0
- package/src/use-auth-config.test.ts +145 -0
- package/src/use-auth.test.ts +313 -0
- package/src/use-auth.ts +2 -1
- package/src/use-captcha.test.ts +273 -0
- package/src/use-client-keys.test.ts +286 -0
- package/src/use-graphql.test.ts +424 -0
- package/src/use-query.test.ts +348 -0
- package/src/use-query.ts +50 -4
- package/src/use-realtime.test.ts +359 -0
- package/src/use-realtime.ts +20 -15
- package/src/use-saml.test.ts +269 -0
- package/src/use-storage.test.ts +549 -0
- package/src/use-storage.ts +10 -2
- package/src/use-users.test.ts +264 -0
- package/vitest.config.ts +22 -0
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/context.tsx","../src/use-auth.ts","../src/use-captcha.ts","../src/use-auth-config.ts","../src/use-saml.ts","../src/use-graphql.ts","../src/use-query.ts","../src/use-realtime.ts","../src/use-storage.ts","../src/use-admin-auth.ts","../src/use-users.ts","../src/use-client-keys.ts","../src/use-admin-hooks.ts"],"sourcesContent":["/**\n * React context for Fluxbase client\n */\n\nimport { createContext, useContext, type ReactNode } from 'react'\nimport type { FluxbaseClient } from '@fluxbase/sdk'\n\nconst FluxbaseContext = createContext<FluxbaseClient | null>(null)\n\nexport interface FluxbaseProviderProps {\n client: FluxbaseClient\n children: ReactNode\n}\n\n/**\n * Provider component to make Fluxbase client available throughout the app\n */\nexport function FluxbaseProvider({ client, children }: FluxbaseProviderProps) {\n return <FluxbaseContext.Provider value={client}>{children}</FluxbaseContext.Provider>\n}\n\n/**\n * Hook to access the Fluxbase client from context\n */\nexport function useFluxbaseClient(): FluxbaseClient {\n const client = useContext(FluxbaseContext)\n\n if (!client) {\n throw new Error('useFluxbaseClient must be used within a FluxbaseProvider')\n }\n\n return client\n}\n","/**\n * Authentication hooks for Fluxbase SDK\n */\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type {\n SignInCredentials,\n SignUpCredentials,\n User,\n AuthSession,\n} from \"@fluxbase/sdk\";\n\n/**\n * Hook to get the current user\n */\nexport function useUser() {\n const client = useFluxbaseClient();\n\n return useQuery({\n queryKey: [\"fluxbase\", \"auth\", \"user\"],\n queryFn: async () => {\n const { data } = await client.auth.getSession();\n if (!data?.session) {\n return null;\n }\n\n try {\n const result = await client.auth.getCurrentUser();\n return result.data?.user ?? null;\n } catch {\n return null;\n }\n },\n staleTime: 1000 * 60 * 5, // 5 minutes\n });\n}\n\n/**\n * Hook to get the current session\n */\nexport function useSession() {\n const client = useFluxbaseClient();\n\n return useQuery<AuthSession | null>({\n queryKey: [\"fluxbase\", \"auth\", \"session\"],\n queryFn: async () => {\n const { data } = await client.auth.getSession();\n return data?.session ?? null;\n },\n staleTime: 1000 * 60 * 5, // 5 minutes\n });\n}\n\n/**\n * Hook for signing in\n */\nexport function useSignIn() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (credentials: SignInCredentials) => {\n return await client.auth.signIn(credentials);\n },\n onSuccess: (session) => {\n queryClient.setQueryData([\"fluxbase\", \"auth\", \"session\"], session);\n // Only set user if this is a complete auth session (not 2FA required)\n if (\"user\" in session) {\n queryClient.setQueryData([\"fluxbase\", \"auth\", \"user\"], session.user);\n }\n },\n });\n}\n\n/**\n * Hook for signing up\n */\nexport function useSignUp() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (credentials: SignUpCredentials) => {\n return await client.auth.signUp(credentials);\n },\n onSuccess: (response) => {\n if (response.data) {\n queryClient.setQueryData(\n [\"fluxbase\", \"auth\", \"session\"],\n response.data.session,\n );\n queryClient.setQueryData(\n [\"fluxbase\", \"auth\", \"user\"],\n response.data.user,\n );\n }\n },\n });\n}\n\n/**\n * Hook for signing out\n */\nexport function useSignOut() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async () => {\n await client.auth.signOut();\n },\n onSuccess: () => {\n queryClient.setQueryData([\"fluxbase\", \"auth\", \"session\"], null);\n queryClient.setQueryData([\"fluxbase\", \"auth\", \"user\"], null);\n queryClient.invalidateQueries({ queryKey: [\"fluxbase\"] });\n },\n });\n}\n\n/**\n * Hook for updating the current user\n */\nexport function useUpdateUser() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (data: Partial<Pick<User, \"email\" | \"metadata\">>) => {\n return await client.auth.updateUser(data);\n },\n onSuccess: (user) => {\n queryClient.setQueryData([\"fluxbase\", \"auth\", \"user\"], user);\n },\n });\n}\n\n/**\n * Combined auth hook with all auth state and methods\n */\nexport function useAuth() {\n const { data: user, isLoading: isLoadingUser } = useUser();\n const { data: session, isLoading: isLoadingSession } = useSession();\n const signIn = useSignIn();\n const signUp = useSignUp();\n const signOut = useSignOut();\n const updateUser = useUpdateUser();\n\n return {\n user,\n session,\n isLoading: isLoadingUser || isLoadingSession,\n isAuthenticated: !!session,\n signIn: signIn.mutateAsync,\n signUp: signUp.mutateAsync,\n signOut: signOut.mutateAsync,\n updateUser: updateUser.mutateAsync,\n isSigningIn: signIn.isPending,\n isSigningUp: signUp.isPending,\n isSigningOut: signOut.isPending,\n isUpdating: updateUser.isPending,\n };\n}\n","/**\n * CAPTCHA hooks for Fluxbase SDK\n *\n * Provides hooks to:\n * - Fetch CAPTCHA configuration from the server\n * - Manage CAPTCHA widget state\n */\n\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type { CaptchaConfig, CaptchaProvider } from \"@fluxbase/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\n/**\n * Hook to get the CAPTCHA configuration from the server\n * Use this to determine which CAPTCHA provider to load\n *\n * @example\n * ```tsx\n * function AuthPage() {\n * const { data: captchaConfig, isLoading } = useCaptchaConfig();\n *\n * if (isLoading) return <Loading />;\n *\n * return captchaConfig?.enabled ? (\n * <CaptchaWidget provider={captchaConfig.provider} siteKey={captchaConfig.site_key} />\n * ) : null;\n * }\n * ```\n */\nexport function useCaptchaConfig() {\n const client = useFluxbaseClient();\n\n return useQuery<CaptchaConfig>({\n queryKey: [\"fluxbase\", \"auth\", \"captcha\", \"config\"],\n queryFn: async () => {\n const { data, error } = await client.auth.getCaptchaConfig();\n if (error) {\n throw error;\n }\n return data!;\n },\n staleTime: 1000 * 60 * 60, // Cache for 1 hour (config rarely changes)\n gcTime: 1000 * 60 * 60 * 24, // Keep in cache for 24 hours\n });\n}\n\n/**\n * CAPTCHA widget state for managing token generation\n */\nexport interface CaptchaState {\n /** Current CAPTCHA token (null until solved) */\n token: string | null;\n /** Whether the CAPTCHA widget is ready */\n isReady: boolean;\n /** Whether a token is being generated */\n isLoading: boolean;\n /** Any error that occurred */\n error: Error | null;\n /** Reset the CAPTCHA widget */\n reset: () => void;\n /** Execute/trigger the CAPTCHA (for invisible CAPTCHA like reCAPTCHA v3) */\n execute: () => Promise<string>;\n /** Callback to be called when CAPTCHA is verified */\n onVerify: (token: string) => void;\n /** Callback to be called when CAPTCHA expires */\n onExpire: () => void;\n /** Callback to be called when CAPTCHA errors */\n onError: (error: Error) => void;\n}\n\n/**\n * Hook to manage CAPTCHA widget state\n *\n * This hook provides a standardized interface for managing CAPTCHA tokens\n * across different providers (hCaptcha, reCAPTCHA v3, Turnstile, Cap).\n *\n * Supported providers:\n * - hcaptcha: Privacy-focused visual challenge\n * - recaptcha_v3: Google's invisible risk-based CAPTCHA\n * - turnstile: Cloudflare's invisible CAPTCHA\n * - cap: Self-hosted proof-of-work CAPTCHA (https://capjs.js.org/)\n *\n * @param provider - The CAPTCHA provider type\n * @returns CAPTCHA state and callbacks\n *\n * @example\n * ```tsx\n * function LoginForm() {\n * const captcha = useCaptcha('hcaptcha');\n *\n * const handleSubmit = async (e: FormEvent) => {\n * e.preventDefault();\n *\n * // Get CAPTCHA token\n * const captchaToken = captcha.token || await captcha.execute();\n *\n * // Sign in with CAPTCHA token\n * await signIn({\n * email,\n * password,\n * captchaToken\n * });\n * };\n *\n * return (\n * <form onSubmit={handleSubmit}>\n * <input name=\"email\" />\n * <input name=\"password\" type=\"password\" />\n *\n * <HCaptcha\n * sitekey={siteKey}\n * onVerify={captcha.onVerify}\n * onExpire={captcha.onExpire}\n * onError={captcha.onError}\n * />\n *\n * <button type=\"submit\" disabled={!captcha.isReady}>\n * Sign In\n * </button>\n * </form>\n * );\n * }\n * ```\n *\n * @example Cap provider\n * ```tsx\n * function LoginForm() {\n * const { data: config } = useCaptchaConfig();\n * const captcha = useCaptcha(config?.provider);\n *\n * // For Cap, load the widget from cap_server_url\n * // <script src={`${config.cap_server_url}/widget.js`} />\n * // <cap-widget data-cap-url={config.cap_server_url} />\n * }\n * ```\n */\nexport function useCaptcha(provider?: CaptchaProvider): CaptchaState {\n const [token, setToken] = useState<string | null>(null);\n const [isReady, setIsReady] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Promise resolver for execute() method\n const executeResolverRef = useRef<((token: string) => void) | null>(null);\n const executeRejecterRef = useRef<((error: Error) => void) | null>(null);\n\n // Callback when CAPTCHA is verified\n const onVerify = useCallback((newToken: string) => {\n setToken(newToken);\n setIsLoading(false);\n setError(null);\n setIsReady(true);\n\n // Resolve the execute() promise if waiting\n if (executeResolverRef.current) {\n executeResolverRef.current(newToken);\n executeResolverRef.current = null;\n executeRejecterRef.current = null;\n }\n }, []);\n\n // Callback when CAPTCHA expires\n const onExpire = useCallback(() => {\n setToken(null);\n setIsReady(true);\n }, []);\n\n // Callback when CAPTCHA errors\n const onError = useCallback((err: Error) => {\n setError(err);\n setIsLoading(false);\n setToken(null);\n\n // Reject the execute() promise if waiting\n if (executeRejecterRef.current) {\n executeRejecterRef.current(err);\n executeResolverRef.current = null;\n executeRejecterRef.current = null;\n }\n }, []);\n\n // Reset the CAPTCHA\n const reset = useCallback(() => {\n setToken(null);\n setError(null);\n setIsLoading(false);\n }, []);\n\n // Execute/trigger the CAPTCHA (for invisible CAPTCHA)\n const execute = useCallback(async (): Promise<string> => {\n // If we already have a token, return it\n if (token) {\n return token;\n }\n\n // If CAPTCHA is not configured, return empty string\n if (!provider) {\n return \"\";\n }\n\n setIsLoading(true);\n setError(null);\n\n // Return a promise that will be resolved by onVerify\n return new Promise<string>((resolve, reject) => {\n executeResolverRef.current = resolve;\n executeRejecterRef.current = reject;\n\n // For invisible CAPTCHAs, the widget should call onVerify when done\n // The actual execution is handled by the CAPTCHA widget component\n });\n }, [token, provider]);\n\n // Mark as ready when provider is set\n useEffect(() => {\n if (provider) {\n setIsReady(true);\n }\n }, [provider]);\n\n return {\n token,\n isReady,\n isLoading,\n error,\n reset,\n execute,\n onVerify,\n onExpire,\n onError,\n };\n}\n\n/**\n * Check if CAPTCHA is required for a specific endpoint\n *\n * @param config - CAPTCHA configuration from useCaptchaConfig\n * @param endpoint - The endpoint to check (e.g., 'signup', 'login', 'password_reset')\n * @returns Whether CAPTCHA is required for this endpoint\n */\nexport function isCaptchaRequiredForEndpoint(\n config: CaptchaConfig | undefined,\n endpoint: string\n): boolean {\n if (!config?.enabled) {\n return false;\n }\n return config.endpoints?.includes(endpoint) ?? false;\n}\n","/**\n * Auth configuration hooks for Fluxbase SDK\n *\n * Provides hooks to fetch comprehensive authentication configuration\n * from the server including signup status, OAuth/SAML providers,\n * password requirements, and CAPTCHA settings.\n */\n\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type { AuthConfig } from \"@fluxbase/sdk\";\n\n/**\n * Hook to get the complete authentication configuration from the server\n *\n * Returns all public auth settings in a single request including:\n * - Signup enabled status\n * - Email verification requirements\n * - Magic link availability\n * - MFA availability\n * - Password requirements (length, complexity)\n * - Available OAuth providers (Google, GitHub, etc.)\n * - Available SAML providers (enterprise SSO)\n * - CAPTCHA configuration\n *\n * Use this to conditionally render UI elements based on server configuration,\n * such as hiding signup forms when signup is disabled or displaying available\n * OAuth provider buttons.\n *\n * @returns Query result with authentication configuration\n *\n * @example\n * ```tsx\n * function AuthPage() {\n * const { data: config, isLoading } = useAuthConfig();\n *\n * if (isLoading) return <Loading />;\n *\n * return (\n * <div>\n * {config?.signup_enabled && (\n * <SignupForm passwordMinLength={config.password_min_length} />\n * )}\n *\n * {config?.oauth_providers.map(provider => (\n * <OAuthButton\n * key={provider.provider}\n * provider={provider.provider}\n * displayName={provider.display_name}\n * authorizeUrl={provider.authorize_url}\n * />\n * ))}\n *\n * {config?.saml_providers.map(provider => (\n * <SAMLButton\n * key={provider.provider}\n * provider={provider.provider}\n * displayName={provider.display_name}\n * />\n * ))}\n * </div>\n * );\n * }\n * ```\n *\n * @example Showing password requirements\n * ```tsx\n * function PasswordInput() {\n * const { data: config } = useAuthConfig();\n *\n * return (\n * <div>\n * <input type=\"password\" minLength={config?.password_min_length} />\n * <ul>\n * <li>Minimum {config?.password_min_length || 8} characters</li>\n * {config?.password_require_uppercase && <li>One uppercase letter</li>}\n * {config?.password_require_lowercase && <li>One lowercase letter</li>}\n * {config?.password_require_number && <li>One number</li>}\n * {config?.password_require_special && <li>One special character</li>}\n * </ul>\n * </div>\n * );\n * }\n * ```\n */\nexport function useAuthConfig() {\n const client = useFluxbaseClient();\n\n return useQuery<AuthConfig>({\n queryKey: [\"fluxbase\", \"auth\", \"config\"],\n queryFn: async () => {\n const { data, error } = await client.auth.getAuthConfig();\n if (error) {\n throw error;\n }\n return data!;\n },\n staleTime: 1000 * 60 * 5, // Cache for 5 minutes (config changes infrequently)\n gcTime: 1000 * 60 * 60, // Keep in cache for 1 hour\n });\n}\n","/**\n * SAML SSO hooks for Fluxbase React SDK\n */\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type { SAMLLoginOptions, SAMLProvider } from \"@fluxbase/sdk\";\n\n/**\n * Hook to get available SAML SSO providers\n *\n * @example\n * ```tsx\n * function SAMLProviderList() {\n * const { data: providers, isLoading } = useSAMLProviders()\n *\n * if (isLoading) return <div>Loading...</div>\n *\n * return (\n * <div>\n * {providers?.map(provider => (\n * <button key={provider.id} onClick={() => signInWithSAML(provider.name)}>\n * Sign in with {provider.name}\n * </button>\n * ))}\n * </div>\n * )\n * }\n * ```\n */\nexport function useSAMLProviders() {\n const client = useFluxbaseClient();\n\n return useQuery<SAMLProvider[]>({\n queryKey: [\"fluxbase\", \"auth\", \"saml\", \"providers\"],\n queryFn: async () => {\n const { data, error } = await client.auth.getSAMLProviders();\n if (error) throw error;\n return data.providers;\n },\n staleTime: 1000 * 60 * 5, // 5 minutes - providers don't change often\n });\n}\n\n/**\n * Hook to get SAML login URL for a provider\n *\n * This hook returns a function to get the login URL for a specific provider.\n * Use this when you need more control over the redirect behavior.\n *\n * @example\n * ```tsx\n * function SAMLLoginButton({ provider }: { provider: string }) {\n * const getSAMLLoginUrl = useGetSAMLLoginUrl()\n *\n * const handleClick = async () => {\n * const { data, error } = await getSAMLLoginUrl.mutateAsync({\n * provider,\n * options: { redirectUrl: window.location.href }\n * })\n * if (!error) {\n * window.location.href = data.url\n * }\n * }\n *\n * return <button onClick={handleClick}>Login with {provider}</button>\n * }\n * ```\n */\nexport function useGetSAMLLoginUrl() {\n const client = useFluxbaseClient();\n\n return useMutation({\n mutationFn: async ({\n provider,\n options,\n }: {\n provider: string;\n options?: SAMLLoginOptions;\n }) => {\n return await client.auth.getSAMLLoginUrl(provider, options);\n },\n });\n}\n\n/**\n * Hook to initiate SAML login (redirects to IdP)\n *\n * This hook returns a mutation that when called, redirects the user to the\n * SAML Identity Provider for authentication.\n *\n * @example\n * ```tsx\n * function SAMLLoginButton() {\n * const signInWithSAML = useSignInWithSAML()\n *\n * return (\n * <button\n * onClick={() => signInWithSAML.mutate({ provider: 'okta' })}\n * disabled={signInWithSAML.isPending}\n * >\n * {signInWithSAML.isPending ? 'Redirecting...' : 'Sign in with Okta'}\n * </button>\n * )\n * }\n * ```\n */\nexport function useSignInWithSAML() {\n const client = useFluxbaseClient();\n\n return useMutation({\n mutationFn: async ({\n provider,\n options,\n }: {\n provider: string;\n options?: SAMLLoginOptions;\n }) => {\n return await client.auth.signInWithSAML(provider, options);\n },\n });\n}\n\n/**\n * Hook to handle SAML callback after IdP authentication\n *\n * Use this in your SAML callback page to complete the authentication flow.\n *\n * @example\n * ```tsx\n * function SAMLCallbackPage() {\n * const handleCallback = useHandleSAMLCallback()\n * const navigate = useNavigate()\n *\n * useEffect(() => {\n * const params = new URLSearchParams(window.location.search)\n * const samlResponse = params.get('SAMLResponse')\n *\n * if (samlResponse) {\n * handleCallback.mutate(\n * { samlResponse },\n * {\n * onSuccess: () => navigate('/dashboard'),\n * onError: (error) => console.error('SAML login failed:', error)\n * }\n * )\n * }\n * }, [])\n *\n * if (handleCallback.isPending) {\n * return <div>Completing sign in...</div>\n * }\n *\n * if (handleCallback.isError) {\n * return <div>Authentication failed: {handleCallback.error.message}</div>\n * }\n *\n * return null\n * }\n * ```\n */\nexport function useHandleSAMLCallback() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({\n samlResponse,\n provider,\n }: {\n samlResponse: string;\n provider?: string;\n }) => {\n return await client.auth.handleSAMLCallback(samlResponse, provider);\n },\n onSuccess: (result) => {\n if (result.data) {\n // Update auth state in React Query cache\n queryClient.setQueryData(\n [\"fluxbase\", \"auth\", \"session\"],\n result.data.session,\n );\n queryClient.setQueryData(\n [\"fluxbase\", \"auth\", \"user\"],\n result.data.user,\n );\n // Invalidate any dependent queries\n queryClient.invalidateQueries({ queryKey: [\"fluxbase\"] });\n }\n },\n });\n}\n\n/**\n * Hook to get SAML Service Provider metadata URL\n *\n * Returns a function that generates the SP metadata URL for a given provider.\n * Use this URL when configuring your SAML IdP.\n *\n * @example\n * ```tsx\n * function SAMLSetupInfo({ provider }: { provider: string }) {\n * const getSAMLMetadataUrl = useSAMLMetadataUrl()\n * const metadataUrl = getSAMLMetadataUrl(provider)\n *\n * return (\n * <div>\n * <p>SP Metadata URL:</p>\n * <code>{metadataUrl}</code>\n * </div>\n * )\n * }\n * ```\n */\nexport function useSAMLMetadataUrl() {\n const client = useFluxbaseClient();\n\n return (provider: string): string => {\n return client.auth.getSAMLMetadataUrl(provider);\n };\n}\n","/**\n * GraphQL hooks for Fluxbase React SDK\n *\n * Provides React Query integration for GraphQL queries and mutations.\n *\n * @example\n * ```tsx\n * import { useGraphQLQuery, useGraphQLMutation } from '@fluxbase/sdk-react'\n *\n * function UsersList() {\n * const { data, isLoading, error } = useGraphQLQuery<UsersQuery>(\n * 'users-list',\n * `query { users { id email } }`\n * )\n *\n * if (isLoading) return <div>Loading...</div>\n * if (error) return <div>Error: {error.message}</div>\n *\n * return (\n * <ul>\n * {data?.users.map(user => (\n * <li key={user.id}>{user.email}</li>\n * ))}\n * </ul>\n * )\n * }\n * ```\n */\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type {\n GraphQLResponse,\n GraphQLError,\n GraphQLRequestOptions,\n} from \"@fluxbase/sdk\";\n\n/**\n * Options for useGraphQLQuery hook\n */\nexport interface UseGraphQLQueryOptions<T> {\n /**\n * Variables to pass to the GraphQL query\n */\n variables?: Record<string, unknown>;\n\n /**\n * Operation name when the document contains multiple operations\n */\n operationName?: string;\n\n /**\n * Additional request options\n */\n requestOptions?: GraphQLRequestOptions;\n\n /**\n * Whether the query is enabled\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Time in milliseconds after which the query is considered stale\n * @default 0 (considered stale immediately)\n */\n staleTime?: number;\n\n /**\n * Time in milliseconds after which inactive query data is garbage collected\n * @default 5 minutes\n */\n gcTime?: number;\n\n /**\n * Whether to refetch on window focus\n * @default true\n */\n refetchOnWindowFocus?: boolean;\n\n /**\n * Transform function to process the response data\n */\n select?: (data: T | undefined) => T | undefined;\n}\n\n/**\n * Options for useGraphQLMutation hook\n */\nexport interface UseGraphQLMutationOptions<T, V> {\n /**\n * Operation name when the document contains multiple operations\n */\n operationName?: string;\n\n /**\n * Additional request options\n */\n requestOptions?: GraphQLRequestOptions;\n\n /**\n * Callback when mutation succeeds\n */\n onSuccess?: (data: T, variables: V) => void;\n\n /**\n * Callback when mutation fails\n */\n onError?: (error: GraphQLError, variables: V) => void;\n\n /**\n * Query keys to invalidate on success\n */\n invalidateQueries?: string[];\n}\n\n/**\n * Hook to execute GraphQL queries with React Query caching\n *\n * @typeParam T - The expected response data type\n * @param queryKey - Unique key for caching (string or array)\n * @param query - The GraphQL query string\n * @param options - Query options including variables\n * @returns React Query result object\n *\n * @example\n * ```tsx\n * interface UsersQuery {\n * users: Array<{ id: string; email: string }>\n * }\n *\n * function UsersList() {\n * const { data, isLoading } = useGraphQLQuery<UsersQuery>(\n * 'users',\n * `query { users { id email } }`\n * )\n *\n * return <div>{data?.users.length} users</div>\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With variables\n * const { data } = useGraphQLQuery<UserQuery>(\n * ['user', userId],\n * `query GetUser($id: ID!) { user(id: $id) { id email } }`,\n * { variables: { id: userId } }\n * )\n * ```\n */\nexport function useGraphQLQuery<T = unknown>(\n queryKey: string | readonly unknown[],\n query: string,\n options?: UseGraphQLQueryOptions<T>\n) {\n const client = useFluxbaseClient();\n const normalizedKey = Array.isArray(queryKey)\n ? [\"fluxbase\", \"graphql\", ...queryKey]\n : [\"fluxbase\", \"graphql\", queryKey];\n\n return useQuery<T | undefined, GraphQLError>({\n queryKey: normalizedKey,\n queryFn: async () => {\n const response: GraphQLResponse<T> = await client.graphql.execute(\n query,\n options?.variables,\n options?.operationName,\n options?.requestOptions\n );\n\n if (response.errors && response.errors.length > 0) {\n throw response.errors[0];\n }\n\n return response.data;\n },\n enabled: options?.enabled ?? true,\n staleTime: options?.staleTime ?? 0,\n gcTime: options?.gcTime,\n refetchOnWindowFocus: options?.refetchOnWindowFocus ?? true,\n select: options?.select,\n });\n}\n\n/**\n * Hook to execute GraphQL mutations\n *\n * @typeParam T - The expected response data type\n * @typeParam V - The variables type\n * @param mutation - The GraphQL mutation string\n * @param options - Mutation options\n * @returns React Query mutation result object\n *\n * @example\n * ```tsx\n * interface CreateUserMutation {\n * insertUser: { id: string; email: string }\n * }\n *\n * interface CreateUserVariables {\n * data: { email: string }\n * }\n *\n * function CreateUserForm() {\n * const mutation = useGraphQLMutation<CreateUserMutation, CreateUserVariables>(\n * `mutation CreateUser($data: UserInput!) {\n * insertUser(data: $data) { id email }\n * }`,\n * {\n * onSuccess: (data) => console.log('Created:', data.insertUser),\n * invalidateQueries: ['users']\n * }\n * )\n *\n * const handleSubmit = (email: string) => {\n * mutation.mutate({ data: { email } })\n * }\n *\n * return (\n * <button\n * onClick={() => handleSubmit('new@example.com')}\n * disabled={mutation.isPending}\n * >\n * Create User\n * </button>\n * )\n * }\n * ```\n */\nexport function useGraphQLMutation<\n T = unknown,\n V extends Record<string, unknown> = Record<string, unknown>,\n>(mutation: string, options?: UseGraphQLMutationOptions<T, V>) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation<T | undefined, GraphQLError, V>({\n mutationFn: async (variables: V) => {\n const response: GraphQLResponse<T> = await client.graphql.execute(\n mutation,\n variables,\n options?.operationName,\n options?.requestOptions\n );\n\n if (response.errors && response.errors.length > 0) {\n throw response.errors[0];\n }\n\n return response.data;\n },\n onSuccess: (data, variables) => {\n // Invalidate specified queries\n if (options?.invalidateQueries) {\n for (const key of options.invalidateQueries) {\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"graphql\", key],\n });\n }\n }\n\n // Call user's onSuccess callback\n if (options?.onSuccess && data !== undefined) {\n options.onSuccess(data, variables);\n }\n },\n onError: (error, variables) => {\n if (options?.onError) {\n options.onError(error, variables);\n }\n },\n });\n}\n\n/**\n * Hook to fetch the GraphQL schema via introspection\n *\n * @param options - Query options\n * @returns React Query result with schema introspection data\n *\n * @example\n * ```tsx\n * function SchemaExplorer() {\n * const { data, isLoading } = useGraphQLIntrospection()\n *\n * if (isLoading) return <div>Loading schema...</div>\n *\n * return (\n * <div>\n * <p>Query type: {data?.__schema.queryType.name}</p>\n * <p>Types: {data?.__schema.types.length}</p>\n * </div>\n * )\n * }\n * ```\n */\nexport function useGraphQLIntrospection(options?: {\n enabled?: boolean;\n staleTime?: number;\n requestOptions?: GraphQLRequestOptions;\n}) {\n const client = useFluxbaseClient();\n\n return useQuery({\n queryKey: [\"fluxbase\", \"graphql\", \"__introspection\"],\n queryFn: async () => {\n const response = await client.graphql.introspect(options?.requestOptions);\n\n if (response.errors && response.errors.length > 0) {\n throw response.errors[0];\n }\n\n return response.data;\n },\n enabled: options?.enabled ?? true,\n staleTime: options?.staleTime ?? 1000 * 60 * 5, // 5 minutes - schema doesn't change often\n });\n}\n\n/**\n * Hook to execute raw GraphQL operations (query or mutation)\n *\n * This is a lower-level hook that doesn't use React Query caching.\n * Useful for one-off operations or when you need full control.\n *\n * @returns Functions to execute queries and mutations\n *\n * @example\n * ```tsx\n * function AdminPanel() {\n * const { executeQuery, executeMutation } = useGraphQL()\n *\n * const handleExport = async () => {\n * const result = await executeQuery<ExportData>(\n * `query { exportAllData { url } }`\n * )\n * if (result.data) {\n * window.open(result.data.exportAllData.url)\n * }\n * }\n *\n * return <button onClick={handleExport}>Export Data</button>\n * }\n * ```\n */\nexport function useGraphQL() {\n const client = useFluxbaseClient();\n\n return {\n /**\n * Execute a GraphQL query\n */\n executeQuery: <T = unknown>(\n query: string,\n variables?: Record<string, unknown>,\n options?: GraphQLRequestOptions\n ): Promise<GraphQLResponse<T>> => {\n return client.graphql.query<T>(query, variables, options);\n },\n\n /**\n * Execute a GraphQL mutation\n */\n executeMutation: <T = unknown>(\n mutation: string,\n variables?: Record<string, unknown>,\n options?: GraphQLRequestOptions\n ): Promise<GraphQLResponse<T>> => {\n return client.graphql.mutation<T>(mutation, variables, options);\n },\n\n /**\n * Execute a GraphQL operation with an explicit operation name\n */\n execute: <T = unknown>(\n document: string,\n variables?: Record<string, unknown>,\n operationName?: string,\n options?: GraphQLRequestOptions\n ): Promise<GraphQLResponse<T>> => {\n return client.graphql.execute<T>(document, variables, operationName, options);\n },\n\n /**\n * Fetch the GraphQL schema via introspection\n */\n introspect: (options?: GraphQLRequestOptions) => {\n return client.graphql.introspect(options);\n },\n };\n}\n","/**\n * Database query hooks for Fluxbase SDK\n */\n\nimport { useQuery, useMutation, useQueryClient, type UseQueryOptions } from '@tanstack/react-query'\nimport { useFluxbaseClient } from './context'\nimport type { QueryBuilder } from '@fluxbase/sdk'\n\nexport interface UseFluxbaseQueryOptions<T> extends Omit<UseQueryOptions<T[], Error>, 'queryKey' | 'queryFn'> {\n /**\n * Custom query key. If not provided, will use table name and filters.\n */\n queryKey?: unknown[]\n}\n\n/**\n * Hook to execute a database query\n * @param buildQuery - Function that builds and returns the query\n * @param options - React Query options\n */\nexport function useFluxbaseQuery<T = any>(\n buildQuery: (client: ReturnType<typeof useFluxbaseClient>) => QueryBuilder<T>,\n options?: UseFluxbaseQueryOptions<T>\n) {\n const client = useFluxbaseClient()\n\n // Build a stable query key\n const queryKey = options?.queryKey || ['fluxbase', 'query', buildQuery.toString()]\n\n return useQuery({\n queryKey,\n queryFn: async () => {\n const query = buildQuery(client)\n const { data, error } = await query.execute()\n\n if (error) {\n throw error\n }\n\n return (Array.isArray(data) ? data : data ? [data] : []) as T[]\n },\n ...options,\n })\n}\n\n/**\n * Hook for table queries with a simpler API\n * @param table - Table name\n * @param buildQuery - Function to build the query\n */\nexport function useTable<T = any>(\n table: string,\n buildQuery?: (query: QueryBuilder<T>) => QueryBuilder<T>,\n options?: UseFluxbaseQueryOptions<T>\n) {\n const client = useFluxbaseClient()\n\n return useFluxbaseQuery(\n (client) => {\n const query = client.from<T>(table)\n return buildQuery ? buildQuery(query) : query\n },\n {\n ...options,\n queryKey: options?.queryKey || ['fluxbase', 'table', table, buildQuery?.toString()],\n }\n )\n}\n\n/**\n * Hook to insert data into a table\n */\nexport function useInsert<T = any>(table: string) {\n const client = useFluxbaseClient()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: async (data: Partial<T> | Partial<T>[]) => {\n const query = client.from<T>(table)\n const { data: result, error } = await query.insert(data as Partial<T>)\n\n if (error) {\n throw error\n }\n\n return result\n },\n onSuccess: () => {\n // Invalidate all queries for this table\n queryClient.invalidateQueries({ queryKey: ['fluxbase', 'table', table] })\n },\n })\n}\n\n/**\n * Hook to update data in a table\n */\nexport function useUpdate<T = any>(table: string) {\n const client = useFluxbaseClient()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: async (params: { data: Partial<T>; buildQuery: (query: QueryBuilder<T>) => QueryBuilder<T> }) => {\n const query = client.from<T>(table)\n const builtQuery = params.buildQuery(query)\n const { data: result, error } = await builtQuery.update(params.data)\n\n if (error) {\n throw error\n }\n\n return result\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['fluxbase', 'table', table] })\n },\n })\n}\n\n/**\n * Hook to upsert data into a table\n */\nexport function useUpsert<T = any>(table: string) {\n const client = useFluxbaseClient()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: async (data: Partial<T> | Partial<T>[]) => {\n const query = client.from<T>(table)\n const { data: result, error } = await query.upsert(data as Partial<T>)\n\n if (error) {\n throw error\n }\n\n return result\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['fluxbase', 'table', table] })\n },\n })\n}\n\n/**\n * Hook to delete data from a table\n */\nexport function useDelete<T = any>(table: string) {\n const client = useFluxbaseClient()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: async (buildQuery: (query: QueryBuilder<T>) => QueryBuilder<T>) => {\n const query = client.from<T>(table)\n const builtQuery = buildQuery(query)\n const { error } = await builtQuery.delete()\n\n if (error) {\n throw error\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['fluxbase', 'table', table] })\n },\n })\n}\n","/**\n * Realtime subscription hooks for Fluxbase SDK\n */\n\nimport { useEffect, useRef } from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type {\n RealtimeCallback,\n RealtimePostgresChangesPayload,\n} from \"@fluxbase/sdk\";\n\nexport interface UseRealtimeOptions {\n /**\n * The channel name (e.g., 'table:public.products')\n */\n channel: string;\n\n /**\n * Event type to listen for ('INSERT', 'UPDATE', 'DELETE', or '*' for all)\n */\n event?: \"INSERT\" | \"UPDATE\" | \"DELETE\" | \"*\";\n\n /**\n * Callback function when an event is received\n */\n callback?: RealtimeCallback;\n\n /**\n * Whether to automatically invalidate queries for the table\n * Default: true\n */\n autoInvalidate?: boolean;\n\n /**\n * Custom query key to invalidate (if autoInvalidate is true)\n * Default: ['fluxbase', 'table', tableName]\n */\n invalidateKey?: unknown[];\n\n /**\n * Whether the subscription is enabled\n * Default: true\n */\n enabled?: boolean;\n}\n\n/**\n * Hook to subscribe to realtime changes for a channel\n */\nexport function useRealtime(options: UseRealtimeOptions) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n const channelRef = useRef<ReturnType<typeof client.realtime.channel> | null>(\n null,\n );\n\n const {\n channel: channelName,\n event = \"*\",\n callback,\n autoInvalidate = true,\n invalidateKey,\n enabled = true,\n } = options;\n\n useEffect(() => {\n if (!enabled) {\n return;\n }\n\n // Create channel and subscribe\n const channel = client.realtime.channel(channelName);\n channelRef.current = channel;\n\n const handleChange = (payload: RealtimePostgresChangesPayload) => {\n // Call user callback\n if (callback) {\n callback(payload);\n }\n\n // Auto-invalidate queries if enabled\n if (autoInvalidate) {\n // Extract table name from channel (e.g., 'table:public.products' -> 'public.products')\n const tableName = channelName.replace(/^table:/, \"\");\n\n const key = invalidateKey || [\"fluxbase\", \"table\", tableName];\n queryClient.invalidateQueries({ queryKey: key });\n }\n };\n\n channel.on(event, handleChange).subscribe();\n\n return () => {\n channel.unsubscribe();\n channelRef.current = null;\n };\n }, [\n client,\n channelName,\n event,\n callback,\n autoInvalidate,\n invalidateKey,\n queryClient,\n enabled,\n ]);\n\n return {\n channel: channelRef.current,\n };\n}\n\n/**\n * Hook to subscribe to a table's changes\n * @param table - Table name (with optional schema, e.g., 'public.products')\n * @param options - Subscription options\n */\nexport function useTableSubscription(\n table: string,\n options?: Omit<UseRealtimeOptions, \"channel\">,\n) {\n return useRealtime({\n ...options,\n channel: `table:${table}`,\n });\n}\n\n/**\n * Hook to subscribe to INSERT events on a table\n */\nexport function useTableInserts(\n table: string,\n callback: (payload: RealtimePostgresChangesPayload) => void,\n options?: Omit<UseRealtimeOptions, \"channel\" | \"event\" | \"callback\">,\n) {\n return useRealtime({\n ...options,\n channel: `table:${table}`,\n event: \"INSERT\",\n callback,\n });\n}\n\n/**\n * Hook to subscribe to UPDATE events on a table\n */\nexport function useTableUpdates(\n table: string,\n callback: (payload: RealtimePostgresChangesPayload) => void,\n options?: Omit<UseRealtimeOptions, \"channel\" | \"event\" | \"callback\">,\n) {\n return useRealtime({\n ...options,\n channel: `table:${table}`,\n event: \"UPDATE\",\n callback,\n });\n}\n\n/**\n * Hook to subscribe to DELETE events on a table\n */\nexport function useTableDeletes(\n table: string,\n callback: (payload: RealtimePostgresChangesPayload) => void,\n options?: Omit<UseRealtimeOptions, \"channel\" | \"event\" | \"callback\">,\n) {\n return useRealtime({\n ...options,\n channel: `table:${table}`,\n event: \"DELETE\",\n callback,\n });\n}\n","/**\n * Storage hooks for Fluxbase SDK\n */\n\nimport { useState } from \"react\";\nimport {\n useMutation,\n useQuery,\n useQueryClient,\n type UseQueryOptions,\n} from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type {\n ListOptions,\n UploadOptions,\n UploadProgress,\n TransformOptions,\n SignedUrlOptions,\n} from \"@fluxbase/sdk\";\n\n/**\n * Hook to list files in a bucket\n */\nexport function useStorageList(\n bucket: string,\n options?: ListOptions &\n Omit<UseQueryOptions<any[], Error>, \"queryKey\" | \"queryFn\">,\n) {\n const client = useFluxbaseClient();\n const { prefix, limit, offset, ...queryOptions } = options || {};\n\n return useQuery({\n queryKey: [\n \"fluxbase\",\n \"storage\",\n bucket,\n \"list\",\n { prefix, limit, offset },\n ],\n queryFn: async () => {\n const { data, error } = await client.storage\n .from(bucket)\n .list({ prefix, limit, offset });\n\n if (error) {\n throw error;\n }\n\n return data || [];\n },\n ...queryOptions,\n });\n}\n\n/**\n * Hook to upload a file to a bucket\n *\n * Note: You can track upload progress by passing an `onUploadProgress` callback in the options:\n *\n * @example\n * ```tsx\n * const upload = useStorageUpload('avatars')\n *\n * upload.mutate({\n * path: 'user.jpg',\n * file: file,\n * options: {\n * onUploadProgress: (progress) => {\n * console.log(`${progress.percentage}% uploaded`)\n * }\n * }\n * })\n * ```\n *\n * For automatic progress state management, use `useStorageUploadWithProgress` instead.\n */\nexport function useStorageUpload(bucket: string) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (params: {\n path: string;\n file: File | Blob | ArrayBuffer;\n options?: UploadOptions;\n }) => {\n const { path, file, options } = params;\n const { data, error } = await client.storage\n .from(bucket)\n .upload(path, file, options);\n\n if (error) {\n throw error;\n }\n\n return data;\n },\n onSuccess: () => {\n // Invalidate list queries for this bucket\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"list\"],\n });\n },\n });\n}\n\n/**\n * Hook to upload a file to a bucket with built-in progress tracking\n *\n * @example\n * ```tsx\n * const { upload, progress, reset } = useStorageUploadWithProgress('avatars')\n *\n * // Upload with automatic progress tracking\n * upload.mutate({\n * path: 'user.jpg',\n * file: file\n * })\n *\n * // Display progress\n * console.log(progress) // { loaded: 1024, total: 2048, percentage: 50 }\n * ```\n */\nexport function useStorageUploadWithProgress(bucket: string) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n const [progress, setProgress] = useState<UploadProgress | null>(null);\n\n const mutation = useMutation({\n mutationFn: async (params: {\n path: string;\n file: File | Blob | ArrayBuffer;\n options?: Omit<UploadOptions, \"onUploadProgress\">;\n }) => {\n const { path, file, options } = params;\n\n // Reset progress at the start of upload\n setProgress({ loaded: 0, total: 0, percentage: 0 });\n\n const { data, error } = await client.storage\n .from(bucket)\n .upload(path, file, {\n ...options,\n onUploadProgress: (p: import(\"@fluxbase/sdk\").UploadProgress) => {\n setProgress(p);\n },\n });\n\n if (error) {\n throw error;\n }\n\n return data;\n },\n onSuccess: () => {\n // Invalidate list queries for this bucket\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"list\"],\n });\n },\n onError: () => {\n // Reset progress on error\n setProgress(null);\n },\n });\n\n return {\n upload: mutation,\n progress,\n reset: () => setProgress(null),\n };\n}\n\n/**\n * Hook to download a file from a bucket\n */\nexport function useStorageDownload(\n bucket: string,\n path: string | null,\n enabled = true,\n) {\n const client = useFluxbaseClient();\n\n return useQuery({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"download\", path],\n queryFn: async () => {\n if (!path) {\n return null;\n }\n\n const { data, error } = await client.storage.from(bucket).download(path);\n\n if (error) {\n throw error;\n }\n\n return data;\n },\n enabled: enabled && !!path,\n });\n}\n\n/**\n * Hook to delete files from a bucket\n */\nexport function useStorageDelete(bucket: string) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (paths: string[]) => {\n const { error } = await client.storage.from(bucket).remove(paths);\n\n if (error) {\n throw error;\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"list\"],\n });\n },\n });\n}\n\n/**\n * Hook to get a public URL for a file\n */\nexport function useStoragePublicUrl(bucket: string, path: string | null) {\n const client = useFluxbaseClient();\n\n if (!path) {\n return null;\n }\n\n const { data } = client.storage.from(bucket).getPublicUrl(path);\n return data.publicUrl;\n}\n\n/**\n * Hook to get a public URL for an image with transformations applied\n *\n * Only works for image files (JPEG, PNG, WebP, GIF, AVIF, etc.)\n *\n * @param bucket - The storage bucket name\n * @param path - The file path (or null to disable)\n * @param transform - Transformation options (width, height, format, quality, fit)\n *\n * @example\n * ```tsx\n * function ImageThumbnail({ path }: { path: string }) {\n * const url = useStorageTransformUrl('images', path, {\n * width: 300,\n * height: 200,\n * format: 'webp',\n * quality: 85,\n * fit: 'cover'\n * });\n *\n * return <img src={url || ''} alt=\"Thumbnail\" />;\n * }\n * ```\n */\nexport function useStorageTransformUrl(\n bucket: string,\n path: string | null,\n transform: TransformOptions,\n): string | null {\n const client = useFluxbaseClient();\n\n if (!path) {\n return null;\n }\n\n return client.storage.from(bucket).getTransformUrl(path, transform);\n}\n\n/**\n * Hook to create a signed URL\n *\n * @deprecated Use useStorageSignedUrlWithOptions for more control including transforms\n */\nexport function useStorageSignedUrl(\n bucket: string,\n path: string | null,\n expiresIn?: number,\n) {\n const client = useFluxbaseClient();\n\n return useQuery({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"signed-url\", path, expiresIn],\n queryFn: async () => {\n if (!path) {\n return null;\n }\n\n const { data, error } = await client.storage\n .from(bucket)\n .createSignedUrl(path, { expiresIn });\n\n if (error) {\n throw error;\n }\n\n return data?.signedUrl || null;\n },\n enabled: !!path,\n staleTime: expiresIn ? expiresIn * 1000 - 60000 : 1000 * 60 * 50, // Refresh 1 minute before expiry\n });\n}\n\n/**\n * Hook to create a signed URL with full options including image transformations\n *\n * @param bucket - The storage bucket name\n * @param path - The file path (or null to disable)\n * @param options - Signed URL options including expiration and transforms\n *\n * @example\n * ```tsx\n * function SecureThumbnail({ path }: { path: string }) {\n * const { data: url } = useStorageSignedUrlWithOptions('images', path, {\n * expiresIn: 3600,\n * transform: {\n * width: 400,\n * height: 300,\n * format: 'webp',\n * quality: 85,\n * fit: 'cover'\n * }\n * });\n *\n * return <img src={url || ''} alt=\"Secure Thumbnail\" />;\n * }\n * ```\n */\nexport function useStorageSignedUrlWithOptions(\n bucket: string,\n path: string | null,\n options?: SignedUrlOptions,\n) {\n const client = useFluxbaseClient();\n const expiresIn = options?.expiresIn;\n\n // Create a stable cache key from transform options\n const transformKey = options?.transform\n ? JSON.stringify(options.transform)\n : null;\n\n return useQuery({\n queryKey: [\n \"fluxbase\",\n \"storage\",\n bucket,\n \"signed-url\",\n path,\n expiresIn,\n transformKey,\n ],\n queryFn: async () => {\n if (!path) {\n return null;\n }\n\n const { data, error } = await client.storage\n .from(bucket)\n .createSignedUrl(path, options);\n\n if (error) {\n throw error;\n }\n\n return data?.signedUrl || null;\n },\n enabled: !!path,\n staleTime: expiresIn ? expiresIn * 1000 - 60000 : 1000 * 60 * 50, // Refresh 1 minute before expiry\n });\n}\n\n/**\n * Hook to move a file\n */\nexport function useStorageMove(bucket: string) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (params: { fromPath: string; toPath: string }) => {\n const { fromPath, toPath } = params;\n const { data, error } = await client.storage\n .from(bucket)\n .move(fromPath, toPath);\n\n if (error) {\n throw error;\n }\n\n return data;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"list\"],\n });\n },\n });\n}\n\n/**\n * Hook to copy a file\n */\nexport function useStorageCopy(bucket: string) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (params: { fromPath: string; toPath: string }) => {\n const { fromPath, toPath } = params;\n const { data, error } = await client.storage\n .from(bucket)\n .copy(fromPath, toPath);\n\n if (error) {\n throw error;\n }\n\n return data;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"list\"],\n });\n },\n });\n}\n\n/**\n * Hook to manage buckets\n */\nexport function useStorageBuckets() {\n const client = useFluxbaseClient();\n\n return useQuery({\n queryKey: [\"fluxbase\", \"storage\", \"buckets\"],\n queryFn: async () => {\n const { data, error } = await client.storage.listBuckets();\n\n if (error) {\n throw error;\n }\n\n return data || [];\n },\n });\n}\n\n/**\n * Hook to create a bucket\n */\nexport function useCreateBucket() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (bucketName: string) => {\n const { error } = await client.storage.createBucket(bucketName);\n\n if (error) {\n throw error;\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", \"buckets\"],\n });\n },\n });\n}\n\n/**\n * Hook to delete a bucket\n */\nexport function useDeleteBucket() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (bucketName: string) => {\n const { error } = await client.storage.deleteBucket(bucketName);\n\n if (error) {\n throw error;\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", \"buckets\"],\n });\n },\n });\n}\n","import { useState, useEffect, useCallback } from \"react\";\nimport { useFluxbaseClient } from \"./context\";\nimport type { AdminAuthResponse, DataResponse } from \"@fluxbase/sdk\";\n\n/**\n * Simplified admin user type returned by authentication\n */\nexport interface AdminUser {\n id: string;\n email: string;\n role: string;\n}\n\nexport interface UseAdminAuthOptions {\n /**\n * Automatically check authentication status on mount\n * @default true\n */\n autoCheck?: boolean;\n}\n\nexport interface UseAdminAuthReturn {\n /**\n * Current admin user if authenticated\n */\n user: AdminUser | null;\n\n /**\n * Whether the admin is authenticated\n */\n isAuthenticated: boolean;\n\n /**\n * Whether the authentication check is in progress\n */\n isLoading: boolean;\n\n /**\n * Any error that occurred during authentication\n */\n error: Error | null;\n\n /**\n * Login as admin\n */\n login: (email: string, password: string) => Promise<AdminAuthResponse>;\n\n /**\n * Logout admin\n */\n logout: () => Promise<void>;\n\n /**\n * Refresh admin user info\n */\n refresh: () => Promise<void>;\n}\n\n/**\n * Hook for admin authentication\n *\n * Manages admin login state, authentication checks, and user info.\n *\n * @example\n * ```tsx\n * function AdminLogin() {\n * const { user, isAuthenticated, isLoading, login, logout } = useAdminAuth()\n *\n * const handleLogin = async (e: React.FormEvent) => {\n * e.preventDefault()\n * await login(email, password)\n * }\n *\n * if (isLoading) return <div>Loading...</div>\n * if (isAuthenticated) return <div>Welcome {user?.email}</div>\n *\n * return <form onSubmit={handleLogin}>...</form>\n * }\n * ```\n */\nexport function useAdminAuth(\n options: UseAdminAuthOptions = {},\n): UseAdminAuthReturn {\n const { autoCheck = true } = options;\n const client = useFluxbaseClient();\n\n const [user, setUser] = useState<AdminUser | null>(null);\n const [isLoading, setIsLoading] = useState(autoCheck);\n const [error, setError] = useState<Error | null>(null);\n\n /**\n * Check current authentication status\n */\n const checkAuth = useCallback(async () => {\n try {\n setIsLoading(true);\n setError(null);\n const { data, error: apiError } = await client.admin.me();\n if (apiError) {\n throw apiError;\n }\n setUser(data!.user);\n } catch (err) {\n setUser(null);\n setError(err as Error);\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n /**\n * Login as admin\n */\n const login = useCallback(\n async (email: string, password: string): Promise<AdminAuthResponse> => {\n try {\n setIsLoading(true);\n setError(null);\n const { data, error: apiError } = await client.admin.login({\n email,\n password,\n });\n if (apiError) {\n throw apiError;\n }\n setUser(data!.user);\n return data!;\n } catch (err) {\n setError(err as Error);\n throw err;\n } finally {\n setIsLoading(false);\n }\n },\n [client],\n );\n\n /**\n * Logout admin\n */\n const logout = useCallback(async (): Promise<void> => {\n try {\n setIsLoading(true);\n setError(null);\n // Clear user state\n setUser(null);\n // Note: Add logout endpoint call here when available\n } catch (err) {\n setError(err as Error);\n throw err;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n /**\n * Refresh admin user info\n */\n const refresh = useCallback(async (): Promise<void> => {\n await checkAuth();\n }, [checkAuth]);\n\n // Auto-check authentication on mount\n useEffect(() => {\n if (autoCheck) {\n checkAuth();\n }\n }, [autoCheck, checkAuth]);\n\n return {\n user,\n isAuthenticated: user !== null,\n isLoading,\n error,\n login,\n logout,\n refresh,\n };\n}\n","import { useState, useEffect, useCallback } from 'react'\nimport { useFluxbaseClient } from './context'\nimport type { EnrichedUser, ListUsersOptions } from '@fluxbase/sdk'\n\nexport interface UseUsersOptions extends ListUsersOptions {\n /**\n * Whether to automatically fetch users on mount\n * @default true\n */\n autoFetch?: boolean\n\n /**\n * Refetch interval in milliseconds (0 to disable)\n * @default 0\n */\n refetchInterval?: number\n}\n\nexport interface UseUsersReturn {\n /**\n * Array of users\n */\n users: EnrichedUser[]\n\n /**\n * Total number of users (for pagination)\n */\n total: number\n\n /**\n * Whether users are being fetched\n */\n isLoading: boolean\n\n /**\n * Any error that occurred\n */\n error: Error | null\n\n /**\n * Refetch users\n */\n refetch: () => Promise<void>\n\n /**\n * Invite a new user\n */\n inviteUser: (email: string, role: 'user' | 'admin') => Promise<void>\n\n /**\n * Update user role\n */\n updateUserRole: (userId: string, role: 'user' | 'admin') => Promise<void>\n\n /**\n * Delete a user\n */\n deleteUser: (userId: string) => Promise<void>\n\n /**\n * Reset user password\n */\n resetPassword: (userId: string) => Promise<{ message: string }>\n}\n\n/**\n * Hook for managing users\n *\n * Provides user list with pagination, search, and management functions.\n *\n * @example\n * ```tsx\n * function UserList() {\n * const { users, total, isLoading, refetch, inviteUser, deleteUser } = useUsers({\n * limit: 20,\n * search: searchTerm\n * })\n *\n * return (\n * <div>\n * {isLoading ? <Spinner /> : (\n * <ul>\n * {users.map(user => (\n * <li key={user.id}>\n * {user.email} - {user.role}\n * <button onClick={() => deleteUser(user.id)}>Delete</button>\n * </li>\n * ))}\n * </ul>\n * )}\n * </div>\n * )\n * }\n * ```\n */\nexport function useUsers(options: UseUsersOptions = {}): UseUsersReturn {\n const { autoFetch = true, refetchInterval = 0, ...listOptions } = options\n const client = useFluxbaseClient()\n\n const [users, setUsers] = useState<EnrichedUser[]>([])\n const [total, setTotal] = useState(0)\n const [isLoading, setIsLoading] = useState(autoFetch)\n const [error, setError] = useState<Error | null>(null)\n\n /**\n * Fetch users from API\n */\n const fetchUsers = useCallback(async () => {\n try {\n setIsLoading(true)\n setError(null)\n const { data, error: apiError } = await client.admin.listUsers(listOptions)\n if (apiError) {\n throw apiError\n }\n setUsers(data!.users)\n setTotal(data!.total)\n } catch (err) {\n setError(err as Error)\n } finally {\n setIsLoading(false)\n }\n }, [client, JSON.stringify(listOptions)])\n\n /**\n * Invite a new user\n */\n const inviteUser = useCallback(\n async (email: string, role: 'user' | 'admin'): Promise<void> => {\n await client.admin.inviteUser({ email, role })\n await fetchUsers() // Refresh list\n },\n [client, fetchUsers]\n )\n\n /**\n * Update user role\n */\n const updateUserRole = useCallback(\n async (userId: string, role: 'user' | 'admin'): Promise<void> => {\n await client.admin.updateUserRole(userId, role)\n await fetchUsers() // Refresh list\n },\n [client, fetchUsers]\n )\n\n /**\n * Delete a user\n */\n const deleteUser = useCallback(\n async (userId: string): Promise<void> => {\n await client.admin.deleteUser(userId)\n await fetchUsers() // Refresh list\n },\n [client, fetchUsers]\n )\n\n /**\n * Reset user password\n */\n const resetPassword = useCallback(\n async (userId: string): Promise<{ message: string }> => {\n const { data, error } = await client.admin.resetUserPassword(userId)\n if (error) {\n throw error\n }\n return data!\n },\n [client]\n )\n\n // Auto-fetch on mount\n useEffect(() => {\n if (autoFetch) {\n fetchUsers()\n }\n }, [autoFetch, fetchUsers])\n\n // Set up refetch interval\n useEffect(() => {\n if (refetchInterval > 0) {\n const interval = setInterval(fetchUsers, refetchInterval)\n return () => clearInterval(interval)\n }\n }, [refetchInterval, fetchUsers])\n\n return {\n users,\n total,\n isLoading,\n error,\n refetch: fetchUsers,\n inviteUser,\n updateUserRole,\n deleteUser,\n resetPassword\n }\n}\n","import { useState, useEffect, useCallback } from 'react'\nimport { useFluxbaseClient } from './context'\nimport type { ClientKey, CreateClientKeyRequest } from '@fluxbase/sdk'\n\nexport interface UseClientKeysOptions {\n /**\n * Whether to automatically fetch client keys on mount\n * @default true\n */\n autoFetch?: boolean\n}\n\nexport interface UseClientKeysReturn {\n /**\n * Array of client keys\n */\n keys: ClientKey[]\n\n /**\n * Whether keys are being fetched\n */\n isLoading: boolean\n\n /**\n * Any error that occurred\n */\n error: Error | null\n\n /**\n * Refetch client keys\n */\n refetch: () => Promise<void>\n\n /**\n * Create a new client key\n */\n createKey: (request: CreateClientKeyRequest) => Promise<{ key: string; keyData: ClientKey }>\n\n /**\n * Update a client key\n */\n updateKey: (keyId: string, update: { name?: string; description?: string }) => Promise<void>\n\n /**\n * Revoke a client key\n */\n revokeKey: (keyId: string) => Promise<void>\n\n /**\n * Delete a client key\n */\n deleteKey: (keyId: string) => Promise<void>\n}\n\n/**\n * Hook for managing client keys\n *\n * Provides client key list and management functions.\n *\n * @example\n * ```tsx\n * function ClientKeyManager() {\n * const { keys, isLoading, createKey, revokeKey } = useClientKeys()\n *\n * const handleCreate = async () => {\n * const { key, keyData } = await createKey({\n * name: 'Backend Service',\n * description: 'Client key for backend',\n * expires_at: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString()\n * })\n * alert(`Key created: ${key}`)\n * }\n *\n * return (\n * <div>\n * <button onClick={handleCreate}>Create Key</button>\n * {keys.map(k => (\n * <div key={k.id}>\n * {k.name}\n * <button onClick={() => revokeKey(k.id)}>Revoke</button>\n * </div>\n * ))}\n * </div>\n * )\n * }\n * ```\n */\nexport function useClientKeys(options: UseClientKeysOptions = {}): UseClientKeysReturn {\n const { autoFetch = true } = options\n const client = useFluxbaseClient()\n\n const [keys, setKeys] = useState<ClientKey[]>([])\n const [isLoading, setIsLoading] = useState(autoFetch)\n const [error, setError] = useState<Error | null>(null)\n\n /**\n * Fetch client keys from API\n */\n const fetchKeys = useCallback(async () => {\n try {\n setIsLoading(true)\n setError(null)\n const response = await client.admin.management.clientKeys.list()\n setKeys(response.client_keys)\n } catch (err) {\n setError(err as Error)\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n /**\n * Create a new client key\n */\n const createKey = useCallback(\n async (request: CreateClientKeyRequest): Promise<{ key: string; keyData: ClientKey }> => {\n const response = await client.admin.management.clientKeys.create(request)\n await fetchKeys() // Refresh list\n return { key: response.key, keyData: response.client_key }\n },\n [client, fetchKeys]\n )\n\n /**\n * Update a client key\n */\n const updateKey = useCallback(\n async (keyId: string, update: { name?: string; description?: string }): Promise<void> => {\n await client.admin.management.clientKeys.update(keyId, update)\n await fetchKeys() // Refresh list\n },\n [client, fetchKeys]\n )\n\n /**\n * Revoke a client key\n */\n const revokeKey = useCallback(\n async (keyId: string): Promise<void> => {\n await client.admin.management.clientKeys.revoke(keyId)\n await fetchKeys() // Refresh list\n },\n [client, fetchKeys]\n )\n\n /**\n * Delete a client key\n */\n const deleteKey = useCallback(\n async (keyId: string): Promise<void> => {\n await client.admin.management.clientKeys.delete(keyId)\n await fetchKeys() // Refresh list\n },\n [client, fetchKeys]\n )\n\n // Auto-fetch on mount\n useEffect(() => {\n if (autoFetch) {\n fetchKeys()\n }\n }, [autoFetch, fetchKeys])\n\n return {\n keys,\n isLoading,\n error,\n refetch: fetchKeys,\n createKey,\n updateKey,\n revokeKey,\n deleteKey\n }\n}\n\n/**\n * @deprecated Use useClientKeys instead\n */\nexport const useAPIKeys = useClientKeys\n\n/** @deprecated Use UseClientKeysOptions instead */\nexport type UseAPIKeysOptions = UseClientKeysOptions\n\n/** @deprecated Use UseClientKeysReturn instead */\nexport type UseAPIKeysReturn = UseClientKeysReturn\n","/**\n * Admin Settings and Management Hooks\n *\n * Hooks for managing application settings, system settings, and webhooks.\n */\n\nimport { useState, useEffect, useCallback } from 'react'\nimport { useFluxbaseClient } from './context'\nimport type {\n AppSettings,\n UpdateAppSettingsRequest,\n SystemSetting,\n UpdateSystemSettingRequest,\n Webhook,\n CreateWebhookRequest,\n UpdateWebhookRequest\n} from '@fluxbase/sdk'\n\n// ============================================================================\n// useAppSettings Hook\n// ============================================================================\n\nexport interface UseAppSettingsOptions {\n autoFetch?: boolean\n}\n\nexport interface UseAppSettingsReturn {\n settings: AppSettings | null\n isLoading: boolean\n error: Error | null\n refetch: () => Promise<void>\n updateSettings: (update: UpdateAppSettingsRequest) => Promise<void>\n}\n\n/**\n * Hook for managing application settings\n *\n * @example\n * ```tsx\n * function SettingsPanel() {\n * const { settings, isLoading, updateSettings } = useAppSettings({ autoFetch: true })\n *\n * const handleToggleFeature = async (feature: string, enabled: boolean) => {\n * await updateSettings({\n * features: { ...settings?.features, [feature]: enabled }\n * })\n * }\n *\n * return <div>...</div>\n * }\n * ```\n */\nexport function useAppSettings(options: UseAppSettingsOptions = {}): UseAppSettingsReturn {\n const { autoFetch = true } = options\n const client = useFluxbaseClient()\n\n const [settings, setSettings] = useState<AppSettings | null>(null)\n const [isLoading, setIsLoading] = useState(autoFetch)\n const [error, setError] = useState<Error | null>(null)\n\n const fetchSettings = useCallback(async () => {\n try {\n setIsLoading(true)\n setError(null)\n const appSettings = await client.admin.settings.app.get()\n setSettings(appSettings)\n } catch (err) {\n setError(err as Error)\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n const updateSettings = useCallback(\n async (update: UpdateAppSettingsRequest): Promise<void> => {\n await client.admin.settings.app.update(update)\n await fetchSettings()\n },\n [client, fetchSettings]\n )\n\n useEffect(() => {\n if (autoFetch) {\n fetchSettings()\n }\n }, [autoFetch, fetchSettings])\n\n return {\n settings,\n isLoading,\n error,\n refetch: fetchSettings,\n updateSettings\n }\n}\n\n// ============================================================================\n// useSystemSettings Hook\n// ============================================================================\n\nexport interface UseSystemSettingsOptions {\n autoFetch?: boolean\n}\n\nexport interface UseSystemSettingsReturn {\n settings: SystemSetting[]\n isLoading: boolean\n error: Error | null\n refetch: () => Promise<void>\n getSetting: (key: string) => SystemSetting | undefined\n updateSetting: (key: string, update: UpdateSystemSettingRequest) => Promise<void>\n deleteSetting: (key: string) => Promise<void>\n}\n\n/**\n * Hook for managing system settings (key-value storage)\n *\n * @example\n * ```tsx\n * function SystemSettings() {\n * const { settings, isLoading, updateSetting } = useSystemSettings({ autoFetch: true })\n *\n * const handleUpdateSetting = async (key: string, value: any) => {\n * await updateSetting(key, { value })\n * }\n *\n * return <div>...</div>\n * }\n * ```\n */\nexport function useSystemSettings(options: UseSystemSettingsOptions = {}): UseSystemSettingsReturn {\n const { autoFetch = true } = options\n const client = useFluxbaseClient()\n\n const [settings, setSettings] = useState<SystemSetting[]>([])\n const [isLoading, setIsLoading] = useState(autoFetch)\n const [error, setError] = useState<Error | null>(null)\n\n const fetchSettings = useCallback(async () => {\n try {\n setIsLoading(true)\n setError(null)\n const response = await client.admin.settings.system.list()\n setSettings(response.settings)\n } catch (err) {\n setError(err as Error)\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n const getSetting = useCallback(\n (key: string): SystemSetting | undefined => {\n return settings.find((s) => s.key === key)\n },\n [settings]\n )\n\n const updateSetting = useCallback(\n async (key: string, update: UpdateSystemSettingRequest): Promise<void> => {\n await client.admin.settings.system.update(key, update)\n await fetchSettings()\n },\n [client, fetchSettings]\n )\n\n const deleteSetting = useCallback(\n async (key: string): Promise<void> => {\n await client.admin.settings.system.delete(key)\n await fetchSettings()\n },\n [client, fetchSettings]\n )\n\n useEffect(() => {\n if (autoFetch) {\n fetchSettings()\n }\n }, [autoFetch, fetchSettings])\n\n return {\n settings,\n isLoading,\n error,\n refetch: fetchSettings,\n getSetting,\n updateSetting,\n deleteSetting\n }\n}\n\n// ============================================================================\n// useWebhooks Hook\n// ============================================================================\n\nexport interface UseWebhooksOptions {\n autoFetch?: boolean\n refetchInterval?: number\n}\n\nexport interface UseWebhooksReturn {\n webhooks: Webhook[]\n isLoading: boolean\n error: Error | null\n refetch: () => Promise<void>\n createWebhook: (webhook: CreateWebhookRequest) => Promise<Webhook>\n updateWebhook: (id: string, update: UpdateWebhookRequest) => Promise<Webhook>\n deleteWebhook: (id: string) => Promise<void>\n testWebhook: (id: string) => Promise<void>\n}\n\n/**\n * Hook for managing webhooks\n *\n * @example\n * ```tsx\n * function WebhooksManager() {\n * const { webhooks, isLoading, createWebhook, deleteWebhook } = useWebhooks({\n * autoFetch: true\n * })\n *\n * const handleCreate = async () => {\n * await createWebhook({\n * url: 'https://example.com/webhook',\n * events: ['user.created', 'user.updated'],\n * enabled: true\n * })\n * }\n *\n * return <div>...</div>\n * }\n * ```\n */\nexport function useWebhooks(options: UseWebhooksOptions = {}): UseWebhooksReturn {\n const { autoFetch = true, refetchInterval = 0 } = options\n const client = useFluxbaseClient()\n\n const [webhooks, setWebhooks] = useState<Webhook[]>([])\n const [isLoading, setIsLoading] = useState(autoFetch)\n const [error, setError] = useState<Error | null>(null)\n\n const fetchWebhooks = useCallback(async () => {\n try {\n setIsLoading(true)\n setError(null)\n const response = await client.admin.management.webhooks.list()\n setWebhooks(response.webhooks)\n } catch (err) {\n setError(err as Error)\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n const createWebhook = useCallback(\n async (webhook: CreateWebhookRequest): Promise<Webhook> => {\n const created = await client.admin.management.webhooks.create(webhook)\n await fetchWebhooks()\n return created\n },\n [client, fetchWebhooks]\n )\n\n const updateWebhook = useCallback(\n async (id: string, update: UpdateWebhookRequest): Promise<Webhook> => {\n const updated = await client.admin.management.webhooks.update(id, update)\n await fetchWebhooks()\n return updated\n },\n [client, fetchWebhooks]\n )\n\n const deleteWebhook = useCallback(\n async (id: string): Promise<void> => {\n await client.admin.management.webhooks.delete(id)\n await fetchWebhooks()\n },\n [client, fetchWebhooks]\n )\n\n const testWebhook = useCallback(\n async (id: string): Promise<void> => {\n await client.admin.management.webhooks.test(id)\n },\n [client]\n )\n\n useEffect(() => {\n if (autoFetch) {\n fetchWebhooks()\n }\n\n if (refetchInterval > 0) {\n const interval = setInterval(fetchWebhooks, refetchInterval)\n return () => clearInterval(interval)\n }\n }, [autoFetch, refetchInterval, fetchWebhooks])\n\n return {\n webhooks,\n isLoading,\n error,\n refetch: fetchWebhooks,\n createWebhook,\n updateWebhook,\n deleteWebhook,\n testWebhook\n }\n}\n"],"mappings":";AAIA,SAAS,eAAe,kBAAkC;AAcjD;AAXT,IAAM,kBAAkB,cAAqC,IAAI;AAU1D,SAAS,iBAAiB,EAAE,QAAQ,SAAS,GAA0B;AAC5E,SAAO,oBAAC,gBAAgB,UAAhB,EAAyB,OAAO,QAAS,UAAS;AAC5D;AAKO,SAAS,oBAAoC;AAClD,QAAM,SAAS,WAAW,eAAe;AAEzC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC5E;AAEA,SAAO;AACT;;;AC5BA,SAAS,aAAa,UAAU,sBAAsB;AAY/C,SAAS,UAAU;AACxB,QAAM,SAAS,kBAAkB;AAEjC,SAAO,SAAS;AAAA,IACd,UAAU,CAAC,YAAY,QAAQ,MAAM;AAAA,IACrC,SAAS,YAAY;AACnB,YAAM,EAAE,KAAK,IAAI,MAAM,OAAO,KAAK,WAAW;AAC9C,UAAI,CAAC,MAAM,SAAS;AAClB,eAAO;AAAA,MACT;AAEA,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,KAAK,eAAe;AAChD,eAAO,OAAO,MAAM,QAAQ;AAAA,MAC9B,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,WAAW,MAAO,KAAK;AAAA;AAAA,EACzB,CAAC;AACH;AAKO,SAAS,aAAa;AAC3B,QAAM,SAAS,kBAAkB;AAEjC,SAAO,SAA6B;AAAA,IAClC,UAAU,CAAC,YAAY,QAAQ,SAAS;AAAA,IACxC,SAAS,YAAY;AACnB,YAAM,EAAE,KAAK,IAAI,MAAM,OAAO,KAAK,WAAW;AAC9C,aAAO,MAAM,WAAW;AAAA,IAC1B;AAAA,IACA,WAAW,MAAO,KAAK;AAAA;AAAA,EACzB,CAAC;AACH;AAKO,SAAS,YAAY;AAC1B,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAc,eAAe;AAEnC,SAAO,YAAY;AAAA,IACjB,YAAY,OAAO,gBAAmC;AACpD,aAAO,MAAM,OAAO,KAAK,OAAO,WAAW;AAAA,IAC7C;AAAA,IACA,WAAW,CAAC,YAAY;AACtB,kBAAY,aAAa,CAAC,YAAY,QAAQ,SAAS,GAAG,OAAO;AAEjE,UAAI,UAAU,SAAS;AACrB,oBAAY,aAAa,CAAC,YAAY,QAAQ,MAAM,GAAG,QAAQ,IAAI;AAAA,MACrE;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAKO,SAAS,YAAY;AAC1B,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAc,eAAe;AAEnC,SAAO,YAAY;AAAA,IACjB,YAAY,OAAO,gBAAmC;AACpD,aAAO,MAAM,OAAO,KAAK,OAAO,WAAW;AAAA,IAC7C;AAAA,IACA,WAAW,CAAC,aAAa;AACvB,UAAI,SAAS,MAAM;AACjB,oBAAY;AAAA,UACV,CAAC,YAAY,QAAQ,SAAS;AAAA,UAC9B,SAAS,KAAK;AAAA,QAChB;AACA,oBAAY;AAAA,UACV,CAAC,YAAY,QAAQ,MAAM;AAAA,UAC3B,SAAS,KAAK;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAKO,SAAS,aAAa;AAC3B,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAc,eAAe;AAEnC,SAAO,YAAY;AAAA,IACjB,YAAY,YAAY;AACtB,YAAM,OAAO,KAAK,QAAQ;AAAA,IAC5B;AAAA,IACA,WAAW,MAAM;AACf,kBAAY,aAAa,CAAC,YAAY,QAAQ,SAAS,GAAG,IAAI;AAC9D,kBAAY,aAAa,CAAC,YAAY,QAAQ,MAAM,GAAG,IAAI;AAC3D,kBAAY,kBAAkB,EAAE,UAAU,CAAC,UAAU,EAAE,CAAC;AAAA,IAC1D;AAAA,EACF,CAAC;AACH;AAKO,SAAS,gBAAgB;AAC9B,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAc,eAAe;AAEnC,SAAO,YAAY;AAAA,IACjB,YAAY,OAAO,SAAoD;AACrE,aAAO,MAAM,OAAO,KAAK,WAAW,IAAI;AAAA,IAC1C;AAAA,IACA,WAAW,CAAC,SAAS;AACnB,kBAAY,aAAa,CAAC,YAAY,QAAQ,MAAM,GAAG,IAAI;AAAA,IAC7D;AAAA,EACF,CAAC;AACH;AAKO,SAAS,UAAU;AACxB,QAAM,EAAE,MAAM,MAAM,WAAW,cAAc,IAAI,QAAQ;AACzD,QAAM,EAAE,MAAM,SAAS,WAAW,iBAAiB,IAAI,WAAW;AAClE,QAAM,SAAS,UAAU;AACzB,QAAM,SAAS,UAAU;AACzB,QAAM,UAAU,WAAW;AAC3B,QAAM,aAAa,cAAc;AAEjC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAW,iBAAiB;AAAA,IAC5B,iBAAiB,CAAC,CAAC;AAAA,IACnB,QAAQ,OAAO;AAAA,IACf,QAAQ,OAAO;AAAA,IACf,SAAS,QAAQ;AAAA,IACjB,YAAY,WAAW;AAAA,IACvB,aAAa,OAAO;AAAA,IACpB,aAAa,OAAO;AAAA,IACpB,cAAc,QAAQ;AAAA,IACtB,YAAY,WAAW;AAAA,EACzB;AACF;;;AC1JA,SAAS,YAAAA,iBAAgB;AAGzB,SAAS,aAAa,WAAW,QAAQ,gBAAgB;AAmBlD,SAAS,mBAAmB;AACjC,QAAM,SAAS,kBAAkB;AAEjC,SAAOC,UAAwB;AAAA,IAC7B,UAAU,CAAC,YAAY,QAAQ,WAAW,QAAQ;AAAA,IAClD,SAAS,YAAY;AACnB,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK,iBAAiB;AAC3D,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AACA,aAAO;AAAA,IACT;AAAA,IACA,WAAW,MAAO,KAAK;AAAA;AAAA,IACvB,QAAQ,MAAO,KAAK,KAAK;AAAA;AAAA,EAC3B,CAAC;AACH;AA4FO,SAAS,WAAW,UAA0C;AACnE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAuB,IAAI;AAGrD,QAAM,qBAAqB,OAAyC,IAAI;AACxE,QAAM,qBAAqB,OAAwC,IAAI;AAGvE,QAAM,WAAW,YAAY,CAAC,aAAqB;AACjD,aAAS,QAAQ;AACjB,iBAAa,KAAK;AAClB,aAAS,IAAI;AACb,eAAW,IAAI;AAGf,QAAI,mBAAmB,SAAS;AAC9B,yBAAmB,QAAQ,QAAQ;AACnC,yBAAmB,UAAU;AAC7B,yBAAmB,UAAU;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,WAAW,YAAY,MAAM;AACjC,aAAS,IAAI;AACb,eAAW,IAAI;AAAA,EACjB,GAAG,CAAC,CAAC;AAGL,QAAM,UAAU,YAAY,CAAC,QAAe;AAC1C,aAAS,GAAG;AACZ,iBAAa,KAAK;AAClB,aAAS,IAAI;AAGb,QAAI,mBAAmB,SAAS;AAC9B,yBAAmB,QAAQ,GAAG;AAC9B,yBAAmB,UAAU;AAC7B,yBAAmB,UAAU;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,QAAQ,YAAY,MAAM;AAC9B,aAAS,IAAI;AACb,aAAS,IAAI;AACb,iBAAa,KAAK;AAAA,EACpB,GAAG,CAAC,CAAC;AAGL,QAAM,UAAU,YAAY,YAA6B;AAEvD,QAAI,OAAO;AACT,aAAO;AAAA,IACT;AAGA,QAAI,CAAC,UAAU;AACb,aAAO;AAAA,IACT;AAEA,iBAAa,IAAI;AACjB,aAAS,IAAI;AAGb,WAAO,IAAI,QAAgB,CAAC,SAAS,WAAW;AAC9C,yBAAmB,UAAU;AAC7B,yBAAmB,UAAU;AAAA,IAI/B,CAAC;AAAA,EACH,GAAG,CAAC,OAAO,QAAQ,CAAC;AAGpB,YAAU,MAAM;AACd,QAAI,UAAU;AACZ,iBAAW,IAAI;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,QAAQ,CAAC;AAEb,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AASO,SAAS,6BACd,QACA,UACS;AACT,MAAI,CAAC,QAAQ,SAAS;AACpB,WAAO;AAAA,EACT;AACA,SAAO,OAAO,WAAW,SAAS,QAAQ,KAAK;AACjD;;;ACjPA,SAAS,YAAAC,iBAAgB;AA6ElB,SAAS,gBAAgB;AAC9B,QAAM,SAAS,kBAAkB;AAEjC,SAAOC,UAAqB;AAAA,IAC1B,UAAU,CAAC,YAAY,QAAQ,QAAQ;AAAA,IACvC,SAAS,YAAY;AACnB,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK,cAAc;AACxD,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AACA,aAAO;AAAA,IACT;AAAA,IACA,WAAW,MAAO,KAAK;AAAA;AAAA,IACvB,QAAQ,MAAO,KAAK;AAAA;AAAA,EACtB,CAAC;AACH;;;AChGA,SAAS,eAAAC,cAAa,YAAAC,WAAU,kBAAAC,uBAAsB;AA0B/C,SAAS,mBAAmB;AACjC,QAAM,SAAS,kBAAkB;AAEjC,SAAOC,UAAyB;AAAA,IAC9B,UAAU,CAAC,YAAY,QAAQ,QAAQ,WAAW;AAAA,IAClD,SAAS,YAAY;AACnB,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK,iBAAiB;AAC3D,UAAI,MAAO,OAAM;AACjB,aAAO,KAAK;AAAA,IACd;AAAA,IACA,WAAW,MAAO,KAAK;AAAA;AAAA,EACzB,CAAC;AACH;AA2BO,SAAS,qBAAqB;AACnC,QAAM,SAAS,kBAAkB;AAEjC,SAAOC,aAAY;AAAA,IACjB,YAAY,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,IACF,MAGM;AACJ,aAAO,MAAM,OAAO,KAAK,gBAAgB,UAAU,OAAO;AAAA,IAC5D;AAAA,EACF,CAAC;AACH;AAwBO,SAAS,oBAAoB;AAClC,QAAM,SAAS,kBAAkB;AAEjC,SAAOA,aAAY;AAAA,IACjB,YAAY,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,IACF,MAGM;AACJ,aAAO,MAAM,OAAO,KAAK,eAAe,UAAU,OAAO;AAAA,IAC3D;AAAA,EACF,CAAC;AACH;AAwCO,SAAS,wBAAwB;AACtC,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcC,gBAAe;AAEnC,SAAOD,aAAY;AAAA,IACjB,YAAY,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,IACF,MAGM;AACJ,aAAO,MAAM,OAAO,KAAK,mBAAmB,cAAc,QAAQ;AAAA,IACpE;AAAA,IACA,WAAW,CAAC,WAAW;AACrB,UAAI,OAAO,MAAM;AAEf,oBAAY;AAAA,UACV,CAAC,YAAY,QAAQ,SAAS;AAAA,UAC9B,OAAO,KAAK;AAAA,QACd;AACA,oBAAY;AAAA,UACV,CAAC,YAAY,QAAQ,MAAM;AAAA,UAC3B,OAAO,KAAK;AAAA,QACd;AAEA,oBAAY,kBAAkB,EAAE,UAAU,CAAC,UAAU,EAAE,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAuBO,SAAS,qBAAqB;AACnC,QAAM,SAAS,kBAAkB;AAEjC,SAAO,CAAC,aAA6B;AACnC,WAAO,OAAO,KAAK,mBAAmB,QAAQ;AAAA,EAChD;AACF;;;AC/LA,SAAS,eAAAE,cAAa,YAAAC,WAAU,kBAAAC,uBAAsB;AA0H/C,SAAS,gBACd,UACA,OACA,SACA;AACA,QAAM,SAAS,kBAAkB;AACjC,QAAM,gBAAgB,MAAM,QAAQ,QAAQ,IACxC,CAAC,YAAY,WAAW,GAAG,QAAQ,IACnC,CAAC,YAAY,WAAW,QAAQ;AAEpC,SAAOC,UAAsC;AAAA,IAC3C,UAAU;AAAA,IACV,SAAS,YAAY;AACnB,YAAM,WAA+B,MAAM,OAAO,QAAQ;AAAA,QACxD;AAAA,QACA,SAAS;AAAA,QACT,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAEA,UAAI,SAAS,UAAU,SAAS,OAAO,SAAS,GAAG;AACjD,cAAM,SAAS,OAAO,CAAC;AAAA,MACzB;AAEA,aAAO,SAAS;AAAA,IAClB;AAAA,IACA,SAAS,SAAS,WAAW;AAAA,IAC7B,WAAW,SAAS,aAAa;AAAA,IACjC,QAAQ,SAAS;AAAA,IACjB,sBAAsB,SAAS,wBAAwB;AAAA,IACvD,QAAQ,SAAS;AAAA,EACnB,CAAC;AACH;AA+CO,SAAS,mBAGd,UAAkB,SAA2C;AAC7D,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcC,gBAAe;AAEnC,SAAOC,aAA4C;AAAA,IACjD,YAAY,OAAO,cAAiB;AAClC,YAAM,WAA+B,MAAM,OAAO,QAAQ;AAAA,QACxD;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AAEA,UAAI,SAAS,UAAU,SAAS,OAAO,SAAS,GAAG;AACjD,cAAM,SAAS,OAAO,CAAC;AAAA,MACzB;AAEA,aAAO,SAAS;AAAA,IAClB;AAAA,IACA,WAAW,CAAC,MAAM,cAAc;AAE9B,UAAI,SAAS,mBAAmB;AAC9B,mBAAW,OAAO,QAAQ,mBAAmB;AAC3C,sBAAY,kBAAkB;AAAA,YAC5B,UAAU,CAAC,YAAY,WAAW,GAAG;AAAA,UACvC,CAAC;AAAA,QACH;AAAA,MACF;AAGA,UAAI,SAAS,aAAa,SAAS,QAAW;AAC5C,gBAAQ,UAAU,MAAM,SAAS;AAAA,MACnC;AAAA,IACF;AAAA,IACA,SAAS,CAAC,OAAO,cAAc;AAC7B,UAAI,SAAS,SAAS;AACpB,gBAAQ,QAAQ,OAAO,SAAS;AAAA,MAClC;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAwBO,SAAS,wBAAwB,SAIrC;AACD,QAAM,SAAS,kBAAkB;AAEjC,SAAOF,UAAS;AAAA,IACd,UAAU,CAAC,YAAY,WAAW,iBAAiB;AAAA,IACnD,SAAS,YAAY;AACnB,YAAM,WAAW,MAAM,OAAO,QAAQ,WAAW,SAAS,cAAc;AAExE,UAAI,SAAS,UAAU,SAAS,OAAO,SAAS,GAAG;AACjD,cAAM,SAAS,OAAO,CAAC;AAAA,MACzB;AAEA,aAAO,SAAS;AAAA,IAClB;AAAA,IACA,SAAS,SAAS,WAAW;AAAA,IAC7B,WAAW,SAAS,aAAa,MAAO,KAAK;AAAA;AAAA,EAC/C,CAAC;AACH;AA4BO,SAAS,aAAa;AAC3B,QAAM,SAAS,kBAAkB;AAEjC,SAAO;AAAA;AAAA;AAAA;AAAA,IAIL,cAAc,CACZ,OACA,WACA,YACgC;AAChC,aAAO,OAAO,QAAQ,MAAS,OAAO,WAAW,OAAO;AAAA,IAC1D;AAAA;AAAA;AAAA;AAAA,IAKA,iBAAiB,CACf,UACA,WACA,YACgC;AAChC,aAAO,OAAO,QAAQ,SAAY,UAAU,WAAW,OAAO;AAAA,IAChE;AAAA;AAAA;AAAA;AAAA,IAKA,SAAS,CACP,UACA,WACA,eACA,YACgC;AAChC,aAAO,OAAO,QAAQ,QAAW,UAAU,WAAW,eAAe,OAAO;AAAA,IAC9E;AAAA;AAAA;AAAA;AAAA,IAKA,YAAY,CAAC,YAAoC;AAC/C,aAAO,OAAO,QAAQ,WAAW,OAAO;AAAA,IAC1C;AAAA,EACF;AACF;;;ACnYA,SAAS,YAAAG,WAAU,eAAAC,cAAa,kBAAAC,uBAA4C;AAgBrE,SAAS,iBACd,YACA,SACA;AACA,QAAM,SAAS,kBAAkB;AAGjC,QAAM,WAAW,SAAS,YAAY,CAAC,YAAY,SAAS,WAAW,SAAS,CAAC;AAEjF,SAAOC,UAAS;AAAA,IACd;AAAA,IACA,SAAS,YAAY;AACnB,YAAM,QAAQ,WAAW,MAAM;AAC/B,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,MAAM,QAAQ;AAE5C,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAQ,MAAM,QAAQ,IAAI,IAAI,OAAO,OAAO,CAAC,IAAI,IAAI,CAAC;AAAA,IACxD;AAAA,IACA,GAAG;AAAA,EACL,CAAC;AACH;AAOO,SAAS,SACd,OACA,YACA,SACA;AACA,QAAM,SAAS,kBAAkB;AAEjC,SAAO;AAAA,IACL,CAACC,YAAW;AACV,YAAM,QAAQA,QAAO,KAAQ,KAAK;AAClC,aAAO,aAAa,WAAW,KAAK,IAAI;AAAA,IAC1C;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,UAAU,SAAS,YAAY,CAAC,YAAY,SAAS,OAAO,YAAY,SAAS,CAAC;AAAA,IACpF;AAAA,EACF;AACF;AAKO,SAAS,UAAmB,OAAe;AAChD,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcC,gBAAe;AAEnC,SAAOC,aAAY;AAAA,IACjB,YAAY,OAAO,SAAoC;AACrD,YAAM,QAAQ,OAAO,KAAQ,KAAK;AAClC,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM,MAAM,OAAO,IAAkB;AAErE,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT;AAAA,IACA,WAAW,MAAM;AAEf,kBAAY,kBAAkB,EAAE,UAAU,CAAC,YAAY,SAAS,KAAK,EAAE,CAAC;AAAA,IAC1E;AAAA,EACF,CAAC;AACH;AAKO,SAAS,UAAmB,OAAe;AAChD,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcD,gBAAe;AAEnC,SAAOC,aAAY;AAAA,IACjB,YAAY,OAAO,WAA0F;AAC3G,YAAM,QAAQ,OAAO,KAAQ,KAAK;AAClC,YAAM,aAAa,OAAO,WAAW,KAAK;AAC1C,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM,WAAW,OAAO,OAAO,IAAI;AAEnE,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT;AAAA,IACA,WAAW,MAAM;AACf,kBAAY,kBAAkB,EAAE,UAAU,CAAC,YAAY,SAAS,KAAK,EAAE,CAAC;AAAA,IAC1E;AAAA,EACF,CAAC;AACH;AAKO,SAAS,UAAmB,OAAe;AAChD,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcD,gBAAe;AAEnC,SAAOC,aAAY;AAAA,IACjB,YAAY,OAAO,SAAoC;AACrD,YAAM,QAAQ,OAAO,KAAQ,KAAK;AAClC,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM,MAAM,OAAO,IAAkB;AAErE,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT;AAAA,IACA,WAAW,MAAM;AACf,kBAAY,kBAAkB,EAAE,UAAU,CAAC,YAAY,SAAS,KAAK,EAAE,CAAC;AAAA,IAC1E;AAAA,EACF,CAAC;AACH;AAKO,SAAS,UAAmB,OAAe;AAChD,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcD,gBAAe;AAEnC,SAAOC,aAAY;AAAA,IACjB,YAAY,OAAO,eAA4D;AAC7E,YAAM,QAAQ,OAAO,KAAQ,KAAK;AAClC,YAAM,aAAa,WAAW,KAAK;AACnC,YAAM,EAAE,MAAM,IAAI,MAAM,WAAW,OAAO;AAE1C,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,WAAW,MAAM;AACf,kBAAY,kBAAkB,EAAE,UAAU,CAAC,YAAY,SAAS,KAAK,EAAE,CAAC;AAAA,IAC1E;AAAA,EACF,CAAC;AACH;;;AChKA,SAAS,aAAAC,YAAW,UAAAC,eAAc;AAClC,SAAS,kBAAAC,uBAAsB;AA6CxB,SAAS,YAAY,SAA6B;AACvD,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcC,gBAAe;AACnC,QAAM,aAAaC;AAAA,IACjB;AAAA,EACF;AAEA,QAAM;AAAA,IACJ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,IACA,UAAU;AAAA,EACZ,IAAI;AAEJ,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAGA,UAAM,UAAU,OAAO,SAAS,QAAQ,WAAW;AACnD,eAAW,UAAU;AAErB,UAAM,eAAe,CAAC,YAA4C;AAEhE,UAAI,UAAU;AACZ,iBAAS,OAAO;AAAA,MAClB;AAGA,UAAI,gBAAgB;AAElB,cAAM,YAAY,YAAY,QAAQ,WAAW,EAAE;AAEnD,cAAM,MAAM,iBAAiB,CAAC,YAAY,SAAS,SAAS;AAC5D,oBAAY,kBAAkB,EAAE,UAAU,IAAI,CAAC;AAAA,MACjD;AAAA,IACF;AAEA,YAAQ,GAAG,OAAO,YAAY,EAAE,UAAU;AAE1C,WAAO,MAAM;AACX,cAAQ,YAAY;AACpB,iBAAW,UAAU;AAAA,IACvB;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,SAAS,WAAW;AAAA,EACtB;AACF;AAOO,SAAS,qBACd,OACA,SACA;AACA,SAAO,YAAY;AAAA,IACjB,GAAG;AAAA,IACH,SAAS,SAAS,KAAK;AAAA,EACzB,CAAC;AACH;AAKO,SAAS,gBACd,OACA,UACA,SACA;AACA,SAAO,YAAY;AAAA,IACjB,GAAG;AAAA,IACH,SAAS,SAAS,KAAK;AAAA,IACvB,OAAO;AAAA,IACP;AAAA,EACF,CAAC;AACH;AAKO,SAAS,gBACd,OACA,UACA,SACA;AACA,SAAO,YAAY;AAAA,IACjB,GAAG;AAAA,IACH,SAAS,SAAS,KAAK;AAAA,IACvB,OAAO;AAAA,IACP;AAAA,EACF,CAAC;AACH;AAKO,SAAS,gBACd,OACA,UACA,SACA;AACA,SAAO,YAAY;AAAA,IACjB,GAAG;AAAA,IACH,SAAS,SAAS,KAAK;AAAA,IACvB,OAAO;AAAA,IACP;AAAA,EACF,CAAC;AACH;;;AC1KA,SAAS,YAAAC,iBAAgB;AACzB;AAAA,EACE,eAAAC;AAAA,EACA,YAAAC;AAAA,EACA,kBAAAC;AAAA,OAEK;AAaA,SAAS,eACd,QACA,SAEA;AACA,QAAM,SAAS,kBAAkB;AACjC,QAAM,EAAE,QAAQ,OAAO,QAAQ,GAAG,aAAa,IAAI,WAAW,CAAC;AAE/D,SAAOC,UAAS;AAAA,IACd,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE,QAAQ,OAAO,OAAO;AAAA,IAC1B;AAAA,IACA,SAAS,YAAY;AACnB,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,QAClC,KAAK,MAAM,EACX,KAAK,EAAE,QAAQ,OAAO,OAAO,CAAC;AAEjC,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO,QAAQ,CAAC;AAAA,IAClB;AAAA,IACA,GAAG;AAAA,EACL,CAAC;AACH;AAwBO,SAAS,iBAAiB,QAAgB;AAC/C,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcC,gBAAe;AAEnC,SAAOC,aAAY;AAAA,IACjB,YAAY,OAAO,WAIb;AACJ,YAAM,EAAE,MAAM,MAAM,QAAQ,IAAI;AAChC,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,QAClC,KAAK,MAAM,EACX,OAAO,MAAM,MAAM,OAAO;AAE7B,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT;AAAA,IACA,WAAW,MAAM;AAEf,kBAAY,kBAAkB;AAAA,QAC5B,UAAU,CAAC,YAAY,WAAW,QAAQ,MAAM;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAmBO,SAAS,6BAA6B,QAAgB;AAC3D,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcD,gBAAe;AACnC,QAAM,CAAC,UAAU,WAAW,IAAIE,UAAgC,IAAI;AAEpE,QAAM,WAAWD,aAAY;AAAA,IAC3B,YAAY,OAAO,WAIb;AACJ,YAAM,EAAE,MAAM,MAAM,QAAQ,IAAI;AAGhC,kBAAY,EAAE,QAAQ,GAAG,OAAO,GAAG,YAAY,EAAE,CAAC;AAElD,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,QAClC,KAAK,MAAM,EACX,OAAO,MAAM,MAAM;AAAA,QAClB,GAAG;AAAA,QACH,kBAAkB,CAAC,MAA8C;AAC/D,sBAAY,CAAC;AAAA,QACf;AAAA,MACF,CAAC;AAEH,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT;AAAA,IACA,WAAW,MAAM;AAEf,kBAAY,kBAAkB;AAAA,QAC5B,UAAU,CAAC,YAAY,WAAW,QAAQ,MAAM;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,IACA,SAAS,MAAM;AAEb,kBAAY,IAAI;AAAA,IAClB;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA,OAAO,MAAM,YAAY,IAAI;AAAA,EAC/B;AACF;AAKO,SAAS,mBACd,QACA,MACA,UAAU,MACV;AACA,QAAM,SAAS,kBAAkB;AAEjC,SAAOF,UAAS;AAAA,IACd,UAAU,CAAC,YAAY,WAAW,QAAQ,YAAY,IAAI;AAAA,IAC1D,SAAS,YAAY;AACnB,UAAI,CAAC,MAAM;AACT,eAAO;AAAA,MACT;AAEA,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,QAAQ,KAAK,MAAM,EAAE,SAAS,IAAI;AAEvE,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT;AAAA,IACA,SAAS,WAAW,CAAC,CAAC;AAAA,EACxB,CAAC;AACH;AAKO,SAAS,iBAAiB,QAAgB;AAC/C,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcC,gBAAe;AAEnC,SAAOC,aAAY;AAAA,IACjB,YAAY,OAAO,UAAoB;AACrC,YAAM,EAAE,MAAM,IAAI,MAAM,OAAO,QAAQ,KAAK,MAAM,EAAE,OAAO,KAAK;AAEhE,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,WAAW,MAAM;AACf,kBAAY,kBAAkB;AAAA,QAC5B,UAAU,CAAC,YAAY,WAAW,QAAQ,MAAM;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAKO,SAAS,oBAAoB,QAAgB,MAAqB;AACvE,QAAM,SAAS,kBAAkB;AAEjC,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,KAAK,IAAI,OAAO,QAAQ,KAAK,MAAM,EAAE,aAAa,IAAI;AAC9D,SAAO,KAAK;AACd;AA0BO,SAAS,uBACd,QACA,MACA,WACe;AACf,QAAM,SAAS,kBAAkB;AAEjC,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,QAAQ,KAAK,MAAM,EAAE,gBAAgB,MAAM,SAAS;AACpE;AAOO,SAAS,oBACd,QACA,MACA,WACA;AACA,QAAM,SAAS,kBAAkB;AAEjC,SAAOF,UAAS;AAAA,IACd,UAAU,CAAC,YAAY,WAAW,QAAQ,cAAc,MAAM,SAAS;AAAA,IACvE,SAAS,YAAY;AACnB,UAAI,CAAC,MAAM;AACT,eAAO;AAAA,MACT;AAEA,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,QAClC,KAAK,MAAM,EACX,gBAAgB,MAAM,EAAE,UAAU,CAAC;AAEtC,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO,MAAM,aAAa;AAAA,IAC5B;AAAA,IACA,SAAS,CAAC,CAAC;AAAA,IACX,WAAW,YAAY,YAAY,MAAO,MAAQ,MAAO,KAAK;AAAA;AAAA,EAChE,CAAC;AACH;AA2BO,SAAS,+BACd,QACA,MACA,SACA;AACA,QAAM,SAAS,kBAAkB;AACjC,QAAM,YAAY,SAAS;AAG3B,QAAM,eAAe,SAAS,YAC1B,KAAK,UAAU,QAAQ,SAAS,IAChC;AAEJ,SAAOA,UAAS;AAAA,IACd,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,SAAS,YAAY;AACnB,UAAI,CAAC,MAAM;AACT,eAAO;AAAA,MACT;AAEA,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,QAClC,KAAK,MAAM,EACX,gBAAgB,MAAM,OAAO;AAEhC,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO,MAAM,aAAa;AAAA,IAC5B;AAAA,IACA,SAAS,CAAC,CAAC;AAAA,IACX,WAAW,YAAY,YAAY,MAAO,MAAQ,MAAO,KAAK;AAAA;AAAA,EAChE,CAAC;AACH;AAKO,SAAS,eAAe,QAAgB;AAC7C,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcC,gBAAe;AAEnC,SAAOC,aAAY;AAAA,IACjB,YAAY,OAAO,WAAiD;AAClE,YAAM,EAAE,UAAU,OAAO,IAAI;AAC7B,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,QAClC,KAAK,MAAM,EACX,KAAK,UAAU,MAAM;AAExB,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT;AAAA,IACA,WAAW,MAAM;AACf,kBAAY,kBAAkB;AAAA,QAC5B,UAAU,CAAC,YAAY,WAAW,QAAQ,MAAM;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAKO,SAAS,eAAe,QAAgB;AAC7C,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcD,gBAAe;AAEnC,SAAOC,aAAY;AAAA,IACjB,YAAY,OAAO,WAAiD;AAClE,YAAM,EAAE,UAAU,OAAO,IAAI;AAC7B,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,QAClC,KAAK,MAAM,EACX,KAAK,UAAU,MAAM;AAExB,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO;AAAA,IACT;AAAA,IACA,WAAW,MAAM;AACf,kBAAY,kBAAkB;AAAA,QAC5B,UAAU,CAAC,YAAY,WAAW,QAAQ,MAAM;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAKO,SAAS,oBAAoB;AAClC,QAAM,SAAS,kBAAkB;AAEjC,SAAOF,UAAS;AAAA,IACd,UAAU,CAAC,YAAY,WAAW,SAAS;AAAA,IAC3C,SAAS,YAAY;AACnB,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,QAAQ,YAAY;AAEzD,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAEA,aAAO,QAAQ,CAAC;AAAA,IAClB;AAAA,EACF,CAAC;AACH;AAKO,SAAS,kBAAkB;AAChC,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcC,gBAAe;AAEnC,SAAOC,aAAY;AAAA,IACjB,YAAY,OAAO,eAAuB;AACxC,YAAM,EAAE,MAAM,IAAI,MAAM,OAAO,QAAQ,aAAa,UAAU;AAE9D,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,WAAW,MAAM;AACf,kBAAY,kBAAkB;AAAA,QAC5B,UAAU,CAAC,YAAY,WAAW,SAAS;AAAA,MAC7C,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAKO,SAAS,kBAAkB;AAChC,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAcD,gBAAe;AAEnC,SAAOC,aAAY;AAAA,IACjB,YAAY,OAAO,eAAuB;AACxC,YAAM,EAAE,MAAM,IAAI,MAAM,OAAO,QAAQ,aAAa,UAAU;AAE9D,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,WAAW,MAAM;AACf,kBAAY,kBAAkB;AAAA,QAC5B,UAAU,CAAC,YAAY,WAAW,SAAS;AAAA,MAC7C,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;;;ACnfA,SAAS,YAAAE,WAAU,aAAAC,YAAW,eAAAC,oBAAmB;AAgF1C,SAAS,aACd,UAA+B,CAAC,GACZ;AACpB,QAAM,EAAE,YAAY,KAAK,IAAI;AAC7B,QAAM,SAAS,kBAAkB;AAEjC,QAAM,CAAC,MAAM,OAAO,IAAIC,UAA2B,IAAI;AACvD,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,SAAS;AACpD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AAKrD,QAAM,YAAYC,aAAY,YAAY;AACxC,QAAI;AACF,mBAAa,IAAI;AACjB,eAAS,IAAI;AACb,YAAM,EAAE,MAAM,OAAO,SAAS,IAAI,MAAM,OAAO,MAAM,GAAG;AACxD,UAAI,UAAU;AACZ,cAAM;AAAA,MACR;AACA,cAAQ,KAAM,IAAI;AAAA,IACpB,SAAS,KAAK;AACZ,cAAQ,IAAI;AACZ,eAAS,GAAY;AAAA,IACvB,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAKX,QAAM,QAAQA;AAAA,IACZ,OAAO,OAAe,aAAiD;AACrE,UAAI;AACF,qBAAa,IAAI;AACjB,iBAAS,IAAI;AACb,cAAM,EAAE,MAAM,OAAO,SAAS,IAAI,MAAM,OAAO,MAAM,MAAM;AAAA,UACzD;AAAA,UACA;AAAA,QACF,CAAC;AACD,YAAI,UAAU;AACZ,gBAAM;AAAA,QACR;AACA,gBAAQ,KAAM,IAAI;AAClB,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,iBAAS,GAAY;AACrB,cAAM;AAAA,MACR,UAAE;AACA,qBAAa,KAAK;AAAA,MACpB;AAAA,IACF;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAKA,QAAM,SAASA,aAAY,YAA2B;AACpD,QAAI;AACF,mBAAa,IAAI;AACjB,eAAS,IAAI;AAEb,cAAQ,IAAI;AAAA,IAEd,SAAS,KAAK;AACZ,eAAS,GAAY;AACrB,YAAM;AAAA,IACR,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,CAAC;AAKL,QAAM,UAAUA,aAAY,YAA2B;AACrD,UAAM,UAAU;AAAA,EAClB,GAAG,CAAC,SAAS,CAAC;AAGd,EAAAC,WAAU,MAAM;AACd,QAAI,WAAW;AACb,gBAAU;AAAA,IACZ;AAAA,EACF,GAAG,CAAC,WAAW,SAAS,CAAC;AAEzB,SAAO;AAAA,IACL;AAAA,IACA,iBAAiB,SAAS;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AClLA,SAAS,YAAAC,WAAU,aAAAC,YAAW,eAAAC,oBAAmB;AA+F1C,SAAS,SAAS,UAA2B,CAAC,GAAmB;AACtE,QAAM,EAAE,YAAY,MAAM,kBAAkB,GAAG,GAAG,YAAY,IAAI;AAClE,QAAM,SAAS,kBAAkB;AAEjC,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAyB,CAAC,CAAC;AACrD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,CAAC;AACpC,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,SAAS;AACpD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AAKrD,QAAM,aAAaC,aAAY,YAAY;AACzC,QAAI;AACF,mBAAa,IAAI;AACjB,eAAS,IAAI;AACb,YAAM,EAAE,MAAM,OAAO,SAAS,IAAI,MAAM,OAAO,MAAM,UAAU,WAAW;AAC1E,UAAI,UAAU;AACZ,cAAM;AAAA,MACR;AACA,eAAS,KAAM,KAAK;AACpB,eAAS,KAAM,KAAK;AAAA,IACtB,SAAS,KAAK;AACZ,eAAS,GAAY;AAAA,IACvB,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,QAAQ,KAAK,UAAU,WAAW,CAAC,CAAC;AAKxC,QAAM,aAAaA;AAAA,IACjB,OAAO,OAAe,SAA0C;AAC9D,YAAM,OAAO,MAAM,WAAW,EAAE,OAAO,KAAK,CAAC;AAC7C,YAAM,WAAW;AAAA,IACnB;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AAKA,QAAM,iBAAiBA;AAAA,IACrB,OAAO,QAAgB,SAA0C;AAC/D,YAAM,OAAO,MAAM,eAAe,QAAQ,IAAI;AAC9C,YAAM,WAAW;AAAA,IACnB;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AAKA,QAAM,aAAaA;AAAA,IACjB,OAAO,WAAkC;AACvC,YAAM,OAAO,MAAM,WAAW,MAAM;AACpC,YAAM,WAAW;AAAA,IACnB;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AAKA,QAAM,gBAAgBA;AAAA,IACpB,OAAO,WAAiD;AACtD,YAAM,EAAE,MAAM,OAAAC,OAAM,IAAI,MAAM,OAAO,MAAM,kBAAkB,MAAM;AACnE,UAAIA,QAAO;AACT,cAAMA;AAAA,MACR;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAGA,EAAAC,WAAU,MAAM;AACd,QAAI,WAAW;AACb,iBAAW;AAAA,IACb;AAAA,EACF,GAAG,CAAC,WAAW,UAAU,CAAC;AAG1B,EAAAA,WAAU,MAAM;AACd,QAAI,kBAAkB,GAAG;AACvB,YAAM,WAAW,YAAY,YAAY,eAAe;AACxD,aAAO,MAAM,cAAc,QAAQ;AAAA,IACrC;AAAA,EACF,GAAG,CAAC,iBAAiB,UAAU,CAAC;AAEhC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACrMA,SAAS,YAAAC,WAAU,aAAAC,YAAW,eAAAC,oBAAmB;AAuF1C,SAAS,cAAc,UAAgC,CAAC,GAAwB;AACrF,QAAM,EAAE,YAAY,KAAK,IAAI;AAC7B,QAAM,SAAS,kBAAkB;AAEjC,QAAM,CAAC,MAAM,OAAO,IAAIC,UAAsB,CAAC,CAAC;AAChD,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,SAAS;AACpD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AAKrD,QAAM,YAAYC,aAAY,YAAY;AACxC,QAAI;AACF,mBAAa,IAAI;AACjB,eAAS,IAAI;AACb,YAAM,WAAW,MAAM,OAAO,MAAM,WAAW,WAAW,KAAK;AAC/D,cAAQ,SAAS,WAAW;AAAA,IAC9B,SAAS,KAAK;AACZ,eAAS,GAAY;AAAA,IACvB,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAKX,QAAM,YAAYA;AAAA,IAChB,OAAO,YAAkF;AACvF,YAAM,WAAW,MAAM,OAAO,MAAM,WAAW,WAAW,OAAO,OAAO;AACxE,YAAM,UAAU;AAChB,aAAO,EAAE,KAAK,SAAS,KAAK,SAAS,SAAS,WAAW;AAAA,IAC3D;AAAA,IACA,CAAC,QAAQ,SAAS;AAAA,EACpB;AAKA,QAAM,YAAYA;AAAA,IAChB,OAAO,OAAe,WAAmE;AACvF,YAAM,OAAO,MAAM,WAAW,WAAW,OAAO,OAAO,MAAM;AAC7D,YAAM,UAAU;AAAA,IAClB;AAAA,IACA,CAAC,QAAQ,SAAS;AAAA,EACpB;AAKA,QAAM,YAAYA;AAAA,IAChB,OAAO,UAAiC;AACtC,YAAM,OAAO,MAAM,WAAW,WAAW,OAAO,KAAK;AACrD,YAAM,UAAU;AAAA,IAClB;AAAA,IACA,CAAC,QAAQ,SAAS;AAAA,EACpB;AAKA,QAAM,YAAYA;AAAA,IAChB,OAAO,UAAiC;AACtC,YAAM,OAAO,MAAM,WAAW,WAAW,OAAO,KAAK;AACrD,YAAM,UAAU;AAAA,IAClB;AAAA,IACA,CAAC,QAAQ,SAAS;AAAA,EACpB;AAGA,EAAAC,WAAU,MAAM;AACd,QAAI,WAAW;AACb,gBAAU;AAAA,IACZ;AAAA,EACF,GAAG,CAAC,WAAW,SAAS,CAAC;AAEzB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKO,IAAM,aAAa;;;AC5K1B,SAAS,YAAAC,WAAU,aAAAC,YAAW,eAAAC,oBAAmB;AA8C1C,SAAS,eAAe,UAAiC,CAAC,GAAyB;AACxF,QAAM,EAAE,YAAY,KAAK,IAAI;AAC7B,QAAM,SAAS,kBAAkB;AAEjC,QAAM,CAAC,UAAU,WAAW,IAAIC,UAA6B,IAAI;AACjE,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,SAAS;AACpD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AAErD,QAAM,gBAAgBC,aAAY,YAAY;AAC5C,QAAI;AACF,mBAAa,IAAI;AACjB,eAAS,IAAI;AACb,YAAM,cAAc,MAAM,OAAO,MAAM,SAAS,IAAI,IAAI;AACxD,kBAAY,WAAW;AAAA,IACzB,SAAS,KAAK;AACZ,eAAS,GAAY;AAAA,IACvB,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,iBAAiBA;AAAA,IACrB,OAAO,WAAoD;AACzD,YAAM,OAAO,MAAM,SAAS,IAAI,OAAO,MAAM;AAC7C,YAAM,cAAc;AAAA,IACtB;AAAA,IACA,CAAC,QAAQ,aAAa;AAAA,EACxB;AAEA,EAAAC,WAAU,MAAM;AACd,QAAI,WAAW;AACb,oBAAc;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,WAAW,aAAa,CAAC;AAE7B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,EACF;AACF;AAoCO,SAAS,kBAAkB,UAAoC,CAAC,GAA4B;AACjG,QAAM,EAAE,YAAY,KAAK,IAAI;AAC7B,QAAM,SAAS,kBAAkB;AAEjC,QAAM,CAAC,UAAU,WAAW,IAAIF,UAA0B,CAAC,CAAC;AAC5D,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,SAAS;AACpD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AAErD,QAAM,gBAAgBC,aAAY,YAAY;AAC5C,QAAI;AACF,mBAAa,IAAI;AACjB,eAAS,IAAI;AACb,YAAM,WAAW,MAAM,OAAO,MAAM,SAAS,OAAO,KAAK;AACzD,kBAAY,SAAS,QAAQ;AAAA,IAC/B,SAAS,KAAK;AACZ,eAAS,GAAY;AAAA,IACvB,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,aAAaA;AAAA,IACjB,CAAC,QAA2C;AAC1C,aAAO,SAAS,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG;AAAA,IAC3C;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,gBAAgBA;AAAA,IACpB,OAAO,KAAa,WAAsD;AACxE,YAAM,OAAO,MAAM,SAAS,OAAO,OAAO,KAAK,MAAM;AACrD,YAAM,cAAc;AAAA,IACtB;AAAA,IACA,CAAC,QAAQ,aAAa;AAAA,EACxB;AAEA,QAAM,gBAAgBA;AAAA,IACpB,OAAO,QAA+B;AACpC,YAAM,OAAO,MAAM,SAAS,OAAO,OAAO,GAAG;AAC7C,YAAM,cAAc;AAAA,IACtB;AAAA,IACA,CAAC,QAAQ,aAAa;AAAA,EACxB;AAEA,EAAAC,WAAU,MAAM;AACd,QAAI,WAAW;AACb,oBAAc;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,WAAW,aAAa,CAAC;AAE7B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AA4CO,SAAS,YAAY,UAA8B,CAAC,GAAsB;AAC/E,QAAM,EAAE,YAAY,MAAM,kBAAkB,EAAE,IAAI;AAClD,QAAM,SAAS,kBAAkB;AAEjC,QAAM,CAAC,UAAU,WAAW,IAAIF,UAAoB,CAAC,CAAC;AACtD,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,SAAS;AACpD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AAErD,QAAM,gBAAgBC,aAAY,YAAY;AAC5C,QAAI;AACF,mBAAa,IAAI;AACjB,eAAS,IAAI;AACb,YAAM,WAAW,MAAM,OAAO,MAAM,WAAW,SAAS,KAAK;AAC7D,kBAAY,SAAS,QAAQ;AAAA,IAC/B,SAAS,KAAK;AACZ,eAAS,GAAY;AAAA,IACvB,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,gBAAgBA;AAAA,IACpB,OAAO,YAAoD;AACzD,YAAM,UAAU,MAAM,OAAO,MAAM,WAAW,SAAS,OAAO,OAAO;AACrE,YAAM,cAAc;AACpB,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,aAAa;AAAA,EACxB;AAEA,QAAM,gBAAgBA;AAAA,IACpB,OAAO,IAAY,WAAmD;AACpE,YAAM,UAAU,MAAM,OAAO,MAAM,WAAW,SAAS,OAAO,IAAI,MAAM;AACxE,YAAM,cAAc;AACpB,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,aAAa;AAAA,EACxB;AAEA,QAAM,gBAAgBA;AAAA,IACpB,OAAO,OAA8B;AACnC,YAAM,OAAO,MAAM,WAAW,SAAS,OAAO,EAAE;AAChD,YAAM,cAAc;AAAA,IACtB;AAAA,IACA,CAAC,QAAQ,aAAa;AAAA,EACxB;AAEA,QAAM,cAAcA;AAAA,IAClB,OAAO,OAA8B;AACnC,YAAM,OAAO,MAAM,WAAW,SAAS,KAAK,EAAE;AAAA,IAChD;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,EAAAC,WAAU,MAAM;AACd,QAAI,WAAW;AACb,oBAAc;AAAA,IAChB;AAEA,QAAI,kBAAkB,GAAG;AACvB,YAAM,WAAW,YAAY,eAAe,eAAe;AAC3D,aAAO,MAAM,cAAc,QAAQ;AAAA,IACrC;AAAA,EACF,GAAG,CAAC,WAAW,iBAAiB,aAAa,CAAC;AAE9C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":["useQuery","useQuery","useQuery","useQuery","useMutation","useQuery","useQueryClient","useQuery","useMutation","useQueryClient","useMutation","useQuery","useQueryClient","useQuery","useQueryClient","useMutation","useQuery","useMutation","useQueryClient","useQuery","client","useQueryClient","useMutation","useEffect","useRef","useQueryClient","useQueryClient","useRef","useEffect","useState","useMutation","useQuery","useQueryClient","useQuery","useQueryClient","useMutation","useState","useState","useEffect","useCallback","useState","useCallback","useEffect","useState","useEffect","useCallback","useState","useCallback","error","useEffect","useState","useEffect","useCallback","useState","useCallback","useEffect","useState","useEffect","useCallback","useState","useCallback","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../src/context.tsx","../src/use-auth.ts","../src/use-captcha.ts","../src/use-auth-config.ts","../src/use-saml.ts","../src/use-graphql.ts","../src/use-query.ts","../src/use-realtime.ts","../src/use-storage.ts","../src/use-admin-auth.ts","../src/use-users.ts","../src/use-client-keys.ts","../src/use-admin-hooks.ts"],"sourcesContent":["/**\n * React context for Fluxbase client\n */\n\nimport { createContext, useContext, type ReactNode } from 'react'\nimport type { FluxbaseClient } from '@fluxbase/sdk'\n\nconst FluxbaseContext = createContext<FluxbaseClient | null>(null)\n\nexport interface FluxbaseProviderProps {\n client: FluxbaseClient\n children: ReactNode\n}\n\n/**\n * Provider component to make Fluxbase client available throughout the app\n */\nexport function FluxbaseProvider({ client, children }: FluxbaseProviderProps) {\n return <FluxbaseContext.Provider value={client}>{children}</FluxbaseContext.Provider>\n}\n\n/**\n * Hook to access the Fluxbase client from context\n */\nexport function useFluxbaseClient(): FluxbaseClient {\n const client = useContext(FluxbaseContext)\n\n if (!client) {\n throw new Error('useFluxbaseClient must be used within a FluxbaseProvider')\n }\n\n return client\n}\n","/**\n * Authentication hooks for Fluxbase SDK\n */\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type {\n SignInCredentials,\n SignUpCredentials,\n User,\n AuthSession,\n} from \"@fluxbase/sdk\";\n\n/**\n * Hook to get the current user\n */\nexport function useUser() {\n const client = useFluxbaseClient();\n\n return useQuery({\n queryKey: [\"fluxbase\", \"auth\", \"user\"],\n queryFn: async () => {\n const { data } = await client.auth.getSession();\n if (!data?.session) {\n return null;\n }\n\n try {\n const result = await client.auth.getCurrentUser();\n return result.data?.user ?? null;\n } catch {\n return null;\n }\n },\n staleTime: 1000 * 60 * 5, // 5 minutes\n });\n}\n\n/**\n * Hook to get the current session\n */\nexport function useSession() {\n const client = useFluxbaseClient();\n\n return useQuery<AuthSession | null>({\n queryKey: [\"fluxbase\", \"auth\", \"session\"],\n queryFn: async () => {\n const { data } = await client.auth.getSession();\n return data?.session ?? null;\n },\n staleTime: 1000 * 60 * 5, // 5 minutes\n });\n}\n\n/**\n * Hook for signing in\n */\nexport function useSignIn() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (credentials: SignInCredentials) => {\n return await client.auth.signIn(credentials);\n },\n onSuccess: (session) => {\n queryClient.setQueryData([\"fluxbase\", \"auth\", \"session\"], session);\n // Only set user if this is a complete auth session (not 2FA required)\n // Check for truthy user value, not just property existence\n if (session && \"user\" in session && session.user) {\n queryClient.setQueryData([\"fluxbase\", \"auth\", \"user\"], session.user);\n }\n },\n });\n}\n\n/**\n * Hook for signing up\n */\nexport function useSignUp() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (credentials: SignUpCredentials) => {\n return await client.auth.signUp(credentials);\n },\n onSuccess: (response) => {\n if (response.data) {\n queryClient.setQueryData(\n [\"fluxbase\", \"auth\", \"session\"],\n response.data.session,\n );\n queryClient.setQueryData(\n [\"fluxbase\", \"auth\", \"user\"],\n response.data.user,\n );\n }\n },\n });\n}\n\n/**\n * Hook for signing out\n */\nexport function useSignOut() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async () => {\n await client.auth.signOut();\n },\n onSuccess: () => {\n queryClient.setQueryData([\"fluxbase\", \"auth\", \"session\"], null);\n queryClient.setQueryData([\"fluxbase\", \"auth\", \"user\"], null);\n queryClient.invalidateQueries({ queryKey: [\"fluxbase\"] });\n },\n });\n}\n\n/**\n * Hook for updating the current user\n */\nexport function useUpdateUser() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (data: Partial<Pick<User, \"email\" | \"metadata\">>) => {\n return await client.auth.updateUser(data);\n },\n onSuccess: (user) => {\n queryClient.setQueryData([\"fluxbase\", \"auth\", \"user\"], user);\n },\n });\n}\n\n/**\n * Combined auth hook with all auth state and methods\n */\nexport function useAuth() {\n const { data: user, isLoading: isLoadingUser } = useUser();\n const { data: session, isLoading: isLoadingSession } = useSession();\n const signIn = useSignIn();\n const signUp = useSignUp();\n const signOut = useSignOut();\n const updateUser = useUpdateUser();\n\n return {\n user,\n session,\n isLoading: isLoadingUser || isLoadingSession,\n isAuthenticated: !!session,\n signIn: signIn.mutateAsync,\n signUp: signUp.mutateAsync,\n signOut: signOut.mutateAsync,\n updateUser: updateUser.mutateAsync,\n isSigningIn: signIn.isPending,\n isSigningUp: signUp.isPending,\n isSigningOut: signOut.isPending,\n isUpdating: updateUser.isPending,\n };\n}\n","/**\n * CAPTCHA hooks for Fluxbase SDK\n *\n * Provides hooks to:\n * - Fetch CAPTCHA configuration from the server\n * - Manage CAPTCHA widget state\n */\n\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type { CaptchaConfig, CaptchaProvider } from \"@fluxbase/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\n/**\n * Hook to get the CAPTCHA configuration from the server\n * Use this to determine which CAPTCHA provider to load\n *\n * @example\n * ```tsx\n * function AuthPage() {\n * const { data: captchaConfig, isLoading } = useCaptchaConfig();\n *\n * if (isLoading) return <Loading />;\n *\n * return captchaConfig?.enabled ? (\n * <CaptchaWidget provider={captchaConfig.provider} siteKey={captchaConfig.site_key} />\n * ) : null;\n * }\n * ```\n */\nexport function useCaptchaConfig() {\n const client = useFluxbaseClient();\n\n return useQuery<CaptchaConfig>({\n queryKey: [\"fluxbase\", \"auth\", \"captcha\", \"config\"],\n queryFn: async () => {\n const { data, error } = await client.auth.getCaptchaConfig();\n if (error) {\n throw error;\n }\n return data!;\n },\n staleTime: 1000 * 60 * 60, // Cache for 1 hour (config rarely changes)\n gcTime: 1000 * 60 * 60 * 24, // Keep in cache for 24 hours\n });\n}\n\n/**\n * CAPTCHA widget state for managing token generation\n */\nexport interface CaptchaState {\n /** Current CAPTCHA token (null until solved) */\n token: string | null;\n /** Whether the CAPTCHA widget is ready */\n isReady: boolean;\n /** Whether a token is being generated */\n isLoading: boolean;\n /** Any error that occurred */\n error: Error | null;\n /** Reset the CAPTCHA widget */\n reset: () => void;\n /** Execute/trigger the CAPTCHA (for invisible CAPTCHA like reCAPTCHA v3) */\n execute: () => Promise<string>;\n /** Callback to be called when CAPTCHA is verified */\n onVerify: (token: string) => void;\n /** Callback to be called when CAPTCHA expires */\n onExpire: () => void;\n /** Callback to be called when CAPTCHA errors */\n onError: (error: Error) => void;\n}\n\n/**\n * Hook to manage CAPTCHA widget state\n *\n * This hook provides a standardized interface for managing CAPTCHA tokens\n * across different providers (hCaptcha, reCAPTCHA v3, Turnstile, Cap).\n *\n * Supported providers:\n * - hcaptcha: Privacy-focused visual challenge\n * - recaptcha_v3: Google's invisible risk-based CAPTCHA\n * - turnstile: Cloudflare's invisible CAPTCHA\n * - cap: Self-hosted proof-of-work CAPTCHA (https://capjs.js.org/)\n *\n * @param provider - The CAPTCHA provider type\n * @returns CAPTCHA state and callbacks\n *\n * @example\n * ```tsx\n * function LoginForm() {\n * const captcha = useCaptcha('hcaptcha');\n *\n * const handleSubmit = async (e: FormEvent) => {\n * e.preventDefault();\n *\n * // Get CAPTCHA token\n * const captchaToken = captcha.token || await captcha.execute();\n *\n * // Sign in with CAPTCHA token\n * await signIn({\n * email,\n * password,\n * captchaToken\n * });\n * };\n *\n * return (\n * <form onSubmit={handleSubmit}>\n * <input name=\"email\" />\n * <input name=\"password\" type=\"password\" />\n *\n * <HCaptcha\n * sitekey={siteKey}\n * onVerify={captcha.onVerify}\n * onExpire={captcha.onExpire}\n * onError={captcha.onError}\n * />\n *\n * <button type=\"submit\" disabled={!captcha.isReady}>\n * Sign In\n * </button>\n * </form>\n * );\n * }\n * ```\n *\n * @example Cap provider\n * ```tsx\n * function LoginForm() {\n * const { data: config } = useCaptchaConfig();\n * const captcha = useCaptcha(config?.provider);\n *\n * // For Cap, load the widget from cap_server_url\n * // <script src={`${config.cap_server_url}/widget.js`} />\n * // <cap-widget data-cap-url={config.cap_server_url} />\n * }\n * ```\n */\nexport function useCaptcha(provider?: CaptchaProvider): CaptchaState {\n const [token, setToken] = useState<string | null>(null);\n const [isReady, setIsReady] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Promise resolver for execute() method\n const executeResolverRef = useRef<((token: string) => void) | null>(null);\n const executeRejecterRef = useRef<((error: Error) => void) | null>(null);\n\n // Callback when CAPTCHA is verified\n const onVerify = useCallback((newToken: string) => {\n setToken(newToken);\n setIsLoading(false);\n setError(null);\n setIsReady(true);\n\n // Resolve the execute() promise if waiting\n if (executeResolverRef.current) {\n executeResolverRef.current(newToken);\n executeResolverRef.current = null;\n executeRejecterRef.current = null;\n }\n }, []);\n\n // Callback when CAPTCHA expires\n const onExpire = useCallback(() => {\n setToken(null);\n setIsReady(true);\n }, []);\n\n // Callback when CAPTCHA errors\n const onError = useCallback((err: Error) => {\n setError(err);\n setIsLoading(false);\n setToken(null);\n\n // Reject the execute() promise if waiting\n if (executeRejecterRef.current) {\n executeRejecterRef.current(err);\n executeResolverRef.current = null;\n executeRejecterRef.current = null;\n }\n }, []);\n\n // Reset the CAPTCHA\n const reset = useCallback(() => {\n setToken(null);\n setError(null);\n setIsLoading(false);\n }, []);\n\n // Execute/trigger the CAPTCHA (for invisible CAPTCHA)\n const execute = useCallback(async (): Promise<string> => {\n // If we already have a token, return it\n if (token) {\n return token;\n }\n\n // If CAPTCHA is not configured, return empty string\n if (!provider) {\n return \"\";\n }\n\n setIsLoading(true);\n setError(null);\n\n // Return a promise that will be resolved by onVerify\n return new Promise<string>((resolve, reject) => {\n executeResolverRef.current = resolve;\n executeRejecterRef.current = reject;\n\n // For invisible CAPTCHAs, the widget should call onVerify when done\n // The actual execution is handled by the CAPTCHA widget component\n });\n }, [token, provider]);\n\n // Mark as ready when provider is set\n useEffect(() => {\n if (provider) {\n setIsReady(true);\n }\n }, [provider]);\n\n return {\n token,\n isReady,\n isLoading,\n error,\n reset,\n execute,\n onVerify,\n onExpire,\n onError,\n };\n}\n\n/**\n * Check if CAPTCHA is required for a specific endpoint\n *\n * @param config - CAPTCHA configuration from useCaptchaConfig\n * @param endpoint - The endpoint to check (e.g., 'signup', 'login', 'password_reset')\n * @returns Whether CAPTCHA is required for this endpoint\n */\nexport function isCaptchaRequiredForEndpoint(\n config: CaptchaConfig | undefined,\n endpoint: string\n): boolean {\n if (!config?.enabled) {\n return false;\n }\n return config.endpoints?.includes(endpoint) ?? false;\n}\n","/**\n * Auth configuration hooks for Fluxbase SDK\n *\n * Provides hooks to fetch comprehensive authentication configuration\n * from the server including signup status, OAuth/SAML providers,\n * password requirements, and CAPTCHA settings.\n */\n\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type { AuthConfig } from \"@fluxbase/sdk\";\n\n/**\n * Hook to get the complete authentication configuration from the server\n *\n * Returns all public auth settings in a single request including:\n * - Signup enabled status\n * - Email verification requirements\n * - Magic link availability\n * - MFA availability\n * - Password requirements (length, complexity)\n * - Available OAuth providers (Google, GitHub, etc.)\n * - Available SAML providers (enterprise SSO)\n * - CAPTCHA configuration\n *\n * Use this to conditionally render UI elements based on server configuration,\n * such as hiding signup forms when signup is disabled or displaying available\n * OAuth provider buttons.\n *\n * @returns Query result with authentication configuration\n *\n * @example\n * ```tsx\n * function AuthPage() {\n * const { data: config, isLoading } = useAuthConfig();\n *\n * if (isLoading) return <Loading />;\n *\n * return (\n * <div>\n * {config?.signup_enabled && (\n * <SignupForm passwordMinLength={config.password_min_length} />\n * )}\n *\n * {config?.oauth_providers.map(provider => (\n * <OAuthButton\n * key={provider.provider}\n * provider={provider.provider}\n * displayName={provider.display_name}\n * authorizeUrl={provider.authorize_url}\n * />\n * ))}\n *\n * {config?.saml_providers.map(provider => (\n * <SAMLButton\n * key={provider.provider}\n * provider={provider.provider}\n * displayName={provider.display_name}\n * />\n * ))}\n * </div>\n * );\n * }\n * ```\n *\n * @example Showing password requirements\n * ```tsx\n * function PasswordInput() {\n * const { data: config } = useAuthConfig();\n *\n * return (\n * <div>\n * <input type=\"password\" minLength={config?.password_min_length} />\n * <ul>\n * <li>Minimum {config?.password_min_length || 8} characters</li>\n * {config?.password_require_uppercase && <li>One uppercase letter</li>}\n * {config?.password_require_lowercase && <li>One lowercase letter</li>}\n * {config?.password_require_number && <li>One number</li>}\n * {config?.password_require_special && <li>One special character</li>}\n * </ul>\n * </div>\n * );\n * }\n * ```\n */\nexport function useAuthConfig() {\n const client = useFluxbaseClient();\n\n return useQuery<AuthConfig>({\n queryKey: [\"fluxbase\", \"auth\", \"config\"],\n queryFn: async () => {\n const { data, error } = await client.auth.getAuthConfig();\n if (error) {\n throw error;\n }\n return data!;\n },\n staleTime: 1000 * 60 * 5, // Cache for 5 minutes (config changes infrequently)\n gcTime: 1000 * 60 * 60, // Keep in cache for 1 hour\n });\n}\n","/**\n * SAML SSO hooks for Fluxbase React SDK\n */\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type { SAMLLoginOptions, SAMLProvider } from \"@fluxbase/sdk\";\n\n/**\n * Hook to get available SAML SSO providers\n *\n * @example\n * ```tsx\n * function SAMLProviderList() {\n * const { data: providers, isLoading } = useSAMLProviders()\n *\n * if (isLoading) return <div>Loading...</div>\n *\n * return (\n * <div>\n * {providers?.map(provider => (\n * <button key={provider.id} onClick={() => signInWithSAML(provider.name)}>\n * Sign in with {provider.name}\n * </button>\n * ))}\n * </div>\n * )\n * }\n * ```\n */\nexport function useSAMLProviders() {\n const client = useFluxbaseClient();\n\n return useQuery<SAMLProvider[]>({\n queryKey: [\"fluxbase\", \"auth\", \"saml\", \"providers\"],\n queryFn: async () => {\n const { data, error } = await client.auth.getSAMLProviders();\n if (error) throw error;\n return data.providers;\n },\n staleTime: 1000 * 60 * 5, // 5 minutes - providers don't change often\n });\n}\n\n/**\n * Hook to get SAML login URL for a provider\n *\n * This hook returns a function to get the login URL for a specific provider.\n * Use this when you need more control over the redirect behavior.\n *\n * @example\n * ```tsx\n * function SAMLLoginButton({ provider }: { provider: string }) {\n * const getSAMLLoginUrl = useGetSAMLLoginUrl()\n *\n * const handleClick = async () => {\n * const { data, error } = await getSAMLLoginUrl.mutateAsync({\n * provider,\n * options: { redirectUrl: window.location.href }\n * })\n * if (!error) {\n * window.location.href = data.url\n * }\n * }\n *\n * return <button onClick={handleClick}>Login with {provider}</button>\n * }\n * ```\n */\nexport function useGetSAMLLoginUrl() {\n const client = useFluxbaseClient();\n\n return useMutation({\n mutationFn: async ({\n provider,\n options,\n }: {\n provider: string;\n options?: SAMLLoginOptions;\n }) => {\n return await client.auth.getSAMLLoginUrl(provider, options);\n },\n });\n}\n\n/**\n * Hook to initiate SAML login (redirects to IdP)\n *\n * This hook returns a mutation that when called, redirects the user to the\n * SAML Identity Provider for authentication.\n *\n * @example\n * ```tsx\n * function SAMLLoginButton() {\n * const signInWithSAML = useSignInWithSAML()\n *\n * return (\n * <button\n * onClick={() => signInWithSAML.mutate({ provider: 'okta' })}\n * disabled={signInWithSAML.isPending}\n * >\n * {signInWithSAML.isPending ? 'Redirecting...' : 'Sign in with Okta'}\n * </button>\n * )\n * }\n * ```\n */\nexport function useSignInWithSAML() {\n const client = useFluxbaseClient();\n\n return useMutation({\n mutationFn: async ({\n provider,\n options,\n }: {\n provider: string;\n options?: SAMLLoginOptions;\n }) => {\n return await client.auth.signInWithSAML(provider, options);\n },\n });\n}\n\n/**\n * Hook to handle SAML callback after IdP authentication\n *\n * Use this in your SAML callback page to complete the authentication flow.\n *\n * @example\n * ```tsx\n * function SAMLCallbackPage() {\n * const handleCallback = useHandleSAMLCallback()\n * const navigate = useNavigate()\n *\n * useEffect(() => {\n * const params = new URLSearchParams(window.location.search)\n * const samlResponse = params.get('SAMLResponse')\n *\n * if (samlResponse) {\n * handleCallback.mutate(\n * { samlResponse },\n * {\n * onSuccess: () => navigate('/dashboard'),\n * onError: (error) => console.error('SAML login failed:', error)\n * }\n * )\n * }\n * }, [])\n *\n * if (handleCallback.isPending) {\n * return <div>Completing sign in...</div>\n * }\n *\n * if (handleCallback.isError) {\n * return <div>Authentication failed: {handleCallback.error.message}</div>\n * }\n *\n * return null\n * }\n * ```\n */\nexport function useHandleSAMLCallback() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({\n samlResponse,\n provider,\n }: {\n samlResponse: string;\n provider?: string;\n }) => {\n return await client.auth.handleSAMLCallback(samlResponse, provider);\n },\n onSuccess: (result) => {\n if (result.data) {\n // Update auth state in React Query cache\n queryClient.setQueryData(\n [\"fluxbase\", \"auth\", \"session\"],\n result.data.session,\n );\n queryClient.setQueryData(\n [\"fluxbase\", \"auth\", \"user\"],\n result.data.user,\n );\n // Invalidate any dependent queries\n queryClient.invalidateQueries({ queryKey: [\"fluxbase\"] });\n }\n },\n });\n}\n\n/**\n * Hook to get SAML Service Provider metadata URL\n *\n * Returns a function that generates the SP metadata URL for a given provider.\n * Use this URL when configuring your SAML IdP.\n *\n * @example\n * ```tsx\n * function SAMLSetupInfo({ provider }: { provider: string }) {\n * const getSAMLMetadataUrl = useSAMLMetadataUrl()\n * const metadataUrl = getSAMLMetadataUrl(provider)\n *\n * return (\n * <div>\n * <p>SP Metadata URL:</p>\n * <code>{metadataUrl}</code>\n * </div>\n * )\n * }\n * ```\n */\nexport function useSAMLMetadataUrl() {\n const client = useFluxbaseClient();\n\n return (provider: string): string => {\n return client.auth.getSAMLMetadataUrl(provider);\n };\n}\n","/**\n * GraphQL hooks for Fluxbase React SDK\n *\n * Provides React Query integration for GraphQL queries and mutations.\n *\n * @example\n * ```tsx\n * import { useGraphQLQuery, useGraphQLMutation } from '@fluxbase/sdk-react'\n *\n * function UsersList() {\n * const { data, isLoading, error } = useGraphQLQuery<UsersQuery>(\n * 'users-list',\n * `query { users { id email } }`\n * )\n *\n * if (isLoading) return <div>Loading...</div>\n * if (error) return <div>Error: {error.message}</div>\n *\n * return (\n * <ul>\n * {data?.users.map(user => (\n * <li key={user.id}>{user.email}</li>\n * ))}\n * </ul>\n * )\n * }\n * ```\n */\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type {\n GraphQLResponse,\n GraphQLError,\n GraphQLRequestOptions,\n} from \"@fluxbase/sdk\";\n\n/**\n * Options for useGraphQLQuery hook\n */\nexport interface UseGraphQLQueryOptions<T> {\n /**\n * Variables to pass to the GraphQL query\n */\n variables?: Record<string, unknown>;\n\n /**\n * Operation name when the document contains multiple operations\n */\n operationName?: string;\n\n /**\n * Additional request options\n */\n requestOptions?: GraphQLRequestOptions;\n\n /**\n * Whether the query is enabled\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Time in milliseconds after which the query is considered stale\n * @default 0 (considered stale immediately)\n */\n staleTime?: number;\n\n /**\n * Time in milliseconds after which inactive query data is garbage collected\n * @default 5 minutes\n */\n gcTime?: number;\n\n /**\n * Whether to refetch on window focus\n * @default true\n */\n refetchOnWindowFocus?: boolean;\n\n /**\n * Transform function to process the response data\n */\n select?: (data: T | undefined) => T | undefined;\n}\n\n/**\n * Options for useGraphQLMutation hook\n */\nexport interface UseGraphQLMutationOptions<T, V> {\n /**\n * Operation name when the document contains multiple operations\n */\n operationName?: string;\n\n /**\n * Additional request options\n */\n requestOptions?: GraphQLRequestOptions;\n\n /**\n * Callback when mutation succeeds\n */\n onSuccess?: (data: T, variables: V) => void;\n\n /**\n * Callback when mutation fails\n */\n onError?: (error: GraphQLError, variables: V) => void;\n\n /**\n * Query keys to invalidate on success\n */\n invalidateQueries?: string[];\n}\n\n/**\n * Hook to execute GraphQL queries with React Query caching\n *\n * @typeParam T - The expected response data type\n * @param queryKey - Unique key for caching (string or array)\n * @param query - The GraphQL query string\n * @param options - Query options including variables\n * @returns React Query result object\n *\n * @example\n * ```tsx\n * interface UsersQuery {\n * users: Array<{ id: string; email: string }>\n * }\n *\n * function UsersList() {\n * const { data, isLoading } = useGraphQLQuery<UsersQuery>(\n * 'users',\n * `query { users { id email } }`\n * )\n *\n * return <div>{data?.users.length} users</div>\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With variables\n * const { data } = useGraphQLQuery<UserQuery>(\n * ['user', userId],\n * `query GetUser($id: ID!) { user(id: $id) { id email } }`,\n * { variables: { id: userId } }\n * )\n * ```\n */\nexport function useGraphQLQuery<T = unknown>(\n queryKey: string | readonly unknown[],\n query: string,\n options?: UseGraphQLQueryOptions<T>\n) {\n const client = useFluxbaseClient();\n const normalizedKey = Array.isArray(queryKey)\n ? [\"fluxbase\", \"graphql\", ...queryKey]\n : [\"fluxbase\", \"graphql\", queryKey];\n\n return useQuery<T | undefined, GraphQLError>({\n queryKey: normalizedKey,\n queryFn: async () => {\n const response: GraphQLResponse<T> = await client.graphql.execute(\n query,\n options?.variables,\n options?.operationName,\n options?.requestOptions\n );\n\n if (response.errors && response.errors.length > 0) {\n throw response.errors[0];\n }\n\n return response.data;\n },\n enabled: options?.enabled ?? true,\n staleTime: options?.staleTime ?? 0,\n gcTime: options?.gcTime,\n refetchOnWindowFocus: options?.refetchOnWindowFocus ?? true,\n select: options?.select,\n });\n}\n\n/**\n * Hook to execute GraphQL mutations\n *\n * @typeParam T - The expected response data type\n * @typeParam V - The variables type\n * @param mutation - The GraphQL mutation string\n * @param options - Mutation options\n * @returns React Query mutation result object\n *\n * @example\n * ```tsx\n * interface CreateUserMutation {\n * insertUser: { id: string; email: string }\n * }\n *\n * interface CreateUserVariables {\n * data: { email: string }\n * }\n *\n * function CreateUserForm() {\n * const mutation = useGraphQLMutation<CreateUserMutation, CreateUserVariables>(\n * `mutation CreateUser($data: UserInput!) {\n * insertUser(data: $data) { id email }\n * }`,\n * {\n * onSuccess: (data) => console.log('Created:', data.insertUser),\n * invalidateQueries: ['users']\n * }\n * )\n *\n * const handleSubmit = (email: string) => {\n * mutation.mutate({ data: { email } })\n * }\n *\n * return (\n * <button\n * onClick={() => handleSubmit('new@example.com')}\n * disabled={mutation.isPending}\n * >\n * Create User\n * </button>\n * )\n * }\n * ```\n */\nexport function useGraphQLMutation<\n T = unknown,\n V extends Record<string, unknown> = Record<string, unknown>,\n>(mutation: string, options?: UseGraphQLMutationOptions<T, V>) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation<T | undefined, GraphQLError, V>({\n mutationFn: async (variables: V) => {\n const response: GraphQLResponse<T> = await client.graphql.execute(\n mutation,\n variables,\n options?.operationName,\n options?.requestOptions\n );\n\n if (response.errors && response.errors.length > 0) {\n throw response.errors[0];\n }\n\n return response.data;\n },\n onSuccess: (data, variables) => {\n // Invalidate specified queries\n if (options?.invalidateQueries) {\n for (const key of options.invalidateQueries) {\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"graphql\", key],\n });\n }\n }\n\n // Call user's onSuccess callback\n if (options?.onSuccess && data !== undefined) {\n options.onSuccess(data, variables);\n }\n },\n onError: (error, variables) => {\n if (options?.onError) {\n options.onError(error, variables);\n }\n },\n });\n}\n\n/**\n * Hook to fetch the GraphQL schema via introspection\n *\n * @param options - Query options\n * @returns React Query result with schema introspection data\n *\n * @example\n * ```tsx\n * function SchemaExplorer() {\n * const { data, isLoading } = useGraphQLIntrospection()\n *\n * if (isLoading) return <div>Loading schema...</div>\n *\n * return (\n * <div>\n * <p>Query type: {data?.__schema.queryType.name}</p>\n * <p>Types: {data?.__schema.types.length}</p>\n * </div>\n * )\n * }\n * ```\n */\nexport function useGraphQLIntrospection(options?: {\n enabled?: boolean;\n staleTime?: number;\n requestOptions?: GraphQLRequestOptions;\n}) {\n const client = useFluxbaseClient();\n\n return useQuery({\n queryKey: [\"fluxbase\", \"graphql\", \"__introspection\"],\n queryFn: async () => {\n const response = await client.graphql.introspect(options?.requestOptions);\n\n if (response.errors && response.errors.length > 0) {\n throw response.errors[0];\n }\n\n return response.data;\n },\n enabled: options?.enabled ?? true,\n staleTime: options?.staleTime ?? 1000 * 60 * 5, // 5 minutes - schema doesn't change often\n });\n}\n\n/**\n * Hook to execute raw GraphQL operations (query or mutation)\n *\n * This is a lower-level hook that doesn't use React Query caching.\n * Useful for one-off operations or when you need full control.\n *\n * @returns Functions to execute queries and mutations\n *\n * @example\n * ```tsx\n * function AdminPanel() {\n * const { executeQuery, executeMutation } = useGraphQL()\n *\n * const handleExport = async () => {\n * const result = await executeQuery<ExportData>(\n * `query { exportAllData { url } }`\n * )\n * if (result.data) {\n * window.open(result.data.exportAllData.url)\n * }\n * }\n *\n * return <button onClick={handleExport}>Export Data</button>\n * }\n * ```\n */\nexport function useGraphQL() {\n const client = useFluxbaseClient();\n\n return {\n /**\n * Execute a GraphQL query\n */\n executeQuery: <T = unknown>(\n query: string,\n variables?: Record<string, unknown>,\n options?: GraphQLRequestOptions\n ): Promise<GraphQLResponse<T>> => {\n return client.graphql.query<T>(query, variables, options);\n },\n\n /**\n * Execute a GraphQL mutation\n */\n executeMutation: <T = unknown>(\n mutation: string,\n variables?: Record<string, unknown>,\n options?: GraphQLRequestOptions\n ): Promise<GraphQLResponse<T>> => {\n return client.graphql.mutation<T>(mutation, variables, options);\n },\n\n /**\n * Execute a GraphQL operation with an explicit operation name\n */\n execute: <T = unknown>(\n document: string,\n variables?: Record<string, unknown>,\n operationName?: string,\n options?: GraphQLRequestOptions\n ): Promise<GraphQLResponse<T>> => {\n return client.graphql.execute<T>(document, variables, operationName, options);\n },\n\n /**\n * Fetch the GraphQL schema via introspection\n */\n introspect: (options?: GraphQLRequestOptions) => {\n return client.graphql.introspect(options);\n },\n };\n}\n","/**\n * Database query hooks for Fluxbase SDK\n */\n\nimport { useQuery, useMutation, useQueryClient, type UseQueryOptions } from '@tanstack/react-query'\nimport { useFluxbaseClient } from './context'\nimport type { QueryBuilder } from '@fluxbase/sdk'\n\nexport interface UseFluxbaseQueryOptions<T> extends Omit<UseQueryOptions<T[], Error>, 'queryKey' | 'queryFn'> {\n /**\n * Custom query key. If not provided, will use table name and filters.\n */\n queryKey?: unknown[]\n}\n\n/**\n * Hook to execute a database query\n * @param buildQuery - Function that builds and returns the query\n * @param options - React Query options\n *\n * IMPORTANT: You must provide a stable `queryKey` in options for proper caching.\n * Without a custom queryKey, each render may create a new cache entry.\n *\n * @example\n * ```tsx\n * // Always provide a queryKey for stable caching\n * useFluxbaseQuery(\n * (client) => client.from('users').select('*'),\n * { queryKey: ['users', 'all'] }\n * )\n * ```\n */\nexport function useFluxbaseQuery<T = any>(\n buildQuery: (client: ReturnType<typeof useFluxbaseClient>) => QueryBuilder<T>,\n options?: UseFluxbaseQueryOptions<T>\n) {\n const client = useFluxbaseClient()\n\n // Require queryKey for stable caching - function.toString() is not reliable\n // as it can vary between renders for inline functions\n if (!options?.queryKey) {\n console.warn(\n '[useFluxbaseQuery] No queryKey provided. This may cause cache misses. ' +\n 'Please provide a stable queryKey in options.'\n )\n }\n\n const queryKey = options?.queryKey || ['fluxbase', 'query', 'unstable']\n\n return useQuery({\n queryKey,\n queryFn: async () => {\n const query = buildQuery(client)\n const { data, error } = await query.execute()\n\n if (error) {\n throw error\n }\n\n return (Array.isArray(data) ? data : data ? [data] : []) as T[]\n },\n ...options,\n })\n}\n\n/**\n * Hook for table queries with a simpler API\n * @param table - Table name\n * @param buildQuery - Optional function to build the query (e.g., add filters)\n * @param options - Query options including a stable queryKey\n *\n * NOTE: When using buildQuery with filters, provide a custom queryKey that includes\n * the filter values to ensure proper caching.\n *\n * @example\n * ```tsx\n * // Simple query - queryKey is auto-generated from table name\n * useTable('users')\n *\n * // With filters - provide queryKey including filter values\n * useTable('users',\n * (q) => q.eq('status', 'active'),\n * { queryKey: ['users', 'active'] }\n * )\n * ```\n */\nexport function useTable<T = any>(\n table: string,\n buildQuery?: (query: QueryBuilder<T>) => QueryBuilder<T>,\n options?: UseFluxbaseQueryOptions<T>\n) {\n const client = useFluxbaseClient()\n\n // Generate a stable base queryKey from table name\n // When buildQuery is provided without a custom queryKey, warn about potential cache issues\n if (buildQuery && !options?.queryKey) {\n console.warn(\n `[useTable] Using buildQuery without a custom queryKey for table \"${table}\". ` +\n 'This may cause cache misses. Provide a queryKey that includes your filter values.'\n )\n }\n\n return useFluxbaseQuery(\n (client) => {\n const query = client.from<T>(table)\n return buildQuery ? buildQuery(query) : query\n },\n {\n ...options,\n // Use table name as base key, or custom key if provided\n queryKey: options?.queryKey || ['fluxbase', 'table', table],\n }\n )\n}\n\n/**\n * Hook to insert data into a table\n */\nexport function useInsert<T = any>(table: string) {\n const client = useFluxbaseClient()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: async (data: Partial<T> | Partial<T>[]) => {\n const query = client.from<T>(table)\n const { data: result, error } = await query.insert(data as Partial<T>)\n\n if (error) {\n throw error\n }\n\n return result\n },\n onSuccess: () => {\n // Invalidate all queries for this table\n queryClient.invalidateQueries({ queryKey: ['fluxbase', 'table', table] })\n },\n })\n}\n\n/**\n * Hook to update data in a table\n */\nexport function useUpdate<T = any>(table: string) {\n const client = useFluxbaseClient()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: async (params: { data: Partial<T>; buildQuery: (query: QueryBuilder<T>) => QueryBuilder<T> }) => {\n const query = client.from<T>(table)\n const builtQuery = params.buildQuery(query)\n const { data: result, error } = await builtQuery.update(params.data)\n\n if (error) {\n throw error\n }\n\n return result\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['fluxbase', 'table', table] })\n },\n })\n}\n\n/**\n * Hook to upsert data into a table\n */\nexport function useUpsert<T = any>(table: string) {\n const client = useFluxbaseClient()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: async (data: Partial<T> | Partial<T>[]) => {\n const query = client.from<T>(table)\n const { data: result, error } = await query.upsert(data as Partial<T>)\n\n if (error) {\n throw error\n }\n\n return result\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['fluxbase', 'table', table] })\n },\n })\n}\n\n/**\n * Hook to delete data from a table\n */\nexport function useDelete<T = any>(table: string) {\n const client = useFluxbaseClient()\n const queryClient = useQueryClient()\n\n return useMutation({\n mutationFn: async (buildQuery: (query: QueryBuilder<T>) => QueryBuilder<T>) => {\n const query = client.from<T>(table)\n const builtQuery = buildQuery(query)\n const { error } = await builtQuery.delete()\n\n if (error) {\n throw error\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['fluxbase', 'table', table] })\n },\n })\n}\n","/**\n * Realtime subscription hooks for Fluxbase SDK\n */\n\nimport { useEffect, useRef } from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type {\n RealtimeCallback,\n RealtimePostgresChangesPayload,\n} from \"@fluxbase/sdk\";\n\nexport interface UseRealtimeOptions {\n /**\n * The channel name (e.g., 'table:public.products')\n */\n channel: string;\n\n /**\n * Event type to listen for ('INSERT', 'UPDATE', 'DELETE', or '*' for all)\n */\n event?: \"INSERT\" | \"UPDATE\" | \"DELETE\" | \"*\";\n\n /**\n * Callback function when an event is received\n */\n callback?: RealtimeCallback;\n\n /**\n * Whether to automatically invalidate queries for the table\n * Default: true\n */\n autoInvalidate?: boolean;\n\n /**\n * Custom query key to invalidate (if autoInvalidate is true)\n * Default: ['fluxbase', 'table', tableName]\n */\n invalidateKey?: unknown[];\n\n /**\n * Whether the subscription is enabled\n * Default: true\n */\n enabled?: boolean;\n}\n\n/**\n * Hook to subscribe to realtime changes for a channel\n *\n * NOTE: The callback and invalidateKey are stored in refs to prevent\n * subscription recreation on every render when inline functions/arrays are used.\n */\nexport function useRealtime(options: UseRealtimeOptions) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n const channelRef = useRef<ReturnType<typeof client.realtime.channel> | null>(\n null,\n );\n\n const {\n channel: channelName,\n event = \"*\",\n callback,\n autoInvalidate = true,\n invalidateKey,\n enabled = true,\n } = options;\n\n // Store callback and invalidateKey in refs to avoid subscription recreation\n // when inline functions/arrays are passed\n const callbackRef = useRef(callback);\n const invalidateKeyRef = useRef(invalidateKey);\n const autoInvalidateRef = useRef(autoInvalidate);\n\n // Keep refs up to date\n callbackRef.current = callback;\n invalidateKeyRef.current = invalidateKey;\n autoInvalidateRef.current = autoInvalidate;\n\n useEffect(() => {\n if (!enabled) {\n return;\n }\n\n // Create channel and subscribe\n const channel = client.realtime.channel(channelName);\n channelRef.current = channel;\n\n const handleChange = (payload: RealtimePostgresChangesPayload) => {\n // Call user callback (using ref for latest value)\n if (callbackRef.current) {\n callbackRef.current(payload);\n }\n\n // Auto-invalidate queries if enabled\n if (autoInvalidateRef.current) {\n // Extract table name from channel (e.g., 'table:public.products' -> 'public.products')\n const tableName = channelName.replace(/^table:/, \"\");\n\n const key = invalidateKeyRef.current || [\"fluxbase\", \"table\", tableName];\n queryClient.invalidateQueries({ queryKey: key });\n }\n };\n\n channel.on(event, handleChange).subscribe();\n\n return () => {\n channel.unsubscribe();\n channelRef.current = null;\n };\n }, [client, channelName, event, queryClient, enabled]);\n\n return {\n channel: channelRef.current,\n };\n}\n\n/**\n * Hook to subscribe to a table's changes\n * @param table - Table name (with optional schema, e.g., 'public.products')\n * @param options - Subscription options\n */\nexport function useTableSubscription(\n table: string,\n options?: Omit<UseRealtimeOptions, \"channel\">,\n) {\n return useRealtime({\n ...options,\n channel: `table:${table}`,\n });\n}\n\n/**\n * Hook to subscribe to INSERT events on a table\n */\nexport function useTableInserts(\n table: string,\n callback: (payload: RealtimePostgresChangesPayload) => void,\n options?: Omit<UseRealtimeOptions, \"channel\" | \"event\" | \"callback\">,\n) {\n return useRealtime({\n ...options,\n channel: `table:${table}`,\n event: \"INSERT\",\n callback,\n });\n}\n\n/**\n * Hook to subscribe to UPDATE events on a table\n */\nexport function useTableUpdates(\n table: string,\n callback: (payload: RealtimePostgresChangesPayload) => void,\n options?: Omit<UseRealtimeOptions, \"channel\" | \"event\" | \"callback\">,\n) {\n return useRealtime({\n ...options,\n channel: `table:${table}`,\n event: \"UPDATE\",\n callback,\n });\n}\n\n/**\n * Hook to subscribe to DELETE events on a table\n */\nexport function useTableDeletes(\n table: string,\n callback: (payload: RealtimePostgresChangesPayload) => void,\n options?: Omit<UseRealtimeOptions, \"channel\" | \"event\" | \"callback\">,\n) {\n return useRealtime({\n ...options,\n channel: `table:${table}`,\n event: \"DELETE\",\n callback,\n });\n}\n","/**\n * Storage hooks for Fluxbase SDK\n */\n\nimport { useState } from \"react\";\nimport {\n useMutation,\n useQuery,\n useQueryClient,\n type UseQueryOptions,\n} from \"@tanstack/react-query\";\nimport { useFluxbaseClient } from \"./context\";\nimport type {\n ListOptions,\n UploadOptions,\n UploadProgress,\n TransformOptions,\n SignedUrlOptions,\n} from \"@fluxbase/sdk\";\n\n/**\n * Hook to list files in a bucket\n */\nexport function useStorageList(\n bucket: string,\n options?: ListOptions &\n Omit<UseQueryOptions<any[], Error>, \"queryKey\" | \"queryFn\">,\n) {\n const client = useFluxbaseClient();\n const { prefix, limit, offset, ...queryOptions } = options || {};\n\n return useQuery({\n queryKey: [\n \"fluxbase\",\n \"storage\",\n bucket,\n \"list\",\n { prefix, limit, offset },\n ],\n queryFn: async () => {\n const { data, error } = await client.storage\n .from(bucket)\n .list({ prefix, limit, offset });\n\n if (error) {\n throw error;\n }\n\n return data || [];\n },\n ...queryOptions,\n });\n}\n\n/**\n * Hook to upload a file to a bucket\n *\n * Note: You can track upload progress by passing an `onUploadProgress` callback in the options:\n *\n * @example\n * ```tsx\n * const upload = useStorageUpload('avatars')\n *\n * upload.mutate({\n * path: 'user.jpg',\n * file: file,\n * options: {\n * onUploadProgress: (progress) => {\n * console.log(`${progress.percentage}% uploaded`)\n * }\n * }\n * })\n * ```\n *\n * For automatic progress state management, use `useStorageUploadWithProgress` instead.\n */\nexport function useStorageUpload(bucket: string) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (params: {\n path: string;\n file: File | Blob | ArrayBuffer;\n options?: UploadOptions;\n }) => {\n const { path, file, options } = params;\n const { data, error } = await client.storage\n .from(bucket)\n .upload(path, file, options);\n\n if (error) {\n throw error;\n }\n\n return data;\n },\n onSuccess: () => {\n // Invalidate list queries for this bucket\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"list\"],\n });\n },\n });\n}\n\n/**\n * Hook to upload a file to a bucket with built-in progress tracking\n *\n * @example\n * ```tsx\n * const { upload, progress, reset } = useStorageUploadWithProgress('avatars')\n *\n * // Upload with automatic progress tracking\n * upload.mutate({\n * path: 'user.jpg',\n * file: file\n * })\n *\n * // Display progress\n * console.log(progress) // { loaded: 1024, total: 2048, percentage: 50 }\n * ```\n */\nexport function useStorageUploadWithProgress(bucket: string) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n const [progress, setProgress] = useState<UploadProgress | null>(null);\n\n const mutation = useMutation({\n mutationFn: async (params: {\n path: string;\n file: File | Blob | ArrayBuffer;\n options?: Omit<UploadOptions, \"onUploadProgress\">;\n }) => {\n const { path, file, options } = params;\n\n // Reset progress at the start of upload\n setProgress({ loaded: 0, total: 0, percentage: 0 });\n\n const { data, error } = await client.storage\n .from(bucket)\n .upload(path, file, {\n ...options,\n onUploadProgress: (p: import(\"@fluxbase/sdk\").UploadProgress) => {\n setProgress(p);\n },\n });\n\n if (error) {\n throw error;\n }\n\n return data;\n },\n onSuccess: () => {\n // Invalidate list queries for this bucket\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"list\"],\n });\n },\n onError: () => {\n // Reset progress on error\n setProgress(null);\n },\n });\n\n return {\n upload: mutation,\n progress,\n reset: () => setProgress(null),\n };\n}\n\n/**\n * Hook to download a file from a bucket\n */\nexport function useStorageDownload(\n bucket: string,\n path: string | null,\n enabled = true,\n) {\n const client = useFluxbaseClient();\n\n return useQuery({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"download\", path],\n queryFn: async () => {\n if (!path) {\n return null;\n }\n\n const { data, error } = await client.storage.from(bucket).download(path);\n\n if (error) {\n throw error;\n }\n\n return data;\n },\n enabled: enabled && !!path,\n });\n}\n\n/**\n * Hook to delete files from a bucket\n */\nexport function useStorageDelete(bucket: string) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (paths: string[]) => {\n const { error } = await client.storage.from(bucket).remove(paths);\n\n if (error) {\n throw error;\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"list\"],\n });\n },\n });\n}\n\n/**\n * Hook to get a public URL for a file\n */\nexport function useStoragePublicUrl(bucket: string, path: string | null) {\n const client = useFluxbaseClient();\n\n if (!path) {\n return null;\n }\n\n const { data } = client.storage.from(bucket).getPublicUrl(path);\n return data.publicUrl;\n}\n\n/**\n * Hook to get a public URL for an image with transformations applied\n *\n * Only works for image files (JPEG, PNG, WebP, GIF, AVIF, etc.)\n *\n * @param bucket - The storage bucket name\n * @param path - The file path (or null to disable)\n * @param transform - Transformation options (width, height, format, quality, fit)\n *\n * @example\n * ```tsx\n * function ImageThumbnail({ path }: { path: string }) {\n * const url = useStorageTransformUrl('images', path, {\n * width: 300,\n * height: 200,\n * format: 'webp',\n * quality: 85,\n * fit: 'cover'\n * });\n *\n * return <img src={url || ''} alt=\"Thumbnail\" />;\n * }\n * ```\n */\nexport function useStorageTransformUrl(\n bucket: string,\n path: string | null,\n transform: TransformOptions,\n): string | null {\n const client = useFluxbaseClient();\n\n if (!path) {\n return null;\n }\n\n return client.storage.from(bucket).getTransformUrl(path, transform);\n}\n\n/**\n * Hook to create a signed URL\n *\n * @deprecated Use useStorageSignedUrlWithOptions for more control including transforms\n */\nexport function useStorageSignedUrl(\n bucket: string,\n path: string | null,\n expiresIn?: number,\n) {\n const client = useFluxbaseClient();\n\n return useQuery({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"signed-url\", path, expiresIn],\n queryFn: async () => {\n if (!path) {\n return null;\n }\n\n const { data, error } = await client.storage\n .from(bucket)\n .createSignedUrl(path, { expiresIn });\n\n if (error) {\n throw error;\n }\n\n return data?.signedUrl || null;\n },\n enabled: !!path,\n // Refresh 1 minute before expiry, but ensure staleTime is never negative\n // For very short expirations (<60s), use half the expiration time\n staleTime: expiresIn\n ? Math.max(expiresIn * 500, expiresIn * 1000 - 60000) // At least half the expiration time\n : 1000 * 60 * 50, // 50 minutes default\n });\n}\n\n/**\n * Hook to create a signed URL with full options including image transformations\n *\n * @param bucket - The storage bucket name\n * @param path - The file path (or null to disable)\n * @param options - Signed URL options including expiration and transforms\n *\n * @example\n * ```tsx\n * function SecureThumbnail({ path }: { path: string }) {\n * const { data: url } = useStorageSignedUrlWithOptions('images', path, {\n * expiresIn: 3600,\n * transform: {\n * width: 400,\n * height: 300,\n * format: 'webp',\n * quality: 85,\n * fit: 'cover'\n * }\n * });\n *\n * return <img src={url || ''} alt=\"Secure Thumbnail\" />;\n * }\n * ```\n */\nexport function useStorageSignedUrlWithOptions(\n bucket: string,\n path: string | null,\n options?: SignedUrlOptions,\n) {\n const client = useFluxbaseClient();\n const expiresIn = options?.expiresIn;\n\n // Create a stable cache key from transform options\n const transformKey = options?.transform\n ? JSON.stringify(options.transform)\n : null;\n\n return useQuery({\n queryKey: [\n \"fluxbase\",\n \"storage\",\n bucket,\n \"signed-url\",\n path,\n expiresIn,\n transformKey,\n ],\n queryFn: async () => {\n if (!path) {\n return null;\n }\n\n const { data, error } = await client.storage\n .from(bucket)\n .createSignedUrl(path, options);\n\n if (error) {\n throw error;\n }\n\n return data?.signedUrl || null;\n },\n enabled: !!path,\n // Refresh 1 minute before expiry, but ensure staleTime is never negative\n // For very short expirations (<60s), use half the expiration time\n staleTime: expiresIn\n ? Math.max(expiresIn * 500, expiresIn * 1000 - 60000) // At least half the expiration time\n : 1000 * 60 * 50, // 50 minutes default\n });\n}\n\n/**\n * Hook to move a file\n */\nexport function useStorageMove(bucket: string) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (params: { fromPath: string; toPath: string }) => {\n const { fromPath, toPath } = params;\n const { data, error } = await client.storage\n .from(bucket)\n .move(fromPath, toPath);\n\n if (error) {\n throw error;\n }\n\n return data;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"list\"],\n });\n },\n });\n}\n\n/**\n * Hook to copy a file\n */\nexport function useStorageCopy(bucket: string) {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (params: { fromPath: string; toPath: string }) => {\n const { fromPath, toPath } = params;\n const { data, error } = await client.storage\n .from(bucket)\n .copy(fromPath, toPath);\n\n if (error) {\n throw error;\n }\n\n return data;\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", bucket, \"list\"],\n });\n },\n });\n}\n\n/**\n * Hook to manage buckets\n */\nexport function useStorageBuckets() {\n const client = useFluxbaseClient();\n\n return useQuery({\n queryKey: [\"fluxbase\", \"storage\", \"buckets\"],\n queryFn: async () => {\n const { data, error } = await client.storage.listBuckets();\n\n if (error) {\n throw error;\n }\n\n return data || [];\n },\n });\n}\n\n/**\n * Hook to create a bucket\n */\nexport function useCreateBucket() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (bucketName: string) => {\n const { error } = await client.storage.createBucket(bucketName);\n\n if (error) {\n throw error;\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", \"buckets\"],\n });\n },\n });\n}\n\n/**\n * Hook to delete a bucket\n */\nexport function useDeleteBucket() {\n const client = useFluxbaseClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (bucketName: string) => {\n const { error } = await client.storage.deleteBucket(bucketName);\n\n if (error) {\n throw error;\n }\n },\n onSuccess: () => {\n queryClient.invalidateQueries({\n queryKey: [\"fluxbase\", \"storage\", \"buckets\"],\n });\n },\n });\n}\n","import { useState, useEffect, useCallback } from \"react\";\nimport { useFluxbaseClient } from \"./context\";\nimport type { AdminAuthResponse, DataResponse } from \"@fluxbase/sdk\";\n\n/**\n * Simplified admin user type returned by authentication\n */\nexport interface AdminUser {\n id: string;\n email: string;\n role: string;\n}\n\nexport interface UseAdminAuthOptions {\n /**\n * Automatically check authentication status on mount\n * @default true\n */\n autoCheck?: boolean;\n}\n\nexport interface UseAdminAuthReturn {\n /**\n * Current admin user if authenticated\n */\n user: AdminUser | null;\n\n /**\n * Whether the admin is authenticated\n */\n isAuthenticated: boolean;\n\n /**\n * Whether the authentication check is in progress\n */\n isLoading: boolean;\n\n /**\n * Any error that occurred during authentication\n */\n error: Error | null;\n\n /**\n * Login as admin\n */\n login: (email: string, password: string) => Promise<AdminAuthResponse>;\n\n /**\n * Logout admin\n */\n logout: () => Promise<void>;\n\n /**\n * Refresh admin user info\n */\n refresh: () => Promise<void>;\n}\n\n/**\n * Hook for admin authentication\n *\n * Manages admin login state, authentication checks, and user info.\n *\n * @example\n * ```tsx\n * function AdminLogin() {\n * const { user, isAuthenticated, isLoading, login, logout } = useAdminAuth()\n *\n * const handleLogin = async (e: React.FormEvent) => {\n * e.preventDefault()\n * await login(email, password)\n * }\n *\n * if (isLoading) return <div>Loading...</div>\n * if (isAuthenticated) return <div>Welcome {user?.email}</div>\n *\n * return <form onSubmit={handleLogin}>...</form>\n * }\n * ```\n */\nexport function useAdminAuth(\n options: UseAdminAuthOptions = {},\n): UseAdminAuthReturn {\n const { autoCheck = true } = options;\n const client = useFluxbaseClient();\n\n const [user, setUser] = useState<AdminUser | null>(null);\n const [isLoading, setIsLoading] = useState(autoCheck);\n const [error, setError] = useState<Error | null>(null);\n\n /**\n * Check current authentication status\n */\n const checkAuth = useCallback(async () => {\n try {\n setIsLoading(true);\n setError(null);\n const { data, error: apiError } = await client.admin.me();\n if (apiError) {\n throw apiError;\n }\n setUser(data!.user);\n } catch (err) {\n setUser(null);\n setError(err as Error);\n } finally {\n setIsLoading(false);\n }\n }, [client]);\n\n /**\n * Login as admin\n */\n const login = useCallback(\n async (email: string, password: string): Promise<AdminAuthResponse> => {\n try {\n setIsLoading(true);\n setError(null);\n const { data, error: apiError } = await client.admin.login({\n email,\n password,\n });\n if (apiError) {\n throw apiError;\n }\n setUser(data!.user);\n return data!;\n } catch (err) {\n setError(err as Error);\n throw err;\n } finally {\n setIsLoading(false);\n }\n },\n [client],\n );\n\n /**\n * Logout admin\n *\n * WARNING: Currently only clears local state. The server-side session/token\n * remains valid until it expires. This should call a logout endpoint to\n * invalidate the session on the server for proper security.\n */\n const logout = useCallback(async (): Promise<void> => {\n try {\n setIsLoading(true);\n setError(null);\n\n // TODO: Call server-side logout endpoint when available\n // This is a security concern - the token remains valid on the server\n // await client.admin.logout();\n\n // Clear local user state\n setUser(null);\n } catch (err) {\n setError(err as Error);\n throw err;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n /**\n * Refresh admin user info\n */\n const refresh = useCallback(async (): Promise<void> => {\n await checkAuth();\n }, [checkAuth]);\n\n // Auto-check authentication on mount\n useEffect(() => {\n if (autoCheck) {\n checkAuth();\n }\n }, [autoCheck, checkAuth]);\n\n return {\n user,\n isAuthenticated: user !== null,\n isLoading,\n error,\n login,\n logout,\n refresh,\n };\n}\n","import { useState, useEffect, useCallback } from 'react'\nimport { useFluxbaseClient } from './context'\nimport type { EnrichedUser, ListUsersOptions } from '@fluxbase/sdk'\n\nexport interface UseUsersOptions extends ListUsersOptions {\n /**\n * Whether to automatically fetch users on mount\n * @default true\n */\n autoFetch?: boolean\n\n /**\n * Refetch interval in milliseconds (0 to disable)\n * @default 0\n */\n refetchInterval?: number\n}\n\nexport interface UseUsersReturn {\n /**\n * Array of users\n */\n users: EnrichedUser[]\n\n /**\n * Total number of users (for pagination)\n */\n total: number\n\n /**\n * Whether users are being fetched\n */\n isLoading: boolean\n\n /**\n * Any error that occurred\n */\n error: Error | null\n\n /**\n * Refetch users\n */\n refetch: () => Promise<void>\n\n /**\n * Invite a new user\n */\n inviteUser: (email: string, role: 'user' | 'admin') => Promise<void>\n\n /**\n * Update user role\n */\n updateUserRole: (userId: string, role: 'user' | 'admin') => Promise<void>\n\n /**\n * Delete a user\n */\n deleteUser: (userId: string) => Promise<void>\n\n /**\n * Reset user password\n */\n resetPassword: (userId: string) => Promise<{ message: string }>\n}\n\n/**\n * Hook for managing users\n *\n * Provides user list with pagination, search, and management functions.\n *\n * @example\n * ```tsx\n * function UserList() {\n * const { users, total, isLoading, refetch, inviteUser, deleteUser } = useUsers({\n * limit: 20,\n * search: searchTerm\n * })\n *\n * return (\n * <div>\n * {isLoading ? <Spinner /> : (\n * <ul>\n * {users.map(user => (\n * <li key={user.id}>\n * {user.email} - {user.role}\n * <button onClick={() => deleteUser(user.id)}>Delete</button>\n * </li>\n * ))}\n * </ul>\n * )}\n * </div>\n * )\n * }\n * ```\n */\nexport function useUsers(options: UseUsersOptions = {}): UseUsersReturn {\n const { autoFetch = true, refetchInterval = 0, ...listOptions } = options\n const client = useFluxbaseClient()\n\n const [users, setUsers] = useState<EnrichedUser[]>([])\n const [total, setTotal] = useState(0)\n const [isLoading, setIsLoading] = useState(autoFetch)\n const [error, setError] = useState<Error | null>(null)\n\n /**\n * Fetch users from API\n */\n const fetchUsers = useCallback(async () => {\n try {\n setIsLoading(true)\n setError(null)\n const { data, error: apiError } = await client.admin.listUsers(listOptions)\n if (apiError) {\n throw apiError\n }\n setUsers(data!.users)\n setTotal(data!.total)\n } catch (err) {\n setError(err as Error)\n } finally {\n setIsLoading(false)\n }\n }, [client, JSON.stringify(listOptions)])\n\n /**\n * Invite a new user\n */\n const inviteUser = useCallback(\n async (email: string, role: 'user' | 'admin'): Promise<void> => {\n await client.admin.inviteUser({ email, role })\n await fetchUsers() // Refresh list\n },\n [client, fetchUsers]\n )\n\n /**\n * Update user role\n */\n const updateUserRole = useCallback(\n async (userId: string, role: 'user' | 'admin'): Promise<void> => {\n await client.admin.updateUserRole(userId, role)\n await fetchUsers() // Refresh list\n },\n [client, fetchUsers]\n )\n\n /**\n * Delete a user\n */\n const deleteUser = useCallback(\n async (userId: string): Promise<void> => {\n await client.admin.deleteUser(userId)\n await fetchUsers() // Refresh list\n },\n [client, fetchUsers]\n )\n\n /**\n * Reset user password\n */\n const resetPassword = useCallback(\n async (userId: string): Promise<{ message: string }> => {\n const { data, error } = await client.admin.resetUserPassword(userId)\n if (error) {\n throw error\n }\n return data!\n },\n [client]\n )\n\n // Auto-fetch on mount\n useEffect(() => {\n if (autoFetch) {\n fetchUsers()\n }\n }, [autoFetch, fetchUsers])\n\n // Set up refetch interval\n useEffect(() => {\n if (refetchInterval > 0) {\n const interval = setInterval(fetchUsers, refetchInterval)\n return () => clearInterval(interval)\n }\n }, [refetchInterval, fetchUsers])\n\n return {\n users,\n total,\n isLoading,\n error,\n refetch: fetchUsers,\n inviteUser,\n updateUserRole,\n deleteUser,\n resetPassword\n }\n}\n","import { useState, useEffect, useCallback } from 'react'\nimport { useFluxbaseClient } from './context'\nimport type { ClientKey, CreateClientKeyRequest } from '@fluxbase/sdk'\n\nexport interface UseClientKeysOptions {\n /**\n * Whether to automatically fetch client keys on mount\n * @default true\n */\n autoFetch?: boolean\n}\n\nexport interface UseClientKeysReturn {\n /**\n * Array of client keys\n */\n keys: ClientKey[]\n\n /**\n * Whether keys are being fetched\n */\n isLoading: boolean\n\n /**\n * Any error that occurred\n */\n error: Error | null\n\n /**\n * Refetch client keys\n */\n refetch: () => Promise<void>\n\n /**\n * Create a new client key\n */\n createKey: (request: CreateClientKeyRequest) => Promise<{ key: string; keyData: ClientKey }>\n\n /**\n * Update a client key\n */\n updateKey: (keyId: string, update: { name?: string; description?: string }) => Promise<void>\n\n /**\n * Revoke a client key\n */\n revokeKey: (keyId: string) => Promise<void>\n\n /**\n * Delete a client key\n */\n deleteKey: (keyId: string) => Promise<void>\n}\n\n/**\n * Hook for managing client keys\n *\n * Provides client key list and management functions.\n *\n * @example\n * ```tsx\n * function ClientKeyManager() {\n * const { keys, isLoading, createKey, revokeKey } = useClientKeys()\n *\n * const handleCreate = async () => {\n * const { key, keyData } = await createKey({\n * name: 'Backend Service',\n * description: 'Client key for backend',\n * expires_at: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString()\n * })\n * alert(`Key created: ${key}`)\n * }\n *\n * return (\n * <div>\n * <button onClick={handleCreate}>Create Key</button>\n * {keys.map(k => (\n * <div key={k.id}>\n * {k.name}\n * <button onClick={() => revokeKey(k.id)}>Revoke</button>\n * </div>\n * ))}\n * </div>\n * )\n * }\n * ```\n */\nexport function useClientKeys(options: UseClientKeysOptions = {}): UseClientKeysReturn {\n const { autoFetch = true } = options\n const client = useFluxbaseClient()\n\n const [keys, setKeys] = useState<ClientKey[]>([])\n const [isLoading, setIsLoading] = useState(autoFetch)\n const [error, setError] = useState<Error | null>(null)\n\n /**\n * Fetch client keys from API\n */\n const fetchKeys = useCallback(async () => {\n try {\n setIsLoading(true)\n setError(null)\n const response = await client.admin.management.clientKeys.list()\n setKeys(response.client_keys)\n } catch (err) {\n setError(err as Error)\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n /**\n * Create a new client key\n */\n const createKey = useCallback(\n async (request: CreateClientKeyRequest): Promise<{ key: string; keyData: ClientKey }> => {\n const response = await client.admin.management.clientKeys.create(request)\n await fetchKeys() // Refresh list\n return { key: response.key, keyData: response.client_key }\n },\n [client, fetchKeys]\n )\n\n /**\n * Update a client key\n */\n const updateKey = useCallback(\n async (keyId: string, update: { name?: string; description?: string }): Promise<void> => {\n await client.admin.management.clientKeys.update(keyId, update)\n await fetchKeys() // Refresh list\n },\n [client, fetchKeys]\n )\n\n /**\n * Revoke a client key\n */\n const revokeKey = useCallback(\n async (keyId: string): Promise<void> => {\n await client.admin.management.clientKeys.revoke(keyId)\n await fetchKeys() // Refresh list\n },\n [client, fetchKeys]\n )\n\n /**\n * Delete a client key\n */\n const deleteKey = useCallback(\n async (keyId: string): Promise<void> => {\n await client.admin.management.clientKeys.delete(keyId)\n await fetchKeys() // Refresh list\n },\n [client, fetchKeys]\n )\n\n // Auto-fetch on mount\n useEffect(() => {\n if (autoFetch) {\n fetchKeys()\n }\n }, [autoFetch, fetchKeys])\n\n return {\n keys,\n isLoading,\n error,\n refetch: fetchKeys,\n createKey,\n updateKey,\n revokeKey,\n deleteKey\n }\n}\n\n/**\n * @deprecated Use useClientKeys instead\n */\nexport const useAPIKeys = useClientKeys\n\n/** @deprecated Use UseClientKeysOptions instead */\nexport type UseAPIKeysOptions = UseClientKeysOptions\n\n/** @deprecated Use UseClientKeysReturn instead */\nexport type UseAPIKeysReturn = UseClientKeysReturn\n","/**\n * Admin Settings and Management Hooks\n *\n * Hooks for managing application settings, system settings, and webhooks.\n */\n\nimport { useState, useEffect, useCallback } from 'react'\nimport { useFluxbaseClient } from './context'\nimport type {\n AppSettings,\n UpdateAppSettingsRequest,\n SystemSetting,\n UpdateSystemSettingRequest,\n Webhook,\n CreateWebhookRequest,\n UpdateWebhookRequest\n} from '@fluxbase/sdk'\n\n// ============================================================================\n// useAppSettings Hook\n// ============================================================================\n\nexport interface UseAppSettingsOptions {\n autoFetch?: boolean\n}\n\nexport interface UseAppSettingsReturn {\n settings: AppSettings | null\n isLoading: boolean\n error: Error | null\n refetch: () => Promise<void>\n updateSettings: (update: UpdateAppSettingsRequest) => Promise<void>\n}\n\n/**\n * Hook for managing application settings\n *\n * @example\n * ```tsx\n * function SettingsPanel() {\n * const { settings, isLoading, updateSettings } = useAppSettings({ autoFetch: true })\n *\n * const handleToggleFeature = async (feature: string, enabled: boolean) => {\n * await updateSettings({\n * features: { ...settings?.features, [feature]: enabled }\n * })\n * }\n *\n * return <div>...</div>\n * }\n * ```\n */\nexport function useAppSettings(options: UseAppSettingsOptions = {}): UseAppSettingsReturn {\n const { autoFetch = true } = options\n const client = useFluxbaseClient()\n\n const [settings, setSettings] = useState<AppSettings | null>(null)\n const [isLoading, setIsLoading] = useState(autoFetch)\n const [error, setError] = useState<Error | null>(null)\n\n const fetchSettings = useCallback(async () => {\n try {\n setIsLoading(true)\n setError(null)\n const appSettings = await client.admin.settings.app.get()\n setSettings(appSettings)\n } catch (err) {\n setError(err as Error)\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n const updateSettings = useCallback(\n async (update: UpdateAppSettingsRequest): Promise<void> => {\n await client.admin.settings.app.update(update)\n await fetchSettings()\n },\n [client, fetchSettings]\n )\n\n useEffect(() => {\n if (autoFetch) {\n fetchSettings()\n }\n }, [autoFetch, fetchSettings])\n\n return {\n settings,\n isLoading,\n error,\n refetch: fetchSettings,\n updateSettings\n }\n}\n\n// ============================================================================\n// useSystemSettings Hook\n// ============================================================================\n\nexport interface UseSystemSettingsOptions {\n autoFetch?: boolean\n}\n\nexport interface UseSystemSettingsReturn {\n settings: SystemSetting[]\n isLoading: boolean\n error: Error | null\n refetch: () => Promise<void>\n getSetting: (key: string) => SystemSetting | undefined\n updateSetting: (key: string, update: UpdateSystemSettingRequest) => Promise<void>\n deleteSetting: (key: string) => Promise<void>\n}\n\n/**\n * Hook for managing system settings (key-value storage)\n *\n * @example\n * ```tsx\n * function SystemSettings() {\n * const { settings, isLoading, updateSetting } = useSystemSettings({ autoFetch: true })\n *\n * const handleUpdateSetting = async (key: string, value: any) => {\n * await updateSetting(key, { value })\n * }\n *\n * return <div>...</div>\n * }\n * ```\n */\nexport function useSystemSettings(options: UseSystemSettingsOptions = {}): UseSystemSettingsReturn {\n const { autoFetch = true } = options\n const client = useFluxbaseClient()\n\n const [settings, setSettings] = useState<SystemSetting[]>([])\n const [isLoading, setIsLoading] = useState(autoFetch)\n const [error, setError] = useState<Error | null>(null)\n\n const fetchSettings = useCallback(async () => {\n try {\n setIsLoading(true)\n setError(null)\n const response = await client.admin.settings.system.list()\n setSettings(response.settings)\n } catch (err) {\n setError(err as Error)\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n const getSetting = useCallback(\n (key: string): SystemSetting | undefined => {\n return settings.find((s) => s.key === key)\n },\n [settings]\n )\n\n const updateSetting = useCallback(\n async (key: string, update: UpdateSystemSettingRequest): Promise<void> => {\n await client.admin.settings.system.update(key, update)\n await fetchSettings()\n },\n [client, fetchSettings]\n )\n\n const deleteSetting = useCallback(\n async (key: string): Promise<void> => {\n await client.admin.settings.system.delete(key)\n await fetchSettings()\n },\n [client, fetchSettings]\n )\n\n useEffect(() => {\n if (autoFetch) {\n fetchSettings()\n }\n }, [autoFetch, fetchSettings])\n\n return {\n settings,\n isLoading,\n error,\n refetch: fetchSettings,\n getSetting,\n updateSetting,\n deleteSetting\n }\n}\n\n// ============================================================================\n// useWebhooks Hook\n// ============================================================================\n\nexport interface UseWebhooksOptions {\n autoFetch?: boolean\n refetchInterval?: number\n}\n\nexport interface UseWebhooksReturn {\n webhooks: Webhook[]\n isLoading: boolean\n error: Error | null\n refetch: () => Promise<void>\n createWebhook: (webhook: CreateWebhookRequest) => Promise<Webhook>\n updateWebhook: (id: string, update: UpdateWebhookRequest) => Promise<Webhook>\n deleteWebhook: (id: string) => Promise<void>\n testWebhook: (id: string) => Promise<void>\n}\n\n/**\n * Hook for managing webhooks\n *\n * @example\n * ```tsx\n * function WebhooksManager() {\n * const { webhooks, isLoading, createWebhook, deleteWebhook } = useWebhooks({\n * autoFetch: true\n * })\n *\n * const handleCreate = async () => {\n * await createWebhook({\n * url: 'https://example.com/webhook',\n * events: ['user.created', 'user.updated'],\n * enabled: true\n * })\n * }\n *\n * return <div>...</div>\n * }\n * ```\n */\nexport function useWebhooks(options: UseWebhooksOptions = {}): UseWebhooksReturn {\n const { autoFetch = true, refetchInterval = 0 } = options\n const client = useFluxbaseClient()\n\n const [webhooks, setWebhooks] = useState<Webhook[]>([])\n const [isLoading, setIsLoading] = useState(autoFetch)\n const [error, setError] = useState<Error | null>(null)\n\n const fetchWebhooks = useCallback(async () => {\n try {\n setIsLoading(true)\n setError(null)\n const response = await client.admin.management.webhooks.list()\n setWebhooks(response.webhooks)\n } catch (err) {\n setError(err as Error)\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n const createWebhook = useCallback(\n async (webhook: CreateWebhookRequest): Promise<Webhook> => {\n const created = await client.admin.management.webhooks.create(webhook)\n await fetchWebhooks()\n return created\n },\n [client, fetchWebhooks]\n )\n\n const updateWebhook = useCallback(\n async (id: string, update: UpdateWebhookRequest): Promise<Webhook> => {\n const updated = await client.admin.management.webhooks.update(id, update)\n await fetchWebhooks()\n return updated\n },\n [client, fetchWebhooks]\n )\n\n const deleteWebhook = useCallback(\n async (id: string): Promise<void> => {\n await client.admin.management.webhooks.delete(id)\n await fetchWebhooks()\n },\n [client, fetchWebhooks]\n )\n\n const testWebhook = useCallback(\n async (id: string): Promise<void> => {\n await client.admin.management.webhooks.test(id)\n },\n [client]\n )\n\n useEffect(() => {\n if (autoFetch) {\n fetchWebhooks()\n }\n\n if (refetchInterval > 0) {\n const interval = setInterval(fetchWebhooks, refetchInterval)\n return () => clearInterval(interval)\n }\n }, [autoFetch, refetchInterval, fetchWebhooks])\n\n return {\n webhooks,\n isLoading,\n error,\n refetch: fetchWebhooks,\n createWebhook,\n updateWebhook,\n deleteWebhook,\n testWebhook\n }\n}\n"],"mappings":"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","names":["useQuery","useQuery","useQuery","useQuery","useMutation","useQuery","useQueryClient","useQuery","useMutation","useQueryClient","useMutation","useQuery","useQueryClient","useQuery","useQueryClient","useMutation","useQuery","useMutation","useQueryClient","useQuery","client","useQueryClient","useMutation","useEffect","useRef","useQueryClient","useQueryClient","useRef","useEffect","useState","useMutation","useQuery","useQueryClient","useQuery","useQueryClient","useMutation","useState","useState","useEffect","useCallback","useState","useCallback","useEffect","useState","useEffect","useCallback","useState","useCallback","error","useEffect","useState","useEffect","useCallback","useState","useCallback","useEffect","useState","useEffect","useCallback","useState","useCallback","useEffect"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluxbase/sdk-react",
|
|
3
|
-
"version": "2026.1
|
|
3
|
+
"version": "2026.2.1",
|
|
4
4
|
"description": "React hooks for Fluxbase SDK",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
"docs:watch": "typedoc --watch",
|
|
20
20
|
"type-check": "tsc --noEmit",
|
|
21
21
|
"format": "prettier --write src",
|
|
22
|
-
"format:check": "prettier --check src"
|
|
22
|
+
"format:check": "prettier --check src",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest",
|
|
25
|
+
"test:coverage": "vitest run --coverage"
|
|
23
26
|
},
|
|
24
27
|
"keywords": [
|
|
25
28
|
"fluxbase",
|
|
@@ -36,17 +39,24 @@
|
|
|
36
39
|
"access": "public"
|
|
37
40
|
},
|
|
38
41
|
"peerDependencies": {
|
|
39
|
-
"@fluxbase/sdk": "^2026.1.
|
|
40
|
-
"@tanstack/react-query": "^5.
|
|
42
|
+
"@fluxbase/sdk": "^2026.1.22",
|
|
43
|
+
"@tanstack/react-query": "^5.90.20",
|
|
41
44
|
"react": "^18.0.0 || ^19.0.0"
|
|
42
45
|
},
|
|
43
46
|
"devDependencies": {
|
|
44
47
|
"@fluxbase/sdk": "file:../sdk",
|
|
45
|
-
"@tanstack/react-query": "^5.
|
|
46
|
-
"@
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
48
|
+
"@tanstack/react-query": "^5.90.20",
|
|
49
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
50
|
+
"@testing-library/react": "^16.3.2",
|
|
51
|
+
"@types/react": "^19.2.10",
|
|
52
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
53
|
+
"jsdom": "^27.4.0",
|
|
54
|
+
"prettier": "^3.8.1",
|
|
55
|
+
"react": "^19.2.4",
|
|
56
|
+
"react-dom": "^19.2.4",
|
|
57
|
+
"tsup": "^8.5.1",
|
|
58
|
+
"typedoc": "^0.28.16",
|
|
59
|
+
"typescript": "^5.9.3",
|
|
60
|
+
"vitest": "^4.0.18"
|
|
51
61
|
}
|
|
52
62
|
}
|