

# AWS AppSync resolver reference (JavaScript)
<a name="resolver-reference-js-version"></a>

The following sections contain the `APPSYNC_JS` runtime and JavaScript resolver reference:
+  [ JavaScript resolvers overview ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html) - Learn more about how resolvers work in AWS AppSync.
+  [ Resolver context object reference ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html) - Learn more about the context object and how it's used in resolvers.
+  [ JavaScript runtime features for resolvers and functions ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html) - Learn more about supported runtime features and using utilities to simplify code.
+  [ JavaScript resolver function reference for DynamoDB ](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html) - Learn more about how resolvers interact with DynamoDB.
+  [ JavaScript resolver function reference for OpenSearch ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-elasticsearch-js.html) - Learn more about resolver request and response structure and interactions with OpenSearch Service.
+  [ JavaScript resolver function reference for Lambda ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-lambda-js.html) - Learn more about resolver request and response structure and interactions with Lambda.
+  [ JavaScript resolver function reference for EventBridge data source ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-eventbridge-js.html) - Learn more about resolver request and response structure and interactions with EventBridge.
+  [ JavaScript resolver function reference for None data source ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-none-js.html) - Learn more about resolver request and response structure and interactions with NONE data sources.
+  [ JavaScript resolver function reference for HTTP ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-http-js.html) - Learn more about resolver request and response structure and interactions with HTTP endpoints.
+  [ JavaScript resolver function reference for Amazon RDS ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-rds-js.html) - Learn more about resolver structure and interactions with RDS.
+  [ JavaScript resolver function reference for Amazon Bedrock](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-bedrock-js.html) - Learn more about resolver structure and interactions with Amazon Bedrock.

# AWS AppSync JavaScript resolvers overview
<a name="resolver-reference-overview-js"></a>

AWS AppSync lets you respond to GraphQL requests by performing operations on your data sources. For each GraphQL field you wish to run a query, mutation, or subscription on, a resolver must be attached.

Resolvers are the connectors between GraphQL and a data source. They tell AWS AppSync how to translate an incoming GraphQL request into instructions for your backend data source and how to translate the response from that data source back into a GraphQL response. With AWS AppSync, you can write your resolvers using JavaScript and run them in the AWS AppSync (`APPSYNC_JS`) environment. 

AWS AppSync allows you to write unit resolvers or pipeline resolvers composed of multiple AWS AppSync functions in a pipeline.

## Supported runtime features
<a name="runtime-support-js"></a>

The AWS AppSync JavaScript runtime provides a subset of JavaScript libraries, utilities, and features. For a complete list of features and functionality supported by the `APPSYNC_JS` runtime, see [JavaScript runtime features for resolvers and functions](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html).

## Unit resolvers
<a name="unit-resolver-js"></a>

A unit resolver is composed of code that defines a request and response handler that are executed against a data source. The request handler takes a context object as an argument and returns the request payload used to call your data source. The response handler receives a payload back from the data source with the result of the executed request. The response handler transforms the payload into a GraphQL response to resolve the GraphQL field. In the example below, a resolver retrieves an item from an DynamoDB data source:

```
import * as ddb from '@aws-appsync/utils/dynamodb'

export function request(ctx) {
  return ddb.get({ key: { id: ctx.args.id } });
}

export const response = (ctx) => ctx.result;
```

## Anatomy of a JavaScript pipeline resolver
<a name="anatomy-of-a-pipeline-resolver-js"></a>

A pipeline resolver is composed of code that defines a request and response handler and a list of functions. Each function has a **request** and **response** handler that it executes against a data source. As a pipeline resolver delegates runs to a list of functions, it is therefore not linked to any data source. Unit resolvers and functions are primitives that execute operation against data sources.

### Pipeline resolver request handler
<a name="request-handler-js"></a>

The request handler of a pipeline resolver (the before step) allows you to perform some preparation logic before running the defined functions.

### Functions list
<a name="functions-list-js"></a>

The list of functions a pipeline resolver will run in sequence. The pipeline resolver request handler evaluation result is made available to the first function as `ctx.prev.result`. Each function evaluation result is available to the next function as `ctx.prev.result`.

### Pipeline resolver response handler
<a name="response-handler-js"></a>

The response handler of a pipeline resolver allows you to perform some final logic from the output of the last function to the expected GraphQL field type. The output of the last function in the functions list is available in the pipeline resolver response handler as `ctx.prev.result` or `ctx.result`.

### Execution flow
<a name="execution-flow-js"></a>

Given a pipeline resolver comprised of two functions, the list below represents the execution flow when the resolver is invoked:

1.  Pipeline resolver request handler

1.  Function 1: Function request handler 

1.  Function 1: Data source invocation 

1.  Function 1: Function response handler 

1.  Function 2: Function request handler 

1.  Function 2: Data source invocation 

1.  Function 2: Function response handler 

1.  Pipeline resolver response handler 

