Amplify-cli: How to add a custom mutation and resolver for an existing GraphQL table?

Created on 10 May 2019  路  1Comment  路  Source: aws-amplify/amplify-cli

* Which Category is your question related to? *
GraphQL/Appsync Resolvers

* What AWS Services are you utilizing? *
Amplify/Appsync

* Provide additional details e.g. code snippets *
So maybe this is a stupid question but the whole CF/stacks thing is a little foreign to me so after a lot of time searching and searching, I think it's time to just ask.

How do I add a custom mutation and resolver for an existing GraphQL table?

This is my rough schema:

type User @model
{
  id: ID!
  addresses: [Address]
}
type Address {
  address1: String
}

Now, I want to create a custom resolver in VTL to add an address. I know I can, on client side, pull the existing entries, push a new element to the list, and update the User.
I also know I can make Address an @model with the @connection directive. I do not want to go down that path though. I do that for other models, but for this and a few other things, I want to keep it within the single model.
My current attempt is this:
Add the following to my schema.graphql:

type Mutation {
  addAddress(
    address1: String
  ): User
}

And then no Mutation.addAddress.res/req.vtl is created (I know about custom resolvers and putting them into the amplify/backend/api//resolvers/ directory, I've done that for other resolvers already successfully).
So I figure the next step is that I need to create a custom stack that follows the flow of my User.json stack.

That's where I keep failing, anything I've tried has given me an error when I amplify push. I've tried to copy/paste the User.json stack and put it into the custom directory (amplify/backend/api//stacks), and then just added the following:
EDIT: I added the below to the Resources section.

        "AddAddressResolver": {
            "Type": "AWS::AppSync::Resolver",
            "Properties": {
                "ApiId": {
                    "Ref": "GetAttGraphQLAPIApiId"
                },
                "DataSourceName": {
                    "Fn::GetAtt": [
                        "UserDataSource",
                        "Name"
                    ]
                },
                "FieldName": "addAddress",
                "TypeName": "Mutation",
                "RequestMappingTemplateS3Location": {
                    "Fn::Sub": [
                        "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName}",
                        {
                            "S3DeploymentBucket": {
                                "Ref": "S3DeploymentBucket"
                            },
                            "S3DeploymentRootKey": {
                                "Ref": "S3DeploymentRootKey"
                            },
                            "ResolverFileName": {
                                "Fn::Join": [
                                    ".",
                                    [
                                        "Mutation",
                                        "addAddress",
                                        "req",
                                        "vtl"
                                    ]
                                ]
                            }
                        }
                    ]
                },
                "ResponseMappingTemplateS3Location": {
                    "Fn::Sub": [
                        "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName}",
                        {
                            "S3DeploymentBucket": {
                                "Ref": "S3DeploymentBucket"
                            },
                            "S3DeploymentRootKey": {
                                "Ref": "S3DeploymentRootKey"
                            },
                            "ResolverFileName": {
                                "Fn::Join": [
                                    ".",
                                    [
                                        "Mutation",
                                        "addAddress",
                                        "res",
                                        "vtl"
                                    ]
                                ]
                            }
                        }
                    ]
                }
            }
        },

I tried a bunch of other things, and I know I'm just missing something... I have a feeling it's something simple and I just don't know CF well enough. Any help?

Thank you very much.

Most helpful comment

Well hello it looks like I got it to work after more searching.. isn't it funny how that always happens AFTER you post about it... anyways, with help from the following post #1224 I got it to work.

My code is below in case it's helpful to any future readers.

My completed custom stack is as follows (note, the name is Address.json, not User.json as I do not want it to overwrite the existing one and instead only add to it):

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "An auto-generated nested stack.",
    "Metadata": {},
    "Parameters": {
        "AppSyncApiId": {
            "Type": "String",
            "Description": "The id of the AppSync API associated with this project."
        },
        "AppSyncApiName": {
            "Type": "String",
            "Description": "The name of the AppSync API",
            "Default": "AppSyncSimpleTransform"
        },
        "env": {
            "Type": "String",
            "Description": "The environment name. e.g. Dev, Test, or Production",
            "Default": "NONE"
        },
        "S3DeploymentBucket": {
            "Type": "String",
            "Description": "The S3 bucket containing all deployment assets for the project."
        },
        "S3DeploymentRootKey": {
            "Type": "String",
            "Description": "An S3 key relative to the S3DeploymentBucket that points to the root\nof the deployment directory."
        }
    },
    "Resources": {
        "EmptyResource": {
            "Type": "Custom::EmptyResource",
            "Condition": "AlwaysFalse"
        },
        "AddAddressResolver": {
            "Type": "AWS::AppSync::Resolver",
            "Properties": {
                "ApiId": {
                    "Ref": "AppSyncApiId"
                },
                "DataSourceName": "UserTable",
                "FieldName": "addAddress",
                "TypeName": "Mutation",
                "RequestMappingTemplateS3Location": {
                    "Fn::Sub": [
                        "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName}",
                        {
                            "S3DeploymentBucket": {
                                "Ref": "S3DeploymentBucket"
                            },
                            "S3DeploymentRootKey": {
                                "Ref": "S3DeploymentRootKey"
                            },
                            "ResolverFileName": {
                                "Fn::Join": [
                                    ".",
                                    [
                                        "Mutation",
                                        "addAddress",
                                        "req",
                                        "vtl"
                                    ]
                                ]
                            }
                        }
                    ]
                },
                "ResponseMappingTemplateS3Location": {
                    "Fn::Sub": [
                        "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName}",
                        {
                            "S3DeploymentBucket": {
                                "Ref": "S3DeploymentBucket"
                            },
                            "S3DeploymentRootKey": {
                                "Ref": "S3DeploymentRootKey"
                            },
                            "ResolverFileName": {
                                "Fn::Join": [
                                    ".",
                                    [
                                        "Mutation",
                                        "addAddress",
                                        "res",
                                        "vtl"
                                    ]
                                ]
                            }
                        }
                    ]
                }
            }
        }
    },
    "Conditions": {
        "HasEnvironmentParameter": {
            "Fn::Not": [
                {
                    "Fn::Equals": [
                        {
                            "Ref": "env"
                        },
                        "NONE"
                    ]
                }
            ]
        },
        "AlwaysFalse": {
            "Fn::Equals": [
                "true",
                "false"
            ]
        }
    },
    "Outputs": {
        "EmptyOutput": {
            "Description": "An empty output. You may delete this if you have at least one resource above.",
            "Value": ""
        }
    }
}

