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:
- parent: useful when working with relational data
- args: contains supplied operation arguments (params)
- context: contextual data, e.g. id of the authenticated user
- 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'));