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:
@ -1,25 +1,27 @@
|
|||||||
import { GraphQLScalarType, Kind } from 'graphql';
|
import { GraphQLScalarType, Kind } from 'graphql';
|
||||||
|
|
||||||
|
import { ValidationError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||||
|
|
||||||
export const CursorScalarType = new GraphQLScalarType({
|
export const CursorScalarType = new GraphQLScalarType({
|
||||||
name: 'Cursor',
|
name: 'Cursor',
|
||||||
description: 'A custom scalar that represents a cursor for pagination',
|
description: 'A custom scalar that represents a cursor for pagination',
|
||||||
serialize(value) {
|
serialize(value) {
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
throw new Error('Cursor must be a string');
|
throw new ValidationError('Cursor must be a string');
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
parseValue(value) {
|
parseValue(value) {
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
throw new Error('Cursor must be a string');
|
throw new ValidationError('Cursor must be a string');
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
parseLiteral(ast) {
|
parseLiteral(ast) {
|
||||||
if (ast.kind !== Kind.STRING) {
|
if (ast.kind !== Kind.STRING) {
|
||||||
throw new Error('Cursor must be a string');
|
throw new ValidationError('Cursor must be a string');
|
||||||
}
|
}
|
||||||
|
|
||||||
return ast.value;
|
return ast.value;
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { GraphQLScalarType, Kind } from 'graphql';
|
import { GraphQLScalarType, Kind } from 'graphql';
|
||||||
|
|
||||||
|
import { ValidationError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||||
|
|
||||||
type PositionType = 'first' | 'last' | number;
|
type PositionType = 'first' | 'last' | number;
|
||||||
|
|
||||||
const isValidStringPosition = (value: string): boolean =>
|
const isValidStringPosition = (value: string): boolean =>
|
||||||
@ -13,7 +15,9 @@ const checkPosition = (value: any): PositionType => {
|
|||||||
return value;
|
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({
|
export const PositionScalarType = new GraphQLScalarType({
|
||||||
@ -34,6 +38,6 @@ export const PositionScalarType = new GraphQLScalarType({
|
|||||||
return parseFloat(ast.value);
|
return parseFloat(ast.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('Invalid position found');
|
throw new ValidationError('Invalid position value');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import { Maybe } from 'graphql-yoga';
|
|||||||
import { ObjMap } from 'graphql/jsutils/ObjMap';
|
import { ObjMap } from 'graphql/jsutils/ObjMap';
|
||||||
import { ASTNode, Kind, ValueNode } from 'graphql/language';
|
import { ASTNode, Kind, ValueNode } from 'graphql/language';
|
||||||
|
|
||||||
|
import { ValidationError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||||
|
|
||||||
const parseLiteral = (
|
const parseLiteral = (
|
||||||
ast: ValueNode,
|
ast: ValueNode,
|
||||||
variables?: Maybe<ObjMap<unknown>>,
|
variables?: Maybe<ObjMap<unknown>>,
|
||||||
@ -25,7 +27,7 @@ const parseLiteral = (
|
|||||||
case Kind.VARIABLE:
|
case Kind.VARIABLE:
|
||||||
return variables ? variables[ast.name.value] : undefined;
|
return variables ? variables[ast.name.value] : undefined;
|
||||||
default:
|
default:
|
||||||
throw new TypeError(
|
throw new ValidationError(
|
||||||
`JSONStringify cannot represent value: ${JSON.stringify(ast)}`,
|
`JSONStringify cannot represent value: ${JSON.stringify(ast)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -54,7 +56,7 @@ const parseJSON = (value: string): object => {
|
|||||||
try {
|
try {
|
||||||
return JSON.parse(value);
|
return JSON.parse(value);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new TypeError(`Value is not valid JSON: ${value}`);
|
throw new ValidationError(`Value is not valid JSON: ${value}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { GraphQLScalarType } from 'graphql';
|
import { GraphQLScalarType } from 'graphql';
|
||||||
import { IntValueNode, Kind } from 'graphql/language';
|
import { IntValueNode, Kind } from 'graphql/language';
|
||||||
|
|
||||||
|
import { ValidationError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||||
|
|
||||||
export const TimeScalarType = new GraphQLScalarType({
|
export const TimeScalarType = new GraphQLScalarType({
|
||||||
name: 'Time',
|
name: 'Time',
|
||||||
description: 'Time custom scalar type',
|
description: 'Time custom scalar type',
|
||||||
@ -17,8 +19,8 @@ export const TimeScalarType = new GraphQLScalarType({
|
|||||||
if (typeof intAst.value === 'number') {
|
if (typeof intAst.value === 'number') {
|
||||||
return new Date(intAst.value);
|
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}`);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
import { GraphQLScalarType, Kind } from 'graphql';
|
import { GraphQLScalarType, Kind } from 'graphql';
|
||||||
import { validate as uuidValidate } from 'uuid';
|
import { validate as uuidValidate } from 'uuid';
|
||||||
|
|
||||||
|
import { ValidationError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||||
|
|
||||||
const checkUUID = (value: any): string => {
|
const checkUUID = (value: any): string => {
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
throw new Error('UUID must be a string');
|
throw new ValidationError('UUID must be a string');
|
||||||
}
|
}
|
||||||
if (!uuidValidate(value)) {
|
if (!uuidValidate(value)) {
|
||||||
throw new Error('Invalid UUID');
|
throw new ValidationError('Invalid UUID');
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@ -19,7 +21,7 @@ export const UUIDScalarType = new GraphQLScalarType({
|
|||||||
parseValue: checkUUID,
|
parseValue: checkUUID,
|
||||||
parseLiteral(ast): string {
|
parseLiteral(ast): string {
|
||||||
if (ast.kind !== Kind.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;
|
return ast.value;
|
||||||
|
|||||||
Reference in New Issue
Block a user