Introduction to GraphQL
Web / Mobile / VR / AR / IoT / AI
Software architect, consultant, GDE, author
What is GraphQL
GraphQL
A query language for your API
What's wrong with REST
Restful API
The core idea in REST is to have a URL for every resource
RESTfull API problems
Description of resource is coupled to implementation
Overfetching
Underfetching
chaining requests to server to get needed data
So how does GraphQL solve it
Avoid over-fetching
Prevent multipe API calls
Lesser communication with API developers
Self-documenting
How it looks like
Operations
Queries - fetching data from graphql endpoint
Mutations- modifying the data or running a side effect
Subscriptions - subscribe to real-time updates through web sockets
query getPlanets {
allPlanets(first: 1) {
planets {
planet: {
name
}
}
}
}
argument
query getPosts {
first_post: posts(order_by: [{ timestamp:asc}], limit: 1) {
subject
}
last_post: posts(order_by: [{ timestamp:asc}], limit: 1) {
subject
}
}
aliases
mutation deletePost($postId: uuid!) {
delete_posts(where:{id: {_eq: $postId}}) {
affected_rows
returning {
id
}
}
}
variables
Queries - fetching data from graphql endpoint
mutation {
insert_posts(objects: [{
subject: "First blog post"
content: "Hello there"
user: {
data: {
firstName:"John"
lastName:"Smith"
profile: {
data:{ avatarUrl:"some url" bio:"Lorem ipsum"}
}
}
}
}]) {
returning {
id
subject
content
user {
firstName
lastName
}
}
}
}
Mutations- modifying the data or running a side effect
subscription subscribeToMostLikedPosts {
posts(order_by:{ likes:asc} limit: 3) {
subject
content
}
}
Subscriptions - subscribe to real-time updates through web sockets
GraphQL SDL
type Post {
title: String!
content: String!
user: User!
}
type User {
id: ID!
name: String!
address: String
posts: [Post!]!
}
GraphQL Object Type,
fields
Built-in scalar type
Non Nullable
Array type
- Int: A signed 32‐bit integer.
- Float: A signed double-precision floating-point value.
- String: A UTF‐8 character sequence.
- Boolean: true or false.
- ID
GraphQL SDL
GraphQL Resolvers
Query: {
human(obj, args, context, info) {
return context.db.loadHumanByID(args.id).then(
userData => new Human(userData)
)
}
}
Resolver is a function that resolves data for GraphQL type with compliance to schema
Server implementation
Writing your own server
yarn add apollo-server graphql
const { ApolloServer, gql } = require('apollo-server')
const posts = [{
id: 1,
title: "Some title",
description: "Description",
userId: 1
}]
const users = [{
id: 1,
name: "Vladimir Novick",
email: "12312@asdfa.com"
}]
const typeDefs = gql`
type Post {
id: ID!
title: String!
description: String!
user: User
}
type User {
id: ID!
name: String!
email: String
}
type Query {
posts: [Post]
users: [User]
}
type Mutation {
addPost(post: PostInputType): Post
}
input PostInputType {
userId: ID!
title: String!
content: String!
}
`
const resolvers = {
Query: {
posts: () => posts.map(post => {
const user = users.find(user => user.id === post.userId)
return {
id: post.id,
title: post.title,
description: post.description,
user
}
}),
users: () => users
},
Mutation: {
addPost: (_, { post: {userId, title, content}}) => {
const user = users.filter(user => user.id === userId).reduce((acc, u) => u, {})
const postToPublish = {
id: posts.reverse()[0].id + 1,
title,
description: content,
userId: user.id
}
posts.push(postToPublish)
return postToPublish
}
}
}
const server = new ApolloServer({
typeDefs,
resolvers
})
server.listen().then(({ url }) => console.log(url));
What about the client?
yarn add @apollo/react-hooks
passing variables to mutation
passing different options such as refetchQueries etc
What about Architecture
Microservices architecture
3factor.app Architecture
How do you start with backend?
- Code your own
- Use Hasura
- Use AWS AppSync
What is Hasura
open source and free engine that gives you auto-generates real-time GraphQL API on top of new or existing PostgreSQL database
Features
- Can be deployed to any cloud or run locally
- Compatible with all Authentication solutions
- Can run on top of new or existing Postgres database
- Supports Postgres addons (PostGIS, TimescaleDB)
- Auto-generates GraphQL api
- GraphQL queries are compiled to performant SQL statements using native Postgres features
Features
- Comes with hasura-cli which has awesome tools like migrations and more
- Can work with custom SQL statements
- Has configurable access controls for data
- Can be connected to your own GraphQL server (does schema stitching)
- Has eventing system which enables to trigger serverless functions
Let's see it in action
Download docker-compose.yaml
wget https://raw.githubusercontent.com/hasura/graphql-engine/stable/install-manifests/docker-compose/docker-compose.yaml
docker-compose up
Hasura Console overview
- GraphiQL - run your queries in in-browser IDE
- Data - manage your data, access control, relations, permissions
- Remote Schemas - stitch GraphQL schema of your custom GraphQL server
- Event Triggers - connect your serverless functions
GraphiQL tab - use for development
- Set endpoint headers
- Execute queries and mutations
- Analyse queries
Data tab - data management interface
- View and insert data into db
- create and modify tables
- Create relationships
- set permissions and access control
- execute custom sql statements
Remote Schemas tab
stitch your custom GraphQL server schema
Event triggers
- connect custom webhooks to database events to execute serverless functions
- set retry logic
- forward custom headers to webhook
Authentication
Run hasura locally on top of existing postgres
GraphQL meets Distributed SQL
Create local YugabyteDB cluster
yb-ctl create --rf 3 --tserver_flags "ysql_suppress_unsupported_error=true"
Connect to ysqlsh
./bin/ysqlsh --echo-queries
Load sample data
Run Hasura on top of newly created Db
docker run -d -p 8080:8080 -e \
HASURA_GRAPHQL_DATABASE_URL=postgres://postgres:@host.docker.internal:5433/yb_demo \
-e HASURA_GRAPHQL_ENABLE_CONSOLE=true hasura/graphql-engine:latest
Let's see it in action
Thank You
@VladimirNovick
GraphQL - what why and how
By Vladimir Novick
GraphQL - what why and how
- 1,743