-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
♻️(frontend) improve general error catching
- change parseAPIError to make it reusable on all requests - update components depending on it
- Loading branch information
1 parent
db23941
commit df0ecd6
Showing
7 changed files
with
113 additions
and
392 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
174 changes: 0 additions & 174 deletions
174
src/frontend/apps/desk/src/api/__tests__/parseAPIError.test.tsx
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,102 +1,106 @@ | ||
import { APIError } from '@/api/index'; | ||
|
||
type ErrorParams = { | ||
[fieldName: string]: { | ||
causes: string[]; | ||
causeShown?: string; | ||
handleError: () => void; | ||
}; | ||
}; | ||
type ErrorCallback = () => void; | ||
|
||
type ServerErrorParams = { | ||
defaultMessage: string; | ||
handleError?: () => void; | ||
}; | ||
// Type for the error tuple format [causes, message, handleError] | ||
type ErrorTuple = [string[], string, ErrorCallback | undefined]; | ||
|
||
// Server error tuple [defaultMessage, handleError] | ||
type ServerErrorTuple = [string, ErrorCallback | undefined]; | ||
|
||
export type parseAPIErrorParams = { | ||
error: APIError | null; | ||
errorParams?: ErrorParams; | ||
serverErrorParams: ServerErrorParams; | ||
}; | ||
/** | ||
* @function | ||
* @description created to centralize APIError handling to treat already discovered errors and treat error type 500 | ||
* with a default behaviour | ||
* @param error | ||
* @param errorParams | ||
* @param serverErrorParams | ||
* @todo worth refactor to make it easier to use, like const causes = parseAPIError( | ||
* error, | ||
* [ | ||
* [['error1', 'error2'], 'message', callback1], | ||
* [['error3', 'error4'], 'message', callback2], | ||
* ], | ||
* [['default error 500 message'], callbackErrorServer] | ||
* ) | ||
* @function parseAPIError | ||
* @description function to centralize APIError handling to treat discovered errors | ||
* and error type 500 with default behavior using a simplified tuple structure. | ||
* @param error - APIError object | ||
* @param errorParams - Array of tuples: each contains an array of causes, a message, and an optional callback function. | ||
* @param serverErrorParams - A tuple for server error handling: [defaultMessage, handleError] | ||
* @returns Array of error messages or undefined | ||
*/ | ||
|
||
export const parseAPIError = ({ | ||
error, | ||
errorParams, | ||
serverErrorParams, | ||
}: parseAPIErrorParams) => { | ||
if (!error || !serverErrorParams?.defaultMessage) { | ||
}: { | ||
error: APIError | null; | ||
errorParams?: ErrorTuple[]; | ||
serverErrorParams?: ServerErrorTuple; | ||
}): string[] | undefined => { | ||
if (!error) { | ||
return; | ||
} | ||
|
||
let causes: string[] = | ||
// Parse known error causes using the tuple structure | ||
const errorCauses = | ||
error.cause?.length && errorParams | ||
? parseAPIErrorCause({ causes: error.cause, errorParams }) | ||
: []; | ||
? parseAPIErrorCause(error, errorParams) | ||
: undefined; | ||
|
||
// Check if it's a server error (500) and handle that case | ||
const serverErrorCause = | ||
(error?.status === 500 || !error?.status) && serverErrorParams | ||
? parseServerAPIError(serverErrorParams) | ||
: undefined; | ||
|
||
if (error?.status === 500 || !error?.status) { | ||
causes = parseServerAPIError({ causes, serverErrorParams }); | ||
// Combine the causes and return | ||
const causes: string[] = errorCauses ? [...errorCauses] : []; | ||
if (serverErrorCause) { | ||
causes.unshift(serverErrorCause); | ||
} | ||
|
||
return causes; | ||
return causes.length ? causes : undefined; | ||
}; | ||
|
||
export const parseAPIErrorCause = ({ | ||
causes, | ||
errorParams, | ||
}: { | ||
causes: string[]; | ||
errorParams: ErrorParams; | ||
}): string[] => | ||
causes.reduce((arrayCauses, cause) => { | ||
const foundErrorParams = Object.values(errorParams).find((params) => | ||
params.causes.find((knownCause) => | ||
new RegExp(knownCause, 'i').test(cause), | ||
), | ||
); | ||
/** | ||
* @function parseAPIErrorCause | ||
* @description Processes known API error causes using the tuple structure. | ||
* @param error - APIError object | ||
* @param errorParams - Array of tuples: each contains an array of causes, a message, and an optional callback function. | ||
* @returns Array of error messages | ||
*/ | ||
export const parseAPIErrorCause = ( | ||
error: APIError, | ||
errorParams: ErrorTuple[], | ||
): string[] | undefined => { | ||
if (!error.cause) { | ||
return; | ||
} | ||
|
||
if (!foundErrorParams) { | ||
arrayCauses.push(cause); | ||
} | ||
return error.cause.reduce((causes: string[], cause: string) => { | ||
// Find the matching error tuple | ||
const matchedError = errorParams.find(([errorCauses]) => | ||
errorCauses.some((knownCause) => new RegExp(knownCause, 'i').test(cause)), | ||
); | ||
|
||
if (foundErrorParams?.causeShown) { | ||
arrayCauses.push(foundErrorParams.causeShown); | ||
} | ||
if (matchedError) { | ||
const [, message, handleError] = matchedError; | ||
causes.push(message); | ||
|
||
if (typeof foundErrorParams?.handleError === 'function') { | ||
foundErrorParams.handleError(); | ||
if (handleError) { | ||
handleError(); | ||
} | ||
} else { | ||
// If no match is found, add the original cause | ||
causes.push(cause); | ||
} | ||
|
||
return arrayCauses; | ||
}, [] as string[]); | ||
|
||
export const parseServerAPIError = ({ | ||
causes, | ||
serverErrorParams, | ||
}: { | ||
causes: string[]; | ||
serverErrorParams: ServerErrorParams; | ||
}): string[] => { | ||
causes.unshift(serverErrorParams.defaultMessage); | ||
return causes; | ||
}, []); | ||
}; | ||
|
||
if (typeof serverErrorParams?.handleError === 'function') { | ||
serverErrorParams.handleError(); | ||
/** | ||
* @function parseServerAPIError | ||
* @description Handles server errors (500) and adds the default message. | ||
* @param serverErrorParams - Tuple [defaultMessage, handleError] | ||
* @returns Server error message | ||
*/ | ||
export const parseServerAPIError = ([ | ||
defaultMessage, | ||
handleError, | ||
]: ServerErrorTuple): string => { | ||
if (handleError) { | ||
handleError(); | ||
} | ||
|
||
return causes; | ||
return defaultMessage; | ||
}; |
Oops, something went wrong.