diff --git a/docs/core/event_handler/appsync.md b/docs/core/event_handler/appsync.md index 2fe5896b273..14a638b6123 100644 --- a/docs/core/event_handler/appsync.md +++ b/docs/core/event_handler/appsync.md @@ -46,7 +46,10 @@ This is the sample infrastructure we are using for the initial examples with a A You can define your functions to match GraphQL types and fields with the `app.resolver()` decorator. -Here's an example where we have two separate functions to resolve `getTodo` and `listTodos` fields within the `Query` type. For completion, we use Scalar type utilities to generate the right output based on our schema definition. +???+ question "What is a type and field?" + A type would be a top-level **GraphQL Type** like `Query`, `Mutation`, `Todo`. A **GraphQL Field** would be `listTodos` under `Query`, `createTodo` under `Mutation`, etc. + +Here's an example with two separate functions to resolve `getTodo` and `listTodos` fields within the `Query` type. For completion, we use [Scalar type utilities](#scalar-functions) to generate the right output based on our schema definition. ???+ important GraphQL arguments are passed as function keyword arguments. @@ -58,27 +61,35 @@ Here's an example where we have two separate functions to resolve `getTodo` and === "getting_started_graphql_api_resolver.py" - ```python hl_lines="14 20 30 32-33 42 44 55" + ```python hl_lines="14 21 31 33-34 43 45 53 55 66" --8<-- "examples/event_handler_graphql/src/getting_started_graphql_api_resolver.py" ``` === "getting_started_schema.graphql" - ```typescript hl_lines="6-7" + ```typescript hl_lines="7-9 13" --8<-- "examples/event_handler_graphql/src/getting_started_schema.graphql" ``` -=== "getting_started_get_todo.json" +=== "sample events" - ```json hl_lines="2-3" - --8<-- "examples/event_handler_graphql/src/getting_started_get_todo.json" - ``` + === "getting_started_get_todo.json" -=== "getting_started_list_todos.json" + ```json hl_lines="2-3 42" + --8<-- "examples/event_handler_graphql/src/getting_started_get_todo.json" + ``` - ```json hl_lines="2 40 42" - --8<-- "examples/event_handler_graphql/src/getting_started_list_todos.json" - ``` + === "getting_started_list_todos.json" + + ```json hl_lines="2 40" + --8<-- "examples/event_handler_graphql/src/getting_started_list_todos.json" + ``` + + === "getting_started_create_todo.json" + + ```json hl_lines="2 48 49" + --8<-- "examples/event_handler_graphql/src/getting_started_create_todo.json" + ``` ### Scalar functions diff --git a/examples/event_handler_graphql/sam/samconfig.toml b/examples/event_handler_graphql/sam/samconfig.toml new file mode 100644 index 00000000000..fc5a42d082c --- /dev/null +++ b/examples/event_handler_graphql/sam/samconfig.toml @@ -0,0 +1,10 @@ +version = 0.1 +[default] +[default.deploy] +[default.deploy.parameters] +stack_name = "pt-graphql-getting-started" +s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1pssy5gdxqcao" +s3_prefix = "pt-graphql-getting-started" +region = "eu-west-1" +capabilities = "CAPABILITY_IAM" +image_repositories = [] diff --git a/examples/event_handler_graphql/sam/template.yaml b/examples/event_handler_graphql/sam/template.yaml index 3e2ab60ab10..7639114802c 100644 --- a/examples/event_handler_graphql/sam/template.yaml +++ b/examples/event_handler_graphql/sam/template.yaml @@ -70,22 +70,12 @@ Resources: Type: "AWS::AppSync::GraphQLSchema" Properties: ApiId: !GetAtt TodosApi.ApiId - Definition: | - schema { - query:Query - } - - type Query { - getTodo(id: ID!): Todo - listTodos: [Todo] - } - - type Todo { - id: ID! - userId: String - title: String - completed: Boolean - } + DefinitionS3Location: ../src/getting_started_schema.graphql + Metadata: + cfn-lint: + config: + ignore_checks: + - W3002 # allow relative path in DefinitionS3Location # Lambda Direct Data Source and Resolver @@ -115,10 +105,18 @@ Resources: FieldName: "getTodo" DataSourceName: !GetAtt TodosFunctionDataSource.Name + CreateTodoResolver: + Type: "AWS::AppSync::Resolver" + Properties: + ApiId: !GetAtt TodosApi.ApiId + TypeName: "Mutation" + FieldName: "createTodo" + DataSourceName: !GetAtt TodosFunctionDataSource.Name + Outputs: TodosFunction: Description: "Hello World Lambda Function ARN" Value: !GetAtt TodosFunction.Arn TodosApi: - Value: !GetAtt TodosApi.Arn + Value: !GetAtt TodosApi.GraphQLUrl diff --git a/examples/event_handler_graphql/src/getting_started_create_todo.json b/examples/event_handler_graphql/src/getting_started_create_todo.json new file mode 100644 index 00000000000..e8a1ce65f95 --- /dev/null +++ b/examples/event_handler_graphql/src/getting_started_create_todo.json @@ -0,0 +1,53 @@ + { + "arguments": { + "title": "Sample todo mutation" + }, + "identity": null, + "source": null, + "request": { + "headers": { + "x-forwarded-for": "203.0.113.1, 203.0.113.18", + "cloudfront-viewer-country": "NL", + "cloudfront-is-tablet-viewer": "false", + "x-amzn-requestid": "fdc4f30b-44c2-475d-b2f9-9da0778d5275", + "via": "2.0 f655cacd0d6f7c5dc935ea687af6f3c0.cloudfront.net (CloudFront)", + "cloudfront-forwarded-proto": "https", + "origin": "https://eu-west-1.console.aws.amazon.com", + "content-length": "166", + "x-forwarded-proto": "https", + "accept-language": "en-US,en;q=0.5", + "host": "kiuqayvn4jhhzio6whpnk7xj3a.appsync-api.eu-west-1.amazonaws.com", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Firefox/102.0", + "cloudfront-is-mobile-viewer": "false", + "accept": "application/json, text/plain, */*", + "cloudfront-viewer-asn": "1136", + "cloudfront-is-smarttv-viewer": "false", + "accept-encoding": "gzip, deflate, br", + "referer": "https://eu-west-1.console.aws.amazon.com/", + "content-type": "application/json", + "x-api-key": "da2-vsqnxwyzgzf4nh6kvoaidtvs7y", + "sec-fetch-mode": "cors", + "x-amz-cf-id": "0kxqijFPsbGSWJ1u3Z_sUS4Wu2hRoG_2T77aJPuoh_Q4bXAB3x0a3g==", + "x-amzn-trace-id": "Root=1-63fef2cf-6d566e9f4a35b99e6212388e", + "sec-fetch-dest": "empty", + "x-amz-user-agent": "AWS-Console-AppSync/", + "cloudfront-is-desktop-viewer": "true", + "sec-fetch-site": "cross-site", + "x-forwarded-port": "443" + }, + "domainName": null + }, + "prev": null, + "info": { + "selectionSetList": [ + "id", + "title", + "completed" + ], + "selectionSetGraphQL": "{\n id\n title\n completed\n}", + "fieldName": "createTodo", + "parentTypeName": "Mutation", + "variables": {} + }, + "stash": {} +} diff --git a/examples/event_handler_graphql/src/getting_started_graphql_api_resolver.py b/examples/event_handler_graphql/src/getting_started_graphql_api_resolver.py index e4879d609f2..9edd8c68dad 100644 --- a/examples/event_handler_graphql/src/getting_started_graphql_api_resolver.py +++ b/examples/event_handler_graphql/src/getting_started_graphql_api_resolver.py @@ -13,6 +13,7 @@ from aws_lambda_powertools import Logger, Tracer from aws_lambda_powertools.event_handler import AppSyncResolver from aws_lambda_powertools.logging import correlation_paths +from aws_lambda_powertools.utilities.data_classes.appsync import scalar_types_utils from aws_lambda_powertools.utilities.typing import LambdaContext tracer = Tracer() @@ -49,6 +50,16 @@ def list_todos() -> List[Todo]: return todos.json()[:10] +@app.resolver(type_name="Mutation", field_name="createTodo") +@tracer.capture_method +def create_todo(title: str) -> Todo: + payload = {"userId": scalar_types_utils.make_id(), "title": title, "completed": False} # dummy UUID str + todo: Response = requests.post("https://jsonplaceholder.typicode.com/todos", json=payload) + todo.raise_for_status() + + return todo.json() + + @logger.inject_lambda_context(correlation_id_path=correlation_paths.APPSYNC_RESOLVER) @tracer.capture_lambda_handler def lambda_handler(event: dict, context: LambdaContext) -> dict: diff --git a/examples/event_handler_graphql/src/getting_started_schema.graphql b/examples/event_handler_graphql/src/getting_started_schema.graphql index b8ef8f995d0..02d3bc3b2f3 100644 --- a/examples/event_handler_graphql/src/getting_started_schema.graphql +++ b/examples/event_handler_graphql/src/getting_started_schema.graphql @@ -1,12 +1,18 @@ schema { query: Query + mutation: Mutation } type Query { + # these are fields you can attach resolvers to (field: Query, field: getTodo) getTodo(id: ID!): Todo listTodos: [Todo] } +type Mutation { + createTodo(title: String!): Todo +} + type Todo { id: ID! userId: String diff --git a/examples/event_handler_graphql/src/requirements.txt b/examples/event_handler_graphql/src/requirements.txt new file mode 100644 index 00000000000..76d40513e2b --- /dev/null +++ b/examples/event_handler_graphql/src/requirements.txt @@ -0,0 +1,2 @@ +aws-lambda-powertools[tracer] +requests