OAS 'additionalProperties' treated as regular field in some cases
Issue workflow progress
Progress of the issue based on the Contributor Workflow
- [ ] 1. The issue provides a reproduction available on CodeSandbox
- [x ] 2. A failing test has been provided
- [ ] 3. A local solution has been provided
- [ ] 4. A pull request is pending review
Describe the bug
After running mesh-compose on a swagger yaml with 'additionalProperties' field, in cases when it is an object, the resulting supegraph contains it as a simple object property instead of JSON:
application/json:
schema:
type: object
properties:
"additionalPropertiesTrue":
type: object
additionalProperties: true
"additionalPropertiesInteger":
type: object
additionalProperties:
type: integer
"additionalPropertiesObject":
type: object
additionalProperties:
type: object
properties:
code:
type: integer
text:
type: string
"additionalPropertiesObjectWithCustomTitle":
type: object
additionalProperties:
type: object
properties:
code:
type: integer
text:
type: string
title: This is a custom title
"additionalPropertiesArrayInteger":
type: object
additionalProperties:
type: array
items:
type: integer
"additionalPropertiesObjectRef":
type: object
additionalProperties:
"$ref": "#/components/schemas/ref"
"additionalPropertiesObjectRefNested":
type: object
additionalProperties:
"$ref": "#/components/schemas/ref-with-ref"
translated into
additionalPropertiesTrue: JSON
additionalPropertiesInteger: JSON
additionalPropertiesObject: IvanV3Api_PetStore_QueryPostAdditionalPropertiesObject @source(
name: "additionalPropertiesObject"
type: "query_post_additionalPropertiesObject"
subgraph: "V3_Petstore"
)
additionalPropertiesObjectWithCustomTitle: IvanV3Api_PetStore_QueryPostAdditionalPropertiesObjectWithCustomTitle @source(
name: "additionalPropertiesObjectWithCustomTitle"
type: "query_post_additionalPropertiesObjectWithCustomTitle"
subgraph: "V3_Petstore"
)
additionalPropertiesArrayInteger: JSON
additionalPropertiesObjectRef: JSON
additionalPropertiesObjectRefNested: IvanV3Api_PetStore_QueryPostAdditionalPropertiesObjectRefNested @source(
name: "additionalPropertiesObjectRefNested"
type: "query_post_additionalPropertiesObjectRefNested"
subgraph: "V3_Petstore"
)
To Reproduce Steps to reproduce the behavior:
open attached sanbox and run pnpm run start
Expected behavior
all the output for response fields should have JSON type
Environment:
"@graphql-mesh/compose-cli": "^1.4.0", "@omnigraph/openapi": "^0.109.0",
Additional context
the original testing file is from: https://github.com/readmeio/oas-examples/blob/060d4ffbbe63003f923c8cd7268ee39a495cf21f/3.0/yaml/schema-additional-properties.yaml#L18
If you have additionalProperties defined, Mesh adds an additional properties field in order to have those extra fields to be resolvers. This is intentional. If you don't want that, you can filter those fields out by using transforms.
Thanks for the reply @ardatan! I guess I understand that. Does that means the fragment to such gql should be:
additionalPropertiesObject {
additionalProperties {
key
value {
code
text
}
}
}
and it'll be auto-mapped with correct resolvers right?
Note: I'm using codegen to generate hooks out of this gql
If it is JSON, you can't select the fields under of it (which is related to GraphQL itself not Mesh)
But if it is an object, you can select fields like that as in generated in the schema.
@ardatan That's the issue, it is a JSON like:
{
en: {
code: '<span>some str</span>',
text: 'some example text'
},
fr: {},
// pl: ... etc
}
and when we have schema with
additionalProperties:
type: object
# or ref to object
it basically means it's a JSON, since additionalProperties is a schema directive - not a field, so if this GraphQL limitation is not worked around somehow, then I don't understand why this is intentional and how it can be used to make an actual call.
Note: generated type(from the mentioned sandbox):
additionalPropertiesObject: IvanV3Api_PetStore_QueryPostAdditionalPropertiesObject @source(
name: "additionalPropertiesObject"
type: "query_post_additionalPropertiesObject"
subgraph: "V3_Petstore"
)
type IvanV3Api_PetStore_QueryPostAdditionalPropertiesObject @source(name: "query_post_additionalPropertiesObject", subgraph: "V3_Petstore") @join__type(graph: V3_PETSTORE) {
additionalProperties: [IvanV3Api_PetStore_QueryPostAdditionalPropertiesObjectAdditionalPropertiesEntry] @dictionary(subgraph: "V3_Petstore") @source(
name: "additionalProperties"
type: "[query_post_additionalPropertiesObject_additionalProperties_entry]"
subgraph: "V3_Petstore"
)
}
type IvanV3Api_PetStore_QueryPostAdditionalPropertiesObjectAdditionalPropertiesEntry @source(
name: "query_post_additionalPropertiesObject_additionalProperties_entry"
subgraph: "V3_Petstore"
) @join__type(graph: V3_PETSTORE) {
key: ID!
value: IvanV3Api_PetStore_QueryPostAdditionalPropertiesObjectAdditionalProperties @source(
name: "value"
type: "query_post_additionalPropertiesObject_additionalProperties"
subgraph: "V3_Petstore"
)
}
type IvanV3Api_PetStore_QueryPostAdditionalPropertiesObjectAdditionalProperties @source(
name: "query_post_additionalPropertiesObject_additionalProperties"
subgraph: "V3_Petstore"
) @join__type(graph: V3_PETSTORE) {
code: Int
text: String
}
If the generated type is JSON, you can't select fields like;
additionalProperties { key value }
If only the generated type is XAdditionalPropertiesObjectAdditionalProperties, you can select fields
@ardatan in the example above we have:
QueryPostAdditionalPropertiesObject →
QueryPostAdditionalPropertiesObjectAdditionalPropertiesEntry →
PetStore_QueryPostAdditionalPropertiesObjectAdditionalProperties
so that I can select fields, the question is how such call will work, basically my gql call data return will have a property additionalProperties with the correctly mapped key: value records?