diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE new file mode 100644 index 000000000..27116f2f8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE @@ -0,0 +1,16 @@ +**Steps to reproduce the issue, if applicable. Include the actual command and output and/or stack trace.** + + + +**What did you expect to happen?** + + + +**If the issue is a feature request, what is the motivation / use case for it?** + +**Tell us about your environment** +- **exact http-server version:** +- **Node version:** +- **Platform:** + +**Other information (related issues, suggestions for a fix, etc):** diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 000000000..273336171 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,19 @@ +**Please ensure that your pull request fulfills these requirements:** +- [ ] The pull request is being made against the `master` branch +- [ ] Tests for the changes have been added (for bug fixes / features) + +**What is the purpose of this pull request? (bug fix, enhancement, new feature,...)** + + + +**What changes did you make?** + +**Provide some example code that this change will affect, if applicable:** + + + +**Is there anything you'd like reviewers to focus on?** + +**Please provide testing instructions, if applicable:** diff --git a/.gitignore b/.gitignore index 5894e2078..64e3c3aea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -node_modules/* -!node_modules/node-static -npm-debug.log +node_modules/ +npm-debug.log* +.dir-locals.el +.DS_Store diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..e747390ea --- /dev/null +++ b/.travis.yml @@ -0,0 +1,23 @@ +sudo: false +language: node_js +node_js: + - "6" + - "8" + - "10" + - "12" + - "13" + - "14" + +git: + autocrlf: input + +os: + - linux + - windows + - osx + +before_install: + - travis_retry npm install + +script: + - npm test diff --git a/LICENSE b/LICENSE index c9ebaf403..57960369a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 Nodejitsu http://github.com/nodejitsu/http-server/ +Copyright (c) 2011-2020 Charlie Robbins, Marak Squires, and the Contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -17,4 +17,4 @@ 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. \ No newline at end of file +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 2fee07ea2..e983d4ff5 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,34 @@ +[![build status](https://img.shields.io/travis/http-party/http-server.svg?style=flat-square)](https://travis-ci.org/http-party/http-server) +[![npm](https://img.shields.io/npm/v/http-server.svg?style=flat-square)](https://www.npmjs.com/package/http-server) [![homebrew](https://img.shields.io/homebrew/v/http-server?style=flat-square)](https://formulae.brew.sh/formula/http-server) [![npm downloads](https://img.shields.io/npm/dm/http-server?color=blue&label=npm%20downloads&style=flat-square)](https://www.npmjs.com/package/http-server) +[![license](https://img.shields.io/github/license/http-party/http-server.svg?style=flat-square)](https://github.com/http-party/http-server) + # http-server: a command-line http server `http-server` is a simple, zero-configuration command-line http server. It is powerful enough for production usage, but it's simple and hackable enough to be used for testing, local development, and learning. -![](https://github.com/nodeapps/http-server/raw/master/screenshots/public.png) +![Example of running http-server](https://github.com/http-party/http-server/raw/master/screenshots/public.png) -# Installing globally: +## Installation: -Installation via `npm`. If you don't have `npm` yet: +#### Globally via `npm` - curl https://npmjs.org/install.sh | sh - -Once you have `npm`: + npm install --global http-server + +This will install `http-server` globally so that it may be run from the command line anywhere. + +#### Globally via Homebrew + + brew install http-server - npm install http-server -g +#### Running on-demand: + +Using `npx` you can run the script without installing it first: + + npx http-server [path] [options] -This will install `http-server` globally so that it may be run from the command line. +#### As a dependency in your `npm` package: + + npm install http-server ## Usage: @@ -22,42 +36,114 @@ This will install `http-server` globally so that it may be run from the command `[path]` defaults to `./public` if the folder exists, and `./` otherwise. -# Installing as a node app +*Now you can visit http://localhost:8080 to view your server* + +**Note:** Caching is on by default. Add `-c-1` as an option to disable caching. - mkdir myapp - cd myapp/ - jitsu install http-server +## Available Options: -*If you do not have `jitsu` installed you can install it via `npm install jitsu -g`* +`-p` or `--port` Port to use (defaults to 8080). It will also read from `process.env.PORT`. -## Usage +`-a` Address to use (defaults to 0.0.0.0) -### Starting http-server locally +`-d` Show directory listings (defaults to `true`) - node bin/http-server +`-i` Display autoIndex (defaults to `true`) -*Now you can visit http://localhost:8080 to view your server* +`-g` or `--gzip` When enabled (defaults to `false`) it will serve `./public/some-file.js.gz` in place of `./public/some-file.js` when a gzipped version of the file exists and the request accepts gzip encoding. If brotli is also enabled, it will try to serve brotli first. -### Deploy http-server to nodejitsu +`-b` or `--brotli` When enabled (defaults to `false`) it will serve `./public/some-file.js.br` in place of `./public/some-file.js` when a brotli compressed version of the file exists and the request accepts `br` encoding. If gzip is also enabled, it will try to serve brotli first. - jitsu deploy +`-e` or `--ext` Default file extension if none supplied (defaults to `html`) -*You will now be prompted for a `subdomain` to deploy your application on* +`-s` or `--silent` Suppress log messages from output -## Available Options: +`--cors` Enable CORS via the `Access-Control-Allow-Origin` header + +`-o [path]` Open browser window after starting the server. Optionally provide a URL path to open. e.g.: -o /other/dir/ + +`-c` Set cache time (in seconds) for cache-control max-age header, e.g. `-c10` for 10 seconds (defaults to `3600`). To disable caching, use `-c-1`. + +`-U` or `--utc` Use UTC time format in log messages. + +`--log-ip` Enable logging of the client's IP address (default: `false`). + +`-P` or `--proxy` Proxies all requests which can't be resolved locally to the given url. e.g.: -P http://someurl.com + +`--username` Username for basic authentication [none] + +`--password` Password for basic authentication [none] -`-p` Port to listen for connections on (defaults to 8080) +`-S` or `--ssl` Enable https. -`-a` Address to bind to (defaults to '0.0.0.0') +`-C` or `--cert` Path to ssl cert file (default: `cert.pem`). -`-d` Show directory listings (defaults to 'True') +`-K` or `--key` Path to ssl key file (default: `key.pem`). -`-i` Display autoIndex (defaults to 'True') +`-r` or `--robots` Provide a /robots.txt (whose content defaults to `User-agent: *\nDisallow: /`) -`-e` or `--ext` Default file extension (defaults to 'html') +`--no-dotfiles` Do not show dotfiles + +`-H` or `--header` Send the specified header with responses, e.g. `-H "Strict-Transport-Security: max-age=315360000; includeSubdomains"`. -`-s` or `--silent` In silent mode, log messages aren't logged to the console. +`-h` or `--help` Print this list and exit. -`-h` or `--help` Displays a list of commands and exits. +`-v` or `--version` Print the version and exit. + +## Magic Files + +- `index.html` will be served as the default file to any directory requests. +- `404.html` will be served if a file is not found. This can be used for Single-Page App (SPA) hosting to serve the entry page. + +## Catch-all redirect + +To implement a catch-all redirect, use the index page itself as the proxy with: + +``` +http-server --proxy http://localhost:8080? +``` + +Note the `?` at the end of the proxy URL. Thanks to [@houston3](https://github.com/houston3) for this clever hack! + +## TLS/SSL + +First, you need to make sure that [openssl](https://github.com/openssl/openssl) is installed correctly, and you have `key.pem` and `cert.pem` files. You can generate them using this command: + +``` sh +openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem +``` + +You will be prompted with a few questions after entering the command. Use `127.0.0.1` as value for `Common name` if you want to be able to install the certificate in your OS's root certificate store or browser so that it is trusted. + +This generates a cert-key pair and it will be valid for 3650 days (about 10 years). + +Then you need to run the server with `-S` for enabling SSL and `-C` for your certificate file. + +``` sh +http-server -S -C cert.pem +``` + +This is what should be output if successful: + +``` sh +Starting up http-server, serving ./ through https +Available on: + https:127.0.0.1:8080 + https:192.168.1.101:8080 + https:192.168.1.104:8080 +Hit CTRL-C to stop the server +``` + +# Development + +Checkout this repository locally, then: + +```sh +$ npm i +$ node bin/http-server +``` + +*Now you can visit http://localhost:8080 to view your server* -`-c` Set cache time (in seconds) for cache-control max-age header, e.g. -c10 for 10 seconds. To disable caching, use -c-1. +You should see the turtle image in the screenshot above hosted at that URL. See +the `./public` folder for demo content. diff --git a/bin/http-server b/bin/http-server index 3c1f613a0..d2a568930 100755 --- a/bin/http-server +++ b/bin/http-server @@ -1,86 +1,232 @@ #!/usr/bin/env node -var colors = require('colors'), +'use strict'; + +var colors = require('colors/safe'), + os = require('os'), httpServer = require('../lib/http-server'), - argv = require('optimist').argv, portfinder = require('portfinder'), - opener = require('opener'); + opener = require('opener'), + fs = require('fs'), + argv = require('minimist')(process.argv.slice(2)); +var ifaces = os.networkInterfaces(); + +process.title = 'http-server'; if (argv.h || argv.help) { console.log([ - "usage: http-server [path] [options]", - "", - "options:", - " -p Port to use [8080]", - " -a Address to use [0.0.0.0]", - " -d Show directory listings [true]", - " -i Display autoIndex [true]", - " -e --ext Default file extension if none supplied [none]", - " -s --silent Suppress log messages from output", - " --cors Enable CORS via the 'Access-Control-Allow-Origin' header", - " -o Open browser window after staring the server", - " -c Set cache time (in seconds). e.g. -c10 for 10 seconds.", - " To disable caching, use -c-1.", - " -h --help Print this list and exit." + 'usage: http-server [path] [options]', + '', + 'options:', + ' -p --port Port to use [8080]', + ' -a Address to use [0.0.0.0]', + ' -d Show directory listings [true]', + ' -i Display autoIndex [true]', + ' -g --gzip Serve gzip files when possible [false]', + ' -b --brotli Serve brotli files when possible [false]', + ' If both brotli and gzip are enabled, brotli takes precedence', + ' -e --ext Default file extension if none supplied [none]', + ' -s --silent Suppress log messages from output', + ' --cors[=headers] Enable CORS via the "Access-Control-Allow-Origin" header', + ' Optionally provide CORS headers list separated by commas', + ' -o [path] Open browser window after starting the server.', + ' Optionally provide a URL path to open the browser window to.', + ' -c Cache time (max-age) in seconds [3600], e.g. -c10 for 10 seconds.', + ' To disable caching, use -c-1.', + ' -t Connections timeout in seconds [120], e.g. -t60 for 1 minute.', + ' To disable timeout, use -t0', + ' -U --utc Use UTC time format in log messages.', + ' --log-ip Enable logging of the client\'s IP address', + '', + ' -P --proxy Fallback proxy if the request cannot be resolved. e.g.: http://someurl.com', + '', + ' --username Username for basic authentication [none]', + ' Can also be specified with the env variable NODE_HTTP_SERVER_USERNAME', + ' --password Password for basic authentication [none]', + ' Can also be specified with the env variable NODE_HTTP_SERVER_PASSWORD', + '', + ' -S --ssl Enable https.', + ' -C --cert Path to ssl cert file (default: cert.pem).', + ' -K --key Path to ssl key file (default: key.pem).', + '', + ' -r --robots Respond to /robots.txt [User-agent: *\\nDisallow: /]', + ' --no-dotfiles Do not show dotfiles', + ' -H --header Send the specified header with responses,', + ' 'e.g. -H \'X-MY-HEADER: foo\'', + ' -h --help Print this list and exit.', + ' -v --version Print the version and exit.' ].join('\n')); process.exit(); } -var port = argv.p || parseInt(process.env.PORT, 10), +var port = argv.p || argv.port || parseInt(process.env.PORT, 10), host = argv.a || '0.0.0.0', - log = (argv.s || argv.silent) ? (function () {}) : console.log, - requestLogger; + ssl = argv.S || argv.ssl, + proxy = argv.P || argv.proxy, + utc = argv.U || argv.utc, + version = argv.v || argv.version, + logger; if (!argv.s && !argv.silent) { - requestLogger = function(req) { - log('[%s] "%s %s" "%s"', (new Date).toUTCString(), req.method.cyan, req.url.cyan, req.headers['user-agent']); - } + logger = { + info: console.log, + request: function (req, res, error) { + var date = utc ? new Date().toUTCString() : new Date(); + var ip = argv['log-ip'] + ? req.headers['x-forwarded-for'] || '' + req.connection.remoteAddress + : ''; + if (error) { + logger.info( + '[%s] %s "%s %s" Error (%s): "%s"', + date, ip, colors.red(req.method), colors.red(req.url), + colors.red(error.status.toString()), colors.red(error.message) + ); + } + else { + logger.info( + '[%s] %s "%s %s" "%s"', + date, ip, colors.cyan(req.method), colors.cyan(req.url), + req.headers['user-agent'] + ); + } + } + }; +} +else if (colors) { + logger = { + info: function () {}, + request: function () {} + }; +} + +if (version) { + logger.info('v' + require('../package.json').version); + process.exit(); } if (!port) { portfinder.basePort = 8080; portfinder.getPort(function (err, port) { - if (err) throw err; + if (err) { throw err; } listen(port); }); -} else { +} +else { listen(port); } +function addHeader(headers, header) { + if (!header || !header.indexOf) return; + var idx = header.indexOf(':'), + key = header.substring(0, idx), + val = header.substring(idx + 1).trim(); + headers[key] = val; +} + function listen(port) { var options = { root: argv._[0], cache: argv.c, + timeout: argv.t, showDir: argv.d, autoIndex: argv.i, + gzip: argv.g || argv.gzip, + brotli: argv.b || argv.brotli, + robots: argv.r || argv.robots, ext: argv.e || argv.ext, - logFn: requestLogger + logFn: logger.request, + proxy: proxy, + showDotfiles: argv.dotfiles, + headers: {}, + username: argv.username || process.env.NODE_HTTP_SERVER_USERNAME, + password: argv.password || process.env.NODE_HTTP_SERVER_PASSWORD }; if (argv.cors) { - options.headers = { 'Access-Control-Allow-Origin': '*' }; + options.cors = true; + if (typeof argv.cors === 'string') { + options.corsHeaders = argv.cors; + } } + if (ssl) { + options.https = { + cert: argv.C || argv.cert || 'cert.pem', + key: argv.K || argv.key || 'key.pem' + }; + try { + fs.lstatSync(options.https.cert); + } + catch (err) { + logger.info(colors.red('Error: Could not find certificate ' + options.https.cert)); + process.exit(1); + } + try { + fs.lstatSync(options.https.key); + } + catch (err) { + logger.info(colors.red('Error: Could not find private key ' + options.https.key)); + process.exit(1); + } + } + + addHeader(options.headers, argv.H || argv.header); + var server = httpServer.createServer(options); - server.listen(port, host, function() { - log('Starting up http-server, serving '.yellow - + server.root.cyan - + ' on port: '.yellow - + port.toString().cyan); - log('Hit CTRL-C to stop the server'); + server.listen(port, host, function () { + var canonicalHost = host === '0.0.0.0' ? '127.0.0.1' : host, + protocol = ssl ? 'https://' : 'http://'; + + logger.info([colors.yellow('Starting up http-server, serving '), + colors.cyan(server.root), + ssl ? (colors.yellow(' through') + colors.cyan(' https')) : '', + colors.yellow('\nAvailable on:') + ].join('')); + if (argv.a && host !== '0.0.0.0') { + logger.info((' ' + protocol + canonicalHost + ':' + colors.green(port.toString()))); + } + else { + Object.keys(ifaces).forEach(function (dev) { + ifaces[dev].forEach(function (details) { + if (details.family === 'IPv4') { + logger.info((' ' + protocol + details.address + ':' + colors.green(port.toString()))); + } + }); + }); + } + + if (typeof proxy === 'string') { + logger.info('Unhandled requests will be served from: ' + proxy); + } + + logger.info('Hit CTRL-C to stop the server'); if (argv.o) { - opener('http://127.0.0.1:' + port.toString()); + var openUrl = protocol + canonicalHost + ':' + port; + if (typeof argv.o === 'string') { + openUrl += argv.o[0] === '/' ? argv.o : '/' + argv.o; + } + logger.info('open: ' + openUrl); + opener(openUrl); } }); } -if (process.platform !== 'win32') { - // - // Signal handlers don't work on Windows. - // - process.on('SIGINT', function () { - log('http-server stopped.'.red); - process.exit(); +if (process.platform === 'win32') { + require('readline').createInterface({ + input: process.stdin, + output: process.stdout + }).on('SIGINT', function () { + process.emit('SIGINT'); }); } + +process.on('SIGINT', function () { + logger.info(colors.red('http-server stopped.')); + process.exit(); +}); + +process.on('SIGTERM', function () { + logger.info(colors.red('http-server stopped.')); + process.exit(); +}); diff --git a/doc/http-server.1 b/doc/http-server.1 new file mode 100644 index 000000000..751d931d4 --- /dev/null +++ b/doc/http-server.1 @@ -0,0 +1,160 @@ +.TH http-server 1 "April 2020" GNU "http-server man page" + +.SH NAME +http-server \- a simple zero-configuration command-line http server + +.SH SYNOPSIS +.B http-server +[\fIPATH\fR] +[\fIOPTIONS\fR] + +.SH DESCRIPTION +\fBhttp-server\fR is a simple, zero-configuration command-line http server. It is powerful enough for production usage, but it's simple and hackable enough to be used for testing, local development, and learning. + +.SH OPTIONS + +.TP +.BI [\fIPATH\fR] +The directory to serve. +Defaults to ./public if it exists, and ./ otherwise. + +.TP +.BI \-p ", " \-\-port " " \fIPORT\fR +Port to use. +Default is 8080. + +.TP +.BI \-a " " \fIADDRESS\fR +Address to use. +Default is 0.0.0.0. + +.TP +.BI \-d +Show directory listings. +Default is true. + +.TP +.BI \-i +Display autoIndex. +Default is true. + +.TP +.BI \-g ", " \-\-gzip +Serve gzip files when possible. +Default is false. + +.TP +.BI \-b ", " \-\-brotli +Serve brotli files when possible. +If both brotli and gzip are enabled, brotli takes precedence. +Default is false. + +.TP +.BI \-e ", " \-\-ext " " \fIEXTENSION\fR +Default file extension is none is provided. + +.TP +.BI \-s ", " \-\-silent +Suppress log messages from output. + +.TP +.BI \-\-cors " " [\fIHEADERS\fR] +Enable CORS via the "Access-Control-Allow-Origin" header. +Optionally provide CORS headers list separated by commas. + +.TP +.BI \-o " " [\fIPATH\fR] +Open default browser window after starting the server. +Optionally provide a URL path to open the browser window to. + +.TP +.BI \-c " " \fITIME\fR +Cache time (max-age) in seconds. +To disable caching, use \-c \-1. +Default is 3600. + +.TP +.BI \-U ", " \-\-utc +Use UTC time format in log messages. + +.TP +.BI \-\-log\-ip +Enable logging of the client IP address. + +.TP +.BI \-P ", " \-\-proxy +Fallback proxy if the request cannot be resolved. + +.TP +.BI \-\-username " " \fIUSERNAME\fR +Username for basic authentication. +Can also be specified with the environment variable NODE_HTTP_SERVER_USERNAME. +Defaults to none. + +.TP +.BI \-\-password " " \fIPASSWORD\fR +Password for basic authentication. +Can also be specified with the environment variable NODE_HTTP_SERVER_PASSWORD. +Defaults to none. + +.TP +.BI \-S ", " \-\-ssl +Enable https. + +.TP +.BI \-C ", " \-\-cert " " [\fIFILE\fR] +Path to SSL certificate file. +If not specified, uses cert.pem. + +.TP +.BI \-K ", " \-\-key " " [\fIFILE\fR] +Path to SSL key file. +If not specified, uses key.pem. + +.TP +.BI \-r ", " \-\-robots " " [\fIUSER\-AGENT\fR] +Respond to /robots.txt request. +If not specified, uses "User-agent: *\\nDisallow: /]" + +.TP +.BI \-\-no\-dotfiles +Do not show dotfiles. + +.TP +.BI \-h ", " \-\-help +Print usage and exit. + +.TP +.BI \-v ", " \-\-version +Print version and exit. + +.SH FILES +.B index.html +will be served as the default file to any directory requests. + +.B 404.html +will be served if a file is not found. This can be used for SPA hosting to serve the entry page. + +.SH COPYING +Copyright (c) 2011-2020 Charlie Robbins, Marak Squires, and the Contributors. +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. + +.SH VERSION +Version 0.12.2 diff --git a/lib/http-server.js b/lib/http-server.js index 213aa63f1..8bafdf8e9 100644 --- a/lib/http-server.js +++ b/lib/http-server.js @@ -1,9 +1,58 @@ +'use strict'; + var fs = require('fs'), - util = require('util'), union = require('union'), - ecstatic = require('ecstatic'); + ecstatic = require('ecstatic'), + auth = require('basic-auth'), + httpProxy = require('http-proxy'), + corser = require('corser'), + path = require('path'), + secureCompare = require('secure-compare'); + +// a hacky and direct workaround to fix https://github.com/http-party/http-server/issues/525 +function getCaller() { + try { + var stack = new Error().stack; + var stackLines = stack.split('\n'); + var callerStack = stackLines[3]; + return callerStack.match(/at (.+) \(/)[1]; + } + catch (error) { + return ''; + } +} + +var _pathNormalize = path.normalize; +path.normalize = function (p) { + var caller = getCaller(); + var result = _pathNormalize(p); + // https://github.com/jfhbrook/node-ecstatic/blob/master/lib/ecstatic.js#L20 + if (caller === 'decodePathname') { + result = result.replace(/\\/g, '/'); + } + return result; +}; + +// +// Remark: backwards compatibility for previous +// case convention of HTTP +// +exports.HttpServer = exports.HTTPServer = HttpServer; + +/** + * Returns a new instance of HttpServer with the + * specified `options`. + */ +exports.createServer = function (options) { + return new HttpServer(options); +}; -var HTTPServer = exports.HTTPServer = function (options) { +/** + * Constructor function for the HttpServer object + * which is responsible for serving static files along + * with other HTTP-related features. + */ +function HttpServer(options) { options = options || {}; if (options.root) { @@ -19,46 +68,143 @@ var HTTPServer = exports.HTTPServer = function (options) { } } - if (options.headers) { - this.headers = options.headers; - } + this.headers = options.headers || {}; - this.cache = options.cache || 3600; // in seconds. + this.cache = ( + options.cache === undefined ? 3600 : + // -1 is a special case to turn off caching. + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Preventing_caching + options.cache === -1 ? 'no-cache, no-store, must-revalidate' : + options.cache // in seconds. + ); this.showDir = options.showDir !== 'false'; this.autoIndex = options.autoIndex !== 'false'; - + this.showDotfiles = options.showDotfiles; + this.gzip = options.gzip === true; + this.brotli = options.brotli === true; if (options.ext) { this.ext = options.ext === true ? 'html' : options.ext; } + this.contentType = options.contentType || + this.ext === 'html' ? 'text/html' : 'application/octet-stream'; + + var before = options.before ? options.before.slice() : []; + + if (options.logFn) { + before.push(function (req, res) { + options.logFn(req, res); + res.emit('next'); + }); + } + + if (options.username || options.password) { + before.push(function (req, res) { + var credentials = auth(req); + + // We perform these outside the if to avoid short-circuiting and giving + // an attacker knowledge of whether the username is correct via a timing + // attack. + if (credentials) { + // if credentials is defined, name and pass are guaranteed to be string + // type + var usernameEqual = secureCompare(options.username.toString(), credentials.name); + var passwordEqual = secureCompare(options.password.toString(), credentials.pass); + if (usernameEqual && passwordEqual) { + return res.emit('next'); + } + } + + res.statusCode = 401; + res.setHeader('WWW-Authenticate', 'Basic realm=""'); + res.end('Access denied'); + }); + } - this.server = union.createServer({ - before: (options.before || []).concat([ - function (req, res) { - options.logFn && options.logFn(req, res); + if (options.cors) { + this.headers['Access-Control-Allow-Origin'] = '*'; + this.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Range'; + if (options.corsHeaders) { + options.corsHeaders.split(/\s*,\s*/) + .forEach(function (h) { this.headers['Access-Control-Allow-Headers'] += ', ' + h; }, this); + } + before.push(corser.create(options.corsHeaders ? { + requestHeaders: this.headers['Access-Control-Allow-Headers'].split(/\s*,\s*/) + } : null)); + } + + if (options.robots) { + before.push(function (req, res) { + if (req.url === '/robots.txt') { + res.setHeader('Content-Type', 'text/plain'); + var robots = options.robots === true + ? 'User-agent: *\nDisallow: /' + : options.robots.replace(/\\n/, '\n'); + + return res.end(robots); + } + + res.emit('next'); + }); + } + + before.push(ecstatic({ + root: this.root, + cache: this.cache, + showDir: this.showDir, + showDotfiles: this.showDotfiles, + autoIndex: this.autoIndex, + defaultExt: this.ext, + gzip: this.gzip, + brotli: this.brotli, + contentType: this.contentType, + handleError: typeof options.proxy !== 'string' + })); + + if (typeof options.proxy === 'string') { + var proxy = httpProxy.createProxyServer({}); + before.push(function (req, res) { + proxy.web(req, res, { + target: options.proxy, + changeOrigin: true + }, function (err, req, res, target) { + if (options.logFn) { + options.logFn(req, res, { + message: err.message, + status: res.statusCode }); + } res.emit('next'); - }, - ecstatic({ - root: this.root, - cache: this.cache, - showDir : this.showDir, - autoIndex: this.autoIndex, - defaultExt: this.ext - }) - ]), - headers: this.headers || {} - }); -}; + }); + }); + } -HTTPServer.prototype.listen = function () { + var serverOptions = { + before: before, + headers: this.headers, + onError: function (err, req, res) { + if (options.logFn) { + options.logFn(req, res, err); + } + + res.end(); + } + }; + + if (options.https) { + serverOptions.https = options.https; + } + + this.server = union.createServer(serverOptions); + if (options.timeout !== undefined) { + this.server.setTimeout(options.timeout); + } +} + +HttpServer.prototype.listen = function () { this.server.listen.apply(this.server, arguments); }; -HTTPServer.prototype.close = function () { +HttpServer.prototype.close = function () { return this.server.close(); }; - -exports.createServer = function (options) { - return new HTTPServer(options); -}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..acb4dfd60 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2934 @@ +{ + "name": "http-server", + "version": "0.12.3", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "JSV": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", + "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=", + "dev": true + }, + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "dev": true + }, + "ajv": { + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", + "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "alter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/alter/-/alter-0.2.0.tgz", + "integrity": "sha1-x1iICGF1cgNKrmJICvJrHU0cs80=", + "dev": true, + "requires": { + "stable": "~0.1.3" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "ast-traverse": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ast-traverse/-/ast-traverse-0.1.1.tgz", + "integrity": "sha1-ac8rg4bxnc2hux4F1o/jWdiJfeY=", + "dev": true + }, + "ast-types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", + "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "dev": true + }, + "babel-core": { + "version": "5.8.38", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-5.8.38.tgz", + "integrity": "sha1-H8ruedfmG3ULALjlT238nQr4ZVg=", + "dev": true, + "requires": { + "babel-plugin-constant-folding": "^1.0.1", + "babel-plugin-dead-code-elimination": "^1.0.2", + "babel-plugin-eval": "^1.0.1", + "babel-plugin-inline-environment-variables": "^1.0.1", + "babel-plugin-jscript": "^1.0.4", + "babel-plugin-member-expression-literals": "^1.0.1", + "babel-plugin-property-literals": "^1.0.1", + "babel-plugin-proto-to-assign": "^1.0.3", + "babel-plugin-react-constant-elements": "^1.0.3", + "babel-plugin-react-display-name": "^1.0.3", + "babel-plugin-remove-console": "^1.0.1", + "babel-plugin-remove-debugger": "^1.0.1", + "babel-plugin-runtime": "^1.0.7", + "babel-plugin-undeclared-variables-check": "^1.0.2", + "babel-plugin-undefined-to-void": "^1.1.6", + "babylon": "^5.8.38", + "bluebird": "^2.9.33", + "chalk": "^1.0.0", + "convert-source-map": "^1.1.0", + "core-js": "^1.0.0", + "debug": "^2.1.1", + "detect-indent": "^3.0.0", + "esutils": "^2.0.0", + "fs-readdir-recursive": "^0.1.0", + "globals": "^6.4.0", + "home-or-tmp": "^1.0.0", + "is-integer": "^1.0.4", + "js-tokens": "1.0.1", + "json5": "^0.4.0", + "lodash": "^3.10.0", + "minimatch": "^2.0.3", + "output-file-sync": "^1.1.0", + "path-exists": "^1.0.0", + "path-is-absolute": "^1.0.0", + "private": "^0.1.6", + "regenerator": "0.8.40", + "regexpu": "^1.3.0", + "repeating": "^1.1.2", + "resolve": "^1.1.6", + "shebang-regex": "^1.0.0", + "slash": "^1.0.0", + "source-map": "^0.5.0", + "source-map-support": "^0.2.10", + "to-fast-properties": "^1.0.0", + "trim-right": "^1.0.0", + "try-resolve": "^1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "^1.0.0" + } + } + } + }, + "babel-jscs": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/babel-jscs/-/babel-jscs-2.0.5.tgz", + "integrity": "sha1-CjRwRrSBRay8pW6MjtX3NrxU+dA=", + "dev": true, + "requires": { + "babel-core": "~5.8.3", + "lodash.assign": "^3.2.0" + } + }, + "babel-plugin-constant-folding": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-constant-folding/-/babel-plugin-constant-folding-1.0.1.tgz", + "integrity": "sha1-g2HTZMmORJw2kr26Ue/whEKQqo4=", + "dev": true + }, + "babel-plugin-dead-code-elimination": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-dead-code-elimination/-/babel-plugin-dead-code-elimination-1.0.2.tgz", + "integrity": "sha1-X3xFEnTc18zNv7s+C4XdKBIfD2U=", + "dev": true + }, + "babel-plugin-eval": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-eval/-/babel-plugin-eval-1.0.1.tgz", + "integrity": "sha1-ovrtJc5r5preS/7CY/cBaRlZUNo=", + "dev": true + }, + "babel-plugin-inline-environment-variables": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-inline-environment-variables/-/babel-plugin-inline-environment-variables-1.0.1.tgz", + "integrity": "sha1-H1jOkSB61qgmqL9kX6/mj/X+P/4=", + "dev": true + }, + "babel-plugin-jscript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/babel-plugin-jscript/-/babel-plugin-jscript-1.0.4.tgz", + "integrity": "sha1-jzQsOCduh6R9X6CovT1etsytj8w=", + "dev": true + }, + "babel-plugin-member-expression-literals": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-member-expression-literals/-/babel-plugin-member-expression-literals-1.0.1.tgz", + "integrity": "sha1-zF7bD6qNyScXDnTW0cAkQAIWJNM=", + "dev": true + }, + "babel-plugin-property-literals": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-property-literals/-/babel-plugin-property-literals-1.0.1.tgz", + "integrity": "sha1-AlIwGQAZKYCxwRjv6kjOk6q4MzY=", + "dev": true + }, + "babel-plugin-proto-to-assign": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/babel-plugin-proto-to-assign/-/babel-plugin-proto-to-assign-1.0.4.tgz", + "integrity": "sha1-xJ56/QL1d7xNoF6i3wAiUM980SM=", + "dev": true, + "requires": { + "lodash": "^3.9.3" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "babel-plugin-react-constant-elements": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/babel-plugin-react-constant-elements/-/babel-plugin-react-constant-elements-1.0.3.tgz", + "integrity": "sha1-lGc26DeEKcvDSdz/YvUcFDs041o=", + "dev": true + }, + "babel-plugin-react-display-name": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/babel-plugin-react-display-name/-/babel-plugin-react-display-name-1.0.3.tgz", + "integrity": "sha1-dU/jiSboQkpOexWrbqYTne4FFPw=", + "dev": true + }, + "babel-plugin-remove-console": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-remove-console/-/babel-plugin-remove-console-1.0.1.tgz", + "integrity": "sha1-2PJFVsOgUAXUKqqv0neH9T/wE6c=", + "dev": true + }, + "babel-plugin-remove-debugger": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-remove-debugger/-/babel-plugin-remove-debugger-1.0.1.tgz", + "integrity": "sha1-/S6jzWGkKK0fO5yJiC/0KT6MFMc=", + "dev": true + }, + "babel-plugin-runtime": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/babel-plugin-runtime/-/babel-plugin-runtime-1.0.7.tgz", + "integrity": "sha1-v3x9lm3Vbs1cF/ocslPJrLflSq8=", + "dev": true + }, + "babel-plugin-undeclared-variables-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-undeclared-variables-check/-/babel-plugin-undeclared-variables-check-1.0.2.tgz", + "integrity": "sha1-XPGqU52BP/ZOmWQSkK9iCWX2Xe4=", + "dev": true, + "requires": { + "leven": "^1.0.2" + } + }, + "babel-plugin-undefined-to-void": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/babel-plugin-undefined-to-void/-/babel-plugin-undefined-to-void-1.1.6.tgz", + "integrity": "sha1-f1eO+LeN+uYAM4XYQXph7aBuL4E=", + "dev": true + }, + "babylon": { + "version": "5.8.38", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-5.8.38.tgz", + "integrity": "sha1-7JsSCxG/bM1Bc6GL8hfmC3mFn/0=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "basic-auth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", + "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "breakable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/breakable/-/breakable-1.0.0.tgz", + "integrity": "sha1-eEp5eRWjjq0nutRWtVcstLuqeME=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "dev": true, + "requires": { + "exit": "0.1.2", + "glob": "^7.1.1" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "dev": true, + "requires": { + "colors": "1.0.3" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + } + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + }, + "color": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/color/-/color-0.8.0.tgz", + "integrity": "sha1-iQwHw/1OZJU3Y4kRz2keVFi2/KU=", + "dev": true, + "requires": { + "color-convert": "^0.5.0", + "color-string": "^0.3.0" + } + }, + "color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=", + "dev": true + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "dev": true, + "requires": { + "color-name": "^1.0.0" + } + }, + "colornames": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-0.0.2.tgz", + "integrity": "sha1-2BH9bIT1kClJmorEQ2ICk1uSvjE=", + "dev": true + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "colorspace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.0.1.tgz", + "integrity": "sha1-yZx5btMRKLmHalLh7l7gOkpxl0k=", + "dev": true, + "requires": { + "color": "0.8.x", + "text-hex": "0.0.x" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "comment-parser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.3.2.tgz", + "integrity": "sha1-PAPwd2uGo239mgosl8YwfzMggv4=", + "dev": true, + "requires": { + "readable-stream": "^2.0.4" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "common-style": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/common-style/-/common-style-3.1.0.tgz", + "integrity": "sha1-4klABqWZE2zyYSwTHRENFd4Qz9E=", + "dev": true, + "requires": { + "fashion-show": "^3.2.1", + "jscs": "^2.1.1", + "jshint": "^2.8.0" + } + }, + "commoner": { + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz", + "integrity": "sha1-NPw2cs0kOT6LtH5wyqApOBH08sU=", + "dev": true, + "requires": { + "commander": "^2.5.0", + "detective": "^4.3.1", + "glob": "^5.0.15", + "graceful-fs": "^4.1.2", + "iconv-lite": "^0.4.5", + "mkdirp": "^0.5.0", + "private": "^0.1.6", + "q": "^1.1.2", + "recast": "^0.11.17" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", + "dev": true, + "requires": { + "ast-types": "0.9.6", + "esprima": "~3.1.0", + "private": "~0.1.5", + "source-map": "~0.5.0" + } + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=" + }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=", + "dev": true + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.1.tgz", + "integrity": "sha512-7Et6r6XfNW61CPPCIYfm1YPGSmh6+CliYeL4km7GWJcpX5LTAflGF8drLLR+MZX+2P3NZfAfSduutBbSWqER4g==", + "dev": true, + "requires": { + "es-abstract": "^1.16.3", + "es-get-iterator": "^1.0.1", + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "isarray": "^2.0.5", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0", + "side-channel": "^1.0.1", + "which-boxed-primitive": "^1.0.1", + "which-collection": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "defs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/defs/-/defs-1.1.1.tgz", + "integrity": "sha1-siYJ8sehG6ej2xFoBcE5scr/qdI=", + "dev": true, + "requires": { + "alter": "~0.2.0", + "ast-traverse": "~0.1.1", + "breakable": "~1.0.0", + "esprima-fb": "~15001.1001.0-dev-harmony-fb", + "simple-fmt": "~0.1.0", + "simple-is": "~0.2.0", + "stringmap": "~0.2.2", + "stringset": "~0.2.1", + "tryor": "~0.1.2", + "yargs": "~3.27.0" + }, + "dependencies": { + "esprima-fb": { + "version": "15001.1001.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz", + "integrity": "sha1-Q761fsJujPI3092LM+QlM1d/Jlk=", + "dev": true + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", + "dev": true + }, + "yargs": { + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.27.0.tgz", + "integrity": "sha1-ISBUaTFuk5Ex1Z8toMbX+YIh6kA=", + "dev": true, + "requires": { + "camelcase": "^1.2.1", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "os-locale": "^1.4.0", + "window-size": "^0.1.2", + "y18n": "^3.2.0" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "detect-indent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz", + "integrity": "sha1-ncXl3bzu+DJXZLlFGwK8bVQIT3U=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "minimist": "^1.1.0", + "repeating": "^1.1.0" + } + }, + "detective": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "dev": true, + "requires": { + "acorn": "^5.2.1", + "defined": "^1.0.0" + } + }, + "diagnostics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.0.tgz", + "integrity": "sha1-4QkJALSVI+hSe+IPCBJ1IF8q42o=", + "dev": true, + "requires": { + "colorspace": "1.0.x", + "enabled": "1.0.x", + "kuler": "0.0.x" + } + }, + "diff": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", + "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", + "dev": true + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + }, + "entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ecstatic": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", + "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", + "requires": { + "he": "^1.1.1", + "mime": "^1.6.0", + "minimist": "^1.1.0", + "url-join": "^2.0.5" + } + }, + "enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", + "dev": true, + "requires": { + "env-variable": "0.0.x" + } + }, + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "dev": true + }, + "env-variable": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz", + "integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg==", + "dev": true + }, + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-get-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", + "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", + "dev": true, + "requires": { + "es-abstract": "^1.17.4", + "has-symbols": "^1.0.1", + "is-arguments": "^1.0.4", + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + }, + "dependencies": { + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "eventemitter3": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", + "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==" + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", + "dev": true + }, + "fashion-show": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fashion-show/-/fashion-show-3.3.3.tgz", + "integrity": "sha1-wBwRyT+nFcGmfPU0317xU/bdIvE=", + "dev": true, + "requires": { + "async": "~0.9.0", + "chalk": "^1.1.0", + "diagnostics": "1.1.0", + "minimist": "^1.1.2", + "object-assign": "^4.0.1", + "yargs": "~3.5.4" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + } + } + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "follow-redirects": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.11.0.tgz", + "integrity": "sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA==", + "requires": { + "debug": "^3.0.0" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-readdir-recursive": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-0.1.2.tgz", + "integrity": "sha1-MVtPuMHKW4xH3v7zGdBz2tNWgFk=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-6.4.1.tgz", + "integrity": "sha1-hJgDKzttHMge68X3lpDY/in6v08=", + "dev": true + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, + "home-or-tmp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-1.0.0.tgz", + "integrity": "sha1-S58eQIAMPlDGwn94FnavzOcfOYU=", + "dev": true, + "requires": { + "os-tmpdir": "^1.0.1", + "user-home": "^1.1.1" + } + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dev": true, + "requires": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "http-proxy": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", + "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "i": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/i/-/i-0.3.6.tgz", + "integrity": "sha1-2WyScyB28HJxG2sQ/X1PZa2O4j0=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherit": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/inherit/-/inherit-2.2.7.tgz", + "integrity": "sha512-dxJmC1j0Q32NFAjvbd6g3lXYLZ49HgzotgbSMwMkoiTXGhC9412Oc24g7A7M9cPPkw/vDsF2cSII+2zJwocUtQ==", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, + "is-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.0.tgz", + "integrity": "sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g==", + "dev": true + }, + "is-boolean-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz", + "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true + }, + "is-integer": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-integer/-/is-integer-1.0.7.tgz", + "integrity": "sha1-a96Bqs3feLZZtmKdYpytxRqIbVw=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "is-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", + "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", + "dev": true + }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", + "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", + "dev": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true + }, + "is-weakset": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz", + "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-tokens": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.1.tgz", + "integrity": "sha1-zENaXIuUrRWst5gxQPyAGCyJrq4=", + "dev": true + }, + "js-yaml": { + "version": "3.4.6", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.4.6.tgz", + "integrity": "sha1-a+GyP2JJ9T0pM3D9TRqqY84bTrA=", + "dev": true, + "requires": { + "argparse": "^1.0.2", + "esprima": "^2.6.0", + "inherit": "^2.2.2" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jscs": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/jscs/-/jscs-2.11.0.tgz", + "integrity": "sha1-bhHvDKqgdzH53MKysn2OzuHdvLY=", + "dev": true, + "requires": { + "babel-jscs": "^2.0.0", + "chalk": "~1.1.0", + "cli-table": "~0.3.1", + "commander": "~2.9.0", + "escope": "^3.2.0", + "esprima": "~2.7.0", + "estraverse": "^4.1.0", + "exit": "~0.1.2", + "glob": "^5.0.1", + "htmlparser2": "3.8.3", + "js-yaml": "~3.4.0", + "jscs-jsdoc": "^1.3.1", + "jscs-preset-wikimedia": "~1.0.0", + "jsonlint": "~1.6.2", + "lodash": "~3.10.0", + "minimatch": "~3.0.0", + "natural-compare": "~1.2.2", + "pathval": "~0.1.1", + "prompt": "~0.2.14", + "reserved-words": "^0.1.1", + "resolve": "^1.1.6", + "strip-bom": "^2.0.0", + "strip-json-comments": "~1.0.2", + "to-double-quotes": "^2.0.0", + "to-single-quotes": "^2.0.0", + "vow": "~0.4.8", + "vow-fs": "~0.3.4", + "xmlbuilder": "^3.1.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "jscs-jsdoc": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/jscs-jsdoc/-/jscs-jsdoc-1.3.2.tgz", + "integrity": "sha1-HyyCtqtLl1JNqVj0a05WLgMF+ac=", + "dev": true, + "requires": { + "comment-parser": "^0.3.1", + "jsdoctypeparser": "~1.2.0" + } + }, + "jscs-preset-wikimedia": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jscs-preset-wikimedia/-/jscs-preset-wikimedia-1.0.1.tgz", + "integrity": "sha512-RWqu6IYSUlnYuCRCF0obCOHjJV0vhpLcvKbauwxmLQoZ0PiXDTWBYlfpsEfdhg7pmREAEwrARfDRz5qWD6qknA==", + "dev": true + }, + "jsdoctypeparser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-1.2.0.tgz", + "integrity": "sha1-597cFToRhJ/8UUEUSuhqfvDCU5I=", + "dev": true, + "requires": { + "lodash": "^3.7.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "jshint": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.11.0.tgz", + "integrity": "sha512-ooaD/hrBPhu35xXW4gn+o3SOuzht73gdBuffgJzrZBJZPGgGiiTvJEgTyxFvBO2nz0+X1G6etF8SzUODTlLY6Q==", + "dev": true, + "requires": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.11", + "minimatch": "~3.0.2", + "shelljs": "0.3.x", + "strip-json-comments": "1.0.x" + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.4.0.tgz", + "integrity": "sha1-BUNS5MTIDIbAkjh31EneF2pzLI0=", + "dev": true + }, + "jsonlint": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.3.tgz", + "integrity": "sha512-jMVTMzP+7gU/IyC6hvKyWpUU8tmTkK5b3BPNuMI9U8Sit+YAWLlZwB6Y6YrdCxfg2kNz05p3XY3Bmm4m26Nv3A==", + "dev": true, + "requires": { + "JSV": "^4.0.x", + "nomnom": "^1.5.x" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "kuler": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-0.0.0.tgz", + "integrity": "sha1-tmu0a5NOVQ9Z2BiEjgq7pPf1VTw=", + "dev": true, + "requires": { + "colornames": "0.0.2" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "leven": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/leven/-/leven-1.0.2.tgz", + "integrity": "sha1-kUS27ryl8dBoAWnxpncNzqYLdcM=", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", + "dev": true + }, + "lodash._createassigner": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", + "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", + "dev": true, + "requires": { + "lodash._bindcallback": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash.restparam": "^3.0.0" + } + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.assign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", + "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", + "dev": true, + "requires": { + "lodash._baseassign": "^3.0.0", + "lodash._createassigner": "^3.0.0", + "lodash.keys": "^3.0.0" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "natural-compare": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.2.2.tgz", + "integrity": "sha1-H5bWDjFBysG20FZTzg2urHY69qo=", + "dev": true + }, + "ncp": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz", + "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nomnom": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "dev": true, + "requires": { + "chalk": "~0.4.0", + "underscore": "~1.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "dev": true + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "dev": true, + "requires": { + "ansi-styles": "~1.0.0", + "has-color": "~0.1.0", + "strip-ansi": "~0.1.0" + } + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", + "dev": true + } + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", + "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", + "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.4", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.0" + } + }, + "path-exists": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-1.0.0.tgz", + "integrity": "sha1-1aiZjrce83p0w06w2eum6HjuoIE=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "pathval": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-0.1.1.tgz", + "integrity": "sha1-CPkRzcqczllCiA2ngXvAtyO2bYI=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pkginfo": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.4.1.tgz", + "integrity": "sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=", + "dev": true + }, + "portfinder": { + "version": "1.0.25", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz", + "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==", + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "prompt": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/prompt/-/prompt-0.2.14.tgz", + "integrity": "sha1-V3VPZPVD/XsIRXB8gY7OYY8F/9w=", + "dev": true, + "requires": { + "pkginfo": "0.x.x", + "read": "1.0.x", + "revalidator": "0.1.x", + "utile": "0.2.x", + "winston": "0.8.x" + } + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.6.0.tgz", + "integrity": "sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA==" + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true, + "requires": { + "mute-stream": "~0.0.4" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "recast": { + "version": "0.10.33", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.10.33.tgz", + "integrity": "sha1-lCgI96oBbx+nFCxGHX5XBKqo1pc=", + "dev": true, + "requires": { + "ast-types": "0.8.12", + "esprima-fb": "~15001.1001.0-dev-harmony-fb", + "private": "~0.1.5", + "source-map": "~0.5.0" + }, + "dependencies": { + "ast-types": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.8.12.tgz", + "integrity": "sha1-oNkOQ1G7iHcWyD/WN+v4GK9K38w=", + "dev": true + }, + "esprima-fb": { + "version": "15001.1001.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz", + "integrity": "sha1-Q761fsJujPI3092LM+QlM1d/Jlk=", + "dev": true + } + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerator": { + "version": "0.8.40", + "resolved": "https://registry.npmjs.org/regenerator/-/regenerator-0.8.40.tgz", + "integrity": "sha1-oORXxY69uuV1yfjNdRJ+k3VkNdg=", + "dev": true, + "requires": { + "commoner": "~0.10.3", + "defs": "~1.1.0", + "esprima-fb": "~15001.1001.0-dev-harmony-fb", + "private": "~0.1.5", + "recast": "0.10.33", + "through": "~2.3.8" + }, + "dependencies": { + "esprima-fb": { + "version": "15001.1001.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz", + "integrity": "sha1-Q761fsJujPI3092LM+QlM1d/Jlk=", + "dev": true + } + } + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "regexpu": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexpu/-/regexpu-1.3.0.tgz", + "integrity": "sha1-5TTcmRqeWEYFDJjebX3UpVyeoW0=", + "dev": true, + "requires": { + "esprima": "^2.6.0", + "recast": "^0.10.10", + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", + "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + } + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "reserved-words": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz", + "integrity": "sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=", + "dev": true + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "revalidator": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", + "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=" + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shelljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", + "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", + "dev": true + }, + "side-channel": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz", + "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==", + "dev": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "object-inspect": "^1.7.0" + } + }, + "simple-fmt": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/simple-fmt/-/simple-fmt-0.1.0.tgz", + "integrity": "sha1-GRv1ZqWeZTBILLJatTtKjchcOms=", + "dev": true + }, + "simple-is": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/simple-is/-/simple-is-0.2.0.tgz", + "integrity": "sha1-Krt1qt453rXMgVzhDmGRFkhQuvA=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.2.10.tgz", + "integrity": "sha1-6lo5AKHByyUJagrozFwrSxDe09w=", + "dev": true, + "requires": { + "source-map": "0.1.32" + }, + "dependencies": { + "source-map": { + "version": "0.1.32", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", + "integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "stringmap": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stringmap/-/stringmap-0.2.2.tgz", + "integrity": "sha1-VWwTeyWPlCuHdvWy71gqoGnX0bE=", + "dev": true + }, + "stringset": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/stringset/-/stringset-0.2.1.tgz", + "integrity": "sha1-7yWcTjSTRDd/zRyRPdLoSMnAQrU=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "text-hex": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-0.0.0.tgz", + "integrity": "sha1-V4+8haapJjbkLdF7QdAhjM6esrM=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "to-double-quotes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-double-quotes/-/to-double-quotes-2.0.0.tgz", + "integrity": "sha1-qvIx1vqUiUn4GTAburRITYWI5Kc=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-single-quotes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/to-single-quotes/-/to-single-quotes-2.0.1.tgz", + "integrity": "sha1-fMKRUfD18sQZRvEZ9ZMv5VQXASU=", + "dev": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "try-resolve": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/try-resolve/-/try-resolve-1.0.1.tgz", + "integrity": "sha1-z95vq9ctY+V5fPqrhzq76OcA6RI=", + "dev": true + }, + "tryor": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tryor/-/tryor-0.1.2.tgz", + "integrity": "sha1-gUXkynyv9ArN48z5Rui4u3W0Fys=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", + "dev": true + }, + "union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "requires": { + "qs": "^6.4.0" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "url-join": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=" + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utile": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/utile/-/utile-0.2.1.tgz", + "integrity": "sha1-kwyI6ZCY1iIINMNWy9mncFItkNc=", + "dev": true, + "requires": { + "async": "~0.2.9", + "deep-equal": "*", + "i": "0.3.x", + "mkdirp": "0.x.x", + "ncp": "0.4.x", + "rimraf": "2.x.x" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vow": { + "version": "0.4.20", + "resolved": "https://registry.npmjs.org/vow/-/vow-0.4.20.tgz", + "integrity": "sha512-YYoSYXUYABqY08D/WrjcWJxJSErcILRRTQpcPyUc0SFfgIPKSUFzVt7u1HC3TXGJZM/qhsSjCLNQstxqf7asgQ==", + "dev": true + }, + "vow-fs": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/vow-fs/-/vow-fs-0.3.6.tgz", + "integrity": "sha1-LUxZviLivyYY3fWXq0uqkjvnIA0=", + "dev": true, + "requires": { + "glob": "^7.0.5", + "uuid": "^2.0.2", + "vow": "^0.4.7", + "vow-queue": "^0.4.1" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + } + } + }, + "vow-queue": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/vow-queue/-/vow-queue-0.4.3.tgz", + "integrity": "sha512-/poAKDTFL3zYbeQg7cl4BGcfP4sGgXKrHnRFSKj97dteUFu8oyXMwIcdwu8NSx/RmPGIuYx1Bik/y5vU4H/VKw==", + "dev": true, + "requires": { + "vow": "^0.4.17" + } + }, + "vows": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/vows/-/vows-0.8.3.tgz", + "integrity": "sha512-PVIxa/ovXhrw5gA3mz6M+ZF3PHlqX4tutR2p/y9NWPAaFVKcWBE8b2ktfr0opQM/qFmcOVWKjSCJVjnYOvjXhw==", + "dev": true, + "requires": { + "diff": "^4.0.1", + "eyes": "~0.1.6", + "glob": "^7.1.2" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "which-boxed-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz", + "integrity": "sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ==", + "dev": true, + "requires": { + "is-bigint": "^1.0.0", + "is-boolean-object": "^1.0.0", + "is-number-object": "^1.0.3", + "is-string": "^1.0.4", + "is-symbol": "^1.0.2" + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "winston": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-0.8.3.tgz", + "integrity": "sha1-ZLar9M0Brcrv1QCTk7HY6L7BnbA=", + "dev": true, + "requires": { + "async": "0.2.x", + "colors": "0.6.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "pkginfo": "0.3.x", + "stack-trace": "0.0.x" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "pkginfo": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xmlbuilder": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-3.1.0.tgz", + "integrity": "sha1-LIaIjy1OrehQ+jjKf3Ij9yCVFuE=", + "dev": true, + "requires": { + "lodash": "^3.5.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", + "integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "decamelize": "^1.0.0", + "window-size": "0.1.0", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + } + } +} diff --git a/package.json b/package.json index 8ad9ea3f9..19ef25a30 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,40 @@ { "name": "http-server", - "version": "0.6.1", - "author": "Nodejitsu ", - "description": "a simple zero-configuration command-line http server", + "version": "0.12.3", + "description": "A simple zero-configuration command-line http server", "main": "./lib/http-server", "repository": { "type": "git", - "url": "git://github.com/nodeapps/http-server.git" + "url": "git://github.com/http-party/http-server.git" }, "keywords": [ "cli", - "command" + "command", + "http", + "https", + "http-server", + "https-server", + "server" ], "scripts": { "start": "node ./bin/http-server", + "pretest": "common bin/http-server lib/ test", "test": "vows --spec --isolate" }, + "files": [ + "lib", + "bin", + "doc" + ], + "man": "./doc/http-server.1", + "engines": { + "node": ">=6" + }, "contributors": [ + { + "name": "Charlie Robbins", + "email": "charlie.robbins@gmail.com" + }, { "name": "Marak Squires", "email": "marak.squires@gmail.com" @@ -47,32 +65,48 @@ { "name": "Travis Person", "email": "travis.person@gmail.com" + }, + { + "name": "Jinkwon Lee", + "email": "master@bdyne.net" + }, + { + "name": "BigBlueHat", + "email": "byoung@bigbluehat.com" + }, + { + "name": "Daniel Dalton", + "email": "daltond2@hawkmail.newpaltz.edu" + }, + { + "name": "Jade Michael Thornton", + "email": "jade@jmthornton.net" } ], "dependencies": { - "colors": "0.6.x", - "optimist": "0.5.x", - "union": "0.3.x", - "ecstatic": "0.4.x", - "portfinder": "0.2.x", - "opener": "~1.3.0" + "basic-auth": "^1.0.3", + "colors": "^1.4.0", + "corser": "^2.0.1", + "ecstatic": "^3.3.2", + "http-proxy": "^1.18.0", + "minimist": "^1.2.5", + "opener": "^1.5.1", + "portfinder": "^1.0.25", + "secure-compare": "3.0.1", + "union": "~0.5.0" }, "devDependencies": { - "vows": "0.7.x", - "request": "2.21.x" + "common-style": "^3.0.0", + "request": "^2.88.2", + "vows": "~0.8.3" }, "bugs": { - "url": "https://github.com/nodeapps/http-server/issues" + "url": "https://github.com/http-party/http-server/issues" }, - "licenses": [ - { - "type": "MIT", - "url": "https://github.com/nodeapps/http-server/raw/master/LICENSE" - } - ], - "analyze": false, - "preferGlobal": "true", + "license": "MIT", + "preferGlobal": true, "bin": { - "http-server": "./bin/http-server" + "http-server": "./bin/http-server", + "hs": "./bin/http-server" } } diff --git a/public/img/turtle.png b/public/img/turtle.png index 721a796bb..446cad56c 100644 Binary files a/public/img/turtle.png and b/public/img/turtle.png differ diff --git a/screenshots/directory.png b/screenshots/directory.png index b255cea23..1a7d15b88 100644 Binary files a/screenshots/directory.png and b/screenshots/directory.png differ diff --git a/screenshots/public.png b/screenshots/public.png index aa007bdc7..1a732c461 100644 Binary files a/screenshots/public.png and b/screenshots/public.png differ diff --git a/screenshots/start.png b/screenshots/start.png index d4ea2b8a2..b53f95182 100644 Binary files a/screenshots/start.png and b/screenshots/start.png differ diff --git a/test/fixtures/root/compression/index.html b/test/fixtures/root/compression/index.html new file mode 100644 index 000000000..d22051964 --- /dev/null +++ b/test/fixtures/root/compression/index.html @@ -0,0 +1 @@ +I'm not compressed! diff --git a/test/fixtures/root/compression/index.html.br b/test/fixtures/root/compression/index.html.br new file mode 100644 index 000000000..7f1d5c801 --- /dev/null +++ b/test/fixtures/root/compression/index.html.br @@ -0,0 +1,3 @@ + +�im brotli compressed!! + diff --git a/test/fixtures/root/compression/index.html.gz b/test/fixtures/root/compression/index.html.gz new file mode 100644 index 000000000..4d3f3cbd6 Binary files /dev/null and b/test/fixtures/root/compression/index.html.gz differ diff --git a/test/fixtures/root/htmlButNot b/test/fixtures/root/htmlButNot new file mode 100644 index 000000000..3d6a33f6d --- /dev/null +++ b/test/fixtures/root/htmlButNot @@ -0,0 +1,4 @@ +
+

I am HTML?

+ yeah i guess +
diff --git a/test/http-server-test.js b/test/http-server-test.js index 21e0164e0..6d5fce462 100644 --- a/test/http-server-test.js +++ b/test/http-server-test.js @@ -5,18 +5,23 @@ var assert = require('assert'), request = require('request'), httpServer = require('../lib/http-server'); +// Prevent vows from swallowing errors +process.on('uncaughtException', console.error); + var root = path.join(__dirname, 'fixtures', 'root'); vows.describe('http-server').addBatch({ - 'When http-server is listening on 8080': { + 'When http-server is listening on 8080,\n': { topic: function () { var server = httpServer.createServer({ root: root, + robots: true, headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': 'true' } }); + server.listen(8080); this.callback(null, server); }, @@ -39,7 +44,7 @@ vows.describe('http-server').addBatch({ } } }, - 'when requesting non-existent file': { + 'and a non-existent file is requested...': { topic: function () { request('http://127.0.0.1:8080/404', this.callback); }, @@ -47,7 +52,7 @@ vows.describe('http-server').addBatch({ assert.equal(res.statusCode, 404); } }, - 'when requesting /': { + 'requesting /': { topic: function () { request('http://127.0.0.1:8080/', this.callback); }, @@ -57,14 +62,457 @@ vows.describe('http-server').addBatch({ assert.include(body, '/canYouSeeMe'); } }, - 'and options include custom set http-headers': { + 'when robots option is toggled on...': { + topic: function () { + request('http://127.0.0.1:8080/robots.txt', this.callback); + }, + 'should respond with status code 200 to /robots.txt': function (res) { + assert.equal(res.statusCode, 200); + } + }, + 'and options include custom set http-headers...': { topic: function () { request('http://127.0.0.1:8080/', this.callback); }, - 'should respond with headers set in options': function (err, res, body) { + 'should respond with headers set in options': function (err, res) { assert.equal(res.headers['access-control-allow-origin'], '*'); assert.equal(res.headers['access-control-allow-credentials'], 'true'); } + }, + 'and the server is set to proxy port 8081 to 8080, ': { + topic: function () { + var proxyServer = httpServer.createServer({ + proxy: 'http://127.0.0.1:8080/', + root: path.join(__dirname, 'fixtures') + }); + proxyServer.listen(8081); + this.callback(null, proxyServer); + }, + '\nit should serve files from the proxy\'s root': { + topic: function () { + request('http://127.0.0.1:8081/root/file', this.callback); + }, + 'status code should be the endpoint code 200': function (res) { + assert.equal(res.statusCode, 200); + }, + 'and file content': { + topic: function (res, body) { + var self = this; + fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) { + self.callback(err, data, body); + }); + }, + 'should match content of the served file': function (err, file, body) { + assert.equal(body.trim(), file.trim()); + } + } + }, + '\nit should fallback to the proxied server': { + topic: function () { + request('http://127.0.0.1:8081/file', this.callback); + }, + 'status code should be the endpoint code 200': function (res) { + assert.equal(res.statusCode, 200); + }, + 'and file content': { + topic: function (res, body) { + var self = this; + fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) { + self.callback(err, data, body); + }); + }, + 'should match content of the proxied served file': function (err, file, body) { + assert.equal(body.trim(), file.trim()); + } + } + }, + teardown: function (proxyServer) { + proxyServer.close(); + } + }, + teardown: function (server) { + server.close(); + } + }, + 'When CORS is enabled': { + topic: function () { + var server = httpServer.createServer({ + root: root, + cors: true, + corsHeaders: 'X-Test' + }); + server.listen(8082); + this.callback(null, server); + }, + 'and the server is given an OPTIONS request': { + topic: function () { + request({ + method: 'OPTIONS', + uri: 'http://127.0.0.1:8082/', + headers: { + 'Access-Control-Request-Method': 'GET', + Origin: 'http://example.com', + 'Access-Control-Request-Headers': 'Foobar' + } + }, this.callback); + }, + 'status code should be 204': function (err, res) { + assert.equal(res.statusCode, 204); + }, + 'response Access-Control-Allow-Headers should contain X-Test': function (err, res) { + assert.ok(res.headers['access-control-allow-headers'].split(/\s*,\s*/g).indexOf('X-Test') >= 0, 204); + } + }, + teardown: function (server) { + server.close(); + } + }, + 'When gzip and brotli compression is enabled and a compressed file is available': { + topic: function () { + var server = httpServer.createServer({ + root: root, + brotli: true, + gzip: true + }); + server.listen(8084); + this.callback(null, server); + }, + 'and a request accepting only gzip is made': { + topic: function () { + request({ + uri: 'http://127.0.0.1:8084/compression/', + headers: { + 'accept-encoding': 'gzip' + } + }, this.callback); + }, + 'response should be gzip compressed': function (err, res, body) { + assert.equal(res.statusCode, 200); + assert.equal(res.headers['content-encoding'], 'gzip'); + } + }, + 'and a request accepting only brotli is made': { + topic: function () { + request({ + uri: 'http://127.0.0.1:8084/compression/', + headers: { + 'accept-encoding': 'br' + } + }, this.callback); + }, + 'response should be brotli compressed': function (err, res, body) { + assert.equal(res.statusCode, 200); + assert.equal(res.headers['content-encoding'], 'br'); + } + }, + 'and a request accepting both brotli and gzip is made': { + topic: function () { + request({ + uri: 'http://127.0.0.1:8084/compression/', + headers: { + 'accept-encoding': 'gzip, br' + } + }, this.callback); + }, + 'response should be brotli compressed': function (err, res, body) { + assert.equal(res.statusCode, 200); + assert.equal(res.headers['content-encoding'], 'br'); + } + }, + teardown: function (server) { + server.close(); + } + }, + 'When http-server is listening on 8083 with username "good_username" and password "good_password"': { + topic: function () { + var server = httpServer.createServer({ + root: root, + robots: true, + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Credentials': 'true' + }, + username: 'good_username', + password: 'good_password' + }); + + server.listen(8083); + this.callback(null, server); + }, + 'and the user requests an existent file with no auth details': { + topic: function () { + request('http://127.0.0.1:8083/file', this.callback); + }, + 'status code should be 401': function (res) { + assert.equal(res.statusCode, 401); + }, + 'and file content': { + topic: function (res, body) { + var self = this; + fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) { + self.callback(err, data, body); + }); + }, + 'should be a forbidden message': function (err, file, body) { + assert.equal(body, 'Access denied'); + } + } + }, + 'and the user requests an existent file with incorrect username': { + topic: function () { + request('http://127.0.0.1:8083/file', { + auth: { + user: 'wrong_username', + pass: 'good_password' + } + }, this.callback); + }, + 'status code should be 401': function (res) { + assert.equal(res.statusCode, 401); + }, + 'and file content': { + topic: function (res, body) { + var self = this; + fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) { + self.callback(err, data, body); + }); + }, + 'should be a forbidden message': function (err, file, body) { + assert.equal(body, 'Access denied'); + } + } + }, + 'and the user requests an existent file with incorrect password': { + topic: function () { + request('http://127.0.0.1:8083/file', { + auth: { + user: 'good_username', + pass: 'wrong_password' + } + }, this.callback); + }, + 'status code should be 401': function (res) { + assert.equal(res.statusCode, 401); + }, + 'and file content': { + topic: function (res, body) { + var self = this; + fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) { + self.callback(err, data, body); + }); + }, + 'should be a forbidden message': function (err, file, body) { + assert.equal(body, 'Access denied'); + } + } + }, + 'and the user requests a non-existent file with incorrect password': { + topic: function () { + request('http://127.0.0.1:8083/404', { + auth: { + user: 'good_username', + pass: 'wrong_password' + } + }, this.callback); + }, + 'status code should be 401': function (res) { + assert.equal(res.statusCode, 401); + }, + 'and file content': { + topic: function (res, body) { + var self = this; + fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) { + self.callback(err, data, body); + }); + }, + 'should be a forbidden message': function (err, file, body) { + assert.equal(body, 'Access denied'); + } + } + }, + 'and the user requests an existent file with correct auth details': { + topic: function () { + request('http://127.0.0.1:8083/file', { + auth: { + user: 'good_username', + pass: 'good_password' + } + }, this.callback); + }, + 'status code should be 200': function (res) { + assert.equal(res.statusCode, 200); + }, + 'and file content': { + topic: function (res, body) { + var self = this; + fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) { + self.callback(err, data, body); + }); + }, + 'should match content of served file': function (err, file, body) { + assert.equal(body.trim(), file.trim()); + } + } + }, + teardown: function (server) { + server.close(); + } + }, + 'When auto-ext is enabled': { + topic: function () { + var server = httpServer.createServer({ + root: root, + ext: true + }); + server.listen(8085); + this.callback(null, server); + }, + 'and a file with no extension is requested with default options,': { + topic: function () { + request('http://127.0.0.1:8085/htmlButNot', this.callback); + }, + 'content-type should be text/html': function (res) { + assert.equal(res.statusCode, 200); + assert.match(res.headers['content-type'], /^text\/html/); + } + }, + teardown: function (server) { + server.close(); + } + }, + 'When http-server is listening on 8086 with username "good_username" and Number type password 123456': { + topic: function () { + var server = httpServer.createServer({ + root: root, + robots: true, + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Credentials': 'true' + }, + username: 'good_username', + password: 123456 + }); + + server.listen(8086); + this.callback(null, server); + }, + 'and the user requests an existent file with no auth details': { + topic: function () { + request('http://127.0.0.1:8086/file', this.callback); + }, + 'status code should be 401': function (res) { + assert.equal(res.statusCode, 401); + }, + 'and file content': { + topic: function (res, body) { + var self = this; + fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) { + self.callback(err, data, body); + }); + }, + 'should be a forbidden message': function (err, file, body) { + assert.equal(body, 'Access denied'); + } + } + }, + 'and the user requests an existent file with incorrect username': { + topic: function () { + request('http://127.0.0.1:8086/file', { + auth: { + user: 'wrong_username', + pass: '123456' + } + }, this.callback); + }, + 'status code should be 401': function (res) { + assert.equal(res.statusCode, 401); + }, + 'and file content': { + topic: function (res, body) { + var self = this; + fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) { + self.callback(err, data, body); + }); + }, + 'should be a forbidden message': function (err, file, body) { + assert.equal(body, 'Access denied'); + } + } + }, + 'and the user requests an existent file with incorrect password': { + topic: function () { + request('http://127.0.0.1:8086/file', { + auth: { + user: 'good_username', + pass: '654321' + } + }, this.callback); + }, + 'status code should be 401': function (res) { + assert.equal(res.statusCode, 401); + }, + 'and file content': { + topic: function (res, body) { + var self = this; + fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) { + self.callback(err, data, body); + }); + }, + 'should be a forbidden message': function (err, file, body) { + assert.equal(body, 'Access denied'); + } + } + }, + 'and the user requests a non-existent file with incorrect password': { + topic: function () { + request('http://127.0.0.1:8086/404', { + auth: { + user: 'good_username', + pass: '654321' + } + }, this.callback); + }, + 'status code should be 401': function (res) { + assert.equal(res.statusCode, 401); + }, + 'and file content': { + topic: function (res, body) { + var self = this; + fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) { + self.callback(err, data, body); + }); + }, + 'should be a forbidden message': function (err, file, body) { + assert.equal(body, 'Access denied'); + } + } + }, + 'and the user requests an existent file with correct auth details': { + topic: function () { + request('http://127.0.0.1:8086/file', { + auth: { + user: 'good_username', + pass: '123456' + } + }, this.callback); + }, + 'status code should be 200': function (res) { + assert.equal(res.statusCode, 200); + }, + 'and file content': { + topic: function (res, body) { + var self = this; + fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) { + self.callback(err, data, body); + }); + }, + 'should match content of served file': function (err, file, body) { + assert.equal(body.trim(), file.trim()); + } + } + }, + teardown: function (server) { + server.close(); } } }).export(module);