![\[GraphQL request flow diagram showing interactions between request, data sources, and response components.\]](http://docs.aws.amazon.com/appsync/latest/devguide/images/appsync-js-resolver-logic.png)


### Useful `APPSYNC_JS` runtime built-in utilities
<a name="useful-utilities-js"></a>

The following utilities can help you when you’re working with pipeline resolvers.

#### ctx.stash
<a name="ctx-stash-js"></a>

The stash is an object that is made available inside each resolver and function request and response handler. The same stash instance lives through a single resolver run. This means that you can use the stash to pass arbitrary data across request and response handlers and across functions in a pipeline resolver. You can test the stash like a regular JavaScript object.

#### ctx.prev.result
<a name="ctx-prev-result-js"></a>

The `ctx.prev.result` represents the result of the previous operation that was executed in the pipeline. If the previous operation was the pipeline resolver request handler, then `ctx.prev.result` is made available to the first function in the chain. If the previous operation was the first function, then `ctx.prev.result` represents the output of the first function and is made available to the second function in the pipeline. If the previous operation was the last function, then `ctx.prev.result` represents the output of the last function and is made available to the pipeline resolver response handler.

#### util.error
<a name="util-error-js"></a>

The `util.error` utility is useful to throw a field error. Using `util.error` inside a function request or response handler throws a field error immediately, which prevents subsequent functions from being executed. For more details and other `util.error` signatures, visit [JavaScript runtime features for resolvers and functions](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html).

#### util.appendError
<a name="util-appenderror-js"></a>

`util.appendError` is similar to `util.error()`, with the major distinction that it doesn’t interrupt the evaluation of the handler. Instead, it signals there was an error with the field, but allows the handler to be evaluated and consequently return data. Using `util.appendError` inside a function will not disrupt the execution flow of the pipeline. For more details and other `util.error` signatures, visit the [JavaScript runtime features for resolvers and functions](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html).

#### runtime.earlyReturn
<a name="runtime-earlyreturn-js"></a>

The `runtime.earlyReturn` function allows you to prematurely return from any request function. Using `runtime.earlyReturn` inside of a resolver request handler will return from the resolver. Calling it from an AWS AppSync function request handler will return from the function and will continue the run to either the next function in the pipeline or the resolver response handler.

### Writing pipeline resolvers
<a name="writing-resolvers"></a>

A pipeline resolver also has a request and a response handler surrounding the run of the functions in the pipeline: its request handler is run before the first function’s request, and its response handler is run after the last function’s response. The resolver request handler can set up data to be used by functions in the pipeline. The resolver response handler is responsible for returning data that maps to the GraphQL field output type. In the example below, a resolver request handler, defines `allowedGroups`; the data returned should belong to one of these groups. This value can be used by the resolver’s functions to request data. The resolver’s response handler conducts a final check and filters the result to make sure that only items that belong to the allowed groups are returned.

```
import { util } from '@aws-appsync/utils';

/**
 * Called before the request function of the first AppSync function in the pipeline.
 *  @param ctx the context object holds contextual information about the function invocation.
 */
export function request(ctx) {
  ctx.stash.allowedGroups = ['admin'];
  ctx.stash.startedAt = util.time.nowISO8601();
  return {};
}
/**
 * Called after the response function of the last AppSync function in the pipeline.
 * @param ctx the context object holds contextual information about the function invocation.
 */
export function response(ctx) {
  const result = [];
  for (const item of ctx.prev.result) {
    if (ctx.stash.allowedGroups.indexOf(item.group) > -1) result.push(item);
  }
  return result;
}
```

#### Writing AWS AppSync functions
<a name="writing-functions"></a>

AWS AppSync functions enable you to write common logic that you can reuse across multiple resolvers in your schema. For example, you can have one AWS AppSync function called `QUERY_ITEMS` that is responsible for querying items from an Amazon DynamoDB data source. For resolvers that you'd like to query items with, simply add the function to the resolver's pipeline and provide the query index to be used. The logic doesn't have to be re-implemented.

## Supplemental topics
<a name="supplemental-topics"></a>

**Topics**
+ [Example pipeline resolver with Amazon DynamoDB](https://docs.aws.amazon.com/appsync/latest/devguide/writing-code.html)
+ [Configuring utilities for the `APPSYNC_JS` runtime](https://docs.aws.amazon.com/appsync/latest/devguide/utility-resolvers.html)
+ [Bundling, TypeScript, and source maps for the `APPSYNC_JS` runtime](https://docs.aws.amazon.com/appsync/latest/devguide/additional-utilities.html)
+ [Testing your resolver and function handlers](https://docs.aws.amazon.com/appsync/latest/devguide/test-resolvers.html)
+ [Migrating from VTL to JavaScript](https://docs.aws.amazon.com/appsync/latest/devguide/migrating-resolvers.html)
+ [Choosing between direct data source access and proxying via a Lambda data source](https://docs.aws.amazon.com/appsync/latest/devguide/choosing-data-source.html)

# Example pipeline resolver with Amazon DynamoDB
<a name="writing-code"></a>

Suppose you wanted to attach a pipeline resolver on a field named `getPost(id:ID!)` that returns a `Post` type from an Amazon DynamoDB data source with the following GraphQL query:

```
getPost(id:1){
    id
    title
    content
}
```

First, attach a simple resolver to `Query.getPost` with the code below. This is an example of simple resolver code. There is no logic defined in the request handler, and the response handler simply returns the result of the last function.

```
/**
 * Invoked **before** the request handler of the first AppSync function in the pipeline.
 * The resolver `request` handler allows to perform some preparation logic
 * before executing the defined functions in your pipeline.
 * @param ctx the context object holds contextual information about the function invocation.
 */
export function request(ctx) {
  return {}
}

/**
 * Invoked **after** the response handler of the last AppSync function in the pipeline.
 * The resolver `response` handler allows to perform some final evaluation logic
 * from the output of the last function to the expected GraphQL field type.
 * @param ctx the context object holds contextual information about the function invocation.
 */
export function response(ctx) {
  return ctx.prev.result
}
```

Next, define function `GET_ITEM` that retrieves a postitem from your data source:

```
import { util } from '@aws-appsync/utils'
import * as ddb from '@aws-appsync/utils/dynamodb'

/**
 * Request a single item from the attached DynamoDB table datasource
 * @param ctx the context object holds contextual information about the function invocation.
 */
export function request(ctx) {
	const { id } = ctx.args
	return ddb.get({ key: { id } })
}

/**
 * Returns the result
 * @param ctx the context object holds contextual information about the function invocation.
 */
export function response(ctx) {
	const { error, result } = ctx
	if (error) {
		return util.appendError(error.message, error.type, result)
	}
	return ctx.result
}
```

If there is an error during the request, the function’s response handler appends an error that will be returned to the calling client in the GraphQL response. Add the `GET_ITEM` function to your resolver functions list. When you execute the query, the `GET_ITEM` function’s request handler uses the utils provided by AWS AppSync's DynamoDB module to create a `DynamoDBGetItem` request using the `id` as the key. `ddb.get({ key: { id } })` generates the appropriate `GetItem` operation:

```
{
    "operation" : "GetItem",
    "key" : {
        "id" : { "S" : "1" }
    }
}
```

AWS AppSync uses the request to fetch the data from Amazon DynamoDB. Once the data is returned, it is handled by the `GET_ITEM` function’s response handler, which checks for errors and then returns the result. 

```
{
  "result" : {
    "id": 1,
    "title": "hello world",
    "content": "<long story>"
  }
}
```

Finally, the resolver’s response handler returns the result directly.

## Working with errors
<a name="working-with-errors"></a>

If an error occurs in your function during a request, the error will be made available in your function response handler in `ctx.error`. You can append the error to your GraphQL response using the `util.appendError` utility. You can make the error available to other functions in the pipeline by using the stash. See the example below:

```
/**
 * Returns the result
 * @param ctx the context object holds contextual information about the function invocation.
 */
export function response(ctx) {
  const { error, result } = ctx;
  if (error) {
    if (!ctx.stash.errors) ctx.stash.errors = []
    ctx.stash.errors.push(ctx.error)
    return util.appendError(error.message, error.type, result);
  }
  return ctx.result;
}
```

# Configuring utilities for the `APPSYNC_JS` runtime
<a name="utility-resolvers"></a>

AWS AppSync provides two libraries that aid in the development of resolvers with the `APPSYNC_JS` runtime: 
+ `@aws-appsync/eslint-plugin` - Catches and fixes problems quickly during development.
+ `@aws-appsync/utils` - Provides type validation and autocompletion in code editors.

## Configuring the eslint plugin
<a name="utility-resolvers-configuring-eslint-plugin"></a>

[ESLint](https://eslint.org/) is a tool that statically analyzes your code to quickly find problems. You can run ESLint as part of your continuous integration pipeline. `@aws-appsync/eslint-plugin` is an ESLint plugin that catches invalid syntax in your code when leveraging the `APPSYNC_JS` runtime. The plugin allows you to quickly get feedback about your code during development without having to push your changes to the cloud.

`@aws-appsync/eslint-plugin` provides two rule sets that you can use during development. 

**"plugin:@aws-appsync/base"** configures a base set of rules that you can leverage in your project: 


| Rule | Description | 
| --- | --- | 
| no-async | Async processes and promises are not supported. | 
| no-await | Async processes and promises are not supported. | 
| no-classes | Classes are not supported. | 
| no-for | for is not supported (except for for-in and for-of, which are supported) | 
| no-continue | continue is not supported. | 
| no-generators | Generators are not supported. | 
| no-yield | yield is not supported. | 
| no-labels | Labels are not supported. | 
| no-this | this keyword is not supported. | 
| no-try | Try/catch structure is not supported. | 
| no-while | While loops are not supported. | 
| no-disallowed-unary-operators | \$1\$1, --, and \$1 unary operators are not allowed. | 
| no-disallowed-binary-operators | The instanceof operator is not allowed. | 
| no-promise | Async processes and promises are not supported. | 

**"plugin:@aws-appsync/recommended"** provides some additional rules but also requires you to add TypeScript configurations to your project.


| Rule | Description | 
| --- | --- | 
| no-recursion | Recursive function calls are not allowed. | 
| no-disallowed-methods | Some methods are not allowed. See the [reference](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html) for a full set of supported built-in functions. | 
| no-function-passing | Passing functions as function arguments to functions is not allowed. | 
| no-function-reassign | Functions cannot be reassigned. | 
| no-function-return | Functions cannot be the return value of functions. | 

To add the plugin to your project, follow the installation and usage steps at [Getting Started with ESLint](https://eslint.org/docs/latest/user-guide/getting-started#installation-and-usage). Then, install the [plugin](https://www.npmjs.com/package/@aws-appsync/eslint-plugin) in your project using your project package manager (e.g., npm, yarn, or pnpm):

```
$ npm install @aws-appsync/eslint-plugin
```

In your `.eslintrc.{js,yml,json}` file, add **"plugin:@aws-appsync/base"** or **"plugin:@aws-appsync/recommended"** to the `extends` property. The snippet below is a basic sample `.eslintrc` configuration for JavaScript: 

```
{
  "extends": ["plugin:@aws-appsync/base"]
}
```

To use the **"plugin:@aws-appsync/recommended"** rule set, install the required dependency:

```
$ npm install -D @typescript-eslint/parser
```

Then, create an `.eslintrc.js` file:

```
{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 2018,
    "project": "./tsconfig.json"
  },
  "extends": ["plugin:@aws-appsync/recommended"]
}
```

# Bundling, TypeScript, and source maps for the `APPSYNC_JS` runtime
<a name="additional-utilities"></a>

TypeScript enhances AWS AppSync development by providing type safety and early error detection. You can write TypeScript code locally and transpile it to JavaScript before using it with the `APPSYNC_JS` runtime. The process starts with installing TypeScript and configuring tsconfig.json for the `APPSYNC_JS` environment. You can then use bundling tools like esbuild to compile and bundle the code. The Amplify CLI will generate types from the GraphQL schema, allowing you to use these types in resolver code. 

You can leverage custom and external libraries in your resolver and function code, as long as they comply with `APPSYNC_JS` requirements. Bundling tools combine code into a single file for use in AWS AppSync. Source maps can be included to aid debugging. 

## Leveraging libraries and bundling your code
<a name="using-external-libraries"></a>

In your resolver and function code, you can leverage both custom and external libraries so long as they comply with the `APPSYNC_JS` requirements. This makes it possible to reuse existing code in your application. To make use of libraries that are defined by multiple files, you must use a bundling tool, such as [esbuild](https://esbuild.github.io/), to combine your code in a single file that can then be saved to your AWS AppSync resolver or function.

When bundling your code, keep the following in mind:
+ `APPSYNC_JS` only supports ECMAScript modules (ESM).
+ `@aws-appsync/*` modules are integrated into `APPSYNC_JS` and should not be bundled with your code.
+ The `APPSYNC_JS` runtime environment is similar to NodeJS in that code does not run in a browser environment.
+ You can include an optional source map. However, do not include the source content.

  To learn more about source maps, see [Using source maps](#source-maps).

For example, to bundle your resolver code located at `src/appsync/getPost.resolver.js`, you can use the following esbuild CLI command:

```
$ esbuild --bundle \
--sourcemap=inline \
--sources-content=false \
--target=esnext \
--platform=node \
--format=esm \
--external:@aws-appsync/utils \
--outdir=out/appsync \
 src/appsync/getPost.resolver.js
```

## Building your code and working with TypeScript
<a name="working-with-typescript"></a>

[TypeScript](https://www.typescriptlang.org/) is a programming language developed by Microsoft that offers all of JavaScript’s features along with the TypeScript typing system. You can use TypeScript to write type-safe code and catch errors and bugs at build time before saving your code to AWS AppSync. The `@aws-appsync/utils` package is fully typed.

The `APPSYNC_JS` runtime doesn't support TypeScript directly. You must first transpile your TypeScript code to JavaScript code that the `APPSYNC_JS` runtime supports before saving your code to AWS AppSync. You can use TypeScript to write your code in your local integrated development environment (IDE), but note that you cannot create TypeScript code in the AWS AppSync console.

To get started, make sure you have [TypeScript](https://www.typescriptlang.org/download) installed in your project. Then, configure your TypeScript transcompilation settings to work with the `APPSYNC_JS` runtime using [TSConfig](https://www.typescriptlang.org/tsconfig). Here’s an example of a basic `tsconfig.json` file that you can use:

```
// tsconfig.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
   "noEmit": true,
   "moduleResolution": "node",
  }
}
```

You can then use a bundling tool like esbuild to compile and bundle your code. For example, given a project with your AWS AppSync code located at `src/appsync`, you can use the following command to compile and bundle your code:

```
$ esbuild --bundle \
--sourcemap=inline \
--sources-content=false \
--target=esnext \
--platform=node \
--format=esm \
--external:@aws-appsync/utils \
--outdir=out/appsync \
 src/appsync/**/*.ts
```

### Using Amplify codegen
<a name="working-with-amplify-codegen"></a>

You can use the [Amplify CLI](https://docs.amplify.aws/cli/) to generate the types for your schema. From the directory where your `schema.graphql` file is located, run the following command and review the prompts to configure your codegen:

```
$  npx @aws-amplify/cli codegen add
```

To regenerate your codegen under certain circumstances (e.g., when your schema is updated), run the following command:

```
$ npx @aws-amplify/cli codegen
```

You can then use the generated types in your resolver code. For example, given the following schema:

```
type Todo {
  id: ID!
  title: String!
  description: String
}

type Mutation {
  createTodo(title: String!, description: String): Todo
}

type Query {
  listTodos: Todo
}
```

You could use the generated types in the following example AWS AppSync function:

```
import { Context, util } from '@aws-appsync/utils'
import * as ddb from '@aws-appsync/utils/dynamodb'
import { CreateTodoMutationVariables, Todo } from './API' // codegen

export function request(ctx: Context<CreateTodoMutationVariables>) {
	ctx.args.description = ctx.args.description ?? 'created on ' + util.time.nowISO8601()
	return ddb.put<Todo>({ key: { id: util.autoId() }, item: ctx.args })
}

export function response(ctx) {
	return ctx.result as Todo
}
```

### Using generics in TypeScript
<a name="working-with-typescript-generics"></a>

You can use generics with several of the provided types. For example, the snippet below is a `Todo` type:

```
export type Todo = {
  __typename: "Todo",
  id: string,
  title: string,
  description?: string | null,
};
```

You can write a resolver for a subscription that makes use of `Todo`. In your IDE, type definitions and auto-complete hints will guide you into properly using the `toSubscriptionFilter` transform utility:

```
import { util, Context, extensions } from '@aws-appsync/utils'
import { Todo } from './API'

export function request(ctx: Context) {
  return {}
}

export function response(ctx: Context) {
  const filter = util.transform.toSubscriptionFilter<Todo>({
    title: { beginsWith: 'hello' },
    description: { contains: 'created' },
  })
  extensions.setSubscriptionFilter(filter)
  return null
}
```

## Linting your bundles
<a name="using-lint-with-bundles"></a>

You can automatically lint your bundles by importing the `esbuild-plugin-eslint` plugin. You can then enable it by providing a `plugins` value that enables eslint capabilities. Below is a snippet that uses the esbuild JavaScript API in a file called `build.mjs`:

```
/* eslint-disable */
import { build } from 'esbuild'
import eslint from 'esbuild-plugin-eslint'
import glob from 'glob'
const files = await glob('src/**/*.ts')

await build({
  format: 'esm',
  target: 'esnext',
  platform: 'node',
  external: ['@aws-appsync/utils'],
  outdir: 'dist/',
  entryPoints: files,
  bundle: true,
  plugins: [eslint({ useEslintrc: true })],
})
```

## Using source maps
<a name="source-maps"></a>

You can provide an inline source map (`sourcemap`) with your JavaScript code. Source maps are useful for when you bundle JavaScript or TypeScript code and want to see references to your input source files in your logs and runtime JavaScript error messages.

Your `sourcemap` must appear at the end of your code. It is defined by a single comment line that follows the following format:

```
//# sourceMappingURL=data:application/json;base64,<base64 encoded string>
```

Here's an example:

```
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsibGliLmpzIiwgImNvZGUuanMiXSwKICAibWFwcGluZ3MiOiAiO0FBQU8sU0FBUyxRQUFRO0FBQ3RCLFNBQU87QUFDVDs7O0FDRE8sU0FBUyxRQUFRLEtBQUs7QUFDM0IsU0FBTyxNQUFNO0FBQ2Y7IiwKICAibmFtZXMiOiBbXQp9Cg==
```

Source maps can be created with esbuild. The example below shows you how to use the esbuild JavaScript API to include an inline source map when code is built and bundled:

```
/* eslint-disable */
import { build } from 'esbuild'
import eslint from 'esbuild-plugin-eslint'
import glob from 'glob'
const files = await glob('src/**/*.ts')

await build({
  sourcemap: 'inline',
  sourcesContent: false,
  
  format: 'esm',
  target: 'esnext',
  platform: 'node',
  external: ['@aws-appsync/utils'],
  outdir: 'dist/',
  entryPoints: files,
  bundle: true,
  plugins: [eslint({ useEslintrc: true })],
})
```

In particular, the `sourcemap` and `sourcesContent` options specify that a source map should be added in line at the end of each build but should not include the source content. As a convention, we recommend not including source content in your `sourcemap`. You can disable this in esbuild by setting `sources-content` to `false`.

To illustrate how source maps work, review the following example in which a resolver code references helper functions from a helper library. The code contains log statements in the resolver code and in the helper library:

**./src/default.resolver.ts** (your resolver)

```
import { Context } from '@aws-appsync/utils'
import { hello, logit } from './helper'

export function request(ctx: Context) {
  console.log('start >')
  logit('hello world', 42, true)
  console.log('< end')
  return 'test'
}

export function response(ctx: Context): boolean {
  hello()
  return ctx.prev.result
}
```

**.src/helper.ts** (a helper file)

```
export const logit = (...rest: any[]) => {
  // a special logger
  console.log('[logger]', ...rest.map((r) => `<${r}>`))
}

export const hello = () => {
  // This just returns a simple sentence, but it could do more.
  console.log('i just say hello..')
}
```

When you build and bundle the resolver file, your resolver code will include an inline source map. When your resolver runs, the following entries appear in the CloudWatch logs:

![\[CloudWatch log entries showing resolver code execution with inline source map information.\]](http://docs.aws.amazon.com/appsync/latest/devguide/images/cloudwatch-sourcemap.jpeg)


Looking at the entries in the CloudWatch log, you'll notice that the functionality of the two files have been bundled together and are running concurrently. The original file name of each file is also clearly reflected in the logs.

# Testing your resolver and function handlers in AWS AppSync
<a name="test-resolvers"></a>

You can use the `EvaluateCode` API command to remotely test your resolver and function handlers with mocked data before ever saving your code to a resolver or function. To get started with the command, make sure you have added the `appsync:evaluatecode` permission to your policy. For example:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "appsync:evaluateCode",
            "Resource": "arn:aws:appsync:us-east-1:111122223333:*"
        }
    ]
}
```

------

You can leverage the command by using the [AWS CLI](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/index.html) or [AWS SDKs](https://aws.amazon.com/tools/). For example, to test your code using the CLI, simply point to your file, provide a context, and specify the handler you want to evaluate:

```
aws appsync evaluate-code \
  --code file://code.js \
  --function request \
  --context file://context.json \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0
```

The response contains an `evaluationResult` containing the payload returned by your handler. It also contains a `logs` object that holds the list of logs that were generated by your handler during the evaluation. This makes it easy to debug your code execution and see information about your evaluation to help troubleshoot. For example:

```
{
    "evaluationResult": "{\"operation\":\"PutItem\",\"key\":{\"id\":{\"S\":\"record-id\"}},\"attributeValues\":{\"owner\":{\"S\":\"John doe\"},\"expectedVersion\":{\"N\":2},\"authorId\":{\"S\":\"Sammy Davis\"}}}",
    "logs": [
        "INFO - code.js:5:3: \"current id\" \"record-id\"",
        "INFO - code.js:9:3: \"request evaluated\""
    ]
}
```

The evaluation result can be parsed as JSON, which gives:

```
{
  "operation": "PutItem",
  "key": {
    "id": {
      "S": "record-id"
    }
  },
  "attributeValues": {
    "owner": {
      "S": "John doe"
    },
    "expectedVersion": {
      "N": 2
    },
    "authorId": {
      "S": "Sammy Davis"
    }
  }
}
```

Using the SDK, you can easily incorporate tests from your test suite to validate your code's behavior. Our example here uses the [Jest Testing Framework](https://jestjs.io/), but any testing suite works. The following snippet shows a hypothetical validation run. Note that we expect the evaluation response to be valid JSON, so we use `JSON.parse` to retrieve JSON from the string response:

```
const AWS = require('aws-sdk')
const fs = require('fs')
const client = new AWS.AppSync({ region: 'us-east-2' })
const runtime = {name:'APPSYNC_JS',runtimeVersion:'1.0.0')

test('request correctly calls DynamoDB', async () => {
  const code = fs.readFileSync('./code.js', 'utf8')
  const context = fs.readFileSync('./context.json', 'utf8')
  const contextJSON = JSON.parse(context)
  
  const response = await client.evaluateCode({ code, context, runtime, function: 'request' }).promise()
  const result = JSON.parse(response.evaluationResult)
  
  expect(result.key.id.S).toBeDefined()
  expect(result.attributeValues.firstname.S).toEqual(contextJSON.arguments.firstname)
})
```

This yields the following result:

```
Ran all test suites.
> jest

PASS ./index.test.js
✓ request correctly calls DynamoDB (543 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 totalTime: 1.511 s, estimated 2 s
```

# Migrating from VTL to JavaScript in AWS AppSync
<a name="migrating-resolvers"></a>

AWS AppSync allows you to write your business logic for your resolvers and functions using VTL or JavaScript. With both languages, you write logic that instructs the AWS AppSync service on how to interact with your data sources. With VTL, you write mapping templates that must evaluate to a valid JSON-encoded string. With JavaScript, you write request and response handlers that return objects. You don't return a JSON-encoded string.

For example, take the following VTL mapping template to get an Amazon DynamoDB item:

```
{
    "operation": "GetItem",
    "key": {
        "id": $util.dynamodb.toDynamoDBJson($ctx.args.id),
    }
}
```

The utility `$util.dynamodb.toDynamoDBJson` returns a JSON-encoded string. If `$ctx.args.id` is set to `<id>`, the template evaluates to a valid JSON-encoded string:

```
{
    "operation": "GetItem",
    "key": {
        "id": {"S": "<id>"},
    }
}
```

When working with JavaScript, you do not need to print out raw JSON-encoded strings within your code, and using a utility like `toDynamoDBJson` is not needed. An equivalent example of the mapping template above is:

```
import { util } from '@aws-appsync/utils';
export function request(ctx) {
  return {
    operation: 'GetItem',
    key: {id: util.dynamodb.toDynamoDB(ctx.args.id)}
  };
}
```

An alternative is to use `util.dynamodb.toMapValues`, which is the recommended approach to handle an object of values:

```
import { util } from '@aws-appsync/utils';
export function request(ctx) {
  return {
    operation: 'GetItem',
    key: util.dynamodb.toMapValues({ id: ctx.args.id }),
  };
}
```

This evaluates to:

```
{
  "operation": "GetItem",
  "key": {
    "id": {
      "S": "<id>"
    }
  }
}
```

**Note**  
We recommend using the DynamoDB module with DynamoDB data sources:  

```
import * as ddb from '@aws-appsync/utils/dynamodb'

export function request(ctx) {
	ddb.get({ key: { id: ctx.args.id } })
}
```

As another example, take the following mapping template to put an item in an Amazon DynamoDB data source:

```
{
    "operation" : "PutItem",
    "key" : {
        "id": $util.dynamodb.toDynamoDBJson($util.autoId()),
    },
    "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
}
```

When evaluated, this mapping template string must produce a valid JSON-encoded string. When using JavaScript, your code returns the request object directly:

```
import { util } from '@aws-appsync/utils';
export function request(ctx) {
  const { id = util.autoId(), ...values } = ctx.args;
  return {
    operation: 'PutItem',
    key: util.dynamodb.toMapValues({ id }),
    attributeValues: util.dynamodb.toMapValues(values),
  };
}
```

which evaluates to:

```
{
  "operation": "PutItem",
  "key": {
    "id": { "S": "2bff3f05-ff8c-4ed8-92b4-767e29fc4e63" }
  },
  "attributeValues": {
    "firstname": { "S": "Shaggy" },
    "age": { "N": 4 }
  }
}
```

**Note**  
We recommend using the DynamoDB module with DynamoDB data sources:  

```
import { util } from '@aws-appsync/utils'
import * as ddb from '@aws-appsync/utils/dynamodb'

export function request(ctx) {
	const { id = util.autoId(), ...item } = ctx.args
	return ddb.put({ key: { id }, item })
}
```

# Choosing between direct data source access and proxying via a Lambda data source
<a name="choosing-data-source"></a>

With AWS AppSync and the `APPSYNC_JS` runtime, you can write your own code that implements your custom business logic by using AWS AppSync functions to access your data sources. This makes it easy for you to directly interact with data sources like Amazon DynamoDB, Aurora Serverless, OpenSearch Service, HTTP APIs, and other AWS services without having to deploy additional computational services or infrastructure. AWS AppSync also makes it easy to interact with an AWS Lambda function by configuring a Lambda data source. Lambda data sources allow you to run complex business logic using AWS Lambda’s full set capabilities to resolve a GraphQL request. In most cases, an AWS AppSync function directly connected to its target data source will provide all of the functionality you need. In situations where you need to implement complex business logic that is not supported by the `APPSYNC_JS` runtime, you can use a Lambda data source as a proxy to interact with your target data source.


|  |  |  | 
| --- |--- |--- |
|  | Direct data source integration | Lambda data source as a proxy | 
| Use case | AWS AppSync functions interact directly with API data sources. | AWS AppSync functions call Lambdas that interact with API data sources. | 
| Runtime | APPSYNC\$1JS (JavaScript) | Any supported Lambda runtime | 
| Maximum size of code | 32,000 characters per AWS AppSync function | 50 MB (zipped, for direct upload) per Lambda | 
| External modules | Limited - APPSYNC\$1JS supported features only | Yes | 
| Call any AWS service | Yes - Using AWS AppSync HTTP datasource | Yes - Using AWS SDK | 
| Access to the request header | Yes | Yes | 
| Network access | No | Yes | 
| File system access | No | Yes | 
| Logging and metrics | Yes | Yes | 
| Build and test entirely within AppSync | Yes | No | 
| Cold start | No | No - With provisioned concurrency | 
| Auto-scaling | Yes - transparently by AWS AppSync | Yes - As configured in Lambda | 
| Pricing | No additional charge | Charged for Lambda usage | 

AWS AppSync functions that integrate directly with their target data source are ideal for use cases like the following:
+  Interacting with Amazon DynamoDB, Aurora Serverless, and OpenSearch Service
+  Interacting with HTTP APIs and passing incoming headers 
+  Interacting with AWS services using HTTP data sources (with AWS AppSync automatically signing requests with the provided data source role) 
+  Implementing access control before accessing data sources 
+  Implementing the filtering of retrieved data prior to fulfilling a request 
+  Implementing simple orchestration with sequential execution of AWS AppSync functions in a resolver pipeline 
+  Controlling caching and subscription connections in queries and mutations. 

AWS AppSync functions that use a Lambda data source as a proxy are ideal for use cases like the following:
+  Using a language other than JavaScript or Velocity Template Language (VTL) 
+  Adjusting and controlling CPU or memory to optimize performance 
+  Importing third-party libraries or requiring unsupported features in `APPSYNC_JS` 
+  Making multiple network requests and/or getting file system access to fulfill a query 
+  Batching requests using [ batching configuration](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-lambda-js.html). 

# AWS AppSync JavaScript resolver context object reference
<a name="resolver-context-reference-js"></a>

AWS AppSync defines a set of variables and functions for working with request and response handlers. This makes logical operations on data easier with GraphQL. This document describes those functions and provides examples.

## Accessing the `context`
<a name="accessing-the-context-js"></a>

The `context` argument of a request and response handler is an object that holds all of the contextual information for your resolver invocation. It has the following structure:

```
type Context = {
  arguments: any;
  args: any;
  identity: Identity;
  source: any;
  error?: {
    message: string;
    type: string;
  };
  stash: any;
  result: any;
  prev: any;
  request: Request;
  info: Info;
};
```

**Note**  
You will often find that the `context` object is referred to as `ctx`.

Each field in the `context` object is defined as follows:

### `context` fields
<a name="accessing-the-context-list-js"></a>

** `arguments` **  
A map that contains all GraphQL arguments for this field.

** `identity` **  
An object that contains information about the caller. For more information about the structure of this field, see [Identity](#aws-appsync-resolver-context-reference-identity-js).

** `source` **  
A map that contains the resolution of the parent field.

** `stash` **  
The stash is an object that is made available inside each resolver and function handler. The same stash object lives through a single resolver run. This means that you can use the stash to pass arbitrary data across request and response handlers and across functions in a pipeline resolver.   
You cannot delete or replace the entire stash, but you can add, update, delete, and read properties of the stash. 
You can add items to the stash by modifying one of the code examples below:  

```
//Example 1
ctx.stash.newItem = { key: "something" }

//Example 2
Object.assign(ctx.stash, {key1: value1, key2: value})
```
You can remove items from the stash by modifying the code below:  

```
delete ctx.stash.key
```

** `result` **  
A container for the results of this resolver. This field is available only to response handlers.  
For example, if you're resolving the `author` field of the following query:  

```
query {
    getPost(id: 1234) {
        postId
        title
        content
        author {
            id
            name
        }
    }
}
```
Then the full `context` variable is available when a response handler is evaluated:  

```
{
  "arguments" : {
    id: "1234"
  },
  "source": {},
  "result" : {
      "postId": "1234",
      "title": "Some title",
      "content": "Some content",
      "author": {
        "id": "5678",
        "name": "Author Name"
      }
  },
  "identity" : {
      "sourceIp" : ["x.x.x.x"],
      "userArn" : "arn:aws:iam::123456789012:user/appsync",
      "accountId" : "666666666666",
      "user" : "AIDAAAAAAAAAAAAAAAAAA"
  }
}
```

** `prev.result` **  
The result of whatever previous operation was executed in a pipeline resolver.  
If the previous operation was the pipeline resolver's request handler, then `ctx.prev.result` represents that evaluation result and is made available to the first function in the pipeline.  
If the previous operation was the first function, then `ctx.prev.result` represents the evaluation result of the first function response handler and is made available to the second function in the pipeline.  
If the previous operation was the last function, then `ctx.prev.result` represents the evaluation result of the last function and is made available to the pipeline resolver's response handler.

** `info` **  
An object that contains information about the GraphQL request. For the structure of this field, see [Info](#aws-appsync-resolver-context-reference-info-js).

### Identity
<a name="aws-appsync-resolver-context-reference-identity-js"></a>

The `identity` section contains information about the caller. The shape of this section depends on the authorization type of your AWS AppSync API.

For more information about AWS AppSync security options, see [Authorization and authentication](security-authz.md#aws-appsync-security).

** `API_KEY` authorization**  
The `identity` field isn't populated.

**`AWS_LAMBDA` authorization**  
The `identity` has the following form:  

```
type AppSyncIdentityLambda = {
  resolverContext: any;
};
```
The `identity` contains the `resolverContext` key, containing the same `resolverContext` content returned by the Lambda function authorizing the request.

** `AWS_IAM` authorization**  
The `identity` has the following form:  

```
type AppSyncIdentityIAM = {
  accountId: string;
  cognitoIdentityPoolId: string;
  cognitoIdentityId: string;
  sourceIp: string[];
  username: string;
  userArn: string;
  cognitoIdentityAuthType: string;
  cognitoIdentityAuthProvider: string;
};
```

** `AMAZON_COGNITO_USER_POOLS` authorization**  
The `identity` has the following form:  

```
type AppSyncIdentityCognito = {
  sourceIp: string[];
  username: string;
  groups: string[] | null;
  sub: string;
  issuer: string;
  claims: any;
  defaultAuthStrategy: string;
};
```

Each field is defined as follows:

** `accountId` **  
The AWS account ID of the caller.

** `claims` **  
The claims that the user has.

** `cognitoIdentityAuthType` **  
Either authenticated or unauthenticated based on the identity type.

** `cognitoIdentityAuthProvider` **  
A comma-separated list of external identity provider information used in obtaining the credentials used to sign the request.

** `cognitoIdentityId` **  
The Amazon Cognito identity ID of the caller.

** `cognitoIdentityPoolId` **  
The Amazon Cognito identity pool ID associated with the caller.

** `defaultAuthStrategy` **  
The default authorization strategy for this caller (`ALLOW` or `DENY`).

** `issuer` **  
The token issuer.

** `sourceIp` **  
The source IP address of the caller that AWS AppSync receives. If the request doesn't include the `x-forwarded-for` header, the source IP value contains only a single IP address from the TCP connection. If the request includes a `x-forwarded-for` header, the source IP is a list of IP addresses from the `x-forwarded-for` header, in addition to the IP address from the TCP connection.

** `sub` **  
The UUID of the authenticated user.

** `user` **  
The IAM user.

** `userArn` **  
The Amazon Resource Name (ARN) of the IAM user.

** `username` **  
The user name of the authenticated user. In the case of `AMAZON_COGNITO_USER_POOLS` authorization, the value of *username* is the value of attribute *cognito:username*. In the case of `AWS_IAM` authorization, the value of *username* is the value of the AWS user principal. If you're using IAM authorization with credentials vended from Amazon Cognito identity pools, we recommend that you use `cognitoIdentityId`.

### Access request headers
<a name="aws-appsync-resolver-context-reference-util-js"></a>

AWS AppSync supports passing custom headers from clients and accessing them in your GraphQL resolvers by using `ctx.request.headers`. You can then use the header values for actions such as inserting data into a data source or authorization checks. You can use single or multiple request headers using `$curl` with an API key from the command line, as shown in the following examples:

**Single header example** 

Suppose you set a header of `custom` with a value of `nadia` like the following:

```
curl -XPOST -H "Content-Type:application/graphql" -H "custom:nadia" -H "x-api-key:<API-KEY-VALUE>" -d '{"query":"mutation { createEvent(name: \"demo\", when: \"Next Friday!\", where: \"Here!\") {id name when where description}}"}' https://<ENDPOINT>/graphql
```

This could then be accessed with `ctx.request.headers.custom`. For example, it might be in the following code for DynamoDB:

```
"custom": util.dynamodb.toDynamoDB(ctx.request.headers.custom)
```

**Multiple header example** 

You can also pass multiple headers in a single request and access these in the resolver handler. For example, if the `custom` header is set with two values:

```
curl -XPOST -H "Content-Type:application/graphql" -H "custom:bailey" -H "custom:nadia" -H "x-api-key:<API-KEY-VALUE>" -d '{"query":"mutation { createEvent(name: \"demo\", when: \"Next Friday!\", where: \"Here!\") {id name when where description}}"}' https://<ENDPOINT>/graphql
```

You could then access these as an array, such as `ctx.request.headers.custom[1]`.

**Note**  
AWS AppSync doesn't expose the cookie header in `ctx.request.headers`.

### Access the request custom domain name
<a name="aws-access-requested-custom-domain-names-js"></a>

AWS AppSync supports configuring a custom domain that you can use to access your GraphQL and real-time endpoints for your APIs. When making a request with a custom domain name, you can get the domain name using `ctx.request.domainName`.

When using the default GraphQL endpoint domain name, the value is `null`.

### Info
<a name="aws-appsync-resolver-context-reference-info-js"></a>

The `info` section contains information about the GraphQL request. This section has the following form:

```
type Info = {
  fieldName: string;
  parentTypeName: string;
  variables: any;
  selectionSetList: string[];
  selectionSetGraphQL: string;
};
```

Each field is defined as follows:

** `fieldName` **  
The name of the field that is currently being resolved.

** `parentTypeName` **  
The name of the parent type for the field that is currently being resolved.

** `variables` **  
A map which holds all variables that are passed into the GraphQL request.

** `selectionSetList` **  
A list representation of the fields in the GraphQL selection set. Fields that are aliased are referenced only by the alias name, not the field name. The following example shows this in detail.

** `selectionSetGraphQL` **  
A string representation of the selection set, formatted as GraphQL schema definition language (SDL). Although fragments aren't merged into the selection set, inline fragments are preserved, as shown in the following example.

**Note**  
`JSON.stringify` will not include `selectionSetGraphQL` and `selectionSetList` in the string serialization. You must reference these properties directly.

For example, if you are resolving the `getPost` field of the following query:

```
query {
  getPost(id: $postId) {
    postId
    title
    secondTitle: title
    content
    author(id: $authorId) {
      authorId
      name
    }
    secondAuthor(id: "789") {
      authorId
    }
    ... on Post {
      inlineFrag: comments: {
        id
      }
    }
    ... postFrag
  }
}

fragment postFrag on Post {
  postFrag: comments: {
    id
  }
}
```

Then the full `ctx.info` variable that is available when processing a handler might be:

```
{
  "fieldName": "getPost",
  "parentTypeName": "Query",
  "variables": {
    "postId": "123",
    "authorId": "456"
  },
  "selectionSetList": [
    "postId",
    "title",
    "secondTitle"
    "content",
    "author",
    "author/authorId",
    "author/name",
    "secondAuthor",
    "secondAuthor/authorId",
    "inlineFragComments",
    "inlineFragComments/id",
    "postFragComments",
    "postFragComments/id"
  ],
  "selectionSetGraphQL": "{\n  getPost(id: $postId) {\n    postId\n    title\n    secondTitle: title\n    content\n    author(id: $authorId) {\n      authorId\n      name\n    }\n    secondAuthor(id: \"789\") {\n      authorId\n    }\n    ... on Post {\n      inlineFrag: comments {\n        id\n      }\n    }\n    ... postFrag\n  }\n}"
}
```

`selectionSetList` exposes only fields that belong to the current type. If the current type is an interface or union, only selected fields that belong to the interface are exposed. For example, given the following schema:

```
type Query {
    node(id: ID!): Node
}

interface Node {
    id: ID
}

type Post implements Node {
    id: ID
    title: String
    author: String
}

type Blog implements Node {
    id: ID
    title: String
    category: String
}
```

And the following query:

```
query {
    node(id: "post1") {
        id
        ... on Post {
            title
        }

        ... on Blog {
            title
        }
    }
}
```

When calling `ctx.info.selectionSetList` at the `Query.node` field resolution, only `id` is exposed:

```
"selectionSetList": [
    "id"
]
```

# AWS AppSync JavaScript runtime features for resolvers and functions
<a name="resolver-util-reference-js"></a>

The `APPSYNC_JS` runtime environment provides functionality similar to [ECMAScript (ES) version 6.0](https://262.ecma-international.org/6.0/). It supports a subset of its features and provides some additional methods (utilities) that are not part of the ES specifications. The following topics list all the supported language features:
+  [ Supported runtime features ](https://docs.aws.amazon.com/appsync/latest/devguide/supported-features.html) - Learn more about supported core features, primitive objects, built-in objects and functions, etc.
+  [ Built-in utilities ](https://docs.aws.amazon.com/appsync/latest/devguide/built-in-util-js.html) - The util variable contains general utility methods to help you work with data. Unless otherwise specified, all utilities use the UTF-8 character set.
+  [ Built-in modules ](https://docs.aws.amazon.com/appsync/latest/devguide/built-in-modules-js.html) - Learn more about how built-in modules can help write JavaScript resolvers and functions.
+  [ Runtime utilities ](https://docs.aws.amazon.com/appsync/latest/devguide/runtime-utils-js.html) - The runtime library provides utilities to control or modify the runtime properties of your resolvers and functions.
+  [ Time helpers in util.time ](https://docs.aws.amazon.com/appsync/latest/devguide/time-helpers-in-util-time-js.html) - The util.time variable contains datetime methods to help generate timestamps, convert between datetime formats, and parse datetime strings. The syntax for datetime formats is based on [DateTimeFormatter](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html), which you can reference for further documentation.
+  [ DynamoDB helpers in util.dynamodb ](https://docs.aws.amazon.com/appsync/latest/devguide/dynamodb-helpers-in-util-dynamodb-js.html) - util.dynamodb contains helper methods that make it easier to write and read data to Amazon DynamoDB, such as automatic type mapping and formatting.
+  [ HTTP helpers in util.http ](https://docs.aws.amazon.com/appsync/latest/devguide/http-helpers-in-utils-http-js.html) - The util.http utility provides helper methods that you can use to manage HTTP request parameters and to add response headers.
+  [ Transformation helpers in util.transform ](https://docs.aws.amazon.com/appsync/latest/devguide/transformation-helpers-in-utils-transform-js.html) - util.transform contains helper methods that make it easier to perform complex operations against data sources.
+  [ String helpers in util.str ](https://docs.aws.amazon.com/appsync/latest/devguide/str-helpers-in-util-str-js.html) - util.str contains methods to help with common String operations.
+  [ Extensions ](https://docs.aws.amazon.com/appsync/latest/devguide/extensions-js.html) - extensions contains a set of methods to make additional actions within your resolvers.
+  [ XML helpers in util.xml ](https://docs.aws.amazon.com/appsync/latest/devguide/xml-helpers-in-util-xml-js.html) - util.xml contains methods to help with XML string conversion.

**Note**  
Currently, this reference only applies to runtime version **1.0.0**.

# Supported runtime features
<a name="supported-features"></a>

The sections below describe the supported feature set of the APPSYNC\$1JS runtime.

## Core features
<a name="core-features"></a>

The following core features are supported.

------
#### [ Types ]

The following types are supported:
+ numbers
+ strings
+ booleans
+ objects
+ arrays
+ functions

------
#### [ Operators ]

Operators are supported, including:
+ standard math operators (`+`, `-`, `/`, `%`, `*`, etc.)
+ nullish coalescing operator (`??`)
+ Optional chaining (`?.`)
+ bitwise operators
+ `void` and `typeof` operators
+ spread operators (`...`)

The following operators are not supported:
+ unary operators (`++`, `--`, and `~`)
+ `in` operator
**Note**  
Use the `Object.hasOwn` operator to check if the specified property is in the specified object.

------
#### [ Statements ]

The following statements are supported:
+ `const`
+ `let`
+ `var`
+ `break`
+ `else`
+ `for-in`
+ `for-of` 
+ `if`
+ `return`
+ `switch`
+ spread syntax

The following are not supported:
+ `catch`
+ `continue`
+ `do-while`
+ `finally`
+ `for(initialization; condition; afterthought)`
**Note**  
The exceptions are `for-in` and `for-of` expressions, which are supported.
+ `throw`
+ `try`
+ `while`
+ labeled statements

------
#### [ Literals ]

The following ES 6 [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) are supported:
+ Multi-line strings
+ Expression interpolation
+ Nesting templates

------
#### [ Functions ]

The following function syntax is supported:
+ Function declarations are supported.
+ ES 6 arrow functions are supported.
+ ES 6 rest parameter syntax is supported.

------
#### [ Strict mode ]

Functions operate in strict mode by default, so you don’t need to add a `use_strict` statement in your function code. This cannot be changed.

------

## Primitive objects
<a name="primitive-objects"></a>

The following primitive objects of ES and their functions are supported.

------
#### [ Object ]

The following objects are supported:
+ `Object.assign()`
+ `Object.entries()` 
+ `Object.hasOwn()`
+ `Object.keys()` 
+ `Object.values()`
+ `delete` 

------
#### [ String ]

The following strings are supported:
+  `String.prototype.length()` 
+  `String.prototype.charAt()` 
+  `String.prototype.concat()` 
+  `String.prototype.endsWith()` 
+  `String.prototype.indexOf()` 
+  `String.prototype.lastIndexOf()` 
+  `String.raw()` 
+  `String.prototype.replace()`
**Note**  
Regular expressions are not supported.   
However, Java-styled regular expression constructs are supported in the provided parameter. For more information see [Pattern](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html).
+ `String.prototype.replaceAll()`
**Note**  
Regular expressions are not supported.  
However, Java-styled regular expression constructs are supported in the provided parameter. For more information see [Pattern](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html).
+  `String.prototype.slice()` 
+  `String.prototype.split()` 
+  `String.prototype.startsWith()` 
+  `String.prototype.toLowerCase()` 
+  `String.prototype.toUpperCase()` 
+  `String.prototype.trim()` 
+  `String.prototype.trimEnd()` 
+  `String.prototype.trimStart()` 

------
#### [ Number ]

The following numbers are supported:
+  `Number.isFinite` 
+  `Number.isNaN` 

------

## Built-in objects and functions
<a name="built-in-objects-functions"></a>

The following functions and objects are supported.

------
#### [ Math ]

The following math functions are supported:
+  `Math.random()` 
+  `Math.min()` 
+  `Math.max()` 
+  `Math.round()` 
+  `Math.floor()` 
+  `Math.ceil()` 

------
#### [ Array ]

The following array methods are supported:
+ `Array.prototype.length` 
+ `Array.prototype.concat()` 
+ `Array.prototype.fill()` 
+ `Array.prototype.flat()` 
+ `Array.prototype.indexOf()` 
+ `Array.prototype.join()` 
+ `Array.prototype.lastIndexOf()` 
+ `Array.prototype.pop()` 
+ `Array.prototype.push()` 
+ `Array.prototype.reverse()` 
+ `Array.prototype.shift()` 
+ `Array.prototype.slice()` 
+ `Array.prototype.sort()`
**Note**  
`Array.prototype.sort()` doesn't support arguments.
+ `Array.prototype.splice()` 
+ `Array.prototype.unshift()`
+ `Array.prototype.forEach()`
+ `Array.prototype.map()`
+ `Array.prototype.flatMap()`
+ `Array.prototype.filter()`
+ `Array.prototype.reduce()`
+ `Array.prototype.reduceRight()`
+ `Array.prototype.find()`
+ `Array.prototype.some()`
+ `Array.prototype.every()`
+ `Array.prototype.findIndex()`
+ `Array.prototype.findLast()`
+ `Array.prototype.findLastIndex()`
+ `delete` 

------
#### [ Console ]

The console object is available for debugging. During live query execution, console log/error statements are sent to Amazon CloudWatch Logs (if logging is enabled). During code evaluation with `evaluateCode`, log statements are returned in the command response.
+ `console.error()`
+ `console.log()`

------
#### [ Function ]
+ The `apply`, `bind`, and `call` methods not are supported.
+ Function constructors are not supported.
+ Passing a function as an argument is not supported.
+ Recursive function calls are not supported.

------
#### [ JSON ]

The following JSON methods are supported:
+ `JSON.parse()`
**Note**  
Returns a blank string if the parsed string is not valid JSON.
+ `JSON.stringify()`

------
#### [ Promises ]

Async processes are not supported, and promises are not supported.

**Note**  
Network and file system access is not supported within the `APPSYNC_JS` runtime in AWS AppSync. AWS AppSync handles all I/O operations based on the requests made by the AWS AppSync resolver or AWS AppSync function.

------

## Globals
<a name="globals"></a>

The following global constants are supported:
+  `NaN` 
+  `Infinity` 
+  `undefined`
+ [https://docs.aws.amazon.com/appsync/latest/devguide/built-in-util-js.html](https://docs.aws.amazon.com/appsync/latest/devguide/built-in-util-js.html)
+ [https://docs.aws.amazon.com/appsync/latest/devguide/extensions-js.html](https://docs.aws.amazon.com/appsync/latest/devguide/extensions-js.html)
+ `runtime`

## Error types
<a name="error-types"></a>

Throwing errors with `throw` is not supported. You can return an error by using `util.error()` function. You can include an error in your GraphQL response by using the `util.appendError` function.

For more information, see [Error utils](https://docs.aws.amazon.com/appsync/latest/devguide/built-in-util-js.html#utility-helpers-in-error-js).

# Built-in utilities
<a name="built-in-util-js"></a>

The `util` variable contains general utility methods to help you work with data. Unless otherwise specified, all utilities use the UTF-8 character set.

## Encoding utils
<a name="utility-helpers-in-encoding"></a>

### Encoding utils list
<a name="utility-helpers-in-encoding-list-js"></a>

 **`util.urlEncode(String)`**  
Returns the input string as an `application/x-www-form-urlencoded` encoded string.

 **`util.urlDecode(String)`**  
Decodes an `application/x-www-form-urlencoded` encoded string back to its non-encoded form.

**`util.base64Encode(string) : string`**  
Encodes the input into a base64-encoded string.

**`util.base64Decode(string) : string`**  
Decodes the data from a base64-encoded string.

## ID generation utils
<a name="utility-helpers-in-id-gen-js"></a>

### ID generation utils list
<a name="utility-helpers-in-id-gen-list-js"></a>

 **`util.autoId()`**  
Returns a 128-bit randomly generated UUID.

**`util.autoUlid()`**  
Returns a 128-bit randomly generated ULID (Universally Unique Lexicographically Sortable Identifier).

**`util.autoKsuid()`**  
Returns a 128-bit randomly generated KSUID (K-Sortable Unique Identifier) base62 encoded as a String with a length of 27.

## Error utils
<a name="utility-helpers-in-error-js"></a>

### Error utils list
<a name="utility-helpers-in-error-list-js"></a>

 **`util.error(String, String?, Object?, Object?)`**  
Throws a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Additionally, an `errorType` field, a `data` field, and an `errorInfo` field can be specified. The `data` value will be added to the corresponding `error` block inside `errors` in the GraphQL response.  
`data` will be filtered based on the query selection set. The `errorInfo` value will be added to the corresponding `error` block inside `errors` in the GraphQL response.  
`errorInfo` will **not** be filtered based on the query selection set.

 **`util.appendError(String, String?, Object?, Object?)`**  
Appends a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Additionally, an `errorType` field, a `data` field, and an `errorInfo` field can be specified. Unlike `util.error(String, String?, Object?, Object?)`, the template evaluation will not be interrupted, so that data can be returned to the caller. The `data` value will be added to the corresponding `error` block inside `errors` in the GraphQL response.  
`data` will be filtered based on the query selection set. The `errorInfo` value will be added to the corresponding `error` block inside `errors` in the GraphQL response.  
`errorInfo` will **not** be filtered based on the query selection set.

## Type and pattern matching utils
<a name="utility-helpers-in-patterns-js"></a>

### Type and pattern matching utils list
<a name="utility-helpers-in-patterns-js-list"></a>

**`util.matches(String, String) : Boolean`**  
Returns true if the specified pattern in the first argument matches the supplied data in the second argument. The pattern must be a regular expression such as `util.matches("a*b", "aaaaab")`. The functionality is based on [Pattern](https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html), which you can reference for further documentation.

 **`util.authType()`**   
Returns a String describing the multi-auth type being used by a request, returning back either "IAM Authorization", "User Pool Authorization", "Open ID Connect Authorization", or "API Key Authorization".

## Return value behavior utils
<a name="utility-helpers-in-cloudwatch-logs-list-js"></a>

### Return value behavior utils list
<a name="utility-helpers-in-behavior-list-js"></a>

 **`util.escapeJavaScript(String)`**  
Returns the input string as a JavaScript escaped string.

## Resolver authorization utils
<a name="utility-helpers-in-resolver-auth-js"></a>

### Resolver authorization utils list
<a name="utility-helpers-in-resolver-auth-list-js"></a>

 **`util.unauthorized()`**  
Throws `Unauthorized` for the field being resolved. Use this in request or response mapping templates to determine whether to allow the caller to resolve the field.

# Built-in modules
<a name="built-in-modules-js"></a>

Modules are a part of the `APPSYNC_JS` runtime and provide utilities to help write JavaScript resolvers and functions. For samples and examples, see the [aws-appsync-resolver-samples](https://github.com/aws-samples/aws-appsync-resolver-samples) GitHub repository.

## DynamoDB module functions
<a name="built-in-ddb-modules"></a>

DynamoDB module functions provide an enhanced experience when interacting with DynamoDB data sources. You can make requests toward your DynamoDB data sources using the functions and without adding type mapping. 

Modules are imported using `@aws-appsync/utils/dynamodb`:

```
// Modules are imported using @aws-appsync/utils/dynamodb
import * as ddb from '@aws-appsync/utils/dynamodb';
```

### Functions
<a name="built-in-ddb-modules-functions"></a>

#### Functions list
<a name="built-in-ddb-modules-functions-list"></a>

 **` get<T>(payload: GetInput): DynamoDBGetItemRequest`**  
See [Inputs](#built-in-ddb-modules-inputs) for information about GetInput.
Generates a `DynamoDBGetItemRequest` object to make a [GetItem](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-getitem) request to DynamoDB.  

```
import { get } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	return get({ key: { id: ctx.args.id } });
}
```

 **`put<T>(payload): DynamoDBPutItemRequest`**  
Generates a `DynamoDBPutItemRequest` object to make a [PutItem](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-putitem) request to DynamoDB.  

```
import * as ddb from '@aws-appsync/utils/dynamodb'

export function request(ctx) {
	return ddb.put({ key: { id: util.autoId() }, item: ctx.args });
}
```

**`remove<T>(payload): DynamoDBDeleteItemRequest`**  
Generates a `DynamoDBDeleteItemRequest` object to make a [DeleteItem](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-deleteitem) request to DynamoDB.  

```
import * as ddb from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	return ddb.remove({ key: { id: ctx.args.id } });
}
```

**`scan<T>(payload): DynamoDBScanRequest`**  
Generates a `DynamoDBScanRequest` to make a [Scan](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-scan) request to DynamoDB.  

```
import * as ddb from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const { limit = 10, nextToken } = ctx.args;
	return ddb.scan({ limit, nextToken });
}
```

**`sync<T>(payload): DynamoDBSyncRequest`**  
Generates a `DynamoDBSyncRequest` object to make a [Sync](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-sync) request. The request only receives the data altered since the last query (delta updates). Requests can only be made to versioned DynamoDB data sources.  

```
import * as ddb from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const { limit = 10, nextToken, lastSync } = ctx.args;
	return ddb.sync({ limit, nextToken, lastSync });
}
```

**`update<T>(payload): DynamoDBUpdateItemRequest`**  
Generates a `DynamoDBUpdateItemRequest` object to make an [UpdateItem](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-updateitem) request to DynamoDB.

### Operations
<a name="built-in-ddb-modules-operations"></a>

Operation helpers allow you to take specific actions on parts of your data during updates. To get started, import `operations` from `@aws-appsync/utils/dynamodb`:

```
// Modules are imported using operations
import {operations} from '@aws-appsync/utils/dynamodb';
```

#### Operations list
<a name="built-in-ddb-modules-operations-list"></a>

 **`add<T>(payload)`**  
A helper function that adds a new attribute item when updating DynamoDB.  
**Example**  
To add an address (street, city, and zip code) to an existing DynamoDB item using the ID value:  

```
import { update, operations } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const updateObj = {
		address: operations.add({
			street1: '123 Main St',
			city: 'New York',
			zip: '10001',
		}),
	};
	return update({ key: { id: 1 }, update: updateObj });
}
```

**`append <T>(payload)`**  
A helper function that appends a payload to the existing list in DynamoDB.  
**Example**  
To append newly added friend IDs (`newFriendIds`) to an existing friends list (`friendsIds`) during an update:  

```
import { update, operations } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const newFriendIds = [101, 104, 111];
	const updateObj = {
		friendsIds: operations.append(newFriendIds),
	};
	return update({ key: { id: 1 }, update: updateObj });
}
```

**`decrement (by?)`**  
A helper function that decrements the existing attribute value in the item when updating DynamoDB.  
**Example**  
To decrement a friends counter (`friendsCount`) by 10:  

```
import { update, operations } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const updateObj = {
		friendsCount: operations.decrement(10),
	};
	return update({ key: { id: 1 }, update: updateObj });
}
```

**`increment (by?)`**  
A helper function that increments the existing attribute value in the item when updating DynamoDB.  
**Example**  
To increment a friends counter (`friendsCount`) by 10:  

```
import { update, operations } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const updateObj = {
		friendsCount: operations.increment(10),
	};
	return update({ key: { id: 1 }, update: updateObj });
}
```

**`prepend <T>(payload)`**  
A helper function that prepends to the existing list in DynamoDB.  
**Example**  
To prepend newly added friend IDs (`newFriendIds`) to an existing friends list (`friendsIds`) during an update:  

```
import { update, operations } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const newFriendIds = [101, 104, 111];
	const updateObj = {
		friendsIds: operations.prepend(newFriendIds),
	};
	return update({ key: { id: 1 }, update: updateObj });
}
```

**`replace <T>(payload)`**  
A helper function that replaces an existing attribute when updating an item in DynamoDB. This is useful for when you want to update the entire object or subobject in the attribute and not just the keys in the payload.  
**Example**  
To replace an address (street, city, and zip code) in an `info` object:  

```
import { update, operations } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const updateObj = {
		info: {
			address: operations.replace({
				street1: '123 Main St',
				city: 'New York',
				zip: '10001',
			}),
		},
	};
	return update({ key: { id: 1 }, update: updateObj });
}
```

**`updateListItem <T>(payload, index)`**  
A helper function that replaces an item in a list.  
**Example**  
In the scope of the update (`newFriendIds`), this example used `updateListItem` to update the ID values of the second item (index: `1`, new ID: `102`) and third item (index: `2`, new ID: `112`) in a list (`friendsIds`).  

```
import { update, operations as ops } from '@aws-appsync/utils/dynamodb';

export function request(ctx) {
	const newFriendIds = [
		ops.updateListItem('102', 1), ops.updateListItem('112', 2)
	];
	const updateObj = { friendsIds: newFriendIds };
	return update({ key: { id: 1 }, update: updateObj });
}
```

### Inputs
<a name="built-in-ddb-modules-inputs"></a>

#### Inputs list
<a name="built-in-ddb-modules-inputs-list"></a>

 **`Type GetInput<T>`**  

```
GetInput<T>: { 
    consistentRead?: boolean; 
    key: DynamoDBKey<T>; 
}
```
**Type Declaration**  
+ `consistentRead?: boolean` (optional)

  An optional boolean to specify whether you want to perform a strongly consistent read with DynamoDB.
+ `key: DynamoDBKey<T>` (required)

  A required parameter that specifies the key of the item in DynamoDB. DynamoDB items may have a single hash key or hash and sort keys.

**`Type PutInput<T>`**  

```
PutInput<T>: { 
    _version?: number; 
    condition?: DynamoDBFilterObject<T> | null; 
    customPartitionKey?: string; 
    item: Partial<T>; 
    key: DynamoDBKey<T>; 
    populateIndexFields?: boolean; 
}
```
**Type Declaration**  
+ `_version?: number` (optional)
+ `condition?: DynamoDBFilterObject<T> | null` (optional)

  When you put an object in a DynamoDB table, you can optionally specify a conditional expression that controls whether the request should succeed or not based on the state of the object already in DynamoDB before the operation is performed.
+ `customPartitionKey?: string` (optional)

  When enabled, this string value modifies the format of the `ds_sk` and `ds_pk` records used by the delta sync table when versioning has been enabled. When enabled, the processing of the `populateIndexFields` entry is also enabled. 
+ `item: Partial<T>` (required)

  The rest of the attributes of the item to be placed into DynamoDB.
+ `key: DynamoDBKey<T>` (required)

  A required parameter that specifies the key of the item in DynamoDB on which the put will be performed. DynamoDB items may have a single hash key or hash and sort keys.
+ `populateIndexFields?: boolean` (optional)

  A boolean value that, when enabled along with the `customPartitionKey`, creates new entries for each record in the delta sync table, specifically in the `gsi_ds_pk` and `gsi_ds_sk` columns. For more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*.

**`Type QueryInput<T>`**  

```
QueryInput<T>: ScanInput<T> & { 
    query: DynamoDBKeyCondition<Required<T>>; 
}
```
**Type Declaration**  
+ `query: DynamoDBKeyCondition<Required<T>>` (required)

  Specifies a key condition that describes items to query. For a given index, the condition for a partition key should be an equality and the sort key a comparison or a `beginsWith` (when it's a string). Only number and string types are supported for partition and sort keys.

  **Example**

  Take the `User` type below:

  ```
  type User = {
    id: string;
    name: string;
    age: number;
    isVerified: boolean;
    friendsIds: string[] 
  }
  ```

  The query can only include the following fields: `id`, `name`, and `age`:

  ```
  const query: QueryInput<User> = {
      name: { eq: 'John' },
      age: { gt: 20 },
  }
  ```

**`Type RemoveInput<T>`**  

```
RemoveInput<T>: { 
    _version?: number; 
    condition?: DynamoDBFilterObject<T>; 
    customPartitionKey?: string; 
    key: DynamoDBKey<T>; 
    populateIndexFields?: boolean; 
}
```
**Type Declaration**  
+ `_version?: number` (optional)
+ `condition?: DynamoDBFilterObject<T>` (optional)

  When you remove an object in DynamoDB, you can optionally specify a conditional expression that controls whether the request should succeed or not based on the state of the object already in DynamoDB before the operation is performed.

  **Example**

  The following example is a `DeleteItem` expression containing a condition that allows the operation succeed only if the owner of the document matches the user making the request.

  ```
  type Task = {
    id: string;
    title: string;
    description: string;
    owner: string;
    isComplete: boolean;
  }
  const condition: DynamoDBFilterObject<Task> = {
    owner: { eq: 'XXXXXXXXXXXXXXXX' },
  }
  
  remove<Task>({
     key: {
       id: 'XXXXXXXXXXXXXXXX',
    },
    condition,
  });
  ```
+ `customPartitionKey?: string` (optional)

  When enabled, the `customPartitionKey` value modifies the format of the `ds_sk` and `ds_pk` records used by the delta sync table when versioning has been enabled. When enabled, the processing of the `populateIndexFields` entry is also enabled. 
+ `key: DynamoDBKey<T>` (required)

  A required parameter that specifies the key of the item in DynamoDB that is being removed. DynamoDB items may have a single hash key or hash and sort keys.

  **Example**

  If a `User` only has the hash key with a user `id`, then the key would look like this:

  ```
  type User = {
  	id: number
  	name: string
  	age: number
  	isVerified: boolean
  }
  const key: DynamoDBKey<User> = {
  	id: 1,
  }
  ```

  If the table user has a hash key (`id`) and sort key (`name`), then the key would look like this:

  ```
  type User = {
  	id: number
  	name: string
  	age: number
  	isVerified: boolean
  	friendsIds: string[]
  }
  
  const key: DynamoDBKey<User> = {
  	id: 1,
  	name: 'XXXXXXXXXX',
  }
  ```
+ `populateIndexFields?: boolean` (optional)

  A boolean value that, when enabled along with the `customPartitionKey`, creates new entries for each record in the delta sync table, specifically in the `gsi_ds_pk` and `gsi_ds_sk` columns.

**`Type ScanInput<T>`**  

```
ScanInput<T>: { 
    consistentRead?: boolean | null; 
    filter?: DynamoDBFilterObject<T> | null; 
    index?: string | null; 
    limit?: number | null; 
    nextToken?: string | null; 
    scanIndexForward?: boolean | null; 
    segment?: number; 
    select?: DynamoDBSelectAttributes; 
    totalSegments?: number; 
}
```
**Type Declaration**  
+ `consistentRead?: boolean | null` (optional)

  An optional boolean to indicate consistent reads when querying DynamoDB. The default value is `false`.
+ `filter?: DynamoDBFilterObject<T> | null` (optional)

  An optional filter to apply to the results after retrieving it from the table.
+ `index?: string | null` (optional)

  An optional name of the index to scan.
+ `limit?: number | null` (optional)

  An optional max number of results to return.
+ `nextToken?: string | null` (optional)

  An optional pagination token to continue a previous query. This would have been obtained from a previous query.
+ `scanIndexForward?: boolean | null` (optional)

  An optional boolean to indicate whether the query is performed in ascending or descending order. By default, this value is set to `true`.
+ `segment?: number` (optional)
+ `select?: DynamoDBSelectAttributes` (optional)

  Attributes to return from DynamoDB. By default, the AWS AppSync DynamoDB resolver only returns attributes that are projected into the index. The supported values are:
  + `ALL_ATTRIBUTES`

    Returns all the item attributes from the specified table or index. If you query a local secondary index, DynamoDB fetches the entire item from the parent table for each matching item in the index. If the index is configured to project all item attributes, all of the data can be obtained from the local secondary index and no fetching is required.
  + `ALL_PROJECTED_ATTRIBUTES`

    Returns all attributes that have been projected into the index. If the index is configured to project all attributes, this return value is equivalent to specifying `ALL_ATTRIBUTES`.
  + `SPECIFIC_ATTRIBUTES`

    Returns only the attributes listed in `ProjectionExpression`. This return value is equivalent to specifying `ProjectionExpression` without specifying any value for `AttributesToGet`.
+ `totalSegments?: number` (optional)

**`Type DynamoDBSyncInput<T>`**  

```
DynamoDBSyncInput<T>: { 
    basePartitionKey?: string; 
    deltaIndexName?: string; 
    filter?: DynamoDBFilterObject<T> | null; 
    lastSync?: number; 
    limit?: number | null; 
    nextToken?: string | null; 
}
```
**Type Declaration**  
+ `basePartitionKey?: string` (optional)

  The partition key of the base table to be used when performing a Sync operation. This field allows a Sync operation to be performed when the table utilizes a custom partition key.
+ `deltaIndexName?: string` (optional)

  The index used for the Sync operation. This index is required to enable a Sync operation on the whole delta store table when the table uses a custom partition key. The Sync operation will be performed on the GSI (created on `gsi_ds_pk` and `gsi_ds_sk`).
+ `filter?: DynamoDBFilterObject<T> | null` (optional)

  An optional filter to apply to the results after retrieving it from the table.
+ `lastSync?: number` (optional)

  The moment, in epoch milliseconds, at which the last successful Sync operation started. If specified, only items that have changed after `lastSync` are returned. This field should only be populated after retrieving all pages from an initial Sync operation. If omitted, results from the base table will be returned. Otherwise, results from the delta table will be returned.
+ `limit?: number | null` (optional)

  An optional maximum number of items to evaluate at a single time. If omitted, the default limit will be set to `100` items. The maximum value for this field is `1000` items.
+ `nextToken?: string | null` (optional)

**`Type DynamoDBUpdateInput<T>`**  

```
DynamoDBUpdateInput<T>: { 
    _version?: number; 
    condition?: DynamoDBFilterObject<T>; 
    customPartitionKey?: string; 
    key: DynamoDBKey<T>; 
    populateIndexFields?: boolean; 
    update: DynamoDBUpdateObject<T>; 
}
```
**Type Declaration**  
+ `_version?: number` (optional)
+ `condition?: DynamoDBFilterObject<T>` (optional)

  When you update an object in DynamoDB, you can optionally specify a conditional expression that controls whether the request should succeed or not based on the state of the object already in DynamoDB before the operation is performed.
+ `customPartitionKey?: string` (optional)

  When enabled, the `customPartitionKey` value modifies the format of the `ds_sk` and `ds_pk` records used by the delta sync table when versioning has been enabled. When enabled, the processing of the `populateIndexFields` entry is also enabled. 
+ `key: DynamoDBKey<T>` (required)

  A required parameter that specifies the key of the item in DynamoDB that is being updated. DynamoDB items may have a single hash key or hash and sort keys.
+ `populateIndexFields?: boolean` (optional)

  A boolean value that, when enabled along with the `customPartitionKey`, creates new entries for each record in the delta sync table, specifically in the `gsi_ds_pk` and `gsi_ds_sk` columns. 
+ `update: DynamoDBUpdateObject<T>`

  An object that specifies the attributes to be updated along with the new values for them. The update object can be used with `add`, `remove`, `replace`, `increment`, `decrement`, `append`, `prepend`, `updateListItem`.

## Amazon RDS module functions
<a name="built-in-rds-modules"></a>

Amazon RDS module functions provide an enhanced experience when interacting with databases configured with the Amazon RDS Data API. The module is imported using `@aws-appsync/utils/rds`: 

```
import * as rds from '@aws-appsync/utils/rds';
```

Functions can also be imported individually. For instance, the import below uses `sql`:

```
import { sql } from '@aws-appsync/utils/rds';
```

### Functions
<a name="built-in-rds-modules-functions"></a>

You can use the AWS AppSync RDS module's utility helpers to interact with your database.

#### Select
<a name="built-in-rds-modules-functions-select"></a>

The `select` utility creates a `SELECT` statement to query your relational database. 

**Basic use**

In its basic form, you can specify the table you want to query:

```
import { select, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {

    // Generates statement: 
    // "SELECT * FROM "persons"
    return createPgStatement(select({table: 'persons'}));
}
```

Note that you can also specify the schema in your table identifier:

```
import { select, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {

    // Generates statement:
    // SELECT * FROM "private"."persons"
    return createPgStatement(select({table: 'private.persons'}));
}
```

**Specifying columns**

You can specify columns with the `columns` property. If this isn't set to a value, it defaults to `*`:

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name']
    }));
}
```

You can specify a column's table as well:

```
export function request(ctx) {

    // Generates statement: 
    // SELECT "id", "persons"."name"
    // FROM "persons"
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'persons.name']
    }));
}
```

**Limits and offsets**

You can apply `limit` and `offset` to the query:

```
export function request(ctx) {

    // Generates statement: 
    // SELECT "id", "name"
    // FROM "persons"
    // LIMIT :limit
    // OFFSET :offset
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        limit: 10,
        offset: 40
    }));
}
```

**Order By**

You can sort your results with the `orderBy` property. Provide an array of objects specifying the column and an optional `dir` property:

```
export function request(ctx) {

    // Generates statement: 
    // SELECT "id", "name" FROM "persons"
    // ORDER BY "name", "id" DESC
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        orderBy: [{column: 'name'}, {column: 'id', dir: 'DESC'}]
    }));
}
```

**Filters**

You can build filters by using the special condition object:

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE "name" = :NAME
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: {name: {eq: 'Stephane'}}
    }));
}
```

You can also combine filters:

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE "name" = :NAME and "id" > :ID
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: {name: {eq: 'Stephane'}, id: {gt: 10}}
    }));
}
```

You can also create `OR` statements:

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE "name" = :NAME OR "id" > :ID
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: { or: [
            { name: { eq: 'Stephane'} },
            { id: { gt: 10 } }
        ]}
    }));
}
```

You can also negate a condition with `not`:

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE NOT ("name" = :NAME AND "id" > :ID)
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: { not: [
            { name: { eq: 'Stephane'} },
            { id: { gt: 10 } }
        ]}
    }));
}
```

