GraphQL

Declarative way to ask for data from server for any language, its a specification and has many different libs

Benefits:

  • Insightful analytics by data accesses

  • Uses strong type system to define capabilities of an API so frontend and backend work independently

  • Frontend just asks for data they need, no interaction, knowledge of sources, or request needed allowing fast solo iteration

Use cases:

  1. GraphQL with connected database, single web server that implements GraphQL server

  2. GraphQL server weak layer infront of existing systems to unify and hide complexity, doesn't care about sources whether third-party apis, legacy systems, etc

  3. Hybrid

GraphQL vs REST for Frontend

REST

Rest has stateless servers & structured access and currently overused term

Rest would have:

/users/<id>
/users/<id>/posts
/users/<id>/followers

Could change api to be exactly what the page needs, but doesn't allow fast frontend iteration

GraphQL

One graphql url with a post request specifying what you want

Schema Definition Language(SDL)

  • Default types are Int, Float, String, Boolean, ID

Define a one to many relationship:

type Person {
	id: ID!
"""#! means required"""
	name: String! 
	age: Int!
	posts: [Post!]! 
"""Inside ! means values in array nonnullable, and outside means array must exist"""
}

type Post {
	title: String!
	author: Person! 
}

Root Types

This defines ALL queries, mutations, and subscriptions

type Query {
	allPersons(last: Int): [Person!]!
}

type Mutation {
	createPerson(name: String!, age: String!): Person!
	updatePerson(id: ID!, name: String!, age: String!): Person!
	deletePerson(id: ID!): Person!
}

type Subscription {
	newPerson: Person!
	updatedPerson: Person!
	deletePerson: Person!
}

Define a Query

{
	allPersons {
		name
			posts {
				title
			}
	}
}

Modifiers

{
	allPersons(last: 2) {
		name
	}
}

Writing Data with Mutations

Creating, updating, and deleting

mutation {
	createPerson(name: "Bob", age: 36) {
    name
    age
  }
}

Server responds with information shaped by mutation send

{
	"createPerson": {
		"name": "Bob",
		"age": 36
	}
}

Subscriptions

Continuous connection that will push data

subscription {
	newPerson {
		name
		age
	}
}

Resolver

Graphql queries/mutations consists of set of fields

Server have one resolver function per field to fetch data

If query is:

query {
	User(id: "er3txsa8jklf") {
		name
		friends(first: 5) {
			name age
		}
	}
}

Resolvers needed are:

User(id: String!): User
name(user: User!): String!
age(user: User!: Int!)
friends(first: Int, user: User!): [User!]

AWS GQL

Using gel

const LIST_STORY_BY_FILTER = gql`
  query StoryByFilterIdCreatedAt(
    $filterId: String!
    $createdAt: ModelStringKeyConditionInput
    $sortDirection: ModelSortDirection
    $filter: ModelStoryFilterInput
    $limit: Int
    $nextToken: String
  ) {
    storyByFilterIdCreatedAt(
      filterId: $filterId
      createdAt: $createdAt
      sortDirection: $sortDirection
      filter: $filter
      limit: $limit
      nextToken: $nextToken
    ) {
      items {
        id
      }
      nextToken
      __typename
    }
  }
`;

Deleting

  mutation DeleteOptixRanking(
    $input: DeleteOptixRankingInput!
    $condition: ModelOptixRankingConditionInput
  ) {
    deleteOptixRanking(input: $input, condition: $condition) {
      id
      type
      storyIds
      createdAt
      updatedAt
      __typename
    }
  }

Development Server

http://localhost:8000/___graphql

Press Ctrl + Space (or use Shift + Space as an alternate keyboard shortcut) to bring up the autocomplete window and Ctrl + Enter to run the GraphQL query.

Last updated