├── .gitignore ├── README.md ├── index.js ├── lib └── resolver.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .*.swp 3 | 4 | .DS_Store 5 | *~ 6 | .project 7 | .settings 8 | npm-debug.log 9 | coverage.html 10 | .idea 11 | lib-cov 12 | 13 | node_modules 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GraphQL CouchDB demo proxy 2 | 3 | Prototype for GraphQL & CouchDB 4 | 5 | ## Examples 6 | 7 | ``` 8 | Boot server: 9 | 10 | npm run dev 11 | ``` 12 | 13 | ``` 14 | A Database list with metadata: 15 | 16 | http://localhost:3000/graphql?query={all_dbs{db_name,disk_size,doc_count,doc_del_count}} 17 | 18 | Remove a few properties: 19 | 20 | http://localhost:3000/graphql?query={all_dbs{db_name,doc_del_count}} 21 | 22 | 23 | Database list, just names amd disk_size, limit to 1: 24 | 25 | http://localhost:3000/graphql?query={all_dbs(limit:1){db_name,disk_size}} 26 | 27 | 28 | With animaldb, selecting just ids: 29 | 30 | http://localhost:3000/graphql?query={all_dbs{db_name,disk_size,doc_count,doc_del_count},animaldb{_id}} 31 | 32 | ``` 33 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // Import the required libraries 2 | const graphql = require('graphql') 3 | const graphqlHTTP = require('express-graphql') 4 | const express = require('express') 5 | 6 | const resolver = require('./lib/resolver') 7 | 8 | const dbType = new graphql.GraphQLObjectType({ 9 | name: 'Database', 10 | fields: { 11 | db_name: { type: graphql.GraphQLString }, 12 | _global_changes: { type: graphql.GraphQLString }, 13 | update_seq: { type: graphql.GraphQLString }, 14 | sizes: { 15 | type: new graphql.GraphQLObjectType({ 16 | name: 'sizes', 17 | fields: { 18 | file: { type: graphql.GraphQLInt }, 19 | external: { type: graphql.GraphQLInt }, 20 | active: { type: graphql.GraphQLInt } 21 | } 22 | }) 23 | }, 24 | purge_seq: { type: graphql.GraphQLInt }, 25 | doc_del_count: { type: graphql.GraphQLInt }, 26 | doc_count: { type: graphql.GraphQLInt }, 27 | disk_size: { type: graphql.GraphQLInt }, 28 | disk_format_version: { type: graphql.GraphQLInt }, 29 | data_size: { type: graphql.GraphQLInt }, 30 | compact_running: { type: graphql.GraphQLBoolean }, 31 | instance_start_time: { type: graphql.GraphQLString } 32 | } 33 | }) 34 | 35 | const docType = new graphql.GraphQLObjectType({ 36 | name: 'animaldb', 37 | fields: { 38 | _id: { type: graphql.GraphQLString }, 39 | _rev: { type: graphql.GraphQLString }, 40 | min_weight: { type: graphql.GraphQLFloat }, 41 | max_weight: { type: graphql.GraphQLFloat }, 42 | min_length: { type: graphql.GraphQLFloat }, 43 | max_length: { type: graphql.GraphQLFloat }, 44 | latin_name: { type: graphql.GraphQLString }, 45 | wiki_page: { type: graphql.GraphQLString }, 46 | class: { type: graphql.GraphQLString }, 47 | diet: { type: graphql.GraphQLString } 48 | } 49 | }) 50 | 51 | 52 | const schema = new graphql.GraphQLSchema({ 53 | query: new graphql.GraphQLObjectType({ 54 | name: 'Query', 55 | fields: () => { 56 | return { 57 | 58 | all_dbs: { 59 | args: { limit: { type: graphql.GraphQLInt } }, 60 | type: new graphql.GraphQLList(dbType), 61 | resolve: (_, {limit}) => { 62 | return resolver.fetchAllDbs({limit: limit}) 63 | } 64 | }, 65 | 66 | animaldb: { 67 | type: new graphql.GraphQLList(docType), 68 | resolve: (a, b) => { 69 | return resolver.fetchAnimalDb() 70 | } 71 | } 72 | } 73 | } 74 | }) 75 | }) 76 | 77 | express() 78 | .use('/graphql', graphqlHTTP({ schema: schema, pretty: true })) 79 | .listen(3000) 80 | 81 | console.log('GraphQL server running on http://localhost:3000/graphql') 82 | -------------------------------------------------------------------------------- /lib/resolver.js: -------------------------------------------------------------------------------- 1 | const request = require('request') 2 | const couchUrl = 'http://localhost:5984' 3 | 4 | 5 | function requestGET (url) { 6 | return new Promise((resolve, reject) => { 7 | request({ 8 | uri: url, 9 | json: true 10 | }, (err, res, body) => { 11 | if (err) throw err 12 | 13 | resolve(body) 14 | }) 15 | 16 | }, (err) => { 17 | throw err 18 | }) 19 | } 20 | 21 | exports.getDbInfo = getDbInfo 22 | function getDbInfo (id) { 23 | return new Promise((resolve, reject) => { 24 | id = encodeURIComponent(id) 25 | 26 | request({ 27 | uri: `${couchUrl}/${id}`, 28 | json: true 29 | }, (err, res, body) => { 30 | if (err) throw err 31 | 32 | resolve(body) 33 | }) 34 | }, (err) => { 35 | throw err 36 | }) 37 | } 38 | 39 | exports.getAllDbList = getAllDbList 40 | function getAllDbList ({limit = Infinity, skip = 0}) { 41 | return new Promise((resolve, reject) => { 42 | request({ 43 | uri: `${couchUrl}/_all_dbs?limit=${limit}&skip=${skip}`, 44 | json: true 45 | }, (err, res, body) => { 46 | if (err) throw err 47 | 48 | resolve(body) 49 | }) 50 | }, (err) => { 51 | throw err 52 | }) 53 | } 54 | 55 | exports.fetchAllDbs = fetchAllDbs 56 | function fetchAllDbs ({limit = 9999999999999999, skip = 0}) { 57 | return new Promise((resolve, reject) => { 58 | getAllDbList({limit: limit, skip: skip}) 59 | .then((dbs) => { 60 | console.log(dbs) 61 | const infos = dbs.map((db) => { 62 | return getDbInfo(db) 63 | }) 64 | 65 | return infos 66 | }) 67 | .then((requests) => { 68 | // TODO: handle 403 69 | Promise 70 | .all(requests) 71 | .then((result) => { 72 | resolve(result) 73 | }) 74 | }) 75 | }, (err) => { 76 | console.log(err) 77 | throw err 78 | }) 79 | } 80 | 81 | exports.fetchAnimalDb = fetchAnimalDb 82 | function fetchAnimalDb (limit = 20, skip = 0) { 83 | return new Promise((resolve, reject) => { 84 | const url = `${couchUrl}/animaldb/_all_docs?limit=${limit}&include_docs=true` 85 | 86 | requestGET(url) 87 | .then((r) => { 88 | const res = r.rows.map((raw) => { 89 | return raw.doc 90 | }) 91 | 92 | resolve(res) 93 | }, (err) => { 94 | throw err 95 | }) 96 | }) 97 | } 98 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-demo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "nodemon index.js", 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "lint": "standard", 10 | "lint-fix": "standard --fix" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "dependencies": { 16 | "express": "^4.14.0", 17 | "express-graphql": "^0.5.4", 18 | "graphql": "^0.7.0", 19 | "request": "^2.74.0" 20 | }, 21 | "devDependencies": { 22 | "nodemon": "^1.10.2", 23 | "standard": "^8.0.0" 24 | } 25 | } 26 | --------------------------------------------------------------------------------