Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Edge.node field type must be Output Type but got: undefined

I'm trying to set up a node.js server with a Relay-compatible GraphQL schema.

When trying to validate or load the schema I get the following error:

EventEdge.node field type must be Output Type but got: undefined.

This is caused by having a connection type for for the Event type in one of the other type definitions.

I won't post the whole schema because it's quite verbose but when the connection field is commented out the schema is loaded correctly and no errors are thrown.

I've included an example of a simplified schema that causes the same issue:

  const graphql       = require('graphql')
  const relay         = require('graphql-relay')

  const GraphQLID         = graphql.GraphQLID,
        GraphQLInt        = graphql.GraphQLInt,
        GraphQLString     = graphql.GraphQLString,
        GraphQLList       = graphql.GraphQLList,
        GraphQLObjectType = graphql.GraphQLObjectType,
        GraphQLSchema     = graphql.GraphQLSchema,
        GraphQLNonNull    = graphql.GraphQLNonNull

  const connectionArgs               = relay.connectionArgs,
        connectionDefinitions        = relay.connectionDefinitions,
        connectionFromArray          = relay.connectionFromArray,
        cursorForObjectInConnection  = relay.cursorForObjectInConnection,
        fromGlobalId                 = relay.fromGlobalId,
        globalIdField                = relay.globalIdField,
        mutationWithClientMutationId = relay.mutationWithClientMutationId,
        nodeDefinitions              = relay.nodeDefinitions,
        toGlobalId                   = relay.toGlobalId

  // Models (ORM Mappings)
  const models = require('../models')

  // Model handlers
  const handlers = require('../models/handlers')


  /*
   *  Relay Node Definition:
   *  {nodeInterface, nodeField} = nodeDefinitions
   */

  var nodeDefinition = nodeDefinitions(
    (globalId) => {
      // {type, id} = fromGlobalId(globalId)
      const gid = fromGlobalId(globalId);

      switch (gid.type) {
      case 'User':
        return handlers.getUser(id)

      // case 'Event':
      //   return handlers.getEvent(id)
      //
      // case 'Club':
      //   return handlers.getClub(id)

      default:
        return null

      }
    },
    (obj) => {
      switch (true) {
        case (obj instanceof models.User):
          return UserType

        // case (obj instanceof models.Club):
        //   return ClubType
        //
        // case (obj instanceof models.Event):
        //   return EventType

        default:
          return null
      }
    }
  )

  /**************************
   **************************
   * Relay Connections
   *
   * { connectionType, edgeType } = connectionDefinitions({nodeType: LoremType})
   **************************
   **************************/

   // User Connection
   // const usersConnection = connectionDefinitions({name: 'User', nodeType: UserType})

   // Event Connection
   const eventsConnection = connectionDefinitions({name: 'Event', nodeType: EventType})

   // Club Connection
   // const clubsConnection = connectionDefinitions({name: 'Club', nodeType: ClubType})


   /**************************
    **************************
    * GraphQL Type Definitions
    **************************
    **************************/

    /*
    *   User Type
    *
    *   type User : Object {
    *     id: String!
    *     first_name: String
    *     last_name: String
    *     friends: [User]
    *   }
    */

   var UserType = new GraphQLObjectType({
     name: 'User',
     description: 'A user of the app.',
     fields: () => ({
       id: globalIdField('User'),
       events: {
         type: eventsConnection.connectionType,
         description: 'User\'s events.',
         args: connectionArgs,
         resolve: (user, args) => connectionFromArray(getEvents(), args)
       }
     }),
     interfaces: [nodeDefinition.nodeInterface]
   })


   /*
   **  Event Type
   *
   *   type Event : Object {
   *     id: String!
   *     title: String
   *     description: String
   *     datetime: Int
   *     location: [Int]
   *     managers: [User]
   *     club: Club
   *     members: [User]
   *   }
   */

  var EventType = new GraphQLObjectType({
    name: 'Event',
    description: 'An event in the app.',
    fields: () => ({
      id: globalIdField('Event'),
      name: {
        type: GraphQLString,
        description: 'Event\'s name.',
        resolve: event => event.get('name')
      }
    }),
    interfaces: [nodeDefinition.nodeInterface]
  })


  /****************************
   ****************************
   * Relay Mutation Definitions
   ****************************
   ****************************/


  /**************************
   **************************
   * Root Schema Definitions
   **************************
   **************************/

  /*
  **  Root Query
  *
  *   type Query {
  *     user(id: String!): User
  *     club(id: String!): Club
  *     event(id: String!): Event
  *   }
  */

  var QueryType = new GraphQLObjectType({
    name: 'Query',
    fields: () => ({
      node: nodeDefinition.nodeField,
      user: {
        type: UserType,
        resolve: () => handlers.getUser()
      }
    })
  })


  /*
  **  Root Schema
  *
  *   type Schema {
  *     query: Query
  *     mutation: Mutation
  *   }
  */

  var Schema = new GraphQLSchema({
    query: QueryType
  })


  module.exports = Schema
like image 406
BarakChamo Avatar asked Mar 14 '16 17:03

BarakChamo


1 Answers

You've made a reference to EventType before assigning to it. First define the type, then make use of it in the connection:

/**
 *   Event Type
 *
 *   type Event : Object {
 *     id: String!
 *     title: String
 *     description: String
 *     datetime: Int
 *     location: [Int]
 *     managers: [User]
 *     club: Club
 *     members: [User]
 *   }
 */

var EventType = new GraphQLObjectType({
  name: 'Event',
  description: 'An event in the app.',
  fields: () => ({
    id: globalIdField('Event'),
    name: {
      type: GraphQLString,
      description: 'Event\'s name.',
      resolve: event => event.get('name')
    },
  }),
  interfaces: [nodeDefinition.nodeInterface],
});

// Event Connection
const eventsConnection = connectionDefinitions({
  name: 'Event', 
  nodeType: EventType,
});
like image 54
steveluscher Avatar answered Nov 15 '22 07:11

steveluscher