Skip to content

docs(appsync): add mutation example and infrastructure fix #1964

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions docs/core/event_handler/appsync.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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

Expand Down
10 changes: 10 additions & 0 deletions examples/event_handler_graphql/sam/samconfig.toml
Original file line number Diff line number Diff line change
@@ -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 = []
32 changes: 15 additions & 17 deletions examples/event_handler_graphql/sam/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Original file line number Diff line number Diff line change
@@ -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": {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 2 additions & 0 deletions examples/event_handler_graphql/src/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
aws-lambda-powertools[tracer]
requests