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

197 lines (194 loc) 8.18 kB
import * as react_jsx_runtime from 'react/jsx-runtime'; import { createAuthClient } from 'better-auth/client'; import React, { ReactNode, ComponentType } from 'react'; import { FeatureFlagsClient } from './client.js'; import { E as EvaluationContext } from './types-_f512wNn.js'; import 'better-call'; import 'better-auth'; import 'zod'; type BetterAuthClient = ReturnType<typeof createAuthClient>; interface FeatureFlagsProviderProps { client: BetterAuthClient & FeatureFlagsClient; children: ReactNode; /** Pre-populated flags for SSR, prevents content flash */ initialFlags?: Record<string, any>; /** Fetch flags on mount (disable for SSR) */ fetchOnMount?: boolean; /** Evaluation context, changes trigger cache invalidation */ context?: Partial<EvaluationContext>; } interface FeatureProps { /** Flag key to evaluate */ flag: string; /** Fallback content when flag disabled/missing */ fallback?: ReactNode; /** Secondary validation (e.g., subscription tier) */ validateAccess?: (flags: Record<string, any>) => boolean; /** Content when flag enabled and validation passes */ children: ReactNode; } interface VariantProps { /** Flag key for variant evaluation */ flag: string; /** Variant.Case and Variant.Default components */ children: ReactNode; } interface VariantCaseProps { /** Variant key to match */ variant: string; /** Content for this variant */ children: ReactNode; } interface VariantDefaultProps { /** Default content when no variant matches */ children: ReactNode; } interface FeatureFlagErrorBoundaryProps { /** Fallback component or element for errors */ fallback: ReactNode | ComponentType<{ error: Error; }>; /** Error callback for monitoring/logging */ onError?: (error: Error) => void; /** Protected children components */ children: ReactNode; } declare function FeatureFlagsProvider({ client, children, initialFlags, fetchOnMount, context: additionalContext, }: FeatureFlagsProviderProps): react_jsx_runtime.JSX.Element; /** * Hook for boolean flag evaluation. * @param flag Flag key to evaluate * @param defaultValue Fallback for missing/errored flags */ declare function useFeatureFlag(flag: string, defaultValue?: boolean): boolean; /** * Hook for typed flag values (string, number, object). * @param flag Flag key to evaluate * @param defaultValue Type-safe fallback value */ declare function useFeatureFlagValue<T = any>(flag: string, defaultValue?: T): T; /** Hook returning all cached feature flags */ declare function useFeatureFlags(): Record<string, any>; /** Hook for A/B test variant evaluation */ declare function useVariant(flag: string): string | null; /** Hook for flag event tracking */ declare function useTrackEvent(): (flag: string, event: string, value?: number | Record<string, any>) => Promise<{ success: boolean; eventId: string; sampled?: boolean; }>; /** Hook for flag loading state and error handling */ declare function useFeatureFlagsState(): { loading: boolean; error: Error | null; refresh: () => Promise<void>; }; /** Debug hook for cache monitoring, not for production UI */ declare function useFeatureFlagsCacheInfo(): { cacheEnabled: boolean; sessionId?: string; flagCount: number; }; /** Suspense-compatible flag evaluation - throws promise during loading */ declare function useFeatureFlagSuspense(flag: string, defaultValue?: boolean): boolean; /** Suspense-compatible typed flag values */ declare function useFeatureFlagValueSuspense<T = any>(flag: string, defaultValue?: T): T; /** Suspense-compatible all flags hook */ declare function useFeatureFlagsSuspense(): Record<string, any>; /** * Enhanced hook for flag event tracking with idempotency support * @example * const trackEvent = useTrackEventWithIdempotency(); * await trackEvent('feature', 'purchase', { amount: 99.99 }, { idempotencyKey: 'order-123' }); */ declare function useTrackEventWithIdempotency(): (flag: string, event: string, value?: number | Record<string, any>, options?: { idempotencyKey?: string; }) => Promise<{ success: boolean; eventId: string; sampled?: boolean; }>; /** * Hook for batch event tracking - more efficient for multiple events * @example * const trackBatch = useTrackEventBatch(); * await trackBatch([ * { flag: 'feature1', event: 'view', idempotencyKey: 'session-123-1' }, * { flag: 'feature2', event: 'click', data: { button: 'cta' } } * ]); */ declare function useTrackEventBatch(): (events: Array<{ flag: string; event: string; data?: number | Record<string, any>; timestamp?: Date; idempotencyKey?: string; }>, batchId?: string) => Promise<{ success: number; failed: number; sampled?: number; batchId: string; }>; /** * Declarative feature gating component. * @example * <Feature flag="new-dashboard" fallback={<OldDashboard />}> * <NewDashboard /> * </Feature> */ declare function Feature({ flag, fallback, validateAccess, children, }: FeatureProps): react_jsx_runtime.JSX.Element; /** * A/B test variant component. * @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>; /** * Suspense-compatible feature gating component. * Requires <Suspense> boundary to handle loading states. * @example * <Suspense fallback={<Loading />}> * <FeatureSuspense flag="new-dashboard" fallback={<OldDashboard />}> * <NewDashboard /> * </FeatureSuspense> * </Suspense> */ declare function FeatureSuspense({ flag, fallback, validateAccess, children, }: FeatureProps): react_jsx_runtime.JSX.Element; /** * Suspense-compatible variant component. * Requires <Suspense> boundary to handle loading states. * @example * <Suspense fallback={<Loading />}> * <VariantSuspense flag="checkout-flow"> * <Variant.Case variant="v1"><CheckoutV1 /></Variant.Case> * <Variant.Case variant="v2"><CheckoutV2 /></Variant.Case> * <Variant.Default><CheckoutOriginal /></Variant.Default> * </VariantSuspense> * </Suspense> */ declare const VariantSuspense: React.NamedExoticComponent<VariantProps>; interface ErrorBoundaryState { hasError: boolean; error: Error | null; } /** Error boundary for flag evaluation, prevents app crashes */ 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, prefer hooks for new code */ declare function withFeatureFlags<P extends object>(Component: ComponentType<P & { featureFlags: Record<string, any>; }>): ComponentType<P>; /** * HOC for component-level feature gating. * @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, FeatureSuspense, Variant, type VariantCaseProps, type VariantDefaultProps, type VariantProps, VariantSuspense, useFeatureFlag, useFeatureFlagSuspense, useFeatureFlagValue, useFeatureFlagValueSuspense, useFeatureFlags, useFeatureFlagsCacheInfo, useFeatureFlagsState, useFeatureFlagsSuspense, useTrackEvent, useTrackEventBatch, useTrackEventWithIdempotency, useVariant, withFeatureFlag, withFeatureFlags };