Challanges when implementing GraphQL client for Forge Storage API in Forge Remote

I have been trying to implement a Forge Storage client that calls the GraphQL API from a Forge Remote in a typed language. The experience leaves me wondering if the GraphQL schema is inaccurate regarding optional fields and/or if the Atlassian JS implementation is buggy.

To start, I tried to implement the query API exposed via the @forge/api package.

I used a tool to generate language types from the GraphQL schema to query the appStoredEntities. To write the query, I followed the definition in the @forge/storage package (search for listQuery). The generated return type looks as follows (illustrative, only includes types for the queried fields):

Option<{
  edges: Option<Array<Option<{
    cursor: String,
    node: Option<{
      key: String,
      value: Option<String>
    }>
  }>>>
}>

The above type matches the GraphQL schema definition.

For the actual implementation, I tried to follow the JS package code, but here is where it gets tricky.

The JS code (search for the list function) glances over optional fields in several places and assumes they are present. It also exposes inaccurate Typescript types. Some examples:

  • response.appStoredEntities is optional. The code accesses response.appStoredEntities.edges without further checks, which may throw.
  • edges is optional. If edges is not defined, edges.length will throw.
  • the code edges[edges.length - 1].cursor could throw if the returned array is [undefined] or [null].
  • the Typescript return type of list is ListResults and claims that the results property is Array<{ key: string; value: any;}>, however, results can be [undefined].

While I managed to come up with some implementation, I am unsure if it is accurate. Our typed code handles null/undefined values, but I am unsure how the GraphQL API actually behaves.

@atlassian, could someone look into this? It would be good to improve the type accuracy of both the GraphQL and/or JS API (Typescript types).

3 Likes

Hi @tbinna,
Thanks for giving this a go and providing us with feedback. The source of truth should be the GraphQL schema that is exposed by our GraphQL playground (I assume this is what you mean when you refer to the GraphQL schema?), the @forge/storage package should follow this schema. I will forward this along to the owning team.

4 Likes