You can also use the following operators to compare values:


| 
| 
| Operator | Description | Possible value types | 
| --- |--- |--- |
| eq | Equal | number, string, boolean | 
| ne | Not equal | number, string, boolean | 
| le | Less than or equal | number, string | 
| lt | Less than | number, string | 
| ge | Greater than or equal | number, string | 
| gt | Greater than | number, string | 
| contains | Like | string | 
| notContains | Not like | string | 
| beginsWith | Starts with prefix | string | 
| between | Between two values | number, string | 
| attributeExists | The attribute is not null | number, string, boolean | 
| size | checks the length of the element | string | 

#### Insert
<a name="built-in-rds-modules-functions-insert"></a>

The `insert` utility provides a straightforward way of inserting single row items in your database with the `INSERT` operation.

**Single item insertions**

To insert an item, specify the table and then pass in your object of values. The object keys are mapped to your table columns. Columns names are automatically escaped, and values are sent to the database using the variable map:

```
import { insert, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: values } = ctx.args;
    const insertStatement = insert({ table: 'persons', values });
    
    // Generates statement:
    // INSERT INTO `persons`(`name`)
    // VALUES(:NAME)
    return createMySQLStatement(insertStatement)
}
```

**MySQL use case**

You can combine an `insert` followed by a `select` to retrieve your inserted row:

```
import { insert, select, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: values } = ctx.args;
    const insertStatement = insert({  table: 'persons', values });
    const selectStatement = select({
        table: 'persons',
        columns: '*',
        where: { id: { eq: values.id } },
        limit: 1,
    });
    
    // Generates statement:
    // INSERT INTO `persons`(`name`)
    // VALUES(:NAME)
    // and
    // SELECT *
    // FROM `persons`
    // WHERE `id` = :ID
    return createMySQLStatement(insertStatement, selectStatement)
}
```

**Postgres use case**

