Skip to main content

AppSyncApi

The AppSyncApi construct is a higher level CDK construct that makes it easy to create an AppSync GraphQL API. It provides a simple way to define the data sources and the resolvers in your API. And allows you to configure the specific Lambda functions if necessary. See the examples for more details.

Constructor

new AppSyncApi(scope, id, props)

Parameters

Examples

Using the minimal config

import { AppSyncApi } from "@serverless-stack/resources";

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
dataSources: {
notesDS: "src/notes.main",
},
resolvers: {
"Query listNotes": "notesDS",
"Query getNoteById": "notesDS",
"Mutation createNote": "notesDS",
"Mutation updateNote": "notesDS",
"Mutation deleteNote": "notesDS",
},
});

Note that, the resolver key can have extra spaces in between, they are just ignored.

Data source: Function

Auto-creating Lambda data sources

If the data sources are not configured, a Lambda data source is automatically created for each resolver.

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
resolvers: {
"Query listNotes": "src/list.main",
"Query getNoteById": "src/get.main",
"Mutation createNote": "src/create.main",
"Mutation updateNote": "src/update.main",
"Mutation deleteNote": "src/delete.main",
},
});

Specifying function props for all the data sources

You can set some function props and have them apply to all the Lambda data sources.

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
defaults: {
function: {
timeout: 20,
environment: { tableName: "NOTES_TABLE" },
},
},
dataSources: {
notesDS: "src/notes.main",
},
resolvers: {
"Query listNotes": "notesDS",
"Mutation createNote": "notesDS",
},
});

Note that, you can set the defaultFunctionProps while configuring the function per data source. The function one will just override the defaultFunctionProps.

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
defaults: {
function: {
timeout: 20,
},
},
dataSources: {
notesDS: {
function: {
handler: "src/notes.main",
timeout: 10,
},
},
},
resolvers: {
"Query listNotes": "notesDS",
"Mutation createNote": "notesDS",
},
});

So in the above example, the notesDS data source doesn't use the timeout that is set in the defaultFunctionProps. It'll instead use the one that is defined in the function definition (10 seconds).

Similarly, the defaultFunctionProps also applies when the Lambda data sources are auto-created.

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
defaults: {
function: {
timeout: 20,
},
},
resolvers: {
"Query listNotes": {
function: {
handler: "src/list.main",
timeout: 10,
},
},
"Mutation createNote": "src/create.main",
},
});

Attaching permissions for the entire API

Allow the entire API to access S3.

const api = new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
resolvers: {
"Query listNotes": "src/list.main",
"Query getNoteById": "src/get.main",
"Mutation createNote": "src/create.main",
"Mutation updateNote": "src/update.main",
"Mutation deleteNote": "src/delete.main",
},
});

api.attachPermissions(["s3"]);

Attaching permissions for a specific route

Allow one of the data sources to access S3.

const api = new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
dataSources: {
notesDS: "src/notes.main",
billingDS: "src/billing.main",
},
});

api.attachPermissionsToDataSource("billingDS", ["s3"]);

Attaching permissions for an auto-created data source

Allow one of the resolvers to access S3.

const api = new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
resolvers: {
"Query listNotes": "src/list.main",
"Mutation createNote": "src/create.main",
},
});

api.attachPermissionsToDataSource("Query listNotes", ["s3"]);

Using multiple data sources

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
dataSources: {
notesDS: "src/notes.main",
billingDS: "src/billing.main",
},
resolvers: {
"Query listNotes": "notesDS",
"Mutation createNote": "notesDS",
"Mutation charge": "billingDS",
},
});

Getting the function for a data source

const api = new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
dataSources: {
notesDS: "src/notes.main",
billingDS: "src/billing.main",
},
});

const listFunction = api.getFunction("notesDS");
const dataSource = api.getDataSource("notesDS");

Getting the function for a auto-created data source

