Create a cloud-enabled GraphQL API with AWS Amplify and Vue

Introduction to AWS AppSync

AWS AppSync allows you to create highly scalable serverless GraphQL data-driven mobile and web apps by providing an open source Amplify Framework (consisting of AWS AppSync Clients, GraphQL transforms and the CLI), integrations with multiple data sources, and the AWS AppSync console.

  • GraphQL client: client-side library to securely access data from your GraphQL API. Built-in support for real-time and offline/delta client synchronisation.
  • Amplify CLI: set of commands, via theapi category, to automate the setup and provision of resources for AWS AppSync and Amazon API Gateway cloud services. Support for REST and GraphQL APIs.
  • GraphQL Transforms: custom GraphQL schema directives that can be used in your GraphQL schema to enable custom workflows.
  • Data sources: databases (Amazon DynamoDB for NoSQL, Amazon Aurora for RDBMS), searches (Amazon Elasticsearch Service), and AWS Lambda functions.
AWS AppSync data-driven apps architecture overview

Setting up a new project with the Vue CLI

Before moving to the next section, please complete the steps described in “Build your first full-stack serverless app with Vue”.

Creating a new GraphQL API

For this post we are going to create a GraphQL API to list our favourite restaurants. To create it, we will use the following command:

amplify add api
  • Please select from one of the below mentioned services GraphQL
  • Provide API name: RestaurantAPI
  • Choose the default authorization type for the API API key
  • Enter a description for the API key: (empty)
  • After how many days from now the API key should expire (1–365): 7
  • Do you want to configure advanced settings for the GraphQL API No, I am done.
  • Do you have an annotated GraphQL schema? No
  • Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description)
  • Do you want to edit the schema now? Yes
type Restaurant @model {
id: ID!
name: String!
description: String!
city: String!
}

Using your first GraphQL transform

GraphQL transforms allow AppSync to provide further customisation and support for common scenarios, so you don’t have to.

  • @key to configure custom index structures in DynamoDB
  • @searchable to enable searches using Amazon Elasticsearch Service
  • @connection to add relationships between types
  • @lambda to generate AWS Lambda resolvers
  • @auth to add fine grained multi-authorisation support
  • @versioned to add conflict resolution for offline scenarios

Pushing your GraphQL API to the cloud

Let’s run the push command to create the GraphQL API and see the results of using the @model transform:

amplify push
  • Are you sure you want to continue? Yes
  • Do you want to generate code for your newly created GraphQL API Yes
  • Choose the code generation language target javascript
  • Enter the file name pattern of graphql queries, mutations and subscriptions src/graphql/**/*.js
  • Do you want to generate/update all possible GraphQL operations — queries, mutations and subscriptions Yes
  • Enter maximum statement depth [increase from default if your schema is deeply nested] 2
amplify console api
  • Please select from one of the below mentioned services GraphQL

Testing your new GraphQL API

Once in the AWS AppSync console, click on Queries on the left side. This will open an editor that we can use to edit and test GraphQL queries.

mutation createRestaurant {
createRestaurant(input: {
name: "Nobu"
description: "Great Sushi"
city: "New York"
}) {
id name description city
}
}
query listRestaurants {
listRestaurants {
items {
id
name
description
city
}
}
}
query searchRestaurants {
listRestaurants(filter: {
city: {
contains: "New York"
}
}) {
items {
id
name
description
city
}
}
}

Querying data with queries

In the earlier sections, we made sure we had a working GraphQL API. On the client, we will start by displaying a list.

<template>
<div v-for="restaurant of restaurants" :key="restaurant.id">
{{restaurant.name}}
</div>
</template>
<script>
import { API, graphqlOperation } from 'aws-amplify';
import { listRestaurants } from './graphql/queries';

export default {
name: 'app',
data() {
return {
restaurants: [],
}
},
created() {
this.getData();
},
methods: {
async getData() {
try {
const response = await API.graphql(graphqlOperation(listRestaurants));
this.restaurants = response.data.listRestaurants.items;
}
catch (error) {
console.log('Error loading restaurants...', error);
}
},
}
}
</script>
listRestaurants(filter: ModelRestaurantFilterInput, limit: Int, nextToken: String): ModelRestaurantConnectiontype ModelRestaurantConnection {
items: [Restaurant]
nextToken: String
}

Creating data with mutations

In order to add new restaurants, we are going to create a data entry using form to take the required user input and pass it forward to the createRestaurant mutation.

<template>
<div>
<form v-on:submit.prevent>
<div>
<label>Name: </label>
<input v-model='form.name' class='input' />
</div>
...
<button @click='createRestaurant' class='button'>Create</button>
</form>
</div>
</template>
<script>
import { createRestaurant } from './graphql/mutations';

export default {
name: 'app',
data() {
return {
form: { },
}
},
methods: {
async createRestaurant() {
const { name, description, city } = this.form
if (!name || !description || !city) return;

const restaurant = { name, description, city };
try {
const response = await API.graphql(graphqlOperation(createRestaurant, { input: restaurant }))
console.log('Item created!')
this.restaurants = [...this.restaurants, response.data.createRestaurant];
this.form = { name: '', description: '', city: '' };
} catch (error) {
console.log('Error creating restaurant...', error)
}
},
}
}
</script>
type Mutation {
createRestaurant(input: CreateRestaurantInput!): Restaurant
}input CreateRestaurantInput {
id: ID
name: String!
description: String!
city: String!
}

Adding real-time with subscriptions

To demonstrate real-time, we are going to use a subscription to update AppSync clients when new restaurants are added. AppSync clients will subscribe to listen for changes going through our GraphQL API. More specifically, restaurant creation mutations.

import { onCreateRestaurant } from './graphql/subscriptions';

export default {
name: 'app',
created() {
//Subscribe to changes
API.graphql(graphqlOperation(onCreateRestaurant))
.subscribe((sourceData) => {
const newRestaurant = sourceData.value.data.onCreateRestaurant
if (newRestaurant) {
// skip our own mutations and duplicates
if (this.restaurants.some(r => r.id == newRestaurant.id)) return;
this.restaurants = [newRestaurant, ...this.restaurants];
}
});
},
}

Publishing your app via the AWS Amplify Console

The first thing you need to do is create a new repo for this project. Once you’ve created the repo, copy the URL for the project to the clipboard and initialise git in your local project:

git init
git remote add origin repo@repoofyourchoice.com:username/project-name.git
git add .git commit -m 'initial commit'git push origin master
AWS Amplify Console deployment steps.

Cleaning up cloud services

If at any time, you would like to delete a service from your project and your AWS Account, you can do this by running:

amplify delete

Conclusion

Congratulations! You successfully built your first GraphQL API using Vue and AWS AppSync. Thanks for following this tutorial.

Thanks for reading!

Have you got any questions about this tutorial or AWS Amplify? Feel free to reach me anytime at @gerardsans.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Gerard Sans

Gerard Sans

Helping Devs to succeed #AI #web3 / ex @AWSCloud / Just be AWSome / MC Speaker Trainer Community Leader @web3_london / @ReactEurope @ReactiveConf @ngcruise