GraphQL
The Backend
Create the server
npm init
npm i express
Create server.js to spin up the server and listen in any post (here 4000)
const express = require('express');
const app = express();
app.listen('4000', ()=> console.log("listening at 4000"))
node server.js : Outputs Listening at 4000
Install graphQL
npm install express express-graphql graphql --save
Update server.js
var express = require("express")
var { graphqlHTTP } = require("express-graphql")
var { buildSchema } = require("graphql")
const schema = buildSchema(`
type Query {
posts: String
}
`)
var app = express()
app.use(
"/graphql",
graphqlHTTP({
schema: schema,
graphiql: true,
})
)
app.listen(4000)
console.log("Running a GraphQL API server at http://localhost:4000/graphql")
For now we can have “posts” as our schema. There is no data yet so we cannot make any queries
“rootValue” needs to be updated for the value of the /posts response. We will hardcode some values for now
var express = require("express")
var { graphqlHTTP } = require("express-graphql")
var { buildSchema } = require("graphql")
const schema = buildSchema(`
type Query {
posts: String
}
`)
const value = {
posts: () => {
return "Loreum Impusm"
}
}
var app = express()
app.use(
"/graphql",
graphqlHTTP({
schema: schema,
rootValue: value,
graphiql: true,
})
)
app.listen(4000)
console.log("Running a GraphQL API server at http://localhost:4000/graphql")
O/p:
Types
Posts cannot be String! Let us make it as an Array of Strings
So instead of String, we update it to [String]
By default, every type is nullable - it's legitimate to return null as any of the scalar types. Use an exclamation point to indicate a type cannot be nullable, so String! is a non-nullable string.
Ex: userID: Int!
To have an even more complex types, we can have “types” just like how we already have “Query” type previously
const schema = buildSchema(`
type Comment {
body: String
}
type Query {
posts: String,
comments: [Comment]
}
`)
const value = {
posts: () => {
return "Loreum Impusm"
},
comments: () => {
return [{body: "MongoDB"}, {body: "Express"}, {body: "GraphQL"}, {body: "Fancy Tech Stack!"}]
}
}
Update the query to request “body” key inside comments
Updating the types and hardcoded data to match real time scenario:
const schema = buildSchema(`
type Comment {
id: Int!,
postId: Int!,
body: String,
}
type Post {
userId: Int!,
id: Int!,
title: String,
body: String
}
type Query {
posts: [Post],
comments: [Comment]
}
`)
const value = {
posts: () => {
return [{
userId: 1,
id: 9,
title: "nesciunt iure omnis dolorem tempora et accusantium",
body: "consectetur animi nesciunt iure dolore\nenim quia ad\nveniam autem ut quam aut nobis\net est aut quod aut provident voluptas autem voluptas"
},
{
userId: 1,
id: 10,
title: "optio molestias id quia eum",
body: "quo et expedita modi cum officia vel magni\ndoloribus qui repudiandae\nvero nisi sit\nquos veniam quod sed accusamus veritatis error"
}]
},
comments: () => {
return [
{body: "MongoDB", postId: 1},
{body: "Express", postId: 1},
{body: "GraphQL", postId: 2},
{body: "Fancy Tech Stack!", postId: 3}
]
}
}
Now update the Query accordingly:
PASSING THE ARGUMENTS
So far, the resolver functions took no arguments/queries
Scenario: Get “comments” with postId sent as argument/query
type Query {
posts: [Post],
comments(postId: Int!): [Comment]
}
We can access the “postId” in the rootValue by using “args” property. Ex: args.postId in this case.
OR
Using Object Destructuring in ES6, we can use { postId }
comments: ({postId}) => {
let posts = [
{body: "MongoDB", postId: 1},
{body: "Express", postId: 1},
{body: "GraphQL", postId: 2},
{body: "Fancy Tech Stack!", postId: 3}
]
return posts.filter(p => p.postId === postId)
}
OBJECT TYPES
type Comment {
id: Int!,
postId: Int!,
body: String,
}
type Query {
posts: [Post],
comments(postId: Int!): [Comment]
}
Instead of a root-level resolver for the [Comment] type, we can instead use an ES6 class, where the resolvers are instance methods.
Comments
Post a Comment