Skip to content

Incomplete GraphQLSchema Generation for Nested OpenAPI Specifications in GraphQL Mesh #8607

@barmmie

Description

@barmmie

Issue workflow progress

Progress of the issue based on the
Contributor Workflow

Make sure to fork this template and run yarn generate in the terminal.

Please make sure Mesh package versions under package.json matches yours.

  • 2. A failing test has been provided
  • 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:

  1. Use the provided OpenAPI spec in GraphQL Mesh.
  2. Observe the generated schema.
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions