How to Build a GraphQL Schema with GraphQL.js

In this lesson, we'll use the Apollo Server and GraphQL JavaScript libraries to create a minimal GraphQL API that we'll be able to interact with in an IDE environment known as GraphQL Playground.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

Creating a GraphQL Schema with the GraphQL JS Library

📝 This lesson's quiz can be found - here.
🗒️ Solutions for This lesson's quiz can be found - here.

Gameplan

Let's quickly summarize how we want to introduce Apollo Server before we begin doing so.

To introduce Apollo server to our application, the first thing we'll need to do is create an instance of Apollo server. This is done by importing the ApolloServer class and constructing a new instance with the ApolloServer constructor.

import { ApolloServer } from "apollo-server-express";

const server = new ApolloServer();

With an Apollo Server instance created, the apollo-server-express library allows us to specify middleware that works alongside the existing server middleware. It's in this middleware where we can pass in the express app instance as well as specify the endpoint for where our GraphQL API should live.

import { ApolloServer } from "apollo-server-express";

const app = express();
const server = new ApolloServer();

server.applyMiddleware({ app, path: "/api" });

The ApolloServer() constructor can take in a series of options needed to instantiate the Apollo Server instance. The conventional options that can often be passed in are the:

  • typeDefs: String that represents the entire GraphQL schema.
  • resolvers: Map of functions that implement the schema.

Though we're going to aim to get to this point, we'll begin by going through a more "bare-bones" approach to creating a GraphQL server. In the first attempt to creating our schema, we'll import and create GraphQLObjectType's with the help of the graphql JavaScript library.

Simple GraphQL Schema

To begin, we'll have the ApolloServer constructor class imported in our /src/index.ts file. We'll run the constructor function and assign the result to a server const variable. We won't pass in any arguments to the constructor just yet. We'll apply middleware to the Apollo Server instance and pass in the express app instance, and state our GraphQL API will be on a path of /api.

Finally, we'll also remove all the RESTful Express Routes we've created since we'll now be moving towards GraphQL. We'll remove the import of listings as well as remove the import and use of bodyParser.

At this moment, our src/index.ts file will look like the following:

import express from "express";
import { ApolloServer } from "apollo-server-express";

const app = express();
const port = 9000;
const server = new ApolloServer();

server.applyMiddleware({ app, path: "/api" });
app.listen(port);

console.log(`[app] : http://localhost:${port}`);

Let's now look to create a schema with the graphql JavaScript library. We'll build our schema within a new file called graphql.ts that is to be created in our src/ folder.

server/
  // ...
  src/
    graphql.ts
    index.ts
    listings.ts
  // ...

To create our schema, we'll be using class objects that the graphql JavaScript library provides. We're going to begin by importing two classes from the graphql library GraphQLSchema and GraphQLObjectType.

import { GraphQLSchema, GraphQLObjectType } from "graphql";
  • GraphQLSchema is to be used to create a GraphQL Schema by passing in the root level query and mutation GraphQL object types.
  • GraphQLObjectType is the most basic component of a GraphQL schema which can be used to represent practically all our GraphQL object types from the root query and mutation types to specific custom types.

