Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions src/services/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { getUserToken } from '../redux/commonStore';
import { CustomError } from '../utils/types/CustomError';
import { ProblemDetailError } from '../utils/types/ProblemDetailError';
import { NetworkTimeoutError } from '../utils/types/NetworkTimeoutError';

const DEFAULT_TIMEOUT_MS = 50_000;
Expand Down Expand Up @@ -56,20 +56,26 @@ const prepareRequest = (init: FetchInitWithTimeout | undefined, token?: string)
return initWithSignal;
};

export const convertToCustomError = (response: string) => {
const errorJson = parseError(response);
if (errorJson?.businessErrorCode) {
return new CustomError(
`Server error: ${errorJson.detail}`,
export const convertToCustomError = (textError: string) => {
const errorJson = parseError(textError);
if (errorJson?.server && errorJson?.timestamp && errorJson?.traceId && errorJson?.detail) {
let date: Date = new Date(); // Fallback to current timestamp
try {
date = new Date(errorJson.timestamp);
} catch {
// Ignore
}
return new ProblemDetailError(
errorJson.detail,
errorJson.server,
date,
errorJson.traceId,
errorJson.status,
errorJson.businessErrorCode,
errorJson.businessErrorValues
);
}
if (errorJson?.detail) {
return new CustomError(`Server error: ${errorJson.detail}`, errorJson.status);
}
return new CustomError(errorJson);
return new Error(textError);
};

const handleError = (response: Response) => {
Expand Down
2 changes: 2 additions & 0 deletions src/translations/en/errorsEn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@

export const errorsEn = {
'errors.network.timeout': 'The request timed out. Please try again.',
'errors.technicalError':
'Server error: {message}\n (server: {serverName}, timestamp: {timestamp}, trace ID: {traceId})',
};
2 changes: 2 additions & 0 deletions src/translations/fr/errorsFr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@

export const errorsFr = {
'errors.network.timeout': 'La requête a expiré. Veuillez réessayer.',
'errors.technicalError':
'Erreur serveur: {message}\n (serveur: {serverName}, horodatage: {timestamp}, trace ID: {traceId})',
};
27 changes: 20 additions & 7 deletions src/utils/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import { SnackInputs, UseSnackMessageReturn } from '../hooks/useSnackMessage';
import { CustomError, formatMessageValues } from './types/CustomError';
import { ProblemDetailError, formatMessageValues } from './types/ProblemDetailError';
import { NetworkTimeoutError } from './types/NetworkTimeoutError';

export type HeaderSnackInputs = Pick<SnackInputs, 'headerId' | 'headerTxt' | 'headerValues'>;
Expand All @@ -30,12 +30,25 @@ export function snackWithFallback(
});
return;
}
if (error instanceof CustomError && error.businessErrorCode) {
snackError({
messageId: error.businessErrorCode,
messageValues: error.businessErrorValues ? formatMessageValues(error.businessErrorValues) : undefined,
...headerInputs,
});
if (error instanceof ProblemDetailError) {
if (error.businessErrorCode) {
snackError({
messageId: error.businessErrorCode,
messageValues: error.businessErrorValues ? formatMessageValues(error.businessErrorValues) : undefined,
...headerInputs,
});
} else {
snackError({
messageId: 'errors.technicalError',
messageValues: {
message: error.message,
serverName: error.serverName,
timestamp: error.timestamp.toLocaleString(), // It would require refactoring to adapt with GS language so we keep it like that for now
traceId: error.traceId,
},
...headerInputs,
});
}
} else {
catchErrorHandler(error, (message) => {
snackError({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
export class CustomError extends Error {
export class ProblemDetailError extends Error {
serverName: string;

timestamp: Date;

traceId: string;

status?: number;

businessErrorCode?: string;
Expand All @@ -13,11 +19,17 @@

constructor(
message: string,
serverName: string,
timestamp: Date,
traceId: string,
status?: number,
businessErrorCode?: string,
businessErrorValues?: Record<string, unknown>
) {
super(message);
this.serverName = serverName;
this.timestamp = timestamp;
this.traceId = traceId;
this.status = status;
this.businessErrorCode = businessErrorCode;
this.businessErrorValues = businessErrorValues;
Expand All @@ -28,7 +40,7 @@
return Object.fromEntries(
Object.entries(properties).map(([key, value]) => [
key,
typeof value === 'object' && value !== null ? JSON.stringify(value) : String(value),

Check warning on line 43 in src/utils/types/ProblemDetailError.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

'value' will use Object's default stringification format ('[object Object]') when stringified.

See more on https://sonarcloud.io/project/issues?id=gridsuite_commons-ui&issues=AZsS1enLo6AvxQiaXML3&open=AZsS1enLo6AvxQiaXML3&pullRequest=964
])
);
}
2 changes: 1 addition & 1 deletion src/utils/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
export * from './CustomError';
export * from './ProblemDetailError';
export * from './NetworkTimeoutError';
export * from './elementType';
export * from './equipmentType';
Expand Down
Loading