Created
October 19, 2016 06:26
-
-
Save trongthanh/f291f81002976cface6103c89e84aeff to your computer and use it in GitHub Desktop.
Intro to GraphQL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Client-side GraphQL data fetch example with HTML5 Fetch API | |
* | |
* @param {String} url URL to the GraphQL endpoint | |
* @param {String} query The GraphQL query | |
* @return {Promise} the request resolving promise object | |
*/ | |
function fetchData(url = 'http://localhost:3000/graphql', query = '{ hello }') { //eslint-disable-line no-unused-vars | |
let requiredHeaders = new Headers({ | |
'Content-Type': 'application/json', | |
'Accept': 'application/json', | |
}); | |
let req = new Request(url, { | |
method: 'POST', | |
headers: requiredHeaders, | |
body: JSON.stringify({ query }), // TODO: add 'variables' to the body | |
}); | |
return fetch(req).then(response => { | |
console.log('response.status:', response.status); | |
if (response.ok) { | |
return response.json(); // result will be JSON object | |
} else { | |
return response.json(); // Even response is 4**, we still receive json object describe error | |
} | |
}).catch(err => { | |
console.log('Errors:', err); | |
return err; | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "graphql-demo", | |
"version": "1.0.0", | |
"description": "Hellow World", | |
"main": "index.js", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"author": "Thanh Tran <[email protected]> (http://int3ractive.com)", | |
"license": "ISC", | |
"dependencies": { | |
"@risingstack/graffiti": "^3.2.0", | |
"@risingstack/graffiti-mongoose": "^5.3.0", | |
"body-parser": "^1.15.2", | |
"express": "^4.14.0", | |
"express-graphql": "^0.5.4", | |
"graphql": "^0.7.1", | |
"mongoose": "^4.6.4", | |
"react": "^15.3.2", | |
"react-dom": "^15.3.2" | |
}, | |
"devDependencies": { | |
"webpack": "^1.13.2" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Step 1: Start simple GraphQL logic running inside NodeJS | |
*/ | |
var graphql = require('graphql').graphql; | |
var buildSchema = require('graphql').buildSchema; | |
// Construct a schema, using GraphQL schema language | |
/* eslint no-multi-str:0 */ | |
var schema = buildSchema('\ | |
type Query {\ | |
hello: String\ | |
}\ | |
'); | |
// The root provides a resolver function for each API endpoint | |
var root = { | |
hello: function() { | |
return 'Hello world!'; | |
}, | |
}; | |
// Run the GraphQL query '{ hello }' and print out the response | |
graphql(schema, '{ hello }', root).then(function(response) { | |
console.log(response); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Step 10: Nested objects | |
* | |
* Note #1: Mongoose queries are not real Promise, should run exec() at the end of the query | |
*/ | |
const express = require('express'); | |
const graphqlHTTP = require('express-graphql'); | |
const { buildSchema } = require('graphql'); | |
const mongoose = require('mongoose'); | |
mongoose.Promise = global.Promise; //use native Promise for mongoose as per http://mongoosejs.com/docs/promises.html | |
mongoose.connect('mongodb://localhost/graphql'); | |
const Post = mongoose.model('post', { | |
id: mongoose.Schema.Types.ObjectId, | |
timestamp: Date, | |
content: String, | |
author: { type: mongoose.Schema.Types.ObjectId, ref: 'author' }, // --> reference to Author collection | |
}); | |
const Author = mongoose.model('author', { | |
id: mongoose.Schema.Types.ObjectId, | |
firstName: String, | |
lastName: String, | |
email: String, | |
}); | |
// Construct a schema, using GraphQL schema language | |
const schema = buildSchema(` | |
type Post { | |
id: ID!, | |
content: String!, | |
timestamp: String, | |
author: Author, | |
} | |
type Author { | |
_id: ID!, | |
firstName: String!, | |
lastName: String, | |
email: String, | |
} | |
type Query { | |
post(id: ID!): Post, | |
posts: [Post], | |
author(id: ID!): Author, | |
authors: [Author], | |
} | |
input AuthorInput { | |
firstName: String!, | |
lastName: String, | |
email: String, | |
} | |
input PostInput { | |
author: ID!, | |
content: String!, | |
} | |
type Mutation { | |
createPost(input: PostInput): Post, | |
createAuthor(input: AuthorInput): Author, | |
} | |
`); | |
// The root provides a resolver function for each API endpoint | |
const root = { | |
author({id}) { | |
return Author.findOne({_id: id}).exec(); | |
}, | |
authors() { | |
return Author.find({}).exec(); | |
}, | |
createAuthor({input}) { | |
let author = new Author(input); | |
return author.save().exec(); | |
}, | |
post({id}) { | |
return Post.findOne({id: id}).populate('author').exec(); | |
}, | |
posts() { | |
return Post.find({}).populate('author').exec(); | |
}, | |
createPost({input}) { | |
let newPost = new Post(input); | |
// we can do some field remapping if needed: | |
// new Post({ by: input.author, body: input.content }) | |
console.log('newPost', newPost); | |
// map id prop to built-in mongodb _id | |
newPost.id = newPost._id; | |
newPost.timestamp = Date.now(); | |
return newPost.save().then((post) => { | |
// the returned post is raw object, we'll wrap it in Post model again | |
// and do the population for author | |
return new Post(post).populate('author').execPopulate(); | |
}); | |
} | |
}; | |
let app = express(); | |
app.use('/graphql', graphqlHTTP({ | |
schema, | |
rootValue: root, | |
graphiql: true, // enable graphiql's query previewer | |
})); | |
app.listen(3000); | |
console.log('Running a GraphQL API server at localhost:3000/graphql'); | |
/* | |
Query to try in GraphiQL: | |
#1. Create authors | |
mutation { | |
createAuthor(input: { | |
id: "hl", | |
firstName: "Hiếu", | |
lastName: "Lê", | |
email: "[email protected]" | |
}) { | |
id | |
} | |
} | |
mutation { | |
createAuthor(input: { | |
id: "ld", | |
firstName: "Long", | |
lastName: "Đỗ", | |
email: "[email protected]" | |
}) { | |
id | |
} | |
} | |
#2. Create post | |
mutation { | |
createPost(input: { | |
author: "58049c54f754033ed8150c0e", | |
content:"Tháng tư là lời nói dối của anh" | |
}) { | |
id, | |
author { | |
firstName | |
} | |
} | |
} | |
#3. Get author | |
{ | |
author(id: "hl") { | |
firstName, | |
lastName, | |
} | |
} | |
#4. Get authors | |
{ | |
authors { | |
firstName, | |
lastName, | |
} | |
} | |
#5. Get posts | |
{ | |
posts { | |
author { | |
id, | |
firstName, | |
lastName | |
}, | |
content | |
} | |
} | |
*/ | |
/*const db = { | |
posts: [{ | |
id: '58049c54f754033ed8150c0e', | |
author: 'Hiếu', | |
content: 'As I went on, still gaining velocity, the palpitation of night and day merged into one continuous greyness; the sky took on a wonderful deepness of blue, a splendid luminous color like that of early twilight; the jerking sun became a streak of fire, a brilliant arch, in space; the moon a fainter fluctuating band; and I could see nothing of the stars, save now and then a brighter circle flickering in the blue.', | |
timestamp: 1476548728731, | |
}, { | |
id: '2', | |
author: 'Long', | |
content: 'A peep at some distant orb has power to raise and purify our thoughts like a strain of sacred music, or a noble picture, or a passage from the grander poets. It always does one good.', | |
timestamp: 1476462317277, | |
}, { | |
id: '3', | |
author: 'Đạt', | |
content: 'Apparently we had reached a great height in the atmosphere, for the sky was a dead black, and the stars had ceased to twinkle. By the same illusion which lifts the horizon of the sea to the level of the spectator on a hillside, the sable cloud beneath was dished out, and the car seemed to float in the middle of an immense dark sphere, whose upper half was strewn with silver.', | |
timestamp: 1473956762837, | |
}] | |
}; | |
"authors": [ | |
{ | |
"_id": "58049c54f754033ed8150c0e", | |
"firstName": "Hiếu" | |
}, | |
{ | |
"_id": "58049c8df754033ed8150c0f", | |
"firstName": "Long" | |
} | |
] | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const express = require('express'); | |
const { json } = require('body-parser'); | |
const graffiti = require('@risingstack/graffiti'); | |
const { getSchema } = require('@risingstack/graffiti-mongoose'); | |
const mongoose = require('mongoose'); | |
mongoose.Promise = global.Promise; //use native Promise for mongoose as per http://mongoosejs.com/docs/promises.html | |
mongoose.connect('mongodb://localhost/graphql'); | |
const Post = mongoose.model('Post', { | |
id: mongoose.Schema.Types.ObjectId, | |
timestamp: Date, | |
content: String, | |
author: { type: mongoose.Schema.Types.ObjectId, ref: 'Author' }, // --> reference to Author collection | |
}); | |
const Author = mongoose.model('Author', { | |
firstName: String, | |
lastName: String, | |
email: String, | |
// TODO: fix this circular dependencies | |
posts: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Post' }] | |
}); | |
const app = express(); | |
// parse body as json | |
app.use(json()); | |
app.use(graffiti.express({ | |
schema: getSchema([Post, Author]), | |
context: {}, // custom context | |
graphiql: true | |
})); | |
app.listen(3000); | |
console.log('Server started and listen at http://localhost:3000'); | |
/* | |
Sample queries | |
{ | |
anh_hieu: author(id: "58049c54f754033ed8150c0e") { | |
firstName, | |
lastName, | |
email, | |
posts { | |
edges() { | |
node { | |
content, | |
timestamp, | |
} | |
} | |
} | |
} | |
} | |
// get all post | |
{ | |
posts { | |
_id, | |
content | |
author { | |
firstName, | |
lastName | |
} | |
} | |
} | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Step 2: Add express and express-graphql to allows previewing with GraphiQL | |
* and test fetching from from browser | |
* | |
* NOTE #1: Use ES6 const & let | |
* NOTE #2: Use ES6 template string | |
* NOTE #3: Use ES6 object method literal | |
*/ | |
const express = require('express'); | |
const graphqlHTTP = require('express-graphql'); | |
const buildSchema = require('graphql').buildSchema; | |
// Construct a schema, using GraphQL schema language | |
const schema = buildSchema(` | |
type Query { | |
hello: String | |
} | |
`); | |
// The root provides a resolver function for each API endpoint | |
const root = { | |
hello() { | |
return 'Hello world!'; | |
} | |
}; | |
let app = express(); | |
app.use('/graphql', graphqlHTTP({ | |
schema, | |
rootValue: root, | |
graphiql: true, // enable graphiql's query previewer | |
})); | |
app.listen(3000); | |
console.log('Running a GraphQL API server at localhost:3000/graphql'); | |
/* | |
Query to try in GraphiQL: | |
``` | |
{ | |
hello | |
} | |
``` | |
Browser's Fetch API demo | |
``` | |
let requiredHeaders = new Headers({ | |
'Content-Type': 'application/json', | |
'Accept': 'application/json', | |
}); | |
let req = new Request(url, { | |
method: 'POST', | |
headers: requiredHeaders, | |
body: JSON.stringify({ query }) | |
}); | |
fetch(req).then(response => { | |
console.log('response.status:', response.status); | |
if (response.ok) { | |
return response.json(); // result will be JSON object | |
} else { | |
return null; // OR null | |
} | |
}).catch(err => { | |
console.log('Errors:', err); | |
return err; | |
}); | |
``` | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Step 3: Implement query parameters, passing arguments to resolver | |
* | |
*/ | |
const express = require('express'); | |
const graphqlHTTP = require('express-graphql'); | |
const buildSchema = require('graphql').buildSchema; | |
// Construct a schema, using GraphQL schema language | |
const schema = buildSchema(` | |
type Query { | |
hello: String, | |
echo(name: String!): String | |
} | |
`); | |
// The root provides a resolver function for each API endpoint | |
const root = { | |
hello() { | |
return 'Hello world!'; | |
}, | |
echo(args) { | |
let name = args.name; | |
return `Hello ${name.toUpperCase()}. Greetings from GraphQL Server. Ahihi.`; | |
} | |
}; | |
let app = express(); | |
app.use('/graphql', graphqlHTTP({ | |
schema, | |
rootValue: root, | |
graphiql: true, // enable graphiql's query previewer | |
})); | |
app.listen(3000); | |
console.log('Running a GraphQL API server at localhost:3000/graphql'); | |
/* | |
Query to try in GraphiQL: | |
``` | |
{ | |
echo(name: 'Thanh') | |
} | |
``` | |
Browser's Fetch API demo | |
``` | |
// First declare the function fetchData() as in fetch-data.js | |
fatchData('http://localhost:3000/graphql', `{ | |
echo(name: "Hiếu") | |
}`).then(json => { | |
console.log('Response:', JSON.stringify(json)); | |
}); | |
``` | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Step 4: Adding placeholders to query, leaving query as literal string | |
* | |
* Note #1: Only changed the destructuring assignment here | |
*/ | |
const express = require('express'); | |
const graphqlHTTP = require('express-graphql'); | |
const { buildSchema } = require('graphql'); | |
// Construct a schema, using GraphQL schema language | |
const schema = buildSchema(` | |
type Query { | |
hello: String, | |
echo(name: String!): String | |
} | |
`); | |
// The root provides a resolver function for each API endpoint | |
const root = { | |
hello() { | |
return 'Hello world!'; | |
}, | |
echo({ name }) { | |
return `Hello ${name.toUpperCase()}. Greetings from GraphQL Server. Ahihi`; | |
} | |
}; | |
let app = express(); | |
app.use('/graphql', graphqlHTTP({ | |
schema, | |
rootValue: root, | |
graphiql: true, // enable graphiql's query previewer | |
})); | |
app.listen(3000); | |
console.log('Running a GraphQL API server at localhost:3000/graphql'); | |
/* | |
Query to try in GraphiQL: | |
``` | |
query Echo(name: String) { | |
echo(name: $name) | |
} | |
``` | |
Browser's Fetch API demo | |
``` | |
// First declare the function fetchData() as in fetch-data.js | |
fatchData('http://localhost:3000/graphql', ` | |
query Echo($name: String!) { | |
echo(name: $name) | |
}`, { | |
name: 'Hiếu' | |
}) | |
.then(json => { | |
console.log('Response:', JSON.stringify(json)); | |
}); | |
``` | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Step 5: Introduce GraphQL scala types: String, Int, Float, Boolean, ID | |
* List indicated with [] | |
* | |
*/ | |
const express = require('express'); | |
const graphqlHTTP = require('express-graphql'); | |
const { buildSchema } = require('graphql'); | |
// Construct a schema, using GraphQL schema language | |
const schema = buildSchema(` | |
type Query { | |
hello: String!, | |
echo(name: String!): String!, | |
random: Float!, | |
randomRange(fromInt: Int!, toInt: Int!): Int!, | |
areYouGay: Boolean!, | |
names: [String]! | |
} | |
`); | |
// The root provides a resolver function for each API endpoint | |
const root = { | |
hello() { | |
return 'Hello world!'; | |
}, | |
echo({ name }) { | |
return `Hello ${name.toUpperCase()}. Greetings from GraphQL Server. Ahihi`; | |
}, | |
random() { | |
return Math.random(); | |
}, | |
randomRange({fromInt, toInt}) { | |
return fromInt + Math.floor(Math.random() * (toInt - fromInt + 1)); | |
}, | |
areYouGay() { | |
return Math.random() < 0.5; | |
}, | |
names() { | |
return ['Hiếu', 'Quân', 'Khoa', 'Đạt']; | |
} | |
}; | |
let app = express(); | |
app.use('/graphql', graphqlHTTP({ | |
schema, | |
rootValue: root, | |
graphiql: true, // enable graphiql's query previewer | |
})); | |
app.listen(3000); | |
console.log('Running a GraphQL API server at localhost:3000/graphql'); | |
/* | |
Query to try in GraphiQL: | |
``` | |
{ | |
areYouGay, | |
random, | |
randomRange(fromInt: 1, toInt: 6), | |
names, | |
} | |
``` | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Step 6: Introduce custom types | |
* | |
* Note #1: Only scalar field at custom types | |
* Note #2: Custom type can be implemented as ES6 class / custom object in ES5 | |
*/ | |
const express = require('express'); | |
const graphqlHTTP = require('express-graphql'); | |
const { buildSchema } = require('graphql'); | |
// Construct a schema, using GraphQL schema language | |
const schema = buildSchema(` | |
type Post { | |
author: String!, | |
content: String!, | |
timestamp: Float, | |
} | |
type Query { | |
getPosts(limit: Int): [Post] | |
} | |
`); | |
const db = { | |
posts: [{ | |
author: 'Hiếu', | |
content: 'As I went on, still gaining velocity, the palpitation of night and day merged into one continuous greyness; the sky took on a wonderful deepness of blue, a splendid luminous color like that of early twilight; the jerking sun became a streak of fire, a brilliant arch, in space; the moon a fainter fluctuating band; and I could see nothing of the stars, save now and then a brighter circle flickering in the blue.', | |
timestamp: 1476548728731, | |
}, { | |
author: 'Long', | |
content: 'A peep at some distant orb has power to raise and purify our thoughts like a strain of sacred music, or a noble picture, or a passage from the grander poets. It always does one good.', | |
timestamp: 1476462317277, | |
}, { | |
author: 'Đạt', | |
content: 'Apparently we had reached a great height in the atmosphere, for the sky was a dead black, and the stars had ceased to twinkle. By the same illusion which lifts the horizon of the sea to the level of the spectator on a hillside, the sable cloud beneath was dished out, and the car seemed to float in the middle of an immense dark sphere, whose upper half was strewn with silver.', | |
timestamp: 1473956762837, | |
}, { | |
author: 'Khoa', | |
content: 'As the minuteness of the parts formed a great hindrance to my speed, I resolved, contrary to my first intention, to make the being of a gigantic stature; that is to say, about eight feet in height, and proportionably large. After having formed this determination, and having spent some months in successfully collecting and arranging my materials, I began.', | |
timestamp: 1476549446134, | |
}] | |
}; | |
// The root provides a resolver function for each API endpoint | |
const root = { | |
getPosts({ limit }) { | |
if (limit != null) { | |
return db.posts.slice(0, limit); | |
} else { | |
return db.posts; | |
} | |
} | |
}; | |
let app = express(); | |
app.use('/graphql', graphqlHTTP({ | |
schema, | |
rootValue: root, | |
graphiql: true, // enable graphiql's query previewer | |
})); | |
app.listen(3000); | |
console.log('Running a GraphQL API server at localhost:3000/graphql'); | |
/* | |
Query to try in GraphiQL: | |
``` | |
{ | |
getPosts(limit: 3) { | |
author, | |
content | |
} | |
} | |
``` | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Step 7: Mutation and inputs | |
* | |
* NOTE #1: Although we can use query to pass stored data, | |
* we should use Mutation for clarification | |
*/ | |
const express = require('express'); | |
const graphqlHTTP = require('express-graphql'); | |
const { buildSchema } = require('graphql'); | |
// Construct a schema, using GraphQL schema language | |
const schema = buildSchema(` | |
input PostInput { | |
author: String!, | |
content: String!, | |
} | |
type Post { | |
id: ID!, | |
author: String!, | |
content: String!, | |
timestamp: Float, | |
} | |
type Query { | |
getPosts(limit: Int): [Post] | |
} | |
type Mutation { | |
createPost(input: PostInput): Post | |
} | |
`); | |
class Post { | |
constructor({content, author}) { | |
this.id = db.posts.length; | |
this.content = content; | |
this.author = author; | |
this.timestamp = Date.now(); | |
} | |
} | |
const db = { | |
posts: [{ | |
id: '1', | |
author: 'Hiếu', | |
content: 'As I went on, still gaining velocity, the palpitation of night and day merged into one continuous greyness; the sky took on a wonderful deepness of blue, a splendid luminous color like that of early twilight; the jerking sun became a streak of fire, a brilliant arch, in space; the moon a fainter fluctuating band; and I could see nothing of the stars, save now and then a brighter circle flickering in the blue.', | |
timestamp: 1476548728731, | |
}, { | |
id: '2', | |
author: 'Long', | |
content: 'A peep at some distant orb has power to raise and purify our thoughts like a strain of sacred music, or a noble picture, or a passage from the grander poets. It always does one good.', | |
timestamp: 1476462317277, | |
}, { | |
id: '3', | |
author: 'Đạt', | |
content: 'Apparently we had reached a great height in the atmosphere, for the sky was a dead black, and the stars had ceased to twinkle. By the same illusion which lifts the horizon of the sea to the level of the spectator on a hillside, the sable cloud beneath was dished out, and the car seemed to float in the middle of an immense dark sphere, whose upper half was strewn with silver.', | |
timestamp: 1473956762837, | |
}] | |
}; | |
// The root provides a resolver function for each API endpoint | |
const root = { | |
// #1 | |
createPost({input}) { | |
let newPost = new Post(input); | |
db.posts.push(newPost); | |
return newPost; | |
}, | |
// #2 | |
getPosts({ limit }) { | |
return new Promise((resolve/*, reject*/) => { | |
let result; | |
if (limit != null) { | |
result = db.posts.slice(0, limit); | |
} else { | |
result = db.posts; | |
} | |
setTimeout(() => { | |
resolve(result); | |
}, 200); | |
}); | |
}, | |
}; | |
let app = express(); | |
app.use('/graphql', graphqlHTTP({ | |
schema, | |
rootValue: root, | |
graphiql: true, // enable graphiql's query previewer | |
})); | |
app.listen(3000); | |
console.log('Running a GraphQL API server at localhost:3000/graphql'); | |
/* | |
Query to try in GraphiQL: | |
#1. Without variables | |
``` | |
mutation { | |
createPost(input: { | |
author: "Thanh", | |
content: "Hắn vừa đi vừa chửi. Bao giờ cũng thế, cứ rượu xong là hắn chửi. Bắt đầu hắn chửi trời. Có hề gì? Trời có của riêng nhà nào? Rồi hắn chửi đời. Thế cũng chẳng sao: đời là tất cả nhưng chẳng là ai. Tức mình, hắn chửi ngay tất cả làng Vũ Đại. Nhưng cả làng Vũ Đại ai cũng nhủ: “Chắc nó trừ mình ra!”." | |
}) { | |
id, | |
author | |
} | |
} | |
``` | |
#2. With variables | |
mutation CreatePost($input: PostInput!) { | |
createPost(input: $input) { | |
id, | |
author | |
} | |
} | |
"variables": { | |
"input": { | |
"author": "Huy", | |
"content": "Hello Graph QL. Ahihi" | |
} | |
} | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Step 8: Async resolver; express middleware | |
* | |
* #1: 1.1 Request param; 1.2 Middleware | |
* #2: Async resolver with Promise | |
*/ | |
const express = require('express'); | |
const graphqlHTTP = require('express-graphql'); | |
const { buildSchema } = require('graphql'); | |
// Construct a schema, using GraphQL schema language | |
const schema = buildSchema(` | |
type Post { | |
id: ID!, | |
author: String!, | |
content: String!, | |
timestamp: Float, | |
} | |
type Query { | |
lang: String!, | |
getPosts(limit: Int): [Post], | |
} | |
`); | |
function languageMiddleware(req, res, next) { | |
var lang = req.query.lang; | |
if (!lang) { | |
console.log('No lang defined. Using default lang'); | |
req.query.lang = 'vi'; | |
} | |
next(); | |
} | |
const db = { | |
posts: [{ | |
id: '1', | |
author: 'Hiếu', | |
content: 'As I went on, still gaining velocity, the palpitation of night and day merged into one continuous greyness; the sky took on a wonderful deepness of blue, a splendid luminous color like that of early twilight; the jerking sun became a streak of fire, a brilliant arch, in space; the moon a fainter fluctuating band; and I could see nothing of the stars, save now and then a brighter circle flickering in the blue.', | |
timestamp: 1476548728731, | |
}, { | |
id: '2', | |
author: 'Long', | |
content: 'A peep at some distant orb has power to raise and purify our thoughts like a strain of sacred music, or a noble picture, or a passage from the grander poets. It always does one good.', | |
timestamp: 1476462317277, | |
}, { | |
id: '3', | |
author: 'Đạt', | |
content: 'Apparently we had reached a great height in the atmosphere, for the sky was a dead black, and the stars had ceased to twinkle. By the same illusion which lifts the horizon of the sea to the level of the spectator on a hillside, the sable cloud beneath was dished out, and the car seemed to float in the middle of an immense dark sphere, whose upper half was strewn with silver.', | |
timestamp: 1473956762837, | |
}] | |
}; | |
// fake async function | |
function asyncGetPost(limit) { | |
if (limit != null) { | |
return db.posts.slice(0, limit); | |
} else { | |
return db.posts; | |
} | |
} | |
// The root provides a resolver function for each API endpoint | |
const root = { | |
// #1: The request param in resolver | |
lang(args, request) { | |
return request.query.lang; | |
}, | |
// #2: Async demo | |
getPosts({ limit }) { | |
//* | |
return asyncGetPost(limit); | |
/*/ | |
return new Promise((resolve) => { | |
setTimeout(() => { | |
resolve(asyncGetPost(limit)); | |
}, 200); | |
}); | |
//*/ | |
}, | |
}; | |
let app = express(); | |
app.use(languageMiddleware); | |
app.use('/graphql', graphqlHTTP({ | |
schema, | |
rootValue: root, | |
graphiql: true, // enable graphiql's query previewer | |
})); | |
app.listen(3000); | |
console.log('Running a GraphQL API server at localhost:3000/graphql'); | |
/* | |
Query to try in GraphiQL: | |
#1. middleware request | |
``` | |
{ | |
lang | |
} | |
``` | |
#2. async resolver | |
``` | |
{ | |
getPosts { | |
id, | |
author | |
} | |
} | |
``` | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Step 9: Async resolver and MongoDB operations | |
* | |
* Note #1: Compare Mongoose's Date type with GraphQL's (must use String) | |
*/ | |
const express = require('express'); | |
const graphqlHTTP = require('express-graphql'); | |
const { buildSchema } = require('graphql'); | |
const mongoose = require('mongoose'); | |
mongoose.Promise = global.Promise; //use native Promise for mongoose as per http://mongoosejs.com/docs/promises.html | |
mongoose.connect('mongodb://localhost/graphql'); | |
const Post = mongoose.model('Post', { | |
id: mongoose.Schema.Types.ObjectId, | |
timestamp: Date, | |
content: String, | |
author: String, | |
}); | |
// Construct a schema, using GraphQL schema language | |
const schema = buildSchema(` | |
input PostInput { | |
author: String!, | |
content: String!, | |
} | |
type Post { | |
id: ID!, | |
author: String!, | |
content: String!, | |
timestamp: String, | |
} | |
type Query { | |
getPosts: [Post] | |
} | |
type Mutation { | |
createPost(input: PostInput): Post | |
} | |
`); | |
// The root provides a resolver function for each API endpoint | |
const root = { | |
getPosts() { | |
return Post.find({}); | |
}, | |
createPost({input}) { | |
let newPost = new Post(input); | |
// we can do some field remapping if needed: | |
// new Post({ by: input.author, body: input.content }) | |
// map id prop to built-in mongodb _id | |
newPost.id = newPost._id; | |
newPost.timestamp = Date.now(); | |
return newPost.save(); | |
} | |
}; | |
let app = express(); | |
app.use('/graphql', graphqlHTTP({ | |
schema, | |
rootValue: root, | |
graphiql: true, // enable graphiql's query previewer | |
})); | |
app.listen(3000); | |
console.log('Running a GraphQL API server at localhost:3000/graphql'); | |
/* | |
Query to try in GraphiQL: | |
#1. Create new post | |
``` | |
mutation { | |
createPost(input: { | |
author: "Thanh", | |
content: "Hắn vừa đi vừa chửi. Bao giờ cũng thế, cứ rượu xong là hắn chửi. Bắt đầu hắn chửi trời. Có hề gì? Trời có của riêng nhà nào? Rồi hắn chửi đời. Thế cũng chẳng sao: đời là tất cả nhưng chẳng là ai. Tức mình, hắn chửi ngay tất cả làng Vũ Đại. Nhưng cả làng Vũ Đại ai cũng nhủ: “Chắc nó trừ mình ra!”." | |
}) { | |
id, | |
author | |
} | |
} | |
``` | |
#2. Get posts | |
``` | |
{ | |
getPosts { | |
id, | |
author, | |
} | |
} | |
``` | |
*/ | |
/*const db = { | |
posts: [{ | |
id: '1', | |
author: 'Hiếu', | |
content: 'As I went on, still gaining velocity, the palpitation of night and day merged into one continuous greyness; the sky took on a wonderful deepness of blue, a splendid luminous color like that of early twilight; the jerking sun became a streak of fire, a brilliant arch, in space; the moon a fainter fluctuating band; and I could see nothing of the stars, save now and then a brighter circle flickering in the blue.', | |
timestamp: 1476548728731, | |
}, { | |
id: '2', | |
author: 'Long', | |
content: 'A peep at some distant orb has power to raise and purify our thoughts like a strain of sacred music, or a noble picture, or a passage from the grander poets. It always does one good.', | |
timestamp: 1476462317277, | |
}, { | |
id: '3', | |
author: 'Đạt', | |
content: 'Apparently we had reached a great height in the atmosphere, for the sky was a dead black, and the stars had ceased to twinkle. By the same illusion which lifts the horizon of the sea to the level of the spectator on a hillside, the sable cloud beneath was dished out, and the car seemed to float in the middle of an immense dark sphere, whose upper half was strewn with silver.', | |
timestamp: 1473956762837, | |
}] | |
};*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment