├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── package-lock.json ├── package.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Jonas Helfer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # graphql-disable-introspection 2 | Disable introspection queries in GraphQL with a simple validation rule. Queries that contain `__schema` or `__type` will fail validation with this rule. For example, the following queries will be rejected: 3 | 4 | ```graphql 5 | query { 6 | __schema { 7 | queryType { 8 | name 9 | } 10 | } 11 | } 12 | 13 | query { 14 | __type(name: "Query") { 15 | description 16 | fields { 17 | name 18 | } 19 | } 20 | } 21 | ``` 22 | 23 | ## Usage 24 | 25 | The package can be installed from npm 26 | 27 | ```sh 28 | npm install -save graphql-disable-introspection 29 | ``` 30 | 31 | It exports a single validation rule which you can pass to your node GraphQL server with the `validationRules` argument. 32 | 33 | Here's an example for `graphql-server-express`: 34 | 35 | ```diff 36 | import express from 'express'; 37 | import bodyParser from 'body-parser'; 38 | import { graphqlExpress } from 'graphql-server-express'; 39 | + import NoIntrospection from 'graphql-disable-introspection'; 40 | 41 | const myGraphQLSchema = // ... define or import your schema here! 42 | const PORT = 3000; 43 | 44 | var app = express(); 45 | 46 | // bodyParser is needed just for POST. 47 | app.use('/graphql', bodyParser.json(), graphqlExpress({ 48 | schema: myGraphQLSchema, 49 | + validationRules: [NoIntrospection] 50 | })); 51 | 52 | app.listen(PORT); 53 | 54 | ``` 55 | 56 | If you're using `express-graphql`, it works exactly the same way: 57 | 58 | ```diff 59 | app.use('/graphql', graphqlHTTP({ 60 | schema: MyGraphQLSchema, 61 | + validationRules: [NoIntrospection] 62 | })); 63 | ``` 64 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var graphql = require('graphql'); 2 | /** 3 | * No introspection: __schema and __type are disallowed in the query. 4 | */ 5 | module.exports = function NoIntrospection(context) { 6 | return { 7 | Field(node) { 8 | if (node.name.value === '__schema' || node.name.value === '__type') { 9 | context.reportError( 10 | new graphql.GraphQLError( 11 | 'GraphQL introspection is not allowed, but the query contained __schema or __type', 12 | [node] 13 | ) 14 | ); 15 | } 16 | } 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-disable-introspection", 3 | "version": "1.2.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/body-parser": { 8 | "version": "1.17.0", 9 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", 10 | "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==", 11 | "dev": true, 12 | "optional": true, 13 | "requires": { 14 | "@types/connect": "*", 15 | "@types/node": "*" 16 | } 17 | }, 18 | "@types/connect": { 19 | "version": "3.4.32", 20 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", 21 | "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", 22 | "dev": true, 23 | "optional": true, 24 | "requires": { 25 | "@types/node": "*" 26 | } 27 | }, 28 | "@types/events": { 29 | "version": "1.2.0", 30 | "resolved": "http://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", 31 | "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", 32 | "dev": true, 33 | "optional": true 34 | }, 35 | "@types/express": { 36 | "version": "4.16.0", 37 | "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.0.tgz", 38 | "integrity": "sha512-TtPEYumsmSTtTetAPXlJVf3kEqb6wZK0bZojpJQrnD/djV4q1oB6QQ8aKvKqwNPACoe02GNiy5zDzcYivR5Z2w==", 39 | "dev": true, 40 | "optional": true, 41 | "requires": { 42 | "@types/body-parser": "*", 43 | "@types/express-serve-static-core": "*", 44 | "@types/serve-static": "*" 45 | } 46 | }, 47 | "@types/express-serve-static-core": { 48 | "version": "4.16.0", 49 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz", 50 | "integrity": "sha512-lTeoCu5NxJU4OD9moCgm0ESZzweAx0YqsAcab6OB0EB3+As1OaHtKnaGJvcngQxYsi9UNv0abn4/DRavrRxt4w==", 51 | "dev": true, 52 | "optional": true, 53 | "requires": { 54 | "@types/events": "*", 55 | "@types/node": "*", 56 | "@types/range-parser": "*" 57 | } 58 | }, 59 | "@types/graphql": { 60 | "version": "0.8.6", 61 | "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.8.6.tgz", 62 | "integrity": "sha1-s0+4gEk7qDWwwGcCTucBMNb5u2g=", 63 | "dev": true, 64 | "optional": true 65 | }, 66 | "@types/mime": { 67 | "version": "2.0.0", 68 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz", 69 | "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==", 70 | "dev": true, 71 | "optional": true 72 | }, 73 | "@types/node": { 74 | "version": "10.12.12", 75 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.12.tgz", 76 | "integrity": "sha512-Pr+6JRiKkfsFvmU/LK68oBRCQeEg36TyAbPhc2xpez24OOZZCuoIhWGTd39VZy6nGafSbxzGouFPTFD/rR1A0A==", 77 | "dev": true, 78 | "optional": true 79 | }, 80 | "@types/range-parser": { 81 | "version": "1.2.2", 82 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.2.tgz", 83 | "integrity": "sha512-HtKGu+qG1NPvYe1z7ezLsyIaXYyi8SoAVqWDZgDQ8dLrsZvSzUNCwZyfX33uhWxL/SU0ZDQZ3nwZ0nimt507Kw==", 84 | "dev": true, 85 | "optional": true 86 | }, 87 | "@types/serve-static": { 88 | "version": "1.13.2", 89 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", 90 | "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==", 91 | "dev": true, 92 | "optional": true, 93 | "requires": { 94 | "@types/express-serve-static-core": "*", 95 | "@types/mime": "*" 96 | } 97 | }, 98 | "accepts": { 99 | "version": "1.3.5", 100 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", 101 | "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", 102 | "dev": true, 103 | "requires": { 104 | "mime-types": "~2.1.18", 105 | "negotiator": "0.6.1" 106 | } 107 | }, 108 | "array-flatten": { 109 | "version": "1.1.1", 110 | "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 111 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", 112 | "dev": true 113 | }, 114 | "assertion-error": { 115 | "version": "1.1.0", 116 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 117 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 118 | "dev": true 119 | }, 120 | "asynckit": { 121 | "version": "0.4.0", 122 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 123 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", 124 | "dev": true 125 | }, 126 | "balanced-match": { 127 | "version": "1.0.0", 128 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 129 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 130 | "dev": true 131 | }, 132 | "bluebird": { 133 | "version": "3.5.3", 134 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", 135 | "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", 136 | "dev": true 137 | }, 138 | "body-parser": { 139 | "version": "1.18.3", 140 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", 141 | "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", 142 | "dev": true, 143 | "requires": { 144 | "bytes": "3.0.0", 145 | "content-type": "~1.0.4", 146 | "debug": "2.6.9", 147 | "depd": "~1.1.2", 148 | "http-errors": "~1.6.3", 149 | "iconv-lite": "0.4.23", 150 | "on-finished": "~2.3.0", 151 | "qs": "6.5.2", 152 | "raw-body": "2.3.3", 153 | "type-is": "~1.6.16" 154 | } 155 | }, 156 | "brace-expansion": { 157 | "version": "1.1.11", 158 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 159 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 160 | "dev": true, 161 | "requires": { 162 | "balanced-match": "^1.0.0", 163 | "concat-map": "0.0.1" 164 | } 165 | }, 166 | "browser-stdout": { 167 | "version": "1.3.0", 168 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", 169 | "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", 170 | "dev": true 171 | }, 172 | "bytes": { 173 | "version": "3.0.0", 174 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 175 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", 176 | "dev": true 177 | }, 178 | "chai": { 179 | "version": "3.5.0", 180 | "resolved": "http://registry.npmjs.org/chai/-/chai-3.5.0.tgz", 181 | "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", 182 | "dev": true, 183 | "requires": { 184 | "assertion-error": "^1.0.1", 185 | "deep-eql": "^0.1.3", 186 | "type-detect": "^1.0.0" 187 | } 188 | }, 189 | "combined-stream": { 190 | "version": "1.0.7", 191 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", 192 | "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", 193 | "dev": true, 194 | "requires": { 195 | "delayed-stream": "~1.0.0" 196 | } 197 | }, 198 | "commander": { 199 | "version": "2.9.0", 200 | "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz", 201 | "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", 202 | "dev": true, 203 | "requires": { 204 | "graceful-readlink": ">= 1.0.0" 205 | } 206 | }, 207 | "component-emitter": { 208 | "version": "1.2.1", 209 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", 210 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", 211 | "dev": true 212 | }, 213 | "concat-map": { 214 | "version": "0.0.1", 215 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 216 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 217 | "dev": true 218 | }, 219 | "content-disposition": { 220 | "version": "0.5.2", 221 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 222 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", 223 | "dev": true 224 | }, 225 | "content-type": { 226 | "version": "1.0.4", 227 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 228 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 229 | "dev": true 230 | }, 231 | "cookie": { 232 | "version": "0.3.1", 233 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 234 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", 235 | "dev": true 236 | }, 237 | "cookie-signature": { 238 | "version": "1.0.6", 239 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 240 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", 241 | "dev": true 242 | }, 243 | "cookiejar": { 244 | "version": "2.1.2", 245 | "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", 246 | "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", 247 | "dev": true 248 | }, 249 | "core-util-is": { 250 | "version": "1.0.2", 251 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 252 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 253 | "dev": true 254 | }, 255 | "debug": { 256 | "version": "2.6.9", 257 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 258 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 259 | "dev": true, 260 | "requires": { 261 | "ms": "2.0.0" 262 | } 263 | }, 264 | "deep-eql": { 265 | "version": "0.1.3", 266 | "resolved": "http://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", 267 | "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", 268 | "dev": true, 269 | "requires": { 270 | "type-detect": "0.1.1" 271 | }, 272 | "dependencies": { 273 | "type-detect": { 274 | "version": "0.1.1", 275 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", 276 | "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", 277 | "dev": true 278 | } 279 | } 280 | }, 281 | "delayed-stream": { 282 | "version": "1.0.0", 283 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 284 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 285 | "dev": true 286 | }, 287 | "depd": { 288 | "version": "1.1.2", 289 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 290 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", 291 | "dev": true 292 | }, 293 | "destroy": { 294 | "version": "1.0.4", 295 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 296 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", 297 | "dev": true 298 | }, 299 | "diff": { 300 | "version": "3.2.0", 301 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", 302 | "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", 303 | "dev": true 304 | }, 305 | "ee-first": { 306 | "version": "1.1.1", 307 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 308 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", 309 | "dev": true 310 | }, 311 | "encodeurl": { 312 | "version": "1.0.2", 313 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 314 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 315 | "dev": true 316 | }, 317 | "escape-html": { 318 | "version": "1.0.3", 319 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 320 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", 321 | "dev": true 322 | }, 323 | "escape-string-regexp": { 324 | "version": "1.0.5", 325 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 326 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 327 | "dev": true 328 | }, 329 | "etag": { 330 | "version": "1.8.1", 331 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 332 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", 333 | "dev": true 334 | }, 335 | "express": { 336 | "version": "4.16.4", 337 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", 338 | "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", 339 | "dev": true, 340 | "requires": { 341 | "accepts": "~1.3.5", 342 | "array-flatten": "1.1.1", 343 | "body-parser": "1.18.3", 344 | "content-disposition": "0.5.2", 345 | "content-type": "~1.0.4", 346 | "cookie": "0.3.1", 347 | "cookie-signature": "1.0.6", 348 | "debug": "2.6.9", 349 | "depd": "~1.1.2", 350 | "encodeurl": "~1.0.2", 351 | "escape-html": "~1.0.3", 352 | "etag": "~1.8.1", 353 | "finalhandler": "1.1.1", 354 | "fresh": "0.5.2", 355 | "merge-descriptors": "1.0.1", 356 | "methods": "~1.1.2", 357 | "on-finished": "~2.3.0", 358 | "parseurl": "~1.3.2", 359 | "path-to-regexp": "0.1.7", 360 | "proxy-addr": "~2.0.4", 361 | "qs": "6.5.2", 362 | "range-parser": "~1.2.0", 363 | "safe-buffer": "5.1.2", 364 | "send": "0.16.2", 365 | "serve-static": "1.13.2", 366 | "setprototypeof": "1.1.0", 367 | "statuses": "~1.4.0", 368 | "type-is": "~1.6.16", 369 | "utils-merge": "1.0.1", 370 | "vary": "~1.1.2" 371 | }, 372 | "dependencies": { 373 | "statuses": { 374 | "version": "1.4.0", 375 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 376 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", 377 | "dev": true 378 | } 379 | } 380 | }, 381 | "extend": { 382 | "version": "3.0.2", 383 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 384 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 385 | "dev": true 386 | }, 387 | "finalhandler": { 388 | "version": "1.1.1", 389 | "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", 390 | "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", 391 | "dev": true, 392 | "requires": { 393 | "debug": "2.6.9", 394 | "encodeurl": "~1.0.2", 395 | "escape-html": "~1.0.3", 396 | "on-finished": "~2.3.0", 397 | "parseurl": "~1.3.2", 398 | "statuses": "~1.4.0", 399 | "unpipe": "~1.0.0" 400 | }, 401 | "dependencies": { 402 | "statuses": { 403 | "version": "1.4.0", 404 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 405 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", 406 | "dev": true 407 | } 408 | } 409 | }, 410 | "form-data": { 411 | "version": "2.3.3", 412 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 413 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 414 | "dev": true, 415 | "requires": { 416 | "asynckit": "^0.4.0", 417 | "combined-stream": "^1.0.6", 418 | "mime-types": "^2.1.12" 419 | } 420 | }, 421 | "formidable": { 422 | "version": "1.2.1", 423 | "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", 424 | "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==", 425 | "dev": true 426 | }, 427 | "forwarded": { 428 | "version": "0.1.2", 429 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 430 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", 431 | "dev": true 432 | }, 433 | "fresh": { 434 | "version": "0.5.2", 435 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 436 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", 437 | "dev": true 438 | }, 439 | "fs.realpath": { 440 | "version": "1.0.0", 441 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 442 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 443 | "dev": true 444 | }, 445 | "glob": { 446 | "version": "7.1.1", 447 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", 448 | "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", 449 | "dev": true, 450 | "requires": { 451 | "fs.realpath": "^1.0.0", 452 | "inflight": "^1.0.4", 453 | "inherits": "2", 454 | "minimatch": "^3.0.2", 455 | "once": "^1.3.0", 456 | "path-is-absolute": "^1.0.0" 457 | } 458 | }, 459 | "graceful-readlink": { 460 | "version": "1.0.1", 461 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 462 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", 463 | "dev": true 464 | }, 465 | "graphql": { 466 | "version": "15.5.0", 467 | "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.5.0.tgz", 468 | "integrity": "sha512-OmaM7y0kaK31NKG31q4YbD2beNYa6jBBKtMFT6gLYJljHLJr42IqJ8KX08u3Li/0ifzTU5HjmoOOrwa5BRLeDA==", 469 | "dev": true 470 | }, 471 | "graphql-server-core": { 472 | "version": "0.6.0", 473 | "resolved": "https://registry.npmjs.org/graphql-server-core/-/graphql-server-core-0.6.0.tgz", 474 | "integrity": "sha1-RoYly6SgD4AnXAZUMvqkgZhfWmU=", 475 | "dev": true, 476 | "requires": { 477 | "@types/graphql": "^0.8.5" 478 | } 479 | }, 480 | "graphql-server-express": { 481 | "version": "0.6.0", 482 | "resolved": "https://registry.npmjs.org/graphql-server-express/-/graphql-server-express-0.6.0.tgz", 483 | "integrity": "sha1-UWCQtK3YLm7SxKcN0tklAx/cwok=", 484 | "dev": true, 485 | "requires": { 486 | "@types/express": "^4.0.35", 487 | "@types/graphql": "^0.8.6", 488 | "graphql-server-core": "^0.6.0", 489 | "graphql-server-module-graphiql": "^0.6.0" 490 | } 491 | }, 492 | "graphql-server-module-graphiql": { 493 | "version": "0.6.0", 494 | "resolved": "https://registry.npmjs.org/graphql-server-module-graphiql/-/graphql-server-module-graphiql-0.6.0.tgz", 495 | "integrity": "sha1-43Y0sF8ABzGYHo7RMQP5pYYeXaA=", 496 | "dev": true 497 | }, 498 | "growl": { 499 | "version": "1.9.2", 500 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", 501 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", 502 | "dev": true 503 | }, 504 | "has-flag": { 505 | "version": "1.0.0", 506 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", 507 | "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", 508 | "dev": true 509 | }, 510 | "he": { 511 | "version": "1.1.1", 512 | "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", 513 | "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", 514 | "dev": true 515 | }, 516 | "http-errors": { 517 | "version": "1.6.3", 518 | "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", 519 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", 520 | "dev": true, 521 | "requires": { 522 | "depd": "~1.1.2", 523 | "inherits": "2.0.3", 524 | "setprototypeof": "1.1.0", 525 | "statuses": ">= 1.4.0 < 2" 526 | } 527 | }, 528 | "iconv-lite": { 529 | "version": "0.4.23", 530 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", 531 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", 532 | "dev": true, 533 | "requires": { 534 | "safer-buffer": ">= 2.1.2 < 3" 535 | } 536 | }, 537 | "inflight": { 538 | "version": "1.0.6", 539 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 540 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 541 | "dev": true, 542 | "requires": { 543 | "once": "^1.3.0", 544 | "wrappy": "1" 545 | } 546 | }, 547 | "inherits": { 548 | "version": "2.0.3", 549 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 550 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 551 | "dev": true 552 | }, 553 | "ipaddr.js": { 554 | "version": "1.8.0", 555 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", 556 | "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", 557 | "dev": true 558 | }, 559 | "isarray": { 560 | "version": "1.0.0", 561 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 562 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 563 | "dev": true 564 | }, 565 | "json3": { 566 | "version": "3.3.2", 567 | "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", 568 | "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", 569 | "dev": true 570 | }, 571 | "lodash._baseassign": { 572 | "version": "3.2.0", 573 | "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", 574 | "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", 575 | "dev": true, 576 | "requires": { 577 | "lodash._basecopy": "^3.0.0", 578 | "lodash.keys": "^3.0.0" 579 | } 580 | }, 581 | "lodash._basecopy": { 582 | "version": "3.0.1", 583 | "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", 584 | "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", 585 | "dev": true 586 | }, 587 | "lodash._basecreate": { 588 | "version": "3.0.3", 589 | "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", 590 | "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", 591 | "dev": true 592 | }, 593 | "lodash._getnative": { 594 | "version": "3.9.1", 595 | "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", 596 | "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", 597 | "dev": true 598 | }, 599 | "lodash._isiterateecall": { 600 | "version": "3.0.9", 601 | "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", 602 | "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", 603 | "dev": true 604 | }, 605 | "lodash.create": { 606 | "version": "3.1.1", 607 | "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", 608 | "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", 609 | "dev": true, 610 | "requires": { 611 | "lodash._baseassign": "^3.0.0", 612 | "lodash._basecreate": "^3.0.0", 613 | "lodash._isiterateecall": "^3.0.0" 614 | } 615 | }, 616 | "lodash.isarguments": { 617 | "version": "3.1.0", 618 | "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", 619 | "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", 620 | "dev": true 621 | }, 622 | "lodash.isarray": { 623 | "version": "3.0.4", 624 | "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", 625 | "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", 626 | "dev": true 627 | }, 628 | "lodash.keys": { 629 | "version": "3.1.2", 630 | "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", 631 | "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", 632 | "dev": true, 633 | "requires": { 634 | "lodash._getnative": "^3.0.0", 635 | "lodash.isarguments": "^3.0.0", 636 | "lodash.isarray": "^3.0.0" 637 | } 638 | }, 639 | "media-typer": { 640 | "version": "0.3.0", 641 | "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 642 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", 643 | "dev": true 644 | }, 645 | "merge-descriptors": { 646 | "version": "1.0.1", 647 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 648 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", 649 | "dev": true 650 | }, 651 | "methods": { 652 | "version": "1.1.2", 653 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 654 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", 655 | "dev": true 656 | }, 657 | "mime": { 658 | "version": "1.4.1", 659 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", 660 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", 661 | "dev": true 662 | }, 663 | "mime-db": { 664 | "version": "1.37.0", 665 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", 666 | "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", 667 | "dev": true 668 | }, 669 | "mime-types": { 670 | "version": "2.1.21", 671 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", 672 | "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", 673 | "dev": true, 674 | "requires": { 675 | "mime-db": "~1.37.0" 676 | } 677 | }, 678 | "minimatch": { 679 | "version": "3.0.4", 680 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 681 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 682 | "dev": true, 683 | "requires": { 684 | "brace-expansion": "^1.1.7" 685 | } 686 | }, 687 | "minimist": { 688 | "version": "0.0.8", 689 | "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 690 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 691 | "dev": true 692 | }, 693 | "mkdirp": { 694 | "version": "0.5.1", 695 | "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 696 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 697 | "dev": true, 698 | "requires": { 699 | "minimist": "0.0.8" 700 | } 701 | }, 702 | "mocha": { 703 | "version": "3.5.3", 704 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", 705 | "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", 706 | "dev": true, 707 | "requires": { 708 | "browser-stdout": "1.3.0", 709 | "commander": "2.9.0", 710 | "debug": "2.6.8", 711 | "diff": "3.2.0", 712 | "escape-string-regexp": "1.0.5", 713 | "glob": "7.1.1", 714 | "growl": "1.9.2", 715 | "he": "1.1.1", 716 | "json3": "3.3.2", 717 | "lodash.create": "3.1.1", 718 | "mkdirp": "0.5.1", 719 | "supports-color": "3.1.2" 720 | }, 721 | "dependencies": { 722 | "debug": { 723 | "version": "2.6.8", 724 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", 725 | "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", 726 | "dev": true, 727 | "requires": { 728 | "ms": "2.0.0" 729 | } 730 | } 731 | } 732 | }, 733 | "ms": { 734 | "version": "2.0.0", 735 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 736 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 737 | "dev": true 738 | }, 739 | "negotiator": { 740 | "version": "0.6.1", 741 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 742 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", 743 | "dev": true 744 | }, 745 | "on-finished": { 746 | "version": "2.3.0", 747 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 748 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 749 | "dev": true, 750 | "requires": { 751 | "ee-first": "1.1.1" 752 | } 753 | }, 754 | "once": { 755 | "version": "1.4.0", 756 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 757 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 758 | "dev": true, 759 | "requires": { 760 | "wrappy": "1" 761 | } 762 | }, 763 | "parseurl": { 764 | "version": "1.3.2", 765 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 766 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", 767 | "dev": true 768 | }, 769 | "path-is-absolute": { 770 | "version": "1.0.1", 771 | "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 772 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 773 | "dev": true 774 | }, 775 | "path-to-regexp": { 776 | "version": "0.1.7", 777 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 778 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", 779 | "dev": true 780 | }, 781 | "process-nextick-args": { 782 | "version": "2.0.0", 783 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 784 | "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", 785 | "dev": true 786 | }, 787 | "proxy-addr": { 788 | "version": "2.0.4", 789 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", 790 | "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", 791 | "dev": true, 792 | "requires": { 793 | "forwarded": "~0.1.2", 794 | "ipaddr.js": "1.8.0" 795 | } 796 | }, 797 | "qs": { 798 | "version": "6.5.2", 799 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 800 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", 801 | "dev": true 802 | }, 803 | "range-parser": { 804 | "version": "1.2.0", 805 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 806 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", 807 | "dev": true 808 | }, 809 | "raw-body": { 810 | "version": "2.3.3", 811 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", 812 | "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", 813 | "dev": true, 814 | "requires": { 815 | "bytes": "3.0.0", 816 | "http-errors": "1.6.3", 817 | "iconv-lite": "0.4.23", 818 | "unpipe": "1.0.0" 819 | } 820 | }, 821 | "readable-stream": { 822 | "version": "2.3.6", 823 | "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 824 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 825 | "dev": true, 826 | "requires": { 827 | "core-util-is": "~1.0.0", 828 | "inherits": "~2.0.3", 829 | "isarray": "~1.0.0", 830 | "process-nextick-args": "~2.0.0", 831 | "safe-buffer": "~5.1.1", 832 | "string_decoder": "~1.1.1", 833 | "util-deprecate": "~1.0.1" 834 | } 835 | }, 836 | "safe-buffer": { 837 | "version": "5.1.2", 838 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 839 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 840 | "dev": true 841 | }, 842 | "safer-buffer": { 843 | "version": "2.1.2", 844 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 845 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 846 | "dev": true 847 | }, 848 | "send": { 849 | "version": "0.16.2", 850 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", 851 | "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", 852 | "dev": true, 853 | "requires": { 854 | "debug": "2.6.9", 855 | "depd": "~1.1.2", 856 | "destroy": "~1.0.4", 857 | "encodeurl": "~1.0.2", 858 | "escape-html": "~1.0.3", 859 | "etag": "~1.8.1", 860 | "fresh": "0.5.2", 861 | "http-errors": "~1.6.2", 862 | "mime": "1.4.1", 863 | "ms": "2.0.0", 864 | "on-finished": "~2.3.0", 865 | "range-parser": "~1.2.0", 866 | "statuses": "~1.4.0" 867 | }, 868 | "dependencies": { 869 | "statuses": { 870 | "version": "1.4.0", 871 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 872 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", 873 | "dev": true 874 | } 875 | } 876 | }, 877 | "serve-static": { 878 | "version": "1.13.2", 879 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", 880 | "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", 881 | "dev": true, 882 | "requires": { 883 | "encodeurl": "~1.0.2", 884 | "escape-html": "~1.0.3", 885 | "parseurl": "~1.3.2", 886 | "send": "0.16.2" 887 | } 888 | }, 889 | "setprototypeof": { 890 | "version": "1.1.0", 891 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 892 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", 893 | "dev": true 894 | }, 895 | "statuses": { 896 | "version": "1.5.0", 897 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 898 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", 899 | "dev": true 900 | }, 901 | "string_decoder": { 902 | "version": "1.1.1", 903 | "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 904 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 905 | "dev": true, 906 | "requires": { 907 | "safe-buffer": "~5.1.0" 908 | } 909 | }, 910 | "superagent": { 911 | "version": "3.8.3", 912 | "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", 913 | "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", 914 | "dev": true, 915 | "requires": { 916 | "component-emitter": "^1.2.0", 917 | "cookiejar": "^2.1.0", 918 | "debug": "^3.1.0", 919 | "extend": "^3.0.0", 920 | "form-data": "^2.3.1", 921 | "formidable": "^1.2.0", 922 | "methods": "^1.1.1", 923 | "mime": "^1.4.1", 924 | "qs": "^6.5.1", 925 | "readable-stream": "^2.3.5" 926 | }, 927 | "dependencies": { 928 | "debug": { 929 | "version": "3.2.6", 930 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 931 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 932 | "dev": true, 933 | "requires": { 934 | "ms": "^2.1.1" 935 | } 936 | }, 937 | "ms": { 938 | "version": "2.1.1", 939 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 940 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", 941 | "dev": true 942 | } 943 | } 944 | }, 945 | "supertest": { 946 | "version": "3.3.0", 947 | "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.3.0.tgz", 948 | "integrity": "sha512-dMQSzYdaZRSANH5LL8kX3UpgK9G1LRh/jnggs/TI0W2Sz7rkMx9Y48uia3K9NgcaWEV28tYkBnXE4tiFC77ygQ==", 949 | "dev": true, 950 | "requires": { 951 | "methods": "^1.1.2", 952 | "superagent": "^3.8.3" 953 | } 954 | }, 955 | "supertest-as-promised": { 956 | "version": "4.0.2", 957 | "resolved": "https://registry.npmjs.org/supertest-as-promised/-/supertest-as-promised-4.0.2.tgz", 958 | "integrity": "sha1-BGTyvSVlaNSlm86EJpwFSPaHnxo=", 959 | "dev": true, 960 | "requires": { 961 | "bluebird": "^3.3.1", 962 | "methods": "^1.1.1" 963 | } 964 | }, 965 | "supports-color": { 966 | "version": "3.1.2", 967 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", 968 | "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", 969 | "dev": true, 970 | "requires": { 971 | "has-flag": "^1.0.0" 972 | } 973 | }, 974 | "type-detect": { 975 | "version": "1.0.0", 976 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", 977 | "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", 978 | "dev": true 979 | }, 980 | "type-is": { 981 | "version": "1.6.16", 982 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", 983 | "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", 984 | "dev": true, 985 | "requires": { 986 | "media-typer": "0.3.0", 987 | "mime-types": "~2.1.18" 988 | } 989 | }, 990 | "unpipe": { 991 | "version": "1.0.0", 992 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 993 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 994 | "dev": true 995 | }, 996 | "util-deprecate": { 997 | "version": "1.0.2", 998 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 999 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 1000 | "dev": true 1001 | }, 1002 | "utils-merge": { 1003 | "version": "1.0.1", 1004 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1005 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", 1006 | "dev": true 1007 | }, 1008 | "vary": { 1009 | "version": "1.1.2", 1010 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1011 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", 1012 | "dev": true 1013 | }, 1014 | "wrappy": { 1015 | "version": "1.0.2", 1016 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1017 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1018 | "dev": true 1019 | } 1020 | } 1021 | } 1022 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-disable-introspection", 3 | "version": "1.2.0", 4 | "description": "Disable introspection in graphql-js with a validation rule", 5 | "main": "index.js", 6 | "directories": { 7 | "doc": "docs", 8 | "test": "tests" 9 | }, 10 | "scripts": { 11 | "test": "mocha test.js" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/helfer/graphql-disable-introspection.git" 16 | }, 17 | "keywords": [ 18 | "GraphQL", 19 | "Introspection", 20 | "Node", 21 | "disable", 22 | "query", 23 | "validation", 24 | "rule" 25 | ], 26 | "author": "Jonas Helfer ", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/helfer/graphql-disable-introspection/issues" 30 | }, 31 | "homepage": "https://github.com/helfer/graphql-disable-introspection#readme", 32 | "devDependencies": { 33 | "body-parser": "^1.17.1", 34 | "chai": "^3.5.0", 35 | "express": "^4.15.2", 36 | "graphql": "^15.0.0", 37 | "graphql-server-express": "^0.6.0", 38 | "mocha": "^3.2.0", 39 | "supertest": "^3.0.0", 40 | "supertest-as-promised": "^4.0.2" 41 | }, 42 | "peerDependencies": { 43 | "graphql": "^0.9.2 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var graphql = require('graphql'); 2 | var noIntrospection = require('./index'); 3 | var expect = require('chai').expect; 4 | var express = require('express'); 5 | var request = require('supertest-as-promised'); 6 | var graphqlExpress = require('graphql-server-express').graphqlExpress; 7 | var bodyParser = require('body-parser'); 8 | 9 | var schema = new graphql.GraphQLSchema({ 10 | query: new graphql.GraphQLObjectType({ 11 | name: 'Query', 12 | fields: { 13 | hello: { 14 | type: graphql.GraphQLString, 15 | resolve() { 16 | return Promise.resolve('world'); 17 | } 18 | } 19 | } 20 | }) 21 | }); 22 | 23 | describe('NoIntrospection validation rule', function(){ 24 | 25 | it('disallows queries with __schema', function(){ 26 | var query = graphql.parse('{ __schema { queryType { name } } }'); 27 | var validationErrors = graphql.validate(schema, query, [noIntrospection]); 28 | return expect(validationErrors[0].message).to.match(/introspection is not allowed/); 29 | }); 30 | 31 | it('disallows queries with __type', function(){ 32 | var query = graphql.parse('{ __type(name: "Query"){ name } }'); 33 | var validationErrors = graphql.validate(schema, query, [noIntrospection]); 34 | return expect(validationErrors[0].message).to.match(/introspection is not allowed/); 35 | }); 36 | 37 | it('allows valid queries that do not contain __schema or __type', function(){ 38 | var query = graphql.parse('{ hello }'); 39 | var validationErrors = graphql.validate(schema, query, [noIntrospection]); 40 | return expect(validationErrors.length).to.equal(0); 41 | }); 42 | 43 | describe('works with graphql-server-express', function() { 44 | var app = express(); 45 | app.use('/graphql', 46 | bodyParser.json(), 47 | graphqlExpress({ schema: schema, validationRules: [noIntrospection] }) 48 | ); 49 | 50 | it('disables introspection using __schema', function() { 51 | var req = request(app) 52 | .post('/graphql') 53 | .send({ 54 | query: '{ __schema { queryType { name } } }' 55 | }); 56 | 57 | return req.then( function(result) { 58 | return expect(result.body.errors[0].message).to.match(/introspection is not allowed/); 59 | }); 60 | }); 61 | 62 | it('disables introspection using __type', function() { 63 | var req = request(app) 64 | .post('/graphql') 65 | .send({ 66 | query: '{ __type(name: "Query") { name } }' 67 | }); 68 | 69 | return req.then( function(result) { 70 | return expect(result.body.errors[0].message).to.match(/introspection is not allowed/); 71 | }); 72 | }); 73 | 74 | it('allows other valid queries through', function() { 75 | var req = request(app) 76 | .post('/graphql') 77 | .send({ 78 | query: '{ hello }' 79 | }); 80 | 81 | return req.then( function(result) { 82 | return expect(result.body).to.deep.equal({ data: { hello: 'world' } }); 83 | }); 84 | }); 85 | 86 | }); 87 | }); 88 | 89 | 90 | --------------------------------------------------------------------------------