#graphql #arguments #apollo-server #mutation
#graphql #аргументы #apollo-сервер #мутация
Вопрос:
Я реализую пользовательские директивы Graphql для проверки ввода данных клиентом. Пример кода, приведенный ниже, я ссылался на официальные примеры здесь: https://www.apollographql.com/docs/apollo-server/schema/creating-directives/#enforcing-value-restrictions
const { ApolloServer, gql, SchemaDirectiveVisitor } = require('apollo-server');
const { GraphQLScalarType, GraphQLNonNull } = require('graphql');
const typeDefs = gql`
directive @validateInput on FIELD_DEFINITION | INPUT_FIELD_DEFINITION | ARGUMENT_DEFINITION
type Mutation {
sampleMutation(
test1: String @validateInput
nestedInput: SampleMutationInput
): String
}
input SampleMutationInput {
test2: String @validateInput
}
`;
Реализация логики директивы:
class ValidateInputDirective extends SchemaDirectiveVisitor {
visitInputFieldDefinition(field) {
this.wrapType(field);
}
visitFieldDefinition(field) {
this.wrapType(field);
}
visitArgumentDefinition(argument) {
console.log('visitArgumentDefinition', argument);
this.wrapType(argument);
}
wrapType(field) {
console.log('wrapType', field);
if (
field.type instanceof GraphQLNonNull amp;amp;
field.type.ofType instanceof GraphQLScalarType
) {
field.type = new GraphQLNonNull(
new ValidateInputType(field.type.ofType)
);
} else if (field.type instanceof GraphQLScalarType) {
field.type = new ValidateInputType(field.type);
} else {
throw new Error(`Not a scalar type: ${field.type}`);
}
}
}
class ValidateInputType extends GraphQLScalarType {
constructor(type) {
super({
name: 'ValidatedInput',
serialize(value) {
return value;
},
parseValue(value) {
const result = type.parseValue(value);
if (/[?!]/.test(result)) {
throw new Error('Invalid characters');
}
return resu<
},
parseLiteral(ast) {
const result = type.parseLiteral(ast);
if (/[?!]/.test(result)) {
throw new Error('Invalid characters');
}
return resu<
},
});
}
}
export default { validateInput: ValidateInputDirective };
Это работает, как и ожидалось, для поля ввода ‘test2’, но для аргумента ‘test1’ это работает, когда строковое значение напрямую передается мутации, затем вызывается метод «parseLiteral» и к входному значению применяется логика проверки. Однако, когда я передаю значение ‘test1’ в качестве внешних переменных (через формат JSON), директива не работает, и метод «parserValue» никогда не вызывается.
Что я нашел до сих пор:
- «parserValue» используется, когда входные данные поступают из переменной JSON. «parseLiteral» используется, когда входные данные поступают непосредственно из запроса / мутации.
- Похоже, ошибка в инструментах Graphql в соответствии с https://github.com/ardatan/graphql-tools/issues/789
Я хочу понять:
- в чем реальная разница между аргументом, передаваемым переменной, и прямым переходом к мутации?
- есть ли альтернативный способ применить директивы к аргументу, чтобы избежать этой проблемы?
- Если это действительно ошибка с Graphql, исправлена ли она сейчас? Какую версию я должен использовать для решения проблемы?