├── .editorconfig ├── .eslintrc ├── .gitignore ├── .prettierrc ├── README.md ├── graphiql ├── function.json └── index.js ├── graphql ├── function.json └── index.js ├── host.json ├── ingredient ├── function.json └── index.js ├── package-lock.json ├── package.json ├── recipe ├── function.json └── index.js ├── secrets.example.json └── utils ├── baseUrl.js ├── getNutrients.js ├── nutrientMap.js └── sumNutrients.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "rules": {}, 4 | "env": { 5 | "es6": true, 6 | "commonjs": true 7 | }, 8 | "globals": {} 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | bin 3 | obj 4 | csx 5 | .vs 6 | edge 7 | Publish 8 | 9 | *.user 10 | *.suo 11 | *.cscfg 12 | *.Cache 13 | project.lock.json 14 | 15 | /packages 16 | /TestResults 17 | 18 | /tools/NuGet.exe 19 | /App_Data 20 | /secrets 21 | /data 22 | .secrets 23 | appsettings.json 24 | local.settings.json 25 | .DS_Store 26 | .vscode 27 | node_modules/ 28 | secrets.json 29 | package-lock.json 30 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # One Function to Rule Them All: GraphQL on top of Azure Functions 2 | 3 | This is an experiment of using GraphQL to link together disparate functions for GraphQL endpoint. 4 | 5 | ## API 6 | 7 | There are three functions here: 8 | 9 | * `/ingredient` – This will give you back the nutritional information for all the ingredients in a string in a human-readable format in a JSON structure. 10 | * `/recipe` – This will fetch the top result for a recipe and then provide back to you the nutritional information using the ingredient API. 11 | * `/graphql` – This allows you to query both of the other functions using GraphQL. 12 | * `/graphiql` – This allows you to explore the API via the [GraphiQL] web IDE 13 | 14 | ## Powered By 15 | 16 | The [Nutritionix API][nutritionix] and [Food2Fork API][food2fork]. 17 | 18 | ## Running This Code. 19 | 20 | 1. Install Node 8 (I suggest using nvm) 21 | 1. `npm i -g azure-functions-core-tools@core` 22 | 1. Signup for both the Nutritionix and Food2Fork APIs. Copy `secrets.example.json` to `secrets.json` and add your ids and keys in the file or set these environment variables (Application Settings in Azure): 23 | * `NUTRITIONIX_ID` 24 | * `NUTRITIONIX_KEY` 25 | * `FOOD2FORK_KEY` 26 | 1. `npm run start` 27 | 1. Navigate to the graphiql API explorer at http://localhost:7071/api/graphiql 28 | 29 | ## License 30 | 31 | Apache 2.0. Go nuts. 32 | 33 | [nutritionix]: https://www.nutritionix.com/business/api 34 | [food2fork]: http://food2fork.com/about/api 35 | [graphiql]: https://github.com/graphql/graphiql 36 | -------------------------------------------------------------------------------- /graphiql/function.json: -------------------------------------------------------------------------------- 1 | { 2 | "disabled": false, 3 | "bindings": [ 4 | { 5 | "authLevel": "anonymous", 6 | "type": "httpTrigger", 7 | "direction": "in", 8 | "name": "req" 9 | }, 10 | { 11 | "type": "http", 12 | "direction": "out", 13 | "name": "res" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /graphiql/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(context) { 2 | context.res = {}; 3 | context.res = { 4 | status: 200, 5 | body, 6 | headers: { 7 | "Content-Type": "text/html" 8 | } 9 | }; 10 | 11 | context.done(); 12 | }; 13 | 14 | const body = ` 15 | 16 | 17 | 18 | 19 | GraphiQL 20 | 21 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
Loading...
40 | 133 | 134 | `; 135 | -------------------------------------------------------------------------------- /graphql/function.json: -------------------------------------------------------------------------------- 1 | { 2 | "disabled": false, 3 | "bindings": [ 4 | { 5 | "authLevel": "anonymous", 6 | "type": "httpTrigger", 7 | "direction": "in", 8 | "name": "req" 9 | }, 10 | { 11 | "type": "http", 12 | "direction": "out", 13 | "name": "res" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /graphql/index.js: -------------------------------------------------------------------------------- 1 | const { graphql, buildSchema } = require("graphql"); 2 | const axios = require("axios"); 3 | const baseUrl = require("../utils/baseUrl"); 4 | 5 | const schema = buildSchema(` 6 | type Recipe { 7 | name: ID 8 | publisher: String 9 | sourceUrl: String 10 | imageUrl: String 11 | ingredients: [Ingredient] 12 | nutrition: Nutrition 13 | } 14 | 15 | type Ingredient { 16 | name: ID 17 | brand: String 18 | amount: Amount 19 | weightGrams: Float 20 | thumb: String 21 | photo: String 22 | nutrition: Nutrition 23 | } 24 | 25 | scalar Amount { 26 | value: Float 27 | unit: String 28 | } 29 | 30 | type Nutrition { 31 | protein: Amount 32 | fat: Amount 33 | carbohydrates: Amount 34 | ash: Amount 35 | energy: Amount 36 | sucrose: Amount 37 | glucose: Amount 38 | maltose: Amount 39 | alcohol: Amount 40 | water: Amount 41 | adjustedProtein: Amount 42 | caffeine: Amount 43 | theobromine: Amount 44 | kj: Amount 45 | sugars: Amount 46 | galactose: Amount 47 | fiber: Amount 48 | calcium: Amount 49 | iron: Amount 50 | phosphorus: Amount 51 | potassium: Amount 52 | sodium: Amount 53 | zinc: Amount 54 | copper: Amount 55 | fluoride: Amount 56 | manganese: Amount 57 | selenium: Amount 58 | vitaminA: Amount 59 | retinol: Amount 60 | vitaminARae: Amount 61 | betaCarotene: Amount 62 | alphaCarotene: Amount 63 | vitaminE: Amount 64 | vitaminD: Amount 65 | lycopene: Amount 66 | vitaminB12: Amount 67 | vitaminK: Amount 68 | cholesterol: Amount 69 | transFat: Amount 70 | saturatedFat: Amount 71 | } 72 | 73 | type Query { 74 | recipe(name: ID): Recipe 75 | ingredient(name: ID): Ingredient 76 | } 77 | `); 78 | 79 | const root = { 80 | recipe(obj, args, context) { 81 | return axios 82 | .post(`${baseUrl}/api/recipe`, { 83 | name: obj.name, 84 | args, 85 | context 86 | }) 87 | .then(res => res.data); 88 | }, 89 | ingredient(obj, args, context) { 90 | return axios 91 | .post(`${baseUrl}/api/ingredient`, { name: obj.name, context }) 92 | .then(res => res.data); 93 | } 94 | }; 95 | 96 | module.exports = function(context, req) { 97 | const query = req.body.query; 98 | 99 | context.log(`GraphQL request: ${query}`); 100 | 101 | graphql(schema, query, root).then(response => { 102 | context.res = { 103 | body: response 104 | }; 105 | context.done(); 106 | }); 107 | }; 108 | -------------------------------------------------------------------------------- /host.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /ingredient/function.json: -------------------------------------------------------------------------------- 1 | { 2 | "disabled": false, 3 | "bindings": [ 4 | { 5 | "authLevel": "anonymous", 6 | "type": "httpTrigger", 7 | "direction": "in", 8 | "name": "req" 9 | }, 10 | { 11 | "type": "http", 12 | "direction": "out", 13 | "name": "res" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /ingredient/index.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const getNutrients = require("../utils/getNutrients"); 3 | const sumNutrients = require("../utils/sumNutrients"); 4 | const keys = require("../secrets.json"); 5 | 6 | module.exports = function(context, req) { 7 | axios 8 | .post( 9 | `https://trackapi.nutritionix.com/v2/natural/nutrients`, 10 | { 11 | query: req.body.name, 12 | timezone: "US/Pacific" 13 | }, 14 | { 15 | headers: { 16 | "Content-Type": "application/json", 17 | "x-app-id": process.env.NUTRITIONIX_ID || keys.nutritionix.id, 18 | "x-app-key": process.env.NUTRITIONIX_KEY || keys.nutritionix.key 19 | } 20 | } 21 | ) 22 | 23 | .then(res => { 24 | const ingredients = res.data.foods.map(ingredient => ({ 25 | name: ingredient.food_name, 26 | brand: ingredient.brand_name, 27 | amount: { 28 | value: ingredient.serving_qty, 29 | unit: ingredient.serving_unit 30 | }, 31 | weightGrams: ingredient.serving_weight_grams, 32 | thumb: ingredient.photo.thumb, 33 | photo: ingredient.photo.highres, 34 | nutrition: getNutrients(ingredient.full_nutrients) 35 | })); 36 | context.res = { 37 | ingredients, 38 | nutrition: sumNutrients(ingredients) 39 | }; 40 | context.done(); 41 | }) 42 | .catch(e => context.log("err", e)); 43 | }; 44 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-recipe-api", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "acorn": { 8 | "version": "5.5.3", 9 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", 10 | "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", 11 | "dev": true 12 | }, 13 | "acorn-jsx": { 14 | "version": "3.0.1", 15 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", 16 | "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", 17 | "dev": true, 18 | "requires": { 19 | "acorn": "3.3.0" 20 | }, 21 | "dependencies": { 22 | "acorn": { 23 | "version": "3.3.0", 24 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 25 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", 26 | "dev": true 27 | } 28 | } 29 | }, 30 | "ajv": { 31 | "version": "5.5.2", 32 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", 33 | "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", 34 | "dev": true, 35 | "requires": { 36 | "co": "4.6.0", 37 | "fast-deep-equal": "1.1.0", 38 | "fast-json-stable-stringify": "2.0.0", 39 | "json-schema-traverse": "0.3.1" 40 | } 41 | }, 42 | "ajv-keywords": { 43 | "version": "2.1.1", 44 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", 45 | "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", 46 | "dev": true 47 | }, 48 | "ansi-escapes": { 49 | "version": "3.1.0", 50 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", 51 | "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", 52 | "dev": true 53 | }, 54 | "ansi-regex": { 55 | "version": "2.1.1", 56 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 57 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 58 | "dev": true 59 | }, 60 | "ansi-styles": { 61 | "version": "2.2.1", 62 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 63 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", 64 | "dev": true 65 | }, 66 | "argparse": { 67 | "version": "1.0.10", 68 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 69 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 70 | "dev": true, 71 | "requires": { 72 | "sprintf-js": "1.0.3" 73 | } 74 | }, 75 | "array-union": { 76 | "version": "1.0.2", 77 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", 78 | "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", 79 | "dev": true, 80 | "requires": { 81 | "array-uniq": "1.0.3" 82 | } 83 | }, 84 | "array-uniq": { 85 | "version": "1.0.3", 86 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", 87 | "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", 88 | "dev": true 89 | }, 90 | "arrify": { 91 | "version": "1.0.1", 92 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 93 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 94 | "dev": true 95 | }, 96 | "axios": { 97 | "version": "0.18.0", 98 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", 99 | "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", 100 | "requires": { 101 | "follow-redirects": "1.4.1", 102 | "is-buffer": "1.1.6" 103 | } 104 | }, 105 | "babel-code-frame": { 106 | "version": "6.26.0", 107 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", 108 | "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", 109 | "dev": true, 110 | "requires": { 111 | "chalk": "1.1.3", 112 | "esutils": "2.0.2", 113 | "js-tokens": "3.0.2" 114 | }, 115 | "dependencies": { 116 | "chalk": { 117 | "version": "1.1.3", 118 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 119 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 120 | "dev": true, 121 | "requires": { 122 | "ansi-styles": "2.2.1", 123 | "escape-string-regexp": "1.0.5", 124 | "has-ansi": "2.0.0", 125 | "strip-ansi": "3.0.1", 126 | "supports-color": "2.0.0" 127 | } 128 | }, 129 | "strip-ansi": { 130 | "version": "3.0.1", 131 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 132 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 133 | "dev": true, 134 | "requires": { 135 | "ansi-regex": "2.1.1" 136 | } 137 | } 138 | } 139 | }, 140 | "balanced-match": { 141 | "version": "1.0.0", 142 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 143 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 144 | "dev": true 145 | }, 146 | "brace-expansion": { 147 | "version": "1.1.11", 148 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 149 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 150 | "dev": true, 151 | "requires": { 152 | "balanced-match": "1.0.0", 153 | "concat-map": "0.0.1" 154 | } 155 | }, 156 | "buffer-from": { 157 | "version": "1.0.0", 158 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", 159 | "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", 160 | "dev": true 161 | }, 162 | "caller-path": { 163 | "version": "0.1.0", 164 | "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", 165 | "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", 166 | "dev": true, 167 | "requires": { 168 | "callsites": "0.2.0" 169 | } 170 | }, 171 | "callsites": { 172 | "version": "0.2.0", 173 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", 174 | "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", 175 | "dev": true 176 | }, 177 | "chalk": { 178 | "version": "2.3.2", 179 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", 180 | "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", 181 | "dev": true, 182 | "requires": { 183 | "ansi-styles": "3.2.1", 184 | "escape-string-regexp": "1.0.5", 185 | "supports-color": "5.3.0" 186 | }, 187 | "dependencies": { 188 | "ansi-styles": { 189 | "version": "3.2.1", 190 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 191 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 192 | "dev": true, 193 | "requires": { 194 | "color-convert": "1.9.1" 195 | } 196 | }, 197 | "supports-color": { 198 | "version": "5.3.0", 199 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", 200 | "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", 201 | "dev": true, 202 | "requires": { 203 | "has-flag": "3.0.0" 204 | } 205 | } 206 | } 207 | }, 208 | "chardet": { 209 | "version": "0.4.2", 210 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", 211 | "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", 212 | "dev": true 213 | }, 214 | "circular-json": { 215 | "version": "0.3.3", 216 | "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", 217 | "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", 218 | "dev": true 219 | }, 220 | "cli-cursor": { 221 | "version": "2.1.0", 222 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 223 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 224 | "dev": true, 225 | "requires": { 226 | "restore-cursor": "2.0.0" 227 | } 228 | }, 229 | "cli-width": { 230 | "version": "2.2.0", 231 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 232 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", 233 | "dev": true 234 | }, 235 | "co": { 236 | "version": "4.6.0", 237 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 238 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", 239 | "dev": true 240 | }, 241 | "color-convert": { 242 | "version": "1.9.1", 243 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", 244 | "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", 245 | "dev": true, 246 | "requires": { 247 | "color-name": "1.1.3" 248 | } 249 | }, 250 | "color-name": { 251 | "version": "1.1.3", 252 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 253 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 254 | "dev": true 255 | }, 256 | "concat-map": { 257 | "version": "0.0.1", 258 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 259 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 260 | "dev": true 261 | }, 262 | "concat-stream": { 263 | "version": "1.6.2", 264 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 265 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 266 | "dev": true, 267 | "requires": { 268 | "buffer-from": "1.0.0", 269 | "inherits": "2.0.3", 270 | "readable-stream": "2.3.6", 271 | "typedarray": "0.0.6" 272 | } 273 | }, 274 | "core-util-is": { 275 | "version": "1.0.2", 276 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 277 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 278 | "dev": true 279 | }, 280 | "cross-spawn": { 281 | "version": "5.1.0", 282 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", 283 | "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", 284 | "dev": true, 285 | "requires": { 286 | "lru-cache": "4.1.2", 287 | "shebang-command": "1.2.0", 288 | "which": "1.3.0" 289 | } 290 | }, 291 | "debug": { 292 | "version": "3.1.0", 293 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 294 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 295 | "requires": { 296 | "ms": "2.0.0" 297 | } 298 | }, 299 | "deep-is": { 300 | "version": "0.1.3", 301 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 302 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 303 | "dev": true 304 | }, 305 | "del": { 306 | "version": "2.2.2", 307 | "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", 308 | "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", 309 | "dev": true, 310 | "requires": { 311 | "globby": "5.0.0", 312 | "is-path-cwd": "1.0.0", 313 | "is-path-in-cwd": "1.0.1", 314 | "object-assign": "4.1.1", 315 | "pify": "2.3.0", 316 | "pinkie-promise": "2.0.1", 317 | "rimraf": "2.6.2" 318 | } 319 | }, 320 | "doctrine": { 321 | "version": "2.1.0", 322 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", 323 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", 324 | "dev": true, 325 | "requires": { 326 | "esutils": "2.0.2" 327 | } 328 | }, 329 | "escape-string-regexp": { 330 | "version": "1.0.5", 331 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 332 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 333 | "dev": true 334 | }, 335 | "eslint": { 336 | "version": "4.19.1", 337 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", 338 | "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", 339 | "dev": true, 340 | "requires": { 341 | "ajv": "5.5.2", 342 | "babel-code-frame": "6.26.0", 343 | "chalk": "2.3.2", 344 | "concat-stream": "1.6.2", 345 | "cross-spawn": "5.1.0", 346 | "debug": "3.1.0", 347 | "doctrine": "2.1.0", 348 | "eslint-scope": "3.7.1", 349 | "eslint-visitor-keys": "1.0.0", 350 | "espree": "3.5.4", 351 | "esquery": "1.0.1", 352 | "esutils": "2.0.2", 353 | "file-entry-cache": "2.0.0", 354 | "functional-red-black-tree": "1.0.1", 355 | "glob": "7.1.2", 356 | "globals": "11.4.0", 357 | "ignore": "3.3.7", 358 | "imurmurhash": "0.1.4", 359 | "inquirer": "3.3.0", 360 | "is-resolvable": "1.1.0", 361 | "js-yaml": "3.11.0", 362 | "json-stable-stringify-without-jsonify": "1.0.1", 363 | "levn": "0.3.0", 364 | "lodash": "4.17.5", 365 | "minimatch": "3.0.4", 366 | "mkdirp": "0.5.1", 367 | "natural-compare": "1.4.0", 368 | "optionator": "0.8.2", 369 | "path-is-inside": "1.0.2", 370 | "pluralize": "7.0.0", 371 | "progress": "2.0.0", 372 | "regexpp": "1.1.0", 373 | "require-uncached": "1.0.3", 374 | "semver": "5.5.0", 375 | "strip-ansi": "4.0.0", 376 | "strip-json-comments": "2.0.1", 377 | "table": "4.0.2", 378 | "text-table": "0.2.0" 379 | } 380 | }, 381 | "eslint-scope": { 382 | "version": "3.7.1", 383 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", 384 | "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", 385 | "dev": true, 386 | "requires": { 387 | "esrecurse": "4.2.1", 388 | "estraverse": "4.2.0" 389 | } 390 | }, 391 | "eslint-visitor-keys": { 392 | "version": "1.0.0", 393 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", 394 | "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", 395 | "dev": true 396 | }, 397 | "espree": { 398 | "version": "3.5.4", 399 | "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", 400 | "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", 401 | "dev": true, 402 | "requires": { 403 | "acorn": "5.5.3", 404 | "acorn-jsx": "3.0.1" 405 | } 406 | }, 407 | "esprima": { 408 | "version": "4.0.0", 409 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", 410 | "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", 411 | "dev": true 412 | }, 413 | "esquery": { 414 | "version": "1.0.1", 415 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", 416 | "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", 417 | "dev": true, 418 | "requires": { 419 | "estraverse": "4.2.0" 420 | } 421 | }, 422 | "esrecurse": { 423 | "version": "4.2.1", 424 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", 425 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", 426 | "dev": true, 427 | "requires": { 428 | "estraverse": "4.2.0" 429 | } 430 | }, 431 | "estraverse": { 432 | "version": "4.2.0", 433 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", 434 | "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", 435 | "dev": true 436 | }, 437 | "esutils": { 438 | "version": "2.0.2", 439 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 440 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 441 | "dev": true 442 | }, 443 | "external-editor": { 444 | "version": "2.2.0", 445 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", 446 | "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", 447 | "dev": true, 448 | "requires": { 449 | "chardet": "0.4.2", 450 | "iconv-lite": "0.4.21", 451 | "tmp": "0.0.33" 452 | } 453 | }, 454 | "fast-deep-equal": { 455 | "version": "1.1.0", 456 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", 457 | "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", 458 | "dev": true 459 | }, 460 | "fast-json-stable-stringify": { 461 | "version": "2.0.0", 462 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 463 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", 464 | "dev": true 465 | }, 466 | "fast-levenshtein": { 467 | "version": "2.0.6", 468 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 469 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 470 | "dev": true 471 | }, 472 | "figures": { 473 | "version": "2.0.0", 474 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 475 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 476 | "dev": true, 477 | "requires": { 478 | "escape-string-regexp": "1.0.5" 479 | } 480 | }, 481 | "file-entry-cache": { 482 | "version": "2.0.0", 483 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", 484 | "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", 485 | "dev": true, 486 | "requires": { 487 | "flat-cache": "1.3.0", 488 | "object-assign": "4.1.1" 489 | } 490 | }, 491 | "flat-cache": { 492 | "version": "1.3.0", 493 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", 494 | "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", 495 | "dev": true, 496 | "requires": { 497 | "circular-json": "0.3.3", 498 | "del": "2.2.2", 499 | "graceful-fs": "4.1.11", 500 | "write": "0.2.1" 501 | } 502 | }, 503 | "follow-redirects": { 504 | "version": "1.4.1", 505 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", 506 | "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", 507 | "requires": { 508 | "debug": "3.1.0" 509 | } 510 | }, 511 | "fs.realpath": { 512 | "version": "1.0.0", 513 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 514 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 515 | "dev": true 516 | }, 517 | "functional-red-black-tree": { 518 | "version": "1.0.1", 519 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 520 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 521 | "dev": true 522 | }, 523 | "glob": { 524 | "version": "7.1.2", 525 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 526 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 527 | "dev": true, 528 | "requires": { 529 | "fs.realpath": "1.0.0", 530 | "inflight": "1.0.6", 531 | "inherits": "2.0.3", 532 | "minimatch": "3.0.4", 533 | "once": "1.4.0", 534 | "path-is-absolute": "1.0.1" 535 | } 536 | }, 537 | "globals": { 538 | "version": "11.4.0", 539 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.4.0.tgz", 540 | "integrity": "sha512-Dyzmifil8n/TmSqYDEXbm+C8yitzJQqQIlJQLNRMwa+BOUJpRC19pyVeN12JAjt61xonvXjtff+hJruTRXn5HA==", 541 | "dev": true 542 | }, 543 | "globby": { 544 | "version": "5.0.0", 545 | "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", 546 | "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", 547 | "dev": true, 548 | "requires": { 549 | "array-union": "1.0.2", 550 | "arrify": "1.0.1", 551 | "glob": "7.1.2", 552 | "object-assign": "4.1.1", 553 | "pify": "2.3.0", 554 | "pinkie-promise": "2.0.1" 555 | } 556 | }, 557 | "graceful-fs": { 558 | "version": "4.1.11", 559 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 560 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", 561 | "dev": true 562 | }, 563 | "graphql": { 564 | "version": "0.13.2", 565 | "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.13.2.tgz", 566 | "integrity": "sha512-QZ5BL8ZO/B20VA8APauGBg3GyEgZ19eduvpLWoq5x7gMmWnHoy8rlQWPLmWgFvo1yNgjSEFMesmS4R6pPr7xog==", 567 | "requires": { 568 | "iterall": "1.2.2" 569 | } 570 | }, 571 | "has-ansi": { 572 | "version": "2.0.0", 573 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 574 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 575 | "dev": true, 576 | "requires": { 577 | "ansi-regex": "2.1.1" 578 | } 579 | }, 580 | "has-flag": { 581 | "version": "3.0.0", 582 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 583 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 584 | "dev": true 585 | }, 586 | "iconv-lite": { 587 | "version": "0.4.21", 588 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", 589 | "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", 590 | "dev": true, 591 | "requires": { 592 | "safer-buffer": "2.1.2" 593 | } 594 | }, 595 | "ignore": { 596 | "version": "3.3.7", 597 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", 598 | "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", 599 | "dev": true 600 | }, 601 | "imurmurhash": { 602 | "version": "0.1.4", 603 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 604 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 605 | "dev": true 606 | }, 607 | "inflight": { 608 | "version": "1.0.6", 609 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 610 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 611 | "dev": true, 612 | "requires": { 613 | "once": "1.4.0", 614 | "wrappy": "1.0.2" 615 | } 616 | }, 617 | "inherits": { 618 | "version": "2.0.3", 619 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 620 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 621 | "dev": true 622 | }, 623 | "inquirer": { 624 | "version": "3.3.0", 625 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", 626 | "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", 627 | "dev": true, 628 | "requires": { 629 | "ansi-escapes": "3.1.0", 630 | "chalk": "2.3.2", 631 | "cli-cursor": "2.1.0", 632 | "cli-width": "2.2.0", 633 | "external-editor": "2.2.0", 634 | "figures": "2.0.0", 635 | "lodash": "4.17.5", 636 | "mute-stream": "0.0.7", 637 | "run-async": "2.3.0", 638 | "rx-lite": "4.0.8", 639 | "rx-lite-aggregates": "4.0.8", 640 | "string-width": "2.1.1", 641 | "strip-ansi": "4.0.0", 642 | "through": "2.3.8" 643 | } 644 | }, 645 | "is-buffer": { 646 | "version": "1.1.6", 647 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 648 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 649 | }, 650 | "is-fullwidth-code-point": { 651 | "version": "2.0.0", 652 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 653 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 654 | "dev": true 655 | }, 656 | "is-path-cwd": { 657 | "version": "1.0.0", 658 | "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", 659 | "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", 660 | "dev": true 661 | }, 662 | "is-path-in-cwd": { 663 | "version": "1.0.1", 664 | "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", 665 | "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", 666 | "dev": true, 667 | "requires": { 668 | "is-path-inside": "1.0.1" 669 | } 670 | }, 671 | "is-path-inside": { 672 | "version": "1.0.1", 673 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", 674 | "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", 675 | "dev": true, 676 | "requires": { 677 | "path-is-inside": "1.0.2" 678 | } 679 | }, 680 | "is-promise": { 681 | "version": "2.1.0", 682 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 683 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", 684 | "dev": true 685 | }, 686 | "is-resolvable": { 687 | "version": "1.1.0", 688 | "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", 689 | "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", 690 | "dev": true 691 | }, 692 | "isarray": { 693 | "version": "1.0.0", 694 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 695 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 696 | "dev": true 697 | }, 698 | "isexe": { 699 | "version": "2.0.0", 700 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 701 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 702 | "dev": true 703 | }, 704 | "iterall": { 705 | "version": "1.2.2", 706 | "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.2.tgz", 707 | "integrity": "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==" 708 | }, 709 | "js-tokens": { 710 | "version": "3.0.2", 711 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 712 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", 713 | "dev": true 714 | }, 715 | "js-yaml": { 716 | "version": "3.11.0", 717 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", 718 | "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", 719 | "dev": true, 720 | "requires": { 721 | "argparse": "1.0.10", 722 | "esprima": "4.0.0" 723 | } 724 | }, 725 | "json-schema-traverse": { 726 | "version": "0.3.1", 727 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", 728 | "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", 729 | "dev": true 730 | }, 731 | "json-stable-stringify-without-jsonify": { 732 | "version": "1.0.1", 733 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 734 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 735 | "dev": true 736 | }, 737 | "levn": { 738 | "version": "0.3.0", 739 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 740 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 741 | "dev": true, 742 | "requires": { 743 | "prelude-ls": "1.1.2", 744 | "type-check": "0.3.2" 745 | } 746 | }, 747 | "lodash": { 748 | "version": "4.17.5", 749 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", 750 | "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", 751 | "dev": true 752 | }, 753 | "lru-cache": { 754 | "version": "4.1.2", 755 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", 756 | "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", 757 | "dev": true, 758 | "requires": { 759 | "pseudomap": "1.0.2", 760 | "yallist": "2.1.2" 761 | } 762 | }, 763 | "mimic-fn": { 764 | "version": "1.2.0", 765 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 766 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", 767 | "dev": true 768 | }, 769 | "minimatch": { 770 | "version": "3.0.4", 771 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 772 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 773 | "dev": true, 774 | "requires": { 775 | "brace-expansion": "1.1.11" 776 | } 777 | }, 778 | "minimist": { 779 | "version": "0.0.8", 780 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 781 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 782 | "dev": true 783 | }, 784 | "mkdirp": { 785 | "version": "0.5.1", 786 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 787 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 788 | "dev": true, 789 | "requires": { 790 | "minimist": "0.0.8" 791 | } 792 | }, 793 | "ms": { 794 | "version": "2.0.0", 795 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 796 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 797 | }, 798 | "mute-stream": { 799 | "version": "0.0.7", 800 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 801 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", 802 | "dev": true 803 | }, 804 | "natural-compare": { 805 | "version": "1.4.0", 806 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 807 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 808 | "dev": true 809 | }, 810 | "object-assign": { 811 | "version": "4.1.1", 812 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 813 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 814 | "dev": true 815 | }, 816 | "once": { 817 | "version": "1.4.0", 818 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 819 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 820 | "dev": true, 821 | "requires": { 822 | "wrappy": "1.0.2" 823 | } 824 | }, 825 | "onetime": { 826 | "version": "2.0.1", 827 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 828 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 829 | "dev": true, 830 | "requires": { 831 | "mimic-fn": "1.2.0" 832 | } 833 | }, 834 | "optionator": { 835 | "version": "0.8.2", 836 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 837 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 838 | "dev": true, 839 | "requires": { 840 | "deep-is": "0.1.3", 841 | "fast-levenshtein": "2.0.6", 842 | "levn": "0.3.0", 843 | "prelude-ls": "1.1.2", 844 | "type-check": "0.3.2", 845 | "wordwrap": "1.0.0" 846 | } 847 | }, 848 | "os-tmpdir": { 849 | "version": "1.0.2", 850 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 851 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 852 | "dev": true 853 | }, 854 | "path-is-absolute": { 855 | "version": "1.0.1", 856 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 857 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 858 | "dev": true 859 | }, 860 | "path-is-inside": { 861 | "version": "1.0.2", 862 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 863 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", 864 | "dev": true 865 | }, 866 | "pify": { 867 | "version": "2.3.0", 868 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 869 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 870 | "dev": true 871 | }, 872 | "pinkie": { 873 | "version": "2.0.4", 874 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 875 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", 876 | "dev": true 877 | }, 878 | "pinkie-promise": { 879 | "version": "2.0.1", 880 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 881 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 882 | "dev": true, 883 | "requires": { 884 | "pinkie": "2.0.4" 885 | } 886 | }, 887 | "pluralize": { 888 | "version": "7.0.0", 889 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", 890 | "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", 891 | "dev": true 892 | }, 893 | "prelude-ls": { 894 | "version": "1.1.2", 895 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 896 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 897 | "dev": true 898 | }, 899 | "prettier": { 900 | "version": "1.12.1", 901 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.12.1.tgz", 902 | "integrity": "sha1-wa0g6APndJ+vkFpAnSNn4Gu+cyU=", 903 | "dev": true 904 | }, 905 | "process-nextick-args": { 906 | "version": "2.0.0", 907 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 908 | "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", 909 | "dev": true 910 | }, 911 | "progress": { 912 | "version": "2.0.0", 913 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", 914 | "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", 915 | "dev": true 916 | }, 917 | "pseudomap": { 918 | "version": "1.0.2", 919 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 920 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", 921 | "dev": true 922 | }, 923 | "readable-stream": { 924 | "version": "2.3.6", 925 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 926 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 927 | "dev": true, 928 | "requires": { 929 | "core-util-is": "1.0.2", 930 | "inherits": "2.0.3", 931 | "isarray": "1.0.0", 932 | "process-nextick-args": "2.0.0", 933 | "safe-buffer": "5.1.1", 934 | "string_decoder": "1.1.1", 935 | "util-deprecate": "1.0.2" 936 | } 937 | }, 938 | "regexpp": { 939 | "version": "1.1.0", 940 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", 941 | "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", 942 | "dev": true 943 | }, 944 | "require-uncached": { 945 | "version": "1.0.3", 946 | "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", 947 | "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", 948 | "dev": true, 949 | "requires": { 950 | "caller-path": "0.1.0", 951 | "resolve-from": "1.0.1" 952 | } 953 | }, 954 | "resolve-from": { 955 | "version": "1.0.1", 956 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", 957 | "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", 958 | "dev": true 959 | }, 960 | "restore-cursor": { 961 | "version": "2.0.0", 962 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 963 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 964 | "dev": true, 965 | "requires": { 966 | "onetime": "2.0.1", 967 | "signal-exit": "3.0.2" 968 | } 969 | }, 970 | "rimraf": { 971 | "version": "2.6.2", 972 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", 973 | "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", 974 | "dev": true, 975 | "requires": { 976 | "glob": "7.1.2" 977 | } 978 | }, 979 | "run-async": { 980 | "version": "2.3.0", 981 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 982 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 983 | "dev": true, 984 | "requires": { 985 | "is-promise": "2.1.0" 986 | } 987 | }, 988 | "rx-lite": { 989 | "version": "4.0.8", 990 | "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", 991 | "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", 992 | "dev": true 993 | }, 994 | "rx-lite-aggregates": { 995 | "version": "4.0.8", 996 | "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", 997 | "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", 998 | "dev": true, 999 | "requires": { 1000 | "rx-lite": "4.0.8" 1001 | } 1002 | }, 1003 | "safe-buffer": { 1004 | "version": "5.1.1", 1005 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 1006 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", 1007 | "dev": true 1008 | }, 1009 | "safer-buffer": { 1010 | "version": "2.1.2", 1011 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1012 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1013 | "dev": true 1014 | }, 1015 | "semver": { 1016 | "version": "5.5.0", 1017 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", 1018 | "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", 1019 | "dev": true 1020 | }, 1021 | "shebang-command": { 1022 | "version": "1.2.0", 1023 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 1024 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 1025 | "dev": true, 1026 | "requires": { 1027 | "shebang-regex": "1.0.0" 1028 | } 1029 | }, 1030 | "shebang-regex": { 1031 | "version": "1.0.0", 1032 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 1033 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 1034 | "dev": true 1035 | }, 1036 | "signal-exit": { 1037 | "version": "3.0.2", 1038 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1039 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 1040 | "dev": true 1041 | }, 1042 | "slice-ansi": { 1043 | "version": "1.0.0", 1044 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", 1045 | "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", 1046 | "dev": true, 1047 | "requires": { 1048 | "is-fullwidth-code-point": "2.0.0" 1049 | } 1050 | }, 1051 | "sprintf-js": { 1052 | "version": "1.0.3", 1053 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1054 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1055 | "dev": true 1056 | }, 1057 | "string-width": { 1058 | "version": "2.1.1", 1059 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1060 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1061 | "dev": true, 1062 | "requires": { 1063 | "is-fullwidth-code-point": "2.0.0", 1064 | "strip-ansi": "4.0.0" 1065 | } 1066 | }, 1067 | "string_decoder": { 1068 | "version": "1.1.1", 1069 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1070 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1071 | "dev": true, 1072 | "requires": { 1073 | "safe-buffer": "5.1.1" 1074 | } 1075 | }, 1076 | "strip-ansi": { 1077 | "version": "4.0.0", 1078 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1079 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1080 | "dev": true, 1081 | "requires": { 1082 | "ansi-regex": "3.0.0" 1083 | }, 1084 | "dependencies": { 1085 | "ansi-regex": { 1086 | "version": "3.0.0", 1087 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 1088 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 1089 | "dev": true 1090 | } 1091 | } 1092 | }, 1093 | "strip-json-comments": { 1094 | "version": "2.0.1", 1095 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1096 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1097 | "dev": true 1098 | }, 1099 | "supports-color": { 1100 | "version": "2.0.0", 1101 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 1102 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", 1103 | "dev": true 1104 | }, 1105 | "table": { 1106 | "version": "4.0.2", 1107 | "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", 1108 | "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", 1109 | "dev": true, 1110 | "requires": { 1111 | "ajv": "5.5.2", 1112 | "ajv-keywords": "2.1.1", 1113 | "chalk": "2.3.2", 1114 | "lodash": "4.17.5", 1115 | "slice-ansi": "1.0.0", 1116 | "string-width": "2.1.1" 1117 | } 1118 | }, 1119 | "text-table": { 1120 | "version": "0.2.0", 1121 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1122 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1123 | "dev": true 1124 | }, 1125 | "through": { 1126 | "version": "2.3.8", 1127 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1128 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 1129 | "dev": true 1130 | }, 1131 | "tmp": { 1132 | "version": "0.0.33", 1133 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1134 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1135 | "dev": true, 1136 | "requires": { 1137 | "os-tmpdir": "1.0.2" 1138 | } 1139 | }, 1140 | "type-check": { 1141 | "version": "0.3.2", 1142 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1143 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1144 | "dev": true, 1145 | "requires": { 1146 | "prelude-ls": "1.1.2" 1147 | } 1148 | }, 1149 | "typedarray": { 1150 | "version": "0.0.6", 1151 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 1152 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 1153 | "dev": true 1154 | }, 1155 | "util-deprecate": { 1156 | "version": "1.0.2", 1157 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1158 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 1159 | "dev": true 1160 | }, 1161 | "which": { 1162 | "version": "1.3.0", 1163 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", 1164 | "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", 1165 | "dev": true, 1166 | "requires": { 1167 | "isexe": "2.0.0" 1168 | } 1169 | }, 1170 | "wordwrap": { 1171 | "version": "1.0.0", 1172 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 1173 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", 1174 | "dev": true 1175 | }, 1176 | "wrappy": { 1177 | "version": "1.0.2", 1178 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1179 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1180 | "dev": true 1181 | }, 1182 | "write": { 1183 | "version": "0.2.1", 1184 | "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", 1185 | "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", 1186 | "dev": true, 1187 | "requires": { 1188 | "mkdirp": "0.5.1" 1189 | } 1190 | }, 1191 | "yallist": { 1192 | "version": "2.1.2", 1193 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 1194 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", 1195 | "dev": true 1196 | } 1197 | } 1198 | } 1199 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-recipe-api", 3 | "version": "1.0.0", 4 | "description": "GraphQL on top of Azure Functions", 5 | "main": "graphql/index.js", 6 | "scripts": { 7 | "start": "func start", 8 | "lint": "eslint --fix \"./**/*.js\"", 9 | "format": "prettier --write \"{graphql,ingredient,recipe,utils}/**/*.{js,json}\"" 10 | }, 11 | "keywords": [], 12 | "author": "Brian Holt ", 13 | "license": "Apache-2.0", 14 | "dependencies": { 15 | "axios": "^0.18.0", 16 | "graphql": "^0.13.2" 17 | }, 18 | "devDependencies": { 19 | "eslint": "^4.19.1", 20 | "prettier": "^1.12.1" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/btholt/graphql-on-azure-functions.git" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/btholt/graphql-on-azure-functions/issues" 28 | }, 29 | "homepage": "https://github.com/btholt/graphql-on-azure-functions#readme" 30 | } 31 | -------------------------------------------------------------------------------- /recipe/function.json: -------------------------------------------------------------------------------- 1 | { 2 | "disabled": false, 3 | "bindings": [ 4 | { 5 | "authLevel": "anonymous", 6 | "type": "httpTrigger", 7 | "direction": "in", 8 | "name": "req" 9 | }, 10 | { 11 | "type": "http", 12 | "direction": "out", 13 | "name": "res" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /recipe/index.js: -------------------------------------------------------------------------------- 1 | const axios = require("axios"); 2 | const key = process.env.FOOD2FORK_KEY || require("../secrets.json").foodToFork; 3 | const baseUrl = require("../utils/baseUrl"); 4 | 5 | module.exports = function(context, req) { 6 | let recipe; 7 | 8 | axios 9 | .get( 10 | `http://food2fork.com/api/search?key=${key}&q=${encodeURIComponent( 11 | req.body.name 12 | )}` 13 | ) 14 | .then(res => 15 | axios.get( 16 | `http://food2fork.com/api/get?key=${key}&rId=${ 17 | res.data.recipes[0].recipe_id 18 | }` 19 | ) 20 | ) 21 | .then(res => { 22 | recipe = res.data.recipe; 23 | context.log(JSON.stringify(req.body.args, null, 4)); 24 | return axios.post(`${baseUrl}/api/ingredient`, { 25 | name: recipe.ingredients.join(", "), 26 | context: req.body.context ? req.body.context : void 0 27 | }); 28 | }) 29 | .then(res => { 30 | recipe.ingredients = res.data.ingredients; 31 | recipe.nutrition = res.data.nutrition; 32 | context.res = recipe; 33 | context.res = { 34 | name: recipe.title, 35 | publisher: recipe.publisher, 36 | sourceUrl: recipe.source_url, 37 | imageUrl: recipe.image_url, 38 | ingredients: res.data.ingredients, 39 | nutrition: res.data.nutrition 40 | }; 41 | context.done(); 42 | }) 43 | .catch(e => context.log("err", e)); 44 | }; 45 | -------------------------------------------------------------------------------- /secrets.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "foodToFork": "", 3 | "nutritionix": { 4 | "id": "", 5 | "key": "" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /utils/baseUrl.js: -------------------------------------------------------------------------------- 1 | const hostname = process.env.WEBSITE_HOSTNAME; 2 | module.exports = hostname ? `https://${hostname}` : 'http://localhost:7071'; -------------------------------------------------------------------------------- /utils/getNutrients.js: -------------------------------------------------------------------------------- 1 | const nutrientMap = require("./nutrientMap"); 2 | 3 | module.exports = function(nutrientsArray) { 4 | const obj = {}; 5 | 6 | nutrientsArray.forEach(element => { 7 | if (nutrientMap[element.attr_id]) { 8 | obj[nutrientMap[element.attr_id].type] = { 9 | value: element.value, 10 | unit: nutrientMap[element.attr_id].unit 11 | }; 12 | } 13 | }); 14 | 15 | return obj; 16 | }; 17 | -------------------------------------------------------------------------------- /utils/nutrientMap.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 203: { type: "protein", unit: "g" }, 3 | 204: { type: "fat", unit: "g" }, 4 | 205: { type: "carbohydrates", unit: "g" }, 5 | 207: { type: "ash", unit: "g" }, 6 | 208: { type: "energy", unit: "kcal" }, 7 | 209: { type: "starch", unit: "g" }, 8 | 210: { type: "sucrose", unit: "g" }, 9 | 211: { type: "glucose", unit: "g" }, 10 | 212: { type: "fructose", unit: "g" }, 11 | 213: { type: "lactose", unit: "g" }, 12 | 214: { type: "maltose", unit: "g" }, 13 | 221: { type: "alcohol", unit: "g" }, 14 | 255: { type: "water", unit: "g" }, 15 | 257: { type: "adjustedProtein", unit: "g" }, 16 | 262: { type: "caffeine", unit: "g" }, 17 | 263: { type: "theobromine", unit: "g" }, 18 | 268: { type: "kj", unit: "kJ" }, 19 | 269: { type: "sugars", unit: "g" }, 20 | 287: { type: "galactose", unit: "g" }, 21 | 291: { type: "fiber", unit: "g" }, 22 | 301: { type: "calcium", unit: "mg" }, 23 | 303: { type: "iron", unit: "mg" }, 24 | 305: { type: "phosphorus", unit: "mg" }, 25 | 306: { type: "potassium", unit: "mg" }, 26 | 307: { type: "sodium", unit: "mg" }, 27 | 309: { type: "zinc", unit: "mg" }, 28 | 312: { type: "copper", unit: "mg" }, 29 | 313: { type: "fluoride", unit: "µg" }, 30 | 315: { type: "manganese", unit: "mg" }, 31 | 317: { type: "selenium", unit: "µg" }, 32 | 318: { type: "vitaminA", unit: "IU" }, 33 | 319: { type: "retinol", unit: "µg" }, 34 | 320: { type: "vitaminARae", unit: "µg" }, 35 | 321: { type: "betaCarotene", unit: "µg" }, 36 | 322: { type: "alphaCarotene", unit: "µg" }, 37 | 323: { type: "vitaminE", unit: "mg" }, 38 | 324: { type: "vitaminD", unit: "IU" }, 39 | 337: { type: "lycopene", unit: "µg" }, 40 | 412: { type: "vitaminB12", unit: "µg" }, 41 | 430: { type: "vitaminK", unit: "µg" }, 42 | 601: { type: "cholesterol", unit: "mg" }, 43 | 605: { type: "transFats", unit: "g" }, 44 | 606: { type: "saturatedFats", unit: "g" } 45 | }; 46 | -------------------------------------------------------------------------------- /utils/sumNutrients.js: -------------------------------------------------------------------------------- 1 | const nutrientMap = require("./nutrientMap"); 2 | const values = Object.values(nutrientMap); 3 | const nutrientsToGet = values.map(obj => obj.type); 4 | const units = values.map(obj => obj.unit); 5 | 6 | module.exports = function sumNutrients(ingredients) { 7 | return nutrientsToGet 8 | .map(nutrient => { 9 | const ans = [ 10 | nutrient, 11 | ingredients 12 | .map( 13 | ingredient => 14 | ingredient.nutrition[nutrient] 15 | ? ingredient.nutrition[nutrient].value 16 | : 0 17 | ) 18 | .reduce((acc, cur) => acc + cur) 19 | ]; 20 | return ans; 21 | }) 22 | .reduce((acc, cur, index) => { 23 | acc[cur[0]] = { value: cur[1], unit: units[index] }; 24 | return acc; 25 | }, {}); 26 | }; 27 | --------------------------------------------------------------------------------