/serverless-graphql-blog

A Serverless Blog leveraging GraphQL to offer a REST API with only 1 endpoint using Serverless v1.0

Primary LanguageJavaScript

Serverless GraphQL Blog AWS Lambda API Gateway

serverless

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:

GraphiQL.app demo

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.