All the Resolvers in your AppSync API can be found in serverless.yml under the appSync.resolvers
property.
Resolvers are defined using key-value pairs where the key can either be an arbitrary name for the resolver or the type
and field
in the schema it is attached to separated with a dot (.
), and the value is the configuration of the resolver.
appSync:
resolvers:
Query.user:
dataSource: myDataSource
getPosts:
type: Query
field: getPosts
dataSource: myDataSource
type
: The Type in the schema this resolver is attached to. Optional if specified in the configuration key.field
: The Field in the schema this resolver is attached to. Optional if specified in the configuration key.kind
: The kind of resolver. Can beUNIT
orPIPELINE
(see below). Defaults toPIPELINE
dataSource
: The name of the dataSource this resolver uses.functions
: For pipeline resolvers (see below) the array of functions to run in sequencemaxBatchSize
: The maximum batch size to use (only available for AWS Lambda DataSources)code
: The path of the JavaScript resolver handler file, relative toserverless.yml
. If not specified, a minimalistic default is used.request
: The path to the VTL request mapping template file, relative toserverless.yml
.response
: The path to the VTL response mapping template file, relative toserverless.yml
.substitutions
: See Variable Substitutionscaching
: See belowsync
: See SyncConfig
When code
is specified, the JavaScript runtime is used.
When request
and/or response
are specified, the VTL runtime is used.
For direct lambda, set kind
to UNIT
and don't specify request
, response
or code
. This only works with Lambda function data sources.
If nothing is specified, by default, the resolver is a PIPELINE JavaScript resolver, and the following minimalistic code is used for the before
and after
handlers.
export function request() {
return {};
}
export function response(ctx) {
return ctx.prev.result;
}
Example of a UNIT JavaScript resolver.
appSync:
resolvers:
Query.user:
kind: UNIT
dataSource: myDataSource
code: getUser.js
AppSync requires resolvers to be bundled in one single file. By default, this plugin bundles your code with esbuild, using the given path as the entry point.
This means that you can import external libraries and utilities. e.g.
import { Context, util } from '@aws-appsync/utils';
import { generateUpdateExpressions, updateItem } from '../lib/helpers';
export function request(ctx) {
const { id, ...post } = ctx.args.post;
const item = updateItem(post);
return {
operation: 'UpdateItem',
key: {
id: util.dynamodb.toDynamoDB(id),
},
update: generateUpdateExpressions(item),
condition: {
expression: 'attribute_exists(#id)',
expressionNames: {
'#id': 'id',
},
},
};
}
export function response(ctx: Context) {
return ctx.result;
}
For more information, also see the esbuild option.
You can write JS resolver in TypeScript. Resolver files with the .ts
extension are automatically transpiled and bundled using esbuild.
resolvers:
Query.user:
kind: UNIT
dataSource: 'users'
code: 'getUser.ts'
// getUser.ts
import { Context, util } from '@aws-appsync/utils';
export function request(ctx: Context) {
const {
args: { id },
} = ctx;
return {
operation: 'GetItem',
key: util.dynamodb.toMapValues({ id }),
};
}
export function response(ctx: Context) {
return ctx.result;
}
For more information, also see the esbuild option.
When kind
is PIPELINE
, you can specify the pipeline function names to use:
appSync:
pipelineFunctions:
function1:
dataSource: myDataSource
function2:
dataSource: myDataSource
resolvers:
Query.user:
functions:
- function1
- function2
If a DataSource is only used in one single resolver, you can also define it inline in the resolver configuration. This is often the case for Lambda resolvers.
You can even also define the Lambda function definition inline under the dataSource definition. This helps keep everything in one single place!
appSync:
resolvers:
Query.user:
kind: UNIT
dataSource:
type: 'AWS_LAMBDA'
config:
function:
timeout: 30
handler: 'functions/getUser.handler'
If a Pipeline function is only used in a single resolver, you can also define it inline in the resolver configuration.
appSync:
resolvers:
Query.user:
functions:
- dataSource: 'users'
code: 'getUser.js'
Query.user:
dataSource: myDataSource
caching:
ttl: 60
keys:
- '$context.arguments.id'
You can either pass true
which will use the global TTL (See the global caching configuration) and no keys
.
You can also customize each resolver using the following config:
ttl
: The TTL of the cache for this resolver in secondskeys
: An array of keys to use for the cache.
You can define your data sources into several files for organizational reasons. You can pass each file into the dataSources
attribute as an array.
resolvers:
- ${file(appsync/resolvers/users.yml)}
- ${file(appsync/resolvers/posts.yml)}