UNPKG

codalware-auth

Version:

Complete authentication system with enterprise security, attack protection, team workspaces, waitlist, billing, UI components, 2FA, and account recovery - production-ready in 5 minutes. Enhanced CLI with verification, rollback, and App Router scaffolding.

135 lines (115 loc) 3.77 kB
import { useState, useEffect, useCallback } from 'react'; import { useAuth } from './useAuth'; interface FeatureConfig { featureKey: string; isEnabled: boolean; config?: Record<string, unknown>; } interface UseFeatureFlagsReturn { isFeatureEnabled: (featureKey: string) => boolean; getFeatureConfig: (featureKey: string) => Record<string, unknown> | null; features: FeatureConfig[]; loading: boolean; error: string | null; refetch: () => Promise<void>; } /** * Hook to check feature flags for the current tenant * @returns Feature flag utilities and state */ export function useFeatureFlags(): UseFeatureFlagsReturn { const { user } = useAuth(); const [features, setFeatures] = useState<FeatureConfig[]>([]); const [loading, setLoading] = useState(true); const [error, setError] = useState<string | null>(null); const fetchFeatures = useCallback(async () => { if (!user?.tenantId) { setFeatures([]); setLoading(false); return; } try { setLoading(true); setError(null); const response = await fetch('/api/tenant/features'); if (!response.ok) { throw new Error('Failed to fetch features'); } const data = await response.json(); // Transform to simple feature config format const featureConfigs: FeatureConfig[] = (data.features || []) .filter((f: { isEnabledGlobally: boolean }) => f.isEnabledGlobally) .map((f: { featureKey: string; tenantEnabled?: boolean; tenantConfig?: Record<string, unknown>; }) => ({ featureKey: f.featureKey, isEnabled: f.tenantEnabled ?? true, config: f.tenantConfig, })); setFeatures(featureConfigs); } catch (err) { setError(err instanceof Error ? err.message : 'An error occurred'); setFeatures([]); } finally { setLoading(false); } }, [user?.tenantId]); useEffect(() => { void fetchFeatures(); }, [fetchFeatures]); /** * Check if a feature is enabled * @param featureKey - The feature key to check (e.g., "auth.2fa") * @returns true if the feature is enabled, false otherwise */ const isFeatureEnabled = (featureKey: string): boolean => { const feature = features.find(f => f.featureKey === featureKey); return feature?.isEnabled ?? false; }; /** * Get configuration for a feature * @param featureKey - The feature key to get config for * @returns The feature configuration object or null */ const getFeatureConfig = (featureKey: string): Record<string, unknown> | null => { const feature = features.find(f => f.featureKey === featureKey); return feature?.config ?? null; }; return { isFeatureEnabled, getFeatureConfig, features, loading, error, refetch: fetchFeatures, }; } /** * Hook to check a specific feature * @param featureKey - The feature key to check * @returns Object with enabled status and config */ export function useFeature(featureKey: string) { const { isFeatureEnabled, getFeatureConfig, loading, error } = useFeatureFlags(); return { isEnabled: isFeatureEnabled(featureKey), config: getFeatureConfig(featureKey), loading, error, }; } // Specific feature hooks for common features export function use2FAFeature() { return useFeature('auth.2fa'); } export function useMagicLinkFeature() { return useFeature('auth.magic_link'); } export function useMultiTenantFeature() { return useFeature('org.multi_tenant'); } export function useRBACFeature() { return useFeature('auth.rbac'); }