GraphQL Generated Schema Ergonomics

This topic describes possible improvements to the schema generated by the Dgraph GraphQL endpoint. The changes are focused on the ergonomics of type safe GraphQL clients (ie. TypeScript GraphQL Codegen) and minimising redundant null checking and field passing.

I’ll add to it over time, hopefully we can have some productive discussion on whether or not these changes make sense.

1 Like

Filter Queries should return [Type]! instead of [Type]

Currently, generated filter queries have a return type of [Type], meaning the client can expect either null or an array of Type records. By returning [Type]! clients can expect an array, and avoid a null check.

Before:

graph.queryType().then(res => {
  if (res.queryType) {
    res.queryType.forEach(type => {...});
  }
})

After:

graph.queryType().then(res => {
  res.queryType.forEach(type => {...});
})
1 Like

Filter Queries should return [Type!] instead of [Type]

Currently, generated filter queries have a return type of [Type], meaning the client can expect an array of either Type or null elements. By returning [Type!] clients can expect all elements in the array to be of Type and avoid filtering on null values.

The GraphQL endpoint may have to filter null values from the response but these values provide no information to the client at present.

Before:

graph.queryType().then(res => {
  res.queryType
    .filter((type: Type | null) => type !== null)
    .forEach((type: Type) => {...});
})

After:

graph.queryType().then(res => {
  res.queryType.forEach((type: Type) => {...});
})
1 Like

“To Many” fields on AddTypeInputs should be optional

Currently, a type with this schema:

type Book {
  authors: [Author!]!
}

Will generate an AddBookInput with this schema:

input AddBookInput {
  authors: [Author!]!
}

Meaning add mutations will need to provide an empty array of authors for new books. Since the presence of this array has no effect in dgraph terms (ie. we don’t create an “empty” edge) we should allow the input to omit this field.

input AddBookInput {
  authors: [Author!]
}

Note that [Author!]! does not mean “Book always has authors” but rather “Book always has an array of zero or more authors”. As dgraph will always return an array for “authors” when the type is queried authors: [Author] is not really possible.

1 Like

What do you do when you need to return null results then?

I didn’t think that is possible with dgraph anyway? If an edge has a type of [uid] you will always get an empty array.

Return type of updateType should be UpdateTypePayload! not UpdateTypePayload

Currently, the return type of the generated updateType mutation is an optional UpdateTypePayload. This means we must check for null before accessing its fields.

Unless the return type can sometimes be null, it should be UpdateTypePayload!

Edit: the same applies to addType and deleteType actually :slight_smile:

BTW, I’m happy to open PRs for all these, just looking for input from Dgraph team on whether they seem like worthwhile changes.

As most of them are around nullability of values, it’s possible that I’m not aware of some cases where things can actually be null. Although, I would argue that the GraphQL endpoint should avoid those cases if possible :slight_smile: