llzai's picture
Upload 1793 files
9853396 verified
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { graphqlRequest } from '@/gql/graphql';
import { toast } from 'sonner';
import i18n from '@/lib/i18n';
import { useErrorHandler } from '@/hooks/use-error-handler';
import { getTokenFromStorage } from '@/stores/authStore';
// GraphQL queries and mutations
const SYSTEM_VERSION_QUERY = `
query SystemVersion {
systemVersion {
version
commit
buildTime
goVersion
platform
uptime
}
}
`;
export const CHECK_FOR_UPDATE_QUERY = `
query CheckForUpdate {
checkForUpdate {
currentVersion
latestVersion
hasUpdate
releaseUrl
}
}
`;
const BRAND_SETTINGS_QUERY = `
query BrandSettings {
brandSettings {
brandName
brandLogo
}
}
`;
const STORAGE_POLICY_QUERY = `
query StoragePolicy {
storagePolicy {
storeChunks
storeRequestBody
storeResponseBody
cleanupOptions {
resourceType
enabled
cleanupDays
}
}
}
`;
const UPDATE_BRAND_SETTINGS_MUTATION = `
mutation UpdateBrandSettings($input: UpdateBrandSettingsInput!) {
updateBrandSettings(input: $input)
}
`;
const UPDATE_STORAGE_POLICY_MUTATION = `
mutation UpdateStoragePolicy($input: UpdateStoragePolicyInput!) {
updateStoragePolicy(input: $input)
}
`;
const RETRY_POLICY_QUERY = `
query RetryPolicy {
retryPolicy {
maxChannelRetries
maxSingleChannelRetries
retryDelayMs
loadBalancerStrategy
enabled
autoDisableChannel {
enabled
statuses {
status
times
}
}
}
}
`;
const UPDATE_RETRY_POLICY_MUTATION = `
mutation UpdateRetryPolicy($input: UpdateRetryPolicyInput!) {
updateRetryPolicy(input: $input)
}
`;
const DEFAULT_DATA_STORAGE_QUERY = `
query DefaultDataStorageID {
defaultDataStorageID
}
`;
const UPDATE_DEFAULT_DATA_STORAGE_MUTATION = `
mutation UpdateDefaultDataStorage($input: UpdateDefaultDataStorageInput!) {
updateDefaultDataStorage(input: $input)
}
`;
const ONBOARDING_INFO_QUERY = `
query OnboardingInfo {
onboardingInfo {
onboarded
completedAt
systemModelSetting {
onboarded
completedAt
}
autoDisableChannel {
onboarded
completedAt
}
}
}
`;
const COMPLETE_ONBOARDING_MUTATION = `
mutation CompleteOnboarding($input: CompleteOnboardingInput!) {
completeOnboarding(input: $input)
}
`;
const COMPLETE_SYSTEM_MODEL_SETTING_ONBOARDING_MUTATION = `
mutation CompleteSystemModelSettingOnboarding($input: CompleteSystemModelSettingOnboardingInput!) {
completeSystemModelSettingOnboarding(input: $input)
}
`;
const COMPLETE_AUTO_DISABLE_CHANNEL_ONBOARDING_MUTATION = `
mutation CompleteAutoDisableChannelOnboarding($input: CompleteAutoDisableChannelOnboardingInput!) {
completeAutoDisableChannelOnboarding(input: $input)
}
`;
// Types
export interface BrandSettings {
brandName?: string;
brandLogo?: string;
}
export interface SystemGeneralSettings {
currencyCode: string;
timezone: string;
}
export interface UpdateSystemGeneralSettingsInput {
currencyCode?: string;
timezone?: string;
}
export interface StoragePolicy {
storeChunks: boolean;
storeRequestBody: boolean;
storeResponseBody: boolean;
cleanupOptions: CleanupOption[];
}
export interface CleanupOption {
resourceType: string;
enabled: boolean;
cleanupDays: number;
}
export interface UpdateBrandSettingsInput {
brandName?: string;
brandLogo?: string;
}
export interface UpdateStoragePolicyInput {
storeChunks?: boolean;
storeRequestBody?: boolean;
storeResponseBody?: boolean;
cleanupOptions?: CleanupOptionInput[];
}
export interface CleanupOptionInput {
resourceType: string;
enabled: boolean;
cleanupDays: number;
}
export interface AutoDisableChannelStatus {
status: number;
times: number;
}
export interface AutoDisableChannel {
enabled: boolean;
statuses: AutoDisableChannelStatus[];
}
export interface RetryPolicy {
maxChannelRetries: number;
maxSingleChannelRetries: number;
retryDelayMs: number;
loadBalancerStrategy: string;
enabled: boolean;
autoDisableChannel: AutoDisableChannel;
}
export interface AutoDisableChannelStatusInput {
status: number;
times: number;
}
export interface AutoDisableChannelInput {
enabled?: boolean;
statuses?: AutoDisableChannelStatusInput[];
}
export interface RetryPolicyInput {
maxChannelRetries?: number;
maxSingleChannelRetries?: number;
retryDelayMs?: number;
loadBalancerStrategy?: string;
enabled?: boolean;
autoDisableChannel?: AutoDisableChannelInput;
}
export interface UpdateDefaultDataStorageInput {
dataStorageID: string;
}
export interface SystemModelSettingOnboarding {
onboarded: boolean;
completedAt?: string;
}
export interface AutoDisableChannelOnboarding {
onboarded: boolean;
completedAt?: string;
}
export interface OnboardingInfo {
onboarded: boolean;
completedAt?: string;
systemModelSetting?: SystemModelSettingOnboarding;
autoDisableChannel?: AutoDisableChannelOnboarding;
}
export interface CompleteOnboardingInput {
dummy?: string;
}
export interface CompleteSystemModelSettingOnboardingInput {
dummy?: string;
}
export interface CompleteAutoDisableChannelOnboardingInput {
dummy?: string;
}
export interface SystemVersion {
version: string;
commit: string;
buildTime: string;
goVersion: string;
platform: string;
uptime: string;
}
export interface VersionCheck {
currentVersion: string;
latestVersion: string;
hasUpdate: boolean;
releaseUrl: string;
}
// Hooks
export function useBrandSettings() {
const { handleError } = useErrorHandler();
return useQuery({
queryKey: ['brandSettings'],
queryFn: async () => {
try {
const data = await graphqlRequest<{ brandSettings: BrandSettings }>(BRAND_SETTINGS_QUERY);
return data.brandSettings;
} catch (error) {
handleError(error, i18n.t('common.errors.internalServerError'));
throw error;
}
},
});
}
export function useStoragePolicy() {
const { handleError } = useErrorHandler();
return useQuery({
queryKey: ['storagePolicy'],
queryFn: async () => {
try {
const data = await graphqlRequest<{ storagePolicy: StoragePolicy }>(STORAGE_POLICY_QUERY);
return data.storagePolicy;
} catch (error) {
handleError(error, i18n.t('common.errors.internalServerError'));
throw error;
}
},
});
}
export function useUpdateBrandSettings() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: UpdateBrandSettingsInput) => {
const data = await graphqlRequest<{ updateBrandSettings: boolean }>(UPDATE_BRAND_SETTINGS_MUTATION, { input });
return data.updateBrandSettings;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['brandSettings'] });
toast.success(i18n.t('common.success.systemUpdated'));
},
onError: () => {
toast.error(i18n.t('common.errors.systemUpdateFailed'));
},
});
}
export function useUpdateStoragePolicy() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: UpdateStoragePolicyInput) => {
const data = await graphqlRequest<{ updateStoragePolicy: boolean }>(UPDATE_STORAGE_POLICY_MUTATION, { input });
return data.updateStoragePolicy;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['storagePolicy'] });
toast.success(i18n.t('common.success.systemUpdated'));
},
onError: () => {
toast.error(i18n.t('common.errors.systemUpdateFailed'));
},
});
}
export function useRetryPolicy() {
const { handleError } = useErrorHandler();
return useQuery({
queryKey: ['retryPolicy'],
queryFn: async () => {
try {
const data = await graphqlRequest<{ retryPolicy: RetryPolicy }>(RETRY_POLICY_QUERY);
return data.retryPolicy;
} catch (error) {
handleError(error, i18n.t('common.errors.internalServerError'));
throw error;
}
},
});
}
export function useUpdateRetryPolicy() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: RetryPolicyInput) => {
const data = await graphqlRequest<{ updateRetryPolicy: boolean }>(UPDATE_RETRY_POLICY_MUTATION, { input });
return data.updateRetryPolicy;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['retryPolicy'] });
toast.success(i18n.t('common.success.systemUpdated'));
},
onError: () => {
toast.error(i18n.t('common.errors.systemUpdateFailed'));
},
});
}
export function useDefaultDataStorageID() {
const { handleError } = useErrorHandler();
return useQuery({
queryKey: ['defaultDataStorageID'],
queryFn: async () => {
try {
const data = await graphqlRequest<{ defaultDataStorageID: string | null }>(DEFAULT_DATA_STORAGE_QUERY);
return data.defaultDataStorageID;
} catch (error) {
handleError(error, i18n.t('common.errors.internalServerError'));
throw error;
}
},
});
}
export function useUpdateDefaultDataStorage() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: UpdateDefaultDataStorageInput) => {
const data = await graphqlRequest<{ updateDefaultDataStorage: boolean }>(UPDATE_DEFAULT_DATA_STORAGE_MUTATION, { input });
return data.updateDefaultDataStorage;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['defaultDataStorageID'] });
toast.success(i18n.t('common.success.systemUpdated'));
},
onError: () => {
toast.error(i18n.t('common.errors.systemUpdateFailed'));
},
});
}
export function useOnboardingInfo() {
return useQuery({
queryKey: ['onboardingInfo'],
queryFn: async () => {
try {
const data = await graphqlRequest<{ onboardingInfo: OnboardingInfo | null }>(ONBOARDING_INFO_QUERY);
return data.onboardingInfo;
} catch (error) {
return {
onboarded: true,
completedAt: new Date().toISOString(),
};
}
},
});
}
export function useCompleteOnboarding() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input?: CompleteOnboardingInput) => {
const data = await graphqlRequest<{ completeOnboarding: boolean }>(COMPLETE_ONBOARDING_MUTATION, { input: input || {} });
return data.completeOnboarding;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['onboardingInfo'] });
},
onError: () => {
toast.error(i18n.t('common.errors.onboardingFailed'));
},
});
}
export function useCompleteSystemModelSettingOnboarding() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input?: CompleteSystemModelSettingOnboardingInput) => {
const data = await graphqlRequest<{ completeSystemModelSettingOnboarding: boolean }>(
COMPLETE_SYSTEM_MODEL_SETTING_ONBOARDING_MUTATION,
{ input: input || {} }
);
return data.completeSystemModelSettingOnboarding;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['onboardingInfo'] });
},
onError: () => {
toast.error(i18n.t('common.errors.onboardingFailed'));
},
});
}
export function useCompleteAutoDisableChannelOnboarding() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input?: CompleteAutoDisableChannelOnboardingInput) => {
const data = await graphqlRequest<{ completeAutoDisableChannelOnboarding: boolean }>(
COMPLETE_AUTO_DISABLE_CHANNEL_ONBOARDING_MUTATION,
{ input: input || {} }
);
return data.completeAutoDisableChannelOnboarding;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['onboardingInfo'] });
},
onError: () => {
toast.error(i18n.t('common.errors.onboardingFailed'));
},
});
}
export function useSystemVersion() {
return useQuery({
queryKey: ['systemVersion'],
queryFn: async () => {
const data = await graphqlRequest<{ systemVersion: SystemVersion }>(SYSTEM_VERSION_QUERY);
return data.systemVersion;
},
});
}
export function useCheckForUpdate() {
return useQuery({
queryKey: ['checkForUpdate'],
queryFn: async () => {
const data = await graphqlRequest<{ checkForUpdate: VersionCheck }>(CHECK_FOR_UPDATE_QUERY);
return data.checkForUpdate;
},
retry: false,
staleTime: 60 * 60 * 1000, // 1 hour
});
}
// Model Settings
const MODEL_SETTINGS_QUERY = `
query ModelSettings {
systemModelSettings {
fallbackToChannelsOnModelNotFound
queryAllChannelModels
}
}
`;
const UPDATE_MODEL_SETTINGS_MUTATION = `
mutation UpdateModelSettings($input: UpdateSystemModelSettingsInput!) {
updateSystemModelSettings(input: $input)
}
`;
const CHANNEL_SETTINGS_QUERY = `
query SystemChannelSettings {
systemChannelSettings {
probe {
enabled
frequency
}
}
}
`;
const UPDATE_CHANNEL_SETTINGS_MUTATION = `
mutation UpdateChannelSettings($input: UpdateSystemChannelSettingsInput!) {
updateSystemChannelSettings(input: $input)
}
`;
const SYSTEM_GENERAL_SETTINGS_QUERY = `
query SystemGeneralSettings {
systemGeneralSettings {
currencyCode
timezone
}
}
`;
const UPDATE_SYSTEM_GENERAL_SETTINGS_MUTATION = `
mutation UpdateSystemGeneralSettings($input: UpdateSystemGeneralSettingsInput!) {
updateSystemGeneralSettings(input: $input)
}
`;
export interface ModelSettings {
fallbackToChannelsOnModelNotFound: boolean;
queryAllChannelModels: boolean;
}
export interface UpdateModelSettingsInput {
fallbackToChannelsOnModelNotFound?: boolean;
queryAllChannelModels?: boolean;
}
export function useModelSettings() {
const { handleError } = useErrorHandler();
return useQuery({
queryKey: ['modelSettings'],
queryFn: async () => {
try {
const data = await graphqlRequest<{ systemModelSettings: ModelSettings }>(MODEL_SETTINGS_QUERY);
return data.systemModelSettings;
} catch (error) {
handleError(error, i18n.t('common.errors.internalServerError'));
throw error;
}
},
});
}
export function useUpdateModelSettings() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: UpdateModelSettingsInput) => {
const data = await graphqlRequest<{ updateSystemModelSettings: boolean }>(UPDATE_MODEL_SETTINGS_MUTATION, { input });
return data.updateSystemModelSettings;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['modelSettings'] });
toast.success(i18n.t('common.success.systemUpdated'));
},
onError: () => {
toast.error(i18n.t('common.errors.systemUpdateFailed'));
},
});
}
export type ProbeFrequency = 'ONE_MINUTE' | 'FIVE_MINUTES' | 'THIRTY_MINUTES' | 'ONE_HOUR';
export interface ChannelProbeSetting {
enabled: boolean;
frequency: ProbeFrequency;
}
export interface ChannelSetting {
probe: ChannelProbeSetting;
}
export interface UpdateChannelProbeSettingInput {
enabled?: boolean;
frequency?: ProbeFrequency;
}
export interface UpdateSystemChannelSettingsInput {
probe?: UpdateChannelProbeSettingInput;
}
export function useChannelSetting() {
const { handleError } = useErrorHandler();
return useQuery({
queryKey: ['channelSetting'],
queryFn: async () => {
try {
const data = await graphqlRequest<{ systemChannelSettings: ChannelSetting }>(CHANNEL_SETTINGS_QUERY);
return data.systemChannelSettings;
} catch (error) {
handleError(error, i18n.t('common.errors.internalServerError'));
throw error;
}
},
});
}
export function useUpdateChannelSetting() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: UpdateSystemChannelSettingsInput) => {
const data = await graphqlRequest<{ updateSystemChannelSettings: boolean }>(UPDATE_CHANNEL_SETTINGS_MUTATION, { input });
return data.updateSystemChannelSettings;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['channelSetting'] });
queryClient.invalidateQueries({ queryKey: ['channelProbeData'] });
toast.success(i18n.t('common.success.systemUpdated'));
},
onError: () => {
toast.error(i18n.t('common.errors.systemUpdateFailed'));
},
});
}
export function useGeneralSettings() {
const { handleError } = useErrorHandler();
return useQuery({
queryKey: ['generalSettings'],
queryFn: async () => {
try {
const data = await graphqlRequest<{ systemGeneralSettings: SystemGeneralSettings }>(SYSTEM_GENERAL_SETTINGS_QUERY);
return data.systemGeneralSettings;
} catch (error) {
handleError(error, i18n.t('common.errors.internalServerError'));
throw error;
}
},
});
}
export function useUpdateGeneralSettings() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: UpdateSystemGeneralSettingsInput) => {
const data = await graphqlRequest<{ updateSystemGeneralSettings: boolean }>(UPDATE_SYSTEM_GENERAL_SETTINGS_MUTATION, { input });
return data.updateSystemGeneralSettings;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['generalSettings'] });
toast.success(i18n.t('common.success.systemUpdated'));
},
onError: () => {
toast.error(i18n.t('common.errors.systemUpdateFailed'));
},
});
}
// Backup and Restore
const BACKUP_MUTATION = `
mutation Backup($input: BackupOptionsInput!) {
backup(input: $input) {
success
data
message
}
}
`;
const RESTORE_MUTATION = `
mutation Restore($file: Upload!, $input: RestoreOptionsInput!) {
restore(file: $file, input: $input) {
success
message
}
}
`;
export interface BackupOptionsInput {
includeChannels: boolean;
includeModelPrices: boolean;
includeModels: boolean;
includeAPIKeys: boolean;
}
export interface BackupPayload {
success: boolean;
data?: string;
message?: string;
}
export interface RestoreOptionsInput {
includeChannels: boolean;
includeModelPrices: boolean;
includeModels: boolean;
includeAPIKeys: boolean;
channelConflictStrategy: 'skip' | 'overwrite' | 'error';
modelConflictStrategy: 'skip' | 'overwrite' | 'error';
modelPriceConflictStrategy: 'skip' | 'overwrite' | 'error';
apiKeyConflictStrategy: 'skip' | 'overwrite' | 'error';
}
export interface RestorePayload {
success: boolean;
message?: string;
}
export function useBackup() {
return useMutation({
mutationFn: async (input: BackupOptionsInput) => {
const data = await graphqlRequest<{ backup: BackupPayload }>(BACKUP_MUTATION, { input });
return data.backup;
},
onSuccess: (data) => {
if (data.success && data.data) {
const blob = new Blob([data.data], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
a.download = `axonhub-backup-${timestamp}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
toast.success(data.message || i18n.t('system.backup.success'));
} else {
toast.error(data.message || i18n.t('system.backup.failed'));
}
},
onError: () => {
toast.error(i18n.t('system.backup.failed'));
},
});
}
export function useRestore() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({ file, input }: { file: File; input: RestoreOptionsInput }) => {
const formData = new FormData();
formData.append('operations', JSON.stringify({
query: RESTORE_MUTATION,
variables: { file: null, input }
}));
formData.append('map', JSON.stringify({ '0': ['variables.file'] }));
formData.append('0', file);
const token = getTokenFromStorage();
const response = await fetch('/admin/graphql', {
method: 'POST',
headers: {
'Authorization': token ? `Bearer ${token}` : '',
},
body: formData,
});
const result = await response.json();
if (result.errors) {
throw new Error(result.errors[0].message);
}
return result.data.restore as RestorePayload;
},
onSuccess: (data) => {
if (data.success) {
queryClient.invalidateQueries();
toast.success(data.message || i18n.t('system.restore.success'));
} else {
toast.error(data.message || i18n.t('system.restore.failed'));
}
},
onError: (error: Error) => {
toast.error(error.message || i18n.t('system.restore.failed'));
},
});
}
// Auto Backup Settings
const AUTO_BACKUP_SETTINGS_QUERY = `
query AutoBackupSettings {
autoBackupSettings {
enabled
frequency
dataStorageID
includeChannels
includeModels
includeAPIKeys
includeModelPrices
retentionDays
lastBackupAt
lastBackupError
}
}
`;
const UPDATE_AUTO_BACKUP_SETTINGS_MUTATION = `
mutation UpdateAutoBackupSettings($input: UpdateAutoBackupSettingsInput!) {
updateAutoBackupSettings(input: $input)
}
`;
const TRIGGER_AUTO_BACKUP_MUTATION = `
mutation TriggerAutoBackup {
triggerAutoBackup {
success
message
}
}
`;
export type BackupFrequency = 'daily' | 'weekly' | 'monthly';
export interface AutoBackupSettings {
enabled: boolean;
frequency: BackupFrequency;
dataStorageID: number;
includeChannels: boolean;
includeModels: boolean;
includeAPIKeys: boolean;
includeModelPrices: boolean;
retentionDays: number;
lastBackupAt?: string;
lastBackupError?: string;
}
export interface UpdateAutoBackupSettingsInput {
enabled?: boolean;
frequency?: BackupFrequency;
dataStorageID?: number;
includeChannels?: boolean;
includeModels?: boolean;
includeAPIKeys?: boolean;
includeModelPrices?: boolean;
retentionDays?: number;
}
export function useAutoBackupSettings() {
const { handleError } = useErrorHandler();
return useQuery({
queryKey: ['autoBackupSettings'],
queryFn: async () => {
try {
const data = await graphqlRequest<{ autoBackupSettings: AutoBackupSettings }>(AUTO_BACKUP_SETTINGS_QUERY);
return data.autoBackupSettings;
} catch (error) {
handleError(error, i18n.t('common.errors.internalServerError'));
throw error;
}
},
});
}
export function useUpdateAutoBackupSettings() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: UpdateAutoBackupSettingsInput) => {
const data = await graphqlRequest<{ updateAutoBackupSettings: boolean }>(UPDATE_AUTO_BACKUP_SETTINGS_MUTATION, { input });
return data.updateAutoBackupSettings;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['autoBackupSettings'] });
toast.success(i18n.t('common.success.systemUpdated'));
},
onError: () => {
toast.error(i18n.t('common.errors.systemUpdateFailed'));
},
});
}
export function useTriggerAutoBackup() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async () => {
const data = await graphqlRequest<{ triggerAutoBackup: { success: boolean; message?: string } }>(
TRIGGER_AUTO_BACKUP_MUTATION
);
return data.triggerAutoBackup;
},
onSuccess: (data) => {
queryClient.invalidateQueries({ queryKey: ['autoBackupSettings'] });
if (data.success) {
toast.success(i18n.t('system.autoBackup.triggerSuccess'));
} else {
toast.error(data.message || i18n.t('system.autoBackup.triggerFailed'));
}
},
onError: () => {
toast.error(i18n.t('system.autoBackup.triggerFailed'));
},
});
}