aws-amplify / amplify-cli

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development.
Apache License 2.0
2.81k stars 821 forks source link

How to create custom @connection resolver? #1352

Closed plaa closed 5 years ago

plaa commented 5 years ago

Which Category is your question related to? GraphQL API

What AWS Services are you utilizing? AppSync, DynamoDB, Cognito

Provide additional details e.g. code snippets

We're creating a GraphQL API using amplify add api. The vast majority of the API can use the autogenerated code backed by DynamoDB. However, there is one model Person for which we want to fetch data from the Cognito user pool.

I was planning to use custom resolvers using Lambda functions for this purpose, but can't figure out how to handle connections.

In simplified terms, we would have the following schema.graphql:

type Person @model(queries: null, mutations: null, subscriptions: null) {
  id: ID!
  firstName: String
  lastName: String
}
type Post @model {
  id: ID!
  title: String!
  author: Person @connection
}

To be precise, the Person type should not be annotated with @model directive, as the model is not stored in DynamoDB, but the @connection does not work without it.

I can prevent the generation of default getPerson etc. queries and implement them using custom resolvers. However, I also need to override the default Post.author resolver.

I could add a custom resolver template in resolvers/Post.author.req.vtl, but the data source would still be defined to be a DynamoDB table (instead of a Lambda function) in the autogenerated CF stack.

Is there any way to override the autogenerated CF resolver definition / data source in addition to overriding the resolver vtl templates?

yuth commented 5 years ago

We have examples of Custom resolver lambda in the docs. Let me know if you need any additional help

plaa commented 5 years ago

I've gone through the docs and know how to create a custom query resolver. What I haven't been able to do is to create a custom resolver that is used by other types through @connection.

In the example I provided, I know how to create a custom resolver for getPerson. What I haven't been able to figure out is how to make Post.author use a Lambda function. While I can override the Post.author.req.vtl resolver template, I cannot override the autogenerated CloudFormation stack template which defines the data source as DynamoDB instead of Lambda.

mikeparisstuff commented 5 years ago

These docs describe how to connect a lambda resolver (https://aws-amplify.github.io/docs/cli/graphql#add-a-custom-resolver-that-targets-an-aws-lambda-function). To do this you should remove the @model from Person, remove @connection from Post.author, follow the instructions here to add a lambda resolver on the Post.author field (e.g. in the CFN doc the "TypeName": "Post" and "FieldName": "author".

PR #1346 implements the @function directive that provides a much simpler interface for configuring lambda resolvers (although the process is very similar under the hood). Once this is merged, you will be able to do:

type Person {
  id: ID!
  firstName: String
  lastName: String
}
type Post @model {
  id: ID!
  title: String!
  author: Person @function(name: "ResolveUserPoolUser")
}

I'd also point you to #1060 which discusses supporting custom transformers. With this you would be able to implement your own @resolveUser directive that configures a call to AWS Cognito User Pools and can be used in multiple places throughout the schema.

mikeparisstuff commented 5 years ago

I have added this as an example in the Amplify docs. As soon as these PRs from the docs (https://github.com/aws-amplify/docs/pull/640) and cli (https://github.com/aws-amplify/amplify-cli/pull/1346) are merged you will be able to add this without much trouble.

RyanHow commented 5 years ago

@mikeparisstuff the @function appears to be working nicely now it's merged in

madhurvyas1 commented 5 years ago

These docs describe how to connect a lambda resolver (https://aws-amplify.github.io/docs/cli/graphql#add-a-custom-resolver-that-targets-an-aws-lambda-function). To do this you should remove the @model from Person, remove @connection from Post.author, follow the instructions here to add a lambda resolver on the Post.author field (e.g. in the CFN doc the "TypeName": "Post" and "FieldName": "author".

PR #1346 implements the @function directive that provides a much simpler interface for configuring lambda resolvers (although the process is very similar under the hood). Once this is merged, you will be able to do:

type Person {
  id: ID!
  firstName: String
  lastName: String
}
type Post @model {
  id: ID!
  title: String!
  author: Person @function(name: "ResolveUserPoolUser")
}

I'd also point you to #1060 which discusses supporting custom transformers. With this you would be able to implement your own @resolveUser directive that configures a call to AWS Cognito User Pools and can be used in multiple places throughout the schema.

Hi, Im looking for similar solution, but i want to know what arguments will Lambda function receive to identify the user, like user ID, my model will have multiple users, and i want all off them to be resolved by a common function. for example type Person { id: ID! firstName: String lastName: String } type Post @model { id: ID! title: String! author: Person @function(name: "ResolveUserPoolUser") editor: Person @function(name: "ResolveUserPoolUser") }

VitValchar commented 5 years ago

In case anyone is looking for an answer to @madhurvyas1 question: the function event.typeName will be "Post" for both function calls, but the event.fieldName will be "author" for one and "editor" for second, so you can distinguish which one of them is being resolved.

idobleicher commented 3 years ago

I have also the same issue, why does he can't use a custom resolver with the connections. why does he need to use function directive? and what about the typing when you have 6 levels of dep ? which is auto-generated how you make all this connection work. I have issues connecting all of that stuff. ( I'll be really happy to work with an expert on that), and pay of course i really need help! Thanks.

github-actions[bot] commented 3 years ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels for those types of questions.