Unleashing the power of GraphQL

slides.com/joekarlsson | @joekarlsson1

I am
Joe Karlsson

Software Engineer

How's this going to work?

Project Setup

Prerequisites

Clone repo & follow setup instructions

demo

GraphQL

GraphQL Timeline

2012

GraphQL created at Facebook

Support Mobile Native Teams

2015

Open sourced

First Specification

GraphQL.js

2016

GitHub announces GraphQL API

New GraphQL website

First GraphQL Summit

GraphQL First

 

2017

GraphQL Europe

Apollo Client 0.10.0 (RC-0)

graphql.org

Implementations

Query Language


// GET '/graphql'
{
 user(name: "gsans") {
  twitter
 }
}

// result
{
 "user": {
  "twitter": "@gerardsans"
 }
}

GraphQL Server

source: blog

Who is using it?

Why use GraphQL?

Some reasons

  • Declarative
  • De-coupled from storage
  • Validated and structured
  • Facilitates Collaboration
  • Super fast
  • No more API Versioning

Solution Architecture

Server

Client

GraphQL Schema

Type System

  • Scalar Types:
    • Int
    • Float
    • String
    • Boolean
    • ID 
  • Object Types: Todo
  • Entry points: Query, Mutation

Schema Syntax

  • Nullable: String, Todo
  • Non-nullable: String!, Todo!
  • Arrays: [String], [Todo]

Todos Schema (1/2)

schema { 
  query: Query,  
  mutation: Mutation 
}

type Query {
  allTodoes(skip: Int, take: Int): [Todo!]!
}

type Todo {  
  id: ID!
  text: String!
  complete: Boolean!
}

Todos Schema (2/2)

schema { 
  query: Query,  
  mutation: Mutation 
}

type Mutation {
  addTodo(text: String!, complete: Boolean!): Todo
  deleteTodo(id: ID!, text: String, complete: Boolean): Todo
}

Efficient Queries

// server/graphql/schema

const {
  GraphQLObjectType,
  GraphQLNonNull,
  GraphQLSchema,
  GraphQLString,
  GraphQLList,
  GraphQLInt,
  GraphQLBoolean
} = require("graphql/type");

const todoType = new GraphQLObjectType({
  name: "todo",
  description: "todo item",
  fields: () => ({
    itemId: {
      type: GraphQLInt,
      description: "The id of the todo."
    },
    item: {
      type: GraphQLString,
      description: "The name of the todo."
    },
    completed: {
      type: GraphQLBoolean,
      description: "Completed todo?"
    }
  })
});
// server/graphql/schema

const ToDoMongo = require("../database/Todo");

const TodoQueryType = new GraphQLObjectType({
  name: "RootQueryType",
  fields: {
    todo: {
      type: new GraphQLList(todoType),
      description: "Todo items",
      args: {
        itemId: {
          name: "itemId",
          type: new GraphQLNonNull(GraphQLInt)
        }
      },
      resolve: (root, { itemId }, source, fieldASTs) => {
        const foundItems = new Promise((resolve, reject) => {
          ToDoMongo.find({ itemId }, (err, todos) => {
            err ? reject(err) : resolve(todos);
          });
        });

        return foundItems;
      }
    }
  }
});

const schema = new GraphQLSchema({
  query: TodoQueryType
});

module.exports = schema;
// server/graphql/schema

todos: {
  type: new GraphQLList(todoType),
  description: "All todo items",
  args: {},
  resolve: () => {
   const foundItems = new Promise((resolve, reject) => {
      ToDoMongo.find((err, todos) => {
        err ? reject(err) : resolve(todos);
      });
   });

   return foundItems;
  }
},
// server/server.js

const graphqlHTTP = require("express-graphql");

app.use(
  "/graphql",
  graphqlHTTP(request => {
    return {
      schema: schema,
      graphiql: true,
      pretty: true,
      formatError: error => ({
        message: error.message,
        locations: error.locations,
        stack: error.stack ? error.stack.split("\n") : [],
        path: error.path
      })
    };
  })
);

demo

GraphiQL

demo

Effective Mutations

// server/graphql/schema.js

const TodoMutationType = new GraphQLObjectType({
  name: 'todoMutation',
  description: 'These are the things we can change on a todo item.',
  fields: () => ({
    AddTodo: {
      type: todoType,
      description: 'Create a todo and return the new todo.',
      args: {
	itemId: {
            type: new GraphQLNonNull(GraphQLInt),
	    description: 'The id of the todo.',
	    },
            item: {
                type: new GraphQLNonNull(GraphQLString),
		description: 'The name of the todo.',
	    },
	    completed: {
                type: GraphQLBoolean,
		description: 'Has the todo been completed?',
	    }
      },
      resolve: (value, { itemId, item, completed }) => {
            const newTodo = new Promise((resolve, reject) => {
	        ToDoMongo.create({itemId, item, completed},(err, todo) => {
		    err ? reject(err) : resolve(todo);
	    });
	});

	return newTodo
      }
    }
  }),
});


const schema = new GraphQLSchema({
    query: TodoQueryType,
    mutation: TodoMutationType,
});

// client/App.js
createNewTodo (event) {
    event.preventDefault();
    const { value } = this.state;
    const resource = 'AddTodo';
    const params = {itemId: 1234, item: value, completed: false};
    const fields = `{itemId item completed}`;

    getGraphQlData(resource, params, fields, false)
        .then(newTodo => {
	    const newTodos = this.state.todos.slice();
	    newTodos.push(newTodo.data.AddTodo)
	    this.setState({
	        todos: newTodos,
	        value: '',
	    });
        })
        .catch(err => {
            console.error('err', err);
        });
}

demo

1) REST v. GraphQL

2) Schema

3) GraphiQL

4) Queries

5) Mutations

Thanks!

Additional Resources

Let's stay connected

Feedback Welcome!

Please fill out this feedback form:
https://goo.gl/forms/Hsn6oonjyIl1yxCm1

Made with Slides.com