Search code examples
javascriptexpressgraphqlgraphql-jsgraphene-python

Why is my Graphql query returning null?


I am trying to set up a graphql app to all me to easily access data from games.espn.com and I am having an issue of my queries returning null. I'm wondering if I may have missed a return or resolve function somewhere? I have been scouring this code for a few days and can't seem to figure out why this is not returning a value.

Here is my schema.js file:

const {
  GraphQLObjectType,
  GraphQLString,
  GraphQLInt,
  GraphQLSchema,
  GraphQLList,
  GraphQLNonNull,
  GraphQLBoolean,
  GraphQLFloat
} = require('graphql');
const axios = require('axios');
const request = require('request');

const PlayerType = new GraphQLObjectType({
  name: 'Player',
  fields:() => ({
    droppable: {type:GraphQLBoolean},
    percentStarted: {type:GraphQLFloat},
    jersey: {type:GraphQLString},
    playerRatingSeason: {type:GraphQLFloat},
    isIREligible: {type:GraphQLBoolean},
    draftRank: {type:GraphQLInt},
    universeId: {type:GraphQLInt},
    firstName: {type:GraphQLString},
    lastName: {type:GraphQLString},
    sportsId: {type:GraphQLInt},
    healthStatus: {type:GraphQLInt},
    percentOwned: {type:GraphQLFloat},
    proTeamId: {type:GraphQLInt},
    tickerId: {type:GraphQLInt},
    isActive: {type:GraphQLBoolean},
    playerId: {type:GraphQLInt},
    percentChange: {type:GraphQLFloat},
    defaultPositionId: {type: GraphQLInt},
    totalPoints: {type:GraphQLFloat},
  })
});


const CurrentPeriodProjectedStatsType = new GraphQLObjectType({
  name: 'CurrentPeriodProjectedStats',
  fields:() => ({
   appliedProjectedStatTotal: {type:GraphQLFloat}
  })
});


const CurrentPeriodRealStatsType = new GraphQLObjectType({
  name: 'CurrentPeriodRealStats',
  fields:() => ({
    appliedRealStatTotal: {type:GraphQLFloat}
  })
});



const PlayerSlotType = new GraphQLObjectType({
  name: 'PlayerSlot',
  fields:() => ({
    pvoRank: {type:GraphQLInt},
    player: {
      type: PlayerType
    },
    watchList: {type:GraphQLBoolean},
    isKeeper: {type:GraphQLBoolean},
    isTradeLocked: {type:GraphQLBoolean},
    currentPeriodProjectedStats: {
      type: CurrentPeriodProjectedStatsType
    },
    opponentProTeamId: {type:GraphQLInt},
    slotCategoryId: {type:GraphQLInt},
    lockStatus: {type:GraphQLInt},
    isQueuedWaiverLocked: {type:GraphQLBoolean},
    currentPeriodRealStats: {
      type: CurrentPeriodRealStatsType
    }
  })
});


const SlotsType = new GraphQLObjectType({
  name: 'Slots',
  fields:() => ({
    player0: {
      type: PlayerSlotType
    },
    player1: {
      type: PlayerSlotType
    },
    player2: {
      type: PlayerSlotType
    },
    player3: {
      type: PlayerSlotType
    },
    player4: {
      type: PlayerSlotType
    },
    player5: {
      type: PlayerSlotType
    },
    player6: {
      type: PlayerSlotType
    },
    player7: {
      type: PlayerSlotType
    },
    player8: {
      type: PlayerSlotType
    },
    player9: {
      type: PlayerSlotType
    },
    player10: {
      type: PlayerSlotType
    },
    player11: {
      type: PlayerSlotType
    },
    player12: {
      type: PlayerSlotType
    },
    player13: {
      type: PlayerSlotType
    },
    player14: {
      type: PlayerSlotType
    },
    player15: {
      type: PlayerSlotType
    },
  })
});


const DivisionType = new GraphQLObjectType({
  name: 'Division',
  fields:() => ({
    divisionName: {type:GraphQLString},
    divisionId: {type:GraphQLInt},
    size: {type:GraphQLInt}
  })
});


const TeamType = new GraphQLObjectType({
    name: 'Team',
    fields:() => ({
      divisionStanding: {type:GraphQLInt},
      overallStanding: {type:GraphQLInt},
      waiverRank: {type:GraphQLInt},
      division: {
        type: DivisionType
      },
      teamAbbrev: {type:GraphQLString},
      teamNickname: {type:GraphQLString},
      logoUrl: {type:GraphQLString},
      teamLocation: {type:GraphQLString},
      teamId: {type:GraphQLInt},
      logoType: {type:GraphQLString}
    })
});



