Improve userFriendlyMessage devX (#16815)
Two challenges with error messages - always provide a useful/meaningful error message for the end user instead of the generic one. eg: show "Wrong password" and not "An error occured" - avoid technical details unless error regards a technical feature. eg: show "An error occured" and not "Invalid post-hook payload."; but do show "Invalid issuer URL." as it occurs while configuring SSO What this PR does - Make userFriendlyMessage mandatory for widely used GraphqlQueryRunnerException and CommonQueryRunnerException, so that developers are forced to ask themselves what the error message should be, and as it contains very wide error codes (eg: "Bad request") which should not be mapped to just one default message - Keep userFriendlyMessage optional for service-specific exceptions (eg: workflowStepExecutorException), but convert the error code to userFriendlyMessage mapper to a switch case function with a typecheck ensuring that all codes are mapped to a message. These default messages are still overridable where they are thrown.
This commit is contained in:
+26
-13
@@ -1,6 +1,8 @@
|
||||
import { type MessageDescriptor } from '@lingui/core';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { assertUnreachable } from 'twenty-shared/utils';
|
||||
|
||||
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
|
||||
export enum ObjectMetadataExceptionCode {
|
||||
@@ -14,18 +16,29 @@ export enum ObjectMetadataExceptionCode {
|
||||
NAME_CONFLICT = 'NAME_CONFLICT',
|
||||
}
|
||||
|
||||
const objectMetadataExceptionUserFriendlyMessages: Record<
|
||||
ObjectMetadataExceptionCode,
|
||||
MessageDescriptor
|
||||
> = {
|
||||
[ObjectMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND]: msg`Object not found.`,
|
||||
[ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT]: msg`Invalid object input.`,
|
||||
[ObjectMetadataExceptionCode.OBJECT_MUTATION_NOT_ALLOWED]: msg`This object cannot be modified.`,
|
||||
[ObjectMetadataExceptionCode.OBJECT_ALREADY_EXISTS]: msg`An object with this name already exists.`,
|
||||
[ObjectMetadataExceptionCode.MISSING_CUSTOM_OBJECT_DEFAULT_LABEL_IDENTIFIER_FIELD]: msg`Custom object is missing a label identifier field.`,
|
||||
[ObjectMetadataExceptionCode.INVALID_ORM_OUTPUT]: msg`Invalid data format.`,
|
||||
[ObjectMetadataExceptionCode.INTERNAL_SERVER_ERROR]: msg`An unexpected error occurred.`,
|
||||
[ObjectMetadataExceptionCode.NAME_CONFLICT]: msg`A name conflict occurred.`,
|
||||
const getObjectMetadataExceptionUserFriendlyMessage = (
|
||||
code: ObjectMetadataExceptionCode,
|
||||
) => {
|
||||
switch (code) {
|
||||
case ObjectMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND:
|
||||
return msg`Object not found.`;
|
||||
case ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT:
|
||||
return msg`Invalid object input.`;
|
||||
case ObjectMetadataExceptionCode.OBJECT_MUTATION_NOT_ALLOWED:
|
||||
return msg`This object cannot be modified.`;
|
||||
case ObjectMetadataExceptionCode.OBJECT_ALREADY_EXISTS:
|
||||
return msg`An object with this name already exists.`;
|
||||
case ObjectMetadataExceptionCode.MISSING_CUSTOM_OBJECT_DEFAULT_LABEL_IDENTIFIER_FIELD:
|
||||
return msg`Custom object is missing a label identifier field.`;
|
||||
case ObjectMetadataExceptionCode.INVALID_ORM_OUTPUT:
|
||||
return msg`Invalid data format.`;
|
||||
case ObjectMetadataExceptionCode.INTERNAL_SERVER_ERROR:
|
||||
return STANDARD_ERROR_MESSAGE;
|
||||
case ObjectMetadataExceptionCode.NAME_CONFLICT:
|
||||
return msg`A name conflict occurred.`;
|
||||
default:
|
||||
assertUnreachable(code);
|
||||
}
|
||||
};
|
||||
|
||||
export class ObjectMetadataException extends CustomException<ObjectMetadataExceptionCode> {
|
||||
@@ -37,7 +50,7 @@ export class ObjectMetadataException extends CustomException<ObjectMetadataExcep
|
||||
super(message, code, {
|
||||
userFriendlyMessage:
|
||||
userFriendlyMessage ??
|
||||
objectMetadataExceptionUserFriendlyMessages[code],
|
||||
getObjectMetadataExceptionUserFriendlyMessage(code),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user