Open
Description
Custom directive for input is not working in Apollo version 3
Description
I'm following a tutorial at graphql-tools for Enforcing value restrictions to build a directive to validate length of string input.
input AddCycleWorkInput {
name: String! @length(max: 10)
}
Expected
If the length's name input exceeds the specified, i hope throwing any ValidateError or Error
My Environment:
- OS: Windowns 10
@graphql-tools/utils: 8.1.1
apollo-server-core: ^3.3.0
typescript: ^4.4.3
@graphql-tools/utils: 8.1.1
,
Schema build
private static buildSchema(accountsGraphQL: any): GraphQLSchema {
// List directives.
const { lengthDirectiveTypeDefs, lengthDirectiveTransformer } = lengthDirective('length');
// Build schema.
let schema = makeExecutableSchema({
typeDefs: mergeTypeDefs([
lengthDirectiveTypeDefs, // This is problem
accountsGraphQL.typeDefs,
typeDefs
]),
resolvers: mergeResolvers([accountsGraphQL.resolvers, resolvers]),
schemaDirectives: {
...accountsGraphQL.schemaDirectives,
},
});
// needed to validate input fields!
schema = lengthDirectiveTransformer(schema);
return schema;
}
Constructor of Apollo Server
const server = new ApolloServer({
schema: this.buildSchema(accountsGraphQL), // Schema build
context: accountsGraphQL.context,
uploads: false,
formatError: (error) => {
if (error) {
return {
message: error.message,
status: codeToStatus[error.extensions.code.toUpperCase()] || 400,
path: error.path
};
}
}
});
Length directive, to short you can watch this link
export default function lengthDirective(directiveName: string) {
class LimitedLengthType extends GraphQLScalarType {
constructor(type: GraphQLScalarType, maxLength: number) {
super({
name: `${type.name}WithLengthAtMost${maxLength.toString()}`,
serialize(value: string) {
console.log("value1", value);
const newValue: string = type.serialize(value)
if (newValue.length > maxLength) {
throw new Error(`expected ${newValue.length.toString(10)} to be at most ${maxLength.toString(10)}`)
}
return newValue
},
parseValue(value: string) {
console.log("value2", value);
return type.parseValue(value)
},
parseLiteral(ast) {
return type.parseLiteral(ast, {})
}
})
}
}
const limitedLengthTypes: Record<string, Record<number, GraphQLScalarType>> = {}
function getLimitedLengthType(type: GraphQLScalarType, maxLength: number): GraphQLScalarType {
const limitedLengthTypesByTypeName = limitedLengthTypes[type.name]
if (!limitedLengthTypesByTypeName) {
const newType = new LimitedLengthType(type, maxLength)
limitedLengthTypes[type.name] = {}
limitedLengthTypes[type.name][maxLength] = newType
return newType
}
const limitedLengthType = limitedLengthTypesByTypeName[maxLength]
if (!limitedLengthType) {
const newType = new LimitedLengthType(type, maxLength)
limitedLengthTypesByTypeName[maxLength] = newType
return newType
}
return limitedLengthType
}
function wrapType<F extends GraphQLFieldConfig<any, any> | GraphQLInputFieldConfig>(
fieldConfig: F,
directiveArgumentMap: Record<string, any>
): void {
if (isNonNullType(fieldConfig.type) && isScalarType(fieldConfig.type.ofType)) {
fieldConfig.type = getLimitedLengthType(fieldConfig.type.ofType, directiveArgumentMap['max'])
} else if (isScalarType(fieldConfig.type)) {
fieldConfig.type = getLimitedLengthType(fieldConfig.type, directiveArgumentMap['max'])
} else {
throw new Error(`Not a scalar type: ${fieldConfig.type.toString()}`)
}
}
return {
lengthDirectiveTypeDefs: `directive @${directiveName}(max: Int) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION`,
lengthDirectiveTransformer: (schema: GraphQLSchema) =>
mapSchema(schema, {
[MapperKind.FIELD]: fieldConfig => {
const lengthDirective = getDirective(schema, fieldConfig, directiveName)?.[0]
if (lengthDirective) {
wrapType(fieldConfig, lengthDirective)
return fieldConfig
}
},
})
}
}
I know this is a bug of version 3 ApolloServer, but can other way to fix it. Please help me. Thanks a lot.
Metadata
Metadata
Assignees
Labels
No labels