UNPKG

better-auth-feature-flags

Version:

Ship features safely with feature flags, A/B testing, and progressive rollouts - Better Auth plugin for modern release management

179 lines (175 loc) 6.06 kB
import * as react_jsx_runtime from 'react/jsx-runtime'; import { createAuthClient } from 'better-auth/client'; import React, { ReactNode, ComponentType } from 'react'; import { FeatureFlagsClient, EvaluationContext, FeatureFlagVariant } from './client.js'; type BetterAuthClient = ReturnType<typeof createAuthClient>; interface FeatureFlagsProviderProps { client: BetterAuthClient & FeatureFlagsClient; children: ReactNode; /** * Pre-populated flags for SSR/initial render. * Prevents flash of default content. */ initialFlags?: Record<string, any>; /** * Fetch fresh flags on mount. Set false for SSR with initialFlags. */ fetchOnMount?: boolean; /** * Evaluation context merged with session data. * Changes trigger cache invalidation. */ context?: Partial<EvaluationContext>; } interface FeatureProps { /** * Flag key to evaluate. */ flag: string; /** * Renders when flag is false/missing. Defaults to null. */ fallback?: ReactNode; /** * Secondary check after flag passes (e.g., subscription tier). * Return false to show fallback despite flag=true. */ validateAccess?: (flags: Record<string, any>) => boolean; /** * Renders when flag is true AND validateAccess passes. */ children: ReactNode; } interface VariantProps { /** * The feature flag key to check for variants */ flag: string; /** * Children components (Variant.Case and Variant.Default) */ children: ReactNode; } interface VariantCaseProps { /** * The variant key to match */ variant: string; /** * Content to render for this variant */ children: ReactNode; } interface VariantDefaultProps { /** * Content to render when no variant matches */ children: ReactNode; } interface FeatureFlagErrorBoundaryProps { /** * Fallback component to render on error */ fallback: ReactNode | ComponentType<{ error: Error; }>; /** * Error callback */ onError?: (error: Error) => void; /** * Children components */ children: ReactNode; } declare function FeatureFlagsProvider({ client, children, initialFlags, fetchOnMount, context: additionalContext, }: FeatureFlagsProviderProps): react_jsx_runtime.JSX.Element; /** * Returns boolean flag value. Fetches from server if not cached. * @param flag - Flag key to evaluate * @param defaultValue - Fallback if flag missing/errored */ declare function useFeatureFlag(flag: string, defaultValue?: boolean): boolean; /** * Returns typed flag value (string, number, object, etc). * @param flag - Flag key to evaluate * @param defaultValue - Type-safe fallback */ declare function useFeatureFlagValue<T = any>(flag: string, defaultValue?: T): T; /** * Get all feature flags */ declare function useFeatureFlags(): Record<string, any>; /** * Get the variant of a feature flag */ declare function useVariant(flag: string): FeatureFlagVariant | null; /** * Track an event for a feature flag */ declare function useTrackEvent(): (flag: string, event: string, value?: number | Record<string, any>) => Promise<void>; /** * Get feature flags loading and error state */ declare function useFeatureFlagsState(): { loading: boolean; error: Error | null; refresh: () => Promise<void>; }; /** * Debug hook: Exposes cache state for monitoring. * Not for production UI - use for troubleshooting. */ declare function useFeatureFlagsCacheInfo(): { cacheEnabled: boolean; sessionId?: string; flagCount: number; }; /** * Declarative flag gating. Prevents render of protected content. * * @example * <Feature flag="new-dashboard" fallback={<OldDashboard />}> * <NewDashboard /> * </Feature> */ declare function Feature({ flag, fallback, validateAccess, children, }: FeatureProps): react_jsx_runtime.JSX.Element; /** * A/B testing component. Renders child matching current variant. * * @example * <Variant flag="checkout-flow"> * <Variant.Case variant="v1"><CheckoutV1 /></Variant.Case> * <Variant.Case variant="v2"><CheckoutV2 /></Variant.Case> * <Variant.Default><CheckoutOriginal /></Variant.Default> * </Variant> */ declare const Variant: React.NamedExoticComponent<VariantProps>; interface ErrorBoundaryState { hasError: boolean; error: Error | null; } /** * Catches errors in flag evaluation/rendering. * Prevents entire app crash from flag service issues. */ declare class FeatureFlagErrorBoundary extends React.Component<FeatureFlagErrorBoundaryProps, ErrorBoundaryState> { constructor(props: FeatureFlagErrorBoundaryProps); static getDerivedStateFromError(error: Error): ErrorBoundaryState; componentDidCatch(error: Error): void; render(): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined; } /** * HOC for class components or prop drilling. * Prefer hooks (useFeatureFlags) for new code. */ declare function withFeatureFlags<P extends object>(Component: ComponentType<P & { featureFlags: Record<string, any>; }>): ComponentType<P>; /** * HOC for feature gating at component definition. * * @example * export default withFeatureFlag('beta-ui', LegacyComponent)(BetaComponent); */ declare function withFeatureFlag<P extends object>(flag: string, fallback?: ComponentType<P>): (Component: ComponentType<P>) => ComponentType<P>; export { Feature, FeatureFlagErrorBoundary, type FeatureFlagErrorBoundaryProps, FeatureFlagsProvider, type FeatureFlagsProviderProps, type FeatureProps, Variant, type VariantCaseProps, type VariantDefaultProps, type VariantProps, useFeatureFlag, useFeatureFlagValue, useFeatureFlags, useFeatureFlagsCacheInfo, useFeatureFlagsState, useTrackEvent, useVariant, withFeatureFlag, withFeatureFlags };