And I've created files called Mutation.addAddress.req/res.vtl in the custom resolvers directory.

I'll close this for now, thanks!

>All comments

Well hello it looks like I got it to work after more searching.. isn't it funny how that always happens AFTER you post about it... anyways, with help from the following post #1224 I got it to work.

My code is below in case it's helpful to any future readers.

My completed custom stack is as follows (note, the name is Address.json, not User.json as I do not want it to overwrite the existing one and instead only add to it):

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "An auto-generated nested stack.",
    "Metadata": {},
    "Parameters": {
        "AppSyncApiId": {
            "Type": "String",
            "Description": "The id of the AppSync API associated with this project."
        },
        "AppSyncApiName": {
            "Type": "String",
            "Description": "The name of the AppSync API",
            "Default": "AppSyncSimpleTransform"
        },
        "env": {
            "Type": "String",
            "Description": "The environment name. e.g. Dev, Test, or Production",
            "Default": "NONE"
        },
        "S3DeploymentBucket": {
            "Type": "String",
            "Description": "The S3 bucket containing all deployment assets for the project."
        },
        "S3DeploymentRootKey": {
            "Type": "String",
            "Description": "An S3 key relative to the S3DeploymentBucket that points to the root\nof the deployment directory."
        }
    },
    "Resources": {
        "EmptyResource": {
            "Type": "Custom::EmptyResource",
            "Condition": "AlwaysFalse"
        },
        "AddAddressResolver": {
            "Type": "AWS::AppSync::Resolver",
            "Properties": {
                "ApiId": {
                    "Ref": "AppSyncApiId"
                },
                "DataSourceName": "UserTable",
                "FieldName": "addAddress",
                "TypeName": "Mutation",
                "RequestMappingTemplateS3Location": {
                    "Fn::Sub": [
                        "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName}",
                        {
                            "S3DeploymentBucket": {
                                "Ref": "S3DeploymentBucket"
                            },
                            "S3DeploymentRootKey": {
                                "Ref": "S3DeploymentRootKey"
                            },
                            "ResolverFileName": {
                                "Fn::Join": [
                                    ".",
                                    [
                                        "Mutation",
                                        "addAddress",
                                        "req",
                                        "vtl"
                                    ]
                                ]
                            }
                        }
                    ]
                },
                "ResponseMappingTemplateS3Location": {
                    "Fn::Sub": [
                        "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/${ResolverFileName}",
                        {
                            "S3DeploymentBucket": {
                                "Ref": "S3DeploymentBucket"
                            },
                            "S3DeploymentRootKey": {
                                "Ref": "S3DeploymentRootKey"
                            },
                            "ResolverFileName": {
                                "Fn::Join": [
                                    ".",
                                    [
                                        "Mutation",
                                        "addAddress",
                                        "res",
                                        "vtl"
                                    ]
                                ]
                            }
                        }
                    ]
                }
            }
        }
    },
    "Conditions": {
        "HasEnvironmentParameter": {
            "Fn::Not": [
                {
                    "Fn::Equals": [
                        {
                            "Ref": "env"
                        },
                        "NONE"
                    ]
                }
            ]
        },
        "AlwaysFalse": {
            "Fn::Equals": [
                "true",
                "false"
            ]
        }
    },
    "Outputs": {
        "EmptyOutput": {
            "Description": "An empty output. You may delete this if you have at least one resource above.",
            "Value": ""
        }
    }
}

And I've created files called Mutation.addAddress.req/res.vtl in the custom resolvers directory.

I'll close this for now, thanks!

Was this page helpful?
0 / 5 - 0 ratings