Add custom business logic (Experimental)
The default GraphQL API provides a solid foundation for querying, mutating, and fetching data. Even so, you may need additional customization to tailor it to your app's specific requirements around data handling, response formatting, and more.
In the following sections, we walk through the three steps to create a custom mutation or query:
- Define a custom query or mutation
- Configure custom business logic handler code
- Invoke the custom query or mutation
Step 1 - Define a custom query or mutation
Type | When to choose |
---|---|
Query | When the request only needs to read data and will not modify any backend data |
Mutation | When the request will modify backend data |
For every custom query or mutation, you need to set a return type and, optionally, arguments. Use a.query()
or a.mutation()
to define your custom query or mutation in your amplify/data/resource.ts file:
1import { type ClientSchema, a, defineData } from '@aws-amplify/backend';2
3const schema = a.schema({4 // 1. Define your return type as a custom type5 EchoResponse: a.customType({6 content: a.string(),7 executionDuration: a.float()8 }),9
10 // 2. Define your query with the return type and, optionally, arguments11 echo: a.query()12 // arguments that this query accepts13 .arguments({ 14 content: a.string()15 }) 16 // return type of the query17 .returns(a.ref('EchoResponse'))18 // only allow signed-in users to call this API19 .authorization([a.allow.private()])20})21
22export type Schema = ClientSchema<typeof schema>;23
24export const data = defineData({25 schema,26})
Step 2 - Configure custom business logic handler code
After your query or mutation is defined, you need to author your custom business logic in a Lambda function. In your amplify/data/ folder, create a new folder named after your mutation or query with an index.js file.
amplify/data/echo/index.js
1exports.handler = async (event) => {2 const start = performance.now()3 return {4 content: event.arguments.name,5 executionDuration: performance.now() - start6 }7}
In your amplify/data/resource.ts file, import the function using the experimental Func
functionality and then reference the function with your query or mutation using the .function()
modifier along with the functions
map of defineData
.
amplify/data/resource.ts
1import {2 type ClientSchema,3 a,4 defineData,5 Func // Step 1 - Import "Func" to create new functions6} from '@aws-amplify/backend';7
8const schema = a.schema({9 EchoResponse: a.customType({10 content: a.string(),11 executionDuration: a.float()12 }),13
14 echo: a.query()15 .arguments({ content: a.string() }) 16 .returns(a.ref('EchoResponse'))17 .authorization([a.allow.private()])18 // Step 2 - Define a function key ("echoHandler") that will be used19 // to map this query to the corresponding functions provided to20 // defineData(...)21 .function('echoHandler')22})23
24export type Schema = ClientSchema<typeof schema>;25
26export const data = defineData({27 schema,28 // Step 3 - Map the function key to the newly created function29 functions: {30 'echoHandler': Func.fromDir({31 codePath: './echo',32 name: 'echoHandlerFunc',33 })34 }35})
Step 3 - Invoke the custom query or mutation
In the preview of Amplify (Gen 2), you must first generate GraphQL client code for your custom queries and mutations and then pass them into the client.graphql(...)
operation. In your terminal, run the following command:
1npx amplify generate graphql-client-code \2--format graphql-codegen \3--statement-target typescript \4--type-target typescript \5--out ./graphql \6--stack <YOUR_STACK_NAME_HERE> 7# You can find your stack name in your "npx amplify sandbox"8# console logs. It has the following format:9# amplify-<app-name>-<user-name>-sandbox-<unique-id>
This should create the following set of GraphQL client helper code for you under graphql/:
- API.ts – All the type definitions for queries, mutations, and subscriptions
- mutations.ts – The GraphQL mutations from your API
- queries.ts – The GraphQL queries from your API
- subscriptions.ts – The GraphQL subscriptions from your API
To call the echo
query from step 1, we need to import the echo
function from queries.ts and pass it as a query to client.graphql(...)
.
1import { generateClient } from 'aws-amplify/data'2import { type Schema } from '@/amplify/data/resource'3import * as queries from '@/graphql/queries'4
5const client = generateClient<Schema>()6
7async function callEcho() {8 const response = await client.graphql({9 query: echo,10 variables: {11 content: "Echo me!"12 }13 })14
15 console.log(response.data.echo?.content)16 console.log(response.data.echo?.executionDuration)17}