From 76f9637d771d513df8edddb3a2687937195d6b35 Mon Sep 17 00:00:00 2001 From: Nicolas Meienberger Date: Wed, 6 Dec 2023 21:52:49 +0100 Subject: [PATCH] refactor(dashboard): use onError on server actions --- .../worker/src/lib/socket/SocketManager.ts | 2 +- .../worker/src/services/app/app.executors.ts | 5 ++- pnpm-lock.yaml | 13 ++++++ .../LoginContainer/LoginContainer.tsx | 32 ++++++++----- .../RegisterContainer/RegisterContainer.tsx | 18 +++++--- .../ResetPasswordContainer.tsx | 12 ++--- .../AppDetailsContainer.tsx | 14 +++--- .../ChangePasswordForm/ChangePasswordForm.tsx | 13 +++--- .../ChangeUsernameForm/ChangeUsernameForm.tsx | 13 +++--- .../settings/components/OtpForm/OtpForm.tsx | 45 +++++++++---------- .../SettingsContainer/SettingsContainer.tsx | 20 +++++---- src/lib/safe-action.ts | 2 +- 12 files changed, 106 insertions(+), 83 deletions(-) diff --git a/packages/worker/src/lib/socket/SocketManager.ts b/packages/worker/src/lib/socket/SocketManager.ts index 445e344c..a1c922f2 100644 --- a/packages/worker/src/lib/socket/SocketManager.ts +++ b/packages/worker/src/lib/socket/SocketManager.ts @@ -1,4 +1,4 @@ -import { SocketEvent } from '@runtipi/shared'; +import { SocketEvent } from '@runtipi/shared/src/schemas/socket'; import { Socket } from 'socket.io'; import { logger } from '../logger'; diff --git a/packages/worker/src/services/app/app.executors.ts b/packages/worker/src/services/app/app.executors.ts index f01d513e..fa813c8c 100644 --- a/packages/worker/src/services/app/app.executors.ts +++ b/packages/worker/src/services/app/app.executors.ts @@ -3,7 +3,8 @@ import fs from 'fs'; import path from 'path'; import pg from 'pg'; -import { execAsync, pathExists, SocketEvent } from '@runtipi/shared'; +import { execAsync, pathExists } from '@runtipi/shared'; +import { SocketEvent } from '@runtipi/shared/src/schemas/socket'; import { copyDataDir, generateEnvFile } from './app.helpers'; import { logger } from '@/lib/logger'; import { compose } from '@/lib/docker'; @@ -34,7 +35,7 @@ export class AppExecutors { this.logger = logger; } - private handleAppError = (err: unknown, appId: string, event: SocketEvent['event']) => { + private handleAppError = (err: unknown, appId: string, event: Extract['event']) => { if (err instanceof Error) { SocketManager.emit({ type: 'app', event, data: { appId, error: err.message } }); this.logger.error(`An error occurred: ${err.message}`); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1e6fddb0..6099d3d9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4209,6 +4209,11 @@ packages: /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + /base64id@2.0.0: + resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} + engines: {node: ^4.5.0 || >= 5.9} + dev: false + /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} @@ -4673,6 +4678,14 @@ packages: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} dev: true + /cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + dev: false + /cosmiconfig@7.1.0: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} diff --git a/src/app/(auth)/login/components/LoginContainer/LoginContainer.tsx b/src/app/(auth)/login/components/LoginContainer/LoginContainer.tsx index 067f874e..1c389563 100644 --- a/src/app/(auth)/login/components/LoginContainer/LoginContainer.tsx +++ b/src/app/(auth)/login/components/LoginContainer/LoginContainer.tsx @@ -14,10 +14,11 @@ export function LoginContainer() { const router = useRouter(); const loginMutation = useAction(loginAction, { + onError: (e) => { + if (e.serverError) toast.error(e.serverError); + }, onSuccess: (data) => { - if (!data.success) { - toast.error(data.failure.reason); - } else if (data.success && data.totpSessionId) { + if (data.success && data.totpSessionId) { setTotpSessionId(data.totpSessionId); } else { router.push('/dashboard'); @@ -26,18 +27,27 @@ export function LoginContainer() { }); const verifyTotpMutation = useAction(verifyTotpAction, { - onSuccess: (data) => { - if (!data.success) { - toast.error(data.failure.reason); - } else { - router.push('/dashboard'); - } + onError: (e) => { + if (e.serverError) toast.error(e.serverError); + }, + onSuccess: () => { + router.push('/dashboard'); }, }); if (totpSessionId) { - return verifyTotpMutation.execute({ totpCode, totpSessionId })} />; + return ( + verifyTotpMutation.execute({ totpCode, totpSessionId })} + /> + ); } - return loginMutation.execute({ username: email, password })} />; + return ( + loginMutation.execute({ username: email, password })} + /> + ); } diff --git a/src/app/(auth)/register/components/RegisterContainer/RegisterContainer.tsx b/src/app/(auth)/register/components/RegisterContainer/RegisterContainer.tsx index 5941105a..2df0a287 100644 --- a/src/app/(auth)/register/components/RegisterContainer/RegisterContainer.tsx +++ b/src/app/(auth)/register/components/RegisterContainer/RegisterContainer.tsx @@ -11,14 +11,18 @@ export const RegisterContainer: React.FC = () => { const router = useRouter(); const registerMutation = useAction(registerAction, { - onSuccess: (data) => { - if (!data.success) { - toast.error(data.failure.reason); - } else { - router.push('/dashboard'); - } + onError: (e) => { + if (e.serverError) toast.error(e.serverError); + }, + onSuccess: () => { + router.push('/dashboard'); }, }); - return registerMutation.execute({ username: email, password })} loading={registerMutation.status === 'executing'} />; + return ( + registerMutation.execute({ username: email, password })} + loading={registerMutation.status === 'executing'} + /> + ); }; diff --git a/src/app/(auth)/reset-password/components/ResetPasswordContainer/ResetPasswordContainer.tsx b/src/app/(auth)/reset-password/components/ResetPasswordContainer/ResetPasswordContainer.tsx index a0bb6fa5..422bd199 100644 --- a/src/app/(auth)/reset-password/components/ResetPasswordContainer/ResetPasswordContainer.tsx +++ b/src/app/(auth)/reset-password/components/ResetPasswordContainer/ResetPasswordContainer.tsx @@ -15,18 +15,14 @@ export const ResetPasswordContainer: React.FC = () => { const router = useRouter(); const resetPasswordMutation = useAction(resetPasswordAction, { - onSuccess: (data) => { - if (!data.success) { - toast.error(data.failure.reason); - } + onError: (error) => { + if (error.serverError) toast.error(error.serverError); }, }); const cancelRequestMutation = useAction(cancelResetPasswordAction, { - onSuccess: (data) => { - if (!data.success) { - toast.error(data.failure.reason); - } + onError: (error) => { + if (error.serverError) toast.error(error.serverError); }, }); diff --git a/src/app/(dashboard)/app-store/[id]/components/AppDetailsContainer/AppDetailsContainer.tsx b/src/app/(dashboard)/app-store/[id]/components/AppDetailsContainer/AppDetailsContainer.tsx index 9d1e86f7..e4ccb589 100644 --- a/src/app/(dashboard)/app-store/[id]/components/AppDetailsContainer/AppDetailsContainer.tsx +++ b/src/app/(dashboard)/app-store/[id]/components/AppDetailsContainer/AppDetailsContainer.tsx @@ -45,7 +45,7 @@ export const AppDetailsContainer: React.FC = ({ app, l const installMutation = useAction(installAppAction, { onError: (e) => { - toast.error(e.serverError!); + if (e.serverError) toast.error(e.serverError); }, onExecute: () => { setOptimisticStatus('installing'); @@ -55,7 +55,7 @@ export const AppDetailsContainer: React.FC = ({ app, l const uninstallMutation = useAction(uninstallAppAction, { onError: (e) => { - toast.error(e.serverError!); + if (e.serverError) toast.error(e.serverError); }, onExecute: () => { uninstallDisclosure.close(); @@ -65,7 +65,7 @@ export const AppDetailsContainer: React.FC = ({ app, l const stopMutation = useAction(stopAppAction, { onError: (e) => { - toast.error(e.serverError!); + if (e.serverError) toast.error(e.serverError); }, onExecute: () => { stopDisclosure.close(); @@ -75,7 +75,7 @@ export const AppDetailsContainer: React.FC = ({ app, l const startMutation = useAction(startAppAction, { onError: (e) => { - toast.error(e.serverError!); + if (e.serverError) toast.error(e.serverError); }, onExecute: () => { setOptimisticStatus('starting'); @@ -84,7 +84,7 @@ export const AppDetailsContainer: React.FC = ({ app, l const updateMutation = useAction(updateAppAction, { onError: (e) => { - toast.error(e.serverError!); + if (e.serverError) toast.error(e.serverError); }, onExecute: () => { updateDisclosure.close(); @@ -94,7 +94,7 @@ export const AppDetailsContainer: React.FC = ({ app, l const updateConfigMutation = useAction(updateAppConfigAction, { onError: (e) => { - toast.error(e.serverError!); + if (e.serverError) toast.error(e.serverError); }, onExecute: () => { updateSettingsDisclosure.close(); @@ -106,7 +106,7 @@ export const AppDetailsContainer: React.FC = ({ app, l const resetMutation = useAction(resetAppAction, { onError: (e) => { - toast.error(e.serverError!); + if (e.serverError) toast.error(e.serverError); }, onExecute: () => { resetAppDisclosure.open(); diff --git a/src/app/(dashboard)/settings/components/ChangePasswordForm/ChangePasswordForm.tsx b/src/app/(dashboard)/settings/components/ChangePasswordForm/ChangePasswordForm.tsx index 85bb9eb7..05fffe98 100644 --- a/src/app/(dashboard)/settings/components/ChangePasswordForm/ChangePasswordForm.tsx +++ b/src/app/(dashboard)/settings/components/ChangePasswordForm/ChangePasswordForm.tsx @@ -34,13 +34,12 @@ export const ChangePasswordForm = () => { const router = useRouter(); const changePasswordMutation = useAction(changePasswordAction, { - onSuccess: (data) => { - if (!data.success) { - toast.error(data.failure.reason); - } else { - toast.success(t('password-change-success')); - router.push('/'); - } + onError: (e) => { + if (e.serverError) toast.error(e.serverError); + }, + onSuccess: () => { + toast.success(t('password-change-success')); + router.push('/'); }, }); diff --git a/src/app/(dashboard)/settings/components/ChangeUsernameForm/ChangeUsernameForm.tsx b/src/app/(dashboard)/settings/components/ChangeUsernameForm/ChangeUsernameForm.tsx index 924226c8..9de9d4f5 100644 --- a/src/app/(dashboard)/settings/components/ChangeUsernameForm/ChangeUsernameForm.tsx +++ b/src/app/(dashboard)/settings/components/ChangeUsernameForm/ChangeUsernameForm.tsx @@ -27,13 +27,12 @@ export const ChangeUsernameForm = ({ username }: Props) => { type FormValues = z.infer; const changeUsernameMutation = useAction(changeUsernameAction, { - onSuccess: (data) => { - if (!data.success) { - toast.error(data.failure.reason); - } else { - toast.success(t('change-username.success')); - router.push('/'); - } + onError: (e) => { + if (e.serverError) toast.error(e.serverError); + }, + onSuccess: () => { + toast.success(t('change-username.success')); + router.push('/'); }, }); diff --git a/src/app/(dashboard)/settings/components/OtpForm/OtpForm.tsx b/src/app/(dashboard)/settings/components/OtpForm/OtpForm.tsx index 5591a06b..27dc100b 100644 --- a/src/app/(dashboard)/settings/components/OtpForm/OtpForm.tsx +++ b/src/app/(dashboard)/settings/components/OtpForm/OtpForm.tsx @@ -29,28 +29,26 @@ export const OtpForm = (props: { totpEnabled: boolean }) => { onExecute: () => { setupOtpDisclosure.close(); }, + onError: (e) => { + setPassword(''); + if (e.serverError) toast.error(e.serverError); + }, onSuccess: (data) => { - if (!data.success) { - setPassword(''); - toast.error(data.failure.reason); - } else { - setKey(data.key); - setUri(data.uri); - } + setKey(data.key); + setUri(data.uri); }, }); const setupTotpMutation = useAction(setupTotpAction, { - onSuccess: (data) => { - if (!data.success) { - setTotpCode(''); - toast.error(data.failure.reason); - } else { - setTotpCode(''); - setKey(''); - setUri(''); - toast.success(t('2fa-enable-success')); - } + onError: (e) => { + setTotpCode(''); + if (e.serverError) toast.error(e.serverError); + }, + onSuccess: () => { + setTotpCode(''); + setKey(''); + setUri(''); + toast.success(t('2fa-enable-success')); }, }); @@ -58,13 +56,12 @@ export const OtpForm = (props: { totpEnabled: boolean }) => { onExecute: () => { disableOtpDisclosure.close(); }, - onSuccess: (data) => { - if (!data.success) { - setPassword(''); - toast.error(data.failure.reason); - } else { - toast.success(t('2fa-disable-success')); - } + onError: (e) => { + setPassword(''); + if (e.serverError) toast.error(e.serverError); + }, + onSuccess: () => { + toast.success(t('2fa-disable-success')); }, }); diff --git a/src/app/(dashboard)/settings/components/SettingsContainer/SettingsContainer.tsx b/src/app/(dashboard)/settings/components/SettingsContainer/SettingsContainer.tsx index b7bc96b7..84d71c0e 100644 --- a/src/app/(dashboard)/settings/components/SettingsContainer/SettingsContainer.tsx +++ b/src/app/(dashboard)/settings/components/SettingsContainer/SettingsContainer.tsx @@ -20,13 +20,12 @@ export const SettingsContainer = ({ initialValues, currentLocale }: Props) => { const router = useRouter(); const updateSettingsMutation = useAction(updateSettingsAction, { - onSuccess: (data) => { - if (!data.success) { - toast.error(data.failure.reason); - } else { - toast.success(t('settings.settings.settings-updated')); - router.refresh(); - } + onError: (e) => { + if (e.serverError) toast.error(e.serverError); + }, + onSuccess: () => { + toast.success(t('settings.settings.settings-updated')); + router.refresh(); }, }); @@ -36,7 +35,12 @@ export const SettingsContainer = ({ initialValues, currentLocale }: Props) => { return (
- +
); }; diff --git a/src/lib/safe-action.ts b/src/lib/safe-action.ts index da637215..cfe837a3 100644 --- a/src/lib/safe-action.ts +++ b/src/lib/safe-action.ts @@ -6,7 +6,7 @@ export const action = createSafeActionClient({ console.error('Error from server', e); return { - serverError: e.message, + serverError: e.message || 'An unexpected error occurred', }; }, });