1
votes

Using Apollo Playground to test a mutation that uses an input Type object that contains a custom scalar. The field is lastWatched that is custom scalar type of Date. Maybe there is a problem in the resolver for Date or I just can't figure out the correct syntax to use in Playground.

My custom scalar is called Date. Here is my resolver code for Date.

NOTE: Resolver code has been corrected as the problem was in the function: parseLiteral(ast).

    Date: new GraphQLScalarType({
    name: 'Date',
    description: 'Date custom scalar type',
    parseValue(value) {
      console.log('Date scalar parse:', value);
      return dayjs(value); // value from the client
    },
    serialize(value) {
      console.log('Date scalar serialize:', value);
      return dayjs(value).format('YYYY-MM-DD HH:mm:ss'); // value sent to the client
    },
    parseLiteral(ast) {
      console.log('Date scalar parseLit:', ast);
      if (ast.kind === Kind.STRING) {
        return dayjs(ast.value).format('YYYY-MM-DD HH:mm:ss') || null; // ast value is always in string format
      }
      return null;
    }
  })

My schema for the create mutation mutation.

    extend type Mutation {
    createPlaybackPosition(fields: CreatePlaybackPositionInput): PlaybackPositionResponse
    updatePlaybackPosition(filename: ID!): PlaybackPositionResponse
    deletePlaybackPosition(filename: ID!): PlaybackPositionResponse
  }

  input CreatePlaybackPositionInput {
    "pseudo primary key"
    filename: ID!
    "in seconds"
    position: Int!
    "in seconds"
    duration: Int!
    "date and time (local)"
    lastWatched: Date!
  }

In play Play Ground, the mutation looks like:

 mutation {
  createPlaybackPosition(
    fields: {
      filename: "Test Show.S01E01.Piolet"
      position: 0
      duration: 0
      lastWatched: "06/27/2019 14:22:00"
    }
  ) {
    success
    code
    message
    validationErrors
  }
}

When I click the play button I get an error

  {
  "error": {
    "errors": [
      {
        "message": "Expected type Date!, found \"06/27/2019 14:22:00\"; value is not defined",
        "locations": [
          {
            "line": 2,
            "column": 111
          }
        ],
        "extensions": {
          "code": "GRAPHQL_VALIDATION_FAILED",
          "exception": {
            "stacktrace": [
              "ReferenceError: value is not defined",
              "    at GraphQLScalarType.parseLiteral (d:\\Users\\johni\\Projects\\graphql-knex-npvr\\src\\resolvers\\common.js:42:44)",
              "    at isValidScalar (d:\\Users\\johni\\Projects\\graphql-knex-npvr\\node_modules\\graphql\\validation\\rules\\ValuesOfCorrectType.js:175:28)",
              "    at Object.StringValue (d:\\Users\\johni\\Projects\\graphql-knex-npvr\\node_modules\\graphql\\validation\\rules\\ValuesOfCorrectType.js:144:14)",
              "    at Object.enter (d:\\Users\\johni\\Projects\\graphql-knex-npvr\\node_modules\\graphql\\language\\visitor.js:332:29)",
              "    at Object.enter (d:\\Users\\johni\\Projects\\graphql-knex-npvr\\node_modules\\graphql\\language\\visitor.js:383:25)",
              "    at visit (d:\\Users\\johni\\Projects\\graphql-knex-npvr\\node_modules\\graphql\\language\\visitor.js:250:26)",
              "    at Object.validate (d:\\Users\\johni\\Projects\\graphql-knex-npvr\\node_modules\\graphql\\validation\\validate.js:63:22)",
              "    at validate (d:\\Users\\johni\\Projects\\graphql-knex-npvr\\node_modules\\apollo-server-core\\dist\\requestPipeline.js:202:32)",
              "    at Object.<anonymous> (d:\\Users\\johni\\Projects\\graphql-knex-npvr\\node_modules\\apollo-server-core\\dist\\requestPipeline.js:123:42)",
              "    at Generator.next (<anonymous>)",
              "    at fulfilled (d:\\Users\\johni\\Projects\\graphql-knex-npvr\\node_modules\\apollo-server-core\\dist\\requestPipeline.js:4:58)",
              "    at processTicksAndRejections (internal/process/task_queues.js:89:5)"
            ]
          }
        }
      }
    ]
  }
}
1

1 Answers

0
votes

If either of the three scalar methods (serialize, parseLiteral and parseValue) returns undefined, GraphQL will throw the above error. Returning undefined is basically a way of telling GraphQL that the value received is invalid and a validation error should be thrown. You won't see the same behavior with null since this is a valid value in GraphQL, but you will also see the above error if you return NaN.

In this particular case, you're passing ast.value to dayjs, but this is not the value of the string literal you are providing -- it is a ValueNode object like this:

{
  kind: 'StringValue',
  value: '06/27/2019 14:22:00',
  block: false,
  loc: { start: 14, end: 16 }
}

So you should instead do something like:

parseLiteral(ast) {
  if (ast.kind === Kind.STRING) {
    return dayjs(ast.value.value)
  }
  return null
}

If you want to always return null if the value is invalid and never throw the validation error:

return dayjs(ast.value.value) || null