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 accessesresponse.appStoredEntities.edges
without further checks, which may throw.edges
is optional. Ifedges
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
isListResults
and claims that theresults
property isArray<{ 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).