With Postgres, you can use [https://www.postgresql.org/docs/current/dml-returning.html](https://www.postgresql.org/docs/current/dml-returning.html) to obtain data from the row that you inserted. It accepts `*` or an array of column names:

```
import { insert, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: values } = ctx.args;
    const insertStatement = insert({
        table: 'persons',
        values,
        returning: '*'
    });

    // Generates statement:
    // INSERT INTO "persons"("name")
    // VALUES(:NAME)
    // RETURNING *
    return createPgStatement(insertStatement)
}
```

#### Update
<a name="built-in-rds-modules-functions-update"></a>

The `update` utility allows you to update existing rows. You can use the condition object to apply changes to the specified columns in all the rows that satisfy the condition. For example, let's say we have a schema that allows us to make this mutation. We want to update the `name` of `Person` with the `id` value of `3` but only if we've known them (`known_since`) since the year `2000`:

```
mutation Update {
    updatePerson(
        input: {id: 3, name: "Jon"},
        condition: {known_since: {ge: "2000"}}
    ) {
    id
    name
  }
}
```

Our update resolver looks like this:

```
import { update, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: { id, ...values }, condition } = ctx.args;
    const where = {
        ...condition,
        id: { eq: id },
    };
    const updateStatement = update({
        table: 'persons',
        values,
        where,
        returning: ['id', 'name'],
    });

    // Generates statement:
    // UPDATE "persons"
    // SET "name" = :NAME, "birthday" = :BDAY, "country" = :COUNTRY
    // WHERE "id" = :ID
    // RETURNING "id", "name"
    return createPgStatement(updateStatement)
}
```

We can add a check to our condition to make sure that only the row that has the primary key `id` equal to `3` is updated. Similarly, for Postgres `inserts`, you can use `returning` to return the modified data. 

#### Remove
<a name="built-in-rds-modules-functions-remove"></a>

The `remove` utility allows you to delete existing rows. You can use the condition object on all rows that satisfy the condition. Note that `delete` is a reserved keyword in JavaScript. `remove` should be used instead:

```
import { remove, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: { id }, condition } = ctx.args;
    const where = { ...condition, id: { eq: id } };
    const deleteStatement = remove({
        table: 'persons',
        where,
        returning: ['id', 'name'],
    });

    // Generates statement:
    // DELETE "persons"
    // WHERE "id" = :ID
    // RETURNING "id", "name"
    return createPgStatement(updateStatement)
}
```

### Casting
<a name="built-in-rds-modules-casting"></a>

In some cases, you may want more specificity about the correct object type to use in your statement. You can use the provided type hints to specify the type of your parameters. AWS AppSync supports the [same type hints](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html#rdsdtataservice-Type-SqlParameter-typeHint) as the Data API. You can cast your parameters by using the `typeHint` functions from the AWS AppSync `rds` module. 

The following example allows you to send an array as a value that is casted as a JSON object. We use the `->` operator to retrieve the element at the `index` `2` in the JSON array:

```
import { sql, createPgStatement, toJsonObject, typeHint } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const arr = ctx.args.list_of_ids
    const statement = sql`select ${typeHint.JSON(arr)}->2 as value`
    return createPgStatement(statement)
}

export function response(ctx) {
    return toJsonObject(ctx.result)[0][0].value
}
```

Casting is also useful when handling and comparing `DATE`, `TIME`, and `TIMESTAMP`:

```
import { select, createPgStatement, typeHint } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const when = ctx.args.when
    const statement = select({
        table: 'persons',
        where: { createdAt : { gt: typeHint.DATETIME(when) } }
    })
    return createPgStatement(statement)
}
```

Here's another example showing how you can send the current date and time:

```
import { sql, createPgStatement, typeHint } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const now = util.time.nowFormatted('YYYY-MM-dd HH:mm:ss')
    return createPgStatement(sql`select ${typeHint.TIMESTAMP(now)}`)
}
```

**Available type hints**
+ `typeHint.DATE` - The corresponding parameter is sent as an object of the `DATE` type to the database. The accepted format is `YYYY-MM-DD`.
+ `typeHint.DECIMAL` - The corresponding parameter is sent as an object of the `DECIMAL` type to the database.
+ `typeHint.JSON` - The corresponding parameter is sent as an object of the `JSON` type to the database.
+ `typeHint.TIME` - The corresponding string parameter value is sent as an object of the `TIME` type to the database. The accepted format is `HH:MM:SS[.FFF]`. 
+ `typeHint.TIMESTAMP` - The corresponding string parameter value is sent as an object of the `TIMESTAMP` type to the database. The accepted format is `YYYY-MM-DD HH:MM:SS[.FFF]`.
+ `typeHint.UUID` - The corresponding string parameter value is sent as an object of the `UUID` type to the database.

# Runtime utilities
<a name="runtime-utils-js"></a>

The `runtime` library provides utilities to control or modify the runtime properties of your resolvers and functions.

## Runtime utils list
<a name="runtime-utils-list-js"></a>

 **`runtime.earlyReturn(obj?: unknown, returnOptions?: {skipTo: 'END' | 'NEXT'}): never`**  
Invoking this function will halt the execution of the current handler, AWS AppSync function or resolver (Unit or Pipeline Resolver) depending on the current context. The specified object is returned as the result.  
+ When called in an AWS AppSync function request handler, the data source and response handler are skipped, and the next function request handler (or the pipeline resolver response handler if this was the last AWS AppSync function) is called.
+ When called in an AWS AppSync pipeline resolver request handler, the pipeline execution is skipped, and the pipeline resolver response handler is called immediately.
+ When `returnOptions` is given with `skipTo` set to "END", the pipeline execution is skipped, and the pipeline resolver response handler is called immediately.
+ When `returnOptions` is given with `skipTo` set to "NEXT", the function execution is skipped, and the next pipeline handler is called.
**Example**  

```
import { runtime } from '@aws-appsync/utils'

export function request(ctx) {
  runtime.earlyReturn({ hello: 'world' })
  // code below is not executed
  return ctx.args
}

// never called because request returned early
export function response(ctx) {
  return ctx.result
}
```

# Time helpers in util.time
<a name="time-helpers-in-util-time-js"></a>

The `util.time` variable contains datetime methods to help generate timestamps, convert between datetime formats, and parse datetime strings. The syntax for datetime formats is based on [DateTimeFormatter](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html) which you can reference for further documentation.

## Time utils list
<a name="utility-helpers-in-time-list-js"></a>

 **`util.time.nowISO8601()`**  
Returns a String representation of UTC in [ISO8601 format](https://en.wikipedia.org/wiki/ISO_8601).

 **`util.time.nowEpochSeconds()`**  
Returns the number of seconds from the epoch of 1970-01-01T00:00:00Z to now.

 **`util.time.nowEpochMilliSeconds()`**  
Returns the number of milliseconds from the epoch of 1970-01-01T00:00:00Z to now.

 **`util.time.nowFormatted(String)`**  
Returns a string of the current timestamp in UTC using the specified format from a String input type.

 **`util.time.nowFormatted(String, String)`**  
Returns a string of the current timestamp for a timezone using the specified format and timezone from String input types.

 **`util.time.parseFormattedToEpochMilliSeconds(String, String)`**  
Parses a timestamp passed as a String along with a format containing a time zone, then returns the timestamp as milliseconds since epoch.

 **`util.time.parseFormattedToEpochMilliSeconds(String, String, String)`**  
Parses a timestamp passed as a String along with a format and time zone, then returns the timestamp as milliseconds since epoch.

 **`util.time.parseISO8601ToEpochMilliSeconds(String)`**  
Parses an ISO8601 timestamp passed as a String, then returns the timestamp as milliseconds since epoch.

 **`util.time.epochMilliSecondsToSeconds(long)`**  
Converts an epoch milliseconds timestamp to an epoch seconds timestamp.

 **`util.time.epochMilliSecondsToISO8601(long)`**  
Converts an epoch milliseconds timestamp to an ISO8601 timestamp.

 **`util.time.epochMilliSecondsToFormatted(long, String)`**  
Converts an epoch milliseconds timestamp, passed as long, to a timestamp formatted according to the supplied format in UTC.

 **`util.time.epochMilliSecondsToFormatted(long, String, String)`**  
Converts an epoch milliseconds timestamp, passed as a long, to a timestamp formatted according to the supplied format in the supplied timezone.

# DynamoDB helpers in util.dynamodb
<a name="dynamodb-helpers-in-util-dynamodb-js"></a>

`util.dynamodb` contains helper methods that make it easier to write and read data to Amazon DynamoDB, such as automatic type mapping and formatting. 

## toDynamoDB
<a name="utility-helpers-in-toDynamoDB-js"></a>

### toDynamoDB utils list
<a name="utility-helpers-in-toDynamoDB-list-js"></a>

 **`util.dynamodb.toDynamoDB(Object)`**   
General object conversion tool for DynamoDB that converts input objects to the appropriate DynamoDB representation. It's opinionated about how it represents some types: e.g., it will use lists ("L") rather than sets ("SS", "NS", "BS"). This returns an object that describes the DynamoDB attribute value.  
**String example**  

```
Input:      util.dynamodb.toDynamoDB("foo")
Output:     { "S" : "foo" }
```
**Number example**  

```
Input:      util.dynamodb.toDynamoDB(12345)
Output:     { "N" : 12345 }
```
**Boolean example**  

```
Input:      util.dynamodb.toDynamoDB(true)
Output:     { "BOOL" : true }
```
**List example**  

```
Input:      util.dynamodb.toDynamoDB([ "foo", 123, { "bar" : "baz" } ])
Output:     {
               "L" : [
                   { "S" : "foo" },
                   { "N" : 123 },
                   {
                       "M" : {
                           "bar" : { "S" : "baz" }
                       }
                   }
               ]
           }
```
**Map example**  

```
Input:      util.dynamodb.toDynamoDB({ "foo": "bar", "baz" : 1234, "beep": [ "boop"] })
Output:     {
               "M" : {
                   "foo"  : { "S" : "bar" },
                   "baz"  : { "N" : 1234 },
                   "beep" : {
                       "L" : [
                           { "S" : "boop" }
                       ]
                   }
               }
           }
```

## toString utils
<a name="utility-helpers-in-toString-js"></a>

### toString utils list
<a name="utility-helpers-in-toString-list-js"></a>

**`util.dynamodb.toString(String)`**  
Converts an input string to the DynamoDB string format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      util.dynamodb.toString("foo")
Output:     { "S" : "foo" }
```

 **`util.dynamodb.toStringSet(List<String>)`**  
Converts a list with Strings to the DynamoDB string set format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      util.dynamodb.toStringSet([ "foo", "bar", "baz" ])
Output:     { "SS" : [ "foo", "bar", "baz" ] }
```

## toNumber utils
<a name="utility-helpers-in-toNumber-js"></a>

### toNumber utils list
<a name="utility-helpers-in-toNumber-list-js"></a>

 **`util.dynamodb.toNumber(Number)`**  
Converts a number to the DynamoDB number format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      util.dynamodb.toNumber(12345)
Output:     { "N" : 12345 }
```

 **`util.dynamodb.toNumberSet(List<Number>)`**  
Converts a list of numbers to the DynamoDB number set format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      util.dynamodb.toNumberSet([ 1, 23, 4.56 ])
Output:     { "NS" : [ 1, 23, 4.56 ] }
```

## toBinary utils
<a name="utility-helpers-in-toBinary-js"></a>

### toBinary utils list
<a name="utility-helpers-in-toBinary-list-js"></a>

 **`util.dynamodb.toBinary(String)`**  
Converts binary data encoded as a base64 string to DynamoDB binary format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      util.dynamodb.toBinary("foo")
Output:     { "B" : "foo" }
```

 **`util.dynamodb.toBinarySet(List<String>)`**  
Converts a list of binary data encoded as base64 strings to DynamoDB binary set format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      util.dynamodb.toBinarySet([ "foo", "bar", "baz" ])
Output:     { "BS" : [ "foo", "bar", "baz" ] }
```

## toBoolean utils
<a name="utility-helpers-in-toBoolean-js"></a>

### toBoolean utils list
<a name="utility-helpers-in-toBoolean-list-js"></a>

 **`util.dynamodb.toBoolean(Boolean)`**  
Converts a Boolean to the appropriate DynamoDB Boolean format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      util.dynamodb.toBoolean(true)
Output:     { "BOOL" : true }
```

## toNull utils
<a name="utility-helpers-in-toNull-js"></a>

### toNull utils list
<a name="utility-helpers-in-toNull-list-js"></a>

 **`util.dynamodb.toNull()`**  
Returns a null in DynamoDB null format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      util.dynamodb.toNull()
Output:     { "NULL" : null }
```

## toList utils
<a name="utility-helpers-in-toList-js"></a>

### toList utils list
<a name="utility-helpers-in-toList-list-js"></a>

**`util.dynamodb.toList(List)`**  
Converts a list of objects to the DynamoDB list format. Each item in the list is also converted to its appropriate DynamoDB format. It's opinionated about how it represents some of the nested objects: e.g., it will use lists ("L") rather than sets ("SS", "NS", "BS"). This returns an object that describes the DynamoDB attribute value.  

```
Input:      util.dynamodb.toList([ "foo", 123, { "bar" : "baz" } ])
Output:     {
               "L" : [
                   { "S" : "foo" },
                   { "N" : 123 },
                   {
                       "M" : {
                           "bar" : { "S" : "baz" }
                       }
                   }
               ]
           }
```

## toMap utils
<a name="utility-helpers-in-toMap-js"></a>

### toMap utils list
<a name="utility-helpers-in-toMap-list-js"></a>

 **`util.dynamodb.toMap(Map)`**  
Converts a map to the DynamoDB map format. Each value in the map is also converted to its appropriate DynamoDB format. It's opinionated about how it represents some of the nested objects: e.g., it will use lists ("L") rather than sets ("SS", "NS", "BS"). This returns an object that describes the DynamoDB attribute value.  

```
Input:      util.dynamodb.toMap({ "foo": "bar", "baz" : 1234, "beep": [ "boop"] })
Output:     {
               "M" : {
                   "foo"  : { "S" : "bar" },
                   "baz"  : { "N" : 1234 },
                   "beep" : {
                       "L" : [
                           { "S" : "boop" }
                       ]
                   }
               }
           }
```

 **`util.dynamodb.toMapValues(Map)`**  
Creates a copy of the map where each value has been converted to its appropriate DynamoDB format. It's opinionated about how it represents some of the nested objects: e.g., it will use lists ("L") rather than sets ("SS", "NS", "BS").  

```
Input:      util.dynamodb.toMapValues({ "foo": "bar", "baz" : 1234, "beep": [ "boop"] })
Output:     {
               "foo"  : { "S" : "bar" },
               "baz"  : { "N" : 1234 },
               "beep" : {
                   "L" : [
                       { "S" : "boop" }
                   ]
               }
           }
```
This is slightly different to `util.dynamodb.toMap(Map)` as it returns only the contents of the DynamoDB attribute value, but not the whole attribute value itself. For example, the following statements are exactly the same:  

```
util.dynamodb.toMapValues(<map>)
util.dynamodb.toMap(<map>)("M")
```

## S3Object utils
<a name="utility-helpers-in-S3Object-js"></a>

### S3Object utils list
<a name="utility-helpers-in-S3Object-list-js"></a>

**`util.dynamodb.toS3Object(String key, String bucket, String region)`**  
Converts the key, bucket and region into the DynamoDB S3 Object representation. This returns an object that describes the DynamoDB attribute value.  

```
Input:      util.dynamodb.toS3Object("foo", "bar", region = "baz")
Output:     { "S" : "{ \"s3\" : { \"key\" : \"foo", \"bucket\" : \"bar", \"region\" : \"baz" } }" }
```

**`util.dynamodb.toS3Object(String key, String bucket, String region, String version)`**  
Converts the key, bucket, region and optional version into the DynamoDB S3 Object representation. This returns an object that describes the DynamoDB attribute value.  

```
Input:      util.dynamodb.toS3Object("foo", "bar", "baz", "beep")
Output:     { "S" : "{ \"s3\" : { \"key\" : \"foo\", \"bucket\" : \"bar\", \"region\" : \"baz\", \"version\" = \"beep\" } }" }
```

 **`util.dynamodb.fromS3ObjectJson(String)`**  
Accepts the string value of a DynamoDB S3 Object and returns a map that contains the key, bucket, region and optional version.  

```
Input:      util.dynamodb.fromS3ObjectJson({ "S" : "{ \"s3\" : { \"key\" : \"foo\", \"bucket\" : \"bar\", \"region\" : \"baz\", \"version\" = \"beep\" } }" })
Output:     { "key" : "foo", "bucket" : "bar", "region" : "baz", "version" : "beep" }
```

# HTTP helpers in util.http
<a name="http-helpers-in-utils-http-js"></a>

The `util.http` utility provides helper methods that you can use to manage HTTP request parameters and to add response headers.

## util.http utils list
<a name="http-helpers-in-utils-http-list-js"></a>

 **`util.http.copyHeaders(headers)`**  
Copies the headers from the map, excluding the following restricted HTTP headers:  
+ transfer-encoding
+ connection
+ host
+ expect
+ keep-alive
+ upgrade
+ proxy-authenticate
+ proxy-authorization
+ te
+ content-length

**`util.http.addResponseHeader(String, Object)`**  
Adds a single custom header with the name (`String`) and value (`Object`) of the response. The following limitations apply:  
+ In addition to the list of restricted headers for `copyHeaders(headers)`, header names cannot match any of the following:
  + Access-Control-Allow-Credentials
  + Access-Control-Allow-Origin
  + Access-Control-Expose-Headers
  + Access-Control-Max-Age
  + Access-Control-Allow-Methods
  + Access-Control-Allow-Headers
  + Vary
  + Content-Type
+ Header names can't start with the restricted prefixes `x-amzn-` or `x-amz-`.
+ The size of custom response headers can't exceed 4 KB. This includes header names and values.
+ You should define each response header once per GraphQL operation. However, if you define a custom header with the same name multiple times, the most recent definition appears in the response. All headers count towards the header size limit regardless of naming.
+ Headers with an empty or restricted name `(String)` or a null value `(Object)` will be ignored and yield a `ResponseHeaderError` error that is added to the operation's `errors` output.

```
export function request(ctx) {
  util.http.addResponseHeader('itemsCount', 7)
  util.http.addResponseHeader('render', ctx.args.render)
  return {}
}
```

**`util.http.addResponseHeaders(Map)`**  
Adds multiple response headers to the response from the specified map of names `(String)` and values `(Object)`. The same limitations listed for the `addResponseHeader(String, Object)` method also apply to this method.  

```
export function request(ctx) {
  const headers = {
    headerInt: 12,
    headerString: 'stringValue',
    headerObject: {
      field1: 7,
      field2: 'string'
    }
  }
  util.http.addResponseHeaders(headers)
  return {}
}
```

# Transformation helpers in util.transform
<a name="transformation-helpers-in-utils-transform-js"></a>

`util.transform` contains helper methods that make it easier to perform complex operations against data sources.

## Transformation helpers utils list
<a name="transformation-helpers-in-utils-transform-js-list"></a>

**`util.transform.toDynamoDBFilterExpression(filterObject: DynamoDBFilterObject) : string`**  
Converts an input string to a filter expression for use with DynamoDB. We recommend using `toDynamoDBFilterExpression` with [built-in module functions](https://docs.aws.amazon.com/appsync/latest/devguide/built-in-modules-js.html).

**`util.transform.toElasticsearchQueryDSL(object: OpenSearchQueryObject) : string`**  
Converts the given input into its equivalent OpenSearch Query DSL expression, returning it as a JSON string.  
**Example input:**  

```
util.transform.toElasticsearchQueryDSL({
    "upvotes":{
        "ne":15,
        "range":[
            10,
            20
        ]
    },
    "title":{
        "eq":"hihihi",
        "wildcard":"h*i"
    }
  })
```
**Example output:**  

```
{
    "bool":{
      "must":[
          {
            "bool":{
              "must":[
                  {
                    "bool":{
                      "must_not":{
                        "term":{
                          "upvotes":15
                        }
                      }
                    }
                  },
                  {
                    "range":{
                      "upvotes":{
                        "gte":10,
                        "lte":20
                      }
                    }
                  }
              ]
            }
          },
          {
            "bool":{
              "must":[
                  {
                    "term":{
                      "title":"hihihi"
                    }
                  },
                  {
                  "wildcard":{
                      "title":"h*i"
                    }
                  }
              ]
            }
          }
      ]
    }
}
```
The default operator is assumed to be AND.

**`util.transform.toSubscriptionFilter(objFilter, ignoredFields?, rules?): SubscriptionFilter`**  
Converts a `Map` input object to a `SubscriptionFilter` expression object. The `util.transform.toSubscriptionFilter` method is used as an input to the `extensions.setSubscriptionFilter()` extension. For more information, see [Extensions](https://docs.aws.amazon.com/appsync/latest/devguide/extensions-js.html).  
The parameters and return statement is listed below:  
*Parameters*  
+ `objFilter`: `SubscriptionFilterObject`

  A `Map` input object that's converted to the `SubscriptionFilter` expression object.
+ `ignoredFields`: `SubscriptionFilterExcludeKeysType` (optional)

  A `List` of field names in the first object that will be ignored.
+ `rules`: `SubscriptionFilterRuleObject` (optional)

  A `Map` input object with strict rules that's included when you're constructing the `SubscriptionFilter` expression object. These strict rules will be included in the `SubscriptionFilter` expression object so that at least one of the rules will be satisfied to pass the subscription filter.
*Response*  
Returns a `[SubscriptionFilter](https://docs.aws.amazon.com/appsync/latest/devguide/extensions-js.html)`.

**`util.transform.toSubscriptionFilter(Map, List)`**  
Converts a `Map` input object to a `SubscriptionFilter` expression object. The `util.transform.toSubscriptionFilter` method is used as an input to the `extensions.setSubscriptionFilter()` extension. For more information, see [Extensions](https://docs.aws.amazon.com/appsync/latest/devguide/extensions-js.html).  
The first argument is the `Map` input object that's converted to the `SubscriptionFilter` expression object. The second argument is a `List` of field names that are ignored in the first `Map` input object while constructing the `SubscriptionFilter` expression object.

**`util.transform.toSubscriptionFilter(Map, List, Map)`**  
Converts a `Map` input object to a `SubscriptionFilter` expression object. The `util.transform.toSubscriptionFilter` method is used as an input to the `extensions.setSubscriptionFilter()` extension. For more information, see [Extensions](https://docs.aws.amazon.com/appsync/latest/devguide/extensions-js.html). 

**`util.transform.toDynamoDBConditionExpression(conditionObject)`**  
Creates a DynamoDB condition expression.

## Subscription filter arguments
<a name="subscription-filter-arguments-js"></a>

The following table explains the how the arguments of the following utilities are defined:
+ `Util.transform.toSubscriptionFilter(objFilter, ignoredFields?, rules?): SubscriptionFilter`

------
#### [ Argument 1: Map ]

Argument 1 is a `Map` object with the following key values:
+ field names
+ "and"
+ "or"

For field names as keys, the conditions on these fields' entries are in the form of `"operator" : "value"`. 

The following example shows how entries can be added to the `Map`:

```
"field_name" : {
                    "operator1" : value             
               }

## We can have multiple conditions for the same field_name: 

"field_name" : {
                    "operator1" : value             
                    "operator2" : value
                    .
                    .
                    .                  
               }
```

When a field has two or more conditions on it, all of these conditions are considered to use the OR operation.

The input `Map` can also have "and" and "or" as keys, implying that all entries within these should be joined using AND or OR logic depending on the key. The key values "and" and "or" expect an array of conditions.

```
"and" : [
            
            {
                "field_name1" : {
                    "operator1" : value             
                }
             },
             
             {
                "field_name2" : {
                    "operator1" : value             
                }
             },
             .
             .
        ].
```

Note that you can nest "and" and "or". That is, you can have nested "and"/"or" within another "and"/"or" block. However, this doesn't work for simple fields.

```
"and" : [
            
            {
                "field_name1" : {
                    "operator" : value             
                }
             },
             
             {
                "or" : [
                            {
                                "field_name2" : {
                                    "operator" : value             
                                }
                            },
                            
                            {
                                "field_name3" : {
                                    "operator" : value             
                                }
                            }
              
                        ].
```

The following example shows an input of *argument 1* using `util.transform.toSubscriptionFilter(Map) : Map`.

**Input(s)**

Argument 1: Map:

```
{
  "percentageUp": {
    "lte": 50,
    "gte": 20
  },
  "and": [
    {
      "title": {
        "ne": "Book1"
      }
    },
    {
      "downvotes": {
        "gt": 2000
      }
    }
  ],
  "or": [
    {
      "author": {
        "eq": "Admin"
      }
    },
    {
      "isPublished": {
        "eq": false
      }
    }
  ]
}
```

**Output**

The result is a `Map` object:

```
{
  "filterGroup": [
    {
      "filters": [
        {
          "fieldName": "percentageUp",
          "operator": "lte",
          "value": 50
        },
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 2000
        },
        {
          "fieldName": "author",
          "operator": "eq",
          "value": "Admin"
        }
      ]
    },
    {
      "filters": [
        {
          "fieldName": "percentageUp",
          "operator": "lte",
          "value": 50
        },
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 2000
        },
        {
          "fieldName": "isPublished",
          "operator": "eq",
          "value": false
        }
      ]
    },
    {
      "filters": [
        {
          "fieldName": "percentageUp",
          "operator": "gte",
          "value": 20
        },
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 2000
        },
        {
          "fieldName": "author",
          "operator": "eq",
          "value": "Admin"
        }
      ]
    },
    {
      "filters": [
        {
          "fieldName": "percentageUp",
          "operator": "gte",
          "value": 20
        },
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 2000
        },
        {
          "fieldName": "isPublished",
          "operator": "eq",
          "value": false
        }
      ]
    }
  ]
}
```

------
#### [ Argument 2: List ]

Argument 2 contains a `List` of field names that shouldn't be considered in the input `Map` (argument 1) while constructing the `SubscriptionFilter` expression object. The `List` can also be empty.

The following example shows the inputs of argument 1 and argument 2 using `util.transform.toSubscriptionFilter(Map, List) : Map`.

**Input(s)**

Argument 1: Map:

```
{
  "percentageUp": {
    "lte": 50,
    "gte": 20
  },
  "and": [
    {
      "title": {
        "ne": "Book1"
      }
    },
    {
      "downvotes": {
        "gt": 20
      }
    }
  ],
  "or": [
    {
      "author": {
        "eq": "Admin"
      }
    },
    {
      "isPublished": {
        "eq": false
      }
    }
  ]
}
```

Argument 2: List:

```
["percentageUp", "author"]
```

**Output**

The result is a `Map` object:

```
{
  "filterGroup": [
    {
      "filters": [
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 20
        },
        {
          "fieldName": "isPublished",
          "operator": "eq",
          "value": false
        }
      ]
    }
  ]
}
```

------
#### [ Argument 3: Map ]

Argument 3 is a `Map` object that has field names as key values (cannot have "and" or "or"). For field names as keys, the conditions on these fields are entries in the form of `"operator" : "value"`. Unlike argument 1, argument 3 cannot have multiple conditions in the same key. In addition, argument 3 doesn't have an "and" or "or" clause, so there's no nesting involved either.

Argument 3 represents a list of strict rules, which are added to the `SubscriptionFilter` expression object so that **at least one** of these conditions is met to pass the filter.

```
{
  "fieldname1": {
    "operator": value
  },
  "fieldname2": {
    "operator": value
  }
}
.
.
.
```

The following example shows the inputs of *argument 1*, *argument 2*, and *argument 3* using `util.transform.toSubscriptionFilter(Map, List, Map) : Map`.

**Input(s)**

Argument 1: Map:

```
{
  "percentageUp": {
    "lte": 50,
    "gte": 20
  },
  "and": [
    {
      "title": {
        "ne": "Book1"
      }
    },
    {
      "downvotes": {
        "lt": 20
      }
    }
  ],
  "or": [
    {
      "author": {
        "eq": "Admin"
      }
    },
    {
      "isPublished": {
        "eq": false
      }
    }
  ]
}
```

Argument 2: List:

```
["percentageUp", "author"]
```

Argument 3: Map:

```
{
  "upvotes": {
    "gte": 250
  },
  "author": {
    "eq": "Person1"
  }
}
```

**Output**

The result is a `Map` object:

```
{
  "filterGroup": [
    {
      "filters": [
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 20
        },
        {
          "fieldName": "isPublished",
          "operator": "eq",
          "value": false
        },
        {
          "fieldName": "upvotes",
          "operator": "gte",
          "value": 250
        }
      ]
    },
    {
      "filters": [
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 20
        },
        {
          "fieldName": "isPublished",
          "operator": "eq",
          "value": false
        },
        {
          "fieldName": "author",
          "operator": "eq",
          "value": "Person1"
        }
      ]
    }
  ]
}
```

------

# String helpers in util.str
<a name="str-helpers-in-util-str-js"></a>

 `util.str` contains methods to help with common String operations. 

## util.str utils list
<a name="str-helpers-in-util-str-list-js"></a>

 **`util.str.normalize(String, String)`**  
Normalizes a string using one of the four unicode normalization forms: NFC, NFD, NFKC, or NFKD. The first argument is the string to normalize. The second argument is either "nfc", "nfd", "nfkc", or "nfkd" specifying the normalization type to use for the normalization process.

# Extensions
<a name="extensions-js"></a>

`extensions` contains a set of methods to make additional actions within your resolvers.

## Caching extensions
<a name="caching-extensions-js-list"></a>

**`extensions.evictFromApiCache(typeName: string, fieldName: string, keyValuePair: Record<string, any>) : Object`**  
Evicts an item from the AWS AppSync server-side cache. The first argument is the type name. The second argument is the field name. The third argument is an object containing key-value pair items that specify the caching key value. You must put the items in the object in the same order as the caching keys in the cached resolver's `cachingKey`. For more information about caching, see [Caching behavior](https://docs.aws.amazon.com/appsync/latest/devguide/enabling-caching.html#caching-behavior).  
**Example 1:**  
This example evicts the items that were cached for a resolver called `Query.allClasses` on which a caching key called `context.arguments.semester` was used. When the mutation is called and the resolver runs, if an entry is successfully cleared, then the response contains an `apiCacheEntriesDeleted` value in the extensions object that shows how many entries were deleted.  

```
import { util, extensions } from '@aws-appsync/utils';

export const request = (ctx) => ({ payload: null });

export function response(ctx) {
	extensions.evictFromApiCache('Query', 'allClasses', {
		'context.arguments.semester': ctx.args.semester,
	});
	return null;
}
```
This function **only** works for mutations, not queries.

## Subscription extensions
<a name="subscription-extensions-js-list"></a>

**`extensions.setSubscriptionFilter(filterJsonObject)`**  
Defines enhanced subscription filters. Each subscription notification event is evaluated against provided subscription filters and delivers notifications to clients if all filters evaluate to `true`. The argument is `filterJsonObject` (More information about this argument can be found below in the *Argument: filterJsonObject* section.). See [Enhanced subscription filtering](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-enhanced-filtering.html).  
You can use this extension function only in the response handler of a subscription resolver. Also, we recommend using `util.transform.toSubscriptionFilter` to create your filter.

**`extensions.setSubscriptionInvalidationFilter(filterJsonObject)`**  
Defines subscription invalidation filters. Subscription filters are evaluated against the invalidation payload, then invalidate a given subscription if the filters evaluate to `true`. The argument is `filterJsonObject` (More information about this argument can be found below in the *Argument: filterJsonObject* section.). See [Enhanced subscription filtering](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-enhanced-filtering.html).  
You can use this extension function only in the response handler of a subscription resolver. Also, we recommend using `util.transform.toSubscriptionFilter` to create your filter.

**`extensions.invalidateSubscriptions(invalidationJsonObject)`**  
Used to initiate a subscription invalidation from a mutation. The argument is `invalidationJsonObject` (More information about this argument can be found below in the *Argument: invalidationJsonObject* section.).  
This extension can be used only in the response mapping templates of the mutation resolvers.  
You can only use at most five unique `extensions.invalidateSubscriptions()` method calls in any single request. If you exceed this limit, you will receive a GraphQL error.

## Argument: filterJsonObject
<a name="extensions-filterJsonObject-js"></a>

The JSON object defines either subscription or invalidation filters. It's an array of filters in a `filterGroup`. Each filter is a collection of individual filters.

```
{
    "filterGroup": [
        {
           "filters" : [
                 {
                    "fieldName" : "userId",
                    "operator" : "eq",
                    "value" : 1
                }
           ]
           
        },
        {
           "filters" : [
                {
                    "fieldName" : "group",
                    "operator" : "in",
                    "value" : ["Admin", "Developer"]
                }
           ]
           
        }
    ]
}
```

Each filter has three attributes: 
+ `fieldName` – The GraphQL schema field.
+ `operator` – The operator type.
+ `value` – The values to compare to the subscription notification `fieldName` value.

The following is an example assignment of these attributes:

```
{
 "fieldName" : "severity",
 "operator" : "le",
 "value" : context.result.severity
}
```

## Argument: invalidationJsonObject
<a name="extensions-invalidationJsonObject-js"></a>

The `invalidationJsonObject` defines the following:
+ `subscriptionField` – The GraphQL schema subscription to invalidate. A single subscription, defined as a string in the `subscriptionField`, is considered for invalidation.
+ `payload` – A key-value pair list that's used as the input for invalidating subscriptions if the invalidation filter evaluates to `true` against their values.

  The following example invalidates subscribed and connected clients using the `onUserDelete` subscription when the invalidation filter defined in the subscription resolver evaluates to `true` against the `payload` value.

  ```
  export const request = (ctx) => ({ payload: null });
  
  export function response(ctx) {
  	extensions.invalidateSubscriptions({
  		subscriptionField: 'onUserDelete',
  		payload: { group: 'Developer', type: 'Full-Time' },
  	});
  	return ctx.result;
  }
  ```

# XML helpers in util.xml
<a name="xml-helpers-in-util-xml-js"></a>

 `util.xml` contains methods to help with XML string conversion. 

## util.xml utils list
<a name="xml-helpers-in-util-xml-list-js"></a>

 **`util.xml.toMap(String) : Object`**  
Converts a XML string to a dictionary.  
**Example 1:**  

```
Input:

<?xml version="1.0" encoding="UTF-8"?>
<posts>
<post>
    <id>1</id>
    <title>Getting started with GraphQL</title>
</post>
</posts>

Output (object):

{
    "posts":{
      "post":{
        "id":1,
        "title":"Getting started with GraphQL"
      }
    }
}
```
**Example 2:**  

```
Input:

<?xml version="1.0" encoding="UTF-8"?>
<posts>
<post>
  <id>1</id>
  <title>Getting started with GraphQL</title>
</post>
<post>
  <id>2</id>
  <title>Getting started with AppSync</title>
</post>
</posts>

Output (JavaScript object):

{
    "posts":{
    "post":[
        {
            "id":1,
            "title":"Getting started with GraphQL"
        },
        {
            "id":2,
            "title":"Getting started with AppSync"
        }
    ]
    }
}
```

**`util.xml.toJsonString(String, Boolean?) : String`**  
Converts a XML string to a JSON string. This is similar to `toMap`, except that the output is a string. This is useful if you want to directly convert and return the XML response from an HTTP object to JSON. You can set an optional boolean parameter to determine if you want to string-encode the JSON.

# AWS AppSync JavaScript resolver function reference for DynamoDB
<a name="js-resolver-reference-dynamodb"></a>

The AWS AppSync DynamoDB function allows you to use [GraphQL](https://graphql.org) to store and retrieve data in existing Amazon DynamoDB tables in your account by mapping an incoming GraphQL request into a DynamoDB call, and then mapping the DynamoDB response back to GraphQL. This section describes the request and response handlers for supported DynamoDB operations:
+  [GetItem](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-getitem.html) - The GetItem request lets you tell the DynamoDB function to make a GetItem request to DynamoDB, and enables you to specify the key of the item in DynamoDB and whether to use a consistent read or not.
+  [ PutItem ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-putitem.html) - The PutItem request mapping document lets you tell the DynamoDB function to make a PutItem request to DynamoDB, and enables you to specify the key of the item in DynamoDB, the full contents of the item (composed of key and attributeValues), and conditions for the operation to succeed.
+  [ UpdateItem ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-updateitem.html) - The UpdateItem request enables you to tell the DynamoDB function to make a UpdateItem request to DynamoDB and allows you to specify the key of the item in DynamoDB, an update expression describing how to update the item in DynamoDB, and conditions for the operation to succeed.
+  [ DeleteItem ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-deleteitem.html) - The DeleteItem request lets you tell the DynamoDB function to make a DeleteItem request to DynamoDB, and enables you to specify the key of the item in DynamoDB and conditions for the operation to succeed.
+  [ Query ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-query.html) - The Query request object lets you tell the DynamoDB resolver to make a Query request to DynamoDB, and enables you to specify the key expression, which index to use, additional filters, how many items to return, whether to use consistent reads, query direction (forward or backward), and pagination tokens.
+  [ Scan ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-scan.html) - The Scan request lets you tell the DynamoDB function to make a Scan request to DynamoDB, and enables you to specify a filter to exclude results, which index to use, how many items to return, whether to use consistent reads, pagination tokens, and parallel scans.
+  [ Sync ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-sync.html) - The Sync request object lets you retrieve all the results from a DynamoDB table and then receive only the data altered since your last query (the delta updates). Sync requests can only be made to versioned DynamoDB data sources. You can specify a filter to exclude results, how many items to return, pagination Tokens, and when your last Sync operation was started.
+  [ BatchGetItem ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-batch-get-item.html) - The BatchGetItem request object lets you tell the DynamoDB function to make a BatchGetItem request to DynamoDB to retrieve multiple items, potentially across multiple tables. For this request object, you must specify the table names to retrieve the items from and the keys of the items to retrieve from each table.
+  [ BatchDeleteItem ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-batch-delete-item.html) - The BatchDeleteItem request object lets you tell the DynamoDB function to make a BatchWriteItem request to DynamoDB to delete multiple items, potentially across multiple tables. For this request object, you must specify the table names to delete the items from and the keys of the items to delete from each table.
+  [ BatchPutItem ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-batch-put-item.html) - The BatchPutItem request object lets you tell the DynamoDB function to make a BatchWriteItem request to DynamoDB to put multiple items, potentially across multiple tables. For this request object, you must specify the table names to put the items in and the full items to put in each table.
+  [ TransactGetItems ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-transact-get-items.html) - The TransactGetItems request object lets you to tell the DynamoDB function to make a TransactGetItems request to DynamoDB to retrieve multiple items, potentially across multiple tables. For this request object, you must specify the table name of each request item to retrieve the item from and the key of each request item to retrieve from each table.
+  [ TransactWriteItems ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-transact-write-items.html) - The TransactWriteItems request object lets you tell the DynamoDB function to make a TransactWriteItems request to DynamoDB to write multiple items, potentially to multiple tables. For this request object, you must specify the destination table name of each request item, the operation of each request item to perform, and the key of each request item to write.
+  [ Type system (request mapping) ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-typed-values-request.html) - Learn more about how DynamoDB typing is integrated into AWS AppSync requests.
+  [ Type system (response mapping) ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-typed-values-responses.html) - Learn more about how DynamoDB types are converted automatically to GraphQL or JSON in a response payload.
+  [Filters](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-filter.html) - Learn more about filters for query and scan operations.
+  [ Condition expressions ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-condition-expressions.html) - Learn more about condition expressions for PutItem, UpdateItem, and DeleteItem operations.
+  [ Transaction condition expressions ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-transaction-condition-expressions.html) - Learn more about condition expressions for TransactWriteItems operations.
+  [ Projections ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-projections.html) - Learn more about how to specify attributes in read operations.

# GetItem
<a name="js-aws-appsync-resolver-reference-dynamodb-getitem"></a>

The `GetItem` request lets you tell the AWS AppSync DynamoDB function to make a `GetItem` request to DynamoDB, and enables you to specify:
+ The key of the item in DynamoDB
+ Whether to use a consistent read or not

The `GetItem` request has the following structure:

```
type DynamoDBGetItem = {
  operation: 'GetItem';
  key: { [key: string]: any };
  consistentRead?: ConsistentRead;
  projection?: {
    expression: string;
    expressionNames?: { [key: string]: string };
  };
};
```

The fields are defined as follows:

## GetItem fields
<a name="js-getitem-list"></a>

### GetItem fields list
<a name="js-getitem-list-col"></a>

 **`operation`**   
The DynamoDB operation to perform. To perform the `GetItem` DynamoDB operation, this must be set to `GetItem`. This value is required.

 **`key`**   
The key of the item in DynamoDB. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This value is required.

 **`consistentRead`**   
Whether or not to perform a strongly consistent read with DynamoDB. This is optional, and defaults to `false`.

**`projection`**  
A projection that's used to specify the attributes to return from the DynamoDB operation. For more information about projections, see [Projections](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-projections). This field is optional.

The item returned from DynamoDB is automatically converted into GraphQL and JSON primitive types, and is available in the context result (`context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-responses).

For more information about JavaScript resolvers, see [JavaScript resolvers overview](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html).

## Example
<a name="js-example"></a>

The following example is a function request handler for a GraphQL query `getThing(foo: String!, bar: String!)`:

```
export function request(ctx) {
  const {foo, bar} = ctx.args
  return {
    operation : "GetItem",
    key : util.dynamodb.toMapValues({foo, bar}),
    consistentRead : true
  }
}
```

For more information about the DynamoDB `GetItem` API, see the [DynamoDB API documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html).

# PutItem
<a name="js-aws-appsync-resolver-reference-dynamodb-putitem"></a>

The `PutItem` request mapping document lets you tell the AWS AppSync DynamoDB function to make a `PutItem` request to DynamoDB, and enables you to specify the following:
+ The key of the item in DynamoDB
+ The full contents of the item (composed of `key` and `attributeValues`)
+ Conditions for the operation to succeed

The `PutItem` request has the following structure:

```
type DynamoDBPutItemRequest = {
  operation: 'PutItem';
  key: { [key: string]: any };
  attributeValues: { [key: string]: any};
  condition?: ConditionCheckExpression;
  customPartitionKey?: string;
  populateIndexFields?: boolean;
  _version?: number;
};
```

The fields are defined as follows:

## PutItem fields
<a name="js-putitem-list"></a>

### PutItem fields list
<a name="js-putitem-list-col"></a>

 **`operation`**   
The DynamoDB operation to perform. To perform the `PutItem` DynamoDB operation, this must be set to `PutItem`. This value is required.

 **`key`**   
The key of the item in DynamoDB. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This value is required.

 **`attributeValues`**   
The rest of the attributes of the item to be put into DynamoDB. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This field is optional.

 **`condition`**   
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. If no condition is specified, the `PutItem` request overwrites any existing entry for that item. For more information about conditions, see [Condition expressions](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-condition-expressions). This value is optional.

 **`_version`**   
A numeric value that represents the latest known version of an item. This value is optional. This field is used for *Conflict Detection* and is only supported on versioned data sources.

**`customPartitionKey`**  
When enabled, this string value modifies the format of the `ds_sk` and `ds_pk` records used by the delta sync table when versioning has been enabled (for more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*). When enabled, the processing of the `populateIndexFields` entry is also enabled. This field is optional.

**`populateIndexFields`**  
A boolean value that, when enabled **along with the `customPartitionKey`**, creates new entries for each record in the delta sync table, specifically in the `gsi_ds_pk` and `gsi_ds_sk` columns. For more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*. This field is optional.   
The item written to DynamoDB is automatically converted to GraphQL and JSON primitive types and is available in the context result (`context.result`).

The item written to DynamoDB is automatically converted into GraphQL and JSON primitive types and is available in the context result (`context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-responses).

For more information about JavaScript resolvers, see [JavaScript resolvers overview](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html).

## Example 1
<a name="js-example-1"></a>

The following example is a function request handler for a GraphQL mutation `updateThing(foo: String!, bar: String!, name: String!, version: Int!)`.

If no item with the specified key exists, it’s created. If an item already exists with the specified key, it’s overwritten.

```
import { util } from '@aws-appsync/utils';
export function request(ctx) {
  const { foo, bar, ...values} = ctx.args
  return {
    operation: 'PutItem',
    key: util.dynamodb.toMapValues({foo, bar}),
    attributeValues: util.dynamodb.toMapValues(values),
  };
}
```

## Example 2
<a name="js-example-2"></a>

The following example is a function request handler for a GraphQL mutation `updateThing(foo: String!, bar: String!, name: String!, expectedVersion: Int!)`.

This example verifies that the item currently in DynamoDB has the `version` field set to `expectedVersion`.

```
import { util } from '@aws-appsync/utils';
export function request(ctx) {
  const { foo, bar, name, expectedVersion } = ctx.args;
  const values = { name, version: expectedVersion + 1 };
  let condition = util.transform.toDynamoDBConditionExpression({
    version: { eq: expectedVersion },
  });

  return {
    operation: 'PutItem',
    key: util.dynamodb.toMapValues({ foo, bar }),
    attributeValues: util.dynamodb.toMapValues(values),
    condition,
  };
}
```

For more information about the DynamoDB `PutItem` API, see the [DynamoDB API documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html).

# UpdateItem
<a name="js-aws-appsync-resolver-reference-dynamodb-updateitem"></a>

The `UpdateItem` request enables you to tell the AWS AppSync DynamoDB function to make a `UpdateItem` request to DynamoDB and allows you to specify the following:
+ The key of the item in DynamoDB
+ An update expression describing how to update the item in DynamoDB
+ Conditions for the operation to succeed

The `UpdateItem` request has the following structure:

```
type DynamoDBUpdateItemRequest = {
  operation: 'UpdateItem';
  key: { [key: string]: any };
  update: {
    expression: string;
    expressionNames?: { [key: string]: string };
    expressionValues?: { [key: string]: any };
  };
  condition?: ConditionCheckExpression;
  customPartitionKey?: string;
  populateIndexFields?: boolean;
  _version?: number;
};
```

The fields are defined as follows:

## UpdateItem fields
<a name="js-updateitem-list"></a>

### UpdateItem fields list
<a name="js-updateitem-list-col"></a>

 **`operation`**   
The DynamoDB operation to perform. To perform the `UpdateItem` DynamoDB operation, this must be set to `UpdateItem`. This value is required.

 **`key`**   
The key of the item in DynamoDB. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about specifying a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This value is required.

 **`update`**   
The `update` section lets you specify an update expression that describes how to update the item in DynamoDB. For more information about how to write update expressions, see the [DynamoDB UpdateExpressions documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html). This section is required.  
The `update` section has three components:    
** `expression` **  
The update expression. This value is required.  
** `expressionNames` **  
The substitutions for expression attribute *name* placeholders, in the form of key-value pairs. The key corresponds to a name placeholder used in the `expression`, and the value must be a string corresponding to the attribute name of the item in DynamoDB. This field is optional, and should only be populated with substitutions for expression attribute name placeholders used in the `expression`.  
** `expressionValues` **  
The substitutions for expression attribute *value* placeholders, in the form of key-value pairs. The key corresponds to a value placeholder used in the `expression`, and the value must be a typed value. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This must be specified. This field is optional, and should only be populated with substitutions for expression attribute value placeholders used in the `expression`.

 **`condition`**   
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. If no condition is specified, the `UpdateItem` request updates the existing entry regardless of its current state. For more information about conditions, see [Condition expressions](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-condition-expressions). This value is optional.

 **`_version`**   
A numeric value that represents the latest known version of an item. This value is optional. This field is used for *Conflict Detection* and is only supported on versioned data sources.

**`customPartitionKey`**  
When enabled, this string value modifies the format of the `ds_sk` and `ds_pk` records used by the delta sync table when versioning has been enabled (for more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*). When enabled, the processing of the `populateIndexFields` entry is also enabled. This field is optional.

**`populateIndexFields`**  
A boolean value that, when enabled **along with the `customPartitionKey`**, creates new entries for each record in the delta sync table, specifically in the `gsi_ds_pk` and `gsi_ds_sk` columns. For more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*. This field is optional.

The item updated in DynamoDB is automatically converted into GraphQL and JSON primitive types and is available in the context result (`context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-responses).

For more information about JavaScript resolvers, see [JavaScript resolvers overview](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html).

## Example 1
<a name="js-id3"></a>

The following example is a function request handler for the GraphQL mutation `upvote(id: ID!)`.

In this example, an item in DynamoDB has its `upvotes` and `version` fields incremented by 1.

```
import { util } from '@aws-appsync/utils';
export function request(ctx) {
  const { id } = ctx.args;
  return {
    operation: 'UpdateItem',
    key: util.dynamodb.toMapValues({ id }),
    update: {
      expression: 'ADD #votefield :plusOne, version :plusOne',
      expressionNames: { '#votefield': 'upvotes' },
      expressionValues: { ':plusOne': { N: 1 } },
    },
  };
}
```

## Example 2
<a name="js-id4"></a>

The following example is a function request handler for a GraphQL mutation `updateItem(id: ID!, title: String, author: String, expectedVersion: Int!)`.

This is a complex example that inspects the arguments and dynamically generates the update expression that only includes the arguments that have been provided by the client. For example, if `title` and `author` are omitted, they are not updated. If an argument is specified but its value is `null`, then that field is deleted from the object in DynamoDB. Finally, the operation has a condition, which verifies whether the item currently in DynamoDB has the `version` field set to `expectedVersion`:

```
import { util } from '@aws-appsync/utils';
export function request(ctx) {
  const { args: { input: { id, ...values } } } = ctx;

  const condition = {
    id: { attributeExists: true },
    version: { eq: values.expectedVersion },
  };
  values.expectedVersion += 1;
  return dynamodbUpdateRequest({ keys: { id }, values, condition });
}


/**
 * Helper function to update an item
 * @returns an UpdateItem request
 */
function dynamodbUpdateRequest(params) {
  const { keys, values, condition: inCondObj } = params;

  const sets = [];
  const removes = [];
  const expressionNames = {};
  const expValues = {};

  // Iterate through the keys of the values
  for (const [key, value] of Object.entries(values)) {
    expressionNames[`#${key}`] = key;
    if (value) {
      sets.push(`#${key} = :${key}`);
      expValues[`:${key}`] = value;
    } else {
      removes.push(`#${key}`);
    }
  }

  let expression = sets.length ? `SET ${sets.join(', ')}` : '';
  expression += removes.length ? ` REMOVE ${removes.join(', ')}` : '';

  const condition = JSON.parse(
    util.transform.toDynamoDBConditionExpression(inCondObj)
  );

  return {
    operation: 'UpdateItem',
    key: util.dynamodb.toMapValues(keys),
    condition,
    update: {
      expression,
      expressionNames,
      expressionValues: util.dynamodb.toMapValues(expValues),
    },
  };
}
```

For more information about the DynamoDB `UpdateItem` API, see the [DynamoDB API documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html).

# DeleteItem
<a name="js-aws-appsync-resolver-reference-dynamodb-deleteitem"></a>

The `DeleteItem` request lets you tell the AWS AppSync DynamoDB function to make a `DeleteItem` request to DynamoDB, and enables you to specify the following:
+ The key of the item in DynamoDB
+ Conditions for the operation to succeed

The `DeleteItem` request has the following structure:

```
type DynamoDBDeleteItemRequest = {
  operation: 'DeleteItem';
  key: { [key: string]: any };
  condition?: ConditionCheckExpression;
  customPartitionKey?: string;
  populateIndexFields?: boolean;
  _version?: number;
};
```

The fields are defined as follows:

## DeleteItem fields
<a name="js-deleteitem-list"></a>

### DeleteItem fields list
<a name="js-deleteitem-list-col"></a>

** `operation` **  
The DynamoDB operation to perform. To perform the `DeleteItem` DynamoDB operation, this must be set to `DeleteItem`. This value is required.

** `key` **  
The key of the item in DynamoDB. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about specifying a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This value is required.

** `condition` **  
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. If no condition is specified, the `DeleteItem` request deletes an item regardless of its current state. For more information about conditions, see [Condition expressions](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-condition-expressions). This value is optional.

** `_version` **  
A numeric value that represents the latest known version of an item. This value is optional. This field is used for *Conflict Detection* and is only supported on versioned data sources.

**`customPartitionKey`**  
When enabled, this string value modifies the format of the `ds_sk` and `ds_pk` records used by the delta sync table when versioning has been enabled (for more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*). When enabled, the processing of the `populateIndexFields` entry is also enabled. This field is optional.

**`populateIndexFields`**  
A boolean value that, when enabled **along with the `customPartitionKey`**, creates new entries for each record in the delta sync table, specifically in the `gsi_ds_pk` and `gsi_ds_sk` columns. For more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*. This field is optional. 

The item deleted from DynamoDB is automatically converted into GraphQL and JSON primitive types and is available in the context result (`context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-responses).

For more information about JavaScript resolvers, see [JavaScript resolvers overview](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html).

## Example 1
<a name="js-id6"></a>

The following example is a function request handler for a GraphQL mutation `deleteItem(id: ID!)`. If an item exists with this ID, it’s deleted.

```
import { util } from '@aws-appsync/utils';
export function request(ctx) {
  return {
    operation: 'DeleteItem',
    key: util.dynamodb.toMapValues({ id: ctx.args.id }),
  };
}
```

## Example 2
<a name="js-id7"></a>

The following example is a function request handler for a GraphQL mutation `deleteItem(id: ID!, expectedVersion: Int!)`. If an item exists with this ID, it’s deleted, but only if its `version` field set to `expectedVersion`:

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const { id, expectedVersion } = ctx.args;
  const condition = {
    id: { attributeExists: true },
    version: { eq: expectedVersion },
  };
  return {
    operation: 'DeleteItem',
    key: util.dynamodb.toMapValues({ id }),
    condition: util.transform.toDynamoDBConditionExpression(condition),
  };
}
```

For more information about the DynamoDB `DeleteItem` API, see the [DynamoDB API documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html).

# Query
<a name="js-aws-appsync-resolver-reference-dynamodb-query"></a>

The `Query` request object lets you tell the AWS AppSync DynamoDB resolver to make a `Query` request to DynamoDB, and enables you to specify the following:
+ Key expression
+ Which index to use
+ Any additional filter
+ How many items to return
+ Whether to use consistent reads
+ query direction (forward or backward)
+ Pagination token

The `Query` request object has the following structure:

```
type DynamoDBQueryRequest = {
  operation: 'Query';
  query: {
    expression: string;
    expressionNames?: { [key: string]: string };
    expressionValues?: { [key: string]: any };
  };
  index?: string;
  nextToken?: string;
  limit?: number;
  scanIndexForward?: boolean;
  consistentRead?: boolean;
  select?: 'ALL_ATTRIBUTES' | 'ALL_PROJECTED_ATTRIBUTES' | 'SPECIFIC_ATTRIBUTES';
  filter?: {
    expression: string;
    expressionNames?: { [key: string]: string };
    expressionValues?: { [key: string]: any };
  };
  projection?: {
    expression: string;
    expressionNames?: { [key: string]: string };
  };
};
```

The fields are defined as follows:

## Query fields
<a name="js-query-list"></a>

### Query fields list
<a name="js-query-list-col"></a>

** `operation` **  
The DynamoDB operation to perform. To perform the `Query` DynamoDB operation, this must be set to `Query`. This value is required.

** `query` **  
The `query` section lets you specify a key condition expression that describes which items to retrieve from DynamoDB. For more information about how to write key condition expressions, see the [DynamoDB KeyConditions documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.KeyConditions.html) . This section must be specified.    
** `expression` **  
The query expression. This field must be specified.  
** `expressionNames` **  
The substitutions for expression attribute *name* placeholders, in the form of key-value pairs. The key corresponds to a name placeholder used in the `expression`, and the value must be a string corresponding to the attribute name of the item in DynamoDB. This field is optional, and should only be populated with substitutions for expression attribute name placeholders used in the `expression`.  
** `expressionValues` **  
The substitutions for expression attribute *value* placeholders, in the form of key-value pairs. The key corresponds to a value placeholder used in the `expression`, and the value must be a typed value. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This value is required. This field is optional, and should only be populated with substitutions for expression attribute value placeholders used in the `expression`.

** `filter` **  
An additional filter that can be used to filter the results from DynamoDB before they are returned. For more information about filters, see [Filters](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-filter). This field is optional.

** `index` **  
The name of the index to query. The DynamoDB query operation allows you to scan on Local Secondary Indexes and Global Secondary Indexes in addition to the primary key index for a hash key. If specified, this tells DynamoDB to query the specified index. If omitted, the primary key index is queried.

** `nextToken` **  
The pagination token to continue a previous query. This would have been obtained from a previous query. This field is optional.

** `limit` **  
The maximum number of items to evaluate (not necessarily the number of matching items). This field is optional.

** `scanIndexForward` **  
A boolean indicating whether to query forwards or backwards. This field is optional, and defaults to `true`.

** `consistentRead` **  
A boolean indicating whether to use consistent reads when querying DynamoDB. This field is optional, and defaults to `false`.

** `select` **  
By default, the AWS AppSync DynamoDB resolver only returns attributes that are projected into the index. If more attributes are required, you can set this field. This field is optional. The supported values are:    
** `ALL_ATTRIBUTES` **  
Returns all of the item attributes from the specified table or index. If you query a local secondary index, DynamoDB fetches the entire item from the parent table for each matching item in the index. If the index is configured to project all item attributes, all of the data can be obtained from the local secondary index and no fetching is required.  
** `ALL_PROJECTED_ATTRIBUTES` **  
Allowed only when querying an index. Retrieves all attributes that have been projected into the index. If the index is configured to project all attributes, this return value is equivalent to specifying `ALL_ATTRIBUTES`.  
**`SPECIFIC_ATTRIBUTES`**  
Returns only the attributes listed in the `projection`'s `expression`. This return value is equivalent to specifying the `projection`'s `expression` without specifying any value for `Select`.

**`projection`**  
A projection that's used to specify the attributes to return from the DynamoDB operation. For more information about projections, see [Projections](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-projections). This field is optional.

The results from DynamoDB are automatically converted into GraphQL and JSON primitive types and are available in the context result (`context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-responses).

For more information about JavaScript resolvers, see [JavaScript resolvers overview](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html).

The results have the following structure:

```
{
    items = [ ... ],
    nextToken = "a pagination token",
    scannedCount = 10
}
```

The fields are defined as follows:

** `items` **  
A list containing the items returned by the DynamoDB query.

** `nextToken` **  
If there might be more results, `nextToken` contains a pagination token that you can use in another request. Note that AWS AppSync encrypts and obfuscates the pagination token returned from DynamoDB. This prevents your table data from being inadvertently leaked to the caller. Also note that these pagination tokens cannot be used across different functions or resolvers.

** `scannedCount` **  
The number of items that matched the query condition expression, before a filter expression (if present) was applied.

## Example
<a name="js-id9"></a>

The following example is a function request handler for a GraphQL query `getPosts(owner: ID!)`.

In this example, a global secondary index on a table is queried to return all posts owned by the specified ID.

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const { owner } = ctx.args;
  return {
    operation: 'Query',
    query: {
      expression: 'ownerId = :ownerId',
      expressionValues: util.dynamodb.toMapValues({ ':ownerId': owner }),
    },
    index: 'owner-index',
  };
}
```

For more information about the DynamoDB `Query` API, see the [DynamoDB API documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html).

# Scan
<a name="js-aws-appsync-resolver-reference-dynamodb-scan"></a>

The `Scan` request lets you tell the AWS AppSync DynamoDB function to make a `Scan` request to DynamoDB, and enables you to specify the following:
+ A filter to exclude results
+ Which index to use
+ How many items to return
+ Whether to use consistent reads
+ Pagination token
+ Parallel scans

The `Scan` request object has the following structure:

```
type DynamoDBScanRequest = {
  operation: 'Scan';
  index?: string;
  limit?: number;
  consistentRead?: boolean;
  nextToken?: string;
  totalSegments?: number;
  segment?: number;
  filter?: {
    expression: string;
    expressionNames?: { [key: string]: string };
    expressionValues?: { [key: string]: any };
  };
  projection?: {
    expression: string;
    expressionNames?: { [key: string]: string };
  };
};
```

The fields are defined as follows:

## Scan fields
<a name="js-scan-list"></a>

### Scan fields list
<a name="js-scan-list-col"></a>

** `operation` **  
The DynamoDB operation to perform. To perform the `Scan` DynamoDB operation, this must be set to `Scan`. This value is required.

** `filter` **  
A filter that can be used to filter the results from DynamoDB before they are returned. For more information about filters, see [Filters](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-filter). This field is optional.

** `index` **  
The name of the index to query. The DynamoDB query operation allows you to scan on Local Secondary Indexes and Global Secondary Indexes in addition to the primary key index for a hash key. If specified, this tells DynamoDB to query the specified index. If omitted, the primary key index is queried.

** `limit` **  
The maximum number of items to evaluate at a single time. This field is optional.

** `consistentRead` **  
A Boolean that indicates whether to use consistent reads when querying DynamoDB. This field is optional, and defaults to `false`.

** `nextToken` **  
The pagination token to continue a previous query. This would have been obtained from a previous query. This field is optional.

** `select` **  
By default, the AWS AppSync DynamoDB function only returns whatever attributes are projected into the index. If more attributes are required, then this field can be set. This field is optional. The supported values are:    
** `ALL_ATTRIBUTES` **  
Returns all of the item attributes from the specified table or index. If you query a local secondary index, DynamoDB fetches the entire item from the parent table for each matching item in the index. If the index is configured to project all item attributes, all of the data can be obtained from the local secondary index and no fetching is required.  
** `ALL_PROJECTED_ATTRIBUTES` **  
Allowed only when querying an index. Retrieves all attributes that have been projected into the index. If the index is configured to project all attributes, this return value is equivalent to specifying `ALL_ATTRIBUTES`.  
**`SPECIFIC_ATTRIBUTES`**  
Returns only the attributes listed in the `projection`'s `expression`. This return value is equivalent to specifying the `projection`'s `expression` without specifying any value for `Select`.

** `totalSegments` **  
The number of segments to partition the table by when performing a parallel scan. This field is optional, but must be specified if `segment` is specified.

** `segment` **  
The table segment in this operation when performing a parallel scan. This field is optional, but must be specified if `totalSegments` is specified.

**`projection`**  
A projection that's used to specify the attributes to return from the DynamoDB operation. For more information about projections, see [Projections](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-projections). This field is optional.

The results returned by the DynamoDB scan are automatically converted into GraphQL and JSON primitive types and is available in the context result (`context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-responses).

For more information about JavaScript resolvers, see [JavaScript resolvers overview](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html).

The results have the following structure:

```
{
    items = [ ... ],
    nextToken = "a pagination token",
    scannedCount = 10
}
```

The fields are defined as follows:

** `items` **  
A list containing the items returned by the DynamoDB scan.

** `nextToken` **  
If there might be more results, `nextToken` contains a pagination token that you can use in another request. AWS AppSync encrypts and obfuscates the pagination token returned from DynamoDB. This prevents your table data from being inadvertently leaked to the caller. Also, these pagination tokens can’t be used across different functions or resolvers.

** `scannedCount` **  
The number of items that were retrieved by DynamoDB before a filter expression (if present) was applied.

## Example 1
<a name="js-id11"></a>

The following example is a function request handler for the GraphQL query: `allPosts`.

In this example, all entries in the table are returned.

```
export function request(ctx) {
  return { operation: 'Scan' };
}
```

## Example 2
<a name="js-id12"></a>

The following example is a function request handler for the GraphQL query: `postsMatching(title: String!)`.

In this example, all entries in the table are returned where the title starts with the `title` argument.

```
export function request(ctx) {
  const { title } = ctx.args;
  const filter = { filter: { beginsWith: title } };
  return {
    operation: 'Scan',
    filter: JSON.parse(util.transform.toDynamoDBFilterExpression(filter)),
  };
}
```

For more information about the DynamoDB `Scan` API, see the [DynamoDB API documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html).

# Sync
<a name="js-aws-appsync-resolver-reference-dynamodb-sync"></a>

The `Sync` request object lets you retrieve all the results from a DynamoDB table and then receive only the data altered since your last query (the delta updates). `Sync` requests can only be made to versioned DynamoDB data sources. You can specify the following:
+ A filter to exclude results
+ How many items to return
+ Pagination Token
+ When your last `Sync` operation was started

The `Sync` request object has the following structure:

```
type DynamoDBSyncRequest = {
  operation: 'Sync';
  basePartitionKey?: string;
  deltaIndexName?: string;
  limit?: number;
  nextToken?: string;
  lastSync?: number;
  filter?: {
    expression: string;
    expressionNames?: { [key: string]: string };
    expressionValues?: { [key: string]: any };
  };
};
```

The fields are defined as follows:

## Sync fields
<a name="js-sync-list"></a>

### Sync fields list
<a name="js-sync-list-col"></a>

** `operation` **  
The DynamoDB operation to perform. To perform the `Sync` operation, this must be set to `Sync`. This value is required.

** `filter` **  
A filter that can be used to filter the results from DynamoDB before they are returned. For more information about filters, see [Filters](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-filter). This field is optional.

** `limit` **  
The maximum number of items to evaluate at a single time. This field is optional. If omitted, the default limit will be set to `100` items. The maximum value for this field is `1000` items.

** `nextToken` **  
The pagination token to continue a previous query. This would have been obtained from a previous query. This field is optional.

** `lastSync` **  
The moment, in epoch milliseconds, when the last successful `Sync` operation started. If specified, only items that have changed after `lastSync` are returned. This field is optional, and should only be populated after retrieving all pages from an initial `Sync` operation. If omitted, results from the *Base* table will be returned, otherwise, results from the *Delta* table will be returned.

**`basePartitionKey`**  
The partition key of the *Base* table used when performing a `Sync` operation. This field allows a `Sync` operation to be performed when the table utilizes a custom partition key. This is an optional field.

**`deltaIndexName`**  
The index used for the `Sync` operation. This index is required to enable a `Sync` operation on the whole delta store table when the table uses a custom partition key. The `Sync` operation will be performed on the GSI (created on `gsi_ds_pk` and `gsi_ds_sk`). This field is optional.

The results returned by the DynamoDB sync are automatically converted into GraphQL and JSON primitive types and are available in the context result (`context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-responses).

For more information about JavaScript resolvers, see [JavaScript resolvers overview](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html).

The results have the following structure:

```
{
    items = [ ... ],
    nextToken = "a pagination token",
    scannedCount = 10,
    startedAt = 1550000000000
}
```

The fields are defined as follows:

** `items` **  
A list containing the items returned by the sync.

** `nextToken` **  
If there might be more results, `nextToken` contains a pagination token that you can use in another request. AWS AppSync encrypts and obfuscates the pagination token returned from DynamoDB. This prevents your table data from being inadvertently leaked to the caller. Also, these pagination tokens can’t be used across different functions or resolvers.

** `scannedCount` **  
The number of items that were retrieved by DynamoDB before a filter expression (if present) was applied.

** `startedAt` **  
The moment, in epoch milliseconds, when the sync operation started that you can store locally and use in another request as your `lastSync` argument. If a pagination token was included in the request, this value will be the same as the one returned by the request for the first page of results.

## Example
<a name="js-id14"></a>

The following example is a function request handler for the GraphQL query: `syncPosts(nextToken: String, lastSync: AWSTimestamp)`.

In this example, if `lastSync` is omitted, all entries in the base table are returned. If `lastSync` is supplied, only the entries in the delta sync table that have changed since `lastSync` are returned.

```
export function request(ctx) {
  const { nextToken, lastSync } = ctx.args;
  return { operation: 'Sync', limit: 100, nextToken, lastSync };
}
```

# BatchGetItem
<a name="js-aws-appsync-resolver-reference-dynamodb-batch-get-item"></a>

The `BatchGetItem` request object lets you tell the AWS AppSync DynamoDB function to make a `BatchGetItem` request to DynamoDB to retrieve multiple items, potentially across multiple tables. For this request object, you must specify the following:
+ The table names where to retrieve the items from
+ The keys of the items to retrieve from each table

The DynamoDB `BatchGetItem` limits apply and **no condition expression** can be provided.

The `BatchGetItem` request object has the following structure:

```
type DynamoDBBatchGetItemRequest = {
  operation: 'BatchGetItem';
  tables: {
    [tableName: string]: {
      keys: { [key: string]: any }[];
      consistentRead?: boolean; 
      projection?: {
        expression: string;
        expressionNames?: { [key: string]: string };
      };
    };
  };
};
```

The fields are defined as follows:

## BatchGetItem fields
<a name="js-BatchGetItem-list"></a>

### BatchGetItem fields list
<a name="js-BatchGetItem-list-col"></a>

** `operation` **  
The DynamoDB operation to perform. To perform the `BatchGetItem` DynamoDB operation, this must be set to `BatchGetItem`. This value is required.

** `tables` **  
The DynamoDB tables to retrieve the items from. The value is a map where table names are specified as the keys of the map. At least one table must be provided. This `tables` value is required.    
** `keys` **  
List of DynamoDB keys representing the primary key of the items to retrieve. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request).  
** `consistentRead` **  
Whether to use a consistent read when executing a *GetItem* operation. This value is optional and defaults to *false*.  
**`projection`**  
A projection that's used to specify the attributes to return from the DynamoDB operation. For more information about projections, see [Projections](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-projections). This field is optional.

Things to remember:
+ If an item has not been retrieved from the table, a *null* element appears in the data block for that table.
+ Invocation results are sorted per table, based on the order in which they were provided inside the request object.
+ Each `Get` command inside a `BatchGetItem` is atomic, however, a batch can be partially processed. If a batch is partially processed due to an error, the unprocessed keys are returned as part of the invocation result inside the *unprocessedKeys* block.
+  `BatchGetItem` is limited to 100 keys.

For the following example function request handler:

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const { authorId, postId } = ctx.args;
  return {
    operation: 'BatchGetItem',
    tables: {
      authors: [util.dynamodb.toMapValues({ authorId })],
      posts: [util.dynamodb.toMapValues({ authorId, postId })],
    },
  };
}
```

The invocation result available in `ctx.result` is as follows:

```
{
   "data": {
     "authors": [null],
     "posts": [
        // Was retrieved
        {
          "authorId": "a1",
          "postId": "p2",
          "postTitle": "title",
          "postDescription": "description",
        }
     ]
   },
   "unprocessedKeys": {
     "authors": [
        // This item was not processed due to an error
        {
          "authorId": "a1"
        }
      ],
     "posts": []
   }
}
```

The `ctx.error` contains details about the error. The keys **data**, **unprocessedKeys**, and each table key that was provided in the result in the function request object are guaranteed to be present in the invocation result. Items that have been deleted appear in the **data** block. Items that haven’t been processed are marked as *null* inside the data block and are placed inside the **unprocessedKeys** block.

# BatchDeleteItem
<a name="js-aws-appsync-resolver-reference-dynamodb-batch-delete-item"></a>

The `BatchDeleteItem` request object lets you tell the AWS AppSync DynamoDB function to make a `BatchWriteItem` request to DynamoDB to delete multiple items, potentially across multiple tables. For this request object, you must specify the following:
+ The table names where to delete the items from
+ The keys of the items to delete from each table

The DynamoDB `BatchWriteItem` limits apply and **no condition expression** can be provided.

The `BatchDeleteItem` request object has the following structure:

```
type DynamoDBBatchDeleteItemRequest = {
  operation: 'BatchDeleteItem';
  tables: {
    [tableName: string]: { [key: string]: any }[];
  };
};
```

The fields are defined as follows:

## BatchDeleteItem fields
<a name="js-BatchDeleteItem-list"></a>

### BatchDeleteItem fields list
<a name="js-BatchDeleteItem-list-col"></a>

** `operation` **  
The DynamoDB operation to perform. To perform the `BatchDeleteItem` DynamoDB operation, this must be set to `BatchDeleteItem`. This value is required.

** `tables` **  
The DynamoDB tables to delete the items from. Each table is a list of DynamoDB keys representing the primary key of the items to delete. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). At least one table must be provided. The `tables` value is required.

Things to remember:
+ Contrary to the `DeleteItem` operation, the fully deleted item isn’t returned in the response. Only the passed key is returned.
+ If an item has not been deleted from the table, a *null* element appears in the data block for that table.
+ Invocation results are sorted per table, based on the order in which they were provided inside the request object.
+ Each `Delete` command inside a `BatchDeleteItem` is atomic. However a batch can be partially processed. If a batch is partially processed due to an error, the unprocessed keys are returned as part of the invocation result inside the *unprocessedKeys* block.
+  `BatchDeleteItem` is limited to 25 keys.
+ This operation **is not** supported when used with conflict detection. Using both at the same time may result in an error.

For the following example function request handler:

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const { authorId, postId } = ctx.args;
  return {
    operation: 'BatchDeleteItem',
    tables: {
      authors: [util.dynamodb.toMapValues({ authorId })],
      posts: [util.dynamodb.toMapValues({ authorId, postId })],
    },
  };
}
```

The invocation result available in `ctx.result` is as follows:

```
{
   "data": {
     "authors": [null],
     "posts": [
        // Was deleted
        {
          "authorId": "a1",
          "postId": "p2"
        }
     ]
   },
   "unprocessedKeys": {
     "authors": [
        // This key was not processed due to an error
        {
          "authorId": "a1"
        }
      ],
     "posts": []
   }
}
```

The `ctx.error` contains details about the error. The keys **data**, **unprocessedKeys**, and each table key that was provided in the function request object are guaranteed to be present in the invocation result. Items that have been deleted are present in the **data** block. Items that haven’t been processed are marked as *null* inside the data block and are placed inside the **unprocessedKeys** block.

# BatchPutItem
<a name="js-aws-appsync-resolver-reference-dynamodb-batch-put-item"></a>

The `BatchPutItem` request object lets you tell the AWS AppSync DynamoDB function to make a `BatchWriteItem` request to DynamoDB to put multiple items, potentially across multiple tables. For this request object, you must specify the following:
+ The table names where to put the items in
+ The full items to put in each table

The DynamoDB `BatchWriteItem` limits apply and **no condition expression** can be provided.

The `BatchPutItem` request object has the following structure:

```
type DynamoDBBatchPutItemRequest = {
  operation: 'BatchPutItem';
  tables: {
    [tableName: string]: { [key: string]: any}[];
  };
};
```

The fields are defined as follows:

## BatchPutItem fields
<a name="js-BatchPutItem-list"></a>

### BatchPutItem fields list
<a name="js-BatchPutItem-list-col"></a>

** `operation` **  
The DynamoDB operation to perform. To perform the `BatchPutItem` DynamoDB operation, this must be set to `BatchPutItem`. This value is required.

** `tables` **  
The DynamoDB tables to put the items in. Each table entry represents a list of DynamoDB items to insert for this specific table. At least one table must be provided. This value is required.

Things to remember:
+ The fully inserted items are returned in the response, if successful.
+ If an item hasn’t been inserted in the table, a *null* element is displayed in the data block for that table.
+ The inserted items are sorted per table, based on the order in which they were provided inside the request object.
+ Each `Put` command inside a `BatchPutItem` is atomic, however, a batch can be partially processed. If a batch is partially processed due to an error, the unprocessed keys are returned as part of the invocation result inside the *unprocessedKeys* block.
+  `BatchPutItem` is limited to 25 items.
+ This operation **is not** supported when used with conflict detection. Using both at the same time may result in an error.

For the following example function request handler:

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const { authorId, postId, name, title } = ctx.args;
  return {
    operation: 'BatchPutItem',
    tables: {
      authors: [util.dynamodb.toMapValues({ authorId, name })],
      posts: [util.dynamodb.toMapValues({ authorId, postId, title })],
    },
  };
}
```

The invocation result available in `ctx.result` is as follows:

```
{
   "data": {
     "authors": [
         null
     ],
     "posts": [
        // Was inserted
        {
          "authorId": "a1",
          "postId": "p2",
          "title": "title"
        }
     ]
   },
   "unprocessedItems": {
     "authors": [
        // This item was not processed due to an error
        {
          "authorId": "a1",
          "name": "a1_name"
        }
      ],
     "posts": []
   }
}
```

The `ctx.error` contains details about the error. The keys **data**, **unprocessedItems**, and each table key that was provided in the request object are guaranteed to be present in the invocation result. Items that have been inserted are in the **data** block. Items that haven’t been processed are marked as *null* inside the data block and are placed inside the **unprocessedItems** block.

# TransactGetItems
<a name="js-aws-appsync-resolver-reference-dynamodb-transact-get-items"></a>

The `TransactGetItems` request object lets you to tell the AWS AppSync DynamoDB function to make a `TransactGetItems` request to DynamoDB to retrieve multiple items, potentially across multiple tables. For this request object, you must specify the following:
+ The table name of each request item where to retrieve the item from
+ The key of each request item to retrieve from each table

The DynamoDB `TransactGetItems` limits apply and **no condition expression** can be provided.

The `TransactGetItems` request object has the following structure:

```
type DynamoDBTransactGetItemsRequest = {
  operation: 'TransactGetItems';
  transactItems: { table: string; key: { [key: string]: any }; projection?: { expression: string; expressionNames?: { [key: string]: string }; }[];
  };
};
```

The fields are defined as follows:

## TransactGetItems fields
<a name="js-TransactGetItems-list"></a>

### TransactGetItems fields list
<a name="js-TransactGetItems-list-col"></a>

** `operation` **  
The DynamoDB operation to perform. To perform the `TransactGetItems` DynamoDB operation, this must be set to `TransactGetItems`. This value is required.

** `transactItems` **  
The request items to include. The value is an array of request items. At least one request item must be provided. This `transactItems` value is required.    
** `table` **  
The DynamoDB table to retrieve the item from. The value is a string of the table name. This `table` value is required.  
** `key` **  
The DynamoDB key representing the primary key of the item to retrieve. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request).  
**`projection`**  
A projection that's used to specify the attributes to return from the DynamoDB operation. For more information about projections, see [Projections](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-projections). This field is optional.

Things to remember:
+ If a transaction succeeds, the order of retrieved items in the `items` block will be the same as the order of request items.
+ Transactions are performed in an all-or-nothing way. If any request item causes an error, the whole transaction will not be performed and error details will be returned.
+ A request item being unable to be retrieved is not an error. Instead, a *null* element appears in the *items* block in the corresponding position.
+ If the error of a transaction is *TransactionCanceledException*, the `cancellationReasons` block will be populated. The order of cancellation reasons in `cancellationReasons` block will be the same as the order of request items.
+  `TransactGetItems` is limited to 100 request items.

For the following example function request handler:

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const { authorId, postId } = ctx.args;
  return {
    operation: 'TransactGetItems',
    transactItems: [
      {
        table: 'posts',
        key: util.dynamodb.toMapValues({ postId }),
      },
      {
        table: 'authors',
        key: util.dynamodb.toMapValues({ authorId }),
      },
    ],
  };
}
```

If the transaction succeeds and only the first requested item is retrieved, the invocation result available in `ctx.result` is as follows:

```
{
    "items": [
       {
           // Attributes of the first requested item
           "post_id": "p1",
           "post_title": "title",
           "post_description": "description"
       },
       // Could not retrieve the second requested item
       null,
    ],
    "cancellationReasons": null
}
```

If the transaction fails due to *TransactionCanceledException* caused by the first request item, the invocation result available in `ctx.result` is as follows:

```
{
    "items": null,
    "cancellationReasons": [
       {
           "type":"Sample error type",
           "message":"Sample error message"
       },
       {
           "type":"None",
           "message":"None"
       }
    ]
}
```

The `ctx.error` contains details about the error. The keys **items** and **cancellationReasons** are guaranteed to be present in `ctx.result`.

# TransactWriteItems
<a name="js-aws-appsync-resolver-reference-dynamodb-transact-write-items"></a>

The `TransactWriteItems` request object lets you tell the AWS AppSync DynamoDB function to make a `TransactWriteItems` request to DynamoDB to write multiple items, potentially to multiple tables. For this request object, you must specify the following:
+ The destination table name of each request item
+ The operation of each request item to perform. There are four types of operations that are supported: *PutItem*, *UpdateItem*, *DeleteItem*, and *ConditionCheck* 
+ The key of each request item to write

The DynamoDB `TransactWriteItems` limits apply.

The `TransactWriteItems` request object has the following structure:

```
type DynamoDBTransactWriteItemsRequest = {
  operation: 'TransactWriteItems';
  transactItems: TransactItem[];
};
type TransactItem =
  | TransactWritePutItem
  | TransactWriteUpdateItem
  | TransactWriteDeleteItem
  | TransactWriteConditionCheckItem;
type TransactWritePutItem = {
  table: string;
  operation: 'PutItem';
  key: { [key: string]: any };
  attributeValues: { [key: string]: string};
  condition?: TransactConditionCheckExpression;
};
type TransactWriteUpdateItem = {
  table: string;
  operation: 'UpdateItem';
  key: { [key: string]: any };
  update: DynamoDBExpression;
  condition?: TransactConditionCheckExpression;
};
type TransactWriteDeleteItem = {
  table: string;
  operation: 'DeleteItem';
  key: { [key: string]: any };
  condition?: TransactConditionCheckExpression;
};
type TransactWriteConditionCheckItem = {
  table: string;
  operation: 'ConditionCheck';
  key: { [key: string]: any };
  condition?: TransactConditionCheckExpression;
};
type TransactConditionCheckExpression = {
  expression: string;
  expressionNames?: { [key: string]: string};
  expressionValues?: { [key: string]: any};
  returnValuesOnConditionCheckFailure: boolean;
};
```

## TransactWriteItems fields
<a name="js-TransactWriteItems-list"></a>

### TransactWriteItems fields list
<a name="js-TransactWriteItems-list-col"></a>

**The fields are defined as follows: **    
** `operation` **  
The DynamoDB operation to perform. To perform the `TransactWriteItems` DynamoDB operation, this must be set to `TransactWriteItems`. This value is required.  
** `transactItems` **  
The request items to include. The value is an array of request items. At least one request item must be provided. This `transactItems` value is required.  
For `PutItem`, the fields are defined as follows:    
** `table` **  
The destination DynamoDB table. The value is a string of the table name. This `table` value is required.  
** `operation` **  
The DynamoDB operation to perform. To perform the `PutItem` DynamoDB operation, this must be set to `PutItem`. This value is required.  
** `key` **  
The DynamoDB key representing the primary key of the item to put. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This value is required.  
** `attributeValues` **  
The rest of the attributes of the item to be put into DynamoDB. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This field is optional.  
** `condition` **  
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. If no condition is specified, the `PutItem` request overwrites any existing entry for that item. You can specify whether to retrieve the existing item back when condition check fails. For more information about transactional conditions, see [Transaction condition expressions](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-transaction-condition-expressions). This value is optional.
For `UpdateItem`, the fields are defined as follows:    
** `table` **  
The DynamoDB table to update. The value is a string of the table name. This `table` value is required.  
** `operation` **  
The DynamoDB operation to perform. To perform the `UpdateItem` DynamoDB operation, this must be set to `UpdateItem`. This value is required.  
** `key` **  
The DynamoDB key representing the primary key of the item to update. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This value is required.  
** `update` **  
The `update` section lets you specify an update expression that describes how to update the item in DynamoDB. For more information about how to write update expressions, see the [DynamoDB UpdateExpressions documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html). This section is required.  
** `condition` **  
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. If no condition is specified, the `UpdateItem` request updates the existing entry regardless of its current state. You can specify whether to retrieve the existing item back when condition check fails. For more information about transactional conditions, see [Transaction condition expressions](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-transaction-condition-expressions). This value is optional.
For `DeleteItem`, the fields are defined as follows:    
** `table` **  
The DynamoDB table in which to delete the item. The value is a string of the table name. This `table` value is required.  
** `operation` **  
The DynamoDB operation to perform. To perform the `DeleteItem` DynamoDB operation, this must be set to `DeleteItem`. This value is required.  
** `key` **  
The DynamoDB key representing the primary key of the item to delete. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This value is required.  
** `condition` **  
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. If no condition is specified, the `DeleteItem` request deletes an item regardless of its current state. You can specify whether to retrieve the existing item back when condition check fails. For more information about transactional conditions, see [Transaction condition expressions](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-transaction-condition-expressions). This value is optional.
For `ConditionCheck`, the fields are defined as follows:    
** `table` **  
The DynamoDB table in which to check the condition. The value is a string of the table name. This `table` value is required.  
** `operation` **  
The DynamoDB operation to perform. To perform the `ConditionCheck` DynamoDB operation, this must be set to `ConditionCheck`. This value is required.  
** `key` **  
The DynamoDB key representing the primary key of the item to condition check. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This value is required.  
** `condition` **  
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. You can specify whether to retrieve the existing item back when condition check fails. For more information about transactional conditions, see [Transaction condition expressions](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-transaction-condition-expressions). This value is required.

Things to remember:
+ Only keys of request items are returned in the response, if successful. The order of keys will be the same as the order of request items.
+ Transactions are performed in an all-or-nothing way. If any request item causes an error, the whole transaction will not be performed and error details will be returned.
+ No two request items can target the same item. Otherwise they will cause *TransactionCanceledException* error.
+ If the error of a transaction is *TransactionCanceledException*, the `cancellationReasons` block will be populated. If a request item’s condition check fails **and** you did not specify `returnValuesOnConditionCheckFailure` to be `false`, the item existing in the table will be retrieved and stored in `item` at the corresponding position of `cancellationReasons` block.
+  `TransactWriteItems` is limited to 100 request items.
+ This operation **is not** supported when used with conflict detection. Using both at the same time may result in an error.

For the following example function request handler:

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const { authorId, postId, title, description, oldTitle, authorName } = ctx.args;
  return {
    operation: 'TransactWriteItems',
    transactItems: [
      {
        table: 'posts',
        operation: 'PutItem',
        key: util.dynamodb.toMapValues({ postId }),
        attributeValues: util.dynamodb.toMapValues({ title, description }),
        condition: util.transform.toDynamoDBConditionExpression({
          title: { eq: oldTitle },
        }),
      },
      {
        table: 'authors',
        operation: 'UpdateItem',
        key: util.dynamodb.toMapValues({ authorId }),
        update: {
          expression: 'SET authorName = :name',
          expressionValues: util.dynamodb.toMapValues({ ':name': authorName }),
        },
      },
    ],
  };
}
```

If the transaction succeeds, the invocation result available in `ctx.result` is as follows:

```
{
    "keys": [
       // Key of the PutItem request
       {
           "post_id": "p1",
       },
       // Key of the UpdateItem request
       {
           "author_id": "a1"
       }
    ],
    "cancellationReasons": null
}
```

If the transaction fails due to condition check failure of the `PutItem` request, the invocation result available in `ctx.result` is as follows:

```
{
    "keys": null,
    "cancellationReasons": [
       {
           "item": {
               "post_id": "p1",
               "post_title": "Actual old title",
               "post_description": "Old description"
           },
           "type": "ConditionCheckFailed",
           "message": "The condition check failed."
       },
       {
           "type": "None",
           "message": "None"
       }
    ]
}
```

The `ctx.error` contains details about the error. The keys **keys** and **cancellationReasons** are guaranteed to be present in `ctx.result`.

# Type system (request mapping)
<a name="js-aws-appsync-resolver-reference-dynamodb-typed-values-request"></a>

When using the AWS AppSync DynamoDB function to call your DynamoDB tables, AWS AppSync needs to know the type of each value to use in that call. This is because DynamoDB supports more type primitives than GraphQL or JSON (such as sets and binary data). AWS AppSync needs some hints when translating between GraphQL and DynamoDB, otherwise it would have to make some assumptions on how data is structured in your table.

For more information about DynamoDB data types, see the DynamoDB [Data type descriptors](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.LowLevelAPI.html#Programming.LowLevelAPI.DataTypeDescriptors) and [Data types](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) documentation.

A DynamoDB value is represented by a JSON object containing a single key-value pair. The key specifies the DynamoDB type, and the value specifies the value itself. In the following example, the key `S` denotes that the value is a string, and the value `identifier` is the string value itself.

```
{ "S" : "identifier" }
```

Note that the JSON object cannot have more than one key-value pair. If more than one key-value pair is specified, the request object isn’t parsed.

A DynamoDB value is used anywhere in a request object where you need to specify a value. Some places where you need to do this include: `key` and `attributeValue` sections, and the `expressionValues` section of expression sections. In the following example, the DynamoDB String value `identifier` is being assigned to the `id` field in a `key` section (perhaps in a `GetItem` request object).

```
"key" : {
   "id" : { "S" : "identifier" }
}
```

 **Supported Types** 

AWS AppSync supports the following DynamoDB scalar, document, and set types:

**String type `S` **  
A single string value. A DynamoDB String value is denoted by:  

```
{ "S" : "some string" }
```
An example usage is:  

```
"key" : {
   "id" : { "S" : "some string" }
}
```

**String set type `SS` **  
A set of string values. A DynamoDB String Set value is denoted by:  

```
{ "SS" : [ "first value", "second value", ... ] }
```
An example usage is:  

```
"attributeValues" : {
   "phoneNumbers" : { "SS" : [ "+1 555 123 4567", "+1 555 234 5678" ] }
}
```

**Number type `N` **  
A single numeric value. A DynamoDB Number value is denoted by:  

```
{ "N" : 1234 }
```
An example usage is:  

```
"expressionValues" : {
   ":expectedVersion" : { "N" : 1 }
}
```

**Number set type `NS` **  
A set of number values. A DynamoDB Number Set value is denoted by:  

```
{ "NS" : [ 1, 2.3, 4 ... ] }
```
An example usage is:  

```
"attributeValues" : {
   "sensorReadings" : { "NS" : [ 67.8, 12.2, 70 ] }
}
```

**Binary type `B` **  
A binary value. A DynamoDB Binary value is denoted by:  

```
{ "B" : "SGVsbG8sIFdvcmxkIQo=" }
```
Note that the value is actually a string, where the string is the base64-encoded representation of the binary data. AWS AppSync decodes this string back into its binary value before sending it to DynamoDB. AWS AppSync uses the base64 decoding scheme as defined by RFC 2045: any character that isn’t in the base64 alphabet is ignored.  
An example usage is:  

```
"attributeValues" : {
   "binaryMessage" : { "B" : "SGVsbG8sIFdvcmxkIQo=" }
}
```

**Binary set type `BS` **  
A set of binary values. A DynamoDB Binary Set value is denoted by:  

```
{ "BS" : [ "SGVsbG8sIFdvcmxkIQo=", "SG93IGFyZSB5b3U/Cg==" ... ] }
```
Note that the value is actually a string, where the string is the base64-encoded representation of the binary data. AWS AppSync decodes this string back into its binary value before sending it to DynamoDB. AWS AppSync uses the base64 decoding scheme as defined by RFC 2045: any character that is not in the base64 alphabet is ignored.  
An example usage is:  

```
"attributeValues" : {
   "binaryMessages" : { "BS" : [ "SGVsbG8sIFdvcmxkIQo=", "SG93IGFyZSB5b3U/Cg==" ] }
}
```

**Boolean type `BOOL` **  
A Boolean value. A DynamoDB Boolean value is denoted by:  

```
{ "BOOL" : true }
```
Note that only `true` and `false` are valid values.  
An example usage is:  

```
"attributeValues" : {
   "orderComplete" : { "BOOL" : false }
}
```

**List type `L` **  
A list of any other supported DynamoDB value. A DynamoDB List value is denoted by:  

```
{ "L" : [ ... ] }
```
Note that the value is a compound value, where the list can contain zero or more of any supported DynamoDB value (including other lists). The list can also contain a mix of different types.  
An example usage is:  

```
{ "L" : [
      { "S"  : "A string value" },
      { "N"  : 1 },
      { "SS" : [ "Another string value", "Even more string values!" ] }
   ]
}
```

**Map type `M` **  
Representing an unordered collection of key-value pairs of other supported DynamoDB values. A DynamoDB Map value is denoted by:  

```
{ "M" : { ... } }
```
Note that a map can contain zero or more key-value pairs. The key must be a string, and the value can be any supported DynamoDB value (including other maps). The map can also contain a mix of different types.  
An example usage is:  

```
{ "M" : {
      "someString" : { "S"  : "A string value" },
      "someNumber" : { "N"  : 1 },
      "stringSet"  : { "SS" : [ "Another string value", "Even more string values!" ] }
   }
}
```

**Null type `NULL` **  
A null value. A DynamoDB Null value is denoted by:  

```
{ "NULL" : null }
```
An example usage is:  

```
"attributeValues" : {
   "phoneNumbers" : { "NULL" : null }
}
```

For more information about each type, see the [DynamoDB documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html) .

# Type system (response mapping)
<a name="js-aws-appsync-resolver-reference-dynamodb-typed-values-responses"></a>

When receiving a response from DynamoDB, AWS AppSync automatically converts it into GraphQL and JSON primitive types. Each attribute in DynamoDB is decoded and returned in the response handler's context.

For example, if DynamoDB returns the following:

```
{
    "id" : { "S" : "1234" },
    "name" : { "S" : "Nadia" },
    "age" : { "N" : 25 }
}
```

When the result is returned from your pipeline resolver, AWS AppSync converts it into GraphQL and JSON types as:

```
{
    "id" : "1234",
    "name" : "Nadia",
    "age" : 25
}
```

This section explains how AWS AppSync converts the following DynamoDB scalar, document, and set types:

**String type `S` **  
A single string value. A DynamoDB String value is returned as a string.  
For example, if DynamoDB returned the following DynamoDB String value:  

```
{ "S" : "some string" }
```
AWS AppSync converts it to a string:  

```
"some string"
```

**String set type `SS` **  
A set of string values. A DynamoDB String Set value is returned as a list of strings.  
For example, if DynamoDB returned the following DynamoDB String Set value:  

```
{ "SS" : [ "first value", "second value", ... ] }
```
AWS AppSync converts it to a list of strings:  

```
[ "+1 555 123 4567", "+1 555 234 5678" ]
```

**Number type `N` **  
A single numeric value. A DynamoDB Number value is returned as a number.  
For example, if DynamoDB returned the following DynamoDB Number value:  

```
{ "N" : 1234 }
```
AWS AppSync converts it to a number:  

```
1234
```

**Number set type `NS` **  
A set of number values. A DynamoDB Number Set value is returned as a list of numbers.  
For example, if DynamoDB returned the following DynamoDB Number Set value:  

```
{ "NS" : [ 67.8, 12.2, 70 ] }
```
AWS AppSync converts it to a list of numbers:  

```
[ 67.8, 12.2, 70 ]
```

**Binary type `B` **  
A binary value. A DynamoDB Binary value is returned as a string containing the base64 representation of that value.  
For example, if DynamoDB returned the following DynamoDB Binary value:  

```
{ "B" : "SGVsbG8sIFdvcmxkIQo=" }
```
AWS AppSync converts it to a string containing the base64 representation of the value:  

```
"SGVsbG8sIFdvcmxkIQo="
```
Note that the binary data is encoded in the base64 encoding scheme as specified in [RFC 4648](https://tools.ietf.org/html/rfc4648) and [RFC 2045](https://tools.ietf.org/html/rfc2045).

**Binary set type `BS` **  
A set of binary values. A DynamoDB Binary Set value is returned as a list of strings containing the base64 representation of the values.  
For example, if DynamoDB returned the following DynamoDB Binary Set value:  

```
{ "BS" : [ "SGVsbG8sIFdvcmxkIQo=", "SG93IGFyZSB5b3U/Cg==" ... ] }
```
AWS AppSync converts it to a list of strings containing the base64 representation of the values:  

```
[ "SGVsbG8sIFdvcmxkIQo=", "SG93IGFyZSB5b3U/Cg==" ... ]
```
Note that the binary data is encoded in the base64 encoding scheme as specified in [RFC 4648](https://tools.ietf.org/html/rfc4648) and [RFC 2045](https://tools.ietf.org/html/rfc2045).

**Boolean type `BOOL` **  
A Boolean value. A DynamoDB Boolean value is returned as a Boolean.  
For example, if DynamoDB returned the following DynamoDB Boolean value:  

```
{ "BOOL" : true }
```
AWS AppSync converts it to a Boolean:  

```
true
```

**List type `L` **  
A list of any other supported DynamoDB value. A DynamoDB List value is returned as a list of values, where each inner value is also converted.  
For example, if DynamoDB returned the following DynamoDB List value:  

```
{ "L" : [
      { "S"  : "A string value" },
      { "N"  : 1 },
      { "SS" : [ "Another string value", "Even more string values!" ] }
   ]
}
```
AWS AppSync converts it to a list of converted values:  

```
[ "A string value", 1, [ "Another string value", "Even more string values!" ] ]
```

**Map type `M` **  
A key/value collection of any other supported DynamoDB value. A DynamoDB Map value is returned as a JSON object, where each key/value is also converted.  
For example, if DynamoDB returned the following DynamoDB Map value:  

```
{ "M" : {
      "someString" : { "S"  : "A string value" },
      "someNumber" : { "N"  : 1 },
      "stringSet"  : { "SS" : [ "Another string value", "Even more string values!" ] }
   }
}
```
AWS AppSync converts it to a JSON object:  

```
{
   "someString" : "A string value",
   "someNumber" : 1,
   "stringSet"  : [ "Another string value", "Even more string values!" ]
}
```

**Null type `NULL` **  
A null value.  
For example, if DynamoDB returned the following DynamoDB Null value:  

```
{ "NULL" : null }
```
AWS AppSync converts it to a null:  

```
null
```

# Filters
<a name="js-aws-appsync-resolver-reference-dynamodb-filter"></a>

When querying objects in DynamoDB using the `Query` and `Scan` operations, you can optionally specify a `filter` that evaluates the results and returns only the desired values.

The filter property of a `Query` or `Scan` request has the following structure:

```
type DynamoDBExpression = {
  expression: string;
  expressionNames?: { [key: string]: string};
  expressionValues?: { [key: string]: any};
};
```

The fields are defined as follows:

** `expression` **  
The query expression. For more information about how to write filter expressions, see the [DynamoDB QueryFilter](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.QueryFilter.html) and [DynamoDB ScanFilter](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.ScanFilter.html) documentation. This field must be specified.

** `expressionNames` **  
The substitutions for expression attribute *name* placeholders, in the form of key-value pairs. The key corresponds to a name placeholder used in the `expression`. The value must be a string that corresponds to the attribute name of the item in DynamoDB. This field is optional, and should only be populated with substitutions for expression attribute name placeholders used in the `expression`.

** `expressionValues` **  
The substitutions for expression attribute *value* placeholders, in the form of key-value pairs. The key corresponds to a value placeholder used in the `expression`, and the value must be a typed value. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This must be specified. This field is optional, and should only be populated with substitutions for expression attribute value placeholders used in the `expression`.

## Example
<a name="js-id18"></a>

The following example is a filter section for a request, where entries retrieved from DynamoDB are only returned if the title starts with the `title` argument. 

Here we use the `util.transform.toDynamoDBFilterExpression` to automatically create a filter from an object:

```
const filter = util.transform.toDynamoDBFilterExpression({
  title: { beginsWith: 'far away' },
});

const request = {};
request.filter = JSON.parse(filter);
```

This generates the following filter:

```
{
  "filter": {
    "expression": "(begins_with(#title,:title_beginsWith))",
    "expressionNames": { "#title": "title" },
    "expressionValues": {
      ":title_beginsWith": { "S": "far away" }
    }
  }
}
```

# Condition expressions
<a name="js-aws-appsync-resolver-reference-dynamodb-condition-expressions"></a>

When you mutate objects in DynamoDB by using the `PutItem`, `UpdateItem`, and `DeleteItem` DynamoDB operations, you can optionally specify a condition expression that controls whether the request should succeed or not, based on the state of the object already in DynamoDB before the operation is performed.

The AWS AppSync DynamoDB function allows a condition expression to be specified in `PutItem`, `UpdateItem`, and `DeleteItem` request objects, and also a strategy to follow if the condition fails and the object was not updated.

## Example 1
<a name="js-id19"></a>

The following `PutItem` request object doesn’t have a condition expression. As a result, it puts an item in DynamoDB even if an item with the same key already exists, thereby overwriting the existing item.

```
import { util } from '@aws-appsync/utils';
export function request(ctx) {
  const { foo, bar, ...values} = ctx.args
  return {
    operation: 'PutItem',
    key: util.dynamodb.toMapValues({foo, bar}),
    attributeValues: util.dynamodb.toMapValues(values),
  };
}
```

## Example 2
<a name="js-id20"></a>

The following `PutItem` object does have a condition expression that allows the operation succeed only if an item with the same key does *not* exist in DynamoDB.

```
import { util } from '@aws-appsync/utils';
export function request(ctx) {
  const { foo, bar, ...values} = ctx.args
  return {
    operation: 'PutItem',
    key: util.dynamodb.toMapValues({foo, bar}),
    attributeValues: util.dynamodb.toMapValues(values),
    condition: { expression: "attribute_not_exists(id)" }
  };
}
```

By default, if the condition check fails, the AWS AppSync DynamoDB function provides an error for the mutation.

However, the AWS AppSync DynamoDB function offers some additional features to help developers handle some common edge cases:
+ If AWS AppSync DynamoDB functions can determine that the current value in DynamoDB matches the desired result, it treats the operation as if it succeeded anyway.
+ Instead of returning an error, you can configure the function to invoke a custom Lambda function to decide how the AWS AppSync DynamoDB function should handle the failure.

These are described in greater detail in the [Handling a condition check failure](#condition-check) section.

For more information about DynamoDB conditions expressions, see the [DynamoDB ConditionExpressions documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html) .

## Specifying a condition
<a name="js-aws-appsync-resolver-reference-dynamodb-condition-specification"></a>

The `PutItem`, `UpdateItem`, and `DeleteItem` request objects all allow an optional `condition` section to be specified. If omitted, no condition check is made. If specified, the condition must be true for the operation to succeed.

A `condition` section has the following structure:

```
type ConditionCheckExpression = {
  expression: string;
  expressionNames?: { [key: string]: string};
  expressionValues?: { [key: string]: any};
  equalsIgnore?: string[];
  consistentRead?: boolean;
  conditionalCheckFailedHandler?: {
    strategy: 'Custom' | 'Reject';
    lambdaArn?: string;
  };
};
```

The following fields specify the condition:

** `expression` **  
The update expression itself. For more information about how to write condition expressions, see the [DynamoDB ConditionExpressions documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html) . This field must be specified.

** `expressionNames` **  
The substitutions for expression attribute name placeholders, in the form of key-value pairs. The key corresponds to a name placeholder used in the *expression*, and the value must be a string corresponding to the attribute name of the item in DynamoDB. This field is optional, and should only be populated with substitutions for expression attribute name placeholders used in the *expression*.

** `expressionValues` **  
The substitutions for expression attribute value placeholders, in the form of key-value pairs. The key corresponds to a value placeholder used in the expression, and the value must be a typed value. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This must be specified. This field is optional, and should only be populated with substitutions for expression attribute value placeholders used in the expression.

The remaining fields tell the AWS AppSync DynamoDB function how to handle a condition check failure:

** `equalsIgnore` **  
When a condition check fails when using the `PutItem` operation, the AWS AppSync DynamoDB function compares the item currently in DynamoDB against the item it tried to write. If they are the same, it treats the operation as it if succeeded anyway. You can use the `equalsIgnore` field to specify a list of attributes that AWS AppSync should ignore when performing that comparison. For example, if the only difference was a `version` attribute, it treats the operation as if it succeeded. This field is optional.

** `consistentRead` **  
When a condition check fails, AWS AppSync gets the current value of the item from DynamoDB using a strongly consistent read. You can use this field to tell the AWS AppSync DynamoDB function to use an eventually consistent read instead. This field is optional, and defaults to `true`.

** `conditionalCheckFailedHandler` **  
This section allows you to specify how the AWS AppSync DynamoDB function treats a condition check failure after it has compared the current value in DynamoDB against the expected result. This section is optional. If omitted, it defaults to a strategy of `Reject`.    
** `strategy` **  
The strategy the AWS AppSync DynamoDB function takes after it has compared the current value in DynamoDB against the expected result. This field is required and has the following possible values:    
** `Reject` **  
The mutation fails, and an error is added to the GraphQL response.  
** `Custom` **  
The AWS AppSync DynamoDB function invokes a custom Lambda function to decide how to handle the condition check failure. When the `strategy` is set to `Custom`, the `lambdaArn` field must contain the ARN of the Lambda function to invoke.  
** `lambdaArn` **  
The ARN of the Lambda function to invoke that determines how the AWS AppSync DynamoDB function should handle the condition check failure. This field must only be specified when `strategy` is set to `Custom`. For more information about how to use this feature, see [Handling a condition check failure](#condition-check).

## Handling a condition check failure
<a name="js-aws-appsync-resolver-reference-dynamodb-condition-handling"></a>

When a condition check fails, the AWS AppSync DynamoDB function can pass on the error for the mutation and the current value of the object by using the `util.appendError` utility. However, the AWS AppSync DynamoDB function offers some additional features to help developers handle some common edge cases:
+ If AWS AppSync DynamoDB functions can determine that the current value in DynamoDB matches the desired result, it treats the operation as if it succeeded anyway.
+ Instead of returning an error, you can configure the function to invoke a custom Lambda function to decide how the AWS AppSync DynamoDB function should handle the failure.

The flowchart for this process is:

![\[Flowchart showing process for transforming requests with mutation attempts and value checks.\]](http://docs.aws.amazon.com/appsync/latest/devguide/images/DynamoDB-condition-check-failure-handling.png)


### Checking for the desired result
<a name="js-checking-for-the-desired-result"></a>

When the condition check fails, the AWS AppSync DynamoDB function performs a `GetItem` DynamoDB request to get the current value of the item from DynamoDB. By default, it uses a strongly consistent read, however this can be configured using the `consistentRead` field in the `condition` block and compare it against the expected result:
+ For the `PutItem` operation, the AWS AppSync DynamoDB function compares the current value against the one it attempted to write, excluding any attributes listed in `equalsIgnore` from the comparison. If the items are the same, it treats the operation as successful and returns the item that was retrieved from DynamoDB. Otherwise, it follows the configured strategy.

  For example, if the `PutItem` request object looked like the following:

  ```
  import { util } from '@aws-appsync/utils';
  export function request(ctx) {
    const { id, name, version} = ctx.args
    return {
      operation: 'PutItem',
      key: util.dynamodb.toMapValues({foo, bar}),
      attributeValues: util.dynamodb.toMapValues({ name, version: version+1 }),
      condition: { 
        expression: "version = :expectedVersion",
        expressionValues: util.dynamodb.toMapValues({':expectedVersion': version}),
        equalsIgnore: ['version']
      }
    };
  }
  ```

  And the item currently in DynamoDB looked like the following:

  ```
  {
     "id" : { "S" : "1" },
     "name" : { "S" : "Steve" },
     "version" : { "N" : 8 }
  }
  ```

  The AWS AppSync DynamoDB function would compare the item it tried to write against the current value, see that the only difference was the `version` field, but because it’s configured to ignore the `version` field, it treats the operation as successful and returns the item that was retrieved from DynamoDB.
+ For the `DeleteItem` operation, the AWS AppSync DynamoDB function checks to verify that an item was returned from DynamoDB. If no item was returned, it treats the operation as successful. Otherwise, it follows the configured strategy.
+ For the `UpdateItem` operation, the AWS AppSync DynamoDB function does not have enough information to determine if the item currently in DynamoDB matches the expected result, and therefore follows the configured strategy.

If the current state of the object in DynamoDB is different from the expected result, the AWS AppSync DynamoDB function follows the configured strategy, to either reject the mutation or invoke a Lambda function to determine what to do next.

### Following the “reject” strategy
<a name="js-following-the-reject-strategy"></a>

When following the `Reject` strategy, the AWS AppSync DynamoDB function returns an error for the mutation.

For example, given the following mutation request:

```
mutation {
    updatePerson(id: 1, name: "Steve", expectedVersion: 1) {
        Name
        theVersion
    }
}
```

If the item returned from DynamoDB looks like the following:

```
{
   "id" : { "S" : "1" },
   "name" : { "S" : "Steve" },
   "version" : { "N" : 8 }
}
```

And the function response handler looks like the following:

```
import { util } from '@aws-appsync/utils';
export function response(ctx) {
  const { version, ...values } = ctx.result;
  const result = { ...values, theVersion: version };
  if (ctx.error) {
    if (error) {
      return util.appendError(error.message, error.type, result, null);
    }
  }
  return result
}
```

The GraphQL response looks like the following:

```
{
  "data": null,
  "errors": [
    {
      "message": "The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ)"
      "errorType": "DynamoDB:ConditionalCheckFailedException",
      ...
    }
  ]
}
```

Also, if any fields in the returned object are filled by other resolvers and the mutation had succeeded, they won’t be resolved when the object is returned in the `error` section.

### Following the “custom” strategy
<a name="js-following-the-custom-strategy"></a>

When following the `Custom` strategy, the AWS AppSync DynamoDB function invokes a Lambda function to decide what to do next. The Lambda function chooses one of the following options:
+  `reject` the mutation. This tells the AWS AppSync DynamoDB function to behave as if the configured strategy was `Reject`, returning an error for the mutation and the current value of the object in DynamoDB as described in the previous section.
+  `discard` the mutation. This tells the AWS AppSync DynamoDB function to silently ignore the condition check failure and returns the value in DynamoDB.
+  `retry` the mutation. This tells the AWS AppSync DynamoDB function to retry the mutation with a new request object.

 **The Lambda invocation request**

The AWS AppSync DynamoDB function invokes the Lambda function specified in the `lambdaArn`. It uses the same `service-role-arn` configured on the data source. The payload of the invocation has the following structure:

```
{
    "arguments": { ... },
    "requestMapping": {... },
    "currentValue": { ... },
    "resolver": { ... },
    "identity": { ... }
}
```

The fields are defined as follows:

** `arguments` **  
The arguments from the GraphQL mutation. This is the same as the arguments available to the request object in `context.arguments`.

** `requestMapping` **  
The request object for this operation.

** `currentValue` **  
The current value of the object in DynamoDB.

** `resolver` **  
Information about the AWS AppSync resolver or function.

** `identity` **  
Information about the caller. This is the same as the identity information available to the request object in `context.identity`.

A full example of the payload:

```
{
    "arguments": {
        "id": "1",
        "name": "Steve",
        "expectedVersion": 1
    },
    "requestMapping": {
        "version" : "2017-02-28",
        "operation" : "PutItem",
        "key" : {
           "id" : { "S" : "1" }
        },
        "attributeValues" : {
           "name" : { "S" : "Steve" },
           "version" : { "N" : 2 }
        },
        "condition" : {
           "expression" : "version = :expectedVersion",
           "expressionValues" : {
               ":expectedVersion" : { "N" : 1 }
           },
           "equalsIgnore": [ "version" ]
        }
    },
    "currentValue": {
        "id" : { "S" : "1" },
        "name" : { "S" : "Steve" },
        "version" : { "N" : 8 }
    },
    "resolver": {
        "tableName": "People",
        "awsRegion": "us-west-2",
        "parentType": "Mutation",
        "field": "updatePerson",
        "outputType": "Person"
    },
    "identity": {
        "accountId": "123456789012",
        "sourceIp": "x.x.x.x",
        "user": "AIDAAAAAAAAAAAAAAAAAA",
        "userArn": "arn:aws:iam::123456789012:user/appsync"
    }
}
```

 **The Lambda Invocation Response** 

The Lambda function can inspect the invocation payload and apply any business logic to decide how the AWS AppSync DynamoDB function should handle the failure. There are three options for handling the condition check failure:
+  `reject` the mutation. The response payload for this option must have this structure:

  ```
  {
      "action": "reject"
  }
  ```

  This tells the AWS AppSync DynamoDB function to behave as if the configured strategy was `Reject`, returning an error for the mutation and the current value of the object in DynamoDB, as described in the section above.
+  `discard` the mutation. The response payload for this option must have this structure:

  ```
  {
      "action": "discard"
  }
  ```

  This tells the AWS AppSync DynamoDB function to silently ignore the condition check failure and returns the value in DynamoDB.
+  `retry` the mutation. The response payload for this option must have this structure:

  ```
  {
      "action": "retry",
      "retryMapping": { ... }
  }
  ```

  This tells the AWS AppSync DynamoDB function to retry the mutation with a new request object. The structure of the `retryMapping` section depends on the DynamoDB operation, and is a subset of the full request object for that operation.

  For `PutItem`, the `retryMapping` section has the following structure. For a description of the `attributeValues` field, see [PutItem](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-dynamodb.html#aws-appsync-resolver-mapping-template-reference-dynamodb-putitem).

  ```
  {
      "attributeValues": { ... },
      "condition": {
          "equalsIgnore" = [ ... ],
          "consistentRead" = true
      }
  }
  ```

  For `UpdateItem`, the `retryMapping` section has the following structure. For a description of the `update` section, see [UpdateItem](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-dynamodb.html#aws-appsync-resolver-mapping-template-reference-dynamodb-updateitem).

  ```
  {
      "update" : {
          "expression" : "someExpression"
          "expressionNames" : {
              "#foo" : "foo"
          },
          "expressionValues" : {
              ":bar" : ... typed value
          }
      },
      "condition": {
          "consistentRead" = true
      }
  }
  ```

  For `DeleteItem`, the `retryMapping` section has the following structure.

  ```
  {
      "condition": {
          "consistentRead" = true
      }
  }
  ```

  There is no way to specify a different operation or key to work on. The AWS AppSync DynamoDB function only allows retries of the same operation on the same object. Also, the `condition` section doesn’t allow a `conditionalCheckFailedHandler` to be specified. If the retry fails, the AWS AppSync DynamoDB function follows the `Reject` strategy.

Here is an example Lambda function to deal with a failed `PutItem` request. The business logic looks at who made the call. If it was made by `jeffTheAdmin`, it retries the request, updating the `version` and `expectedVersion` from the item currently in DynamoDB. Otherwise, it rejects the mutation.

```
exports.handler = (event, context, callback) => {
    console.log("Event: "+ JSON.stringify(event));

    // Business logic goes here.

    var response;
    if ( event.identity.user == "jeffTheAdmin" ) {
        response = {
            "action" : "retry",
            "retryMapping" : {
                "attributeValues" : event.requestMapping.attributeValues,
                "condition" : {
                    "expression" : event.requestMapping.condition.expression,
                    "expressionValues" : event.requestMapping.condition.expressionValues
                }
            }
        }
        response.retryMapping.attributeValues.version = { "N" : event.currentValue.version.N + 1 }
        response.retryMapping.condition.expressionValues[':expectedVersion'] = event.currentValue.version

    } else {
        response = { "action" : "reject" }
    }

    console.log("Response: "+ JSON.stringify(response))
    callback(null, response)
};
```

# Transaction condition expressions
<a name="js-aws-appsync-resolver-reference-dynamodb-transaction-condition-expressions"></a>

Transaction condition expressions are available in requests of all four types of operations in `TransactWriteItems`, namely, `PutItem`, `DeleteItem`, `UpdateItem`, and `ConditionCheck`.

For `PutItem`, `DeleteItem`, and `UpdateItem`, the transaction condition expression is optional. For `ConditionCheck`, the transaction condition expression is required.

## Example 1
<a name="js-id22"></a>

The following transactional `DeleteItem` function request handler does not have a condition expression. As a result, it deletes the item in DynamoDB.

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const { postId } = ctx.args;
  return {
    operation: 'TransactWriteItems',
    transactItems: [
      {
        table: 'posts',
        operation: 'DeleteItem',
        key: util.dynamodb.toMapValues({ postId }),
      }
    ],
  };
}
```

## Example 2
<a name="js-id23"></a>

The following transactional `DeleteItem` function request handler does have a transaction condition expression that allows the operation succeed only if the author of that post equals a certain name.

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const { postId, authorName} = ctx.args;
  return {
    operation: 'TransactWriteItems',
    transactItems: [
      {
        table: 'posts',
        operation: 'DeleteItem',
        key: util.dynamodb.toMapValues({ postId }),
        condition: util.transform.toDynamoDBConditionExpression({
          authorName: { eq: authorName },
        }),
      }
    ],
  };
}
```

If the condition check fails, it will cause `TransactionCanceledException` and the error detail will be returned in `ctx.result.cancellationReasons`. Note that by default, the old item in DynamoDB that made condition check fail will be returned in `ctx.result.cancellationReasons`.

## Specifying a condition
<a name="js-id24"></a>

The `PutItem`, `UpdateItem`, and `DeleteItem` request objects all allow an optional `condition` section to be specified. If omitted, no condition check is made. If specified, the condition must be true for the operation to succeed. The `ConditionCheck` must have a `condition` section to be specified. The condition must be true for the whole transaction to succeed.

A `condition` section has the following structure:

```
type TransactConditionCheckExpression = {
  expression: string;
  expressionNames?: { [key: string]: string };
  expressionValues?: { [key: string]: string };
  returnValuesOnConditionCheckFailure: boolean;
};
```

The following fields specify the condition:

** `expression` **  
The update expression itself. For more information about how to write condition expressions, see the [DynamoDB ConditionExpressions documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html) . This field must be specified.

** `expressionNames` **  
The substitutions for expression attribute name placeholders, in the form of key-value pairs. The key corresponds to a name placeholder used in the *expression*, and the value must be a string corresponding to the attribute name of the item in DynamoDB. This field is optional, and should only be populated with substitutions for expression attribute name placeholders used in the *expression*.

** `expressionValues` **  
The substitutions for expression attribute value placeholders, in the form of key-value pairs. The key corresponds to a value placeholder used in the expression, and the value must be a typed value. For more information about how to specify a “typed value”, see [Type system (request mapping)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request). This must be specified. This field is optional, and should only be populated with substitutions for expression attribute value placeholders used in the expression.

** `returnValuesOnConditionCheckFailure` **  
Specify whether to retrieve the item in DynamoDB back when a condition check fails. The retrieved item will be in `ctx.result.cancellationReasons[<index>].item`, where `<index>` is the index of the request item that failed the condition check. This value defaults to true.

# Projections
<a name="js-aws-appsync-resolver-reference-dynamodb-projections"></a>

When reading objects in DynamoDB using the `GetItem`, `Scan`, `Query`, `BatchGetItem`, and `TransactGetItems` operations, you can optionally specify a projection that identifies the attributes that you want. The projection property has the following structure, which is similar to filters: 

```
type DynamoDBExpression = {
  expression: string;
  expressionNames?: { [key: string]: string}
};
```

The fields are defined as follows:

** `expression` **  
The projection expression, which is a string. To retrieve a single attribute, specify its name. For multiple attributes, the names must be comma-separated values. For more information on writing projection expressions, see the [DynamoDB projection expressions](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html) documentation. This field is required. 

** `expressionNames` **  
The substitutions for expression attribute *name* placeholders in the form of key-value pairs. The key corresponds to a name placeholder used in the `expression`. The value must be a string that corresponds to the attribute name of the item in DynamoDB. This field is optional and should only be populated with substitutions for expression attribute name placeholders used in the `expression`. For more information about `expressionNames`, see the [DynamoDB documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ExpressionAttributeNames.html). 

## Example 1
<a name="js-id22"></a>

The following example is a projection section for a JavaScript function in which only the attributes `author` and `id` are returned from DynamoDB:

```
projection : {
    expression : "#author, id",
    expressionNames : {
        "#author" : "author"
    }
}
```

**Tip**  
You can access your GraphQL request selection set using [selectionSetList](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html#aws-appsync-resolver-context-reference-info-js). This field allows you to frame your projection expression dynamically according to your requirements.

**Note**  
While using projection expressions with the `Query` and `Scan` operations, the value for `select` must be `SPECIFIC_ATTRIBUTES`. For more information, see the [DynamoDB documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html#DDB-Query-request-Select).

# AWS AppSync JavaScript resolver function reference for OpenSearch
<a name="resolver-reference-elasticsearch-js"></a>

The AWS AppSync resolver for Amazon OpenSearch Service enables you to use GraphQL to store and retrieve data in existing OpenSearch Service domains in your account. This resolver works by allowing you to map an incoming GraphQL request into an OpenSearch Service request, and then map the OpenSearch Service response back to GraphQL. This section describes the function request and response handlers for the supported OpenSearch Service operations.

## Request
<a name="request-js"></a>

Most OpenSearch Service request objects have a common structure where just a few pieces change. The following example runs a search against an OpenSearch Service domain, where documents are of type `post` and are indexed under `id`. The search parameters are defined in the `body` section, with many of the common query clauses being defined in the `query` field. This example will search for documents containing `"Nadia"`, or `"Bailey"`, or both, in the `author` field of a document:

```
export function request(ctx) {
  return {
    operation: 'GET',
    path: '/id/post/_search',
    params: {
      headers: {},
      queryString: {},
      body: {
        from: 0,
        size: 50,
        query: {
          bool: {
            should: [
              { match: { author: 'Nadia' } },
              { match: { author: 'Bailey' } },
            ],
          },
        },
      },
    },
  };
}
```

## Response
<a name="response-mapping-template"></a>

As with other data sources, OpenSearch Service sends a response to AWS AppSync that needs to be converted to GraphQL. .

Most GraphQL queries are looking for the `_source` field from an OpenSearch Service response. Because you can do searches to return either an individual document or a list of documents, there are two common response patterns used in OpenSearch Service:

 **List of Results** 

```
export function response(ctx) {
  const entries = [];
  for (const entry of ctx.result.hits.hits) {
    entries.push(entry['_source']);
  }
  return entries;
}
```

 **Individual Item** 

```
export function response(ctx) {
  return ctx.result['_source']
}
```

## `operation` field
<a name="operation-field"></a>

**Note**  
This applies only to the Request handler. 

HTTP method or verb (GET, POST, PUT, HEAD or DELETE) that AWS AppSync sends to the OpenSearch Service domain. Both the key and the value must be a string.

```
"operation" : "PUT"
```

## `path` field
<a name="path-field"></a>

**Note**  
This applies only to the Request handler. 

The search path for an OpenSearch Service request from AWS AppSync. This forms a URL for the operation’s HTTP verb. Both the key and the value must be strings.

```
"path" : "/indexname/type"

"path" : "/indexname/type/_search"
```

When the request handler is evaluated, this path is sent as part of the HTTP request, including the OpenSearch Service domain. For example, the previous example might translate to:

```
GET https://opensearch-domain-name.REGION.es.amazonaws.com/indexname/type/_search
```

## `params` field
<a name="params-field"></a>

**Note**  
This applies only to the Request handler. 

Used to specify what action your search performs, most commonly by setting the **query** value inside of the **body**. However, there are several other capabilities that can be configured, such as the formatting of responses.
+  **headers** 

  The header information, as key-value pairs. Both the key and the value must be strings. For example:

  ```
  "headers" : {
      "Content-Type" : "application/json"
  }
  ```

   
**Note**  
AWS AppSync currently supports only JSON as a `Content-Type`.
+  **queryString** 

  Key-value pairs that specify common options, such as code formatting for JSON responses. Both the key and the value must be a string. For example, if you want to get pretty-formatted JSON, you would use:

  ```
  "queryString" : {
      "pretty" : "true"
  }
  ```
+  **body** 

  This is the main part of your request, allowing AWS AppSync to craft a well-formed search request to your OpenSearch Service domain. The key must be a string comprised of an object. A couple of demonstrations are shown below.

 **Example 1** 

Return all documents with a city matching “seattle”:

```
export function request(ctx) {
  return {
    operation: 'GET',
    path: '/id/post/_search',
    params: {
      headers: {},
      queryString: {},
      body: { from: 0, size: 50, query: { match: { city: 'seattle' } } },
    },
  };
}
```

 **Example 2** 

Return all documents matching “washington” as the city or the state:

```
export function request(ctx) {
  return {
    operation: 'GET',
    path: '/id/post/_search',
    params: {
      headers: {},
      queryString: {},
      body: {
        from: 0,
        size: 50,
        query: {
          multi_match: { query: 'washington', fields: ['city', 'state'] },
        },
      },
    },
  };
}
```

## Passing variables
<a name="passing-variables"></a>

**Note**  
This applies only to the Request handler. 

You can also pass variables as part of evaluation in your request handler. For example, suppose you had a GraphQL query such as the following:

```
query {
    searchForState(state: "washington"){
        ...
    }
}
```

The function request handler could be the following:

```
export function request(ctx) {
  return {
    operation: 'GET',
    path: '/id/post/_search',
    params: {
      headers: {},
      queryString: {},
      body: {
        from: 0,
        size: 50,
        query: {
          multi_match: { query: ctx.args.state, fields: ['city', 'state'] },
        },
      },
    },
  };
}
```

# AWS AppSync JavaScript resolver function reference for Lambda
<a name="resolver-reference-lambda-js"></a>

You can use AWS AppSync functions and resolvers to invoke Lambda functions located in your account. You can shape your request payloads and the response from your Lambda functions before returning them to your clients. You can also specify the type of operation to perform in your request object. This section describes the requests for the supported Lambda operations.

## Request object
<a name="request-object-js"></a>

The Lambda request object handles fields related to your Lambda function:

```
export type LambdaRequest = {
  operation: 'Invoke' | 'BatchInvoke';
  invocationType?: 'RequestResponse' | 'Event';
  payload: unknown;
};
```

Here's an example that uses an `invoke` operation with its payload data being the `getPost` field from a GraphQL schema along with its arguments from the context:

```
export function request(ctx) {
  return {
    operation: 'Invoke',
    payload: { field: 'getPost', arguments: ctx.args },
  };
}
```

The entire mapping document is passed as the input to your Lambda function so that the previous example now looks like this:

```
{
  "operation": "Invoke",
  "payload": {
    "field": "getPost",
    "arguments": {
      "input": {
        "id": "postId1",
      }
    }
  }
}
```

### Operation
<a name="operation-js"></a>

The Lambda data source lets you define two operations in the `operation` field: `Invoke` and `BatchInvoke`. The `Invoke` operation lets AWS AppSync know to call your Lambda function for every GraphQL field resolver. `BatchInvoke` instructs AWS AppSync to batch requests for the current GraphQL field. The `operation` field is required.

For `Invoke`, the resolved request matches the input payload of the Lambda function. Let's modify the example above:

```
export function request(ctx) {
  return {
    operation: 'Invoke',
    payload: { field: 'getPost', arguments: ctx.args },
  };
}
```

This is resolved and passed to the Lambda function, which could look something like this:

```
{
  "operation": "Invoke",
  "payload": {
    "arguments": {
      "id": "postId1"
    }
  }
}
```

For `BatchInvoke`, the request is applied to every field resolver in the batch. For conciseness, AWS AppSync merges all the request `payload` values into a list under a single object matching the request object. The following example request handler shows the merge:

```
export function request(ctx) {
  return {
    operation: 'Invoke',
    payload: ctx,
  };
}
```

This request is evaluated and resolved into the following mapping document:

```
{
  "operation": "BatchInvoke",
  "payload": [
    {...}, // context for batch item 1
    {...}, // context for batch item 2
    {...}  // context for batch item 3
  ]
}
```

Each element of the `payload` list corresponds to a single batch item. The Lambda function is also expected to return a list-shaped response matching the order of the items sent in the request:

```
[
  { "data": {...}, "errorMessage": null, "errorType": null }, // result for batch item 1
  { "data": {...}, "errorMessage": null, "errorType": null }, // result for batch item 2
  { "data": {...}, "errorMessage": null, "errorType": null }  // result for batch item 3
]
```

### Payload
<a name="payload-js"></a>

The `payload` field is a container used to pass any data to the Lambda function. If the `operation` field is set to `BatchInvoke`, AWS AppSync wraps the existing `payload` values into a list. The `payload` field is optional.

### Invocation type
<a name="async-invocation-type-js"></a>

The Lambda data source allows you to define two invocation types: `RequestResponse` and `Event`. The invocation types are synonymous with the invocation types defined in the [Lambda API](https://docs.aws.amazon.com//lambda/latest/api/API_Invoke.html). The `RequestResponse` invocation type lets AWS AppSync call your Lambda function synchronously to wait for a response. The `Event` invocation allows you to invoke your Lambda function asynchronously. For more information on how Lambda handles `Event` invocation type requests, see [Asynchronous invocation](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html). The `invocationType` field is optional. If this field is not included in the request, AWS AppSync will default to the `RequestResponse` invocation type.

For any `invocationType` field, the resolved request matches the input payload of the Lambda function. Let's modify the example above:

```
export function request(ctx) {
  return {
    operation: 'Invoke',
    invocationType: 'Event',
    payload: { field: 'getPost', arguments: ctx.args },
  };
}
```

This is resolved and passed to the Lambda function, which could look something like this:

```
{
  "operation": "Invoke",
  "invocationType": "Event",
  "payload": {
    "arguments": {
      "id": "postId1"
    }
  }
}
```

When the `BatchInvoke` operation is used in conjunction with the `Event` invocation type field, AWS AppSync merges the field resolver in the same way mentioned above, and the request is passed to your Lambda function as an asynchronous event with the `payload` being a list of values. The response from an `Event` invocation type request results in a `null` value without a response handler:

```
{
  "data": {
    "field": null
  }
}
```

We recommend that you disable resolver caching for `Event` invocation type resolvers because these would not be sent to Lambda if there were a cache hit.

## Response object
<a name="response-object-js"></a>

As with other data sources, your Lambda function sends a response to AWS AppSync that must be converted to a GraphQL type. The result of the Lambda function is contained in the `context` result property (`context.result`).

If the shape of your Lambda function response matches the shape of the GraphQL type, you can forward the response using the following function response handler:

```
export function response(ctx) {
  return ctx.result
}
```

There are no required fields or shape restrictions that apply to the response object. However, because GraphQL is strongly typed, the resolved response must match the expected GraphQL type.

## Lambda function batched response
<a name="aws-appsync-resolver-reference-lambda-batched-response-js"></a>

If the `operation` field is set to `BatchInvoke`, AWS AppSync expects a list of items back from the Lambda function. In order for AWS AppSync to map each result back to the original request item, the response list must match in size and order. It's valid to have `null` items in the response list; `ctx.result` is set to *null* accordingly.

# AWS AppSync JavaScript resolver function reference for EventBridge data source
<a name="resolver-reference-eventbridge-js"></a>

The AWS AppSync resolver function request and response used with the EventBridge data source allows you to send custom events to the Amazon EventBridge bus.

## Request
<a name="request-js"></a>

The request handler allows you to send multiple custom events to an EventBridge event bus:

```
export function request(ctx) {
  return {
    "operation" : "PutEvents",
    "events" : [{}]
  }
}
```

An EventBridge `PutEvents` request has the following type definition:

```
type PutEventsRequest = {
  operation: 'PutEvents'
  events: {
    source: string
    detail: { [key: string]: any }
    detailType: string
    resources?: string[]
    time?: string // RFC3339 Timestamp format
  }[]
}
```

## Response
<a name="response-js"></a>

If the `PutEvents` operation is successful, the response from EventBridge is included in the `ctx.result`:

```
export function response(ctx) {
  if(ctx.error)
    util.error(ctx.error.message, ctx.error.type, ctx.result)
  else
    return ctx.result
}
```

Errors that occur while performing `PutEvents` operations such as `InternalExceptions` or `Timeouts` will appear in `ctx.error`. For a list of EventBridge's common errors, see the [EventBridge common error reference](https://docs.aws.amazon.com/eventbridge/latest/APIReference/CommonErrors.html).

The `result` will have the following type definition:

```
type PutEventsResult = {
  Entries: {
    ErrorCode: string
    ErrorMessage: string
    EventId: string
  }[]
  FailedEntryCount: number
}
```
+ **Entries**

  The ingested event results, both successful and unsuccessful. If the ingestion was successful, the entry has the `EventID` in it. Otherwise, you can use the `ErrorCode` and `ErrorMessage` to identify the problem with the entry.

  For each record, the index of the response element is the same as the index in the request array.
+ **FailedEntryCount**

  The number of failed entries. This value is represented as an integer.

For more information about the response of `PutEvents`, see [PutEvents](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEvents.html#API_PutEvents_ResponseElements).

**Example sample response 1**

The following example is a `PutEvents` operation with two successful events:

```
{
    "Entries" : [ 
        {
            "EventId": "11710aed-b79e-4468-a20b-bb3c0c3b4860"
        }, 
        {
            "EventId": "d804d26a-88db-4b66-9eaf-9a11c708ae82"
        }
    ],
    "FailedEntryCount" : 0
}
```

**Example sample response 2**

The following example is a `PutEvents` operation with three events, two successes and one fail:

```
{
    "Entries" : [ 
        {
            "EventId": "11710aed-b79e-4468-a20b-bb3c0c3b4860"
        }, 
        {
            "EventId": "d804d26a-88db-4b66-9eaf-9a11c708ae82"
        },
        {
            "ErrorCode" : "SampleErrorCode",
            "ErrorMessage" : "Sample Error Message"
        }
    ],
    "FailedEntryCount" : 1
}
```

## `PutEvents` fields
<a name="putevents-field"></a>

`PutEvents` contains the following mapping template fields:
+ **Version**

  Common to all request mapping templates, the `version` field defines the version that the template uses. This field is required. The value `2018-05-29` is the only version supported for the EventBridge mapping templates.
+ **Operation**

  The only supported operation is `PutEvents`. This operation allows you to add custom events to your event bus.
+ **Events**

  An array of events that will be added to the event bus. This array should have an allocation of 1 - 10 items.

  The `Event` object has the following fields:
  + `"source"`: A string that defines the source of the event.
  + `"detail"`: A JSON object that you can use to attach information about the event. This field can be an empty map ( `{ }` ).
  + `"detailType`: A string that identifies the type of event.
  + `"resources"`: A JSON array of strings that identifies resources involved in the event. This field can be an empty array.
  + `"time"`: The event timestamp provided as a string. This should follow the [RFC3339](https://www.rfc-editor.org/rfc/rfc3339.txt) timestamp format.

The snippets below are some examples of valid `Event` objects:

**Example 1**

```
{
    "source" : "source1",
    "detail" : {
        "key1" : [1,2,3,4],
        "key2" : "strval"
    },
    "detailType" : "sampleDetailType",
    "resources" : ["Resouce1", "Resource2"],
    "time" : "2022-01-10T05:00:10Z"
}
```

**Example 2**

```
{
    "source" : "source1",
    "detail" : {},
    "detailType" : "sampleDetailType"
}
```

**Example 3**

```
{
    "source" : "source1",
    "detail" : {
        "key1" : 1200
    },
    "detailType" : "sampleDetailType",
    "resources" : []
}
```

# AWS AppSync JavaScript resolver function reference for `None` data source
<a name="resolver-reference-none-js"></a>

The AWS AppSync resolver function request and response with the data source of type *None* enables you to shape requests for AWS AppSync local operations.

## Request
<a name="request-js"></a>

The request handler can be simple and enables you to pass as much contextual information as possible via the `payload` field.

```
type NONERequest = {
  payload: any;
};
```

Here is an example where the field arguments are passed to the payload:

```
export function request(ctx) {
  return {
    payload: context.args
  };
}
```

The value of the `payload` field will be forwarded to the function response handler and is available in `context.result`.

## Payload
<a name="payload-js"></a>

The `payload` field is a container that can be used to pass any data that is then made available to the function response handler.

 The `payload` field is optional.

## Response
<a name="response-js"></a>

Because there is no data source, the value of the `payload` field will be forwarded to the function response handler and set on the `context.result` property.

If the shape of the `payload` field value exactly matches the shape of the GraphQL type, you can forward the response using the following response handler:

```
export function response(ctx) {
  return ctx.result;
}
```

There are no required fields or shape restrictions that apply to the return response. However, because GraphQL is strongly typed, the resolved response must match the expected GraphQL type.

# AWS AppSync JavaScript resolver function reference for HTTP
<a name="resolver-reference-http-js"></a>

The AWS AppSync HTTP resolver functions enable you to send requests from AWS AppSync to any HTTP endpoint, and responses from your HTTP endpoint back to AWS AppSync. With your request handler, you can provide hints to AWS AppSync about the nature of the operation to be invoked. This section describes the different configurations for the supported HTTP resolver.

## Request
<a name="request-js"></a>

```
type HTTPRequest = {
  method: 'PUT' | 'POST' | 'GET' | 'DELETE' | 'PATCH';
  params?: {
    query?: { [key: string]: any };
    headers?: { [key: string]: string };
    body?: any;
  };
  resourcePath: string;
};
```

The following snippet is an example of an HTTP POST request, with a `text/plain` body:

```
export function request(ctx) {
  return {
    method: 'POST',
    params: {
      headers: { 'Content-Type': 'text/plain' },
      body: 'this is an example of text body',
    },
    resourcePath: '/',
  };
}
```

## Method
<a name="method-js"></a>

**Note**  
This applies only to the Request handler. 

HTTP method or verb (GET, POST, PUT, PATCH, or DELETE) that AWS AppSync sends to the HTTP endpoint.

```
"method": "PUT"
```

## ResourcePath
<a name="resourcepath-js"></a>

 

**Note**  
This applies only to the Request handler. 

The resource path that you want to access. Along with the endpoint in the HTTP data source, the resource path forms the URL that the AWS AppSync service makes a request to.

```
"resourcePath": "/v1/users"
```

When the request is evaluated, this path is sent as part of the HTTP request, including the HTTP endpoint. For example, the previous example might translate to the following:

```
PUT <endpoint>/v1/users
```

## Params fields
<a name="params-field-js"></a>

**Note**  
This applies only to the Request handler. 

Used to specify what action your search performs, most commonly by setting the **query** value inside the **body**. However, there are several other capabilities that can be configured, such as the formatting of responses.

** **headers** **  
The header information, as key-value pairs. Both the key and the value must be strings.  
For example:  

```
"headers" : {
    "Content-Type" : "application/json"
}
```
Currently supported `Content-Type` headers are:  

```
text/*
application/xml
application/json
application/soap+xml
application/x-amz-json-1.0
application/x-amz-json-1.1
application/vnd.api+json
application/x-ndjson
```
You can’t set the following HTTP headers:  

```
HOST
CONNECTION
USER-AGENT
EXPECTATION
TRANSFER_ENCODING
CONTENT_LENGTH
```

** **query** **  
Key-value pairs that specify common options, such as code formatting for JSON responses. Both the key and the value must be a string. The following example shows how you can send a query string as `?type=json`:  

```
"query" : {
    "type" : "json"
}
```

** **body** **  
The body contains the HTTP request body that you choose to set. The request body is always a UTF-8 encoded string unless the content type specifies the charset.  

```
"body":"body string"
```

## Response
<a name="response-js"></a>

See an example [here](https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-http-resolvers-js.html).

# AWS AppSync JavaScript resolver function reference for Amazon RDS
<a name="resolver-reference-rds-js"></a>

The AWS AppSync RDS function and resolver allows developers to send SQL queries to an Amazon Aurora cluster database using the RDS Data API and get back the result of these queries. You can write SQL statements that are sent to the Data API by using AWS AppSync's `rds` module `sql`-tagged template or by using the `rds` module's `select`, `insert`, `update`, and `remove` helper functions. AWS AppSync utilizes the RDS Data Service's [https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html) action to run SQL statements against the database. 

**Topics**
+ [SQL tagged template](#sql-tagged-templates)
+ [Creating statements](#creating-statements)
+ [Retrieving data](#retrieving-data)
+ [Utility functions](#utility-functions)
+ [SQL Select](#utility-functions-select)
+ [SQL Insert](#utility-functions-insert)
+ [SQL Update](#utility-functions-update)
+ [SQL Delete](#utility-functions-delete)
+ [Casting](#casting)

## SQL tagged template
<a name="sql-tagged-templates"></a>

AWS AppSync's `sql` tagged template enables you to create a static statement that can receive dynamic values at runtime by using template expressions. AWS AppSync builds a variable map from the expression values to construct a [https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html) query that is sent to the Amazon Aurora Serverless Data API. With this method, it isn't possible for dynamic values passed at run time to modify the original statement, which could cause unintented execution. All dynamic values are passed as parameters, can't modify the original statement, and aren't executed by the database. This makes your query less vulnerable to SQL injection attacks.

**Note**  
In all cases, when writing SQL statements, you should follow security guidelines to properly handle data that you receive as input.

**Note**  
The `sql` tagged template only supports passing variable values. You can't use an expression to dynamically specify the column or table names. However, you can use utility functions to build dynamic statements.

In the following example, we create a query that filters based on the value of the `col` argument that is set dynamically in the GraphQL query at run time. The value can only be added to the statement using the tag expression:

```
import { sql, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
  const query = sql`
SELECT * FROM table 
WHERE column = ${ctx.args.col}`
  ;
  return createMySQLStatement(query);
}
```

By passing all dynamic values through the variable map, we rely on the database engine to securely handle and sanitize values.

## Creating statements
<a name="creating-statements"></a>

Functions and resolvers can interact with MySQL and PostgreSQL databases. Use `createMySQLStatement` and `createPgStatement` respectively to build statements. For example, `createMySQLStatement` can create a MySQL query. These functions accept up to two statements, useful when a request should retrieve results immediately. With MySQL, you could do:

```
import { sql, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { id, text } = ctx.args;
    const s1 = sql`insert into Post(id, text) values(${id}, ${text})`;
    const s2 = sql`select * from Post where id = ${id}`;
    return createMySQLStatement(s1, s2);
}
```

**Note**  
`createPgStatement` and `createMySQLStatement` does not escape or quote statements built with the `sql` tagged template.

## Retrieving data
<a name="retrieving-data"></a>

The result of your executed SQL statement is available in your response handler in the `context.result` object. The result is a JSON string with the [response elements](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_ExecuteStatement.html#API_ExecuteStatement_ResponseElements) from the `ExecuteStatement` action. When parsed, the result has the following shape:

```
type SQLStatementResults = {
    sqlStatementResults: {
        records: any[];
        columnMetadata: any[];
        numberOfRecordsUpdated: number;
        generatedFields?: any[]
    }[]
}
```

You can use the `toJsonObject` utility to transform the result into a list of JSON objects representing the returned rows. For example:

```
import { toJsonObject } from '@aws-appsync/utils/rds';

export function response(ctx) {
    const { error, result } = ctx;
    if (error) {
        return util.appendError(
            error.message,
            error.type,
            result
        )
    }
    return toJsonObject(result)[1][0]
}
```

Note that `toJsonObject` returns an array of statement results. If you provided one statement, the array length is `1`. If you provided two statements, the array length is `2`. Each result in the array contains `0` or more rows. `toJsonObject` returns `null` if the result value is invalid or unexpected.

## Utility functions
<a name="utility-functions"></a>

You can use the AWS AppSync RDS module's utility helpers to interact with your database.

### SQL Select
<a name="utility-functions-select"></a>

The `select` utility creates a `SELECT` statement to query your relational database. 

**Basic use**

In its basic form, you can specify the table you want to query:

```
import { select, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {

    // Generates statement: 
    // "SELECT * FROM "persons"
    return createPgStatement(select({table: 'persons'}));
}
```

Note that you can also specify the schema in your table identifier:

```
import { select, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {

    // Generates statement:
    // SELECT * FROM "private"."persons"
    return createPgStatement(select({table: 'private.persons'}));
}
```

**Specifying columns**

You can specify columns with the `columns` property. If this isn't set to a value, it defaults to `*`:

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name']
    }));
}
```

You can specify a column's table as well:

```
export function request(ctx) {

    // Generates statement: 
    // SELECT "id", "persons"."name"
    // FROM "persons"
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'persons.name']
    }));
}
```

**Limits and offsets**

You can apply `limit` and `offset` to the query:

```
export function request(ctx) {

    // Generates statement: 
    // SELECT "id", "name"
    // FROM "persons"
    // LIMIT :limit
    // OFFSET :offset
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        limit: 10,
        offset: 40
    }));
}
```

**Order By**

You can sort your results with the `orderBy` property. Provide an array of objects specifying the column and an optional `dir` property:

```
export function request(ctx) {

    // Generates statement: 
    // SELECT "id", "name" FROM "persons"
    // ORDER BY "name", "id" DESC
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        orderBy: [{column: 'name'}, {column: 'id', dir: 'DESC'}]
    }));
}
```

**Filters**

You can build filters by using the special condition object:

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE "name" = :NAME
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: {name: {eq: 'Stephane'}}
    }));
}
```

You can also combine filters:

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE "name" = :NAME and "id" > :ID
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: {name: {eq: 'Stephane'}, id: {gt: 10}}
    }));
}
```

You can also create `OR` statements:

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE "name" = :NAME OR "id" > :ID
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: { or: [
            { name: { eq: 'Stephane'} },
            { id: { gt: 10 } }
        ]}
    }));
}
```

You can also negate a condition with `not`:

```
export function request(ctx) {

    // Generates statement:
    // SELECT "id", "name"
    // FROM "persons"
    // WHERE NOT ("name" = :NAME AND "id" > :ID)
    return createPgStatement(select({
        table: 'persons',
        columns: ['id', 'name'],
        where: { not: [
            { name: { eq: 'Stephane'} },
            { id: { gt: 10 } }
        ]}
    }));
}
```

You can also use the following operators to compare values:


| 
| 
| Operator | Description | Possible value types | 
| --- |--- |--- |
| eq | Equal | number, string, boolean | 
| ne | Not equal | number, string, boolean | 
| le | Less than or equal | number, string | 
| lt | Less than | number, string | 
| ge | Greater than or equal | number, string | 
| gt | Greater than | number, string | 
| contains | Like | string | 
| notContains | Not like | string | 
| beginsWith | Starts with prefix | string | 
| between | Between two values | number, string | 
| attributeExists | The attribute is not null | number, string, boolean | 
| size | checks the length of the element | string | 

### SQL Insert
<a name="utility-functions-insert"></a>

The `insert` utility provides a straightforward way of inserting single row items in your database with the `INSERT` operation.

**Single item insertions**

To insert an item, specify the table and then pass in your object of values. The object keys are mapped to your table columns. Columns names are automatically escaped, and values are sent to the database using the variable map:

```
import { insert, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: values } = ctx.args;
    const insertStatement = insert({ table: 'persons', values });
    
    // Generates statement:
    // INSERT INTO `persons`(`name`)
    // VALUES(:NAME)
    return createMySQLStatement(insertStatement)
}
```

**MySQL use case**

You can combine an `insert` followed by a `select` to retrieve your inserted row:

```
import { insert, select, createMySQLStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: values } = ctx.args;
    const insertStatement = insert({  table: 'persons', values });
    const selectStatement = select({
        table: 'persons',
        columns: '*',
        where: { id: { eq: values.id } },
        limit: 1,
    });
    
    // Generates statement:
    // INSERT INTO `persons`(`name`)
    // VALUES(:NAME)
    // and
    // SELECT *
    // FROM `persons`
    // WHERE `id` = :ID
    return createMySQLStatement(insertStatement, selectStatement)
}
```

**Postgres use case**

With Postgres, you can use [https://www.postgresql.org/docs/current/dml-returning.html](https://www.postgresql.org/docs/current/dml-returning.html) to obtain data from the row that you inserted. It accepts `*` or an array of column names:

```
import { insert, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: values } = ctx.args;
    const insertStatement = insert({
        table: 'persons',
        values,
        returning: '*'
    });

    // Generates statement:
    // INSERT INTO "persons"("name")
    // VALUES(:NAME)
    // RETURNING *
    return createPgStatement(insertStatement)
}
```

### SQL Update
<a name="utility-functions-update"></a>

The `update` utility allows you to update existing rows. You can use the condition object to apply changes to the specified columns in all the rows that satisfy the condition. For example, let's say we have a schema that allows us to make this mutation. We want to update the `name` of `Person` with the `id` value of `3` but only if we've known them (`known_since`) since the year `2000`:

```
mutation Update {
    updatePerson(
        input: {id: 3, name: "Jon"},
        condition: {known_since: {ge: "2000"}}
    ) {
    id
    name
  }
}
```

Our update resolver looks like this:

```
import { update, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: { id, ...values }, condition } = ctx.args;
    const where = {
        ...condition,
        id: { eq: id },
    };
    const updateStatement = update({
        table: 'persons',
        values,
        where,
        returning: ['id', 'name'],
    });

    // Generates statement:
    // UPDATE "persons"
    // SET "name" = :NAME, "birthday" = :BDAY, "country" = :COUNTRY
    // WHERE "id" = :ID
    // RETURNING "id", "name"
    return createPgStatement(updateStatement)
}
```

We can add a check to our condition to make sure that only the row that has the primary key `id` equal to `3` is updated. Similarly, for Postgres `inserts`, you can use `returning` to return the modified data. 

### SQL Delete
<a name="utility-functions-delete"></a>

The `remove` utility allows you to delete existing rows. You can use the condition object on all rows that satisfy the condition. Note that `delete` is a reserved keyword in JavaScript. `remove` should be used instead:

```
import { remove, createPgStatement } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const { input: { id }, condition } = ctx.args;
    const where = { ...condition, id: { eq: id } };
    const deleteStatement = remove({
        table: 'persons',
        where,
        returning: ['id', 'name'],
    });

    // Generates statement:
    // DELETE "persons"
    // WHERE "id" = :ID
    // RETURNING "id", "name"
    return createPgStatement(updateStatement)
}
```

## Casting
<a name="casting"></a>

In some cases, you may want more specificity about the correct object type to use in your statement. You can use the provided type hints to specify the type of your parameters. AWS AppSync supports the [same type hints](https://docs.aws.amazon.com//rdsdataservice/latest/APIReference/API_SqlParameter.html#rdsdtataservice-Type-SqlParameter-typeHint) as the Data API. You can cast your parameters by using the `typeHint` functions from the AWS AppSync `rds` module. 

The following example allows you to send an array as a value that is casted as a JSON object. We use the `->` operator to retrieve the element at the `index` `2` in the JSON array:

```
import { sql, createPgStatement, toJsonObject, typeHint } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const arr = ctx.args.list_of_ids
    const statement = sql`select ${typeHint.JSON(arr)}->2 as value`
    return createPgStatement(statement)
}

export function response(ctx) {
    return toJsonObject(ctx.result)[0][0].value
}
```

Casting is also useful when handling and comparing `DATE`, `TIME`, and `TIMESTAMP`:

```
import { select, createPgStatement, typeHint } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const when = ctx.args.when
    const statement = select({
        table: 'persons',
        where: { createdAt : { gt: typeHint.DATETIME(when) } }
    })
    return createPgStatement(statement)
}
```

Here's another example showing how you can send the current date and time:

```
import { sql, createPgStatement, typeHint } from '@aws-appsync/utils/rds';

export function request(ctx) {
    const now = util.time.nowFormatted('YYYY-MM-dd HH:mm:ss')
    return createPgStatement(sql`select ${typeHint.TIMESTAMP(now)}`)
}
```

**Available type hints**
+ `typeHint.DATE` - The corresponding parameter is sent as an object of the `DATE` type to the database. The accepted format is `YYYY-MM-DD`.
+ `typeHint.DECIMAL` - The corresponding parameter is sent as an object of the `DECIMAL` type to the database.
+ `typeHint.JSON` - The corresponding parameter is sent as an object of the `JSON` type to the database.
+ `typeHint.TIME` - The corresponding string parameter value is sent as an object of the `TIME` type to the database. The accepted format is `HH:MM:SS[.FFF]`. 
+ `typeHint.TIMESTAMP` - The corresponding string parameter value is sent as an object of the `TIMESTAMP` type to the database. The accepted format is `YYYY-MM-DD HH:MM:SS[.FFF]`.
+ `typeHint.UUID` - The corresponding string parameter value is sent as an object of the `UUID` type to the database.

# AWS AppSync JavaScript resolver and function reference for Amazon Bedrock runtime
<a name="resolver-reference-bedrock-js"></a>

You can use AWS AppSync functions and resolvers to invoke models on Amazon Bedrock in your AWS account. You can shape your request payloads and the response from your model invocations functions before returning them to your clients. You can use the Amazon Bedrock runtime’s `InvokeModel` API or the `Converse` API. This section describes the requests for the supported Amazon Bedrock operations.

**Note**  
AWS AppSync only supports synchronous invocations that complete within 10 seconds. It is not possible to call Amazon Bedrock's stream APIs. AWS AppSync only supports invoking foundation models and [inference profiles](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles.html) in the same region as the AWS AppSync API.

## Request object
<a name="request_object"></a>

The `InvokeModel` request object allows you to interact with Amazon Bedrock’s `InvokeModel` API.

```
type BedrockInvokeModelRequest = {
  operation: 'InvokeModel';
  modelId: string;
  body: any;
  guardrailIdentifier?: string;
  guardrailVersion?: string;
  guardrailTrace?: string;
}
```

The `Converse` request object allows you to interact with Amazon Bedrock’s `Converse` API.

```
type BedrockConverseRequest = {
  operation: 'Converse';
  modelId: string;
  messages: BedrockMessage[];
  additionalModelRequestFields?: any;
  additionalModelResponseFieldPaths?: string[];
  guardrailConfig?: BedrockGuardrailConfig;
  inferenceConfig?: BedrockInferenceConfig;
  promptVariables?: { [key: string]: BedrockPromptVariableValues }[];
  system?: BedrockSystemContent[];
  toolConfig?: BedrockToolConfig;
}
```

See the [Type reference](#type-reference-bedrock) section later in this topic for more details.

From your functions and resolvers, you can build your request objects directly or use the helper functions from @aws-appsync/utils/ai to create the request. When specifying the model Id (modelId) in your requests, you can use the model Id or the model ARN.

The following example uses the `invokeModel` function to summarize text using Amazon Titan Text G1 - Lite (amazon.titan-text-lite-v1). A configured guardrail is used to identify and block or filter unwanted content in the prompt flow. Learn more about [Amazon Bedrock Guardrails](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html) in the *Amazon Bedrock User Guide*.

**Important**  
You are responsible for secure application development and preventing vulnerabilities, such as prompt injection. To learn more, see [Prompt injection security](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-injection.html) in the *Amazon Bedrock User Guide*.

```
import { invokeModel } from '@aws-appsync/utils/ai'
export function request(ctx) {
  return invokeModel({
    modelId: 'amazon.titan-text-lite-v1',
    guardrailIdentifier: "zabcd12345678",
    guardrailVersion: "1",
    body: { inputText: `Summarize this text in less than 100 words. : \n<text>${ctx.stash.text ?? ctx.env.DEFAULT_TEXT}</text>` },
  })
}

export function response(ctx) {
  return ctx.result.results[0].outputText
}
```

The following example uses the `converse` function with a cross-region inference profile (us.anthropic.claude-3-5-haiku-20241022-v1:0). Learn more about Amazon Bedrock's [Prerequisites for inference profiles](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-prereq.html) in the *Amazon Bedrock User Guide*

**Reminder**: You are responsible for secure application development and preventing vulnerabilities, such as prompt injection.

```
import { converse } from '@aws-appsync/utils/ai'

export function request(ctx) {
  return converse({
    modelId: 'us.anthropic.claude-3-5-haiku-20241022-v1:0',
    system: [
      {
        text: `
You are a database assistant that provides SQL queries to retrieve data based on a natural language request. 
${ctx.args.explain ? 'Explain your answer' : 'Do not explain your answer'}.
Assume a database with the following tables and columns exists:

Customers:  
- customer_id (INT, PRIMARY KEY)  
- first_name (VARCHAR)  
- last_name (VARCHAR)  
- email (VARCHAR)  
- phone (VARCHAR)  
- address (VARCHAR)  
- city (VARCHAR)  
- state (VARCHAR)  
- zip_code (VARCHAR)  
  
Products:  
- product_id (INT, PRIMARY KEY)  
- product_name (VARCHAR)  
- description (TEXT)  
- category (VARCHAR)  
- price (DECIMAL)  
- stock_quantity (INT)  

Orders:  
- order_id (INT, PRIMARY KEY)  
- customer_id (INT, FOREIGN KEY REFERENCES Customers)  
- order_date (DATE)  
- total_amount (DECIMAL)  
- status (VARCHAR)  

Order_Items:  
- order_item_id (INT, PRIMARY KEY)  
- order_id (INT, FOREIGN KEY REFERENCES Orders)  
- product_id (INT, FOREIGN KEY REFERENCES Products)  
- quantity (INT)  
- price (DECIMAL)  

Reviews:  
- review_id (INT, PRIMARY KEY)  
- product_id (INT, FOREIGN KEY REFERENCES Products)  
- customer_id (INT, FOREIGN KEY REFERENCES Customers)  
- rating (INT)  
- comment (TEXT)  
- review_date (DATE)`,
      },
    ],
    messages: [
      {
        role: 'user',
        content: [{ text: `<request>${ctx.args.text}:</request>` }],
      },
    ],
  })
}

export function response(ctx) {
  return ctx.result.output.message.content[0].text
}
```

The following example uses `converse` to create a structured response. Note that we use environment variables for our DB schema reference and we configure a guardrail to help prevent attacks.

```
import { converse } from '@aws-appsync/utils/ai'

export function request(ctx) {
  return generateObject({
    modelId: ctx.env.HAIKU3_5, // keep the model in an env variable
    prompt: ctx.args.query,
    shape: objectType(
      {
        sql: stringType('the sql query to execute as a javascript template string.'),
        parameters: objectType({}, 'the placeholder parameters for the query, if any.'),
      },
      'the sql query to execute along with the place holder parameters',
    ),
    system: [
      {
        text: `
You are a database assistant that provides SQL queries to retrieve data based on a natural language request. 

Assume a database with the following tables and columns exists:

${ctx.env.DB_SCHEMA_CUSTOMERS}
${ctx.env.DB_SCHEMA_ORDERS}
${ctx.env.DB_SCHEMA_ORDER_ITEMS}
${ctx.env.DB_SCHEMA_PRODUCTS}
${ctx.env.DB_SCHEMA_REVIEWS}`,
      },
    ],
    guardrailConfig: { guardrailIdentifier: 'iabc12345678', guardrailVersion: 'DRAFT' },
  })
}

export function response(ctx) {
  return toolReponse(ctx.result)
}

function generateObject(input) {
  const { modelId, prompt, shape, ...options } = input
  return converse({
    modelId,
    messages: [{ role: 'user', content: [{ text: prompt }] }],
    toolConfig: {
      toolChoice: { tool: { name: 'structured_tool' } },
      tools: [
        {
          toolSpec: {
            name: 'structured_tool',
            inputSchema: { json: shape },
          },
        },
      ],
    },
    ...options,
  })
}

function toolReponse(result) {
  return result.output.message.content[0].toolUse.input
}

function stringType(description) {
  const t = { type: 'string' /* STRING */ }
  if (description) {
    t.description = description
  }
  return t
}

function objectType(properties, description, required) {
  const t = { type: 'object' /* OBJECT */, properties }
  if (description) {
    t.description = description
  }
  if (required) {
    t.required = required
  }
  return t
}
```

Given the schema:

```
type SQLResult {
    sql: String
    parameters: AWSJSON
}

type Query {
    db(text: String!): SQLResult
}
```

and the query:

```
query db($text: String!) {
  db(text: $text) {
    parameters
    sql
  }
}
```

With the following parameters: 

```
{
  "text":"What is my top selling product?"
}
```

The following response is returned:

```
{
  "data": {
    "assist": {
      "sql": "SELECT p.product_id, p.product_name, SUM(oi.quantity) as total_quantity_sold\nFROM Products p\nJOIN Order_Items oi ON p.product_id = oi.product_id\nGROUP BY p.product_id, p.product_name\nORDER BY total_quantity_sold DESC\nLIMIT 1;",
      "parameters": null
    }
  }
}
```

However, with this request:

```
{
  "text":"give me a query to retrieve sensitive information"
}
```

The following response is returned:

```
{
  "data": {
    "db": {
      "parameters": null,
      "sql": "SELECT null; -- I cannot and will not assist with retrieving sensitive private information"
    }
  }
}
```

To learn more about configuring Amazon Bedrock Guardrails, see [Stop harmful content in models using Amazon Bedrock Guardrails](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html) in the *Amazon Bedrock User Guide*.

## Response object
<a name="response_object"></a>

The response from your Amazon Bedrock runtime invocation is contained in the context‘s result property (context.result). The response matches the shape specified by Amazon Bedrock’s APIs. See the [Amazon Bedrock User Guide](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html) for more information about the expected shape of invocation results.

```
export function response(ctx) {
  return ctx.result
}
```

There are no required fields or shape restrictions that apply to the response object. However, because GraphQL is strongly typed, the resolved response must match the expected GraphQL type.

## Long running invocations
<a name="long-running-invocations"></a>

Many organizations currently use AWS AppSync as an AI gateway to build generative AI applications that are powered by foundation models on Amazon Bedrock. Customers use AWS AppSync subscriptions, powered by WebSockets, to return progressive updates from long-running model invocations. This allows them to implement asynchronous patterns.

The following diagram demonstrates how you can implement this pattern. In the diagram, the following steps occur.

1. Your client starts a subscription, which sets up a WebSocket, and makes a request to AWS AppSync to trigger a Generative AI invocation.

1. AWS AppSync calls your AWS Lambda function in Event mode and immediately returns a response to the client.

1. Your Lambda function invokes the model on Amazon Bedrock. The Lambda function can use a synchronous API, such as `InvokeModel`, or a stream API, such as `InvokeModelWithResponseStream`, to get progressive updates.

1. As updates are received, or when the invocation completes, the Lambda function sends updates via mutations to your AWS AppSync API which triggers subscriptions.

1. The subscription events are sent in real-time and received by your client over the WebSocket.

![\[A diagram that demonstrates the workflow for using an AWS AppSync subscription to return updates from a Amazon Bedrock model.\]](http://docs.aws.amazon.com/appsync/latest/devguide/images/bedrock-workflow.png)


## Type reference
<a name="type-reference-bedrock"></a>

```
export type BedrockMessage = {
  role: 'user' | 'assistant' | string;
  content: BedrockMessageContent[];
};

export type BedrockMessageContent =
  | { text: string }
  | { guardContent: BedrockGuardContent }
  | { toolResult: BedrockToolResult }
  | { toolUse: BedrockToolUse };

export type BedrockGuardContent = {
  text: BedrockGuardContentText;
};

export type BedrockGuardContentText = {
  text: string;
  qualifiers?: ('grounding_source' | 'query' | 'guard_content' | string)[];
};

export type BedrockToolResult = {
  content: BedrockToolResultContent[];
  toolUseId: string;
  status?: string;
};

export type BedrockToolResultContent = { json: any } | { text: string };

export type BedrockToolUse = {
  input: any;
  name: string;
  toolUseId: string;
};

export type ConversePayload = {
  modelId: string;
  body: any;
  guardrailIdentifier?: string;
  guardrailVersion?: string;
  guardrailTrace?: string;
};

export type BedrockGuardrailConfig = {
  guardrailIdentifier: string;
  guardrailVersion: string;
  trace: string;
};

export type BedrockInferenceConfig = {
  maxTokens?: number;
  temperature?: number;
  stopSequences?: string[];
  topP?: number;
};

export type BedrockPromptVariableValues = {
  text: string;
};

export type BedrockToolConfig = {
  tools: BedrockTool[];
  toolChoice?: BedrockToolChoice;
};

export type BedrockTool = {
  toolSpec: BedrockToolSpec;
};

export type BedrockToolSpec = {
  name: string;
  description?: string;
  inputSchema: BedrockInputSchema;
};

export type BedrockInputSchema = {
  json: any;
};

export type BedrockToolChoice =
  | { tool: BedrockSpecificToolChoice }
  | { auto: any }
  | { any: any };

export type BedrockSpecificToolChoice = {
  name: string;
};

export type BedrockSystemContent =
  | { guardContent: BedrockGuardContent }
  | { text: string };

export type BedrockConverseOutput = {
  message?: BedrockMessage;
};

export type BedrockConverseMetrics = {
  latencyMs: number;
};

export type BedrockTokenUsage = {
  inputTokens: number;
  outputTokens: number;
  totalTokens: number;
};

export type BedrockConverseTrace = {
  guardrail?: BedrockGuardrailTraceAsssessment;
};

export type BedrockGuardrailTraceAsssessment = {
  inputAssessment?: { [key: string]: BedrockGuardrailAssessment };
  modelOutput?: string[];
  outputAssessments?: { [key: string]: BedrockGuardrailAssessment };
};

export type BedrockGuardrailAssessment = {
  contentPolicy?: BedrockGuardrailContentPolicyAssessment;
  contextualGroundingPolicy?: BedrockGuardrailContextualGroundingPolicyAssessment;
  invocationMetrics?: BedrockGuardrailInvocationMetrics;
  sensitiveInformationPolicy?: BedrockGuardrailSensitiveInformationPolicyAssessment;
  topicPolicy?: BedrockGuardrailTopicPolicyAssessment;
  wordPolicy?: BedrockGuardrailWordPolicyAssessment;
};

export type BedrockGuardrailContentPolicyAssessment = {
  filters: BedrockGuardrailContentFilter[];
};

export type BedrockGuardrailContentFilter = {
  action: 'BLOCKED' | string;
  confidence: 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH' | string;
  type:
    | 'INSULTS'
    | 'HATE'
    | 'SEXUAL'
    | 'VIOLENCE'
    | 'MISCONDUCT'
    | 'PROMPT_ATTACK'
    | string;
  filterStrength: 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH' | string;
};

export type BedrockGuardrailContextualGroundingPolicyAssessment = {
  filters: BedrockGuardrailContextualGroundingFilter;
};

export type BedrockGuardrailContextualGroundingFilter = {
  action: 'BLOCKED' | 'NONE' | string;
  score: number;
  threshold: number;
  type: 'GROUNDING' | 'RELEVANCE' | string;
};

export type BedrockGuardrailInvocationMetrics = {
  guardrailCoverage?: BedrockGuardrailCoverage;
  guardrailProcessingLatency?: number;
  usage?: BedrockGuardrailUsage;
};

export type BedrockGuardrailCoverage = {
  textCharacters?: BedrockGuardrailTextCharactersCoverage;
};

export type BedrockGuardrailTextCharactersCoverage = {
  guarded?: number;
  total?: number;
};

export type BedrockGuardrailUsage = {
  contentPolicyUnits: number;
  contextualGroundingPolicyUnits: number;
  sensitiveInformationPolicyFreeUnits: number;
  sensitiveInformationPolicyUnits: number;
  topicPolicyUnits: number;
  wordPolicyUnits: number;
};

export type BedrockGuardrailSensitiveInformationPolicyAssessment = {
  piiEntities: BedrockGuardrailPiiEntityFilter[];
  regexes: BedrockGuardrailRegexFilter[];
};

export type BedrockGuardrailPiiEntityFilter = {
  action: 'BLOCKED' | 'ANONYMIZED' | string;
  match: string;
  type:
    | 'ADDRESS'
    | 'AGE'
    | 'AWS_ACCESS_KEY'
    | 'AWS_SECRET_KEY'
    | 'CA_HEALTH_NUMBER'
    | 'CA_SOCIAL_INSURANCE_NUMBER'
    | 'CREDIT_DEBIT_CARD_CVV'
    | 'CREDIT_DEBIT_CARD_EXPIRY'
    | 'CREDIT_DEBIT_CARD_NUMBER'
    | 'DRIVER_ID'
    | 'EMAIL'
    | 'INTERNATIONAL_BANK_ACCOUNT_NUMBER'
    | 'IP_ADDRESS'
    | 'LICENSE_PLATE'
    | 'MAC_ADDRESS'
    | 'NAME'
    | 'PASSWORD'
    | 'PHONE'
    | 'PIN'
    | 'SWIFT_CODE'
    | 'UK_NATIONAL_HEALTH_SERVICE_NUMBER'
    | 'UK_NATIONAL_INSURANCE_NUMBER'
    | 'UK_UNIQUE_TAXPAYER_REFERENCE_NUMBER'
    | 'URL'
    | 'USERNAME'
    | 'US_BANK_ACCOUNT_NUMBER'
    | 'US_BANK_ROUTING_NUMBER'
    | 'US_INDIVIDUAL_TAX_IDENTIFICATION_NUMBER'
    | 'US_PASSPORT_NUMBER'
    | 'US_SOCIAL_SECURITY_NUMBER'
    | 'VEHICLE_IDENTIFICATION_NUMBER'
    | string;
};

export type BedrockGuardrailRegexFilter = {
  action: 'BLOCKED' | 'ANONYMIZED' | string;
  match?: string;
  name?: string;
  regex?: string;
};

export type BedrockGuardrailTopicPolicyAssessment = {
  topics: BedrockGuardrailTopic[];
};

export type BedrockGuardrailTopic = {
  action: 'BLOCKED' | string;
  name: string;
  type: 'DENY' | string;
};

export type BedrockGuardrailWordPolicyAssessment = {
  customWords: BedrockGuardrailCustomWord[];
  managedWordLists: BedrockGuardrailManagedWord[];
};

export type BedrockGuardrailCustomWord = {
  action: 'BLOCKED' | string;
  match: string;
};

export type BedrockGuardrailManagedWord = {
  action: 'BLOCKED' | string;
  match: string;
  type: 'PROFANITY' | string;
};
```