Skip to main content

Introduction

With the power of Apache Velocity, AWS AppSync allows for quick deployment of GraphQL APIs. Stored AppSync VTL resolvers require manual instructions to associate it with a GraphQL field. For this, AppSync Butler offers a simple development framework to parse and load VTL resolvers into CDK or SST AppSync constructs by leveraging an intuitive directory structure.

๐Ÿš€ย  Features

โœจย  Simple and intuitive. AppSync Butler is an open and humble framework.

๐Ÿ’‰ย  Variable injection. Define global variables for replacement in AppSync mapping templates.

๐Ÿฆ„ย  Bind resolvers to data sources from within request mapping templates.

๐Ÿฅžย  Comaptible with AWS Cloud Development Kit and Serverless Stack Toolkit.

๐Ÿค”ย  How it works

tip

If you're unfamiliar with AWS AppSync, head over to the AWS AppSync Docs.

With the below GraphQL schema and directory structure, AppSync Butler maps each AppSync Resolver to its corresponding GraphQL field.

schema {
query: Query
mutation: Mutation
}

type Query {
getPost(id: ID!): Post
}

type Mutation {
addPost(post: PostInput!): Post!
}

type Post {
id: ID!
author: Author!
title: String!
content: String!
}

type Author {
id: ID!
username: String!
}
vtl
โ”œโ”€โ”€ functions
โ”‚ย ย  โ”œโ”€โ”€ GetAuthorByAuthorId
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ description.txt
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ request.vtl
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ response.vtl
โ”‚ย ย  โ””โ”€โ”€ GetAuthorIdByPostId
โ”‚ย ย  โ”œโ”€โ”€ description.txt
โ”‚ย ย  โ”œโ”€โ”€ request.vtl
โ”‚ย ย  โ””โ”€โ”€ response.vtl
โ””โ”€โ”€ resolvers
โ”œโ”€โ”€ Mutation
โ”‚ย ย  โ””โ”€โ”€ addPost
โ”‚ย ย  โ”œโ”€โ”€ request.vtl
โ”‚ย ย  โ””โ”€โ”€ response.vtl
โ”œโ”€โ”€ Post
โ”‚ย ย  โ””โ”€โ”€ author
โ”‚ย ย  โ”œโ”€โ”€ after.vtl
โ”‚ย ย  โ”œโ”€โ”€ before.vtl
โ”‚ย ย  โ””โ”€โ”€ pipeline.seq
โ””โ”€โ”€ Query
โ””โ”€โ”€ getPost
โ”œโ”€โ”€ request.vtl
โ””โ”€โ”€ response.vtl

โœจย  Tabular representation

ResolverResolver TypeGraphQL TypeGraphQL Field
vtl/resolvers/Query/getPostUnitQuerygetPost
vtl/resolvers/Mutation/addPostUnitMutationaddPost
vtl/resolvers/Post/authorPipelinePostauthor

๐Ÿค–ย  Functions

Each subdirectory under vtl/functions/ should contain the necessary files to build an AppSync VTL function:

  • Request Mapping Template: request.vtl
  • Response Mapping Template: response.vtl
  • Description (optional): description.txt

When loading functions, AppSync Butler iterates over each function and adds it to the supplied CDK or SST AppSync construct.

๐Ÿง ย  Resolvers

info

AppSync Butler supports both unit and pipeline resolvers.

Each subdirectory under vtl/resolvers/ should represent a valid GraphQL type (e.g. vtl/resolvers/Query) and contains zero-or-more subdirectories as field-level resolvers (e.g. vtl/resolver/Query/getPost). AppSync Butler reads the VTL files in vtl/resolver/Query/getPost and adds the Query.getPost resolver to the GraphQL API construct.

Unit resolver files

  • Request Mapping Template: request.vtl
  • Response Mapping Template: response.vtl

Pipeline resolver files

  • Before Mapping Template (optional): before.vtl
  • Pipeline sequence definition file: pipeline.seq
  • After Mapping Template (optional): after.vtl

The pipeline sequence defintion file denotes the ordered AppSync VTL functions to execute sequentially using newline-delimitted function names. To execute vtl/functions/GetUserId and vtl/functions/GetUser, we can define the pipeline sequence defintion file in the following format:

GetUserId
GetUser

AppSync Butler handles the necessary steps to load this pipeline resolver into AppSync.

แตกย  Variables

AppSync Butler parses mapping templates (request, response, before, after) and replaces references of a user-defined variable to its specified value. Variables are denoted as {{ var }}. Variables are defined during the instantialization of a loader or set using loader.builder.parser.setVariable(key, value)

danger

AppSync Butler throws an UndefinedVariableError if an unrecognized variable is encountered in a mapping template.

๐Ÿ”ฎย  Data Sources

Data sources are provided during instantialization and specified directly from with-in request mapping templates.

/vtl/resolvers/Query/getPost/request.vtl
##@butler.dataSource('myDynamoDbDataSource')

{
"version": "...",
"operation": "GetItem",
"key": { ... }
}
info

Alternatively, the default data source can be provided during instantialization. This is highly suitable for Single Table design applications where setting the data source is not necessary.

๐ŸŽฏย  Who's this for

  • Developers utilizing AWS CDK or SST to deploy a GraphQL API.
  • Entrepreneurs leveraging AWS AppSync to define their business logic and require a simplistic AppSync development framework with a smooth learning curve.
tip

As an entrepreneur that is heavily relying on AWS AppSync, it is highly cruicial to employ Infrastructure-as-Code tools such as AWS Cloud Development Kit or Serverless Stack Toolkit to define your stack as it boosts your product value.

๐Ÿš˜ย  Forthcoming features

To support us, give this project a star on GitHub. Here's a list of future objectives that are still under consideration:

  • Provide a, programmable, resolver testing mechanism through deploying a test stack and executing GraphQL operations against it. Alternatively, simulating VTL templates yields a zero-cost test suite.
  • VTL validation prior deployment. This would cut-down time spent in errorus deployments.
  • Access properties of other data sources (e.g. a DynamoDB's table name) instead of relying on defined variables.
  • Possibly warn users of any missing resolvers for any GraphQL fields.