This lesson preview is part of the The newline Guide to Building Your First GraphQL Server with Node and TypeScript course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to The newline Guide to Building Your First GraphQL Server with Node and TypeScript, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course The newline Guide to Building Your First GraphQL Server with Node and TypeScript
  • [00:00 - 00:12] Let's quickly summarize how we want to introduce Apollo Server before we begin doing so. To introduce Apollo Server to our application, the first thing we'll need to do is create an instance of Apollo Server.

    [00:13 - 00:36] This is done by importing the Apollo Server class and constructing a new instance with the Apollo Server constructor. With an Apollo Server instance created, the Apollo Server Express library allows us to specify middleware that work alongside the existing Server middleware.

    [00:37 - 00:55] It's in this middleware where we can pass in the Express app instance as well as specify the endpoint for where our GraphQL API should live. The Apollo Server constructor can take in a series of options needed to instant iate the Apollo Server instance.

    [00:56 - 01:17] The conventional options that can be passed are the type definitions, a string that represents the entire GraphQL schema, and resolvers, map of functions that implement the schema. Though we're going to aim to get to this point, we'll actually begin by going through a more bare-bones approach to creating our GraphQL Server.

    [01:18 - 01:35] In the first attempt, we'll import and create GraphQL object types with the help of the GraphQL JavaScript library. To begin, we'll remove the empty type definitions, string and resolvers map in our constructor.

    [01:36 - 01:46] We'll remove all the RESTful Express routes we've created since we'll be moving to implement this with GraphQL. We'll remove the import of listings for now.

    [01:47 - 02:05] And finally, we'll also remove the import and use of body parser since we won't need it any longer. TypeScript gives us a warning at the Apollo Server constructor function since it expects an argument here that we haven't specified.

    [02:06 - 02:20] Here it expects a configuration that contains either an existing schema or type definitions and resolvers. We'll create a schema with the GraphQL JavaScript library and come back and use it here when complete.

    [02:21 - 02:38] We'll build our schema within a new file called GraphQL that is to be created in our source folder. To create our schema, we'll be using class objects that the GraphQL JavaScript library provides.

    [02:39 - 02:49] We're going to begin by importing two classes from the GraphQL library. GraphQL object type and GraphQL schema.

    [02:50 - 03:16] GraphQL object type is the most basic component of a GraphQL schema which can be used to represent practically all our GraphQL types, from the root query and mutation types to specific custom types. GraphQL schema is a class that will allow us to create a GraphQL schema by passing in the query and mutation GraphQL object types.

    [03:17 - 03:35] To get us started, we'll construct a blank query and mutation object types with the help of the GraphQL object type class. The GraphQL object type constructor can take a series of options.

    [03:36 - 03:56] However, we'll only specify the name option for each object type for now and name them accordingly as query and mutation. We'll then pass the constructed query and mutation object types as options to our GraphQL schema constructor.

    [03:57 - 04:07] We'll also export this created schema. Note that this is us using the ES6 property shorthand syntax here.

    [04:08 - 04:23] This is equivalent to us basically specifying the value here being the same name as the keys that we're passing in. The ES6 syntax allows us to omit this if the value name is the same as the name of the key.

    [04:24 - 04:40] So the shorthand syntax can just be directly us placing query and mutation. TypeScript displays some errors in our GraphQL object type constructors telling us that the fields of the object type is required.

    [04:41 - 04:52] This is valid since the GraphQL query language is all about selecting fields on objects. We'll go ahead and declare the fields option for each object type.

    [04:53 - 05:05] The fields option expects us to specify a map of the different fields that live within the object type. In both cases, we'll declare a simple hello field to get us started.

    [05:06 - 05:33] a field property also takes options of its own. Here we can specify the type option to dictate the type of the field and it resolve function to dictate how the field is expected to resolve. Type could be a scalar type, object type, enum type, etc.

    [05:34 - 05:53] In this case, we'll say that the return type of our hello field is a string. So we'll import the GraphQL string scalar type and specify that as the type of our hello fields.

    [05:54 - 06:08] Every field in a schema should have a resolver function that resolves the value of that GraphQL field. Here we're able to use the resolve function option to do so.

    [06:09 - 06:24] For both hello fields, we'll resolve to return simple string messages. Hello from the query for the query and hello from the mutation for the mutation .

    [06:25 - 06:43] We'll now save the changes we've made in this file. With our bare bones schema created, we can have it imported and passed into the Apollo server constructor in the source index.ts file.

    [06:44 - 07:08] And that's it for now. We'll head to the terminal, run our server, and when the server is running, we 'll head to the routes we've specified as our GraphQL API, which would be localhost9000/ api.

    [07:09 - 07:28] When doing so, we'll be presented with an interactive IDE to now interact with our own API. Apollo server provides this IDE known as GraphQL Playground, which is built by the Prisma team and based on another IDE called Graphical.

    [07:29 - 07:49] We used the Graphical interface when we interacted with GitHub's public GraphQL API. GraphQL Playground is intended to be a more sophisticated IDE by giving us capabilities such as looking through query history, automatic schema reloading, configuration of HTTP headers, and so on.

    [07:50 - 08:15] The vast majority of time, we'll often find ourselves interacting with our schema by surveying the documentation of the schema and running queries and mutations to verify that our API works as intended without having to use curl or tools like Postman. With that said, let's look to see how our bare bones GraphQL API behaves.

    [08:16 - 08:35] When we open the docs tab, we can see the hello field be specified as an option for both the query GraphQL object type and the mutation GraphQL object type. Whenever we click a field, we're always presented with details about the type in question.

    [08:36 - 08:47] On the left hand pane, let's look to write our first query. We'll use the query keyword and declare the hello field as the field we'd like to query.

    [08:48 - 09:02] We'll press play and when successful, we'll get the data we expect, the string that says hello from the query. This will behave very similar for the mutation as well.

    [09:03 - 09:20] We'll just change the query keyword to mutation, but we'll keep the hello field since that's the field we'd also like to retrieve from the mutation. When we press play, we'll also get the expected string value that now says hello from the mutation.

    [09:21 - 09:25] Amazing. Our Express app is now fully prepared with Apollo server.