0
votes

Here are my typescript objects (simplified):

@ObjectType()
export default class Game {
  @Field(() => ID)
  id?: string

  @arrayProp({items: Player})
  @Field(() => [Player])
  players: Player[] = []
}

@ObjectType()
export class Player {
  @Field(() => ID)
  id?: string
}

It generates this schema using type-graphql:

type Game {
  id: ID!
  players: [Player!]!
}
type Player {
  id: ID!
}

I use a resolver to query the user's games:

@Resolver(() => User)
export class UserGameResolver {
  @FieldResolver(() => [Game])
  async ongoingGames(@Ctx('userId') userId: string) {
    return GameModel.find({'players.userId': userId, setup: null})
  }
}

And it produces this error: "GraphQL error: Cannot return null for non-nullable field Player.id"

What I already know:

  • Game and Player "id" field is a "virtual" field created by Mongoose as an alias for "_id" which is the real property (I don't want to manipulate _id on the frontend, I want to serialize the alias).
  • If I don't query the games' players, it works. So Game.id is properly serialize by my apollo server resolver. So for this object, the virtual property is accessed and serialized properly.
  • The player id exists and the virtual property works on mongoose side: if I do console.log(mongooseResult[0].players[0].id), I can see my player id in the console.
  • Apollo server is suppose to use this default field resolver for player.id: https://github.com/graphql/graphql-js/blob/master/src/execution/execute.js#L1181-L1199 (documentation: https://www.apollographql.com/docs/apollo-server/data/resolvers/#default-resolvers). Based on the source code the virtual property should be serialized, as it is accessed this way: 'player['id']'.

If someone has an clue about what is happening here, it would be great!

1

1 Answers

1
votes

you should try to use _id

if you really want to use id (the virtual), then you need to either use .toJson or .toObject with the options { virtuals: true }

return GameModel.find({'players.userId': userId, setup: null}).toObject({ virtuals: true });