const List0Type = new GraphQLObjectType({
  name: 'List0',
  fields: () => ({
    slots: {
      type: SlotsType
    },
    team: {
      type: TeamType
    },
    teamId: {type: GraphQLInt},
    appliedActiveProjectedTotal: {type: GraphQLFloat},
    appliedInactiveProjectedTotal: {type: GraphQLFloat},
    appliedActiveRealTotal: {type: GraphQLFloat},
    appliedInactiveRealTotal: {type: GraphQLFloat},
  })
});


const TeamsType = new GraphQLObjectType({
  name: 'Teams',
  fields: () => ({
    list0: {
      type: List0Type
    },
    list1: {
      type: List0Type
    }
  })
});


// need to define each type individually, working from the bottom up and creating types as needed
const BoxscoreType = new GraphQLObjectType({
  name: 'Boxscore',
  fields: () => ({
    teams: {
      type: TeamsType,
      /*resolve(boxscore){
        return boxscore.teams;
      }*/
    },
    scoringPeriodId: {
      type: GraphQLInt,
    },
    matchupPeriodId: {
      type: GraphQLInt,
    },
    homeTeamBonus: {
      type: GraphQLInt,
    }

  })
});

const MetadataType = new GraphQLObjectType({
  name: 'metadata',
  fields: {
    leagueId: {type: GraphQLString},
    status: {type: GraphQLString},
    dateModifiedLeague: {type: GraphQLString},
    seasonId: {type: GraphQLString},
  }
});

const BoxscoreDataType = new GraphQLObjectType({
  name: 'BoxscoreData',
  fields: {
    boxscore: {type:BoxscoreType},
    metadata: {type:MetadataType},
  },
});

const EspnQuery = new GraphQLObjectType({
    name: 'EspnQuery',
    fields: {
      getBoxscore: {
        type: BoxscoreDataType,
        args: {
          leagueId: {
            name: 'leagueId',
            type: new GraphQLNonNull(GraphQLInt)
          },
          seasonId: {
            name: 'seasonId',
            type: new GraphQLNonNull(GraphQLInt)
          },
          teamId: {
            name: 'teamId',
            type: new GraphQLNonNull(GraphQLInt)
          },
          scoringPeriodId: {
            name: 'scoringPeriodId',
            type: new GraphQLNonNull(GraphQLInt)
          },
        },
        resolve: (obj, {leagueId, seasonId, teamId, scoringPeriodId}) => {
            const url = 'http://games.espn.com/ffl/api/v2/boxscore?leagueId=1150587&seasonId=2017&teamId=5&scoringPeriodId=7'
            //const url = 'http://games.espn.com/ffl/api/v2/boxscore?leagueId='+ leagueId + '&seasonId=' + seasonId + '&teamId=' + teamId + '&scoringPeriodId=' + scoringPeriodId
            //console.log('leagueId is: ' + leagueId + 'seasonId is: '+seasonId+'teamId is: '+teamId+'scoringPeriodId is: '+scoringPeriodId);

            return axios(url)
              .then(res => res.data);


        }
      }
    },
  });

// Keep at the bottom //
module.exports = new GraphQLSchema({
  query: EspnQuery
});

And the query I'm running in Graphiql is:

{
    getBoxscore(leagueId: 1150587, seasonId: 2017, teamId: 5, scoringPeriodId: 7) {
        boxscore{
        teams {
            list0{
          slots{
            player0{
              player{
                firstName
              }
            }
          }
        }
       }
      }
    }
}

Which unfortunately is returning:

{
  "data": {
    "getBoxscore": {
      "boxscore": {
        "teams": {
          "list0": null
        }
      }
    }
  }
}

Solution

  • The structure of your schema doesn't match the structure of the data. Where ever there is an array being returned, you should utilize a GraphQLList -- there's no need for the ListType you've added.

    For example, if you look at the JSON being returned by the endpoint, teams is an array, not an object. You've created a TeamType that matches the structure of the team data, but we need to tell GraphQL that teams is going to be a List (array) of TeamType objects, not just a single one. So we write:

    teams: { type: new GraphQLList(TeamsType) }
    

    Written in GraphQL schema language, that would be [TeamsType]. Most of the fields in TeamsType are objects, or scalars. However, slots is also an array, so for that you would similarly write:

    slots: { type: new GraphQLList(SlotsType) }
    

    And so on.