- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8 - Actualizaciones de configuracion Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
226 lines
6.8 KiB
TypeScript
226 lines
6.8 KiB
TypeScript
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import {
|
|
featureFlagsApi,
|
|
CreateFlagRequest,
|
|
UpdateFlagRequest,
|
|
SetTenantFlagRequest,
|
|
SetUserFlagRequest,
|
|
FlagType,
|
|
FlagScope,
|
|
} from '@/services/api';
|
|
|
|
// Query keys
|
|
const flagKeys = {
|
|
all: ['feature-flags'] as const,
|
|
list: () => [...flagKeys.all, 'list'] as const,
|
|
detail: (id: string) => [...flagKeys.all, 'detail', id] as const,
|
|
tenantOverrides: () => [...flagKeys.all, 'tenant-overrides'] as const,
|
|
userOverrides: (userId: string) => [...flagKeys.all, 'user-overrides', userId] as const,
|
|
evaluation: () => [...flagKeys.all, 'evaluation'] as const,
|
|
evaluationKey: (key: string) => [...flagKeys.evaluation(), key] as const,
|
|
check: (key: string) => [...flagKeys.all, 'check', key] as const,
|
|
};
|
|
|
|
// ==================== Flag Management ====================
|
|
|
|
export function useFeatureFlags() {
|
|
return useQuery({
|
|
queryKey: flagKeys.list(),
|
|
queryFn: () => featureFlagsApi.list(),
|
|
});
|
|
}
|
|
|
|
export function useFeatureFlag(id: string) {
|
|
return useQuery({
|
|
queryKey: flagKeys.detail(id),
|
|
queryFn: () => featureFlagsApi.get(id),
|
|
enabled: !!id,
|
|
});
|
|
}
|
|
|
|
export function useCreateFeatureFlag() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (data: CreateFlagRequest) => featureFlagsApi.create(data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.list() });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useUpdateFeatureFlag() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: ({ id, data }: { id: string; data: UpdateFlagRequest }) =>
|
|
featureFlagsApi.update(id, data),
|
|
onSuccess: (_, { id }) => {
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.list() });
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.detail(id) });
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.evaluation() });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDeleteFeatureFlag() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (id: string) => featureFlagsApi.delete(id),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.list() });
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.evaluation() });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useToggleFeatureFlag() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: ({ id, enabled }: { id: string; enabled: boolean }) =>
|
|
featureFlagsApi.toggle(id, enabled),
|
|
onSuccess: (_, { id }) => {
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.list() });
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.detail(id) });
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.evaluation() });
|
|
},
|
|
});
|
|
}
|
|
|
|
// ==================== Tenant Flags ====================
|
|
|
|
export function useTenantFlagOverrides() {
|
|
return useQuery({
|
|
queryKey: flagKeys.tenantOverrides(),
|
|
queryFn: () => featureFlagsApi.getTenantOverrides(),
|
|
});
|
|
}
|
|
|
|
export function useSetTenantFlagOverride() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (data: SetTenantFlagRequest) => featureFlagsApi.setTenantOverride(data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.tenantOverrides() });
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.evaluation() });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useRemoveTenantFlagOverride() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (flagId: string) => featureFlagsApi.removeTenantOverride(flagId),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.tenantOverrides() });
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.evaluation() });
|
|
},
|
|
});
|
|
}
|
|
|
|
// ==================== User Flags ====================
|
|
|
|
export function useUserFlagOverrides(userId: string) {
|
|
return useQuery({
|
|
queryKey: flagKeys.userOverrides(userId),
|
|
queryFn: () => featureFlagsApi.getUserOverrides(userId),
|
|
enabled: !!userId,
|
|
});
|
|
}
|
|
|
|
export function useSetUserFlagOverride() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (data: SetUserFlagRequest) => featureFlagsApi.setUserOverride(data),
|
|
onSuccess: (_, { user_id }) => {
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.userOverrides(user_id) });
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.evaluation() });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useRemoveUserFlagOverride() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: ({ userId, flagId }: { userId: string; flagId: string }) =>
|
|
featureFlagsApi.removeUserOverride(userId, flagId),
|
|
onSuccess: (_, { userId }) => {
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.userOverrides(userId) });
|
|
queryClient.invalidateQueries({ queryKey: flagKeys.evaluation() });
|
|
},
|
|
});
|
|
}
|
|
|
|
// ==================== Evaluation ====================
|
|
|
|
export function useFlagEvaluation(key: string) {
|
|
return useQuery({
|
|
queryKey: flagKeys.evaluationKey(key),
|
|
queryFn: () => featureFlagsApi.evaluate(key),
|
|
enabled: !!key,
|
|
});
|
|
}
|
|
|
|
export function useAllFlagEvaluations() {
|
|
return useQuery({
|
|
queryKey: flagKeys.evaluation(),
|
|
queryFn: () => featureFlagsApi.evaluateAll(),
|
|
});
|
|
}
|
|
|
|
export function useFlagCheck(key: string) {
|
|
return useQuery({
|
|
queryKey: flagKeys.check(key),
|
|
queryFn: () => featureFlagsApi.check(key),
|
|
enabled: !!key,
|
|
});
|
|
}
|
|
|
|
// ==================== Helper functions ====================
|
|
|
|
export function getFlagTypeLabel(type: FlagType): string {
|
|
const labels: Record<FlagType, string> = {
|
|
boolean: 'Boolean',
|
|
string: 'String',
|
|
number: 'Number',
|
|
json: 'JSON',
|
|
};
|
|
return labels[type] || type;
|
|
}
|
|
|
|
export function getFlagTypeColor(type: FlagType): string {
|
|
const colors: Record<FlagType, string> = {
|
|
boolean: 'bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-400',
|
|
string: 'bg-blue-100 text-blue-800 dark:bg-blue-900/20 dark:text-blue-400',
|
|
number: 'bg-purple-100 text-purple-800 dark:bg-purple-900/20 dark:text-purple-400',
|
|
json: 'bg-orange-100 text-orange-800 dark:bg-orange-900/20 dark:text-orange-400',
|
|
};
|
|
return colors[type] || 'bg-gray-100 text-gray-800';
|
|
}
|
|
|
|
export function getFlagScopeLabel(scope: FlagScope): string {
|
|
const labels: Record<FlagScope, string> = {
|
|
global: 'Global',
|
|
tenant: 'Tenant',
|
|
user: 'User',
|
|
plan: 'Plan',
|
|
};
|
|
return labels[scope] || scope;
|
|
}
|
|
|
|
export function getFlagScopeColor(scope: FlagScope): string {
|
|
const colors: Record<FlagScope, string> = {
|
|
global: 'bg-gray-100 text-gray-800 dark:bg-gray-900/20 dark:text-gray-400',
|
|
tenant: 'bg-blue-100 text-blue-800 dark:bg-blue-900/20 dark:text-blue-400',
|
|
user: 'bg-purple-100 text-purple-800 dark:bg-purple-900/20 dark:text-purple-400',
|
|
plan: 'bg-amber-100 text-amber-800 dark:bg-amber-900/20 dark:text-amber-400',
|
|
};
|
|
return colors[scope] || 'bg-gray-100 text-gray-800';
|
|
}
|