Search code examples
graphqlsequelize.jsgraphql-jssequelize-cliexpress-graphql

How to implement interface using GraphQL and node


I want to achieve the fields of one object type within another object type

Here is my schema file.

const Films = new GraphQLInterfaceType({
  name: 'films',
  fields: () => ({
    id:{
        type: GraphQLID
      },
      name: {
        type: GraphQLString,
      },
    })
})

const MovieStream = new GraphQLObjectType({
    name: 'MovieStream',
    interfaces: () => [Films], 
    fields: () => ({
        id: {
            type: GraphQLID,    
          },    
          movie_id: {
              type: GraphQLString,   
            },    
    })
})

Here I am trying to use the interface. But It shows error:

{
  "errors": [
    {
      "message": "Query root type must be Object type, it cannot be { __validationErrors: undefined, __allowedLegacyNames: [], _queryType: undefined, _mutationType: undefined, _subscriptionType: undefined, _directives: [@include, @skip, @deprecated], astNode: undefined, extensionASTNodes: undefined, _typeMap: { __Schema: __Schema, __Type: __Type, __TypeKind: __TypeKind, String: String, Boolean: Boolean, __Field: __Field, __InputValue: __InputValue, __EnumValue: __EnumValue, __Directive: __Directive, __DirectiveLocation: __DirectiveLocation, films: films, ID: ID, Date: Date, JSON: JSON, MovieStream: MovieStream }, _possibleTypeMap: {}, _implementations: { films: [] } }."
    },
    {
      "message": "Expected GraphQL named type but got: { __validationErrors: undefined, __allowedLegacyNames: [], _queryType: undefined, _mutationType: undefined, _subscriptionType: undefined, _directives: [@include, @skip, @deprecated], astNode: undefined, extensionASTNodes: undefined, _typeMap: { __Schema: __Schema, __Type: __Type, __TypeKind: __TypeKind, String: String, Boolean: Boolean, __Field: __Field, __InputValue: __InputValue, __EnumValue: __EnumValue, __Directive: __Directive, __DirectiveLocation: __DirectiveLocation, films: films, ID: ID, Date: Date, JSON: JSON, MovieStream: MovieStream }, _possibleTypeMap: {}, _implementations: { films: [] } }."
    }
  ]
}

Here is Query type:

const QueryRoot = new GraphQLObjectType({

  name: 'Query',
  fields: () => ({
        getContentList:{
        type: new GraphQLList(contentCategory),
        args: {
          id: {
            type: GraphQLInt
          },
          permalink: {
              type: GraphQLString
          },
          language: {
              type: GraphQLString
          },
          content_types_id: {
              type: GraphQLString
          },
          oauth_token:{
              type: GraphQLString
          }

        },

        resolve: (parent, args, context, resolveInfo) => {
           var category_flag = 0;
           var menuItemInfo = '';
           user_id = args.user_id ? args.user_id : 0;
          // console.log("context"+context['oauth_token']);
           return AuthDb.models.oauth_registration.findAll({attributes: ['oauth_token', 'studio_id'],where:{
              //  oauth_token:context['oauth_token'],
               $or: [
                  {
                      oauth_token: 
                      {
                          $eq: context['oauth_token']
                      }
                  },

                  {
                      oauth_token: 
                      {
                          $eq: args.oauth_token
                      }
                  },
              ]

              },limit:1}).then(oauth_registration => { 
              var oauthRegistration = oauth_registration[0]
              // for(var i = 0;i<=oauth_registration.ength;i++){
                      if(oauth_registration && oauthRegistration && oauthRegistration.oauth_token == context['oauth_token'] || oauthRegistration.oauth_token == args.oauth_token){
                         studio_id = oauthRegistration.studio_id;
                         return joinMonster.default(resolveInfo,{}, sql => {
                            return contentCategoryDb.query(sql).then(function(result) { 

                                return result[0];
                            });   
                        } ,{dialect: 'mysql'});

                      }else{
                          throw new Error('Invalid OAuth Token');
                      }

                  })

        },

        where: (filmTable, args, context) => {
            return getLanguage_id(args.language).then(language_id=>{
                return ` ${filmTable}.permalink = "${args.permalink}" and ${filmTable}.studio_id = "${studio_id}" and (${filmTable}.language_id = "${language_id}"  OR  ${filmTable}.parent_id = 0 AND ${filmTable}.id NOT IN (SELECT ${filmTable}.parent_id FROM content_category WHERE ${filmTable}.permalink = "${args.permalink}" and ${filmTable}.language_id = "${language_id}" and ${filmTable}.studio_id = "${studio_id}"))`
            })

              },

    }

  })
})

module.exports = new GraphQLSchema({
    query: QueryRoot
})

Please help me out. have i done something wrong in the use of interface?

I have found the answer through this post Is it possible to fetch data from multiple tables using GraphQLList

Anyone please tell me the exact way to use the interface in my code.


Solution

  • Although the error you have printed does not really relate to interfaces implementations, in order for you to use interfaces, you have to implement the methods/types the interface references. So in your situation your object MovieStream is missing the type name that you refer in the object Films.

    Your code should look something like:

    const Films = new GraphQLInterfaceType({
        name: 'films',
        fields: () => ({
            id:{
                type: GraphQLID
            },
            name: {
                type: GraphQLString,
    
            },
        })
    })
    
    const MovieStream = new GraphQLObjectType({
        name: 'MovieStream',
        interfaces: () => [Films],
        fields: () => ({
            id: {
                type: GraphQLID,
            },
            name: {
                type: GraphQLString // You're missing this!
            },
            movie_id: {
                type: GraphQLString,
            },
        })
    })
    

    Now back to the error you have printed "message": "Query root type must be Object type, it cannot be...

    This seems to be related to your QueryRoot object, it seems that GraphQLSchema is not recognizing the root object. If this issue is still there once you fix the interface, have a look at this answer here