serverless-graphql-blog
This Serverless Framework Project creates a REST API for a basic blog structure, including Posts, Authors and Comments utilizing GraphQL and FaunaDB for persistent storage. The entire REST API consists of only 1 endpoint.
This project is based on an earlier Serverless demo. You can read about the original version in this blog post.
Install & Deploy
Make sure you have the most recent version of the Serverless Framework (1.0 and higher) and you are using NodeV4 or greater.
npm install serverless -g
Clone this repo:
git clone https://github.com/fauna/serverless-graphql-blog
cd serverless-graphql-blog
Install (top level) npm dependencies, and blog level dependencies.
npm install
cd blog/
npm install
cd ..
Sign up for FaunaDB for free, and configure database and a FaunaDB Server Secret for your application. Do this by visiting http://dashboard.fauna.com/ and creating a database, then browse back to its parent database and select Manage Keys > Create a Key. Then create a key with the server
role and copy the key secret to your serverless.yaml
file in place of SERVER_SECRET_FOR_YOUR_FAUNADB_DATABASE
Now deploy your service, and make note of the POST endpoint URL it's assigned.
serverless deploy
Invoke the private endpoint for creating the classes and indexes in your FaunaDB database.
serverless invoke --function setupFaunaDB
Querying with GraphiQL
The graphql-js endpoint provided in this Serverless Project is compatible with GraphiQL, a query visualization tool used with graphql-js.
Usage with GraphiQL.app (an Electron wrapper around GraphiQL) is recommended and is shown below:
Sample GraphQL queries
Before these queries will have anything to read, you'll want to create an author and some posts, at least. To create an author, visit the Author's class in the FaunaDB dashboard. The URL will look something like: https://dashboard.fauna.com/db/my-graphql-blog/classes/authors
Click "Create Instance", enter some data like this, and save your author instance.
{
"name": "Chris",
"id": "123"
}
Now, you can switch to GraphiQL to run a mutation to create a blog post. Make sure and enter the endpoint URL that came back when you ran serverless deploy
. Now you can enter a query like this to create a blog post for your author.
mutation createNewPost {
post: createPost (id: "5",
title: "Fifth post!",
bodyContent: "Test content",
author: "123") { id, title } }
Now that you've created some data, you can run other queries.
List of author names
{ authors { name } }
Results
{
"data":{
"authors":[
{"name":"Chris"}
]
}
}
List of posts with id and title
{ posts { id, title } }
Results
{
"data": {
"posts": [
{ "id":"1",
"title":"First Post Title"
}
]
}
}
List of posts with id, title and nested author name
{ posts { id, title, author { name } } }
Results
{
"data": {
"posts": [
{ "id":"1",
"title":"First Post Title",
"author":{
"name":"Chris"
}
}
]
}
}
List of posts with post, author and comments information (for a Post with no comments, i.e. comments:[])
{ posts { id, title, author { id, name }, comments { id, content, author { name } } } }
Results
{
"data":{
"posts":[
{
"id":"1",
"title":"First Post Title",
"author":{
"id":"1",
"name":"Kevin"
},
"comments":[]
}
]
}
}
Sample GraphQL Mutations
These have been expressed in curl, but you can use GraphiQL instead.
Create Post
curl -XPOST -d '{"query": "mutation createNewPost { post: createPost (id: \"5\", title: \"Fifth post!\", bodyContent: \"Test content\", author: \"1\") { id, title } }"}' <endpoint>/dev/blog/graphql
Results
{
"data":{
"post":{
"id":"5",
"title":"Fifth post!"
}
}
}
Mutation Validation
If your blog post title is too short it will fail. Validations are defined using graphql-custom-types in blog/lib/schema.js
curl -XPOST -d '{"query": "mutation createNewPost { post: createPost (id: \"8\", title: \"123456789\", bodyContent: \"Test content 5\") { id, title } }"}' <endpoint>/dev/blog/graphql
Results
{
"errors":[
{
"message":"Query error: String not long enough"}
]
}
Introspection Query
curl -XPOST -d '{"query": "{__schema { queryType { name, fields { name, description} }}}"}' <endpoint>/dev/blog/graphql
Returns:
{
"data":{
"__schema":{
"queryType":{
"name":"BlogSchema",
"fields":[
{
"name":"posts",
"description":"List of posts in the blog"
},
{
"name":"authors",
"description":"List of Authors"
},
{
"name":"author",
"description":"Get Author by id"
}
]
}
}
}
}
TODOs and Contribution Opportunities
-
Currently there is no creation mechanism for comments or authors, so those have to be created via the FaunaDB Dashboard. Adding Mutations for the cases should be straightforward.
-
Currently there is no UI for the blog. Maybe there is an existing graphql powered blog frontend that this backend can be adapted to fit?
-
Predicate pushdown is missing, so the graphql layer is not taking advantage of all the query capabilities FaunaDB offers. GraphQL and the FaunaDB query language are similar enough that a full-featured FaunaDB graphql layer could potentially combine queries after the resolver has run.