Search code examples
javascriptgeojsongraphqlgraphql-js

GraphQL.js mutation with custom scalar type


I have a GeoJSON-based API in GraphQL that I am trying to do mutations on. I am using some of the types in graphql-geojson. The definition of the input types and the mutation is as below:

# ... from graphql-geojson ...
var CoordinatesScalar = new ScalarType({
 name: 'GeoJSONCoordinates',
 description: 'A (multidimensional) set of coordinates following x, y, z order.',
 serialize: coerceCoordinates,
 parseValue: coerceCoordinates,
 parseLiteral: parseCoordinates})


# ... schema.js ...
var waypointInputType = new GraphQLInputObjectType({
  name: 'WaypointInput',
  fields: {... schema.js ...]
var waypointInputType = new GraphQLInputObjectType({
  name: 'WaypointInput',
  fields: {
    type: {type: GraphQLString},
    coordinates: {type: CoordinatesScalar}
  }
});
var missionInputType = new GraphQLInputObjectType({
  name: 'MissionInput',
  fields: () => ({
    waypoints: {type: waypointInputType},
    max_groundspeed: {type: GraphQLFloat}
  })
});

var createMission = {
  type: missionType,
  description: 'Create a new mission.',
  args: {
    mission: {type: missionInputType}
  },
  resolve(value, {mission}) {
    return models.Mission.create(mission).then(mission => mission);
  }
};

# ... in schema definition ...
mutation: new GraphQLObjectType({
name: 'RootMutationType',
fields: {
  createMission
}
})

In graphiql, I'm issuing a mutation like

mutation {
  createMission(mission: {
    waypoints: {
      type: "LineString",
      coordinates: [[1, 2], [3, 4]]
    }
  }) {
    id
  }
}

to save some new coordinates and query for the created mission id. However, graphql throws an error that Argument mission has invalid value [...] coordinates: expected type GeoJSONCoordinates, found [[1, 2], [3, 4]]. I can put arbitrary strings in coordinates, but nested arrays do not seem to work. With a nested array in quotes, I get a string back when I query:

{
 "waypoints": {
          "type": "LineString",
          "bbox": null,
          "coordinates": "[[1, 2], [3, 3]]"
      }
}

Can I use CoordinatesScalar as an input type, or do I need to define an input type that CoordinatesScalar can parse specially for the input?


Solution

  • If you use the full syntax for issuing a mutation, you can specify the types of your inputs:

    mutation CreateMission(mission: MissonInput) {
      createMission(mission: $mission) {
        id
      }
    }
    

    Then you can provide variables:

    {
      mission: {
        waypoints: {
          type: "LineString",
          coordinates: [[1, 2], [3, 4]]
        }
      }
    }
    

    I'm not sure if this will solve it, let me know! :)