const api = new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
resolvers: {
"Query listNotes": "src/list.main",
"Mutation createNote": "src/create.main",
},
});

const listFunction = api.getFunction("Query listNotes");
const dataSource = api.getDataSource("Query listNotes");

Data source: DynamoDB

import { MappingTemplate } from "@aws-cdk/aws-appsync-alpha";

const notesTable = new Table(this, "Notes", {
fields: {
id: "string"
},
primaryIndex: { partitionKey: "id" },
});

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
dataSources: {
tableDS: {
type: "dynamodb",
table: notesTable
},
},
resolvers: {
"Query listNotes": {
dataSource: "tableDS",
cdk: {
resolver: {
requestMappingTemplate: MappingTemplate.dynamoDbScanTable(),
responseMappingTemplate: MappingTemplate.dynamoDbResultList(),
},
},
},
},
});

Data source: RDS

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
dataSources: {
rdsDS: {
type: "rds",
rds: cluster,
},
},
resolvers: {
"Query listNotes": {
dataSource: "rdsDS",
requestMapping: {
inline: `
{
"version": "2018-05-29",
"statements": [
"SELECT * FROM notes"
]
}
`,
},
responseMapping: {
inline: `$util.rds.toJsonObject($ctx.result)`,
},
},
},
});

Data source: HTTP

Starting a Step Function execution on the Mutation callStepFunction.

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
dataSources: {
httpDS: {
type: "http",
endpoint: "https://states.amazonaws.com",
cdk: {
dataSource: {
authorizationConfig: {
signingRegion: "us-east-1",
signingServiceName: "states",
},
},
},
},
},
resolvers: {
"Mutation callStepFunction": {
dataSource: "httpDS",
requestMapping: { file: "request.vtl" },
responseMapping: { file: "response.vtl" },
},
},
});

Configuring resolvers

You can also add data sources and resolvers after the API has been created.

Adding data sources and resolvers

const api = new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
dataSources: {
notesDS: "src/notes.main",
},
resolvers: {
"Query listNotes": "notesDS",
"Mutation createNote": "notesDS",
},
});

api.addDataSources(this, {
billingDS: "src/billing.main",
});

api.addResolvers(this, {
"Mutation charge": "billingDS",
});

Auto-creating Lambda data sources

const api = new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
resolvers: {
"Query listNotes": "src/list.main",
"Query getNoteById": "src/get.main",
"Mutation createNote": "src/create.main",
},
});

api.addResolvers(this, {
"Mutation updateNote": "src/update.main",
"Mutation deleteNote": "src/delete.main",
});

Lazily adding resolvers

const api = new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
});

api.addResolvers(this, {
"Query listNotes": "src/list.main",
"Mutation createNote": "src/create.main",
});

Getting the function for a resolver

const api = new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
dataSources: {
notesDS: "src/notes.main",
billingDS: "src/billing.main",
},
resolvers: {
"Query listNotes": "notesDS",
"Mutation createNote": "notesDS",
"Mutation charge": "billingDS",
},
});

const resolver = api.getResolver("Mutation charge");

Custom domains

You can configure the API with a custom domain hosted either on Route 53 or externally.

Using the basic config

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
customDomain: "api.domain.com",
});

Using the full config

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
customDomain: {
domainName: "api.domain.com",
hostedZone: "domain.com",
},
});

Importing an existing certificate

import { Certificate } from "aws-cdk-lib/aws-certificatemanager";

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
customDomain: {
domainName: "api.domain.com",
cdk: {
certificate: Certificate.fromCertificateArn(this, "MyCert", certArn),
},
},
});

Specifying a hosted zone

If you have multiple hosted zones for a given domain, you can choose the one you want to use to configure the domain.

import { HostedZone } from "aws-cdk-lib/aws-route53";

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
customDomain: {
domainName: "api.domain.com",
cdk: {
hostedZone: HostedZone.fromHostedZoneAttributes(this, "MyZone", {
hostedZoneId,
zoneName,
}),
},
},
});

