Files
api/web/store/unraidApi.ts
Pujit Mehrotra 4a29fc9dda fix(web): display error message in sidebar when api is offline (#984)
* fix(web): display error message in sidebar when api is offline

* refactor(web): move offline error derivation to UnraidApiStore

* feat(web): display error in upc when api is offline
2024-12-17 10:25:05 -05:00

117 lines
3.7 KiB
TypeScript

import { type ApolloClient as ApolloClientType, type NormalizedCacheObject } from '@apollo/client';
import { ArrowPathIcon } from '@heroicons/vue/24/solid';
import { WebguiUnraidApiCommand } from '~/composables/services/webgui';
import { client } from '~/helpers/create-apollo-client';
import { useErrorsStore } from '~/store/errors';
import { useServerStore } from '~/store/server';
import type { UserProfileLink } from '~/types/userProfile';
// import { logErrorMessages } from '@vue/apollo-util';
import { createPinia, defineStore, setActivePinia } from 'pinia';
/**
* @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components
* @see https://github.com/vuejs/pinia/discussions/1085
*/
setActivePinia(createPinia());
export const useUnraidApiStore = defineStore('unraidApi', () => {
const errorsStore = useErrorsStore();
const serverStore = useServerStore();
const unraidApiClient = ref<ApolloClientType<NormalizedCacheObject> | null>(client);
// const unraidApiErrors = ref<any[]>([]);
const unraidApiStatus = ref<'connecting' | 'offline' | 'online' | 'restarting'>('offline');
const prioritizeCorsError = ref(false); // Ensures we don't overwrite this specific error message with a non-descriptive network error message
const offlineError = computed(() => {
if (unraidApiStatus.value === 'offline') {
return new Error('The Unraid API is currently offline.');
}
});
// maintains an error in global store while api is offline
watch(
offlineError,
(error) => {
const errorId = 'unraidApiOffline';
if (error) {
errorsStore.setError({
heading: 'Warning: API is offline!',
message: error.message,
ref: errorId,
level: 'warning',
type: 'unraidApiState',
});
} else {
errorsStore.removeErrorByRef(errorId);
}
},
{ immediate: true }
);
const unraidApiRestartAction = computed((): UserProfileLink | undefined => {
const { connectPluginInstalled, stateDataError } = serverStore;
if (unraidApiStatus.value !== 'offline' || !connectPluginInstalled || stateDataError) {
return undefined;
}
return {
click: () => restartUnraidApiClient(),
emphasize: true,
icon: ArrowPathIcon,
text: 'Restart unraid-api',
};
});
/**
* Automatically called when an apiKey is unset in the serverStore
*/
const closeUnraidApiClient = async () => {
if (!unraidApiClient.value) {
return;
}
if (unraidApiClient.value) {
await unraidApiClient.value.clearStore();
unraidApiClient.value.stop();
// (wsLink.value as any).subscriptionClient.close(); // needed if we start using subscriptions
}
unraidApiClient.value = null;
unraidApiStatus.value = 'offline';
};
/**
* Can both start and restart the unraid-api depending on it's current status
*/
const restartUnraidApiClient = async () => {
const command = unraidApiStatus.value === 'offline' ? 'start' : 'restart';
unraidApiStatus.value = 'restarting';
try {
await WebguiUnraidApiCommand({
csrf_token: serverStore.csrf,
command,
});
} catch (error) {
let errorMessage = 'Unknown error';
if (typeof error === 'string') {
errorMessage = error.toUpperCase();
} else if (error instanceof Error) {
errorMessage = error.message;
}
errorsStore.setError({
heading: 'Error: unraid-api restart',
message: errorMessage,
level: 'error',
ref: 'restartUnraidApiClient',
type: 'request',
});
}
};
return {
unraidApiClient,
unraidApiStatus,
offlineError,
prioritizeCorsError,
unraidApiRestartAction,
closeUnraidApiClient,
restartUnraidApiClient,
};
});