Skip to main content

GraphQL Server

A GraphQL Server has to implement the GraphQL Specification.

GraphQL Server

Depending on the language you choose you might have multiple implementations to choose from. E.g. for node.js you can use GraphQL Yoga, which based on Apollo Server. GraphQL Yoga is GraphQL spec-compliant and provides you with a rich feature set, such as:

  • File upload
  • GraphQL Subscriptions
  • TypeScript typings
  • GraphQL Playground
  • Extensible via Express middleware
  • Schema directives
  • Apollo Tracing
  • Accepts both application/json and application/graphql content-types
  • Runs everywhere: Can be deployed via now, up, AWS Lambda, Heroku etc.
  • Supports middleware out of the box

You can easily create a server by passing it the schema + resolvers (for typeDefs and resolvers see sections below):

import { GraphQLServer } from 'graphql-yoga';

const server = new GraphQLServer({
typeDefs,
resolvers
});

server.start(() => console.log('Server is up'));

Type Definitions (Schema)

A schema describes data structures and operations you can perform on them. You can either use built-in "primitive" types or custom types to describe your data. The following 5 scalar (single value) types are supported:

  • String
  • Boolean
  • Int
  • Float
  • ID Note: Types must start with a capital letter

Each field you specify in your schema must be either of one of these types above or a custom type. A schema usually contains custom types (e.g. type User), queries (type Query) and mutations (type Mutation). Queries and Mutations must then be implemented by so called Resolvers.

You should put your type definitions into a schema.graphql file. Then you can pass the path to that file to the GraphQL server (e.g. typeDefs: '.src/schema.graphql').

Query

The following schema contains two queries. The first one is returning a scalar value (String) and the second one retruns an array of a custom type User (non-scalar value).

const typeDefs = `
type Query {
hello: String!
users: [User]!
}

type User {
id: ID!
name: String!
}
`

Mutation

const typeDefs = `
type Mutation {
createUser(name: String!): User!
}
`

Resolvers

Resolvers are functions that run when operations are performed. E.g.:

const resolvers = {
Query: {
hello() {
return 'static string';
},
users() {
return {
id: 'some-id',
name: 'Tom'
}
}
},
Mutation: {
createUser(parent, { name }) {
return {
id: 'some-id-2',
name
}
}
}
};

A resolver function can access the following four parameters:

  1. parent: useful when working with relational data
  2. args: contains supplied operation arguments (params)
  3. context: contextual data, e.g. id of the authenticated user
  4. info: info about the operation that gets send along to the server

Context

If we want to share information across resolver functions, e.g. authorized user, etc, we can make use of the context property.

import { GraphQLServer } from 'graphql-yoga';

const server = new GraphQLServer({
typeDefs,
resolvers
context: {
// whatever you want to share across all resolvers (3rd argument!)
}
});

server.start(() => console.log('Server is up'));