"
+ ],
+ "license": "MIT",
+ "repository": "jonathanong/ee-first",
+ "devDependencies": {
+ "istanbul": "0.3.9",
+ "mocha": "2.2.5"
+ },
+ "files": [
+ "index.js",
+ "LICENSE"
+ ],
+ "scripts": {
+ "test": "mocha --reporter spec --bail --check-leaks test/",
+ "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
+ "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
+ }
+}
diff --git a/node_modules/encodeurl/HISTORY.md b/node_modules/encodeurl/HISTORY.md
new file mode 100644
index 00000000..41313b2b
--- /dev/null
+++ b/node_modules/encodeurl/HISTORY.md
@@ -0,0 +1,14 @@
+1.0.2 / 2018-01-21
+==================
+
+ * Fix encoding `%` as last character
+
+1.0.1 / 2016-06-09
+==================
+
+ * Fix encoding unpaired surrogates at start/end of string
+
+1.0.0 / 2016-06-08
+==================
+
+ * Initial release
diff --git a/node_modules/encodeurl/LICENSE b/node_modules/encodeurl/LICENSE
new file mode 100644
index 00000000..8812229b
--- /dev/null
+++ b/node_modules/encodeurl/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2016 Douglas Christopher Wilson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/encodeurl/README.md b/node_modules/encodeurl/README.md
new file mode 100644
index 00000000..127c5a0d
--- /dev/null
+++ b/node_modules/encodeurl/README.md
@@ -0,0 +1,128 @@
+# encodeurl
+
+[![NPM Version][npm-image]][npm-url]
+[![NPM Downloads][downloads-image]][downloads-url]
+[![Node.js Version][node-version-image]][node-version-url]
+[![Build Status][travis-image]][travis-url]
+[![Test Coverage][coveralls-image]][coveralls-url]
+
+Encode a URL to a percent-encoded form, excluding already-encoded sequences
+
+## Installation
+
+This is a [Node.js](https://nodejs.org/en/) module available through the
+[npm registry](https://www.npmjs.com/). Installation is done using the
+[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
+
+```sh
+$ npm install encodeurl
+```
+
+## API
+
+```js
+var encodeUrl = require('encodeurl')
+```
+
+### encodeUrl(url)
+
+Encode a URL to a percent-encoded form, excluding already-encoded sequences.
+
+This function will take an already-encoded URL and encode all the non-URL
+code points (as UTF-8 byte sequences). This function will not encode the
+"%" character unless it is not part of a valid sequence (`%20` will be
+left as-is, but `%foo` will be encoded as `%25foo`).
+
+This encode is meant to be "safe" and does not throw errors. It will try as
+hard as it can to properly encode the given URL, including replacing any raw,
+unpaired surrogate pairs with the Unicode replacement character prior to
+encoding.
+
+This function is _similar_ to the intrinsic function `encodeURI`, except it
+will not encode the `%` character if that is part of a valid sequence, will
+not encode `[` and `]` (for IPv6 hostnames) and will replace raw, unpaired
+surrogate pairs with the Unicode replacement character (instead of throwing).
+
+## Examples
+
+### Encode a URL containing user-controled data
+
+```js
+var encodeUrl = require('encodeurl')
+var escapeHtml = require('escape-html')
+
+http.createServer(function onRequest (req, res) {
+ // get encoded form of inbound url
+ var url = encodeUrl(req.url)
+
+ // create html message
+ var body = 'Location ' + escapeHtml(url) + ' not found
'
+
+ // send a 404
+ res.statusCode = 404
+ res.setHeader('Content-Type', 'text/html; charset=UTF-8')
+ res.setHeader('Content-Length', String(Buffer.byteLength(body, 'utf-8')))
+ res.end(body, 'utf-8')
+})
+```
+
+### Encode a URL for use in a header field
+
+```js
+var encodeUrl = require('encodeurl')
+var escapeHtml = require('escape-html')
+var url = require('url')
+
+http.createServer(function onRequest (req, res) {
+ // parse inbound url
+ var href = url.parse(req)
+
+ // set new host for redirect
+ href.host = 'localhost'
+ href.protocol = 'https:'
+ href.slashes = true
+
+ // create location header
+ var location = encodeUrl(url.format(href))
+
+ // create html message
+ var body = 'Redirecting to new site: ' + escapeHtml(location) + '
'
+
+ // send a 301
+ res.statusCode = 301
+ res.setHeader('Content-Type', 'text/html; charset=UTF-8')
+ res.setHeader('Content-Length', String(Buffer.byteLength(body, 'utf-8')))
+ res.setHeader('Location', location)
+ res.end(body, 'utf-8')
+})
+```
+
+## Testing
+
+```sh
+$ npm test
+$ npm run lint
+```
+
+## References
+
+- [RFC 3986: Uniform Resource Identifier (URI): Generic Syntax][rfc-3986]
+- [WHATWG URL Living Standard][whatwg-url]
+
+[rfc-3986]: https://tools.ietf.org/html/rfc3986
+[whatwg-url]: https://url.spec.whatwg.org/
+
+## License
+
+[MIT](LICENSE)
+
+[npm-image]: https://img.shields.io/npm/v/encodeurl.svg
+[npm-url]: https://npmjs.org/package/encodeurl
+[node-version-image]: https://img.shields.io/node/v/encodeurl.svg
+[node-version-url]: https://nodejs.org/en/download
+[travis-image]: https://img.shields.io/travis/pillarjs/encodeurl.svg
+[travis-url]: https://travis-ci.org/pillarjs/encodeurl
+[coveralls-image]: https://img.shields.io/coveralls/pillarjs/encodeurl.svg
+[coveralls-url]: https://coveralls.io/r/pillarjs/encodeurl?branch=master
+[downloads-image]: https://img.shields.io/npm/dm/encodeurl.svg
+[downloads-url]: https://npmjs.org/package/encodeurl
diff --git a/node_modules/encodeurl/index.js b/node_modules/encodeurl/index.js
new file mode 100644
index 00000000..fc4906c6
--- /dev/null
+++ b/node_modules/encodeurl/index.js
@@ -0,0 +1,60 @@
+/*!
+ * encodeurl
+ * Copyright(c) 2016 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict'
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = encodeUrl
+
+/**
+ * RegExp to match non-URL code points, *after* encoding (i.e. not including "%")
+ * and including invalid escape sequences.
+ * @private
+ */
+
+var ENCODE_CHARS_REGEXP = /(?:[^\x21\x25\x26-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E]|%(?:[^0-9A-Fa-f]|[0-9A-Fa-f][^0-9A-Fa-f]|$))+/g
+
+/**
+ * RegExp to match unmatched surrogate pair.
+ * @private
+ */
+
+var UNMATCHED_SURROGATE_PAIR_REGEXP = /(^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF]([^\uDC00-\uDFFF]|$)/g
+
+/**
+ * String to replace unmatched surrogate pair with.
+ * @private
+ */
+
+var UNMATCHED_SURROGATE_PAIR_REPLACE = '$1\uFFFD$2'
+
+/**
+ * Encode a URL to a percent-encoded form, excluding already-encoded sequences.
+ *
+ * This function will take an already-encoded URL and encode all the non-URL
+ * code points. This function will not encode the "%" character unless it is
+ * not part of a valid sequence (`%20` will be left as-is, but `%foo` will
+ * be encoded as `%25foo`).
+ *
+ * This encode is meant to be "safe" and does not throw errors. It will try as
+ * hard as it can to properly encode the given URL, including replacing any raw,
+ * unpaired surrogate pairs with the Unicode replacement character prior to
+ * encoding.
+ *
+ * @param {string} url
+ * @return {string}
+ * @public
+ */
+
+function encodeUrl (url) {
+ return String(url)
+ .replace(UNMATCHED_SURROGATE_PAIR_REGEXP, UNMATCHED_SURROGATE_PAIR_REPLACE)
+ .replace(ENCODE_CHARS_REGEXP, encodeURI)
+}
diff --git a/node_modules/encodeurl/package.json b/node_modules/encodeurl/package.json
new file mode 100644
index 00000000..b9f25ef1
--- /dev/null
+++ b/node_modules/encodeurl/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "encodeurl",
+ "description": "Encode a URL to a percent-encoded form, excluding already-encoded sequences",
+ "version": "1.0.2",
+ "contributors": [
+ "Douglas Christopher Wilson "
+ ],
+ "license": "MIT",
+ "keywords": [
+ "encode",
+ "encodeurl",
+ "url"
+ ],
+ "repository": "pillarjs/encodeurl",
+ "devDependencies": {
+ "eslint": "3.19.0",
+ "eslint-config-standard": "10.2.1",
+ "eslint-plugin-import": "2.8.0",
+ "eslint-plugin-node": "5.2.1",
+ "eslint-plugin-promise": "3.6.0",
+ "eslint-plugin-standard": "3.0.1",
+ "istanbul": "0.4.5",
+ "mocha": "2.5.3"
+ },
+ "files": [
+ "LICENSE",
+ "HISTORY.md",
+ "README.md",
+ "index.js"
+ ],
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "scripts": {
+ "lint": "eslint .",
+ "test": "mocha --reporter spec --bail --check-leaks test/",
+ "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
+ "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
+ }
+}
diff --git a/node_modules/escape-html/LICENSE b/node_modules/escape-html/LICENSE
new file mode 100644
index 00000000..2e70de97
--- /dev/null
+++ b/node_modules/escape-html/LICENSE
@@ -0,0 +1,24 @@
+(The MIT License)
+
+Copyright (c) 2012-2013 TJ Holowaychuk
+Copyright (c) 2015 Andreas Lubbe
+Copyright (c) 2015 Tiancheng "Timothy" Gu
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/escape-html/Readme.md b/node_modules/escape-html/Readme.md
new file mode 100644
index 00000000..653d9eaa
--- /dev/null
+++ b/node_modules/escape-html/Readme.md
@@ -0,0 +1,43 @@
+
+# escape-html
+
+ Escape string for use in HTML
+
+## Example
+
+```js
+var escape = require('escape-html');
+var html = escape('foo & bar');
+// -> foo & bar
+```
+
+## Benchmark
+
+```
+$ npm run-script bench
+
+> escape-html@1.0.3 bench nodejs-escape-html
+> node benchmark/index.js
+
+
+ http_parser@1.0
+ node@0.10.33
+ v8@3.14.5.9
+ ares@1.9.0-DEV
+ uv@0.10.29
+ zlib@1.2.3
+ modules@11
+ openssl@1.0.1j
+
+ 1 test completed.
+ 2 tests completed.
+ 3 tests completed.
+
+ no special characters x 19,435,271 ops/sec ±0.85% (187 runs sampled)
+ single special character x 6,132,421 ops/sec ±0.67% (194 runs sampled)
+ many special characters x 3,175,826 ops/sec ±0.65% (193 runs sampled)
+```
+
+## License
+
+ MIT
\ No newline at end of file
diff --git a/node_modules/escape-html/index.js b/node_modules/escape-html/index.js
new file mode 100644
index 00000000..bf9e226f
--- /dev/null
+++ b/node_modules/escape-html/index.js
@@ -0,0 +1,78 @@
+/*!
+ * escape-html
+ * Copyright(c) 2012-2013 TJ Holowaychuk
+ * Copyright(c) 2015 Andreas Lubbe
+ * Copyright(c) 2015 Tiancheng "Timothy" Gu
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Module variables.
+ * @private
+ */
+
+var matchHtmlRegExp = /["'&<>]/;
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = escapeHtml;
+
+/**
+ * Escape special characters in the given string of html.
+ *
+ * @param {string} string The string to escape for inserting into HTML
+ * @return {string}
+ * @public
+ */
+
+function escapeHtml(string) {
+ var str = '' + string;
+ var match = matchHtmlRegExp.exec(str);
+
+ if (!match) {
+ return str;
+ }
+
+ var escape;
+ var html = '';
+ var index = 0;
+ var lastIndex = 0;
+
+ for (index = match.index; index < str.length; index++) {
+ switch (str.charCodeAt(index)) {
+ case 34: // "
+ escape = '"';
+ break;
+ case 38: // &
+ escape = '&';
+ break;
+ case 39: // '
+ escape = ''';
+ break;
+ case 60: // <
+ escape = '<';
+ break;
+ case 62: // >
+ escape = '>';
+ break;
+ default:
+ continue;
+ }
+
+ if (lastIndex !== index) {
+ html += str.substring(lastIndex, index);
+ }
+
+ lastIndex = index + 1;
+ html += escape;
+ }
+
+ return lastIndex !== index
+ ? html + str.substring(lastIndex, index)
+ : html;
+}
diff --git a/node_modules/escape-html/package.json b/node_modules/escape-html/package.json
new file mode 100644
index 00000000..57ec7bd0
--- /dev/null
+++ b/node_modules/escape-html/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "escape-html",
+ "description": "Escape string for use in HTML",
+ "version": "1.0.3",
+ "license": "MIT",
+ "keywords": [
+ "escape",
+ "html",
+ "utility"
+ ],
+ "repository": "component/escape-html",
+ "devDependencies": {
+ "benchmark": "1.0.0",
+ "beautify-benchmark": "0.2.4"
+ },
+ "files": [
+ "LICENSE",
+ "Readme.md",
+ "index.js"
+ ],
+ "scripts": {
+ "bench": "node benchmark/index.js"
+ }
+}
diff --git a/node_modules/etag/HISTORY.md b/node_modules/etag/HISTORY.md
new file mode 100644
index 00000000..222b293d
--- /dev/null
+++ b/node_modules/etag/HISTORY.md
@@ -0,0 +1,83 @@
+1.8.1 / 2017-09-12
+==================
+
+ * perf: replace regular expression with substring
+
+1.8.0 / 2017-02-18
+==================
+
+ * Use SHA1 instead of MD5 for ETag hashing
+ - Improves performance for larger entities
+ - Works with FIPS 140-2 OpenSSL configuration
+
+1.7.0 / 2015-06-08
+==================
+
+ * Always include entity length in ETags for hash length extensions
+ * Generate non-Stats ETags using MD5 only (no longer CRC32)
+ * Improve stat performance by removing hashing
+ * Remove base64 padding in ETags to shorten
+ * Use MD5 instead of MD4 in weak ETags over 1KB
+
+1.6.0 / 2015-05-10
+==================
+
+ * Improve support for JXcore
+ * Remove requirement of `atime` in the stats object
+ * Support "fake" stats objects in environments without `fs`
+
+1.5.1 / 2014-11-19
+==================
+
+ * deps: crc@3.2.1
+ - Minor fixes
+
+1.5.0 / 2014-10-14
+==================
+
+ * Improve string performance
+ * Slightly improve speed for weak ETags over 1KB
+
+1.4.0 / 2014-09-21
+==================
+
+ * Support "fake" stats objects
+ * Support Node.js 0.6
+
+1.3.1 / 2014-09-14
+==================
+
+ * Use the (new and improved) `crc` for crc32
+
+1.3.0 / 2014-08-29
+==================
+
+ * Default strings to strong ETags
+ * Improve speed for weak ETags over 1KB
+
+1.2.1 / 2014-08-29
+==================
+
+ * Use the (much faster) `buffer-crc32` for crc32
+
+1.2.0 / 2014-08-24
+==================
+
+ * Add support for file stat objects
+
+1.1.0 / 2014-08-24
+==================
+
+ * Add fast-path for empty entity
+ * Add weak ETag generation
+ * Shrink size of generated ETags
+
+1.0.1 / 2014-08-24
+==================
+
+ * Fix behavior of string containing Unicode
+
+1.0.0 / 2014-05-18
+==================
+
+ * Initial release
diff --git a/node_modules/etag/LICENSE b/node_modules/etag/LICENSE
new file mode 100644
index 00000000..cab251c2
--- /dev/null
+++ b/node_modules/etag/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2014-2016 Douglas Christopher Wilson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/etag/README.md b/node_modules/etag/README.md
new file mode 100644
index 00000000..09c2169e
--- /dev/null
+++ b/node_modules/etag/README.md
@@ -0,0 +1,159 @@
+# etag
+
+[![NPM Version][npm-image]][npm-url]
+[![NPM Downloads][downloads-image]][downloads-url]
+[![Node.js Version][node-version-image]][node-version-url]
+[![Build Status][travis-image]][travis-url]
+[![Test Coverage][coveralls-image]][coveralls-url]
+
+Create simple HTTP ETags
+
+This module generates HTTP ETags (as defined in RFC 7232) for use in
+HTTP responses.
+
+## Installation
+
+This is a [Node.js](https://nodejs.org/en/) module available through the
+[npm registry](https://www.npmjs.com/). Installation is done using the
+[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
+
+```sh
+$ npm install etag
+```
+
+## API
+
+
+
+```js
+var etag = require('etag')
+```
+
+### etag(entity, [options])
+
+Generate a strong ETag for the given entity. This should be the complete
+body of the entity. Strings, `Buffer`s, and `fs.Stats` are accepted. By
+default, a strong ETag is generated except for `fs.Stats`, which will
+generate a weak ETag (this can be overwritten by `options.weak`).
+
+
+
+```js
+res.setHeader('ETag', etag(body))
+```
+
+#### Options
+
+`etag` accepts these properties in the options object.
+
+##### weak
+
+Specifies if the generated ETag will include the weak validator mark (that
+is, the leading `W/`). The actual entity tag is the same. The default value
+is `false`, unless the `entity` is `fs.Stats`, in which case it is `true`.
+
+## Testing
+
+```sh
+$ npm test
+```
+
+## Benchmark
+
+```bash
+$ npm run-script bench
+
+> etag@1.8.1 bench nodejs-etag
+> node benchmark/index.js
+
+ http_parser@2.7.0
+ node@6.11.1
+ v8@5.1.281.103
+ uv@1.11.0
+ zlib@1.2.11
+ ares@1.10.1-DEV
+ icu@58.2
+ modules@48
+ openssl@1.0.2k
+
+> node benchmark/body0-100b.js
+
+ 100B body
+
+ 4 tests completed.
+
+ buffer - strong x 258,647 ops/sec ±1.07% (180 runs sampled)
+ buffer - weak x 263,812 ops/sec ±0.61% (184 runs sampled)
+ string - strong x 259,955 ops/sec ±1.19% (185 runs sampled)
+ string - weak x 264,356 ops/sec ±1.09% (184 runs sampled)
+
+> node benchmark/body1-1kb.js
+
+ 1KB body
+
+ 4 tests completed.
+
+ buffer - strong x 189,018 ops/sec ±1.12% (182 runs sampled)
+ buffer - weak x 190,586 ops/sec ±0.81% (186 runs sampled)
+ string - strong x 144,272 ops/sec ±0.96% (188 runs sampled)
+ string - weak x 145,380 ops/sec ±1.43% (187 runs sampled)
+
+> node benchmark/body2-5kb.js
+
+ 5KB body
+
+ 4 tests completed.
+
+ buffer - strong x 92,435 ops/sec ±0.42% (188 runs sampled)
+ buffer - weak x 92,373 ops/sec ±0.58% (189 runs sampled)
+ string - strong x 48,850 ops/sec ±0.56% (186 runs sampled)
+ string - weak x 49,380 ops/sec ±0.56% (190 runs sampled)
+
+> node benchmark/body3-10kb.js
+
+ 10KB body
+
+ 4 tests completed.
+
+ buffer - strong x 55,989 ops/sec ±0.93% (188 runs sampled)
+ buffer - weak x 56,148 ops/sec ±0.55% (190 runs sampled)
+ string - strong x 27,345 ops/sec ±0.43% (188 runs sampled)
+ string - weak x 27,496 ops/sec ±0.45% (190 runs sampled)
+
+> node benchmark/body4-100kb.js
+
+ 100KB body
+
+ 4 tests completed.
+
+ buffer - strong x 7,083 ops/sec ±0.22% (190 runs sampled)
+ buffer - weak x 7,115 ops/sec ±0.26% (191 runs sampled)
+ string - strong x 3,068 ops/sec ±0.34% (190 runs sampled)
+ string - weak x 3,096 ops/sec ±0.35% (190 runs sampled)
+
+> node benchmark/stats.js
+
+ stat
+
+ 4 tests completed.
+
+ real - strong x 871,642 ops/sec ±0.34% (189 runs sampled)
+ real - weak x 867,613 ops/sec ±0.39% (190 runs sampled)
+ fake - strong x 401,051 ops/sec ±0.40% (189 runs sampled)
+ fake - weak x 400,100 ops/sec ±0.47% (188 runs sampled)
+```
+
+## License
+
+[MIT](LICENSE)
+
+[npm-image]: https://img.shields.io/npm/v/etag.svg
+[npm-url]: https://npmjs.org/package/etag
+[node-version-image]: https://img.shields.io/node/v/etag.svg
+[node-version-url]: https://nodejs.org/en/download/
+[travis-image]: https://img.shields.io/travis/jshttp/etag/master.svg
+[travis-url]: https://travis-ci.org/jshttp/etag
+[coveralls-image]: https://img.shields.io/coveralls/jshttp/etag/master.svg
+[coveralls-url]: https://coveralls.io/r/jshttp/etag?branch=master
+[downloads-image]: https://img.shields.io/npm/dm/etag.svg
+[downloads-url]: https://npmjs.org/package/etag
diff --git a/node_modules/etag/index.js b/node_modules/etag/index.js
new file mode 100644
index 00000000..2a585c91
--- /dev/null
+++ b/node_modules/etag/index.js
@@ -0,0 +1,131 @@
+/*!
+ * etag
+ * Copyright(c) 2014-2016 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict'
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = etag
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var crypto = require('crypto')
+var Stats = require('fs').Stats
+
+/**
+ * Module variables.
+ * @private
+ */
+
+var toString = Object.prototype.toString
+
+/**
+ * Generate an entity tag.
+ *
+ * @param {Buffer|string} entity
+ * @return {string}
+ * @private
+ */
+
+function entitytag (entity) {
+ if (entity.length === 0) {
+ // fast-path empty
+ return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"'
+ }
+
+ // compute hash of entity
+ var hash = crypto
+ .createHash('sha1')
+ .update(entity, 'utf8')
+ .digest('base64')
+ .substring(0, 27)
+
+ // compute length of entity
+ var len = typeof entity === 'string'
+ ? Buffer.byteLength(entity, 'utf8')
+ : entity.length
+
+ return '"' + len.toString(16) + '-' + hash + '"'
+}
+
+/**
+ * Create a simple ETag.
+ *
+ * @param {string|Buffer|Stats} entity
+ * @param {object} [options]
+ * @param {boolean} [options.weak]
+ * @return {String}
+ * @public
+ */
+
+function etag (entity, options) {
+ if (entity == null) {
+ throw new TypeError('argument entity is required')
+ }
+
+ // support fs.Stats object
+ var isStats = isstats(entity)
+ var weak = options && typeof options.weak === 'boolean'
+ ? options.weak
+ : isStats
+
+ // validate argument
+ if (!isStats && typeof entity !== 'string' && !Buffer.isBuffer(entity)) {
+ throw new TypeError('argument entity must be string, Buffer, or fs.Stats')
+ }
+
+ // generate entity tag
+ var tag = isStats
+ ? stattag(entity)
+ : entitytag(entity)
+
+ return weak
+ ? 'W/' + tag
+ : tag
+}
+
+/**
+ * Determine if object is a Stats object.
+ *
+ * @param {object} obj
+ * @return {boolean}
+ * @api private
+ */
+
+function isstats (obj) {
+ // genuine fs.Stats
+ if (typeof Stats === 'function' && obj instanceof Stats) {
+ return true
+ }
+
+ // quack quack
+ return obj && typeof obj === 'object' &&
+ 'ctime' in obj && toString.call(obj.ctime) === '[object Date]' &&
+ 'mtime' in obj && toString.call(obj.mtime) === '[object Date]' &&
+ 'ino' in obj && typeof obj.ino === 'number' &&
+ 'size' in obj && typeof obj.size === 'number'
+}
+
+/**
+ * Generate a tag for a stat.
+ *
+ * @param {object} stat
+ * @return {string}
+ * @private
+ */
+
+function stattag (stat) {
+ var mtime = stat.mtime.getTime().toString(16)
+ var size = stat.size.toString(16)
+
+ return '"' + size + '-' + mtime + '"'
+}
diff --git a/node_modules/etag/package.json b/node_modules/etag/package.json
new file mode 100644
index 00000000..b06ab803
--- /dev/null
+++ b/node_modules/etag/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "etag",
+ "description": "Create simple HTTP ETags",
+ "version": "1.8.1",
+ "contributors": [
+ "Douglas Christopher Wilson ",
+ "David Björklund "
+ ],
+ "license": "MIT",
+ "keywords": [
+ "etag",
+ "http",
+ "res"
+ ],
+ "repository": "jshttp/etag",
+ "devDependencies": {
+ "beautify-benchmark": "0.2.4",
+ "benchmark": "2.1.4",
+ "eslint": "3.19.0",
+ "eslint-config-standard": "10.2.1",
+ "eslint-plugin-import": "2.7.0",
+ "eslint-plugin-markdown": "1.0.0-beta.6",
+ "eslint-plugin-node": "5.1.1",
+ "eslint-plugin-promise": "3.5.0",
+ "eslint-plugin-standard": "3.0.1",
+ "istanbul": "0.4.5",
+ "mocha": "1.21.5",
+ "safe-buffer": "5.1.1",
+ "seedrandom": "2.4.3"
+ },
+ "files": [
+ "LICENSE",
+ "HISTORY.md",
+ "README.md",
+ "index.js"
+ ],
+ "engines": {
+ "node": ">= 0.6"
+ },
+ "scripts": {
+ "bench": "node benchmark/index.js",
+ "lint": "eslint --plugin markdown --ext js,md .",
+ "test": "mocha --reporter spec --bail --check-leaks test/",
+ "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
+ "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
+ }
+}
diff --git a/node_modules/express-graphql/LICENSE b/node_modules/express-graphql/LICENSE
new file mode 100644
index 00000000..51ba8841
--- /dev/null
+++ b/node_modules/express-graphql/LICENSE
@@ -0,0 +1,30 @@
+BSD License
+
+For GraphQL software
+
+Copyright (c) 2015-present, Facebook, Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name Facebook nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/node_modules/express-graphql/PATENTS b/node_modules/express-graphql/PATENTS
new file mode 100644
index 00000000..953668b0
--- /dev/null
+++ b/node_modules/express-graphql/PATENTS
@@ -0,0 +1,11 @@
+Additional Grant of Patent Rights Version 2
+
+"Software" means the GraphQL software distributed by Facebook, Inc.
+
+Facebook, Inc. (“Facebook”) hereby grants to each recipient of the Software (“you”) a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (subject to the termination provision below) license under any Necessary Claims, to make, have made, use, sell, offer to sell, import, and otherwise transfer the Software. For avoidance of doubt, no license is granted under Facebook’s rights in any patent claims that are infringed by (i) modifications to the Software made by you or any third party or (ii) the Software in combination with any software or other technology.
+
+The license granted hereunder will terminate, automatically and without notice, if you (or any of your subsidiaries, corporate affiliates or agents) initiate directly or indirectly, or take a direct financial interest in, any Patent Assertion: (i) against Facebook or any of its subsidiaries or corporate affiliates, (ii) against any party if such Patent Assertion arises in whole or in part from any software, technology, product or service of Facebook or any of its subsidiaries or corporate affiliates, or (iii) against any party relating to the Software. Notwithstanding the foregoing, if Facebook or any of its subsidiaries or corporate affiliates files a lawsuit alleging patent infringement against you in the first instance, and you respond by filing a patent infringement counterclaim in that lawsuit against that party that is unrelated to the Software, the license granted hereunder will not terminate under section (i) of this paragraph due to such counterclaim.
+
+A “Necessary Claim” is a claim of a patent owned by Facebook that is necessarily infringed by the Software standing alone.
+
+A “Patent Assertion” is any lawsuit or other action alleging direct, indirect, or contributory infringement or inducement to infringe any patent, including a cross-claim or counterclaim.
diff --git a/node_modules/express-graphql/README.md b/node_modules/express-graphql/README.md
new file mode 100644
index 00000000..7245d1e5
--- /dev/null
+++ b/node_modules/express-graphql/README.md
@@ -0,0 +1,303 @@
+GraphQL HTTP Server Middleware
+==============================
+
+[](https://travis-ci.org/graphql/express-graphql)
+[](https://coveralls.io/github/graphql/express-graphql?branch=master)
+
+Create a GraphQL HTTP server with any HTTP web framework that supports connect styled middleware, including [Connect](https://github.com/senchalabs/connect) itself, [Express](http://expressjs.com) and [Restify](http://restify.com/).
+
+## Installation
+
+```sh
+npm install --save express-graphql
+```
+
+
+## Simple Setup
+
+Just mount `express-graphql` as a route handler:
+
+```js
+const express = require('express');
+const graphqlHTTP = require('express-graphql');
+
+const app = express();
+
+app.use('/graphql', graphqlHTTP({
+ schema: MyGraphQLSchema,
+ graphiql: true
+}));
+
+app.listen(4000);
+```
+
+
+## Setup with Restify
+
+Use `.get` or `.post` (or both) rather than `.use` to configure your route handler. If you want to show GraphiQL in the browser, set `graphiql: true` on your `.get` handler.
+
+```js
+const restify = require('restify');
+const graphqlHTTP = require('express-graphql');
+
+const app = restify.createServer();
+
+app.post('/graphql', graphqlHTTP({
+ schema: MyGraphQLSchema,
+ graphiql: false
+}));
+
+app.get('/graphql', graphqlHTTP({
+ schema: MyGraphQLSchema,
+ graphiql: true
+}));
+
+app.listen(4000);
+```
+
+
+## Options
+
+The `graphqlHTTP` function accepts the following options:
+
+ * **`schema`**: A `GraphQLSchema` instance from [`GraphQL.js`][].
+ A `schema` *must* be provided.
+
+ * **`graphiql`**: If `true`, presents [GraphiQL][] when the GraphQL endpoint is
+ loaded in a browser. We recommend that you set
+ `graphiql` to `true` when your app is in development, because it's
+ quite useful. You may or may not want it in production.
+
+ * **`rootValue`**: A value to pass as the `rootValue` to the `graphql()`
+ function from [`GraphQL.js/src/execute.js`](https://github.com/graphql/graphql-js/blob/master/src/execution/execute.js#L121).
+
+ * **`context`**: A value to pass as the `context` to the `graphql()`
+ function from [`GraphQL.js/src/execute.js`](https://github.com/graphql/graphql-js/blob/master/src/execution/execute.js#L122). If `context` is not provided, the
+ `request` object is passed as the context.
+
+ * **`pretty`**: If `true`, any JSON response will be pretty-printed.
+
+ * **`formatError`**: An optional function which will be used to format any
+ errors produced by fulfilling a GraphQL operation. If no function is
+ provided, GraphQL's default spec-compliant [`formatError`][] function will be used.
+
+ * **`extensions`**: An optional function for adding additional metadata to the
+ GraphQL response as a key-value object. The result will be added to
+ `"extensions"` field in the resulting JSON. This is often a useful place to
+ add development time metadata such as the runtime of a query or the amount
+ of resources consumed. This may be an async function. The function is
+ given one object as an argument: `{ document, variables, operationName, result }`.
+
+ * **`validationRules`**: Optional additional validation rules queries must
+ satisfy in addition to those defined by the GraphQL spec.
+
+In addition to an object defining each option, options can also be provided as
+a function (or async function) which returns this options object. This function
+is provided the arguments `(request, response, graphQLParams)` and is called
+after the request has been parsed.
+
+The `graphQLParams` is provided as the object `{ query, variables, operationName, raw }`.
+
+```js
+app.use('/graphql', graphqlHTTP(async (request, response, graphQLParams) => ({
+ schema: MyGraphQLSchema,
+ rootValue: await someFunctionToGetRootValue(request)
+ graphiql: true
+})));
+```
+
+
+## HTTP Usage
+
+Once installed at a path, `express-graphql` will accept requests with
+the parameters:
+
+ * **`query`**: A string GraphQL document to be executed.
+
+ * **`variables`**: The runtime values to use for any GraphQL query variables
+ as a JSON object.
+
+ * **`operationName`**: If the provided `query` contains multiple named
+ operations, this specifies which operation should be executed. If not
+ provided, a 400 error will be returned if the `query` contains multiple
+ named operations.
+
+ * **`raw`**: If the `graphiql` option is enabled and the `raw` parameter is
+ provided raw JSON will always be returned instead of GraphiQL even when
+ loaded from a browser.
+
+GraphQL will first look for each parameter in the URL's query-string:
+
+```
+/graphql?query=query+getUser($id:ID){user(id:$id){name}}&variables={"id":"4"}
+```
+
+If not found in the query-string, it will look in the POST request body.
+
+If a previous middleware has already parsed the POST body, the `request.body`
+value will be used. Use [`multer`][] or a similar middleware to add support
+for `multipart/form-data` content, which may be useful for GraphQL mutations
+involving uploading files. See an [example using multer](https://github.com/graphql/express-graphql/blob/304b24b993c8f16fffff8d23b0fa4088e690874b/src/__tests__/http-test.js#L674-L741).
+
+If the POST body has not yet been parsed, express-graphql will interpret it
+depending on the provided *Content-Type* header.
+
+ * **`application/json`**: the POST body will be parsed as a JSON
+ object of parameters.
+
+ * **`application/x-www-form-urlencoded`**: this POST body will be
+ parsed as a url-encoded string of key-value pairs.
+
+ * **`application/graphql`**: The POST body will be parsed as GraphQL
+ query string, which provides the `query` parameter.
+
+
+## Combining with Other Express Middleware
+
+By default, the express request is passed as the GraphQL `context`.
+Since most express middleware operates by adding extra data to the
+request object, this means you can use most express middleware just by inserting it before `graphqlHTTP` is mounted. This covers scenarios such as authenticating the user, handling file uploads, or mounting GraphQL on a dynamic endpoint.
+
+This example uses [`express-session`][] to provide GraphQL with the currently logged-in session.
+
+```js
+const session = require('express-session');
+const graphqlHTTP = require('express-graphql');
+
+const app = express();
+
+app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}));
+
+app.use('/graphql', graphqlHTTP({
+ schema: MySessionAwareGraphQLSchema,
+ graphiql: true
+}));
+```
+
+Then in your type definitions, you can access the request via the third "context" argument in your `resolve` function:
+
+```js
+new GraphQLObjectType({
+ name: 'MyType',
+ fields: {
+ myField: {
+ type: GraphQLString,
+ resolve(parentValue, args, request) {
+ // use `request.session` here
+ }
+ }
+ }
+});
+```
+
+
+## Providing Extensions
+
+The GraphQL response allows for adding additional information in a response to
+a GraphQL query via a field in the response called `"extensions"`. This is added
+by providing an `extensions` function when using `graphqlHTTP`. The function
+must return a JSON-serializable Object.
+
+When called, this is provided an argument which you can use to get information
+about the GraphQL request:
+
+`{ document, variables, operationName, result }`
+
+This example illustrates adding the amount of time consumed by running the
+provided query, which could perhaps be used by your development tools.
+
+```js
+const graphqlHTTP = require('express-graphql');
+
+const app = express();
+
+app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}));
+
+app.use('/graphql', graphqlHTTP(request => {
+ const startTime = Date.now();
+ return {
+ schema: MyGraphQLSchema,
+ graphiql: true,
+ extensions({ document, variables, operationName, result }) {
+ return { runTime: Date.now() - startTime };
+ }
+ };
+}));
+```
+
+When querying this endpoint, it would include this information in the result,
+for example:
+
+```js
+{
+ "data": { ... }
+ "extensions": {
+ "runTime": 135
+ }
+}
+```
+
+
+## Additional Validation Rules
+
+GraphQL's [validation phase](https://facebook.github.io/graphql/#sec-Validation) checks the query to ensure that it can be successfully executed against the schema. The `validationRules` option allows for additional rules to be run during this phase. Rules are applied to each node in an AST representing the query using the Visitor pattern.
+
+A validation rule is a function which returns a visitor for one or more node Types. Below is an example of a validation preventing the specific fieldname `metadata` from being queried. For more examples see the [`specifiedRules`](https://github.com/graphql/graphql-js/tree/master/src/validation/rules) in the [graphql-js](https://github.com/graphql/graphql-js) package.
+
+```js
+import { GraphQLError } from 'graphql';
+
+export function DisallowMetadataQueries(context) {
+ return {
+ Field(node) {
+ const fieldName = node.name.value;
+
+ if (fieldName === "metadata") {
+ context.reportError(
+ new GraphQLError(
+ `Validation: Requesting the field ${fieldName} is not allowed`,
+ ),
+ );
+ }
+ }
+ };
+}
+```
+
+## Other Exports
+
+**`getGraphQLParams(request: Request): Promise`**
+
+Given an HTTP Request, this returns a Promise for the parameters relevant to
+running a GraphQL request. This function is used internally to handle the
+incoming request, you may use it directly for building other similar services.
+
+```js
+const graphqlHTTP = require('express-graphql');
+
+graphqlHTTP.getGraphQLParams(request).then(params => {
+ // do something...
+})
+```
+
+
+## Debugging Tips
+
+During development, it's useful to get more information from errors, such as
+stack traces. Providing a function to `formatError` enables this:
+
+```js
+formatError: error => ({
+ message: error.message,
+ locations: error.locations,
+ stack: error.stack ? error.stack.split('\n') : [],
+ path: error.path
+})
+```
+
+
+[`GraphQL.js`]: https://github.com/graphql/graphql-js
+[`formatError`]: https://github.com/graphql/graphql-js/blob/master/src/error/formatError.js
+[GraphiQL]: https://github.com/graphql/graphiql
+[`multer`]: https://github.com/expressjs/multer
+[`express-session`]: https://github.com/expressjs/session
diff --git a/node_modules/express-graphql/dist/index.js b/node_modules/express-graphql/dist/index.js
new file mode 100644
index 00000000..16fdbd98
--- /dev/null
+++ b/node_modules/express-graphql/dist/index.js
@@ -0,0 +1,299 @@
+'use strict';
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * strict
+ */
+
+var _accepts = require('accepts');
+
+var _accepts2 = _interopRequireDefault(_accepts);
+
+var _graphql = require('graphql');
+
+var _httpErrors = require('http-errors');
+
+var _httpErrors2 = _interopRequireDefault(_httpErrors);
+
+var _url = require('url');
+
+var _url2 = _interopRequireDefault(_url);
+
+var _parseBody = require('./parseBody');
+
+var _renderGraphiQL = require('./renderGraphiQL');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Middleware for express; takes an options object or function as input to
+ * configure behavior, and returns an express middleware.
+ */
+
+
+/**
+ * Used to configure the graphqlHTTP middleware by providing a schema
+ * and other configuration options.
+ *
+ * Options can be provided as an Object, a Promise for an Object, or a Function
+ * that returns an Object or a Promise for an Object.
+ */
+
+
+/**
+ * All information about a GraphQL request.
+ */
+module.exports = graphqlHTTP;
+function graphqlHTTP(options) {
+ if (!options) {
+ throw new Error('GraphQL middleware requires options.');
+ }
+
+ return function graphqlMiddleware(request, response) {
+ // Higher scoped variables are referred to at various stages in the
+ // asynchronous state machine below.
+ var params = void 0;
+ var pretty = void 0;
+ var formatErrorFn = void 0;
+ var extensionsFn = void 0;
+ var showGraphiQL = void 0;
+ var query = void 0;
+
+ var documentAST = void 0;
+ var variables = void 0;
+ var operationName = void 0;
+
+ // Promises are used as a mechanism for capturing any thrown errors during
+ // the asynchronous process below.
+
+ // Parse the Request to get GraphQL request parameters.
+ return getGraphQLParams(request).then(function (graphQLParams) {
+ params = graphQLParams;
+ // Then, resolve the Options to get OptionsData.
+ return typeof options === 'function' ? options(request, response, params) : options;
+ }).then(function (optionsData) {
+ // Assert that optionsData is in fact an Object.
+ if (!optionsData || (typeof optionsData === 'undefined' ? 'undefined' : _typeof(optionsData)) !== 'object') {
+ throw new Error('GraphQL middleware option function must return an options object ' + 'or a promise which will be resolved to an options object.');
+ }
+
+ // Assert that schema is required.
+ if (!optionsData.schema) {
+ throw new Error('GraphQL middleware options must contain a schema.');
+ }
+
+ // Collect information from the options data object.
+ var schema = optionsData.schema;
+ var context = optionsData.context || request;
+ var rootValue = optionsData.rootValue;
+ var graphiql = optionsData.graphiql;
+ pretty = optionsData.pretty;
+ formatErrorFn = optionsData.formatError;
+ extensionsFn = optionsData.extensions;
+
+ var validationRules = _graphql.specifiedRules;
+ if (optionsData.validationRules) {
+ validationRules = validationRules.concat(optionsData.validationRules);
+ }
+
+ // GraphQL HTTP only supports GET and POST methods.
+ if (request.method !== 'GET' && request.method !== 'POST') {
+ response.setHeader('Allow', 'GET, POST');
+ throw (0, _httpErrors2.default)(405, 'GraphQL only supports GET and POST requests.');
+ }
+
+ // Get GraphQL params from the request and POST body data.
+ query = params.query;
+ variables = params.variables;
+ operationName = params.operationName;
+ showGraphiQL = graphiql && canDisplayGraphiQL(request, params);
+
+ // If there is no query, but GraphiQL will be displayed, do not produce
+ // a result, otherwise return a 400: Bad Request.
+ if (!query) {
+ if (showGraphiQL) {
+ return null;
+ }
+ throw (0, _httpErrors2.default)(400, 'Must provide query string.');
+ }
+
+ // GraphQL source.
+ var source = new _graphql.Source(query, 'GraphQL request');
+
+ // Parse source to AST, reporting any syntax error.
+ try {
+ documentAST = (0, _graphql.parse)(source);
+ } catch (syntaxError) {
+ // Return 400: Bad Request if any syntax errors errors exist.
+ response.statusCode = 400;
+ return { errors: [syntaxError] };
+ }
+
+ // Validate AST, reporting any errors.
+ var validationErrors = (0, _graphql.validate)(schema, documentAST, validationRules);
+ if (validationErrors.length > 0) {
+ // Return 400: Bad Request if any validation errors exist.
+ response.statusCode = 400;
+ return { errors: validationErrors };
+ }
+
+ // Only query operations are allowed on GET requests.
+ if (request.method === 'GET') {
+ // Determine if this GET request will perform a non-query.
+ var operationAST = (0, _graphql.getOperationAST)(documentAST, operationName);
+ if (operationAST && operationAST.operation !== 'query') {
+ // If GraphiQL can be shown, do not perform this query, but
+ // provide it to GraphiQL so that the requester may perform it
+ // themselves if desired.
+ if (showGraphiQL) {
+ return null;
+ }
+
+ // Otherwise, report a 405: Method Not Allowed error.
+ response.setHeader('Allow', 'POST');
+ throw (0, _httpErrors2.default)(405, 'Can only perform a ' + operationAST.operation + ' operation ' + 'from a POST request.');
+ }
+ }
+ // Perform the execution, reporting any errors creating the context.
+ try {
+ return (0, _graphql.execute)(schema, documentAST, rootValue, context, variables, operationName);
+ } catch (contextError) {
+ // Return 400: Bad Request if any execution context errors exist.
+ response.statusCode = 400;
+ return { errors: [contextError] };
+ }
+ }).then(function (result) {
+ // Collect and apply any metadata extensions if a function was provided.
+ // http://facebook.github.io/graphql/#sec-Response-Format
+ if (result && extensionsFn) {
+ return Promise.resolve(extensionsFn({
+ document: documentAST,
+ variables: variables,
+ operationName: operationName,
+ result: result
+ })).then(function (extensions) {
+ if (extensions && (typeof extensions === 'undefined' ? 'undefined' : _typeof(extensions)) === 'object') {
+ result.extensions = extensions;
+ }
+ return result;
+ });
+ }
+ return result;
+ }).catch(function (error) {
+ // If an error was caught, report the httpError status, or 500.
+ response.statusCode = error.status || 500;
+ return { errors: [error] };
+ }).then(function (result) {
+ // If no data was included in the result, that indicates a runtime query
+ // error, indicate as such with a generic status code.
+ // Note: Information about the error itself will still be contained in
+ // the resulting JSON payload.
+ // http://facebook.github.io/graphql/#sec-Data
+ if (response.statusCode === 200 && result && !result.data) {
+ response.statusCode = 500;
+ }
+ // Format any encountered errors.
+ if (result && result.errors) {
+ result.errors = result.errors.map(formatErrorFn || _graphql.formatError);
+ }
+
+ // If allowed to show GraphiQL, present it instead of JSON.
+ if (showGraphiQL) {
+ var payload = (0, _renderGraphiQL.renderGraphiQL)({
+ query: query,
+ variables: variables,
+ operationName: operationName,
+ result: result
+ });
+ return sendResponse(response, 'text/html', payload);
+ }
+
+ // At this point, result is guaranteed to exist, as the only scenario
+ // where it will not is when showGraphiQL is true.
+ if (!result) {
+ throw (0, _httpErrors2.default)(500, 'Internal Error');
+ }
+
+ // If "pretty" JSON isn't requested, and the server provides a
+ // response.json method (express), use that directly.
+ // Otherwise use the simplified sendResponse method.
+ if (!pretty && typeof response.json === 'function') {
+ response.json(result);
+ } else {
+ var _payload = JSON.stringify(result, null, pretty ? 2 : 0);
+ sendResponse(response, 'application/json', _payload);
+ }
+ });
+ };
+}
+
+/**
+ * Provided a "Request" provided by express or connect (typically a node style
+ * HTTPClientRequest), Promise the GraphQL request parameters.
+ */
+module.exports.getGraphQLParams = getGraphQLParams;
+function getGraphQLParams(request) {
+ return (0, _parseBody.parseBody)(request).then(function (bodyData) {
+ var urlData = request.url && _url2.default.parse(request.url, true).query || {};
+ return parseGraphQLParams(urlData, bodyData);
+ });
+}
+
+/**
+ * Helper function to get the GraphQL params from the request.
+ */
+function parseGraphQLParams(urlData, bodyData) {
+ // GraphQL Query string.
+ var query = urlData.query || bodyData.query;
+ if (typeof query !== 'string') {
+ query = null;
+ }
+
+ // Parse the variables if needed.
+ var variables = urlData.variables || bodyData.variables;
+ if (variables && typeof variables === 'string') {
+ try {
+ variables = JSON.parse(variables);
+ } catch (error) {
+ throw (0, _httpErrors2.default)(400, 'Variables are invalid JSON.');
+ }
+ } else if ((typeof variables === 'undefined' ? 'undefined' : _typeof(variables)) !== 'object') {
+ variables = null;
+ }
+
+ // Name of GraphQL operation to execute.
+ var operationName = urlData.operationName || bodyData.operationName;
+ if (typeof operationName !== 'string') {
+ operationName = null;
+ }
+
+ var raw = urlData.raw !== undefined || bodyData.raw !== undefined;
+
+ return { query: query, variables: variables, operationName: operationName, raw: raw };
+}
+
+/**
+ * Helper function to determine if GraphiQL can be displayed.
+ */
+function canDisplayGraphiQL(request, params) {
+ // If `raw` exists, GraphiQL mode is not enabled.
+ // Allowed to show GraphiQL if not requested as raw and this request
+ // prefers HTML over JSON.
+ return !params.raw && (0, _accepts2.default)(request).types(['json', 'html']) === 'html';
+}
+
+/**
+ * Helper function for sending a response using only the core Node server APIs.
+ */
+function sendResponse(response, type, data) {
+ var chunk = new Buffer(data, 'utf8');
+ response.setHeader('Content-Type', type + '; charset=utf-8');
+ response.setHeader('Content-Length', String(chunk.length));
+ response.end(chunk);
+}
\ No newline at end of file
diff --git a/node_modules/express-graphql/dist/index.js.flow b/node_modules/express-graphql/dist/index.js.flow
new file mode 100644
index 00000000..5ff14242
--- /dev/null
+++ b/node_modules/express-graphql/dist/index.js.flow
@@ -0,0 +1,411 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @flow strict
+ */
+
+import accepts from 'accepts';
+import {
+ Source,
+ parse,
+ validate,
+ execute,
+ formatError,
+ getOperationAST,
+ specifiedRules,
+} from 'graphql';
+import httpError from 'http-errors';
+import url from 'url';
+
+import { parseBody } from './parseBody';
+import { renderGraphiQL } from './renderGraphiQL';
+
+import type { DocumentNode, GraphQLError, GraphQLSchema } from 'graphql';
+import type { $Request, $Response } from 'express';
+
+/**
+ * Used to configure the graphqlHTTP middleware by providing a schema
+ * and other configuration options.
+ *
+ * Options can be provided as an Object, a Promise for an Object, or a Function
+ * that returns an Object or a Promise for an Object.
+ */
+export type Options =
+ | ((
+ request: $Request,
+ response: $Response,
+ params?: GraphQLParams,
+ ) => OptionsResult)
+ | OptionsResult;
+export type OptionsResult = OptionsData | Promise;
+export type OptionsData = {
+ /**
+ * A GraphQL schema from graphql-js.
+ */
+ schema: GraphQLSchema,
+
+ /**
+ * A value to pass as the context to the graphql() function.
+ */
+ context?: ?mixed,
+
+ /**
+ * An object to pass as the rootValue to the graphql() function.
+ */
+ rootValue?: ?mixed,
+
+ /**
+ * A boolean to configure whether the output should be pretty-printed.
+ */
+ pretty?: ?boolean,
+
+ /**
+ * An optional function which will be used to format any errors produced by
+ * fulfilling a GraphQL operation. If no function is provided, GraphQL's
+ * default spec-compliant `formatError` function will be used.
+ */
+ formatError?: ?(error: GraphQLError) => mixed,
+
+ /**
+ * An optional array of validation rules that will be applied on the document
+ * in additional to those defined by the GraphQL spec.
+ */
+ validationRules?: ?Array,
+
+ /**
+ * An optional function for adding additional metadata to the GraphQL response
+ * as a key-value object. The result will be added to "extensions" field in
+ * the resulting JSON. This is often a useful place to add development time
+ * info such as the runtime of a query or the amount of resources consumed.
+ *
+ * Information about the request is provided to be used.
+ *
+ * This function may be async.
+ */
+ extensions?: ?(info: RequestInfo) => { [key: string]: mixed },
+
+ /**
+ * A boolean to optionally enable GraphiQL mode.
+ */
+ graphiql?: ?boolean,
+};
+
+/**
+ * All information about a GraphQL request.
+ */
+export type RequestInfo = {
+ /**
+ * The parsed GraphQL document.
+ */
+ document: ?DocumentNode,
+
+ /**
+ * The variable values used at runtime.
+ */
+ variables: ?{ [name: string]: mixed },
+
+ /**
+ * The (optional) operation name requested.
+ */
+ operationName: ?string,
+
+ /**
+ * The result of executing the operation.
+ */
+ result: ?mixed,
+};
+
+type Middleware = (request: $Request, response: $Response) => Promise;
+
+/**
+ * Middleware for express; takes an options object or function as input to
+ * configure behavior, and returns an express middleware.
+ */
+module.exports = graphqlHTTP;
+function graphqlHTTP(options: Options): Middleware {
+ if (!options) {
+ throw new Error('GraphQL middleware requires options.');
+ }
+
+ return function graphqlMiddleware(request: $Request, response: $Response) {
+ // Higher scoped variables are referred to at various stages in the
+ // asynchronous state machine below.
+ let params;
+ let pretty;
+ let formatErrorFn;
+ let extensionsFn;
+ let showGraphiQL;
+ let query;
+
+ let documentAST;
+ let variables;
+ let operationName;
+
+ // Promises are used as a mechanism for capturing any thrown errors during
+ // the asynchronous process below.
+
+ // Parse the Request to get GraphQL request parameters.
+ return getGraphQLParams(request)
+ .then(graphQLParams => {
+ params = graphQLParams;
+ // Then, resolve the Options to get OptionsData.
+ return typeof options === 'function'
+ ? options(request, response, params)
+ : options;
+ })
+ .then(optionsData => {
+ // Assert that optionsData is in fact an Object.
+ if (!optionsData || typeof optionsData !== 'object') {
+ throw new Error(
+ 'GraphQL middleware option function must return an options object ' +
+ 'or a promise which will be resolved to an options object.',
+ );
+ }
+
+ // Assert that schema is required.
+ if (!optionsData.schema) {
+ throw new Error('GraphQL middleware options must contain a schema.');
+ }
+
+ // Collect information from the options data object.
+ const schema = optionsData.schema;
+ const context = optionsData.context || request;
+ const rootValue = optionsData.rootValue;
+ const graphiql = optionsData.graphiql;
+ pretty = optionsData.pretty;
+ formatErrorFn = optionsData.formatError;
+ extensionsFn = optionsData.extensions;
+
+ let validationRules = specifiedRules;
+ if (optionsData.validationRules) {
+ validationRules = validationRules.concat(optionsData.validationRules);
+ }
+
+ // GraphQL HTTP only supports GET and POST methods.
+ if (request.method !== 'GET' && request.method !== 'POST') {
+ response.setHeader('Allow', 'GET, POST');
+ throw httpError(405, 'GraphQL only supports GET and POST requests.');
+ }
+
+ // Get GraphQL params from the request and POST body data.
+ query = params.query;
+ variables = params.variables;
+ operationName = params.operationName;
+ showGraphiQL = graphiql && canDisplayGraphiQL(request, params);
+
+ // If there is no query, but GraphiQL will be displayed, do not produce
+ // a result, otherwise return a 400: Bad Request.
+ if (!query) {
+ if (showGraphiQL) {
+ return null;
+ }
+ throw httpError(400, 'Must provide query string.');
+ }
+
+ // GraphQL source.
+ const source = new Source(query, 'GraphQL request');
+
+ // Parse source to AST, reporting any syntax error.
+ try {
+ documentAST = parse(source);
+ } catch (syntaxError) {
+ // Return 400: Bad Request if any syntax errors errors exist.
+ response.statusCode = 400;
+ return { errors: [syntaxError] };
+ }
+
+ // Validate AST, reporting any errors.
+ const validationErrors = validate(schema, documentAST, validationRules);
+ if (validationErrors.length > 0) {
+ // Return 400: Bad Request if any validation errors exist.
+ response.statusCode = 400;
+ return { errors: validationErrors };
+ }
+
+ // Only query operations are allowed on GET requests.
+ if (request.method === 'GET') {
+ // Determine if this GET request will perform a non-query.
+ const operationAST = getOperationAST(documentAST, operationName);
+ if (operationAST && operationAST.operation !== 'query') {
+ // If GraphiQL can be shown, do not perform this query, but
+ // provide it to GraphiQL so that the requester may perform it
+ // themselves if desired.
+ if (showGraphiQL) {
+ return null;
+ }
+
+ // Otherwise, report a 405: Method Not Allowed error.
+ response.setHeader('Allow', 'POST');
+ throw httpError(
+ 405,
+ `Can only perform a ${operationAST.operation} operation ` +
+ 'from a POST request.',
+ );
+ }
+ }
+ // Perform the execution, reporting any errors creating the context.
+ try {
+ return execute(
+ schema,
+ documentAST,
+ rootValue,
+ context,
+ variables,
+ operationName,
+ );
+ } catch (contextError) {
+ // Return 400: Bad Request if any execution context errors exist.
+ response.statusCode = 400;
+ return { errors: [contextError] };
+ }
+ })
+ .then(result => {
+ // Collect and apply any metadata extensions if a function was provided.
+ // http://facebook.github.io/graphql/#sec-Response-Format
+ if (result && extensionsFn) {
+ return Promise.resolve(
+ extensionsFn({
+ document: documentAST,
+ variables,
+ operationName,
+ result,
+ }),
+ ).then(extensions => {
+ if (extensions && typeof extensions === 'object') {
+ (result: any).extensions = extensions;
+ }
+ return result;
+ });
+ }
+ return result;
+ })
+ .catch(error => {
+ // If an error was caught, report the httpError status, or 500.
+ response.statusCode = error.status || 500;
+ return { errors: [error] };
+ })
+ .then(result => {
+ // If no data was included in the result, that indicates a runtime query
+ // error, indicate as such with a generic status code.
+ // Note: Information about the error itself will still be contained in
+ // the resulting JSON payload.
+ // http://facebook.github.io/graphql/#sec-Data
+ if (response.statusCode === 200 && result && !result.data) {
+ response.statusCode = 500;
+ }
+ // Format any encountered errors.
+ if (result && result.errors) {
+ (result: any).errors = result.errors.map(
+ formatErrorFn || formatError,
+ );
+ }
+
+ // If allowed to show GraphiQL, present it instead of JSON.
+ if (showGraphiQL) {
+ const payload = renderGraphiQL({
+ query,
+ variables,
+ operationName,
+ result,
+ });
+ return sendResponse(response, 'text/html', payload);
+ }
+
+ // At this point, result is guaranteed to exist, as the only scenario
+ // where it will not is when showGraphiQL is true.
+ if (!result) {
+ throw httpError(500, 'Internal Error');
+ }
+
+ // If "pretty" JSON isn't requested, and the server provides a
+ // response.json method (express), use that directly.
+ // Otherwise use the simplified sendResponse method.
+ if (!pretty && typeof response.json === 'function') {
+ response.json(result);
+ } else {
+ const payload = JSON.stringify(result, null, pretty ? 2 : 0);
+ sendResponse(response, 'application/json', payload);
+ }
+ });
+ };
+}
+
+export type GraphQLParams = {
+ query: ?string,
+ variables: ?{ [name: string]: mixed },
+ operationName: ?string,
+ raw: ?boolean,
+};
+
+/**
+ * Provided a "Request" provided by express or connect (typically a node style
+ * HTTPClientRequest), Promise the GraphQL request parameters.
+ */
+module.exports.getGraphQLParams = getGraphQLParams;
+function getGraphQLParams(request: $Request): Promise {
+ return parseBody(request).then(bodyData => {
+ const urlData = (request.url && url.parse(request.url, true).query) || {};
+ return parseGraphQLParams(urlData, bodyData);
+ });
+}
+
+/**
+ * Helper function to get the GraphQL params from the request.
+ */
+function parseGraphQLParams(
+ urlData: { [param: string]: mixed },
+ bodyData: { [param: string]: mixed },
+): GraphQLParams {
+ // GraphQL Query string.
+ let query = urlData.query || bodyData.query;
+ if (typeof query !== 'string') {
+ query = null;
+ }
+
+ // Parse the variables if needed.
+ let variables = urlData.variables || bodyData.variables;
+ if (variables && typeof variables === 'string') {
+ try {
+ variables = JSON.parse(variables);
+ } catch (error) {
+ throw httpError(400, 'Variables are invalid JSON.');
+ }
+ } else if (typeof variables !== 'object') {
+ variables = null;
+ }
+
+ // Name of GraphQL operation to execute.
+ let operationName = urlData.operationName || bodyData.operationName;
+ if (typeof operationName !== 'string') {
+ operationName = null;
+ }
+
+ const raw = urlData.raw !== undefined || bodyData.raw !== undefined;
+
+ return { query, variables, operationName, raw };
+}
+
+/**
+ * Helper function to determine if GraphiQL can be displayed.
+ */
+function canDisplayGraphiQL(request: $Request, params: GraphQLParams): boolean {
+ // If `raw` exists, GraphiQL mode is not enabled.
+ // Allowed to show GraphiQL if not requested as raw and this request
+ // prefers HTML over JSON.
+ return !params.raw && accepts(request).types(['json', 'html']) === 'html';
+}
+
+/**
+ * Helper function for sending a response using only the core Node server APIs.
+ */
+function sendResponse(response: $Response, type: string, data: string): void {
+ const chunk = new Buffer(data, 'utf8');
+ response.setHeader('Content-Type', type + '; charset=utf-8');
+ response.setHeader('Content-Length', String(chunk.length));
+ response.end(chunk);
+}
diff --git a/node_modules/express-graphql/dist/parseBody.js b/node_modules/express-graphql/dist/parseBody.js
new file mode 100644
index 00000000..60ae15d9
--- /dev/null
+++ b/node_modules/express-graphql/dist/parseBody.js
@@ -0,0 +1,162 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * strict
+ */
+
+exports.parseBody = parseBody;
+
+var _contentType = require('content-type');
+
+var _contentType2 = _interopRequireDefault(_contentType);
+
+var _rawBody = require('raw-body');
+
+var _rawBody2 = _interopRequireDefault(_rawBody);
+
+var _httpErrors = require('http-errors');
+
+var _httpErrors2 = _interopRequireDefault(_httpErrors);
+
+var _querystring = require('querystring');
+
+var _querystring2 = _interopRequireDefault(_querystring);
+
+var _zlib = require('zlib');
+
+var _zlib2 = _interopRequireDefault(_zlib);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Provided a "Request" provided by express or connect (typically a node style
+ * HTTPClientRequest), Promise the body data contained.
+ */
+function parseBody(req) {
+ return new Promise(function (resolve, reject) {
+ var body = req.body;
+
+ // If express has already parsed a body as a keyed object, use it.
+ if ((typeof body === 'undefined' ? 'undefined' : _typeof(body)) === 'object' && !(body instanceof Buffer)) {
+ return resolve(body);
+ }
+
+ // Skip requests without content types.
+ if (req.headers['content-type'] === undefined) {
+ return resolve({});
+ }
+
+ var typeInfo = _contentType2.default.parse(req);
+
+ // If express has already parsed a body as a string, and the content-type
+ // was application/graphql, parse the string body.
+ if (typeof body === 'string' && typeInfo.type === 'application/graphql') {
+ return resolve(graphqlParser(body));
+ }
+
+ // Already parsed body we didn't recognise? Parse nothing.
+ if (body) {
+ return resolve({});
+ }
+
+ // Use the correct body parser based on Content-Type header.
+ switch (typeInfo.type) {
+ case 'application/graphql':
+ return read(req, typeInfo, graphqlParser, resolve, reject);
+ case 'application/json':
+ return read(req, typeInfo, jsonEncodedParser, resolve, reject);
+ case 'application/x-www-form-urlencoded':
+ return read(req, typeInfo, urlEncodedParser, resolve, reject);
+ }
+
+ // If no Content-Type header matches, parse nothing.
+ return resolve({});
+ });
+}
+
+function jsonEncodedParser(body) {
+ if (jsonObjRegex.test(body)) {
+ /* eslint-disable no-empty */
+ try {
+ return JSON.parse(body);
+ } catch (error) {}
+ // Do nothing
+
+ /* eslint-enable no-empty */
+ }
+ throw (0, _httpErrors2.default)(400, 'POST body sent invalid JSON.');
+}
+
+function urlEncodedParser(body) {
+ return _querystring2.default.parse(body);
+}
+
+function graphqlParser(body) {
+ return { query: body };
+}
+
+/**
+ * RegExp to match an Object-opening brace "{" as the first non-space
+ * in a string. Allowed whitespace is defined in RFC 7159:
+ *
+ * x20 Space
+ * x09 Horizontal tab
+ * x0A Line feed or New line
+ * x0D Carriage return
+ */
+var jsonObjRegex = /^[\x20\x09\x0a\x0d]*\{/;
+
+// Read and parse a request body.
+function read(req, typeInfo, parseFn, resolve, reject) {
+ var charset = (typeInfo.parameters.charset || 'utf-8').toLowerCase();
+
+ // Assert charset encoding per JSON RFC 7159 sec 8.1
+ if (charset.slice(0, 4) !== 'utf-') {
+ throw (0, _httpErrors2.default)(415, 'Unsupported charset "' + charset.toUpperCase() + '".');
+ }
+
+ // Get content-encoding (e.g. gzip)
+ var contentEncoding = req.headers['content-encoding'];
+ var encoding = typeof contentEncoding === 'string' ? contentEncoding.toLowerCase() : 'identity';
+ var length = encoding === 'identity' ? req.headers['content-length'] : null;
+ var limit = 100 * 1024; // 100kb
+ var stream = decompressed(req, encoding);
+
+ // Read body from stream.
+ (0, _rawBody2.default)(stream, { encoding: charset, length: length, limit: limit }, function (err, body) {
+ if (err) {
+ return reject(err.type === 'encoding.unsupported' ? (0, _httpErrors2.default)(415, 'Unsupported charset "' + charset.toUpperCase() + '".') : (0, _httpErrors2.default)(400, 'Invalid body: ' + err.message + '.'));
+ }
+
+ try {
+ // Decode and parse body.
+ return resolve(parseFn(body));
+ } catch (error) {
+ return reject(error);
+ }
+ });
+}
+
+// Return a decompressed stream, given an encoding.
+function decompressed(req, encoding) {
+ switch (encoding) {
+ case 'identity':
+ return req;
+ case 'deflate':
+ return req.pipe(_zlib2.default.createInflate());
+ case 'gzip':
+ return req.pipe(_zlib2.default.createGunzip());
+ }
+ throw (0, _httpErrors2.default)(415, 'Unsupported content-encoding "' + encoding + '".');
+}
\ No newline at end of file
diff --git a/node_modules/express-graphql/dist/parseBody.js.flow b/node_modules/express-graphql/dist/parseBody.js.flow
new file mode 100644
index 00000000..0cd87262
--- /dev/null
+++ b/node_modules/express-graphql/dist/parseBody.js.flow
@@ -0,0 +1,147 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @flow strict
+ */
+
+import contentType from 'content-type';
+import getBody from 'raw-body';
+import httpError from 'http-errors';
+import querystring from 'querystring';
+import zlib from 'zlib';
+
+import type { $Request } from 'express';
+
+/**
+ * Provided a "Request" provided by express or connect (typically a node style
+ * HTTPClientRequest), Promise the body data contained.
+ */
+export function parseBody(req: $Request): Promise<{ [param: string]: mixed }> {
+ return new Promise((resolve, reject) => {
+ const body = req.body;
+
+ // If express has already parsed a body as a keyed object, use it.
+ if (typeof body === 'object' && !(body instanceof Buffer)) {
+ return resolve((body: any));
+ }
+
+ // Skip requests without content types.
+ if (req.headers['content-type'] === undefined) {
+ return resolve({});
+ }
+
+ const typeInfo = contentType.parse(req);
+
+ // If express has already parsed a body as a string, and the content-type
+ // was application/graphql, parse the string body.
+ if (typeof body === 'string' && typeInfo.type === 'application/graphql') {
+ return resolve(graphqlParser(body));
+ }
+
+ // Already parsed body we didn't recognise? Parse nothing.
+ if (body) {
+ return resolve({});
+ }
+
+ // Use the correct body parser based on Content-Type header.
+ switch (typeInfo.type) {
+ case 'application/graphql':
+ return read(req, typeInfo, graphqlParser, resolve, reject);
+ case 'application/json':
+ return read(req, typeInfo, jsonEncodedParser, resolve, reject);
+ case 'application/x-www-form-urlencoded':
+ return read(req, typeInfo, urlEncodedParser, resolve, reject);
+ }
+
+ // If no Content-Type header matches, parse nothing.
+ return resolve({});
+ });
+}
+
+function jsonEncodedParser(body) {
+ if (jsonObjRegex.test(body)) {
+ /* eslint-disable no-empty */
+ try {
+ return JSON.parse(body);
+ } catch (error) {
+ // Do nothing
+ }
+ /* eslint-enable no-empty */
+ }
+ throw httpError(400, 'POST body sent invalid JSON.');
+}
+
+function urlEncodedParser(body) {
+ return querystring.parse(body);
+}
+
+function graphqlParser(body) {
+ return { query: body };
+}
+
+/**
+ * RegExp to match an Object-opening brace "{" as the first non-space
+ * in a string. Allowed whitespace is defined in RFC 7159:
+ *
+ * x20 Space
+ * x09 Horizontal tab
+ * x0A Line feed or New line
+ * x0D Carriage return
+ */
+const jsonObjRegex = /^[\x20\x09\x0a\x0d]*\{/;
+
+// Read and parse a request body.
+function read(req, typeInfo, parseFn, resolve, reject) {
+ const charset = (typeInfo.parameters.charset || 'utf-8').toLowerCase();
+
+ // Assert charset encoding per JSON RFC 7159 sec 8.1
+ if (charset.slice(0, 4) !== 'utf-') {
+ throw httpError(415, `Unsupported charset "${charset.toUpperCase()}".`);
+ }
+
+ // Get content-encoding (e.g. gzip)
+ const contentEncoding = req.headers['content-encoding'];
+ const encoding =
+ typeof contentEncoding === 'string'
+ ? contentEncoding.toLowerCase()
+ : 'identity';
+ const length = encoding === 'identity' ? req.headers['content-length'] : null;
+ const limit = 100 * 1024; // 100kb
+ const stream = decompressed(req, encoding);
+
+ // Read body from stream.
+ getBody(stream, { encoding: charset, length, limit }, (err, body) => {
+ if (err) {
+ return reject(
+ err.type === 'encoding.unsupported'
+ ? httpError(415, `Unsupported charset "${charset.toUpperCase()}".`)
+ : httpError(400, `Invalid body: ${err.message}.`),
+ );
+ }
+
+ try {
+ // Decode and parse body.
+ return resolve(parseFn(body));
+ } catch (error) {
+ return reject(error);
+ }
+ });
+}
+
+// Return a decompressed stream, given an encoding.
+function decompressed(req, encoding) {
+ switch (encoding) {
+ case 'identity':
+ return req;
+ case 'deflate':
+ return req.pipe(zlib.createInflate());
+ case 'gzip':
+ return req.pipe(zlib.createGunzip());
+ }
+ throw httpError(415, `Unsupported content-encoding "${encoding}".`);
+}
diff --git a/node_modules/express-graphql/dist/renderGraphiQL.js b/node_modules/express-graphql/dist/renderGraphiQL.js
new file mode 100644
index 00000000..a5916801
--- /dev/null
+++ b/node_modules/express-graphql/dist/renderGraphiQL.js
@@ -0,0 +1,42 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.renderGraphiQL = renderGraphiQL;
+
+
+// Current latest version of GraphiQL.
+var GRAPHIQL_VERSION = '0.11.11';
+
+// Ensures string values are safe to be used within a \n \n \n \n \n\n\n Loading...
\n \n\n