-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Custom type and ref arg handling in SchemaProcessor with tests #412
base: feat/allow-customtype-ref-in-arguments
Are you sure you want to change the base?
feat: Custom type and ref arg handling in SchemaProcessor with tests #412
Conversation
|
- Update schema processor to correctly include all custom types - Adjust test cases in CustomOperations.test.ts, client-schema.ts, and ssr-req-client.ts - Update corresponding snapshots to reflect change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm seeing some unexpected changes in the code and tests/snapshots, as called out in the comments.
Let's baseline on the requirements. When custom query/mutation arguments
contain non-scalar values (e.g., custom types or a refs to custom types), we should:
- Define a GraphQL Input type from the arguments in the SDL output from
schema.transform()
- Reference this input type in the query/mutation field argument
- The GraphQL Type definition for the custom type should remain in the SDL output
For example, given:
Location: a.customType({
lat: a.float(),
long: a.float(),
}),
addLocationToPost: a
.mutation()
.arguments({ postId: a.string(), location: a.ref('Location') })
.handler(a.handler.custom({ entry: './source.js' }))
.returns(a.boolean())
The GraphQL output should be:
type Location
{
lat: Float
long: Float
}
input AddLocationToPostLocationInput
{
lat: Float
long: Float
}
type Mutation {
addLocationToPost(postId: string, location: AddLocationToPostLocationInput): Boolean
}
However, when I pull down the PR and run schema.transform()
on the same schema , I get the following output:
type Location
{
lat: Float
long: Float
}
type Mutation {
addLocationToPost(postId: String, location: ID): Boolean
}
- Input type is not getting generated
addLocationToPost
field arglocation
is referencing typeID
instead of the Input type
After making the requested changes, I recommend linking @aws-amplify/data-schema
into a sample app and actually attempting to deploy some schemas with custom operations containing non-scalar arguments
to make sure everything works as expected.
"type LikePostReturnType | ||
{ | ||
stringField: String | ||
intField: Int | ||
floatField: Float | ||
boolField: Boolean | ||
datetimeField: AWSDateTime | ||
jsonField: AWSJSON | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't be dropping this type definition. If we're just left with
type Mutation {
likePost(postId: String!): LikePostReturnType
}
The field return type LikePostReturnType
is referencing an undefined type. This schema would error during deployment
"type GetPostDetailsReturnType | ||
{ | ||
stringField: String | ||
intField: Int | ||
floatField: Float | ||
boolField: Boolean | ||
datetimeField: AWSDateTime | ||
jsonField: AWSJSON | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above ^. This type definition should not get dropped
"type CreateCustomTypePostReturnType @aws_api_key | ||
{ | ||
title: String! | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here and below
`${fieldName}: ${modelFieldToGql(fieldDef.data)}${fieldAuth}`, | ||
); | ||
if (isInput) { | ||
gqlFields.push(`${fieldName}: ID${fieldAuth}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does an input become a field of type ID
?
'queryWithCustomTypeArg(customArg: ID): String', | ||
'queryWithRefArg(refArg: ID): String', | ||
'mutateWithCustomTypeArg(customArg: ID): String', | ||
'mutationWithRefArg(refArg: ID): String', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly to previous comments, these should all be input types, something like:
'queryWithCustomTypeArg(customArg: QueryWithCustomTypeArgInput): String',
'queryWithRefArg(refArg: QueryWithRefArgInput): String',
'mutateWithCustomTypeArg(customArg: MutateWithCustomTypeArgInput): String',
'mutationWithRefArg(refArg: MutationWithRefArgInput): String'
And we should also test that these Input types themselves are being emitted in schema.transform()
"authMode": undefined, | ||
"authToken": undefined, | ||
"query": " | ||
mutation($customArg: ID) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and below, ID
is not the correct GraphQL data type for these operations. We should be referencing the Input type that is generated from our Custom Type
`${fieldName}: ${refFieldToGql(fieldDef.data, secondaryIndexes[fieldName])}${fieldAuth}`, | ||
); | ||
if (isInput) { | ||
gqlFields.push(`${fieldName}: ID${fieldAuth}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
const s = a.schema({ | ||
MyQueryReturnType: a.customType({ | ||
fieldA: a.string(), | ||
fieldB: a.integer(), | ||
nestedCustomType: a.customType({ | ||
nestedA: a.string(), | ||
nestedB: a.string(), | ||
grandChild: a.customType({ | ||
grandA: a.string(), | ||
grandB: a.string(), | ||
}), | ||
}), | ||
}), | ||
myQuery: a | ||
.query() | ||
.handler(a.handler.function('myFn')) | ||
.returns( | ||
a.customType({ | ||
fieldA: a.string(), | ||
fieldB: a.integer(), | ||
nestedCustomType: a.customType({ | ||
nestedA: a.string(), | ||
nestedB: a.string(), | ||
grandChild: a.customType({ | ||
grandA: a.string(), | ||
grandB: a.string(), | ||
}), | ||
}), | ||
}), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are both of these cases covered under test? It might make sense to duplicate this test here to ensure we cover both inline custom types and ref custom types.
@@ -595,7 +595,11 @@ exports[`schema auth rules global public auth - multiple models 1`] = ` | |||
"functionSlots": [], | |||
"jsFunctions": [], | |||
"lambdaFunctions": {}, | |||
"schema": "type A @model @auth(rules: [{allow: public, provider: apiKey}]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand why this changed. What caused this diff?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably related to Ivan's comments below.
Problem:
-Custom type and ref arguments in custom queries and mutations were not properly handled in the SchemaProcessor, leading to incorrect GraphQL schema generation.
-Several integration tests in custom-operations.ts were previously skipped due to schema validation issues related to custom type argument features.
Related PR
-This PR addresses the skipped tests and completes the implementation started in PR #402.
Changes:
generateInputTypes
function to create GraphQL input types for custom structures.Validation:
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.