Skip to content
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

Draft
wants to merge 7 commits into
base: feat/allow-customtype-ref-in-arguments
Choose a base branch
from

Conversation

vaisshnavi7
Copy link
Contributor

@vaisshnavi7 vaisshnavi7 commented Dec 11, 2024

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:

  • Updated SchemaProcessor.ts to generate GraphQL input types for custom types and ref arguments.
  • Modified the processing of custom operations to use these generated input types.
  • Implemented generateInputTypes function to create GraphQL input types for custom structures.
  • Expanded and fixed integration tests in custom-operations.ts:
    • Re-enabled previously skipped tests
    • Added new test for schema.transform() to ensure correct schema generation
    • Added new tests for mocked runtime behavior of client operations with custom type and ref arguments
  • Updated test snapshots to reflect new schema generation behavior
  • Adjusted test cases in CustomOperations.test.ts, client-schema.ts, and ssr-req-client.ts

Validation:

  • Expanded existing integration tests in custom-operations.ts to cover new functionality, including:
    • A new test for schema.transform() to verify correct schema generation
    • New tests for mocked client operations with custom type and ref arguments
  • Re-enabled and fixed previously skipped tests in custom-operations.ts
  • Verified that all tests now pass, including those for custom types and ref arguments

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Copy link

changeset-bot bot commented Dec 11, 2024

⚠️ No Changeset found

Latest commit: 4e49d64

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

- 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
@vaisshnavi7 vaisshnavi7 marked this pull request as ready for review December 16, 2024 21:07
@vaisshnavi7 vaisshnavi7 requested review from a team as code owners December 16, 2024 21:07
Copy link
Member

@iartemiev iartemiev left a 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:

  1. Define a GraphQL Input type from the arguments in the SDL output from schema.transform()
  2. Reference this input type in the query/mutation field argument
  3. 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 arg location is referencing type ID 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.

Comment on lines 48 to 56
"type LikePostReturnType
{
stringField: String
intField: Int
floatField: Float
boolField: Boolean
datetimeField: AWSDateTime
jsonField: AWSJSON
}
Copy link
Member

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

Comment on lines 112 to 120
"type GetPostDetailsReturnType
{
stringField: String
intField: Int
floatField: Float
boolField: Boolean
datetimeField: AWSDateTime
jsonField: AWSJSON
}
Copy link
Member

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

Comment on lines 261 to 264
"type CreateCustomTypePostReturnType @aws_api_key
{
title: String!
}
Copy link
Member

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}`);
Copy link
Member

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?

Comment on lines 298 to 301
'queryWithCustomTypeArg(customArg: ID): String',
'queryWithRefArg(refArg: ID): String',
'mutateWithCustomTypeArg(customArg: ID): String',
'mutationWithRefArg(refArg: ID): String',
Copy link
Member

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) {
Copy link
Member

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}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Comment on lines 1364 to -1382
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(),
}),
}),
}),
)
Copy link
Member

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}])
Copy link
Member

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?

Copy link
Member

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.

@vaisshnavi7 vaisshnavi7 marked this pull request as draft December 27, 2024 04:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants