Fix scalar throwing 500 (#9465)

## Context
Scalar validation/serde throws 500 instead of 400.

## Test
Before
<img width="785" alt="Screenshot 2025-01-08 at 19 17 14"
src="https://github.com/user-attachments/assets/61fadbd0-ce62-49be-bda6-c7047feb8725"
/>

After
<img width="831" alt="Screenshot 2025-01-08 at 19 16 05"
src="https://github.com/user-attachments/assets/d7038f0c-ea7a-4016-90d8-d2ce35c5763b"
/>
This commit is contained in:
Weiko
2025-01-08 19:24:14 +01:00
committed by GitHub
parent 09513b66c4
commit 9bfcd1573c
5 changed files with 24 additions and 12 deletions

View File

@ -1,25 +1,27 @@
import { GraphQLScalarType, Kind } from 'graphql';
import { ValidationError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
export const CursorScalarType = new GraphQLScalarType({
name: 'Cursor',
description: 'A custom scalar that represents a cursor for pagination',
serialize(value) {
if (typeof value !== 'string') {
throw new Error('Cursor must be a string');
throw new ValidationError('Cursor must be a string');
}
return value;
},
parseValue(value) {
if (typeof value !== 'string') {
throw new Error('Cursor must be a string');
throw new ValidationError('Cursor must be a string');
}
return value;
},
parseLiteral(ast) {
if (ast.kind !== Kind.STRING) {
throw new Error('Cursor must be a string');
throw new ValidationError('Cursor must be a string');
}
return ast.value;

View File

@ -1,5 +1,7 @@
import { GraphQLScalarType, Kind } from 'graphql';
import { ValidationError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
type PositionType = 'first' | 'last' | number;
const isValidStringPosition = (value: string): boolean =>
@ -13,7 +15,9 @@ const checkPosition = (value: any): PositionType => {
return value;
}
throw new Error('Invalid position found');
throw new ValidationError(
`Invalid position value: '${value}'. Position must be 'first', 'last', or a number`,
);
};
export const PositionScalarType = new GraphQLScalarType({
@ -34,6 +38,6 @@ export const PositionScalarType = new GraphQLScalarType({
return parseFloat(ast.value);
}
throw new Error('Invalid position found');
throw new ValidationError('Invalid position value');
},
});

View File

@ -3,6 +3,8 @@ import { Maybe } from 'graphql-yoga';
import { ObjMap } from 'graphql/jsutils/ObjMap';
import { ASTNode, Kind, ValueNode } from 'graphql/language';
import { ValidationError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
const parseLiteral = (
ast: ValueNode,
variables?: Maybe<ObjMap<unknown>>,
@ -25,7 +27,7 @@ const parseLiteral = (
case Kind.VARIABLE:
return variables ? variables[ast.name.value] : undefined;
default:
throw new TypeError(
throw new ValidationError(
`JSONStringify cannot represent value: ${JSON.stringify(ast)}`,
);
}
@ -54,7 +56,7 @@ const parseJSON = (value: string): object => {
try {
return JSON.parse(value);
} catch (e) {
throw new TypeError(`Value is not valid JSON: ${value}`);
throw new ValidationError(`Value is not valid JSON: ${value}`);
}
};

View File

@ -1,6 +1,8 @@
import { GraphQLScalarType } from 'graphql';
import { IntValueNode, Kind } from 'graphql/language';
import { ValidationError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
export const TimeScalarType = new GraphQLScalarType({
name: 'Time',
description: 'Time custom scalar type',
@ -17,8 +19,8 @@ export const TimeScalarType = new GraphQLScalarType({
if (typeof intAst.value === 'number') {
return new Date(intAst.value);
}
throw new Error(`Invalid timestamp value: ${ast.value}`);
throw new ValidationError(`Invalid timestamp value: ${ast.value}`);
}
throw new Error(`Invalid AST kind: ${ast.kind}`);
throw new ValidationError(`Invalid AST kind: ${ast.kind}`);
},
});

View File

@ -1,12 +1,14 @@
import { GraphQLScalarType, Kind } from 'graphql';
import { validate as uuidValidate } from 'uuid';
import { ValidationError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
const checkUUID = (value: any): string => {
if (typeof value !== 'string') {
throw new Error('UUID must be a string');
throw new ValidationError('UUID must be a string');
}
if (!uuidValidate(value)) {
throw new Error('Invalid UUID');
throw new ValidationError('Invalid UUID');
}
return value;
@ -19,7 +21,7 @@ export const UUIDScalarType = new GraphQLScalarType({
parseValue: checkUUID,
parseLiteral(ast): string {
if (ast.kind !== Kind.STRING) {
throw new Error('UUID must be a string');
throw new ValidationError('UUID must be a string');
}
return ast.value;