Using the GraphQL Schema Language
The GraphQL schema language is a human-readable syntax to help create GraphQL schemas. In this lesson, we'll use the GraphQL schema language to re-create the schema we have in a more readable and simpler format.
📝 This lesson's quiz can be found - here. 🗒️ Solutions for this lesson's quiz can be found - here. 📃 Grab a cheatsheet that summarizes creating a simple GraphQL API with the
ApolloServer
constructor - here.
The GraphQL schema language (sometimes known as the Schema Definition Language) uses a simple syntax to define and create a GraphQL schema and is language agnostic. Most graphql server libraries provide us with the capability of creating a schema with the GraphQL schema language. The GraphQL JavaScript library also allows us to create a schema with the GraphQL schema language, but we'll achieve this with the apollo-server-express
package.
Apollo Server conventionally allows us to define a GraphQL schema by setting up two different values.
typeDefs
- string that represents the GraphQL schema.resolvers
- map of functions that implement the schema.
We'll create these in separate files located within a src/graphql
folder. We'll also create an index.ts
file in the src/grapqhl
folder to gather the typeDefs
and resolvers
map and export them explicitly from the graphql/
folder.
server/
src/
graphql/
index.ts
resolvers.ts
typeDefs.ts
// ...
typeDefs#
Listing
#
We'll begin by creating our schema definition with the GraphQL schema language in the src/graphql/typeDefs.ts
file. To do so, we'll import and use the gql
template literal tag from apollo-server-express
.
import { gql } from "apollo-server-express";
The gql
tag will allow us to write GraphQL in our code by having strings be parsed as a GraphQL Abstract Syntax Tree. Let's see this in action before we discuss how the gql
tag works. We'll export and create a const
variable named typeDefs
that has the gql
tag wrapped around a template literal string.
import { gql } from "apollo-server-express";
export const typeDefs = gql``;
We'll first define the Listing
object type as we've done in the previous lesson but in this instance use the syntax of the GraphQL schema language. We can define a new object type by using the type
keyword.
import { gql } from "apollo-server-express";
export const typeDefs = gql`
type Listing {}
`;
We can declare the fields of our Listing
object type and use the built-in scalar types to reference the types of each field - ID
for the id type, String
for the string types, and Int
for the integer types.
import { gql } from "apollo-server-express";
export const typeDefs = gql`
type Listing {
id: ID
title: String
image: String
address: String
price: Int
numOfGuests: Int
numOfBeds: Int
numOfBaths: Int
rating: Float
}
`;
Recall how we've wanted each of the fields within the Listing
type to never be null
? In the last lesson, we achieved this by wrapping the types with the GraphQLNonNull
wrapper. With the GraphQL schema language, we can simply place an !
after a type definition to declare that the type should always be defined.
import { gql } from "apollo-server-express";
export const typeDefs = gql`
type Listing {
id: ID!
title: String!
image: String!
address: String!
price: Int!
numOfGuests: Int!
numOfBeds: Int!
numOfBaths: Int!
rating: Int!
}
`;
Query
#
With our Listing
type defined, we can go ahead and declare the shape of the root Query
and Mutation
types.
We intend on having a single listings
field be in our Query
object that's responsible in returning a list of Listing
objects. With the GraphQL schema language, we can simply wrap the type with []
brackets to denote a GraphQL List.
import { gql } from "apollo-server-express";
export const typeDefs = gql`
type Listing {
id: ID!
title: String!
image: String!
address: String!
price: Int!
numOfGuests: Int!
numOfBeds: Int!
numOfBaths: Int!
rating: Int!
}
type Query {
listings: [Listing]
}
`;
For our listings
query field, we want to ensure the value returned is not null
and contains a list of not null
values. We'll place the !
marks accordingly to denote this.
import { gql } from "apollo-server-express";
export const typeDefs = gql`
type Listing {
id: ID!
title: String!
image: String!
address: String!
price: Int!
numOfGuests: Int!
numOfBeds: Int!
numOfBaths: Int!
rating: Int!
}
type Query {
listings: [Listing!]!
}
`;
Mutation
#
Finally, we'll declare the shape of the Mutation
object type that contains a deleteListing
field that is to return a required Listing
type.
import { gql } from "apollo-server-express";
export const typeDefs = gql`
type Listing {
id: ID!
title: String!
image: String!
address: String!
price: Int!
numOfGuests: Int!