aws-amplify / amplify-category-api

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development. This plugin provides functionality for the API category, allowing for the creation and management of GraphQL and REST based backends for your amplify project.
https://docs.amplify.aws/
Apache License 2.0
88 stars 76 forks source link

Custom queries with lambda function resolvers with invoke prefix do not compile #2009

Open vishal-dms opened 10 months ago

vishal-dms commented 10 months ago

How did you install the Amplify CLI?

npm

If applicable, what version of Node.js are you using?

N/A

Amplify CLI Version

12.6.0

What operating system are you using?

Mac

Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes made.

N/A

Describe the bug

When we have two custom queries with Lambda function resolvers such that the function names differ by invoke prefix and this is specified as second query, the gql-transformer fails to compile the schema resulting in the following type of error - 🛑 DataSource InvokeFunctionNameLambdaDataSource is missing in the API

Workaround is to specify the invoke prefix query first and then the other query.

Expected behavior

GraphQL Transformer should be able to compile queries that have invoke prefix irrespective of the order they are specified in.

Reproduction steps

  1. Add two Lambda functions named testfunction & invokeTestfunction to your backend

  2. Try deploying or compiling the following schema -

    type Query {
    foo(msg: String): String @function(name: "testfunction-${env}")
    bar(msg: String): String @function(name: "invokeTestfunction-${env}")
    }
  3. This will result in the below error -

    $ amplify api gql-compile
    🛑 DataSource InvokeTestfunctionLambdaDataSource is missing in the API
  4. Re-order the queries and observe a successfull compilation -

    type Query {
    bar(msg: String): String @function(name: "invokeTestfunction-${env}")
    foo(msg: String): String @function(name: "testfunction-${env}")
    }

Project Identifier

N/A

Log output

``` # Put your logs below this line ```

Additional information

N/A

Before submitting, please confirm:

AnilMaktala commented 10 months ago

Hey @vishal-dms, Thank you for raising this. We are able to replicate this by following the steps provided in the description.Hence, marking this as a bug for the team to evaluate further.

Schema:

input AMPLIFY {
  globalAuthRule: AuthRule = { allow: public }
} # FOR TESTING ONLY!
type Todo @model {
  id: ID!
  name: String!
  description: String
}

type Todo2 @model {
  id: ID!
  name: String!
  description: String
}

type Query {
  foo(msg: String): String @function(name: "testfunction-${env}")
  bar(msg: String): String @function(name: "invokeTestfunction-${env}")
}
image
sushpatg commented 10 months ago

Hi Team, Follow up bug when using invoke prefix.

The workaround to re-order the invoke prefix query first and then the other query is helping us to compile. But it is not creating Pipeline function.

As per the above Schema, Query foo just have before and after mapping template and pipeline function is missing

Kindly let us if there is any other workaround than changing the function name

Generated resolver:

"QueryfooResolver": {
      "Type": "AWS::AppSync::Resolver",
      "Properties": {
        "ApiId": {
          "Ref": "referencetotransformerrootstackGraphQLAPI20497F53ApiId"
        },
        "FieldName": "foo",
        "TypeName": "Query",
        "Kind": "PIPELINE",
        "PipelineConfig": {
          "Functions": []
        },
        "RequestMappingTemplate": "## [Start] Stash resolver specific context.. **\n$util.qr($ctx.stash.put(\"typeName\", \"Query\"))\n$util.qr($ctx.stash.put(\"fieldName\", \"foo\"))\n{}\n## [End] Stash resolver specific context.. **",
        "ResponseMappingTemplateS3Location": {
          "Fn::Join": [
            "",
            [
              "s3://",
              {
                "Ref": "referencetotransformerrootstackS3DeploymentBucket7592718ARef"
              },
              "/",
              {
                "Ref": "referencetotransformerrootstackS3DeploymentRootKeyA71EA735Ref"
              },
              "/resolvers/Query.foo.res.vtl"
            ]
          ]
        }
      }
    }
  },
AnilMaktala commented 10 months ago

Hey @sushpatg, Is there a particular reason behind the use of the 'invoke' prefix in the function name? 'Invoke' is a pre-existing string in the library, which leads to issues when incorporated into the function name. If there isn't a strong justification for its use, I'd recommend considering an alternative name, as illustrated below.

type Query {
  foo(msg: String): String @function(name: "testfunction-${env}")
  bar(msg: String): String @function(name: "invTestfunction-${env}")
}