Incomplete GraphQLSchema Generation for Nested OpenAPI Specifications in GraphQL Mesh
Issue workflow progress
Progress of the issue based on the Contributor Workflow
- [x] 1. The issue provides a reproduction available on Github, Stackblitz or CodeSandbox
Make sure to fork this template and run
yarn generatein the terminal.Please make sure Mesh package versions under
package.jsonmatches yours.
- [ ] 2. A failing test has been provided
- [x] 3. A local solution has been provided
- [ ] 4. A pull request is pending review
Describe the bug
When using an OpenAPI specification with allOf containing nested schemas, such as the one provided in this example:
https://codesandbox.io/p/devbox/smoosh-snow-j4939p?file=%2Fimdb.yml%3A18%2C1-19%2C1&workspaceId=ws_TwYYzLD6zQ1it3GjibBn21
GraphQL Mesh fails to correctly deep merge the response object, resulting in incomplete schema generation. Specifically, the generated schema omits certain nested fields, resulting in an incomplete representation of the expected schema.
To Reproduce Steps to reproduce the behavior:
- Use the provided OpenAPI spec in GraphQL Mesh.
- Observe the generated schema.
- Compare the generated schema with the expected schema.
https://codesandbox.io/p/devbox/smoosh-snow-j4939p?file=%2F.mesh%2Fsources%2FHello%20World%2Fschema.graphql%3A22%2C1-23%2C1&workspaceId=ws_TwYYzLD6zQ1it3GjibBn21
Expected behavior
The generated schema should include all nested fields and look like this:
type query_movies_by_movieId_allOf_0_movie @join__type(graph: STUDOCU_REST_API) {
"""
The ID of the movie
"""
id: String!
"""
The title of the movie
"""
title: String!
"""
Genre of the movie
"""
genre: String!
"""
The director of the movie
"""
director: String
"""
The ID of the director
"""
directorId: String
"""
The rating of the movie
"""
rating: Float
"""
The number of ratings for the movie
"""
ratingCount: Int
}
The generated schema is incomplete and only includes the following fields:
type query_movies_by_movieId_allOf_2_movie {
"""
The rating of the movie
"""
rating: Float
"""
The number of ratings for the movie
"""
ratingCount: Int
}
Additional context
The issue appears to originate from the following code in the getComposerFromJSONSchema.ts file:
https://github.com/ardatan/graphql-mesh/blob/master/packages/loaders/json-schema/src/getComposerFromJSONSchema.ts#L1048-#L1052
Updating the code to handle deep merging of NonNullComposer<ObjectTypeComposer> fields resolves the issue. Suggested fix:
...
if (existingFieldUnwrappedTC instanceof ObjectTypeComposer &&
newFieldUnwrappedTC instanceof ObjectTypeComposer) {
deepMergeObjectTypeComposerFields(existingFieldUnwrappedTC, newFieldUnwrappedTC);
}
else if (existingFieldUnwrappedTC instanceof NonNullComposer
&& existingFieldUnwrappedTC.ofType instanceof ObjectTypeComposer
&& newFieldUnwrappedTC instanceof NonNullComposer
&& newFieldUnwrappedTC.ofType instanceof ObjectTypeComposer
) {
deepMergeObjectTypeComposerFields(existingFieldUnwrappedTC.getUnwrappedTC(), newFieldUnwrappedTC.getUnwrappedTC());
}
else {
if (newFieldUnwrappedTC &&
existingFieldUnwrappedTC &&
!isUnspecificType(newFieldUnwrappedTC) &&
isUnspecificType(existingFieldUnwrappedTC)) {
continue;
}
fieldMap[fieldName] = newField;
}
...
A similar fix might be required for input fields. Let me know if I can create a pull request with the proposed solution.
Thanks for the feedback! And PRS are welcome of course π
The proposed fix caused other issues with the generated schema.
I eventually used this library to merge the allOfs and as such simplify the generated openapi spec, before passing it into graphql-mesh.
That fixed my issue.
Thanks for your time and the effort on this project π