Loading domain name from SSM parameter

If you have the domain name stored in AWS SSM Parameter Store, you can reference the value as the domain name:

import { StringParameter } from "aws-cdk-lib/aws-ssm";

const rootDomain = StringParameter.valueForStringParameter(this, `/myApp/domain`);

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
customDomain: {
domainName: `api.${rootDomain}`,
cdk: {
hostedZone: HostedZone.fromHostedZoneAttributes(this, "MyZone", {
hostedZoneId,
zoneName,
}),
},
},
});

Note that, normally SST will look for a hosted zone by stripping out the first part of the domainName. But this is not possible when the domainName is a reference. So you'll need to specify the cdk.hostedZone explicitly.

Using externally hosted domain

import { Certificate } from "aws-cdk-lib/aws-certificatemanager";

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
customDomain: {
isExternalDomain: true,
domainName: "api.domain.com",
cdk: {
certificate: Certificate.fromCertificateArn(this, "MyCert", certArn),
},
},
});

Note that you can also migrate externally hosted domains to Route 53 by following this guide.

Authorization

Using API Key

import * as cdk from "aws-cdk-lib";
import * as appsync from "@aws-cdk/aws-appsync-alpha";

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
cdk: {
graphqlApi: {
authorizationConfig: {
defaultAuthorization: {
authorizationType: appsync.AuthorizationType.API_KEY,
apiKeyConfig: {
expires: cdk.Expiration.after(cdk.Duration.days(365)),
},
},
},
},
},
});

Using Cognito User Pool

import * as appsync from "@aws-cdk/aws-appsync-alpha";
import { Auth, AppSyncApi } from "@serverless-stack/resources";

// Create a User Pool using the Auth construct
const auth = new Auth(this, "Auth");

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
cdk: {
graphqlApi: {
authorizationConfig: {
defaultAuthorization: {
authorizationType: appsync.AuthorizationType.USER_POOL,
userPoolConfig: {
userPool: auth.cdk.userPool,
},
},
},
},
},
});

Using AWS IAM

import * as appsync from "@aws-cdk/aws-appsync-alpha";

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
cdk: {
graphqlApi: {
authorizationConfig: {
defaultAuthorization: {
authorizationType: appsync.AuthorizationType.IAM,
},
},
},
},
});

Using OpenID Connect

import * as appsync from "@aws-cdk/aws-appsync-alpha";

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
cdk: {
graphqlApi: {
authorizationConfig: {
defaultAuthorization: {
authorizationType: appsync.AuthorizationType.OIDC,
openIdConnectConfig: {
oidcProvider: "https://myorg.us.auth0.com",
},
},
},
},
},
});

Advanced examples

Configuring the GraphQL Api

Configure the internally created CDK GraphqlApi instance.

import * as appsync from "@aws-cdk/aws-appsync-alpha";

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
cdk: {
graphqlApi: {
name: "My GraphQL API",
logConfig: {
excludeVerboseContent: false,
fieldLogLevel: appsync.FieldLogLevel.ALL,
},
xrayEnabled: false,
},
},
});

Importing an existing GraphQL Api

Override the internally created CDK GraphqlApi instance.

import { GraphqlApi } from "@aws-cdk/aws-appsync-alpha";

new AppSyncApi(stack, "GraphqlApi", {
cdk: {
graphqlApi: GraphqlApi.fromGraphqlApiAttributes(this, "IGraphqlApi", {
graphqlApiId,
}),
},
resolvers: {
"Query listNotes": "src/list.main",
"Mutation createNote": "src/create.main",
},
});

AppSyncApiProps

customDomain?

Type : string | AppSyncApiDomainProps

Specify a custom domain to use in addition to the automatically generated one. SST currently supports domains that are configured using Route 53

