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
TypeScript
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 };