├── .gitignore ├── README.md ├── index.js ├── package.json └── server ├── Pokemon.js ├── mongoService.js ├── schema.js ├── schemaTypes.js └── server.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a very simple Pokedex backend API built with Node, Express, GraphQL, and Babel. 2 | 3 | It's just meant for learning and should be complemented by a series of articles on [http://davidandsuzi.com](http://davidandsuzi.com). 4 | 5 | ### Running 6 | 7 | ``` 8 | npm install 9 | node index 10 | ``` 11 | 12 | ### Dependencies 13 | 14 | A MongoDB instance running locally (```sudo mongod```) is required to run any of the user related queries and mutations (the pokemon root query, which uses in-memory data, works independent of MongoDB). -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('babel/register'); 2 | require('./server/server.js'); 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learning-graphql-with-pokedex", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "dependencies": { 7 | "babel": "^5.8.5", 8 | "body-parser": "^1.13.2", 9 | "express": "^4.13.1", 10 | "graphql": "^0.4.3", 11 | "mongodb": "^2.0.39", 12 | "q": "^1.4.1" 13 | }, 14 | "devDependencies": {}, 15 | "scripts": { 16 | "start": "node index", 17 | "test": "echo \"Error: no test specified\" && exit 1" 18 | }, 19 | "author": "David Chang ", 20 | "license": "ISC" 21 | } 22 | -------------------------------------------------------------------------------- /server/Pokemon.js: -------------------------------------------------------------------------------- 1 | // definitely ripped from https://gist.github.com/MathewReiss/20a58ad5c1bc9a6bc23b#file-phone-js-L9-L163 2 | var grass = "grass", water = "water", fire = "fire", bug = "bug", 3 | psychic = "psychic", flying = "flying", ghost = "ghost", fighting = "fighting", 4 | normal = "normal", poison = "poison", electric = "electric", ground = "ground", 5 | fairy = "fairy", rock = "rock", ice = "ice", dragon = "dragon"; 6 | 7 | export const Pokemon = [ 8 | { name : "Bulbasaur", type : grass, stage : 0, caught : 0, species : "Seed Pokemon"}, 9 | { name : "Ivysaur", type : grass, stage : 3, caught : 0, species : "Seed Pokemon"}, 10 | { name : "Venusaur", type : grass, stage : 5, caught : 0, species : "Seed Pokemon"}, 11 | { name : "Charmander", type : fire, stage : 0, caught : 0, species : "Lizard Pokemon"}, 12 | { name : "Charmeleon", type : fire, stage : 3, caught : 0, species : "Flame Pokemon"}, 13 | { name : "Charizard", type : fire, stage : 5, caught : 0, species : "Flame Pokemon"}, 14 | { name : "Squirtle", type : water, stage : 0, caught : 0, species : "Tiny Turtle Pokemon"}, 15 | { name : "Wartortle", type : water, stage : 3, caught : 0, species : "Turtle Pokemon"}, 16 | { name : "Blastoise", type : water, stage : 5, caught : 0, species : "Shellfish Pokemon"}, 17 | { name : "Caterpie", type : bug, stage : 1, caught : 0, species : "Worm Pokemon"}, 18 | { name : "Metapod", type : bug, stage : 2, caught : 0, species : "Cocoon Pokemon"}, 19 | { name : "Butterfree", type : bug, stage : 4, caught : 0, species : "Butterfly Pokemon"}, 20 | { name : "Weedle", type : bug, stage : 1, caught : 0, species : "Hairy Bug Pokemon"}, 21 | { name : "Kakuna", type : bug, stage : 2, caught : 0, species : "Cocoon Pokemon"}, 22 | { name : "Beedrill", type : bug, stage : 4, caught : 0, species : "Poison Bee Pokemon"}, 23 | { name : "Pidgey", type : flying, stage : 1, caught : 0, species : "Tiny Bird Pokemon"}, 24 | { name : "Pidgeotto", type : flying, stage : 3, caught : 0, species : "Bird Pokemon"}, 25 | { name : "Pidgeot", type : flying, stage : 5, caught : 0, species : "Bird Pokemon"}, 26 | { name : "Rattata", type : normal, stage : 1, caught : 0, species : "Mouse Pokemon"}, 27 | { name : "Raticate", type : normal, stage : 2, caught : 0, species : "Mouse Pokemon"}, 28 | { name : "Spearow", type : flying, stage : 1, caught : 0, species : "Tiny Bird Pokemon"}, 29 | { name : "Fearow", type : flying, stage : 3, caught : 0, species : "Beak Pokemon"}, 30 | { name : "Ekans", type : poison, stage : 1, caught : 0, species : "Snake Pokemon"}, 31 | { name : "Arbok", type : poison, stage : 3, caught : 0, species : "Cobra Pokemon"}, 32 | { name : "Pikachu", type : electric, stage : 1, caught : 0, species : "Mouse Pokemon"}, 33 | { name : "Raichu", type : electric, stage : 3, caught : 0, species : "Mouse Pokemon"}, 34 | { name : "Sandshrew", type : ground, stage : 1, caught : 0, species : "Mouse Pokemon"}, 35 | { name : "Sandslash", type : ground, stage : 2, caught : 0, species : "Mouse Pokemon"}, 36 | { name : "Nidoran F", type : poison, stage : 1, caught : 0, species : "Poison Pin Pokemon"}, 37 | { name : "Nidorina", type : poison, stage : 2, caught : 0, species : "Poison Pin Pokemon"}, 38 | { name : "Nidoqueen", type : poison, stage : 5, caught : 0, species : "Drill Pokemon"}, 39 | { name : "Nidoran M", type : poison, stage : 1, caught : 0, species : "Poison Pin Pokemon"}, 40 | { name : "Nidorino", type : poison, stage : 2, caught : 0, species : "Poison Pin Pokemon"}, 41 | { name : "Nidoking", type : poison, stage : 5, caught : 0, species : "Drill Pokemon"}, 42 | { name : "Clefairy", type : fairy, stage : 1, caught : 0, species : "Fairy Pokemon"}, 43 | { name : "Clefable", type : fairy, stage : 3, caught : 0, species : "Fairy Pokemon"}, 44 | { name : "Vuplix", type : fire, stage : 1, caught : 0, species : "Fox Pokemon"}, 45 | { name : "Ninetales", type : fire, stage : 3, caught : 0, species : "Fox Pokemon"}, 46 | { name : "Jigglypuff", type : fairy, stage : 1, caught : 0, species : "Balloon Pokemon"}, 47 | { name : "Wigglytuff", type : fairy, stage : 3, caught : 0, species : "Balloon Pokemon"}, 48 | { name : "Zubat", type : poison, stage : 1, caught : 0, species : "Bat Pokemon"}, 49 | { name : "Golbat", type : poison, stage : 2, caught : 0, species : "Bat Pokemon"}, 50 | { name : "Oddish", type : grass, stage : 1, caught : 0, species : "Weed Pokemon"}, 51 | { name : "Gloom", type : grass, stage : 2, caught : 0, species : "Weed Pokemon"}, 52 | { name : "Vileplume", type : grass, stage : 3, caught : 0, species : "Flower Pokemon"}, 53 | { name : "Paras", type : bug, stage : 1, caught : 0, species : "Mushroom Pokemon"}, 54 | { name : "Parasect", type : bug, stage : 2, caught : 0, species : "Mushroom Pokemon"}, 55 | { name : "Venonat", type : bug, stage : 1, caught : 0, species : "Insect Pokemon"}, 56 | { name : "Venomoth", type : bug, stage : 2, caught : 0, species : "Poison Moth Pokemon"}, 57 | { name : "Diglett", type : ground, stage : 1, caught : 0, species : "Mole Pokemon"}, 58 | { name : "Dugtrio", type : ground, stage : 2, caught : 0, species : "Mole Pokemon"}, 59 | { name : "Meowth", type : normal, stage : 1, caught : 0, species : "Scratch Cat Pokemon"}, 60 | { name : "Persian", type : normal, stage : 2, caught : 0, species : "Classy Cat Pokemon"}, 61 | { name : "Psyduck", type : water, stage : 1, caught : 0, species : "Duck Pokemon"}, 62 | { name : "Golduck", type : water, stage : 2, caught : 0, species : "Duck Pokemon"}, 63 | { name : "Mankey", type : fighting, stage : 1, caught : 0, species : "Pig Monkey Pokemon"}, 64 | { name : "Primeape", type : fighting, stage : 2, caught : 0, species : "Pig Monkey Pokemon"}, 65 | { name : "Growlithe", type : fire, stage : 1, caught : 0, species : "Puppy Pokemon"}, 66 | { name : "Arcanine", type : fire, stage : 2, caught : 0, species : "Legendary Pokemon"}, 67 | { name : "Poliwag", type : water, stage : 1, caught : 0, species : "Tadpole Pokemon"}, 68 | { name : "Poliwhirl", type : water, stage : 2, caught : 0, species : "Tadpole Pokemon"}, 69 | { name : "Poliwrath", type : water, stage : 5, caught : 0, species : "Tadpole Pokemon"}, 70 | { name : "Abra", type : psychic, stage : 1, caught : 0, species : "Psi Pokemon"}, 71 | { name : "Kadabra", type : psychic, stage : 2, caught : 0, species : "Psi Pokemon"}, 72 | { name : "Alakazam", type : psychic, stage : 5, caught : 0, species : "Psi Pokemon"}, 73 | { name : "Machop", type : fighting, stage : 1, caught : 0, species : "Superpower Pokemon"}, 74 | { name : "Machoke", type : fighting, stage : 2, caught : 0, species : "Superpower Pokemon"}, 75 | { name : "Machamp", type : fighting, stage : 5, caught : 0, species : "Superpower Pokemon"}, 76 | { name : "Bellsprout", type : grass, stage : 1, caught : 0, species : "Flower Pokemon"}, 77 | { name : "Weepinbell", type : grass, stage : 3, caught : 0, species : "Flycatcher Pokemon"}, 78 | { name : "Victreebel", type : grass, stage : 5, caught : 0, species : "Flycatcher Pokemon"}, 79 | { name : "Tentacool", type : water, stage : 1, caught : 0, species : "Jellyfish Pokemon"}, 80 | { name : "Tentacruel", type : water, stage : 3, caught : 0, species : "Jellyfish Pokemon"}, 81 | { name : "Geodude", type : rock, stage : 1, caught : 0, species : "Rock Pokemon"}, 82 | { name : "Graveler", type : rock, stage : 3, caught : 0, species : "Rock Pokemon"}, 83 | { name : "Golem", type : rock, stage : 5, caught : 0, species : "Megaton Pokemon"}, 84 | { name : "Ponyta", type : fire, stage : 2, caught : 0, species : "Fire Horse Pokemon"}, 85 | { name : "Rapidash", type : fire, stage : 3, caught : 0, species : "Fire Horse Pokemon"}, 86 | { name : "Slowpoke", type : water, stage : 2, caught : 0, species : "Dopey Pokemon"}, 87 | { name : "Slowbro", type : water, stage : 3, caught : 0, species : "Hermit Crab Pokemon"}, 88 | { name : "Magnemite", type : electric, stage : 2, caught : 0, species : "Magnet Pokemon"}, 89 | { name : "Magneton", type : electric, stage : 3, caught : 0, species : "Magnet Pokemon"}, 90 | { name : "Farfetch'd", type : flying, stage : 3, caught : 0, species : "Wild Duck Pokemon"}, 91 | { name : "Doduo", type : flying, stage : 2, caught : 0, species : "Twin Bird Pokemon"}, 92 | { name : "Dodrio", type : flying, stage : 4, caught : 0, species : "Triple Bird Pokemon"}, 93 | { name : "Seel", type : water, stage : 3, caught : 0, species : "Sea Lion Pokemon"}, 94 | { name : "Dewgong", type : ice, stage : 5, caught : 0, species : "Sea Lion Pokemon"}, 95 | { name : "Grimer", type : poison, stage : 2, caught : 0, species : "Sludge Pokemon"}, 96 | { name : "Muk", type : poison, stage : 4, caught : 0, species : "Sludge Pokemon"}, 97 | { name : "Shellder", type : water, stage : 2, caught : 0, species : "Bivalve Pokemon"}, 98 | { name : "Cloyster", type : ice, stage : 4, caught : 0, species : "Bivalve Pokemon"}, 99 | { name : "Gastly", type : ghost, stage : 2, caught : 0, species : "Gas Pokemon"}, 100 | { name : "Haunter", type : ghost, stage : 3, caught : 0, species : "Gas Pokemon"}, 101 | { name : "Gengar", type : ghost, stage : 4, caught : 0, species : "Shadow Pokemon"}, 102 | { name : "Onix", type : rock, stage : 3, caught : 0, species : "Rock Snake Pokemon"}, 103 | { name : "Drozee", type : psychic, stage : 1, caught : 0, species : "Hypnosis Pokemon"}, 104 | { name : "Hypno", type : psychic, stage : 3, caught : 0, species : "Hypnosis Pokemon"}, 105 | { name : "Krabby", type : water, stage : 3, caught : 0, species : "River Crab Pokemon"}, 106 | { name : "Kingler", type : water, stage : 4, caught : 0, species : "Pincer Pokemon"}, 107 | { name : "Voltorb", type : electric, stage : 1, caught : 0, species : "Ball Pokemon"}, 108 | { name : "Electrode", type : electric, stage : 3, caught : 0, species : "Ball Pokemon"}, 109 | { name : "Exeggcute", type : grass, stage : 3, caught : 0, species : "Egg Pokemon"}, 110 | { name : "Exeggutor", type : grass, stage : 5, caught : 0, species : "Coconut Pokemon"}, 111 | { name : "Cubone", type : ground, stage : 3, caught : 0, species : "Lonely Pokemon"}, 112 | { name : "Marowak", type : ground, stage : 4, caught : 0, species : "Bone Keeper Pokemon"}, 113 | { name : "Hitmonchan", type : fighting, stage : 5, caught : 0, species : "Kicking Pokemon"}, 114 | { name : "Hitmonlee", type : fighting, stage : 5, caught : 0, species : "Punching Pokemon"}, 115 | { name : "Lickitung", type : normal, stage : 4, caught : 0, species : "Licking Pokemon"}, 116 | { name : "Koffing", type : poison, stage : 2, caught : 0, species : "Poison Gas Pokemon"}, 117 | { name : "Weezing", type : poison, stage : 4, caught : 0, species : "Poison Gas Pokemon"}, 118 | { name : "Rhyhorn", type : rock, stage : 3, caught : 0, species : "Spikes Pokemon"}, 119 | { name : "Rhydon", type : rock, stage : 4, caught : 0, species : "Drill Pokemon"}, 120 | { name : "Chansey", type : normal, stage : 4, caught : 0, species : "Egg Pokemon"}, 121 | { name : "Tangela", type : grass, stage : 4, caught : 0, species : "Vine Pokemon"}, 122 | { name : "Kangaskhan", type : normal, stage : 4, caught : 0, species : "Parent Pokemon"}, 123 | { name : "Horsea", type : water, stage : 1, caught : 0, species : "Dragon Pokemon"}, 124 | { name : "Seadra", type : water, stage : 2, caught : 0, species : "Dragon Pokemon"}, 125 | { name : "Goldeen", type : water, stage : 3, caught : 0, species : "Goldfish Pokemon"}, 126 | { name : "Seaking", type : water, stage : 4, caught : 0, species : "Goldfish Pokemon"}, 127 | { name : "Staryu", type : water, stage : 1, caught : 0, species : "Star Shape Pokemon"}, 128 | { name : "Starmie", type : water, stage : 2, caught : 0, species : "Mysterious Pokemon"}, 129 | { name : "Mr. Mime", type : psychic, stage : 4, caught : 0, species : "Barrier Pokemon"}, 130 | { name : "Scyther", type : bug, stage : 4, caught : 0, species : "Mantis Pokemon"}, 131 | { name : "Jynx", type : psychic, stage : 4, caught : 0, species : "Human Shape Pokemon"}, 132 | { name : "Electabuzz", type : electric, stage : 5, caught : 0, species : "Electric Pokemon"}, 133 | { name : "Magmar", type : fire, stage : 5, caught : 0, species : "Spitfire Pokemon"}, 134 | { name : "Pinsir", type : bug, stage : 5, caught : 0, species : "Stag Beetle Pokemon"}, 135 | { name : "Tauros", type : normal, stage : 4, caught : 0, species : "Wild Bull Pokemon"}, 136 | { name : "Magikarp", type : water, stage : 1, caught : 0, species : "Fish Pokemon"}, 137 | { name : "Gyrados", type : water, stage : 5, caught : 0, species : "Atrocious Pokemon"}, 138 | { name : "Lapras", type : water, stage : 4, caught : 0, species : "Transport Pokemon"}, 139 | { name : "Ditto", type : normal, stage : 4, caught : 0, species : "Transform Pokemon"}, 140 | { name : "Eevee", type : normal, stage : 2, caught : 0, species : "Evolution Pokemon"}, 141 | { name : "Vaporeon", type : water, stage : 4, caught : 0, species : "Bubble Jet Pokemon"}, 142 | { name : "Jolteon", type : electric, stage : 4, caught : 0, species : "Lightning Pokemon"}, 143 | { name : "Flareon", type : fire, stage : 4, caught : 0, species : "Flame Pokemon"}, 144 | { name : "Porygon", type : normal, stage : 5, caught : 0, species : "Virtual Pokemon"}, 145 | { name : "Omanyte", type : water, stage : 4, caught : 0, species : "Spiral Pokemon"}, 146 | { name : "Omastar", type : water, stage : 5, caught : 0, species : "Spiral Pokemon"}, 147 | { name : "Kabuto", type : rock, stage : 4, caught : 0, species : "Shellfish Pokemon"}, 148 | { name : "Kabutops", type : rock, stage : 5, caught : 0, species : "Shellfish Pokemon"}, 149 | { name : "Aerodactyl", type : flying, stage : 5, caught : 0, species : "Fossil Pokemon"}, 150 | { name : "Snorlax", type : normal, stage : 5, caught : 0, species : "Sleeping Pokemon"}, 151 | { name : "Articuno", type : ice, stage : 6, caught : 0, species : "Freeze Pokemon"}, 152 | { name : "Zapdos", type : electric, stage : 6, caught : 0, species : "Electric Pokemon"}, 153 | { name : "Moltres", type : fire, stage : 6, caught : 0, species : "Flame Pokemon"}, 154 | { name : "Dratini", type : dragon, stage : 4, caught : 0, species : "Dragon Pokemon"}, 155 | { name : "Dragonair", type : dragon, stage : 5, caught : 0, species : "Dragon Pokemon"}, 156 | { name : "Dragonite", type : dragon, stage : 6, caught : 0, species : "Dragon Pokemon"}, 157 | { name : "Mewtwo", type : psychic, stage : 6, caught : 0, species : "Genetic Pokemon"}, 158 | { name : "Mew", type : psychic, stage : 7, caught : 0, species : "New Species Pokemon"} 159 | ]; -------------------------------------------------------------------------------- /server/mongoService.js: -------------------------------------------------------------------------------- 1 | let MongoClient = require('mongodb').MongoClient; 2 | let Q = require('q'); 3 | 4 | // Connection URL 5 | const MONGO_URL = 'mongodb://localhost:27017/pokedex'; 6 | 7 | export const mongo = cb => { 8 | 9 | let deferred = Q.defer(); 10 | 11 | // Use connect method to connect to the Server 12 | MongoClient.connect(MONGO_URL, (err, db) => { 13 | if (err) { 14 | return deferred.reject(err); 15 | } 16 | return deferred.resolve(db); 17 | }); 18 | 19 | return deferred.promise; 20 | }; -------------------------------------------------------------------------------- /server/schema.js: -------------------------------------------------------------------------------- 1 | // schema.js 2 | import { 3 | GraphQLObjectType, 4 | GraphQLSchema, 5 | GraphQLNonNull, 6 | GraphQLList, 7 | GraphQLString, 8 | } from 'graphql'; 9 | 10 | import { Pokemon } from './Pokemon'; 11 | import { PokemonType, UserType } from './schemaTypes'; 12 | import { mongo } from './mongoService'; 13 | 14 | let Q = require('q'); 15 | 16 | let schema = new GraphQLSchema({ 17 | query: new GraphQLObjectType({ 18 | name: 'RootQueryType', 19 | fields: { 20 | pokemon: { 21 | type: new GraphQLList(PokemonType), 22 | resolve: () => Pokemon 23 | }, 24 | user: { 25 | type: UserType, 26 | args: { 27 | name: { 28 | description: 'The name of the user', 29 | type: new GraphQLNonNull(GraphQLString) 30 | } 31 | }, 32 | resolve: (root, {name}) => { 33 | 34 | return mongo() 35 | .then(db => { 36 | let deferred = Q.defer(); 37 | 38 | let collection = db.collection('users'); 39 | collection.find({ name }) 40 | .toArray((err, docs) => { 41 | if (err) { 42 | deferred.reject(err); 43 | return; 44 | } 45 | 46 | db.close(); 47 | deferred.resolve(docs.length ? docs[0] : null); 48 | }); 49 | 50 | return deferred.promise; 51 | }); 52 | 53 | } 54 | } 55 | } 56 | }), 57 | 58 | mutation: new GraphQLObjectType({ 59 | name: 'Mutation', 60 | fields: { 61 | upsertUser: { 62 | type: UserType, 63 | args: { 64 | name: { 65 | description: 'The name of the user', 66 | type: new GraphQLNonNull(GraphQLString) 67 | } 68 | }, 69 | resolve: (obj, {name}) => { 70 | 71 | let toCreate = { 72 | name, 73 | caught: [], 74 | created: new Date().valueOf() 75 | }; 76 | 77 | return mongo() 78 | .then(db => { 79 | let deferred = Q.defer(); 80 | 81 | let collection = db.collection('users'); 82 | 83 | // see if the user already exists 84 | collection.find({ name }) 85 | .toArray((err, docs) => { 86 | if (err) { 87 | db.close(); 88 | return deferred.reject(err); 89 | } 90 | 91 | if (docs.length) { 92 | db.close(); 93 | return deferred.resolve(docs[0]); 94 | } 95 | 96 | // insert the user if they do not exist 97 | collection.insert(toCreate, (err, result) => { 98 | db.close(); 99 | 100 | if (err) { 101 | deferred.reject(err); 102 | return; 103 | } 104 | 105 | deferred.resolve(toCreate); 106 | }); 107 | }); 108 | 109 | return deferred.promise; 110 | }); 111 | 112 | } 113 | }, 114 | caughtPokemon: { 115 | type: UserType, 116 | args: { 117 | name: { 118 | description: 'The name of the user', 119 | type: new GraphQLNonNull(GraphQLString) 120 | }, 121 | pokemon: { 122 | description: 'The name of the Pokemon that was caught', 123 | type: new GraphQLNonNull(GraphQLString) 124 | } 125 | }, 126 | resolve: (obj, {name, pokemon}) => { 127 | return mongo() 128 | .then(db => { 129 | let deferred = Q.defer(); 130 | 131 | let collection = db.collection('users'); 132 | 133 | // find the user 134 | collection.find({ name }) 135 | .toArray((err, docs) => { 136 | if (err || !docs.length) { 137 | db.close(); 138 | return deferred.reject(err || 'The user was not found'); 139 | } 140 | 141 | let caught = docs[0].caught; 142 | caught.push(pokemon); 143 | 144 | // update the user with updated caught array 145 | collection.update({ name }, { 146 | $set : { caught } 147 | }, (err, result) => { 148 | if (err) { 149 | db.close(); 150 | return deferred.reject(err); 151 | } 152 | 153 | deferred.resolve({ 154 | name : docs[0].name, 155 | created : docs[0].created, 156 | caught 157 | }); 158 | }); 159 | }); 160 | 161 | return deferred.promise; 162 | }); 163 | } 164 | } 165 | } 166 | }) 167 | }); 168 | 169 | export default schema; 170 | -------------------------------------------------------------------------------- /server/schemaTypes.js: -------------------------------------------------------------------------------- 1 | import { 2 | GraphQLObjectType, 3 | GraphQLInt, 4 | GraphQLList, 5 | GraphQLString, 6 | } from 'graphql'; 7 | 8 | export const PokemonType = new GraphQLObjectType({ 9 | name: 'Pokemon', 10 | description: 'A Pokemon', 11 | fields: () => ({ 12 | name: { 13 | type: GraphQLString, 14 | description: 'The name of the Pokemon.', 15 | }, 16 | type: { 17 | type: GraphQLString, 18 | description: 'The type of the Pokemon.', 19 | }, 20 | stage: { 21 | type: GraphQLInt, 22 | description: 'The level of the Pokemon.', 23 | }, 24 | species: { 25 | type: GraphQLString, 26 | description: 'The species of the Pokemon.', 27 | } 28 | }) 29 | }); 30 | 31 | export const UserType = new GraphQLObjectType({ 32 | name: 'User', 33 | description: 'A User', 34 | fields: () => ({ 35 | name: { 36 | type: GraphQLString, 37 | description: 'The name of the User.', 38 | }, 39 | caught: { 40 | type: new GraphQLList(GraphQLString), 41 | description: 'The Pokemon that have been caught by the User.', 42 | }, 43 | created: { 44 | type: GraphQLInt, 45 | description: 'The creation timestamp of the User.' 46 | } 47 | }) 48 | }); -------------------------------------------------------------------------------- /server/server.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import schema from './schema'; 3 | import { graphql } from 'graphql'; 4 | import bodyParser from 'body-parser'; 5 | 6 | let app = express(); 7 | 8 | // parse POST body as text 9 | app.use(bodyParser.text({ type: 'application/graphql' })); 10 | 11 | app.post('/graphql', (req, res) => { 12 | // execute GraphQL! 13 | graphql(schema, req.body) 14 | .then(result => res.send(result)); 15 | }); 16 | 17 | let server = app.listen( 18 | 3000, 19 | () => console.log(`GraphQL running on port ${server.address().port}`) 20 | ); 21 | --------------------------------------------------------------------------------