new AppSyncApi(stack, "GraphqlApi", {
customDomain: "api.example.com"
})
new AppSyncApi(stack, "GraphqlApi", {
customDomain: {
domainName: "api.example.com",
hostedZone: "domain.com",
}
})

dataSources?

Type : Record<string, string | Function | AppSyncApiLambdaDataSourceProps | AppSyncApiDynamoDbDataSourceProps | AppSyncApiRdsDataSourceProps | AppSyncApiHttpDataSourceProps | AppSyncApiNoneDataSourceProps>

Define datasources. Can be a function, dynamodb table, rds cluster or http endpoint

new AppSyncApi(stack, "GraphqlApi", {
dataSources: {
notes: "src/notes.main",
},
resolvers: {
"Query listNotes": "notes",
},
});

defaults.function?

Type : FunctionProps

The default function props to be applied to all the Lambda functions in the AppSyncApi. The environment, permissions and layers properties will be merged with per route definitions if they are defined.

new AppSyncApi(stack, "AppSync", {
defaults: {
function: {
timeout: 20,
environment: { tableName: table.tableName },
permissions: [table],
}
},
});

resolvers?

Type : Record<string, string | Function | AppSyncApiResolverProps>

The resolvers for this API. Takes an object, with the key being the type name and field name as a string and the value is either a string with the name of existing data source.

new AppSyncApi(stack, "GraphqlApi", {
resolvers: {
"Query listNotes": "src/list.main",
"Query getNoteById": "src/get.main",
"Mutation createNote": "src/create.main",
"Mutation updateNote": "src/update.main",
"Mutation deleteNote": "src/delete.main",
},
});

schema?

Type : string | Array<string>

The GraphQL schema definition.

new AppSyncApi(stack, "GraphqlApi", {
schema: "graphql/schema.graphql",
});

cdk.graphqlApi?

Type : IGraphqlApi | AppSyncApiCdkGraphqlProps

Properties

An instance of AppSyncApi has the following properties.

apiArn

Type : string

The ARN of the internally created AppSync GraphQL API.

apiId

Type : string

The Id of the internally created AppSync GraphQL API.

apiName

Type : string

The name of the internally created AppSync GraphQL API.

customDomainUrl

Type : undefined | string

If custom domain is enabled, this is the custom domain URL of the Api.

url

Type : string

The AWS generated URL of the Api.

cdk.certificate?

Type : ICertificate

If custom domain is enabled, this is the internally created CDK Certificate instance.

cdk.graphqlApi

Type : GraphqlApi

The internally created appsync api

Methods

An instance of AppSyncApi has the following methods.

addDataSources

addDataSources(scope, dataSources)

Parameters

Add data sources after the construct has been created

api.addDataSources(stack, {
billingDS: "src/billing.main",
});

addResolvers

addResolvers(scope, resolvers)

Parameters

Add resolvers the construct has been created

api.addResolvers(stack, {
"Mutation charge": "billingDS",
});

attachPermissions

attachPermissions(permissions)

Parameters

Attaches the given list of permissions to all function datasources

api.attachPermissions(["s3"]);

attachPermissionsToDataSource

attachPermissionsToDataSource(key, permissions)

Parameters

Attaches the given list of permissions to a specific function datasource. This allows that function to access other AWS resources.

api.attachPermissionsToRoute("Mutation charge", ["s3"]);


### getDataSource

