In the previous two posts, we firstly create a basic server, then extended this with REST functionality, now lets add GraphQL capabilities.
First off, run the following
- yarn add express-graphql graphql
- Add a folder named schema
With the schema folder add a new file userSchema.ts with the following code
import { buildSchema } from "graphql"; export const schema = buildSchema(` type User { firstName: String lastName: String } type Query { users: [User] } `);
In the above code, we create a GraphQL schema based upon our User type, along with the type Query for us to use the User type.
Next we’ll create a folder named resolvers along with the file userResolver.ts. GraphQL uses resolvers to interact with the data via GraphQL (like the code in the indexController in the previous post).
import { stubData } from "../models/user"; export const userResolver = { users: () => { return stubData; } }
Now let’s update the server.ts file by adding the GraphQL code, I’ll include the whole file here (at least the specifics for GraphQL)
import graphqlHTTP from "express-graphql"; import { schema } from "./schema/userSchema"; import { userResolver } from "./resolvers/userResolver"; const server = express(); server.use('/graphql', graphqlHTTP({ schema: schema, rootValue: userResolver, graphiql: true, })); const port = 4000; server.listen(port, () => console.log(`Server on port ${port}`) );
In the above we’ve specified graphiql: true which allows us to via the GraphIQL page using http://localhost:4000/graphql
Now if you type the following into the left hand (query) pane
{ users { firstName lastName } }
Running this from GraphIQL should output all our stubData.
We’ve essentially got the users method from our original code but now let’s add the equivalent of the create method, which in GraphQL terms is a mutation type.
In the userSchema.ts file, change the schema to look like this
export const schema = buildSchema(` type User { firstName: String lastName: String } input UserInput { firstName: String lastName: String } type Mutation { create(user: UserInput): User } type Query { users: [User] } `);
We’ve added an input type UserInput along with the type Mutation. Next, within the userResolve.ts file change the userResolve to add the create function, as below
export const userResolver = { users: () => { return stubData; }, create: (data: any) => { stubData.push(new User(data.user.firstName, data.user.lastName)); return data.user; } }
Let’s test this code by executing the following query via GraphIQL
mutation { create(user: { firstName: "Miner", lastName: "FortyNiner", }) { firstName lastName } }