Schemas, Mutations, DB Store, and data-loader
const {
GraphQLSchema // class to create instance of Schema
} = require('graphql');
const mySchema = new GraphQLSchema({
query: queryType
});
module.exports = mySchema;
const {
GraphQLSchema // class to create instance of Schema
, GraphQLObjectType
, GraphQLString
} = require('graphql');
const queryType = new GraphQLObjectType({
name: 'RootQuery',
fields: {
hello: {
type: GraphQLString,
resolve: () => "World"
}
}
});
// function, the actual executor of the schema
const { graphql } = require('graphql');
// the schema to execute
const mySchema = require('./schema');
// get query from cli arguments
const query = process.argv[2];
// execute mySchema against a query
graphql(mySchema, query);
// execute mySchema against a query
// async operation, returns a promise
graphql(mySchema, query)
.then(console.log); // print results
$ node . '{ hello }'
let counter = 42;
...
counter: {
type: GraphQLInt,
resolve: () => counter
}
$ node . '{ counter }'
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => res.send('hello world'));
app.listen(PORT);
app.get('/graphql', (req,res) => {
const { query } = req.query;
// execute mySchema against a query
// async operation, returns a promise
graphql(mySchema, query)
.then(result => res.json(result));
});
http://localhost:3000/graphql?query={hello,counter}
$ curl localhost:3000/graphql\?query=%7Bhello%2Ccounter%7D
app.use('/graphql', graphqlHTTP({
schema: mySchema
}));
http://localhost:3000/graphql?query={hello,counter}
$ curl localhost:3000/graphql\?query=%7Bhello%2Ccounter%7D
graphiql: true
in the wrong place
counter++
name: RootMutation
fields: incrementCounter
type: GraphQLInt
resolve: ++counter
add mutationType to mySchema
const mutationType = new GraphQLObjectType({
name: 'RootMutation',
fields: {
incrementCounter: {
type: GraphQLInt,
resolve: () => ++counter
}
}
});
const mySchema = new GraphQLSchema({
query: queryType,
mutation: mutationType
});
type: new GraphQLList(GraphQLInt)
resolve: counters
create a counters array variable
let counters = [42, 43];
...
counters: {
type: new GraphQLList(GraphQLInt),
resolve: () => counters
}
name: CounterObj
fields
id
type: GraphQLID
value
type: GraphQLInt
Add counterObj field to queryType
Add countersObj field to queryType
let counterObj = {
id: 55,
value: 42
};
let countersObj = [
{ id: 550, value: 43 },
{ id: 551, value: 44 }
];
...
const CounterObjType = new GraphQLObjectType({
name: 'CounterObj',
fields: {
id: { type: GraphQLID },
value: { type: GraphQLInt }
}
});
...
counterObj: {
type: CounterObjType,
resolve: () => counterObj
},
countersObj: {
type: new GraphQLList(CounterObjType),
resolve: () => countersObj
}
fields
id
first_name
last_name
spouse_id
queryType has one field, person
resolve to new temp person variable
const person = {
id: 1,
first_name: 'Jon',
last_name: 'Borgonia',
email: 'jon.borgonia@gmail.com',
spouse_id: 2
};
const PersonType = new GraphQLObjectType({
name: 'Person',
fields: {
id: { type: GraphQLID },
first_name: { type: GraphQLString },
last_name: { type: GraphQLString },
email: { type: GraphQLString },
spouse_id: { type: GraphQLInt }
}
});
const queryType = new GraphQLObjectType({
name: 'RootQuery',
fields: {
person: {
type: PersonType,
resolve: () => person
}
}
});
The bad way
fields: {
id: { type: GraphQLID },
firstName: {
type: GraphQLString,
// 4th arg is the execution env --v
resolve: ( obj, {}, {}, { fieldName } ) => obj[fieldName]
},
lastName: {
type: GraphQLString,
resolve: obj => obj.last_name
},
email: { type: GraphQLString },
spouseId: { type: GraphQLInt }
}
const person = humps.camelizeKeys({
...
fields: {
id: { type: GraphQLID },
firstName: { type: GraphQLString },
lastName: { type: GraphQLString },
email: { type: GraphQLString },
spouseId: { type: GraphQLInt }
}
require the pg module
create a new postgres connection pool
const pool = new pg.Pool({
database: 'graphql_server_db',
user: 'postgres'
});
create a database named people
add about 10 rows, each married to another row
context: { pool }
fields: {
person: {
type: PersonType,
// 3rd is context ------v
resolve: ( obj, args, { pool }, info ) => pool.query(`
select * from people
where id = 1
`).then(result => humps.camelizeKeys(result.rows[0]))
}
}
fields: {
person: {
type: PersonType,
args: {
id: {
type: new GraphQLNonNull(GraphQLInt)
}
},
resolve: ( obj, args, { pool }, info ) => pool.query(`
select * from people
where id = $1
`, [args.id])
.then(result => humps.camelizeKeys(result.rows[0]))
}
}
fullName: {
type: GraphQLString,
resolve: obj => `${obj.firstName} ${obj.lastName}`
}
spouse: {
type: PersonType,
resolve: ( obj, args, { pool }, info ) => pool.query(`
select * from people
where id = $1
`, [obj.spouseId]).then(result => humps.camelizeKeys(result.rows[0])) }
})
fields: () => ({
...
})
cleaning up
const humps = require('humps');
module.exports = (pool) => ({
getUserById(userId) {
return pool.query(`
select * from people
where id = $1
`, [userId]).then(result => humps.camelizeKeys(result.rows[0]));
}
});
spouse: {
type: PersonType,
resolve: ( obj, args, { pool }, info ) => db(pool).getUserById(obj.spouseId)
}
...
// fields, person
resolve: ( obj, args, { pool }, info ) => db(pool).getUserById(args.id)
people: {
type: new GraphQLList(PersonType),
resolve: ( obj, args, { pool } ) => db(pool).getUsers()
}
getUsers() {
return pool.query(`
select * from people
`).then(result => humps.camelizeKeys(result.rows));
}
"Batching"
*WIP* *WIP* *WIP* *WIP* *WIP* *WIP*