```ts
getDataSource(key)

Parameters

  • key string

Get a datasource by name

api.getDataSource("billingDS");

getFunction

getFunction(key)

Parameters

  • key string

Get the instance of the internally created Function, for a given resolver.

const func = api.getFunction("Mutation charge");

getResolver

getResolver(key)

Parameters

  • key string

Get a resolver

api.getResolver("Mutation charge");

MappingTemplateFile

file

Type : string

Path to the file containing the VTL mapping template

AppSyncApiDomainProps

domainName?

Type : string

The domain to be assigned to the API endpoint (ie. api.domain.com)

hostedZone?

Type : string

The hosted zone in Route 53 that contains the domain. By default, SST will look for a hosted zone by stripping out the first part of the domainName that's passed in. So, if your domainName is api.domain.com. SST will default the hostedZone to domain.com.

isExternalDomain?

Type : boolean

Set this option if the domain is not hosted on Amazon Route 53.

cdk.certificate?

Type : ICertificate

Override the internally created certificate

cdk.hostedZone?

Type : IHostedZone

Override the internally created hosted zone

MappingTemplateInline

inline

Type : string

Inline definition of the VTL mapping template

AppSyncApiResolverProps

Used to define full resolver config

dataSource?

Type : string

The data source for this resolver. The data source must be already created.

function?

Type : string | Function | FunctionProps

The function definition used to create the data source for this resolver.

requestMapping?

Type : MappingTemplateFile | MappingTemplateInline

VTL request mapping template

  requestMapping: {
inline: '{"version" : "2017-02-28", "operation" : "Scan"}',
},
  requestMapping: {
file: "path/to/template.vtl",
},

responseMapping?

Type : MappingTemplateFile | MappingTemplateInline

VTL response mapping template

  responseMapping: {
inline: "$util.toJson($ctx.result.items)",
},
  responseMapping: {
file: "path/to/template.vtl",
},

cdk.resolver

Type : Omit<ResolverProps, "api" | "fieldName" | "typeName" | "dataSource">

This allows you to override the default settings this construct uses internally to create the resolver.

AppSyncApiCdkGraphqlProps

name?

Type : string

AppSyncApiRdsDataSourceProps

Used to define a RDS data source

new AppSyncApi(stack, "AppSync", {
dataSources: {
rds: {
type: "rds",
rds: MyRDSCluster
},
},
});

databaseName?

Type : string

The name of the database to connect to

description?

Type : string

Description of the data source

name?

Type : string

Name of the data source

rds?

Type : RDS

Target RDS construct

type

Type : "rds"

String literal to signify that this data source is an RDS database

cdk.dataSource.databaseName?

Type : string

cdk.dataSource.secretStore

Type : ISecret

cdk.dataSource.serverlessCluster

Type : IServerlessCluster

AppSyncApiHttpDataSourceProps

Used to define an http data source

new AppSyncApi(stack, "AppSync", {
dataSources: {
http: {
type: "http",
endpoint: "https://example.com"
},
},
});

description?

Type : string

Description of the data source

endpoint

Type : string

URL to forward requests to

name?

Type : string

Name of the data source

type

Type : "http"

String literal to signify that this data source is an HTTP endpoint

cdk.dataSource.authorizationConfig?

Type : AwsIamConfig

AppSyncApiNoneDataSourceProps

Used to define a none data source

new AppSyncApi(stack, "AppSync", {
dataSources: {
http: {
type: "http",
endpoint: "https://example.com"
},
},
});

description?

Type : string

Description of the data source

name?

Type : string

Name of the data source

type

Type : "none"

String literal to signify that this data source is an HTTP endpoint

AppSyncApiLambdaDataSourceProps

Used to define a lambda data source

new AppSyncApi(stack, "AppSync", {
dataSources: {
lambda: {
type: "function",
function: "src/function.handler"
},
},
});

description?

Type : string

Description of the data source

function

Type : string | Function | FunctionProps

Function definition

name?

Type : string

Name of the data source

type?

Type : "function"

String literal to signify that this data source is a function

AppSyncApiDynamoDbDataSourceProps

Used to define a DynamoDB data source

new AppSyncApi(stack, "AppSync", {
dataSources: {
table: {
type: "table",
table: MyTable
},
},
});

description?

Type : string

Description of the data source

name?

Type : string

Name of the data source

table?

Type : Table

Target table

type

Type : "dynamodb"

String literal to signify that this data source is a dynamodb table

cdk.dataSource.table

Type : Table