graphql-tools: Something wrong with directives

I tried all kinds of things but could not solve this problem

error

Related Codes;

LengthDirective.js

const {
  GraphQLNonNull,
  GraphQLString,
  isNonNullType,
  isScalarType
} = require("graphql")
const { SchemaDirectiveVisitor } = require("graphql-tools")
const LimitedLengthType = require("../scalars/LimitedLengthType");
const InvalidScalarTypeError = require("../scalars/InvalidScalarTypeError")

class LengthDirective extends SchemaDirectiveVisitor{

  visitInputFieldDefinition(field, _details) {
    this.wrapType(field)
  }

  visitFieldDefinition(field, _details) {
    this.wrapType(field)
  }

  visitArgumentDefinition(argument, details) {
    this.wrapType(argument)
  }

  wrapType(field){
    if(isNonNullType(field.type) && field.type.ofType === GraphQLString){
      field.type = new GraphQLNonNull(
        new LimitedLengthType(field.astNode.name.value, field.type.ofType, {
          max: this.args.max,
          min: this.args.min
        })
      )
    }else if(isScalarType(field.type) && field.type === GraphQLString){
      field.type = new LimitedLengthType(field.astNode.name.value, field.type, {
        max: this.args.max,
        min: this.args.min
      })
    }else{
      throw new InvalidScalarTypeError(`Not a scalar type: ${field.type}`, field)
    }
  }

}

module.exports = LengthDirective

LimitedLengthType.js

const ScalarType = require("./ScalarType")
const GraphQLValidationError = require("./GraphQLValidationError");

class LimitedLengthType extends ScalarType{

  constructor(name, type, args){
    super({
      name: `LimitedLength`,
      serialize: value => {
        value = type.serialize(value)

        this.validate(name, args, value)

        return value
      },
      parseValue: value => {
        value = type.parseValue(value)

        this.validate(name, args, value)

        return value
      },
      parseLiteral: ast => {
        ast = type.parseLiteral(ast)

        this.validate(name, args, ast)

        return ast
      }
    })
  }

  validate(name, args, value){
    if(args.max && value.length > args.max){
      throw new GraphQLValidationError(name, `Must be no more than ${args.max} characters in length`, [{
        arg: "max",
        value: args.min
      }])
    }

    if(args.min && value.length < args.min){
      throw new GraphQLValidationError(name, `Must be at least ${args.min} characters in length`, [{
        arg: "min",
        value: args.min
      }])
    }
  }
}

module.exports = LimitedLengthType

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 16 (5 by maintainers)

Most upvoted comments

Your directive changes the type in the schema, so you need to use the correct type of the variable, which is now LimitedLength

You cannot hide the fact that you changed the type from the client, as the directive modifies the schema and so the type is changed on the server, client, everywhere.

Let’s keep it in English because there is a community out there might take a look at this issue and understand the solution đŸ˜ƒ Thank you for the reproduction!

@anilmisirlioglu it’s possible use directives for validation without leaking implementation details to the client, this project did it: https://github.com/profusion/apollo-validation-directives

Works for me, client still has proper types. You can use it straight away or check their code to create own validators.

Duplicate of #789

Not really possible to change types using directives and use variables…

There’s some other ideas there about validation, not sure what the status of variables with those solutions…

of course

the query we tested;

mutation($user_id: ID!, $description: String, $project_id: ID){
  startTimeTracker(data: { user_id: $user_id, project_id: $project_id, description: $description }){
    tracker{
      id,
      user_id,
      team_id,
      project_id,
      startAt,
      finishAt,
      description
    }
    errorCode
  }
}