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
- 1. The issue provides a reproduction available on
Github,
Stackblitz
or
CodeSandbox
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
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