ardatan / graphql-mesh

🕸️ GraphQL Mesh - The Graph of Everything - Federated architecture for any API service

Home Page:https://the-guild.dev/graphql/mesh

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

JSON-Schema issues with required + nullable=true fields

FGoessler opened this issue · comments

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

Fields marked as nullable and required in JSON schema or OpenAPI schema-based sources unexpectedly generate a required field in the GraphQL schema. The expected outcome would be a regular optional field in the GraphQL schema.

This seems like a regression of the issue discussed here: #2627

To Reproduce

Code Sandbox Link

Use a .meshrc.ts specifying a source via JSON schema that specifies a response field as required but also nullable. Minimal complete example:

import { YamlConfig } from "@graphql-mesh/types"

export const config: YamlConfig.Config = {
  sources: [
    {
      name: "FooApi",
      handler: {
        jsonSchema: {
          endpoint: "https://www.example.com/",
          operations: [
            {
              type: "Query",
              field: "foo",
              path: "/foo",
              method: "GET",
              responseSchema: {
                "type": "object",
                "required": [
                  "bar"
                ],
                "properties": {
                  "bar": {
                    "type": "string",
                    "nullable": true,
                    "example": "lorem ipsum"
                  }
                }
              }
            },
          ],
        },
      },
    }
  ],
}

export default  config

Expected behavior

Upon mesh build a GraphQL type like this SHOULD BE generated as part of .mesh/schema.graphql:

type query_foo {
  bar: String
}

Note how bar is NOT required.

Actual behavior

Upon mesh build a GraphQL type like this IS generated as part of .mesh/schema.graphql:

type query_foo {
  bar: String!
}

Note how bar is required.

Environment:

  • OS: MacOS 13.2
  • NodeJS: v18.19.0

package.json (freshly created today Fri 9th feb 2024):

{
  "name": "reproduce-gql-mesh-issue",
  "version": "1.0.0",
  "scripts": {
    "prebuild": "mesh build"
  },
  "dependencies": {
    "@graphql-mesh/cli": "^0.88.6",
    "@graphql-mesh/json-schema": "^0.98.0",
    "graphql": "^16.8.1"
  }
}

Additional context

It took me and @nathanbrachotte a while to dig into this issue. We discovered it originally when importing an OpenAPI schema. After tracking it further down we could nail this down to this general JSON schema issue.

Based on my debugging into the code that was added to fix the original issue, this added code seems to run correctly.

At least the following code fragment from the getComposerFromJSONSchema.js seems to work as intended.

let nullable = true;
if (subSchemaAndTypeComposers.required?.includes(propertyName)) {
 nullable = false;
}
// Nullable has more priority
if (typeComposers.nullable === false) {
 nullable = false;
}
if (typeComposers.nullable === true) {
 nullable = true;
}
return !nullable ? typeComposers.input?.getTypeNonNull() : typeComposers.input; 

I hence assume the bug is somewhere in the upstream schema generation. Am not at all familiar with that though.

EDIT:

After some further digging I think the "faulty code" is here & here.
These sections seem to again iterate over all fields that are supposed to be required based on the upper objects schema. Without looking at the individual fields nullable values.

Based on my limited testing just removing these sections fully solved the issue. The required fields logic seems to stay intact.

But again just my findings and I have no prior experience with the internals of GraphQL Mesh. 😅

Opened a PR based on my findings above that should fix this issue: #6561