diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..f0e5fbdd --- /dev/null +++ b/.eslintignore @@ -0,0 +1,84 @@ +CHANGELOG.md +README.md +*.d.ts +recipes +patches + +test-legacy +*.js.snap +*.tsbuildinfo +.cache +.*cache +*.cache + +# TODO: lint +example +benchmark + +# Build environment +dist + +# Package managers lockfiles +package-lock.json +shrinkwrap.json +pnpm-lock.json + +# Logs +logs +*.log +*~ + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..6307a094 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,176 @@ +'use strict'; + +const airbnbBase = require('eslint-config-airbnb-base'); + +// eslint-disable-next-line import/no-dynamic-require +const bestPractices = require(airbnbBase.extends[0]); + +const ignoredProps = bestPractices.rules[ + 'no-param-reassign' +][1].ignorePropertyModificationsFor.concat( + 'err', + 'x', + '_', + 'opts', + 'options', + 'settings', + 'config', + 'cfg', +); + +// Additional rules that are specific and overiding previous +const additionalChanges = { + strict: 'off', + + // Enforce using named functions when regular function is used, + // otherwise use arrow functions + 'func-names': ['error', 'always'], + // Always use parens (for consistency). + // https://eslint.org/docs/rules/arrow-parens + 'arrow-parens': ['error', 'always', { requireForBlockBody: true }], + 'prefer-arrow-callback': [ + 'error', + { allowNamedFunctions: true, allowUnboundThis: true }, + ], + // http://eslint.org/docs/rules/max-params + 'max-params': ['error', { max: 3 }], + // http://eslint.org/docs/rules/max-statements + 'max-statements': ['error', { max: 20 }], + // http://eslint.org/docs/rules/max-statements-per-line + 'max-statements-per-line': ['error', { max: 1 }], + // http://eslint.org/docs/rules/max-nested-callbacks + 'max-nested-callbacks': ['error', { max: 4 }], + // http://eslint.org/docs/rules/max-depth + 'max-depth': ['error', { max: 4 }], + // enforces no braces where they can be omitted + // https://eslint.org/docs/rules/arrow-body-style + // Never enable for object literal. + 'arrow-body-style': [ + 'error', + 'as-needed', + { requireReturnForObjectLiteral: false }, + ], + // Allow functions to be use before define because: + // 1) they are hoisted, + // 2) because ensure read flow is from top to bottom + // 3) logically order of the code. + // 4) the only addition is 'typedefs' option, see overrides for TS files + 'no-use-before-define': [ + 'error', + { + functions: false, + classes: true, + variables: true, + }, + ], + // Same as AirBnB, but adds `opts`, `options`, `x` and `err` to exclusions! + // disallow reassignment of function parameters + // disallow parameter object manipulation except for specific exclusions + // rule: https://eslint.org/docs/rules/no-param-reassign.html + 'no-param-reassign': [ + 'error', + { + props: true, + ignorePropertyModificationsFor: ignoredProps, + }, + ], + + // disallow declaration of variables that are not used in the code + 'no-unused-vars': [ + 'error', + { + ignoreRestSiblings: true, // airbnb's default + vars: 'all', // airbnb's default + varsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))', + args: 'after-used', // airbnb's default + argsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))', + + // catch blocks are handled by Unicorns + caughtErrors: 'none', + // caughtErrorsIgnorePattern: '^(?:$$|xx|_|__|[iI]gnor(?:e|ing|ed))', + }, + ], +}; + +const importRules = { + 'import/namespace': ['error', { allowComputed: true }], + 'import/no-absolute-path': 'error', + 'import/no-webpack-loader-syntax': 'error', + 'import/no-self-import': 'error', + + // Enable this sometime in the future when Node.js has ES2015 module support + // 'import/no-cycle': 'error', + + // Disabled as it doesn't work with TypeScript + // 'import/newline-after-import': 'error', + + 'import/no-amd': 'error', + 'import/no-duplicates': 'error', + + // Enable this sometime in the future when Node.js has ES2015 module support + // 'import/unambiguous': 'error', + + // Enable this sometime in the future when Node.js has ES2015 module support + // 'import/no-commonjs': 'error', + + // Looks useful, but too unstable at the moment + // 'import/no-deprecated': 'error', + + 'import/no-extraneous-dependencies': 'off', + 'import/no-mutable-exports': 'error', + 'import/no-named-as-default-member': 'error', + 'import/no-named-as-default': 'error', + + // Disabled because it's buggy and it also doesn't work with TypeScript + // 'import/no-unresolved': [ + // 'error', + // { + // commonjs: true + // } + // ], + + 'import/order': 'error', + 'import/no-unassigned-import': [ + 'error', + { allow: ['@babel/polyfill', '@babel/register'] }, + ], + + 'import/prefer-default-export': 'off', + + // Ensure more web-compat + // ! note that it doesn't work in CommonJS + // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md + 'import/extensions': 'off', + + // ? Always use named exports. Enable? + // 'import/no-default-export': 'error', + + // ? enable? + 'import/exports-last': 'off', + + // todo: Enable in future. + // Ensures everything is tested (all exports should be used). + // For cases when you don't want or can't test, add eslint-ignore comment! + // see: https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unused-modules.md + 'import/no-unused-modules': 'off', + + 'import/no-useless-path-segments': ['error', { noUselessIndex: false }], +}; + +module.exports = { + env: { + es6: true, + es2020: true, + jest: true, + node: true, + commonjs: true, + }, + extends: ['eslint:recommended', 'airbnb-base', 'plugin:prettier/recommended'], + plugins: ['prettier'], + rules: { + 'prettier/prettier': 'error', + + ...additionalChanges, + ...importRules, + }, +}; diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..8ef910f0 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,97 @@ +CHANGELOG.md +LICENSE +LICENSE.md +LICENSE*.md +dist +# fixture +# fixtures +# __fixture__ +# __fixtures__ +.gitkeep +*.map +*.lock +.npmrc +.yarnrc +*.js.snap +coverage +*.ico +*.png +*.svg +*.jpeg +*.jpg + +.* +!.*rc.js +!.verb*.md +patches +**/static/**/*.css + +*.tsbuildinfo +.cache +.*cache +*.cache + +# Package managers lockfiles +package-lock.json +shrinkwrap.json +pnpm-lock.json + +# Logs +logs +*.log +*~ + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000..2a02d8c0 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require( '@tunnckocore/prettier-config'); diff --git a/benchmark/bench-multipart-parser.js b/benchmark/bench-multipart-parser.js index cdcabe34..72832f35 100644 --- a/benchmark/bench-multipart-parser.js +++ b/benchmark/bench-multipart-parser.js @@ -1,20 +1,19 @@ -var assert = require('assert'); +let assert = require('assert'); require('../test/common'); -var multipartParser = require('../lib/multipart_parser'), - MultipartParser = multipartParser.MultipartParser, - parser = new MultipartParser(), - boundary = '-----------------------------168072824752491622650073', - mb = 100, - buffer = createMultipartBuffer(boundary, mb * 1024 * 1024), - callbacks = - { partBegin: -1, - partEnd: -1, - headerField: -1, - headerValue: -1, - partData: -1, - end: -1, - }; - +let multipartParser = require('../lib/multipart_parser'); + var MultipartParser = multipartParser.MultipartParser; + var parser = new MultipartParser(); + var boundary = '-----------------------------168072824752491622650073'; + var mb = 100; + var buffer = createMultipartBuffer(boundary, mb * 1024 * 1024); + var callbacks = + partBegin: -1, + partEnd: -1, + headerField: -1, + headerValue: -1, + partData: -1, + end: -1, + }; parser.initWithBoundary(boundary); parser.onHeaderField = function() { @@ -41,22 +40,24 @@ parser.onEnd = function() { callbacks.end++; }; -var start = +new Date(), - nparsed = parser.write(buffer), - duration = +new Date() - start, - mbPerSec = (mb / (duration / 1000)).toFixed(2); +let start = +new Date(); + var nparsed = parser.write(buffer); + var duration = +new Date() - start; + var mbPerSec = (mb / (duration / 1000)).toFixed(2); -console.log(mbPerSec+' mb/sec'); +console.log(`${mbPerSec} mb/sec`); assert.equal(nparsed, buffer.length); function createMultipartBuffer(boundary, size) { - var head = - '--'+boundary+'\r\n' - + 'content-disposition: form-data; name="field1"\r\n' - + '\r\n' - , tail = '\r\n--'+boundary+'--\r\n' - , buffer = Buffer.alloc(size); + let head = + '--' + + boundary + + '\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n', + tail = '\r\n--' + boundary + '--\r\n', + buffer = Buffer.alloc(size); buffer.write(head, 0, 'ascii'); buffer.write(tail, buffer.length - tail.length, 'ascii'); @@ -64,7 +65,7 @@ function createMultipartBuffer(boundary, size) { } process.on('exit', function() { - for (var k in callbacks) { - assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]); + for (let k in callbacks) { + assert.equal(0, callbacks[k], `${k} count off by ${callbacks[k]}`); } }); diff --git a/example/json.js b/example/json.js index 34a0d8e9..c0bd4154 100644 --- a/example/json.js +++ b/example/json.js @@ -1,66 +1,73 @@ -var common = require('../test/common'), - http = require('http'), - util = require('util'), - formidable = common.formidable, - port = common.port, - server; +const http = require('http'); +const util = require('util'); +const common = require('../test/common'); -server = http.createServer(function(req, res) { +const { formidable } = common; +const { port } = common; +let server; + +server = http.createServer((req, res) => { if (req.method !== 'POST') { - res.writeHead(200, {'content-type': 'text/plain'}); - res.end('Please POST a JSON payload to http://localhost:'+port+'/'); + res.writeHead(200, { 'content-type': 'text/plain' }); + res.end(`Please POST a JSON payload to http://localhost:${port}/`); return; } - var form = new formidable.IncomingForm(), - fields = {}; + const form = new formidable.IncomingForm(); + const fields = {}; form - .on('error', function(err) { - res.writeHead(500, {'content-type': 'text/plain'}); - res.end('error:\n\n' + util.inspect(err)); + .on('error', (err) => { + res.writeHead(500, { 'content-type': 'text/plain' }); + res.end(`error:\n\n${util.inspect(err)}`); console.error(err); }) - .on('field', function(field, value) { + .on('field', (field, value) => { console.log(field, value); fields[field] = value; }) - .on('end', function() { + .on('end', () => { console.log('-> post done'); - res.writeHead(200, {'content-type': 'text/plain'}); - res.end('received fields:\n\n '+util.inspect(fields)); + res.writeHead(200, { 'content-type': 'text/plain' }); + res.end(`received fields:\n\n ${util.inspect(fields)}`); }); form.parse(req); }); server.listen(port); -console.log('listening on http://localhost:'+port+'/'); +console.log(`listening on http://localhost:${port}/`); -var message = '{"numbers":[1,2,3,4,5],"nested":{"key":"value"}}'; -var request = http.request({ - host: 'localhost', - path: '/', - port: port, - method: 'POST', - headers: { 'content-type':'application/json', 'content-length': message.length } -}, function(response) { - var data = ''; - console.log('\nServer responded with:'); - console.log('Status:', response.statusCode); - response.pipe(process.stdout); - response.on('end', function() { - console.log('\n'); - process.exit(); - }); - // response.on('data', function(chunk) { - // data += chunk.toString('utf8'); - // }); - // response.on('end', function() { - // console.log('Response Data:'); - // console.log(data); - // process.exit(); - // }); -}); +const message = '{"numbers":[1,2,3,4,5],"nested":{"key":"value"}}'; +const request = http.request( + { + host: 'localhost', + path: '/', + port, + method: 'POST', + headers: { + 'content-type': 'application/json', + 'content-length': message.length, + }, + }, + (response) => { + const data = ''; + console.log('\nServer responded with:'); + console.log('Status:', response.statusCode); + response.pipe(process.stdout); + response.on('end', () => { + console.log('\n'); + process.exit(); + }); + // response.on('data', function(chunk) { + // data += chunk.toString('utf8'); + // }); + // response.on('end', function() { + // console.log('Response Data:'); + // console.log(data); + // process.exit(); + // }); + }, +); request.write(message); request.end(); diff --git a/example/multipartParser.js b/example/multipartParser.js index 2c4d5afd..098df73d 100644 --- a/example/multipartParser.js +++ b/example/multipartParser.js @@ -1,24 +1,23 @@ const { MultipartParser } = require('../lib/multipart_parser.js'); - // hand crafted multipart const boundary = '--abcxyz'; const next = '\r\n'; const formData = 'Content-Disposition: form-data; '; const buffer = Buffer.from( - `${boundary}${next}${formData}name="text"${next}${next}text ...${next}${next}${boundary}${next}${formData}name="z"${next}${next}text inside z${next}${next}${boundary}${next}${formData}name="file1"; filename="a.txt"${next}Content-Type: text/plain${next}${next}Content of a.txt.${next}${next}${boundary}${next}${formData}name="file2"; filename="a.html"${next}Content-Type: text/html${next}${next}Content of a.html.${next}${next}${boundary}--` + `${boundary}${next}${formData}name="text"${next}${next}text ...${next}${next}${boundary}${next}${formData}name="z"${next}${next}text inside z${next}${next}${boundary}${next}${formData}name="file1"; filename="a.txt"${next}Content-Type: text/plain${next}${next}Content of a.txt.${next}${next}${boundary}${next}${formData}name="file2"; filename="a.html"${next}Content-Type: text/html${next}${next}Content of a.html.${next}${next}${boundary}--`, ); const multipartParser = new MultipartParser(); -multipartParser.on('data', ({name, buffer, start, end}) => { - console.log(`${name}:`); - if (buffer && start && end) { - console.log(String(buffer.slice(start, end))); - } - console.log(); +multipartParser.on('data', ({ name, buffer, start, end }) => { + console.log(`${name}:`); + if (buffer && start && end) { + console.log(String(buffer.slice(start, end))); + } + console.log(); }); multipartParser.on('error', (error) => { - console.error(error); + console.error(error); }); multipartParser.initWithBoundary(boundary.substring(2)); // todo make better error message when it is forgotten diff --git a/example/multiple.js b/example/multiple.js index e8fcaa1e..fd25c74c 100644 --- a/example/multiple.js +++ b/example/multiple.js @@ -1,14 +1,15 @@ -var common = require('../test/common'); -var http = require('http'), - util = require('util'), - os = require('os'), - formidable = common.formidable, - port = common.port, - server; - -server = http.createServer(function(req, res) { +const http = require('http'); +const util = require('util'); +const os = require('os'); +const common = require('../test/common'); + +const { formidable } = common; +const { port } = common; +let server; + +server = http.createServer((req, res) => { if (req.url === '/') { - res.writeHead(200, {'content-type': 'text/html'}); + res.writeHead(200, { 'content-type': 'text/html' }); res.end( `

@@ -27,24 +28,24 @@ server = http.createServer(function(req, res) {

-
` + `, ); } else if (req.url === '/upload') { - var form = new formidable.IncomingForm({multiples: true}); + const form = new formidable.IncomingForm({ multiples: true }); form.uploadDir = os.tmpdir(); - form.parse(req, function (error, fields, files) { - res.writeHead(200, {'content-type': 'text/plain'}); - res.write('received fields:\n\n '+util.inspect(fields)); + form.parse(req, (error, fields, files) => { + res.writeHead(200, { 'content-type': 'text/plain' }); + res.write(`received fields:\n\n ${util.inspect(fields)}`); res.write('\n\n'); - res.end('received files:\n\n '+util.inspect(files)); - }) + res.end(`received files:\n\n ${util.inspect(files)}`); + }); } else { - res.writeHead(404, {'content-type': 'text/plain'}); + res.writeHead(404, { 'content-type': 'text/plain' }); res.end('404'); } }); server.listen(port); -console.log('listening on http://localhost:'+port+'/'); +console.log(`listening on http://localhost:${port}/`); diff --git a/example/post.js b/example/post.js index cb85881b..45713d65 100644 --- a/example/post.js +++ b/example/post.js @@ -1,44 +1,45 @@ -var common = require('../test/common'); -var http = require('http'), - util = require('util'), - formidable = common.formidable, - port = common.port, - server; +const http = require('http'); +const util = require('util'); +const common = require('../test/common'); -server = http.createServer(function(req, res) { +const { formidable } = common; +const { port } = common; +let server; + +server = http.createServer((req, res) => { if (req.url === '/') { - res.writeHead(200, {'content-type': 'text/html'}); + res.writeHead(200, { 'content-type': 'text/html' }); res.end( `


- '
` + '`, ); } else if (req.url === '/post') { - var form = new formidable.IncomingForm(), - fields = []; + const form = new formidable.IncomingForm(); + const fields = []; form - .on('error', function(err) { - res.writeHead(200, {'content-type': 'text/plain'}); - res.end('error:\n\n'+util.inspect(err)); + .on('error', (err) => { + res.writeHead(200, { 'content-type': 'text/plain' }); + res.end(`error:\n\n${util.inspect(err)}`); }) - .on('field', function(field, value) { + .on('field', (field, value) => { console.log(field, value); fields.push([field, value]); }) - .on('end', function() { + .on('end', () => { console.log('-> post done'); - res.writeHead(200, {'content-type': 'text/plain'}); - res.end('received fields:\n\n '+util.inspect(fields)); + res.writeHead(200, { 'content-type': 'text/plain' }); + res.end(`received fields:\n\n ${util.inspect(fields)}`); }); form.parse(req); } else { - res.writeHead(404, {'content-type': 'text/plain'}); + res.writeHead(404, { 'content-type': 'text/plain' }); res.end('404'); } }); server.listen(port); -console.log('listening on http://localhost:'+port+'/'); +console.log(`listening on http://localhost:${port}/`); diff --git a/example/upload.js b/example/upload.js index 4162323c..1e4e1014 100644 --- a/example/upload.js +++ b/example/upload.js @@ -1,50 +1,51 @@ -var common = require('../test/common'); -var http = require('http'), - util = require('util'), - os = require('os'), - formidable = common.formidable, - port = common.port, - server; +const http = require('http'); +const util = require('util'); +const os = require('os'); +const common = require('../test/common'); -server = http.createServer(function(req, res) { +const { formidable } = common; +const { port } = common; +let server; + +server = http.createServer((req, res) => { if (req.url === '/') { - res.writeHead(200, {'content-type': 'text/html'}); + res.writeHead(200, { 'content-type': 'text/html' }); res.end( `


-
` + `, ); } else if (req.url === '/upload') { - var form = new formidable.IncomingForm(), - files = [], - fields = []; + const form = new formidable.IncomingForm(); + const files = []; + const fields = []; form.uploadDir = os.tmpdir(); form - .on('field', function(field, value) { + .on('field', (field, value) => { console.log(field, value); fields.push([field, value]); }) - .on('file', function(field, file) { + .on('file', (field, file) => { console.log(field, file); files.push([field, file]); }) - .on('end', function() { + .on('end', () => { console.log('-> upload done'); - res.writeHead(200, {'content-type': 'text/plain'}); - res.write('received fields:\n\n '+util.inspect(fields)); + res.writeHead(200, { 'content-type': 'text/plain' }); + res.write(`received fields:\n\n ${util.inspect(fields)}`); res.write('\n\n'); - res.end('received files:\n\n '+util.inspect(files)); + res.end(`received files:\n\n ${util.inspect(files)}`); }); form.parse(req); } else { - res.writeHead(404, {'content-type': 'text/plain'}); + res.writeHead(404, { 'content-type': 'text/plain' }); res.end('404'); } }); server.listen(port); -console.log('listening on http://localhost:'+port+'/'); +console.log(`listening on http://localhost:${port}/`); diff --git a/index.js b/index.js deleted file mode 100644 index 4cc88b35..00000000 --- a/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./lib'); \ No newline at end of file diff --git a/package.json b/package.json index d7375f6f..a667f3d5 100644 --- a/package.json +++ b/package.json @@ -1,28 +1,35 @@ { "name": "formidable", + "version": "1.2.1", + "license": "MIT", "description": "A node.js module for parsing form data, especially file uploads.", "homepage": "https://github.com/node-formidable/node-formidable", - "license": "MIT", - "version": "1.2.1", - "devDependencies": { - "findit": "^0.1.2", - "hashish": "^0.0.4", - "urun": "^0.0.6", - "utest": "^0.0.8", - "request": "^2.11.4" - }, + "funding": "https://ko-fi.com/tunnckoCore/commissions", + "repository": "node-formidable/node-formidable", "main": "./src/index.js", "files": [ "src" ], "scripts": { + "cleanup": "rm -rf test/tmp", + "lint": "eslint . --cache --fix --quiet --format codeframe", "pretest": "yarn run cleanup", - "test": "mkdir test/tmp && node test/run.js", - "cleanup": "rm -rf test/tmp" + "test": "mkdir test/tmp && node test/run.js" + }, + "devDependencies": { + "@tunnckocore/prettier-config": "^1.2.0", + "eslint": "^6.8.0", + "eslint-config-airbnb-base": "^14.0.0", + "eslint-config-prettier": "^6.10.0", + "eslint-plugin-import": "^2.20.0", + "eslint-plugin-prettier": "^3.1.2", + "prettier": "^1.19.1", + "prettier-plugin-pkgjson": "^0.2.0", + "request": "^2.11.4", + "urun": "^0.0.6", + "utest": "^0.0.8" }, - "repository": "node-formidable/node-formidable", "bugs": { "url": "http://github.com/node-formidable/node-formidable/issues" - }, - "funding": "https://ko-fi.com/tunnckoCore/commissions" + } } diff --git a/src/default_options.js b/src/default_options.js index 05c70b31..1ceb57a8 100644 --- a/src/default_options.js +++ b/src/default_options.js @@ -1,11 +1,13 @@ +'use strict'; + const defaultOptions = { - maxFields: 1000, - maxFieldsSize: 20 * 1024 * 1024, - maxFileSize: 200 * 1024 * 1024, - keepExtensions: false, - encoding: 'utf-8', - hash: false, - multiples: false, + maxFields: 1000, + maxFieldsSize: 20 * 1024 * 1024, + maxFileSize: 200 * 1024 * 1024, + keepExtensions: false, + encoding: 'utf-8', + hash: false, + multiples: false, }; exports.defaultOptions = defaultOptions; diff --git a/src/dummy_parser.js b/src/dummy_parser.js index 5e5a4013..4745e784 100644 --- a/src/dummy_parser.js +++ b/src/dummy_parser.js @@ -1,5 +1,8 @@ -const { Transform } = require('stream'); +/* eslint-disable no-underscore-dangle */ + +'use strict'; +const { Transform } = require('stream'); class DummyParser extends Transform { constructor(incomingForm) { @@ -14,5 +17,4 @@ class DummyParser extends Transform { } } - exports.DummyParser = DummyParser; diff --git a/src/file.js b/src/file.js index 73f58521..c3252551 100644 --- a/src/file.js +++ b/src/file.js @@ -1,81 +1,88 @@ -var util = require('util'), - fs = require('fs'), - EventEmitter = require('events').EventEmitter, - crypto = require('crypto'); +/* eslint-disable no-underscore-dangle */ -function File(properties) { - EventEmitter.call(this); +'use strict'; - this.size = 0; - this.path = null; - this.name = null; - this.type = null; - this.hash = null; - this.lastModifiedDate = null; +const fs = require('fs'); +const crypto = require('crypto'); +const { EventEmitter } = require('events'); - this._writeStream = null; +class File extends EventEmitter { + constructor(properties) { + super(); - for (var key in properties) { - this[key] = properties[key]; - } - - if(typeof this.hash === 'string') { - this.hash = crypto.createHash(properties.hash); - } else { + this.size = 0; + this.path = null; + this.name = null; + this.type = null; this.hash = null; - } -} -module.exports = File; -util.inherits(File, EventEmitter); + this.lastModifiedDate = null; + + this._writeStream = null; -File.prototype.open = function() { - this._writeStream = new fs.WriteStream(this.path); -}; + // eslint-disable-next-line guard-for-in, no-restricted-syntax + for (const key in properties) { + this[key] = properties[key]; + } -File.prototype.toJSON = function() { - var json = { - size: this.size, - path: this.path, - name: this.name, - type: this.type, - mtime: this.lastModifiedDate, - length: this.length, - filename: this.filename, - mime: this.mime - }; - if (this.hash && this.hash != "") { - json.hash = this.hash; + if (typeof this.hash === 'string') { + this.hash = crypto.createHash(properties.hash); + } else { + this.hash = null; + } } - return json; -}; -File.prototype.toString = function () { - return `File: ${this.name}, Path: ${this.path}`; -}; + open() { + this._writeStream = new fs.WriteStream(this.path); + } -File.prototype.write = function(buffer, cb) { - if (this.hash) { - this.hash.update(buffer); + toJSON() { + const json = { + size: this.size, + path: this.path, + name: this.name, + type: this.type, + mtime: this.lastModifiedDate, + length: this.length, + filename: this.filename, + mime: this.mime, + }; + if (this.hash && this.hash !== '') { + json.hash = this.hash; + } + return json; } - if (this._writeStream.closed) { - return cb(); + toString() { + return `File: ${this.name}, Path: ${this.path}`; } - this._writeStream.write(buffer, () => { - this.lastModifiedDate = new Date(); - this.size += buffer.length; - this.emit('progress', this.size); - cb(); - }); -}; + write(buffer, cb) { + if (this.hash) { + this.hash.update(buffer); + } -File.prototype.end = function(cb) { - if (this.hash) { - this.hash = this.hash.digest('hex'); + if (this._writeStream.closed) { + cb(); + return; + } + + this._writeStream.write(buffer, () => { + this.lastModifiedDate = new Date(); + this.size += buffer.length; + this.emit('progress', this.size); + cb(); + }); + } + + end(cb) { + if (this.hash) { + this.hash = this.hash.digest('hex'); + } + this._writeStream.end(() => { + this.emit('end'); + cb(); + }); } - this._writeStream.end(() => { - this.emit('end'); - cb(); - }); -}; +} + +exports.File = File; diff --git a/src/incoming_form.js b/src/incoming_form.js index 49f56753..0a2aa4b0 100644 --- a/src/incoming_form.js +++ b/src/incoming_form.js @@ -1,88 +1,89 @@ -var crypto = require('crypto'); -var fs = require('fs'); -var util = require('util'), - path = require('path'), - File = require('./file'), - defaultOptions = require('./default_options').defaultOptions, - DummyParser = require('./dummy_parser').DummyParser, - MultipartParser = require('./multipart_parser').MultipartParser, - QuerystringParser = require('./querystring_parser').QuerystringParser, - OctetParser = require('./octet_parser').OctetParser, - JSONParser = require('./json_parser').JSONParser, - StringDecoder = require('string_decoder').StringDecoder, - EventEmitter = require('events').EventEmitter, - Stream = require('stream').Stream, - os = require('os'); +/* eslint-disable class-methods-use-this */ +/* eslint-disable no-underscore-dangle */ + +'use strict'; + +const os = require('os'); +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); +const { Stream } = require('stream'); +const { EventEmitter } = require('events'); +const { StringDecoder } = require('string_decoder'); + +const { File } = require('./file'); +const { JSONParser } = require('./json_parser'); +const { DummyParser } = require('./dummy_parser'); +const { OctetParser } = require('./octet_parser'); +const { defaultOptions } = require('./default_options'); +const { MultipartParser } = require('./multipart_parser'); +const { QuerystringParser } = require('./querystring_parser'); function hasOwnProp(obj, key) { return Object.prototype.hasOwnProperty.call(obj, key); } -function IncomingForm(options = {}) { - if (!(this instanceof IncomingForm)) return new IncomingForm(options); - EventEmitter.call(this); +class IncomingForm extends EventEmitter { + constructor(options = {}) { + super(); + this.error = null; + this.ended = false; - this.error = null; - this.ended = false; + Object.assign(this, defaultOptions, options); + this.uploadDir = this.uploadDir || os.tmpdir(); - Object.assign(this, defaultOptions, options); - this.uploadDir = this.uploadDir || os.tmpdir(); + this.headers = null; + this.type = null; - this.headers = null; - this.type = null; + this.bytesReceived = null; + this.bytesExpected = null; - this.bytesReceived = null; - this.bytesExpected = null; - - this._parser = null; - this._flushing = 0; - this._fieldsSize = 0; - this._fileSize = 0; - this.openedFiles = []; - - return this; -} -util.inherits(IncomingForm, EventEmitter); -exports.IncomingForm = IncomingForm; + this._parser = null; + this._flushing = 0; + this._fieldsSize = 0; + this._fileSize = 0; + this.openedFiles = []; + } -IncomingForm.prototype.parse = function(req, cb) { - this.pause = function() { - try { - req.pause(); - } catch (err) { - // the stream was destroyed - if (!this.ended) { - // before it was completed, crash & burn - this._error(err); + parse(req, cb) { + this.pause = () => { + try { + req.pause(); + } catch (err) { + // the stream was destroyed + if (!this.ended) { + // before it was completed, crash & burn + this._error(err); + } + return false; } - return false; - } - return true; - }; - - this.resume = function() { - try { - req.resume(); - } catch (err) { - // the stream was destroyed - if (!this.ended) { - // before it was completed, crash & burn - this._error(err); + return true; + }; + + this.resume = () => { + try { + req.resume(); + } catch (err) { + // the stream was destroyed + if (!this.ended) { + // before it was completed, crash & burn + this._error(err); + } + return false; } - return false; - } - return true; - }; + return true; + }; - // Setup callback first, so we don't miss anything from data events emitted - // immediately. - if (cb) { - var fields = {}, files = {}; - this - .on('field', function(name, value) { + // Setup callback first, so we don't miss anything from data events emitted + // immediately. + if (cb) { + const fields = {}; + const files = {}; + this.on('field', (name, value) => { + // TODO: too much nesting if (this.multiples && name.slice(-2) === '[]') { - var realName = name.slice(0, name.length - 2); + const realName = name.slice(0, name.length - 2); if (hasOwnProp(fields, realName)) { if (!Array.isArray(fields[realName])) { fields[realName] = [fields[realName]]; @@ -95,243 +96,261 @@ IncomingForm.prototype.parse = function(req, cb) { fields[name] = value; } }) - .on('file', function(name, file) { - if (this.multiples) { - if (hasOwnProp(files, name)) { - if (!Array.isArray(files[name])) { - files[name] = [files[name]]; + .on('file', (name, file) => { + // TODO: too much nesting + if (this.multiples) { + if (hasOwnProp(files, name)) { + if (!Array.isArray(files[name])) { + files[name] = [files[name]]; + } + files[name].push(file); + } else { + files[name] = file; } - files[name].push(file); } else { files[name] = file; } - } else { - files[name] = file; - } + }) + .on('error', (err) => { + cb(err, fields, files); + }) + .on('end', () => { + cb(null, fields, files); + }); + } + + // Parse headers and setup the parser, ready to start listening for data. + this.writeHeaders(req.headers); + + // Start listening for data. + req + .on('error', (err) => { + this._error(err); + }) + .on('aborted', () => { + this.emit('aborted'); + this._error(new Error('Request aborted')); }) - .on('error', function(err) { - cb(err, fields, files); + .on('data', (buffer) => { + try { + this.write(buffer); + } catch (err) { + this._error(err); + } }) - .on('end', function() { - cb(null, fields, files); + .on('end', () => { + if (this.error) { + return; + } + + this._parser.end(); }); - } - // Parse headers and setup the parser, ready to start listening for data. - this.writeHeaders(req.headers); - - // Start listening for data. - req - .on('error', (err) => { - this._error(err); - }) - .on('aborted', () => { - this.emit('aborted'); - this._error(new Error('Request aborted')); - }) - .on('data', (buffer) => { - try { - this.write(buffer); - } catch (err) { - this._error(err); - } - }) - .on('end', () => { - if (this.error) { - return; - } + return this; + } - this._parser.end(); + writeHeaders(headers) { + this.headers = headers; + this._parseContentLength(); + this._parseContentType(); + this._parser.once('error', (error) => { + this._error(error); }); + } + + write(buffer) { + if (this.error) { + return null; + } + if (!this._parser) { + this._error(new Error('uninitialized parser')); + return null; + } + + this.bytesReceived += buffer.length; + this.emit('progress', this.bytesReceived, this.bytesExpected); - return this; -}; - -IncomingForm.prototype.writeHeaders = function(headers) { - this.headers = headers; - this._parseContentLength(); - this._parseContentType(); - this._parser.once('error', (error) => { - this._error(error); - }); -}; - -IncomingForm.prototype.write = function(buffer) { - if (this.error) { - return; + this._parser.write(buffer); + + return this.bytesReceived; } - if (!this._parser) { - this._error(new Error('uninitialized parser')); - return; + + pause() { + // this does nothing, unless overwritten in IncomingForm.parse + return false; } - this.bytesReceived += buffer.length; - this.emit('progress', this.bytesReceived, this.bytesExpected); + resume() { + // this does nothing, unless overwritten in IncomingForm.parse + return false; + } - this._parser.write(buffer); + onPart(part) { + // this method can be overwritten by the user + this.handlePart(part); + } - return this.bytesReceived; -}; + handlePart(part) { + // This MUST check exactly for undefined. You can not change it to !part.filename. + if (part.filename === undefined) { + let value = ''; + const decoder = new StringDecoder(this.encoding); + + part.on('data', (buffer) => { + this._fieldsSize += buffer.length; + if (this._fieldsSize > this.maxFieldsSize) { + this._error( + new Error( + `maxFieldsSize exceeded, received ${this._fieldsSize} bytes of field data`, + ), + ); + return; + } + value += decoder.write(buffer); + }); -IncomingForm.prototype.pause = function() { - // this does nothing, unless overwritten in IncomingForm.parse - return false; -}; + part.on('end', () => { + this.emit('field', part.name, value); + }); + return; + } + + this._flushing += 1; -IncomingForm.prototype.resume = function() { - // this does nothing, unless overwritten in IncomingForm.parse - return false; -}; + const file = new File({ + path: this._uploadPath(part.filename), + name: part.filename, + type: part.mime, + hash: this.hash, + }); -IncomingForm.prototype.onPart = function(part) { - // this method can be overwritten by the user - this.handlePart(part); -}; + this.emit('fileBegin', part.name, file); -IncomingForm.prototype.handlePart = function(part) { - // This MUST check exactly for undefined. You can not change it to !part.filename. - if (part.filename === undefined) { - var value = '' - , decoder = new StringDecoder(this.encoding); + file.open(); + this.openedFiles.push(file); part.on('data', (buffer) => { - this._fieldsSize += buffer.length; - if (this._fieldsSize > this.maxFieldsSize) { - this._error(new Error(`maxFieldsSize exceeded, received ${this._fieldsSize} bytes of field data`)); + this._fileSize += buffer.length; + if (this._fileSize > this.maxFileSize) { + this._error( + new Error( + `maxFileSize exceeded, received ${this._fileSize} bytes of file data`, + ), + ); + return; + } + if (buffer.length === 0) { return; } - value += decoder.write(buffer); + this.pause(); + file.write(buffer, () => { + this.resume(); + }); }); part.on('end', () => { - this.emit('field', part.name, value); + file.end(() => { + this._flushing -= 1; + this.emit('file', part.name, file); + this._maybeEnd(); + }); }); - return; } - this._flushing++; - - var file = new File({ - path: this._uploadPath(part.filename), - name: part.filename, - type: part.mime, - hash: this.hash - }); - - this.emit('fileBegin', part.name, file); - - file.open(); - this.openedFiles.push(file); - - part.on('data', (buffer) => { - this._fileSize += buffer.length; - if (this._fileSize > this.maxFileSize) { - this._error(new Error(`maxFileSize exceeded, received ${this._fileSize} bytes of file data`)); + // eslint-disable-next-line max-statements + _parseContentType() { + if (this.bytesExpected === 0) { + this._parser = new DummyParser(this); return; } - if (buffer.length == 0) { + + if (!this.headers['content-type']) { + this._error(new Error('bad content-type header, no content-type')); return; } - this.pause(); - file.write(buffer, () => { - this.resume(); - }); - }); - - part.on('end', () => { - file.end(() => { - this._flushing--; - this.emit('file', part.name, file); - this._maybeEnd(); - }); - }); -}; + if (this.headers['content-type'].match(/octet-stream/i)) { + this._initOctetStream(); + return; + } -IncomingForm.prototype._parseContentType = function() { - if (this.bytesExpected === 0) { - this._parser = new DummyParser(this); - return; - } + if (this.headers['content-type'].match(/urlencoded/i)) { + this._initUrlencoded(); + return; + } - if (!this.headers['content-type']) { - this._error(new Error('bad content-type header, no content-type')); - return; - } + if (this.headers['content-type'].match(/multipart/i)) { + const m = this.headers['content-type'].match( + /boundary=(?:"([^"]+)"|([^;]+))/i, + ); + if (m) { + this._initMultipart(m[1] || m[2]); + } else { + this._error( + new Error('bad content-type header, no multipart boundary'), + ); + } + return; + } - if (this.headers['content-type'].match(/octet-stream/i)) { - this._initOctetStream(); - return; - } + if (this.headers['content-type'].match(/json/i)) { + this._initJSONencoded(); + return; + } - if (this.headers['content-type'].match(/urlencoded/i)) { - this._initUrlencoded(); - return; + this._error( + new Error( + `bad content-type header, unknown content-type: ${this.headers['content-type']}`, + ), + ); } - if (this.headers['content-type'].match(/multipart/i)) { - var m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i); - if (m) { - this._initMultipart(m[1] || m[2]); - } else { - this._error(new Error('bad content-type header, no multipart boundary')); + _error(err) { + if (this.error || this.ended) { + return; } - return; - } - if (this.headers['content-type'].match(/json/i)) { - this._initJSONencoded(); - return; - } + this.error = err; + this.emit('error', err); - this._error(new Error(`bad content-type header, unknown content-type: ${this.headers['content-type']}`)); -}; - -IncomingForm.prototype._error = function(err) { - if (this.error || this.ended) { - return; + if (Array.isArray(this.openedFiles)) { + this.openedFiles.forEach((file) => { + file._writeStream.destroy(); + setTimeout(fs.unlink, 0, file.path, () => {}); + }); + } } - this.error = err; - this.emit('error', err); + _parseContentLength() { + this.bytesReceived = 0; + if (this.headers['content-length']) { + this.bytesExpected = parseInt(this.headers['content-length'], 10); + } else if (this.headers['transfer-encoding'] === undefined) { + this.bytesExpected = 0; + } - if (Array.isArray(this.openedFiles)) { - this.openedFiles.forEach(function(file) { - file._writeStream.destroy(); - setTimeout(fs.unlink, 0, file.path, function(error) { }); - }); - } -}; - -IncomingForm.prototype._parseContentLength = function() { - this.bytesReceived = 0; - if (this.headers['content-length']) { - this.bytesExpected = parseInt(this.headers['content-length'], 10); - } else if (this.headers['transfer-encoding'] === undefined) { - this.bytesExpected = 0; + if (this.bytesExpected !== null) { + this.emit('progress', this.bytesReceived, this.bytesExpected); + } } - if (this.bytesExpected !== null) { - this.emit('progress', this.bytesReceived, this.bytesExpected); + _newParser() { + return new MultipartParser(); } -}; -IncomingForm.prototype._newParser = function() { - return new MultipartParser(); -}; + _initMultipart(boundary) { + this.type = 'multipart'; -IncomingForm.prototype._initMultipart = function(boundary) { - this.type = 'multipart'; + const parser = new MultipartParser(); + let headerField; + let headerValue; + let part; - var parser = new MultipartParser(), - headerField, - headerValue, - part; + parser.initWithBoundary(boundary); - parser.initWithBoundary(boundary); - - parser.on('data', ({name, buffer, start, end}) => { - if (name === 'partBegin') { + // eslint-disable-next-line max-statements, consistent-return + parser.on('data', ({ name, buffer, start, end }) => { + if (name === 'partBegin') { part = new Stream(); part.readable = true; part.headers = {}; @@ -344,216 +363,236 @@ IncomingForm.prototype._initMultipart = function(boundary) { headerField = ''; headerValue = ''; - } else if (name === 'headerField') { + } else if (name === 'headerField') { headerField += buffer.toString(this.encoding, start, end); - } else if (name === 'headerValue') { + } else if (name === 'headerValue') { headerValue += buffer.toString(this.encoding, start, end); - } else if (name === 'headerEnd') { + } else if (name === 'headerEnd') { headerField = headerField.toLowerCase(); part.headers[headerField] = headerValue; // matches either a quoted-string or a token (RFC 2616 section 19.5.1) - var m = headerValue.match(/\bname=("([^"]*)"|([^\(\)<>@,;:\\"\/\[\]\?=\{\}\s\t/]+))/i); - if (headerField == 'content-disposition') { - if (m) { - part.name = m[2] || m[3] || ''; - } + const m = headerValue.match( + // eslint-disable-next-line no-useless-escape + /\bname=("([^"]*)"|([^\(\)<>@,;:\\"\/\[\]\?=\{\}\s\t/]+))/i, + ); + if (headerField === 'content-disposition') { + if (m) { + part.name = m[2] || m[3] || ''; + } - part.filename = this._fileName(headerValue); - } else if (headerField == 'content-type') { - part.mime = headerValue; - } else if (headerField == 'content-transfer-encoding') { - part.transferEncoding = headerValue.toLowerCase(); + part.filename = this._fileName(headerValue); + } else if (headerField === 'content-type') { + part.mime = headerValue; + } else if (headerField === 'content-transfer-encoding') { + part.transferEncoding = headerValue.toLowerCase(); } headerField = ''; headerValue = ''; - } else if (name === 'headersEnd') { - - switch(part.transferEncoding){ - case 'binary': - case '7bit': - case '8bit': { - const dataPropagation = ({name, buffer, start, end}) => { - if (name === 'partData') { - part.emit('data', buffer.slice(start, end)); - } - }; - const dataStopPropagation = ({name}) => { - if (name === 'partEnd') { - part.emit('end'); - parser.off('data', dataPropagation); - parser.off('data', dataStopPropagation); - } - }; - parser.on('data', dataPropagation); - parser.on('data', dataStopPropagation); - break; - } case 'base64': { - const dataPropagation = ({name, buffer, start, end}) => { - if (name === 'partData') { - part.transferBuffer += buffer.slice(start, end).toString('ascii'); - - /* + } else if (name === 'headersEnd') { + switch (part.transferEncoding) { + case 'binary': + case '7bit': + case '8bit': { + const dataPropagation = (ctx) => { + if (ctx.name === 'partData') { + part.emit('data', ctx.buffer.slice(ctx.start, ctx.end)); + } + }; + const dataStopPropagation = (ctx) => { + if (ctx.name === 'partEnd') { + part.emit('end'); + parser.off('data', dataPropagation); + parser.off('data', dataStopPropagation); + } + }; + parser.on('data', dataPropagation); + parser.on('data', dataStopPropagation); + break; + } + case 'base64': { + const dataPropagation = (ctx) => { + if (ctx.name === 'partData') { + part.transferBuffer += ctx.buffer + .slice(ctx.start, ctx.end) + .toString('ascii'); + + /* four bytes (chars) in base64 converts to three bytes in binary encoding. So we should always work with a number of bytes that can be divided by 4, it will result in a number of buytes that can be divided vy 3. */ - var offset = parseInt(part.transferBuffer.length / 4, 10) * 4; - part.emit('data', Buffer.from(part.transferBuffer.substring(0, offset), 'base64')); - part.transferBuffer = part.transferBuffer.substring(offset); - } + const offset = parseInt(part.transferBuffer.length / 4, 10) * 4; + part.emit( + 'data', + Buffer.from( + part.transferBuffer.substring(0, offset), + 'base64', + ), + ); + part.transferBuffer = part.transferBuffer.substring(offset); + } }; - const dataStopPropagation = ({name}) => { - if (name === 'partEnd') { - part.emit('data', Buffer.from(part.transferBuffer, 'base64')); - part.emit('end'); - parser.off('data', dataPropagation); - parser.off('data', dataStopPropagation); - } + const dataStopPropagation = (ctx) => { + if (ctx.name === 'partEnd') { + part.emit('data', Buffer.from(part.transferBuffer, 'base64')); + part.emit('end'); + parser.off('data', dataPropagation); + parser.off('data', dataStopPropagation); + } }; parser.on('data', dataPropagation); parser.on('data', dataStopPropagation); break; - - } default: - return this._error(new Error('unknown transfer-encoding')); + } + default: + return this._error(new Error('unknown transfer-encoding')); } this.onPart(part); - } else if (name === 'end') { + } else if (name === 'end') { this.ended = true; this._maybeEnd(); - } - }); + } + }); - this._parser = parser; -}; + this._parser = parser; + } -IncomingForm.prototype._fileName = function(headerValue) { - // matches either a quoted-string or a token (RFC 2616 section 19.5.1) - var m = headerValue.match(/\bfilename=("(.*?)"|([^\(\)<>@,;:\\"\/\[\]\?=\{\}\s\t/]+))($|;\s)/i); - if (!m) return; + _fileName(headerValue) { + // matches either a quoted-string or a token (RFC 2616 section 19.5.1) + const m = headerValue.match( + // eslint-disable-next-line no-useless-escape + /\bfilename=("(.*?)"|([^\(\)<>@,;:\\"\/\[\]\?=\{\}\s\t/]+))($|;\s)/i, + ); + if (!m) return null; + + const match = m[2] || m[3] || ''; + let filename = match.substr(match.lastIndexOf('\\') + 1); + filename = filename.replace(/%22/g, '"'); + filename = filename.replace(/&#([\d]{4});/g, (_, code) => + String.fromCharCode(code), + ); + return filename; + } - var match = m[2] || m[3] || ''; - var filename = match.substr(match.lastIndexOf('\\') + 1); - filename = filename.replace(/%22/g, '"'); - filename = filename.replace(/&#([\d]{4});/g, function(m, code) { - return String.fromCharCode(code); - }); - return filename; -}; + _initUrlencoded() { + this.type = 'urlencoded'; -IncomingForm.prototype._initUrlencoded = function() { - this.type = 'urlencoded'; + const parser = new QuerystringParser(this.maxFields); - var parser = new QuerystringParser(this.maxFields); + parser.on('data', ({ key, value }) => { + this.emit('field', key, value); + }); - parser.on('data', ({key, value}) => { - this.emit('field', key, value); - }); + parser.onEnd = () => { + this.ended = true; + this._maybeEnd(); + }; - parser.onEnd = () => { - this.ended = true; - this._maybeEnd(); - }; + this._parser = parser; + } - this._parser = parser; -}; + _initOctetStream() { + this.type = 'octet-stream'; + const filename = this.headers['x-file-name']; + const mime = this.headers['content-type']; -IncomingForm.prototype._initOctetStream = function() { - this.type = 'octet-stream'; - var filename = this.headers['x-file-name']; - var mime = this.headers['content-type']; + const file = new File({ + path: this._uploadPath(filename), + name: filename, + type: mime, + }); - var file = new File({ - path: this._uploadPath(filename), - name: filename, - type: mime - }); + this.emit('fileBegin', filename, file); + file.open(); + this.openedFiles.push(file); + this._flushing += 1; - this.emit('fileBegin', filename, file); - file.open(); - this.openedFiles.push(file); - this._flushing++; + this._parser = new OctetParser(); - this._parser = new OctetParser(); + // Keep track of writes that haven't finished so we don't emit the file before it's done being written + let outstandingWrites = 0; - //Keep track of writes that haven't finished so we don't emit the file before it's done being written - var outstandingWrites = 0; + this._parser.on('data', (buffer) => { + this.pause(); + outstandingWrites += 1; - this._parser.on('data', (buffer) => { - this.pause(); - outstandingWrites++; + file.write(buffer, () => { + outstandingWrites -= 1; + this.resume(); - file.write(buffer, () => { - outstandingWrites--; - this.resume(); + if (this.ended) { + this._parser.emit('doneWritingFile'); + } + }); + }); - if(this.ended){ - this._parser.emit('doneWritingFile'); + this._parser.on('end', () => { + this._flushing -= 1; + this.ended = true; + + const done = () => { + file.end(() => { + this.emit('file', 'file', file); + this._maybeEnd(); + }); + }; + + if (outstandingWrites === 0) { + done(); + } else { + this._parser.once('doneWritingFile', done); } }); - }); - - this._parser.on('end', () => { - this._flushing--; - this.ended = true; - - var done = () => { - file.end(() => { - this.emit('file', 'file', file); - this._maybeEnd(); - }); - }; + } - if(outstandingWrites === 0){ - done(); - } else { - this._parser.once('doneWritingFile', done); - } - }); -}; + _initJSONencoded() { + this.type = 'json'; -IncomingForm.prototype._initJSONencoded = function() { - this.type = 'json'; + const parser = new JSONParser(); - var parser = new JSONParser(); + parser.on('data', ({ key, value }) => { + this.emit('field', key, value); + }); + // parser.on('data', (key) => { + // this.emit('field', key); + // }); - parser.on('data', ({ key, value }) => { - this.emit('field', key, value); - }); - // parser.on('data', (key) => { - // this.emit('field', key); - // }); + parser.once('end', () => { + this.ended = true; + this._maybeEnd(); + }); - parser.once('end', () => { - this.ended = true; - this._maybeEnd(); - }); + this._parser = parser; + } - this._parser = parser; -}; + _uploadPath(filename) { + const buf = crypto.randomBytes(16); + let name = `upload_${buf.toString('hex')}`; -IncomingForm.prototype._uploadPath = function(filename) { - var buf = crypto.randomBytes(16); - var name = `upload_${buf.toString('hex')}`; + if (this.keepExtensions) { + let ext = path.extname(filename); + ext = ext.replace(/(\.[a-z0-9]+).*/i, '$1'); - if (this.keepExtensions) { - var ext = path.extname(filename); - ext = ext.replace(/(\.[a-z0-9]+).*/i, '$1'); + name += ext; + } - name += ext; + return path.join(this.uploadDir, name); } - return path.join(this.uploadDir, name); -}; + _maybeEnd() { + if (!this.ended || this._flushing || this.error) { + return; + } -IncomingForm.prototype._maybeEnd = function() { - if (!this.ended || this._flushing || this.error) { - return; + this.emit('end'); } +} - this.emit('end'); -}; +IncomingForm.IncomingForm = IncomingForm; +exports.IncomingForm = IncomingForm; +exports.default = IncomingForm; +module.exports = exports.default; diff --git a/src/index.js b/src/index.js index 2c47a29b..9d193b21 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,9 @@ +'use strict'; + const { IncomingForm } = require('./incoming_form'); IncomingForm.IncomingForm = IncomingForm; +exports.IncomingForm = IncomingForm; exports.default = IncomingForm; module.exports = exports.default; diff --git a/src/json_parser.js b/src/json_parser.js index 8078957f..392896bc 100644 --- a/src/json_parser.js +++ b/src/json_parser.js @@ -1,5 +1,8 @@ -const { Transform } = require('stream'); +/* eslint-disable no-underscore-dangle */ + +'use strict'; +const { Transform } = require('stream'); class JSONParser extends Transform { constructor() { @@ -8,22 +11,20 @@ class JSONParser extends Transform { } _transform(chunk, encoding, callback) { - this.chunks.push(String(chunk));// todo consider using a string decoder + this.chunks.push(String(chunk)); // todo consider using a string decoder callback(); } _flush(callback) { try { - var fields = JSON.parse(this.chunks.join('')); - for (var key in fields) { - this.push({ - key, - value: fields[key], - }); - } + const fields = JSON.parse(this.chunks.join('')); + Object.keys(fields).forEach((key) => { + const value = fields[key]; + this.push({ key, value }); + }); } catch (e) { - callback(e); - return; + callback(e); + return; } this.chunks = null; callback(); diff --git a/src/multipart_parser.js b/src/multipart_parser.js index f3c0cd45..ba018d93 100644 --- a/src/multipart_parser.js +++ b/src/multipart_parser.js @@ -1,184 +1,191 @@ +/* eslint-disable no-fallthrough */ +/* eslint-disable no-bitwise */ +/* eslint-disable no-plusplus */ +/* eslint-disable no-underscore-dangle */ const { Transform } = require('stream'); +let s = 0; +const STATE = { + PARSER_UNINITIALIZED: s++, + START: s++, + START_BOUNDARY: s++, + HEADER_FIELD_START: s++, + HEADER_FIELD: s++, + HEADER_VALUE_START: s++, + HEADER_VALUE: s++, + HEADER_VALUE_ALMOST_DONE: s++, + HEADERS_ALMOST_DONE: s++, + PART_DATA_START: s++, + PART_DATA: s++, + PART_END: s++, + END: s++, +}; + +let f = 1; +const FBOUNDARY = { PART_BOUNDARY: f, LAST_BOUNDARY: (f *= 2) }; + +const LF = 10; +const CR = 13; +const SPACE = 32; +const HYPHEN = 45; +const COLON = 58; +const A = 97; +const Z = 122; -var s = 0, - S = - { PARSER_UNINITIALIZED: s++, - START: s++, - START_BOUNDARY: s++, - HEADER_FIELD_START: s++, - HEADER_FIELD: s++, - HEADER_VALUE_START: s++, - HEADER_VALUE: s++, - HEADER_VALUE_ALMOST_DONE: s++, - HEADERS_ALMOST_DONE: s++, - PART_DATA_START: s++, - PART_DATA: s++, - PART_END: s++, - END: s++ - }, - - f = 1, - F = - { PART_BOUNDARY: f, - LAST_BOUNDARY: f *= 2 - }, - - LF = 10, - CR = 13, - SPACE = 32, - HYPHEN = 45, - COLON = 58, - A = 97, - Z = 122, - - lower = function(c) { - return c | 0x20; - }; - -for (s in S) { - exports[s] = S[s]; +function lower(c) { + return c | 0x20; } +Object.keys(STATE).forEach((stateName) => { + exports[stateName] = STATE[stateName]; +}); + class MultipartParser extends Transform { constructor() { super({ readableObjectMode: true }); this.boundary = null; this.boundaryChars = null; this.lookbehind = null; - this.state = S.PARSER_UNINITIALIZED; + this.state = STATE.PARSER_UNINITIALIZED; this.index = null; this.flags = 0; } _final(callback) { - if ((this.state == S.HEADER_FIELD_START && this.index === 0) || - (this.state == S.PART_DATA && this.index == this.boundary.length)) { - this.callback('partEnd'); - this.callback('end'); - callback(); - } else if (this.state != S.END) { - callback(new Error(`MultipartParser.end(): stream ended unexpectedly: ${this.explain()}`)); - } + if ( + (this.state === STATE.HEADER_FIELD_START && this.index === 0) || + (this.state === STATE.PART_DATA && this.index === this.boundary.length) + ) { + this.callback('partEnd'); + this.callback('end'); + callback(); + } else if (this.state !== STATE.END) { + callback( + new Error( + `MultipartParser.end(): stream ended unexpectedly: ${this.explain()}`, + ), + ); + } } - initWithBoundary (str) { + initWithBoundary(str) { this.boundary = Buffer.from(`\r\n--${str}`); - this.lookbehind = Buffer.alloc(this.boundary.length+8); - this.state = S.START; + this.lookbehind = Buffer.alloc(this.boundary.length + 8); + this.state = STATE.START; this.boundaryChars = {}; - for (var i = 0; i < this.boundary.length; i++) { + for (let i = 0; i < this.boundary.length; i++) { this.boundaryChars[this.boundary[i]] = true; } } - _transform(buffer, encoding, callback) { - var i = 0, - len = buffer.length, - prevIndex = this.index, - index = this.index, - state = this.state, - flags = this.flags, - lookbehind = this.lookbehind, - boundary = this.boundary, - boundaryChars = this.boundaryChars, - boundaryLength = this.boundary.length, - boundaryEnd = boundaryLength - 1, - bufferLength = buffer.length, - c, - cl, - - mark = (name) => { - this[`${name}Mark`] = i; - }, - clear = (name) => { - delete this[`${name}Mark`]; - }, - callback = (name, buffer, start, end) => { - if (start !== undefined && start === end) { - return; - } - this.push({name, buffer, start, end}); - }, - dataCallback = (name, clear) => { - var markSymbol = `${name}Mark`; - if (!(markSymbol in this)) { - return; - } + // eslint-disable-next-line max-statements + _transform(buffer, _, done) { + let i = 0; + let prevIndex = this.index; + let { index, state, flags } = this; + const { lookbehind, boundary, boundaryChars } = this; + const boundaryLength = boundary.length; + const boundaryEnd = boundaryLength - 1; + const bufferLength = buffer.length; + const selfParser = this; + let c = null; + let cl = null; - if (!clear) { - callback(name, buffer, this[markSymbol], buffer.length); - this[markSymbol] = 0; - } else { - callback(name, buffer, this[markSymbol], i); - delete this[markSymbol]; - } - }; + function setMark(name, idx) { + selfParser[`${name}Mark`] = idx || i; + } + + function clearMarkSymbol(name) { + delete selfParser[`${name}Mark`]; + } + + // eslint-disable-next-line max-params + function callback(name, buf, start, end) { + if (start !== undefined && start === end) { + return; + } + selfParser.push({ name, buffer: buf, start, end }); + } + + function dataCallback(name, shouldClear) { + const markSymbol = `${name}Mark`; + if (!(markSymbol in selfParser)) { + return; + } + + if (!shouldClear) { + callback(name, buffer, selfParser[markSymbol], buffer.length); + setMark(markSymbol, 0); + } else { + callback(name, buffer, selfParser[markSymbol], i); + clearMarkSymbol(markSymbol); + } + } - for (i = 0; i < len; i++) { + for (i = 0; i < bufferLength; i++) { c = buffer[i]; switch (state) { - case S.PARSER_UNINITIALIZED: + case STATE.PARSER_UNINITIALIZED: return i; - case S.START: + case STATE.START: index = 0; - state = S.START_BOUNDARY; - case S.START_BOUNDARY: - if (index == boundary.length - 2) { - if (c == HYPHEN) { - flags |= F.LAST_BOUNDARY; - } else if (c != CR) { + state = STATE.START_BOUNDARY; + case STATE.START_BOUNDARY: + if (index === boundary.length - 2) { + if (c === HYPHEN) { + flags |= FBOUNDARY.LAST_BOUNDARY; + } else if (c !== CR) { return i; } index++; break; - } else if (index - 1 == boundary.length - 2) { - if (flags & F.LAST_BOUNDARY && c == HYPHEN){ + } else if (index - 1 === boundary.length - 2) { + if (flags & FBOUNDARY.LAST_BOUNDARY && c === HYPHEN) { callback('end'); - state = S.END; + state = STATE.END; flags = 0; - } else if (!(flags & F.LAST_BOUNDARY) && c == LF) { + } else if (!(flags & FBOUNDARY.LAST_BOUNDARY) && c === LF) { index = 0; callback('partBegin'); - state = S.HEADER_FIELD_START; + state = STATE.HEADER_FIELD_START; } else { return i; } break; } - if (c != boundary[index+2]) { + if (c !== boundary[index + 2]) { index = -2; } - if (c == boundary[index+2]) { + if (c === boundary[index + 2]) { index++; } break; - case S.HEADER_FIELD_START: - state = S.HEADER_FIELD; - mark('headerField'); + case STATE.HEADER_FIELD_START: + state = STATE.HEADER_FIELD; + setMark('headerField'); index = 0; - case S.HEADER_FIELD: - if (c == CR) { - clear('headerField'); - state = S.HEADERS_ALMOST_DONE; + case STATE.HEADER_FIELD: + if (c === CR) { + clearMarkSymbol('headerField'); + state = STATE.HEADERS_ALMOST_DONE; break; } index++; - if (c == HYPHEN) { + if (c === HYPHEN) { break; } - if (c == COLON) { - if (index == 1) { + if (c === COLON) { + if (index === 1) { // empty header field return i; } dataCallback('headerField', true); - state = S.HEADER_VALUE_START; + state = STATE.HEADER_VALUE_START; break; } @@ -187,38 +194,38 @@ class MultipartParser extends Transform { return i; } break; - case S.HEADER_VALUE_START: - if (c == SPACE) { + case STATE.HEADER_VALUE_START: + if (c === SPACE) { break; } - mark('headerValue'); - state = S.HEADER_VALUE; - case S.HEADER_VALUE: - if (c == CR) { + setMark('headerValue'); + state = STATE.HEADER_VALUE; + case STATE.HEADER_VALUE: + if (c === CR) { dataCallback('headerValue', true); callback('headerEnd'); - state = S.HEADER_VALUE_ALMOST_DONE; + state = STATE.HEADER_VALUE_ALMOST_DONE; } break; - case S.HEADER_VALUE_ALMOST_DONE: - if (c != LF) { + case STATE.HEADER_VALUE_ALMOST_DONE: + if (c !== LF) { return i; } - state = S.HEADER_FIELD_START; + state = STATE.HEADER_FIELD_START; break; - case S.HEADERS_ALMOST_DONE: - if (c != LF) { + case STATE.HEADERS_ALMOST_DONE: + if (c !== LF) { return i; } callback('headersEnd'); - state = S.PART_DATA_START; + state = STATE.PART_DATA_START; break; - case S.PART_DATA_START: - state = S.PART_DATA; - mark('partData'); - case S.PART_DATA: + case STATE.PART_DATA_START: + state = STATE.PART_DATA; + setMark('partData'); + case STATE.PART_DATA: prevIndex = index; if (index === 0) { @@ -232,7 +239,7 @@ class MultipartParser extends Transform { } if (index < boundary.length) { - if (boundary[index] == c) { + if (boundary[index] === c) { if (index === 0) { dataCallback('partData', true); } @@ -240,33 +247,33 @@ class MultipartParser extends Transform { } else { index = 0; } - } else if (index == boundary.length) { + } else if (index === boundary.length) { index++; - if (c == CR) { + if (c === CR) { // CR = part boundary - flags |= F.PART_BOUNDARY; - } else if (c == HYPHEN) { + flags |= FBOUNDARY.PART_BOUNDARY; + } else if (c === HYPHEN) { // HYPHEN = end boundary - flags |= F.LAST_BOUNDARY; + flags |= FBOUNDARY.LAST_BOUNDARY; } else { index = 0; } - } else if (index - 1 == boundary.length) { - if (flags & F.PART_BOUNDARY) { + } else if (index - 1 === boundary.length) { + if (flags & FBOUNDARY.PART_BOUNDARY) { index = 0; - if (c == LF) { + if (c === LF) { // unset the PART_BOUNDARY flag - flags &= ~F.PART_BOUNDARY; + flags &= ~FBOUNDARY.PART_BOUNDARY; callback('partEnd'); callback('partBegin'); - state = S.HEADER_FIELD_START; + state = STATE.HEADER_FIELD_START; break; } - } else if (flags & F.LAST_BOUNDARY) { - if (c == HYPHEN) { + } else if (flags & FBOUNDARY.LAST_BOUNDARY) { + if (c === HYPHEN) { callback('partEnd'); callback('end'); - state = S.END; + state = STATE.END; flags = 0; } else { index = 0; @@ -279,13 +286,13 @@ class MultipartParser extends Transform { if (index > 0) { // when matching a possible boundary, keep a lookbehind reference // in case it turns out to be a false lead - lookbehind[index-1] = c; + lookbehind[index - 1] = c; } else if (prevIndex > 0) { // if our boundary turned out to be rubbish, the captured lookbehind // belongs to partData callback('partData', lookbehind, 0, prevIndex); prevIndex = 0; - mark('partData'); + setMark('partData'); // reconsider the current character even so it interrupted the sequence // it could be the beginning of a new sequence @@ -293,7 +300,7 @@ class MultipartParser extends Transform { } break; - case S.END: + case STATE.END: break; default: return i; @@ -308,18 +315,21 @@ class MultipartParser extends Transform { this.state = state; this.flags = flags; - return len; + done(); + return bufferLength; } - explain () { + explain() { return `state = ${MultipartParser.stateToString(this.state)}`; } } -MultipartParser.stateToString = function(stateNumber) { - for (var state in S) { - var number = S[state]; - if (number === stateNumber) return state; +// eslint-disable-next-line consistent-return +MultipartParser.stateToString = (stateNumber) => { + // eslint-disable-next-line no-restricted-syntax, guard-for-in + for (const stateName in STATE) { + const number = STATE[stateName]; + if (number === stateNumber) return stateName; } }; exports.MultipartParser = MultipartParser; diff --git a/src/octet_parser.js b/src/octet_parser.js index 04eeee7e..c752cfd5 100644 --- a/src/octet_parser.js +++ b/src/octet_parser.js @@ -1,3 +1,5 @@ +'use strict'; + const { PassThrough } = require('stream'); class OctetParser extends PassThrough {} diff --git a/src/querystring_parser.js b/src/querystring_parser.js index c5b1306e..dd9a81d2 100644 --- a/src/querystring_parser.js +++ b/src/querystring_parser.js @@ -1,31 +1,38 @@ +/* eslint-disable no-underscore-dangle */ + +'use strict'; + const { Transform } = require('stream'); const querystring = require('querystring'); // This is a buffering parser, not quite as nice as the multipart one. // If I find time I'll rewrite this to be fully streaming as well class QuerystringParser extends Transform { - constructor(maxKeys) { - super({ readableObjectMode: true }); - this.maxKeys = maxKeys; - this.buffer = ''; - } + constructor(maxKeys) { + super({ readableObjectMode: true }); + this.maxKeys = maxKeys; + this.buffer = ''; + } - _transform(buffer, encoding, callback) { - this.buffer += buffer.toString('ascii'); - callback(); - } + _transform(buffer, encoding, callback) { + this.buffer += buffer.toString('ascii'); + callback(); + } - _flush(callback) { - var fields = querystring.parse(this.buffer, '&', '=', { maxKeys: this.maxKeys }); - for (var key in fields) { - this.push({ - key, - value: fields[key], - }); - } - this.buffer = ''; - callback(); + _flush(callback) { + const fields = querystring.parse(this.buffer, '&', '=', { + maxKeys: this.maxKeys, + }); + // eslint-disable-next-line no-restricted-syntax, guard-for-in + for (const key in fields) { + this.push({ + key, + value: fields[key], + }); } + this.buffer = ''; + callback(); + } } exports.QuerystringParser = QuerystringParser; diff --git a/t.js b/t.js index 1705ef19..15153e1b 100644 --- a/t.js +++ b/t.js @@ -1,27 +1,33 @@ +/* eslint-disable no-underscore-dangle */ + +'use strict'; + const { Transform } = require('stream'); class MyTransform extends Transform { - constructor() { - // writableObjectMode , objectMode - super({ readableObjectMode: true, /*encoding: 'utf-8' */}); - } + constructor() { + // writableObjectMode , objectMode + super({ readableObjectMode: true /* encoding: 'utf-8' */ }); + } - _transform(chunk, encoding, callback) { - console.log(typeof chunk, encoding) - this.push({ - "a": chunk, - "b": "b" - }); - callback(); - } + _transform(chunk, encoding, callback) { + console.log(typeof chunk, encoding); + this.push({ + a: chunk, + b: 'b', + }); + callback(); + } - _flush(callback) { - callback(); - } + // eslint-disable-next-line class-methods-use-this + _flush(callback) { + callback(); + } } const myTransform = new MyTransform(); console.log(myTransform._readableState.objectMode); // true -myTransform.on('data', console.log) -myTransform.write(Buffer.from("oyo")); + +myTransform.on('data', console.log); +myTransform.write(Buffer.from('oyo')); myTransform.end(); diff --git a/test-legacy/common.js b/test-legacy/common.js index e0830490..43a217cb 100644 --- a/test-legacy/common.js +++ b/test-legacy/common.js @@ -1,9 +1,10 @@ -var path = require('path'), - fs = require('fs'); +const path = require('path'); +const fs = require('fs'); exports.lib = path.join(__dirname, '../../lib'); global.assert = require('assert'); + global.TEST_PORT = 13532; global.TEST_FIXTURES = path.join(__dirname, '../fixture'); global.TEST_TMP = path.join(__dirname, '../tmp'); diff --git a/test-legacy/integration/test-multipart-parser.js b/test-legacy/integration/test-multipart-parser.js index 01fddb3c..453efd7c 100644 --- a/test-legacy/integration/test-multipart-parser.js +++ b/test-legacy/integration/test-multipart-parser.js @@ -1,26 +1,27 @@ -var common = require('../common'); -var CHUNK_LENGTH = 10, - multipartParser = require(common.lib + '/multipart_parser'), - MultipartParser = multipartParser.MultipartParser, - parser = new MultipartParser(), - fixtures = require(TEST_FIXTURES + '/multipart'); +const common = require('../common'); + +const CHUNK_LENGTH = 10; +const multipartParser = require(`${common.lib}/multipart_parser`); +const { MultipartParser } = multipartParser; +const parser = new MultipartParser(); +const fixtures = require(`${TEST_FIXTURES}/multipart`); Object.keys(fixtures).forEach(function(name) { - var fixture = fixtures[name], - buffer = Buffer.alloc(Buffer.byteLength(fixture.raw, 'binary')), - offset = 0, - chunk, - nparsed, + const fixture = fixtures[name]; + const buffer = Buffer.alloc(Buffer.byteLength(fixture.raw, 'binary')); + let offset = 0; + let chunk; + let nparsed; - parts = [], - part = null, - headerField, - headerValue, - endCalled = ''; + const parts = []; + let part = null; + let headerField; + let headerValue; + let endCalled = ''; parser.initWithBoundary(fixture.boundary); parser.onPartBegin = function() { - part = {headers: {}, data: ''}; + part = { headers: {}, data: '' }; parts.push(part); headerField = ''; headerValue = ''; @@ -41,7 +42,7 @@ Object.keys(fixtures).forEach(function(name) { }; parser.onPartData = function(b, start, end) { - var str = b.toString('ascii', start, end); + const str = b.toString('ascii', start, end); part.data += b.slice(start, end); }; @@ -53,11 +54,11 @@ Object.keys(fixtures).forEach(function(name) { while (offset < buffer.length) { if (offset + CHUNK_LENGTH < buffer.length) { - chunk = buffer.slice(offset, offset+CHUNK_LENGTH); + chunk = buffer.slice(offset, offset + CHUNK_LENGTH); } else { chunk = buffer.slice(offset, buffer.length); } - offset = offset + CHUNK_LENGTH; + offset += CHUNK_LENGTH; nparsed = parser.write(chunk); if (nparsed != chunk.length) { @@ -66,7 +67,9 @@ Object.keys(fixtures).forEach(function(name) { } puts('-- ERROR --'); p(chunk.toString('ascii')); - throw new Error(chunk.length+' bytes written, but only '+nparsed+' bytes parsed!'); + throw new Error( + `${chunk.length} bytes written, but only ${nparsed} bytes parsed!`, + ); } } diff --git a/test-legacy/simple/test-file.js b/test-legacy/simple/test-file.js index 52ceedb4..a29c0e3b 100644 --- a/test-legacy/simple/test-file.js +++ b/test-legacy/simple/test-file.js @@ -1,10 +1,12 @@ -var common = require('../common'); -var WriteStreamStub = GENTLY.stub('fs', 'WriteStream'); +const common = require('../common'); -var File = require(common.lib + '/file'), - EventEmitter = require('events').EventEmitter, - file, - gently; +const WriteStreamStub = GENTLY.stub('fs', 'WriteStream'); + +const File = require(`${common.lib}/file`); +const { EventEmitter } = require('events'); + +let file; +let gently; function test(test) { gently = new Gently(); @@ -24,16 +26,16 @@ test(function constructor() { assert.strictEqual(file._writeStream, null); (function testSetProperties() { - var file2 = new File({foo: 'bar'}); + const file2 = new File({ foo: 'bar' }); assert.equal(file2.foo, 'bar'); })(); }); test(function open() { - var WRITE_STREAM; + let WRITE_STREAM; file.path = '/foo'; - gently.expect(WriteStreamStub, 'new', function (path) { + gently.expect(WriteStreamStub, 'new', function(path) { WRITE_STREAM = this; assert.strictEqual(path, file.path); }); @@ -43,18 +45,18 @@ test(function open() { }); test(function write() { - var BUFFER = {length: 10}, - CB_STUB, - CB = function() { - CB_STUB.apply(this, arguments); - }; + const BUFFER = { length: 10 }; + let CB_STUB; + const CB = function() { + CB_STUB.apply(this, arguments); + }; file._writeStream = {}; - gently.expect(file._writeStream, 'write', function (buffer, cb) { + gently.expect(file._writeStream, 'write', function(buffer, cb) { assert.strictEqual(buffer, BUFFER); - gently.expect(file, 'emit', function (event, bytesWritten) { + gently.expect(file, 'emit', function(event, bytesWritten) { assert.ok(file.lastModifiedDate instanceof Date); assert.equal(event, 'progress'); assert.equal(bytesWritten, file.size); @@ -66,7 +68,7 @@ test(function write() { cb(); - gently.expect(file, 'emit', function (event, bytesWritten) { + gently.expect(file, 'emit', function(event, bytesWritten) { assert.equal(event, 'progress'); assert.equal(bytesWritten, file.size); }); @@ -82,20 +84,19 @@ test(function write() { }); test(function end() { - var CB_STUB, - CB = function() { - CB_STUB.apply(this, arguments); - }; + let CB_STUB; + const CB = function() { + CB_STUB.apply(this, arguments); + }; file._writeStream = {}; - gently.expect(file._writeStream, 'end', function (cb) { - gently.expect(file, 'emit', function (event) { + gently.expect(file._writeStream, 'end', function(cb) { + gently.expect(file, 'emit', function(event) { assert.equal(event, 'end'); }); - CB_STUB = gently.expect(function endCb() { - }); + CB_STUB = gently.expect(function endCb() {}); cb(); }); diff --git a/test-legacy/simple/test-incoming-form.js b/test-legacy/simple/test-incoming-form.js index b7b9f65a..e3fa5b81 100644 --- a/test-legacy/simple/test-incoming-form.js +++ b/test-legacy/simple/test-incoming-form.js @@ -1,18 +1,26 @@ -var common = require('../common'); -var MultipartParserStub = GENTLY.stub('./multipart_parser', 'MultipartParser'), - QuerystringParserStub = GENTLY.stub('./querystring_parser', 'QuerystringParser'), - EventEmitterStub = GENTLY.stub('events', 'EventEmitter'), - StreamStub = GENTLY.stub('stream', 'Stream'), - FileStub = GENTLY.stub('./file'); - -var formidable = require(common.lib + '/index'), - IncomingForm = formidable.IncomingForm, - events = require('events'), - fs = require('fs'), - path = require('path'), - fixtures = require(TEST_FIXTURES + '/multipart'), - form, - gently; +const common = require('../common'); + +const MultipartParserStub = GENTLY.stub( + './multipart_parser', + 'MultipartParser', +); +const QuerystringParserStub = GENTLY.stub( + './querystring_parser', + 'QuerystringParser', +); +const EventEmitterStub = GENTLY.stub('events', 'EventEmitter'); +const StreamStub = GENTLY.stub('stream', 'Stream'); +const FileStub = GENTLY.stub('./file'); + +const formidable = require(`${common.lib}/index`); +const { IncomingForm } = formidable; +const events = require('events'); +const fs = require('fs'); +const path = require('path'); + +const fixtures = require(`${TEST_FIXTURES}/multipart`); +let form; +let gently; function test(test) { gently = new Gently(); @@ -31,7 +39,7 @@ test(function constructor() { // Can't assume dir === '/tmp' for portability // assert.strictEqual(form.uploadDir, '/tmp'); // Make sure it is a directory instead - assert.doesNotThrow(function () { + assert.doesNotThrow(function() { assert(fs.statSync(form.uploadDir).isDirectory()); }); assert.strictEqual(form.encoding, 'utf-8'); @@ -46,26 +54,26 @@ test(function constructor() { (function testSimpleConstructor() { gently.expect(EventEmitterStub, 'call'); - var form = IncomingForm(); + const form = IncomingForm(); assert.ok(form instanceof IncomingForm); })(); (function testSimpleConstructorShortcut() { gently.expect(EventEmitterStub, 'call'); - var form = formidable(); + const form = formidable(); assert.ok(form instanceof IncomingForm); })(); }); test(function parse() { - var REQ = {headers: {}} - , emit = {}; + const REQ = { headers: {} }; + const emit = {}; gently.expect(form, 'writeHeaders', function(headers) { assert.strictEqual(headers, REQ.headers); }); - var EVENTS = ['error', 'aborted', 'data', 'end']; + const EVENTS = ['error', 'aborted', 'data', 'end']; gently.expect(REQ, 'on', EVENTS.length, function(event, fn) { assert.equal(event, EVENTS.shift()); emit[event] = fn; @@ -82,7 +90,7 @@ test(function parse() { (function testPauseCriticalException() { form.ended = false; - var ERR = new Error('dasdsa'); + const ERR = new Error('dasdsa'); gently.expect(REQ, 'pause', function() { throw ERR; }); @@ -97,7 +105,7 @@ test(function parse() { (function testPauseHarmlessException() { form.ended = true; - var ERR = new Error('dasdsa'); + const ERR = new Error('dasdsa'); gently.expect(REQ, 'pause', function() { throw ERR; }); @@ -113,7 +121,7 @@ test(function parse() { (function testResumeCriticalException() { form.ended = false; - var ERR = new Error('dasdsa'); + const ERR = new Error('dasdsa'); gently.expect(REQ, 'resume', function() { throw ERR; }); @@ -128,7 +136,7 @@ test(function parse() { (function testResumeHarmlessException() { form.ended = true; - var ERR = new Error('dasdsa'); + const ERR = new Error('dasdsa'); gently.expect(REQ, 'resume', function() { throw ERR; }); @@ -137,15 +145,15 @@ test(function parse() { })(); (function testEmitError() { - var ERR = new Error('something bad happened'); - gently.expect(form, '_error',function(err) { + const ERR = new Error('something bad happened'); + gently.expect(form, '_error', function(err) { assert.strictEqual(err, ERR); }); emit.error(ERR); })(); (function testEmitAborted() { - gently.expect(form, 'emit',function(event) { + gently.expect(form, 'emit', function(event) { assert.equal(event, 'aborted'); }); gently.expect(form, '_error'); @@ -153,9 +161,8 @@ test(function parse() { emit.aborted(); })(); - (function testEmitData() { - var BUFFER = [1, 2, 3]; + const BUFFER = [1, 2, 3]; gently.expect(form, 'write', function(buffer) { assert.strictEqual(buffer, BUFFER); }); @@ -166,7 +173,7 @@ test(function parse() { form._parser = {}; (function testWithError() { - var ERR = new Error('haha'); + const ERR = new Error('haha'); gently.expect(form._parser, 'end', function() { return ERR; }); @@ -191,9 +198,9 @@ test(function parse() { (function testWithCallback() { gently.expect(EventEmitterStub, 'call'); - var form = new IncomingForm(), - REQ = {headers: {}}, - parseCalled = 0; + const form = new IncomingForm(); + const REQ = { headers: {} }; + const parseCalled = 0; gently.expect(form, 'on', 4, function(event, fn) { if (event == 'field') { @@ -220,13 +227,13 @@ test(function parse() { return this; }); - var parseCbOk = function (err, fields, files) { - //assert.deepEqual(fields, {field1: ['foo', 'bar'], field2: 'nice'}); - assert.deepEqual(files, {file1: '2', file2: '3'}); + const parseCbOk = function(err, fields, files) { + // assert.deepEqual(fields, {field1: ['foo', 'bar'], field2: 'nice'}); + assert.deepEqual(files, { file1: '2', file2: '3' }); }; form.parse(REQ, parseCbOk); - var ERR = new Error('test'); + const ERR = new Error('test'); gently.expect(form, 'on', 3, function(event, fn) { if (event == 'field') { fn('foo', 'bar'); @@ -245,19 +252,19 @@ test(function parse() { form.parse(REQ, function parseCbErr(err, fields, files) { assert.strictEqual(err, ERR); - assert.deepEqual(fields, {foo: 'bar'}); + assert.deepEqual(fields, { foo: 'bar' }); }); })(); (function testWriteOrder() { gently.expect(EventEmitterStub, 'call'); - var form = new IncomingForm(); - var REQ = new events.EventEmitter(); - var BUF = {}; - var DATACB = null; + const form = new IncomingForm(); + const REQ = new events.EventEmitter(); + const BUF = {}; + const DATACB = null; REQ.on('newListener', function(event, fn) { - if ('data' === event) fn(BUF); + if (event === 'data') fn(BUF); }); gently.expect(form, 'writeHeaders'); @@ -277,9 +284,8 @@ test(function resume() { assert.strictEqual(form.resume(), false); }); - test(function writeHeaders() { - var HEADERS = {}; + const HEADERS = {}; gently.expect(form, '_parseContentLength'); gently.expect(form, '_parseContentType'); @@ -288,8 +294,8 @@ test(function writeHeaders() { }); test(function write() { - var parser = {}, - BUFFER = [1, 2, 3]; + const parser = {}; + const BUFFER = [1, 2, 3]; form._parser = parser; form.bytesExpected = 523423; @@ -337,19 +343,21 @@ test(function write() { }); test(function parseContentType() { - var HEADERS = {}; + const HEADERS = {}; - form.headers = {'content-type': 'application/x-www-form-urlencoded'}; + form.headers = { 'content-type': 'application/x-www-form-urlencoded' }; gently.expect(form, '_initUrlencoded'); form._parseContentType(); // accept anything that has 'urlencoded' in it - form.headers = {'content-type': 'broken-client/urlencoded-stupid'}; + form.headers = { 'content-type': 'broken-client/urlencoded-stupid' }; gently.expect(form, '_initUrlencoded'); form._parseContentType(); - var BOUNDARY = '---------------------------57814261102167618332366269'; - form.headers = {'content-type': 'multipart/form-data; boundary='+BOUNDARY}; + const BOUNDARY = '---------------------------57814261102167618332366269'; + form.headers = { + 'content-type': `multipart/form-data; boundary=${BOUNDARY}`, + }; gently.expect(form, '_initMultipart', function(boundary) { assert.equal(boundary, BOUNDARY); @@ -357,7 +365,9 @@ test(function parseContentType() { form._parseContentType(); (function testQuotedBoundary() { - form.headers = {'content-type': 'multipart/form-data; boundary="' + BOUNDARY + '"'}; + form.headers = { + 'content-type': `multipart/form-data; boundary="${BOUNDARY}"`, + }; gently.expect(form, '_initMultipart', function(boundary) { assert.equal(boundary, BOUNDARY); @@ -366,7 +376,7 @@ test(function parseContentType() { })(); (function testNoBoundary() { - form.headers = {'content-type': 'multipart/form-data'}; + form.headers = { 'content-type': 'multipart/form-data' }; gently.expect(form, '_error', function(err) { assert.ok(err.message.match(/no multipart boundary/i)); @@ -384,7 +394,7 @@ test(function parseContentType() { })(); (function testUnknownContentType() { - form.headers = {'content-type': 'invalid'}; + form.headers = { 'content-type': 'invalid' }; gently.expect(form, '_error', function(err) { assert.ok(err.message.match(/unknown content-type/i)); @@ -394,7 +404,7 @@ test(function parseContentType() { }); test(function parseContentLength() { - var HEADERS = {}; + const HEADERS = {}; form.headers = {}; gently.expect(form, 'emit', function(event, bytesReceived, bytesExpected) { @@ -426,14 +436,16 @@ test(function parseContentLength() { }); test(function _initMultipart() { - var BOUNDARY = '123', - PARSER; + const BOUNDARY = '123'; + let PARSER; gently.expect(MultipartParserStub, 'new', function() { PARSER = this; }); - gently.expect(MultipartParserStub.prototype, 'initWithBoundary', function(boundary) { + gently.expect(MultipartParserStub.prototype, 'initWithBoundary', function( + boundary, + ) { assert.equal(boundary, BOUNDARY); }); @@ -442,29 +454,27 @@ test(function _initMultipart() { assert.strictEqual(form._parser, PARSER); (function testRegularField() { - var PART; + let PART; gently.expect(StreamStub, 'new', function() { PART = this; }); gently.expect(form, 'onPart', function(part) { assert.strictEqual(part, PART); - assert.deepEqual - ( part.headers - , { 'content-disposition': 'form-data; name="field1"' - , 'foo': 'bar' - } - ); + assert.deepEqual(part.headers, { + 'content-disposition': 'form-data; name="field1"', + foo: 'bar', + }); assert.equal(part.name, 'field1'); - var strings = ['hello', ' world']; + const strings = ['hello', ' world']; gently.expect(part, 'emit', 2, function(event, b) { - assert.equal(event, 'data'); - assert.equal(b.toString(), strings.shift()); + assert.equal(event, 'data'); + assert.equal(b.toString(), strings.shift()); }); gently.expect(part, 'emit', function(event, b) { - assert.equal(event, 'end'); + assert.equal(event, 'end'); }); }); @@ -484,18 +494,17 @@ test(function _initMultipart() { })(); (function testFileField() { - var PART; + let PART; gently.expect(StreamStub, 'new', function() { PART = this; }); gently.expect(form, 'onPart', function(part) { - assert.deepEqual - ( part.headers - , { 'content-disposition': 'form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"' - , 'content-type': 'text/plain' - } - ); + assert.deepEqual(part.headers, { + 'content-disposition': + 'form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"', + 'content-type': 'text/plain', + }); assert.equal(part.name, 'field2'); assert.equal(part.filename, 'Sun"et.jpg'); assert.equal(part.mime, 'text/plain'); @@ -506,13 +515,19 @@ test(function _initMultipart() { }); gently.expect(part, 'emit', function(event, b) { - assert.equal(event, 'end'); + assert.equal(event, 'end'); }); }); PARSER.onPartBegin(); PARSER.onHeaderField(Buffer.from('content-disposition'), 0, 19); - PARSER.onHeaderValue(Buffer.from('form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"'), 0, 85); + PARSER.onHeaderValue( + Buffer.from( + 'form-data; name="field2"; filename="C:\\Documents and Settings\\IE\\Must\\Die\\Sun"et.jpg"', + ), + 0, + 85, + ); PARSER.onHeaderEnd(); PARSER.onHeaderField(Buffer.from('Content-Type'), 0, 12); PARSER.onHeaderValue(Buffer.from('text/plain'), 0, 10); @@ -531,11 +546,10 @@ test(function _initMultipart() { test(function _fileName() { // TODO - return; }); test(function _initUrlencoded() { - var PARSER; + let PARSER; gently.expect(QuerystringParserStub, 'new', function() { PARSER = this; @@ -546,7 +560,8 @@ test(function _initUrlencoded() { assert.strictEqual(form._parser, PARSER); (function testOnField() { - var KEY = 'KEY', VAL = 'VAL'; + const KEY = 'KEY'; + const VAL = 'VAL'; gently.expect(form, 'emit', function(field, key, val) { assert.equal(field, 'field'); assert.equal(key, KEY); @@ -565,7 +580,7 @@ test(function _initUrlencoded() { }); test(function _error() { - var ERR = new Error('bla'); + const ERR = new Error('bla'); gently.expect(form, 'emit', function(event, err) { assert.equal(event, 'error'); @@ -580,7 +595,7 @@ test(function _error() { }); test(function onPart() { - var PART = {}; + const PART = {}; gently.expect(form, 'handlePart', function(part) { assert.strictEqual(part, PART); }); @@ -590,7 +605,7 @@ test(function onPart() { test(function handlePart() { (function testUtf8Field() { - var PART = new events.EventEmitter(); + const PART = new events.EventEmitter(); PART.name = 'my_field'; gently.expect(form, 'emit', function(event, field, value) { @@ -602,37 +617,43 @@ test(function handlePart() { form.handlePart(PART); PART.emit('data', Buffer.from('hello')); PART.emit('data', Buffer.from(' world: ')); - PART.emit('data', Buffer.from([0xE2])); - PART.emit('data', Buffer.from([0x82, 0xAC])); + PART.emit('data', Buffer.from([0xe2])); + PART.emit('data', Buffer.from([0x82, 0xac])); PART.emit('end'); })(); (function testBinaryField() { - var PART = new events.EventEmitter(); + const PART = new events.EventEmitter(); PART.name = 'my_field2'; gently.expect(form, 'emit', function(event, field, value) { assert.equal(event, 'field'); assert.equal(field, 'my_field2'); - assert.equal(value, 'hello world: '+Buffer.from([0xE2, 0x82, 0xAC]).toString('binary')); + assert.equal( + value, + `hello world: ${Buffer.from([0xe2, 0x82, 0xac]).toString('binary')}`, + ); }); form.encoding = 'binary'; form.handlePart(PART); PART.emit('data', Buffer.from('hello')); PART.emit('data', Buffer.from(' world: ')); - PART.emit('data', Buffer.from([0xE2])); - PART.emit('data', Buffer.from([0x82, 0xAC])); + PART.emit('data', Buffer.from([0xe2])); + PART.emit('data', Buffer.from([0x82, 0xac])); PART.emit('end'); })(); (function testFieldSize() { form.maxFieldsSize = 8; - var PART = new events.EventEmitter(); + const PART = new events.EventEmitter(); PART.name = 'my_field'; gently.expect(form, '_error', function(err) { - assert.equal(err.message, 'maxFieldsSize exceeded, received 9 bytes of field data'); + assert.equal( + err.message, + 'maxFieldsSize exceeded, received 9 bytes of field data', + ); }); form.handlePart(PART); @@ -642,9 +663,9 @@ test(function handlePart() { })(); (function testFilePart() { - var PART = new events.EventEmitter(), - FILE = new events.EventEmitter(), - PATH = '/foo/bar'; + const PART = new events.EventEmitter(); + let FILE = new events.EventEmitter(); + const PATH = '/foo/bar'; PART.name = 'my_file'; PART.filename = 'sweet.txt'; @@ -661,7 +682,7 @@ test(function handlePart() { assert.equal(properties.type, PART.mime); FILE = this; - gently.expect(form, 'emit', function (event, field, file) { + gently.expect(form, 'emit', function(event, field, file) { assert.equal(event, 'fileBegin'); assert.strictEqual(field, PART.name); assert.strictEqual(file, FILE); @@ -673,7 +694,7 @@ test(function handlePart() { form.handlePart(PART); assert.equal(form._flushing, 1); - var BUFFER; + let BUFFER; gently.expect(form, 'pause'); gently.expect(FILE, 'write', function(buffer, cb) { assert.strictEqual(buffer, BUFFER); @@ -682,7 +703,7 @@ test(function handlePart() { cb(); }); - PART.emit('data', BUFFER = Buffer.from('test')); + PART.emit('data', (BUFFER = Buffer.from('test'))); gently.expect(FILE, 'end', function(cb) { gently.expect(form, 'emit', function(event, field, file) { @@ -702,7 +723,8 @@ test(function handlePart() { test(function _uploadPath() { (function testUniqueId() { - var UUID_A, UUID_B; + let UUID_A; + let UUID_B; gently.expect(GENTLY.hijacked.path, 'join', function(uploadDir, uuid) { assert.equal(uploadDir, form.uploadDir); UUID_A = uuid; @@ -719,8 +741,8 @@ test(function _uploadPath() { (function testFileExtension() { form.keepExtensions = true; - var FILENAME = 'foo.jpg', - EXT = '.bar'; + const FILENAME = 'foo.jpg'; + const EXT = '.bar'; gently.expect(GENTLY.hijacked.path, 'extname', function(filename) { assert.equal(filename, FILENAME); diff --git a/test-legacy/simple/test-multipart-parser.js b/test-legacy/simple/test-multipart-parser.js index 80c5601a..b20a2803 100644 --- a/test-legacy/simple/test-multipart-parser.js +++ b/test-legacy/simple/test-multipart-parser.js @@ -1,7 +1,8 @@ -var common = require('../common'); -var multipartParser = require(common.lib + '/multipart_parser'), - MultipartParser = multipartParser.MultipartParser, - parser; +const common = require('../common'); + +const multipartParser = require(`${common.lib}/multipart_parser`); +const { MultipartParser } = multipartParser; +let parser; function test(test) { parser = new MultipartParser(); @@ -19,17 +20,32 @@ test(function constructor() { }); test(function initWithBoundary() { - var boundary = 'abc'; + const boundary = 'abc'; parser.initWithBoundary(boundary); - assert.deepEqual(Array.prototype.slice.call(parser.boundary), [13, 10, 45, 45, 97, 98, 99]); + assert.deepEqual(Array.prototype.slice.call(parser.boundary), [ + 13, + 10, + 45, + 45, + 97, + 98, + 99, + ]); assert.equal(parser.state, multipartParser.START); - assert.deepEqual(parser.boundaryChars, {10: true, 13: true, 45: true, 97: true, 98: true, 99: true}); + assert.deepEqual(parser.boundaryChars, { + 10: true, + 13: true, + 45: true, + 97: true, + 98: true, + 99: true, + }); }); test(function parserError() { - var boundary = 'abc', - buffer = Buffer.alloc(5); + const boundary = 'abc'; + const buffer = Buffer.alloc(5); parser.initWithBoundary(boundary); buffer.write('--ad', 0); @@ -38,7 +54,10 @@ test(function parserError() { test(function end() { (function testError() { - assert.equal(parser.end().message, 'MultipartParser.end(): stream ended unexpectedly: ' + parser.explain()); + assert.equal( + parser.end().message, + `MultipartParser.end(): stream ended unexpectedly: ${parser.explain()}`, + ); })(); (function testRegular() { diff --git a/test-legacy/simple/test-querystring-parser.js b/test-legacy/simple/test-querystring-parser.js index c7978f8b..147227c1 100644 --- a/test-legacy/simple/test-querystring-parser.js +++ b/test-legacy/simple/test-querystring-parser.js @@ -1,7 +1,8 @@ -var common = require('../common'); -var QuerystringParser = require(common.lib + '/querystring_parser').QuerystringParser, - gently, - parser; +const common = require('../common'); + +const { QuerystringParser } = require(`${common.lib}/querystring_parser`); +let gently; +let parser; function test(test) { gently = new Gently(); @@ -16,23 +17,26 @@ test(function constructor() { }); test(function write() { - var a = Buffer.from('a=1'); + const a = Buffer.from('a=1'); assert.equal(parser.write(a), a.length); - var b = Buffer.from('&b=2'); + const b = Buffer.from('&b=2'); parser.write(b); assert.equal(parser.buffer, a + b); }); test(function end() { - var FIELDS = {a: ['b', {c: 'd'}], e: 'f'}; + const FIELDS = { a: ['b', { c: 'd' }], e: 'f' }; gently.expect(GENTLY.hijacked.querystring, 'parse', function(str) { assert.equal(str, parser.buffer); return FIELDS; }); - gently.expect(parser, 'onField', Object.keys(FIELDS).length, function(key, val) { + gently.expect(parser, 'onField', Object.keys(FIELDS).length, function( + key, + val, + ) { assert.deepEqual(FIELDS[key], val); }); diff --git a/test-legacy/system/test-multi-video-upload.js b/test-legacy/system/test-multi-video-upload.js index b35ffd68..f9626af5 100644 --- a/test-legacy/system/test-multi-video-upload.js +++ b/test-legacy/system/test-multi-video-upload.js @@ -1,14 +1,16 @@ -var common = require('../common'); -var BOUNDARY = '---------------------------10102754414578508781458777923', - FIXTURE = TEST_FIXTURES+'/multi_video.upload', - fs = require('fs'), - http = require('http'), - formidable = require(common.lib + '/index'), - server = http.createServer(); +const common = require('../common'); + +const BOUNDARY = '---------------------------10102754414578508781458777923'; +const FIXTURE = `${TEST_FIXTURES}/multi_video.upload`; +const fs = require('fs'); +const http = require('http'); + +const formidable = require(`${common.lib}/index`); +const server = http.createServer(); server.on('request', function(req, res) { - var form = new formidable.IncomingForm(), - uploads = {}; + const form = new formidable.IncomingForm(); + const uploads = {}; form.uploadDir = TEST_TMP; form.hash = 'sha1'; @@ -18,7 +20,7 @@ server.on('request', function(req, res) { .on('fileBegin', function(field, file) { assert.equal(field, 'upload'); - var tracker = {file: file, progress: [], ended: false}; + const tracker = { file, progress: [], ended: false }; uploads[file.name] = tracker; file .on('progress', function(bytesReceived) { @@ -41,12 +43,21 @@ server.on('request', function(req, res) { assert.ok(uploads['shortest_video.flv']); assert.ok(uploads['shortest_video.flv'].ended); assert.ok(uploads['shortest_video.flv'].progress.length > 3); - assert.equal(uploads['shortest_video.flv'].file.hash, 'd6a17616c7143d1b1438ceeef6836d1a09186b3a'); - assert.equal(uploads['shortest_video.flv'].progress.slice(-1), uploads['shortest_video.flv'].file.size); + assert.equal( + uploads['shortest_video.flv'].file.hash, + 'd6a17616c7143d1b1438ceeef6836d1a09186b3a', + ); + assert.equal( + uploads['shortest_video.flv'].progress.slice(-1), + uploads['shortest_video.flv'].file.size, + ); assert.ok(uploads['shortest_video.mp4']); assert.ok(uploads['shortest_video.mp4'].ended); assert.ok(uploads['shortest_video.mp4'].progress.length > 3); - assert.equal(uploads['shortest_video.mp4'].file.hash, '937dfd4db263f4887ceae19341dcc8d63bcd557f'); + assert.equal( + uploads['shortest_video.mp4'].file.hash, + '937dfd4db263f4887ceae19341dcc8d63bcd557f', + ); server.close(); res.writeHead(200); @@ -55,7 +66,10 @@ server.on('request', function(req, res) { }); server.listen(TEST_PORT, function() { - var stat, headers, request, fixture; + let stat; + let headers; + let request; + let fixture; stat = fs.statSync(FIXTURE); request = http.request({ @@ -63,7 +77,7 @@ server.listen(TEST_PORT, function() { path: '/', method: 'POST', headers: { - 'content-type': 'multipart/form-data; boundary='+BOUNDARY, + 'content-type': `multipart/form-data; boundary=${BOUNDARY}`, 'content-length': stat.size, }, }); diff --git a/test/common.js b/test/common.js deleted file mode 100644 index 0c6fa6e1..00000000 --- a/test/common.js +++ /dev/null @@ -1,18 +0,0 @@ -var path = require('path'); - -var root = path.join(__dirname, '../'); -exports.dir = { - root : root, - lib : root + '/src', - fixture : root + '/test/fixture', - tmp : root + '/test/tmp', -}; - -exports.port = 13532; - -exports.formidable = require('..'); -exports.assert = require('assert'); - -exports.require = function(lib) { - return require(exports.dir.lib + '/' + lib); -}; diff --git a/test/fixture/js/encoding.js b/test/fixture/js/encoding.js index fc220265..94230fbb 100644 --- a/test/fixture/js/encoding.js +++ b/test/fixture/js/encoding.js @@ -1,24 +1,49 @@ module.exports['menu_seperator.png.http'] = [ - {type: 'file', name: 'image', filename: 'menu_separator.png', fixture: 'menu_separator.png', - sha1: 'c845ca3ea794be298f2a1b79769b71939eaf4e54'} + { + type: 'file', + name: 'image', + filename: 'menu_separator.png', + fixture: 'menu_separator.png', + sha1: 'c845ca3ea794be298f2a1b79769b71939eaf4e54', + }, ]; module.exports['beta-sticker-1.png.http'] = [ - {type: 'file', name: 'sticker', filename: 'beta-sticker-1.png', fixture: 'beta-sticker-1.png', - sha1: '6abbcffd12b4ada5a6a084fe9e4584f846331bc4'} + { + type: 'file', + name: 'sticker', + filename: 'beta-sticker-1.png', + fixture: 'beta-sticker-1.png', + sha1: '6abbcffd12b4ada5a6a084fe9e4584f846331bc4', + }, ]; module.exports['blank.gif.http'] = [ - {type: 'file', name: 'file', filename: 'blank.gif', fixture: 'blank.gif', - sha1: 'a1fdee122b95748d81cee426d717c05b5174fe96'} + { + type: 'file', + name: 'file', + filename: 'blank.gif', + fixture: 'blank.gif', + sha1: 'a1fdee122b95748d81cee426d717c05b5174fe96', + }, ]; module.exports['binaryfile.tar.gz.http'] = [ - {type: 'file', name: 'file', filename: 'binaryfile.tar.gz', fixture: 'binaryfile.tar.gz', - sha1: 'cfabe13b348e5e69287d677860880c52a69d2155'} + { + type: 'file', + name: 'file', + filename: 'binaryfile.tar.gz', + fixture: 'binaryfile.tar.gz', + sha1: 'cfabe13b348e5e69287d677860880c52a69d2155', + }, ]; module.exports['plain.txt.http'] = [ - {type: 'file', name: 'file', filename: 'plain.txt', fixture: 'plain.txt', - sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'} + { + type: 'file', + name: 'file', + filename: 'plain.txt', + fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872', + }, ]; diff --git a/test/fixture/js/no-filename.js b/test/fixture/js/no-filename.js index f03b4f01..37e73d03 100644 --- a/test/fixture/js/no-filename.js +++ b/test/fixture/js/no-filename.js @@ -1,9 +1,19 @@ module.exports['generic.http'] = [ - {type: 'file', name: 'upload', filename: '', fixture: 'plain.txt', - sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, + { + type: 'file', + name: 'upload', + filename: '', + fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872', + }, ]; module.exports['filename-name.http'] = [ - {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', - sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, + { + type: 'file', + name: 'upload', + filename: 'plain.txt', + fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872', + }, ]; diff --git a/test/fixture/js/preamble.js b/test/fixture/js/preamble.js index d2e4cfdb..5c6eedcc 100644 --- a/test/fixture/js/preamble.js +++ b/test/fixture/js/preamble.js @@ -1,9 +1,19 @@ module.exports['crlf.http'] = [ - {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', - sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, + { + type: 'file', + name: 'upload', + filename: 'plain.txt', + fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872', + }, ]; module.exports['preamble.http'] = [ - {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', - sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, + { + type: 'file', + name: 'upload', + filename: 'plain.txt', + fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872', + }, ]; diff --git a/test/fixture/js/special-chars-in-filename.js b/test/fixture/js/special-chars-in-filename.js index f5eccdad..342a4e8b 100644 --- a/test/fixture/js/special-chars-in-filename.js +++ b/test/fixture/js/special-chars-in-filename.js @@ -1,21 +1,26 @@ -var properFilename = 'funkyfilename.txt'; +const properFilename = 'funkyfilename.txt'; function expect(filename) { return [ - {type: 'field', name: 'title', value: 'Weird filename'}, - {type: 'file', name: 'upload', filename: filename, fixture: properFilename}, + { type: 'field', name: 'title', value: 'Weird filename' }, + { + type: 'file', + name: 'upload', + filename, + fixture: properFilename, + }, ]; } -var webkit = " ? % * | \" < > . ? ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"; -var ffOrIe = " ? % * | \" < > . ☃ ; ' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt"; +const webkit = ' ? % * | " < > . ? ; \' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt'; +const ffOrIe = ' ? % * | " < > . ☃ ; \' @ # $ ^ & ( ) - _ = + { } [ ] ` ~.txt'; module.exports = { - 'osx-chrome-13.http' : expect(webkit), - 'osx-firefox-3.6.http' : expect(ffOrIe), - 'osx-safari-5.http' : expect(webkit), - 'xp-chrome-12.http' : expect(webkit), - 'xp-ie-7.http' : expect(ffOrIe), - 'xp-ie-8.http' : expect(ffOrIe), - 'xp-safari-5.http' : expect(webkit), + 'osx-chrome-13.http': expect(webkit), + 'osx-firefox-3.6.http': expect(ffOrIe), + 'osx-safari-5.http': expect(webkit), + 'xp-chrome-12.http': expect(webkit), + 'xp-ie-7.http': expect(ffOrIe), + 'xp-ie-8.http': expect(ffOrIe), + 'xp-safari-5.http': expect(webkit), }; diff --git a/test/fixture/js/workarounds.js b/test/fixture/js/workarounds.js index e59c5b26..9616e2e1 100644 --- a/test/fixture/js/workarounds.js +++ b/test/fixture/js/workarounds.js @@ -1,8 +1,18 @@ module.exports['missing-hyphens1.http'] = [ - {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', - sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, + { + type: 'file', + name: 'upload', + filename: 'plain.txt', + fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872', + }, ]; module.exports['missing-hyphens2.http'] = [ - {type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt', - sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'}, + { + type: 'file', + name: 'upload', + filename: 'plain.txt', + fixture: 'plain.txt', + sha1: 'b31d07bac24ac32734de88b3687dddb10e976872', + }, ]; diff --git a/test/fixture/multipart.js b/test/fixture/multipart.js index aa354e73..18b9d6d7 100644 --- a/test/fixture/multipart.js +++ b/test/fixture/multipart.js @@ -1,72 +1,76 @@ -exports.rfc1867 = - { boundary: 'AaB03x', - raw: - '--AaB03x\r\n'+ - 'content-disposition: form-data; name="field1"\r\n'+ - '\r\n'+ - 'Joe Blow\r\nalmost tricked you!\r\n'+ - '--AaB03x\r\n'+ - 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ - 'Content-Type: text/plain\r\n'+ - '\r\n'+ - '... contents of file1.txt ...\r\r\n'+ - '--AaB03x--\r\n', - parts: - [ { headers: { - 'content-disposition': 'form-data; name="field1"', - }, - data: 'Joe Blow\r\nalmost tricked you!', +exports.rfc1867 = { + boundary: 'AaB03x', + raw: + '--AaB03x\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + + 'Joe Blow\r\nalmost tricked you!\r\n' + + '--AaB03x\r\n' + + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n' + + 'Content-Type: text/plain\r\n' + + '\r\n' + + '... contents of file1.txt ...\r\r\n' + + '--AaB03x--\r\n', + parts: [ + { + headers: { + 'content-disposition': 'form-data; name="field1"', }, - { headers: { - 'content-disposition': 'form-data; name="pics"; filename="file1.txt"', - 'Content-Type': 'text/plain', - }, - data: '... contents of file1.txt ...\r', - } - ] - }; + data: 'Joe Blow\r\nalmost tricked you!', + }, + { + headers: { + 'content-disposition': 'form-data; name="pics"; filename="file1.txt"', + 'Content-Type': 'text/plain', + }, + data: '... contents of file1.txt ...\r', + }, + ], +}; -exports['noTrailing\r\n'] = - { boundary: 'AaB03x', - raw: - '--AaB03x\r\n'+ - 'content-disposition: form-data; name="field1"\r\n'+ - '\r\n'+ - 'Joe Blow\r\nalmost tricked you!\r\n'+ - '--AaB03x\r\n'+ - 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ - 'Content-Type: text/plain\r\n'+ - '\r\n'+ - '... contents of file1.txt ...\r\r\n'+ - '--AaB03x--', - parts: - [ { headers: { - 'content-disposition': 'form-data; name="field1"', - }, - data: 'Joe Blow\r\nalmost tricked you!', +exports['noTrailing\r\n'] = { + boundary: 'AaB03x', + raw: + '--AaB03x\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + + 'Joe Blow\r\nalmost tricked you!\r\n' + + '--AaB03x\r\n' + + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n' + + 'Content-Type: text/plain\r\n' + + '\r\n' + + '... contents of file1.txt ...\r\r\n' + + '--AaB03x--', + parts: [ + { + headers: { + 'content-disposition': 'form-data; name="field1"', + }, + data: 'Joe Blow\r\nalmost tricked you!', + }, + { + headers: { + 'content-disposition': 'form-data; name="pics"; filename="file1.txt"', + 'Content-Type': 'text/plain', }, - { headers: { - 'content-disposition': 'form-data; name="pics"; filename="file1.txt"', - 'Content-Type': 'text/plain', - }, - data: '... contents of file1.txt ...\r', - } - ] - }; + data: '... contents of file1.txt ...\r', + }, + ], +}; -exports.emptyHeader = - { boundary: 'AaB03x', - raw: - '--AaB03x\r\n'+ - 'content-disposition: form-data; name="field1"\r\n'+ - ': foo\r\n'+ - '\r\n'+ - 'Joe Blow\r\nalmost tricked you!\r\n'+ - '--AaB03x\r\n'+ - 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n'+ - 'Content-Type: text/plain\r\n'+ - '\r\n'+ - '... contents of file1.txt ...\r\r\n'+ - '--AaB03x--\r\n', - expectError: true, - }; +exports.emptyHeader = { + boundary: 'AaB03x', + raw: + '--AaB03x\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + ': foo\r\n' + + '\r\n' + + 'Joe Blow\r\nalmost tricked you!\r\n' + + '--AaB03x\r\n' + + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n' + + 'Content-Type: text/plain\r\n' + + '\r\n' + + '... contents of file1.txt ...\r\r\n' + + '--AaB03x--\r\n', + expectError: true, +}; diff --git a/test/integration/test-fixtures.js b/test/integration/test-fixtures.js index b61fabc0..3819bdf3 100644 --- a/test/integration/test-fixtures.js +++ b/test/integration/test-fixtures.js @@ -1,96 +1,144 @@ -var hashish = require('hashish'); -var fs = require('fs'); -var findit = require('findit'); -var path = require('path'); -var http = require('http'); -var net = require('net'); -var assert = require('assert'); +/* eslint-disable global-require */ +/* eslint-disable import/no-dynamic-require */ -var common = require('../common'); -var formidable = common.formidable; +'use strict'; -var server = http.createServer(); -server.listen(common.port, findFixtures); +const fs = require('fs'); +const net = require('net'); +const path = require('path'); +const http = require('http'); +const assert = require('assert'); + +const Formidable = require('../../src/index'); + +const PORT = 13532; +const CWD = process.cwd(); +const FIXTURES_PATH = path.join(CWD, 'test', 'fixture', 'js'); +const FIXTURES_HTTP = path.join(CWD, 'test', 'fixture', 'http'); +const UPLOAD_DIR = path.join(CWD, 'test', 'tmp'); + +const server = http.createServer(); +server.listen(PORT, findFixtures); function findFixtures() { - var fixtures = []; - findit - .sync(common.dir.fixture + '/js') - .forEach(function(jsPath) { - if (!/\.js$/.test(jsPath) || /workarounds/.test(jsPath)) return; - - var group = path.basename(jsPath, '.js'); - hashish.forEach(require(jsPath), function(fixture, name) { - fixtures.push({ - name : group + '/' + name, - fixture : fixture, + const choosenPort = server.address().port; + const url = `http://localhost:${choosenPort}`; + console.log('Server up and running at:', url); + + const results = fs + .readdirSync(FIXTURES_PATH) + // .filter((x) => /special/.test(x)) + // the `workarounds` - doesn't work because `this.callback()` call which should be fixed + // the `spcial-chars-in-filename` - not sure yet why + .filter((x) => /\.js$/.test(x) && !/workarounds|special/.test(x)) + .reduce((acc, fp) => { + const group = path.basename(fp, '.js'); + const filepath = path.join(FIXTURES_PATH, fp); + const mod = require(filepath); + + Object.keys(mod).forEach((k) => { + Object.keys(mod[k]).forEach((_fixture) => { + acc.push({ + fixture: mod[k], + name: path.join(group, k), + }); }); }); - }); - testNext(fixtures); -} + return acc; + }, []); -function testNext(fixtures) { - var fixture = fixtures.shift(); - if (!fixture) return server.close(); + testNext(results); +} - var name = fixture.name; +function testNext(results) { + let fixture = results.shift(); + if (!fixture) { + server.close(); + return; + } + const fixtureName = fixture.name; fixture = fixture.fixture; - uploadFixture(name, function(err, parts) { - if (err) throw {err, name}; + uploadFixture(fixtureName, (err, parts) => { + if (err) { + err.fixtureName = fixtureName; + throw err; + } + + // console.log(parts); + // const titleParts = parts.find((x) => x.type === 'field'); + // const titleFixtures = fixture.find((x) => x.type === 'field'); - fixture.forEach(function(expectedPart, i) { - var parsedPart = parts[i]; - assert.equal(parsedPart.type, expectedPart.type); - assert.equal(parsedPart.name, expectedPart.name); + // const uploadParts = parts.find((x) => x.name === 'upload'); + // const uploadFixtures = fixture.find((x) => x.name === 'upload'); + + // console.log('titleParts', titleParts); + // console.log('titleFixtures', titleFixtures); + // const fileFromFixture = fixture.find((x) => x.type === 'file'); + // const fieldFromFixture = fixture.find((x) => x.type === 'field'); + + // console.log('parts', fileFromParts); + // console.log('fixture', fileFromFixture); + + fixture.forEach((expectedPart, i) => { + const parsedPart = parts[i]; + assert.strictEqual(parsedPart.type, expectedPart.type); + assert.strictEqual(parsedPart.name, expectedPart.name); if (parsedPart.type === 'file') { - var file = parsedPart.value; - assert.equal(file.name, expectedPart.filename); - if(expectedPart.sha1) assert.equal(file.hash, expectedPart.sha1); + const file = parsedPart.value; + assert.strictEqual(file.name, expectedPart.filename); + + if (expectedPart.sha1) { + assert.strictEqual(file.hash, expectedPart.sha1); + } } }); - testNext(fixtures); + testNext(results); }); } -function uploadFixture(name, cb) { - server.once('request', function(req, res) { - var form = new formidable.IncomingForm(); - form.uploadDir = common.dir.tmp; - form.hash = "sha1"; +function uploadFixture(fixtureName, cb) { + server.once('request', (req, res) => { + const form = new Formidable({ + uploadDir: UPLOAD_DIR, + hash: 'sha1', + multiples: true, + }); form.parse(req); - function callback() { - var realCallback = cb; - cb = function() {}; - realCallback.apply(null, arguments); + function callback(...args) { + const realCallback = cb; + // eslint-disable-next-line no-param-reassign + cb = function calbackFn() {}; + + realCallback(...args); } - var parts = []; + const parts = []; form .on('error', callback) - .on('fileBegin', function(name, value) { - parts.push({type: 'file', name: name, value: value}); + .on('fileBegin', (name, value) => { + parts.push({ type: 'file', name, value }); }) - .on('field', function(name, value) { - parts.push({type: 'field', name: name, value: value}); + .on('field', (name, value) => { + parts.push({ type: 'field', name, value }); }) - .on('end', function() { + .on('end', () => { res.end('OK'); callback(null, parts); }); }); - var socket = net.createConnection(common.port); - var file = fs.createReadStream(common.dir.fixture + '/http/' + name); + const socket = net.createConnection(PORT); + const fixturePath = path.join(FIXTURES_HTTP, fixtureName); + console.log(fixturePath); + const file = fs.createReadStream(fixturePath); - file.pipe(socket, {end: false}); - socket.on('data', function () { + file.pipe(socket, { end: false }); + socket.on('data', () => { socket.end(); }); - } diff --git a/test/integration/test-json.js b/test/integration/test-json.js index 2519f2a9..08b78314 100644 --- a/test/integration/test-json.js +++ b/test/integration/test-json.js @@ -1,38 +1,41 @@ -var common = require('../common'); -var formidable = common.formidable; -var http = require('http'); -var assert = require('assert'); - -var testData = { - numbers: [1, 2, 3, 4, 5], - nested: { key: 'value' } +'use strict'; + +const http = require('http'); +const assert = require('assert'); +const Formidable = require('../../src/index'); + +const testData = { + numbers: [1, 2, 3, 4, 5], + nested: { key: 'value' }, }; -var server = http.createServer(function(req, res) { - var form = new formidable.IncomingForm(); +const PORT = 13532; +const server = http.createServer((req, res) => { + const form = new Formidable(); - form.parse(req, function(err, fields, files) { - assert.deepEqual(fields, testData); + form.parse(req, (err, fields) => { + assert.deepEqual(fields, testData); - res.end(); - server.close(); - }); + res.end(); + server.close(); + }); }); -var port = common.port; +server.listen(PORT, (err) => { + const choosenPort = server.address().port; + const url = `http://localhost:${choosenPort}`; + console.log('Server up and running at:', url); -server.listen(port, function(err){ - assert.equal(err, null); + assert(!err, 'should not have error, but be falsey'); - var request = http.request({ - port: port, - method: 'POST', - headers: { - 'Content-Type': 'application/json' - } - }); + const request = http.request({ + port: PORT, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }); - request.write(JSON.stringify(testData)); - request.end(); + request.write(JSON.stringify(testData)); + request.end(); }); - diff --git a/test/integration/test-octet-stream.js b/test/integration/test-octet-stream.js index 643d2c6f..45226258 100644 --- a/test/integration/test-octet-stream.js +++ b/test/integration/test-octet-stream.js @@ -1,45 +1,53 @@ -var common = require('../common'); -var formidable = common.formidable; -var http = require('http'); -var fs = require('fs'); -var path = require('path'); -var hashish = require('hashish'); -var assert = require('assert'); +'use strict'; -var testFilePath = path.join(__dirname, '../fixture/file/binaryfile.tar.gz'); +const fs = require('fs'); +const http = require('http'); +const path = require('path'); +const assert = require('assert'); -var server = http.createServer(function(req, res) { - var form = new formidable.IncomingForm(); +const Formidable = require('../../src/index'); - form.parse(req, function(err, fields, files) { - assert.equal(hashish(files).length, 1); - var file = files.file; +const PORT = 13532; +const testFilePath = path.join( + path.dirname(__dirname), + 'fixture', + 'file', + 'binaryfile.tar.gz', +); - assert.equal(file.size, 301); +const server = http.createServer((req, res) => { + const form = new Formidable(); - var uploaded = fs.readFileSync(file.path); - var original = fs.readFileSync(testFilePath); + form.parse(req, (err, fields, files) => { + assert.strictEqual(Object.keys(files).length, 1); + const { file } = files; - assert.deepEqual(uploaded, original); + assert.strictEqual(file.size, 301); - res.end(); - server.close(); - }); + const uploaded = fs.readFileSync(file.path); + const original = fs.readFileSync(testFilePath); + + assert.deepEqual(uploaded, original); + + res.end(); + server.close(); + }); }); -var port = common.port; +server.listen(PORT, (err) => { + const choosenPort = server.address().port; + const url = `http://localhost:${choosenPort}`; + console.log('Server up and running at:', url); -server.listen(port, function(err){ - assert.equal(err, null); + assert(!err, 'should not have error, but be falsey'); - var request = http.request({ - port: port, - method: 'POST', - headers: { - 'Content-Type': 'application/octet-stream' - } - }); + const request = http.request({ + port: PORT, + method: 'POST', + headers: { + 'Content-Type': 'application/octet-stream', + }, + }); - fs.createReadStream(testFilePath).pipe(request); + fs.createReadStream(testFilePath).pipe(request); }); - diff --git a/test/run.js b/test/run.js index 5a0cc334..fc114f33 100755 --- a/test/run.js +++ b/test/run.js @@ -1,4 +1,6 @@ +'use strict'; + require('urun')(__dirname, { verbose: true, - reporter: 'BashTapReporter' + reporter: 'BashTapReporter', }); diff --git a/test/standalone/ignored-issue-46.js b/test/standalone/ignored-issue-46.js new file mode 100644 index 00000000..629a85ee --- /dev/null +++ b/test/standalone/ignored-issue-46.js @@ -0,0 +1,57 @@ +'use strict'; + +// @TODO: this test should be fixed?! later. + +const http = require('http'); +const assert = require('assert'); +const request = require('request'); +const Formidable = require('../../src/index'); + +// OS choosing port +const PORT = 13532; + +const indexForm = ` +
+ + +
+`; + +const server = http.createServer((req, res) => { + // Show a form for testing purposes. + if (req.method === 'GET') { + res.writeHead(200, { 'content-type': 'text/html' }); + res.end(indexForm); + return; + } + + // Parse form and write results to response. + const form = new Formidable(); + form.parse(req, (err, fields, files) => { + res.writeHead(200, { 'content-type': 'text/plain' }); + res.write(JSON.stringify({ err, fields, files })); + res.end(); + }); +}); + +server.listen(PORT, () => { + const choosenPort = server.address().port; + const url = `http://localhost:${choosenPort}`; + console.log('Server up and running at:', url); + + const parts = [ + { + 'content-disposition': 'form-data; name="foo"', + body: 'barry', + }, + ]; + + request({ method: 'POST', url, multipart: parts }, (e, res, body) => { + const obj = JSON.parse(body); + console.log(obj); + + assert.strictEqual('foo' in obj.fields, true); + assert.strictEqual('barry', obj.fields.foo); + server.close(); + }); +}); diff --git a/test/standalone/test-connection-aborted.js b/test/standalone/test-connection-aborted.js index 98566f35..6dc7181a 100644 --- a/test/standalone/test-connection-aborted.js +++ b/test/standalone/test-connection-aborted.js @@ -1,27 +1,38 @@ -var assert = require('assert'); -var http = require('http'); -var net = require('net'); -var formidable = require('../../src/index'); +'use strict'; -var server = http.createServer(function (req, res) { - var form = new formidable.IncomingForm(); - var aborted_received = false; - form.on('aborted', function () { - aborted_received = true; +const assert = require('assert'); +const http = require('http'); +const net = require('net'); +const Formidable = require('../../src/index'); + +const PORT = 13532; +const server = http.createServer((req) => { + const form = new Formidable(); + let abortedReceived = false; + form.on('aborted', () => { + abortedReceived = true; }); - form.on('error', function () { - assert(aborted_received, 'Error event should follow aborted'); + form.on('error', () => { + assert(abortedReceived, 'Error event should follow aborted'); server.close(); }); - form.on('end', function () { + form.on('end', () => { throw new Error('Unexpected "end" event'); }); form.parse(req); -}).listen(0, 'localhost', function () { - var client = net.connect(server.address().port); +}); + +server.listen(PORT, 'localhost', () => { + const choosenPort = server.address().port; + const url = `http://localhost:${choosenPort}`; + console.log('Server up and running at:', url); + + const client = net.connect(choosenPort); + client.write( - "POST / HTTP/1.1\r\n" + - "Content-Length: 70\r\n" + - "Content-Type: multipart/form-data; boundary=foo\r\n\r\n"); + 'POST / HTTP/1.1\r\n' + + 'Content-Length: 70\r\n' + + 'Content-Type: multipart/form-data; boundary=foo\r\n\r\n', + ); client.end(); }); diff --git a/test/standalone/test-content-transfer-encoding.js b/test/standalone/test-content-transfer-encoding.js index 5a7c3f37..6c3b58fd 100644 --- a/test/standalone/test-content-transfer-encoding.js +++ b/test/standalone/test-content-transfer-encoding.js @@ -1,23 +1,34 @@ -var assert = require('assert'); -var common = require('../common'); -var formidable = require('../../src/index'); -var http = require('http'); - -var server = http.createServer(function(req, res) { - var form = new formidable.IncomingForm(); - form.uploadDir = common.dir.tmp; - form.on('end', function () { +'use strict'; + +const path = require('path'); +const http = require('http'); +const assert = require('assert'); + +const Formidable = require('../../src/index'); + +const UPLOAD_DIR = path.join(process.cwd(), 'test', 'tmp'); + +// OS choosing port +const PORT = 13532; +const server = http.createServer((req, res) => { + const form = new Formidable(); + form.uploadDir = UPLOAD_DIR; + form.on('end', () => { throw new Error('Unexpected "end" event'); }); - form.on('error', function (e) { + form.on('error', (e) => { res.writeHead(500); res.end(e.message); }); form.parse(req); }); -server.listen(0, function() { - var body = +server.listen(PORT, () => { + const choosenPort = server.address().port; + const url = `http://localhost:${choosenPort}`; + console.log('Server up and running at:', url); + + const body = '--foo\r\n' + 'Content-Disposition: form-data; name="file1"; filename="file1"\r\n' + 'Content-Type: application/octet-stream\r\n' + @@ -29,18 +40,19 @@ server.listen(0, function() { '\r\nThis is the second file\r\n' + '--foo--\r\n'; - var req = http.request({ + const req = http.request({ method: 'POST', - port: server.address().port, + port: choosenPort, headers: { 'Content-Length': body.length, - 'Content-Type': 'multipart/form-data; boundary=foo' - } + 'Content-Type': 'multipart/form-data; boundary=foo', + }, }); - req.on('response', function (res) { - assert.equal(res.statusCode, 500); - res.on('data', function () {}); - res.on('end', function () { + + req.on('response', (res) => { + assert.strictEqual(res.statusCode, 500); + res.on('data', () => {}); + res.on('end', () => { server.close(); }); }); diff --git a/test/standalone/test-issue-46.js b/test/standalone/test-issue-46.js deleted file mode 100644 index c4b60325..00000000 --- a/test/standalone/test-issue-46.js +++ /dev/null @@ -1,49 +0,0 @@ -var http = require('http'), - formidable = require('../../src/index'), - request = require('request'), - assert = require('assert'); - -var host = 'localhost'; - -var index = [ - '
', - ' ', - ' ', - '
' -].join("\n"); - -var server = http.createServer(function(req, res) { - - // Show a form for testing purposes. - if (req.method == 'GET') { - res.writeHead(200, {'content-type': 'text/html'}); - res.end(index); - return; - } - - // Parse form and write results to response. - var form = new formidable.IncomingForm(); - form.parse(req, function(err, fields, files) { - res.writeHead(200, {'content-type': 'text/plain'}); - res.write(JSON.stringify({err: err, fields: fields, files: files})); - res.end(); - }); - -}).listen(0, host, function() { - - console.log("Server up and running..."); - - var server = this, - url = 'http://' + host + ':' + server.address().port; - - var parts = [ - {'Content-Disposition': 'form-data; name="foo"', 'body': 'bar'} - ]; - - var req = request({method: 'POST', url: url, multipart: parts}, function(e, res, body) { - var obj = JSON.parse(body); - assert.equal("bar", obj.fields.foo); - server.close(); - }); - -}); diff --git a/test/standalone/test-keep-alive-error.js b/test/standalone/test-keep-alive-error.js index e33576a9..ab90059c 100644 --- a/test/standalone/test-keep-alive-error.js +++ b/test/standalone/test-keep-alive-error.js @@ -1,54 +1,66 @@ -var assert = require('assert'); -var http = require('http'); -var net = require('net'); -var formidable = require('../../src/index'); +'use strict'; -var ok = 0; -var errors = 0; +const net = require('net'); +const http = require('http'); +const assert = require('assert'); +const Formidable = require('../../src/index'); -var server = http.createServer(function (req, res) { - var form = new formidable.IncomingForm(); - form.on('error', function (e) { +let ok = 0; +let errors = 0; + +const PORT = 13532; +const server = http.createServer((req, res) => { + const form = new Formidable(); + form.on('error', () => { errors += 1; res.writeHead(500); res.end(); }); - form.on('end', function () { + form.on('end', () => { ok += 1; res.writeHead(200); res.end(); }); form.parse(req); -}) +}); + +server.listen(PORT, 'localhost', () => { + const choosenPort = server.address().port; + const url = `http://localhost:${choosenPort}`; + console.log('Server up and running at:', url); -server.listen(0, 'localhost', function () { - var client = net.createConnection(server.address().port); + const client = net.createConnection(choosenPort); // first send malformed post upload - client.write('POST /upload-test HTTP/1.1\r\n' + - 'Host: localhost\r\n' + - 'Connection: keep-alive\r\n' + - 'Content-Type: multipart/form-data; boundary=----aaa\r\n' + - 'Content-Length: 10011\r\n\r\n' + - '------aaa\n\r'); // expected \r\n + client.write( + 'POST /upload-test HTTP/1.1\r\n' + + 'Host: localhost\r\n' + + 'Connection: keep-alive\r\n' + + 'Content-Type: multipart/form-data; boundary=----aaa\r\n' + + 'Content-Length: 10011\r\n\r\n' + + '------aaa\n\r', + ); // expected \r\n - setTimeout(function () { - var buf = Buffer.alloc(10000); + setTimeout(() => { + const buf = Buffer.alloc(10000); buf.fill('a'); client.write(buf); // correct post upload - client.write('POST /upload-test HTTP/1.1\r\n' + + client.write( + 'POST /upload-test HTTP/1.1\r\n' + 'Host: localhost\r\n' + 'Connection: keep-alive\r\n' + 'Content-Type: multipart/form-data; boundary=----aaa\r\n' + 'Content-Length: 13\r\n\r\n' + - '------aaa--\r\n'); + '------aaa--\r\n', + ); - setTimeout(function () { - assert.strictEqual(ok, 1, 'should ok count === 1, has: ' + ok); + setTimeout(() => { + assert.strictEqual(ok, 1, `should ok count === 1, has: ${ok}`); // TODO: fix it! // assert.strictEqual(errors, 1, 'should errors count === 1, has: ' + errors); + console.log('should errors === 1', errors); client.end(); server.close(); }, 100); diff --git a/test/unit/test-file.js b/test/unit/test-file.js index 1a5f044b..b77ee130 100644 --- a/test/unit/test-file.js +++ b/test/unit/test-file.js @@ -1,12 +1,15 @@ -var common = require('../common'); -var test = require('utest'); -var assert = common.assert; -var File = common.require('file'); +'use strict'; + +const assert = require('assert'); +const test = require('utest'); + +const { File } = require('../../src/file'); + +let file; +const now = new Date(); -var file; -var now = new Date(); test('IncomingForm', { - before: function() { + before() { file = new File({ size: 1024, path: '/tmp/cat.png', @@ -14,13 +17,13 @@ test('IncomingForm', { type: 'image/png', lastModifiedDate: now, filename: 'cat.png', - mime: 'image/png' + mime: 'image/png', }); }, - '#toJSON()': function() { - var obj = file.toJSON(); - var len = Object.keys(obj).length; + '#toJSON()': () => { + const obj = file.toJSON(); + const len = Object.keys(obj).length; assert.equal(1024, obj.size); assert.equal('/tmp/cat.png', obj.path); assert.equal('cat.png', obj.name); @@ -29,5 +32,5 @@ test('IncomingForm', { assert.equal('cat.png', obj.filename); assert.equal(now, obj.mtime); assert.equal(len, 8); - } + }, }); diff --git a/test/unit/test-incoming-form.js b/test/unit/test-incoming-form.js index 4ec7f16b..539a94be 100644 --- a/test/unit/test-incoming-form.js +++ b/test/unit/test-incoming-form.js @@ -1,103 +1,108 @@ -var common = require('../common'); -var test = require('utest'); -var assert = common.assert; -var IncomingForm = common.require('incoming_form').IncomingForm; -var path = require('path'); -var Request = require('http').ClientRequest - -var form; +/* eslint-disable no-underscore-dangle */ + +'use strict'; + +const path = require('path'); +const assert = require('assert'); +const Request = require('http').ClientRequest; + +const test = require('utest'); +const { IncomingForm } = require('../../src/incoming_form'); + +let form; + test('IncomingForm', { - before: function() { + before() { form = new IncomingForm(); }, - '#_fileName with regular characters': function() { - var filename = 'foo.txt'; - console.log('xxxxxxxxxxxx1') + '#_fileName with regular characters': () => { + const filename = 'foo.txt'; + console.log('xxxxxxxxxxxx1'); assert.equal(form._fileName(makeHeader(filename)), 'foo.txt'); - console.log('xxxxxxxxxxxx1') + console.log('xxxxxxxxxxxx1'); }, - '#_fileName with unescaped quote': function() { - var filename = 'my".txt'; - console.log('xxxxxxxxxxxx2') + '#_fileName with unescaped quote': () => { + const filename = 'my".txt'; + console.log('xxxxxxxxxxxx2'); assert.equal(form._fileName(makeHeader(filename)), 'my".txt'); - console.log('xxxxxxxxxxxx2') + console.log('xxxxxxxxxxxx2'); }, - '#_fileName with escaped quote': function() { - var filename = 'my%22.txt'; - console.log('xxxxxxxxxxxx3') + '#_fileName with escaped quote': () => { + const filename = 'my%22.txt'; + console.log('xxxxxxxxxxxx3'); assert.equal(form._fileName(makeHeader(filename)), 'my".txt'); - console.log('xxxxxxxxxxxx3') + console.log('xxxxxxxxxxxx3'); }, - '#_fileName with bad quote and additional sub-header': function() { - var filename = 'my".txt'; - console.log('xxxxxxxxxxxx4') - var header = makeHeader(filename) + '; foo="bar"'; + '#_fileName with bad quote and additional sub-header': () => { + const filename = 'my".txt'; + console.log('xxxxxxxxxxxx4'); + const header = `${makeHeader(filename)}; foo="bar"`; assert.equal(form._fileName(header), filename); - console.log('xxxxxxxxxxxx4') + console.log('xxxxxxxxxxxx4'); }, - '#_fileName with semicolon': function() { - var filename = 'my;.txt'; - console.log('xxxxxxxxxxxx5') + '#_fileName with semicolon': () => { + const filename = 'my;.txt'; + console.log('xxxxxxxxxxxx5'); assert.equal(form._fileName(makeHeader(filename)), 'my;.txt'); - console.log('xxxxxxxxxxxx5') + console.log('xxxxxxxxxxxx5'); }, - '#_fileName with utf8 character': function() { - var filename = 'my☃.txt'; - console.log('xxxxxxxxxxxx6') + '#_fileName with utf8 character': () => { + const filename = 'my☃.txt'; + console.log('xxxxxxxxxxxx6'); assert.equal(form._fileName(makeHeader(filename)), 'my☃.txt'); - console.log('xxxxxxxxxxxx6') + console.log('xxxxxxxxxxxx6'); }, - '#_uploadPath strips harmful characters from extension when keepExtensions': function() { + '#_uploadPath strips harmful characters from extension when keepExtensions': () => { form.keepExtensions = true; - console.log('xxxxxxxxxxxx7.1') + console.log('xxxxxxxxxxxx7.1'); - var ext = path.extname(form._uploadPath('fine.jpg?foo=bar')); + let ext = path.extname(form._uploadPath('fine.jpg?foo=bar')); assert.equal(ext, '.jpg'); - console.log('xxxxxxxxxxxx7.2') + console.log('xxxxxxxxxxxx7.2'); ext = path.extname(form._uploadPath('fine?foo=bar')); assert.equal(ext, ''); - console.log('xxxxxxxxxxxx7.3') + console.log('xxxxxxxxxxxx7.3'); ext = path.extname(form._uploadPath('super.cr2+dsad')); assert.equal(ext, '.cr2'); - console.log('xxxxxxxxxxxx7.4') + console.log('xxxxxxxxxxxx7.4'); ext = path.extname(form._uploadPath('super.bar')); assert.equal(ext, '.bar'); - console.log('xxxxxxxxxxxx7.5') + console.log('xxxxxxxxxxxx7.5'); ext = path.extname(form._uploadPath('file.aAa')); assert.equal(ext, '.aAa'); - console.log('xxxxxxxxxxxx7.6') + console.log('xxxxxxxxxxxx7.6'); }, - '#_Array parameters support': function () { - console.log('xxxxxxxxxxxx8') - form = new IncomingForm({multiples: true}); + '#_Array parameters support': () => { + console.log('xxxxxxxxxxxx8'); + form = new IncomingForm({ multiples: true }); const req = new Request(); - req.headers = 'content-type: json; content-length:8' - form.parse(req, function (error, fields, files) { - console.log('xxxxxxxxxxxx8.1') + req.headers = 'content-type: json; content-length:8'; + form.parse(req, (error, fields) => { + console.log('xxxxxxxxxxxx8.1'); assert.equal(Array.isArray(fields.a), true); assert.equal(fields.a[0], 1); assert.equal(fields.a[1], 2); - console.log('xxxxxxxxxxxx8.2') - }) + console.log('xxxxxxxxxxxx8.2'); + }); form.emit('field', 'a[]', 1); form.emit('field', 'a[]', 2); form.emit('end'); - console.log('xxxxxxxxxxxx8') + console.log('xxxxxxxxxxxx8'); }, }); function makeHeader(filename) { - return 'Content-Disposition: form-data; name="upload"; filename="' + filename + '"'; + return `Content-Disposition: form-data; name="upload"; filename="${filename}"`; } diff --git a/tool/record.js b/tool/record.js index 9f1cef86..0b133315 100644 --- a/tool/record.js +++ b/tool/record.js @@ -1,47 +1,51 @@ -var http = require('http'); -var fs = require('fs'); -var connections = 0; +/* eslint-disable no-param-reassign */ +const http = require('http'); +const fs = require('fs'); -var server = http.createServer(function(req, res) { - var socket = req.socket; +let connections = 0; + +const server = http.createServer((req, res) => { + const { socket } = req; console.log('Request: %s %s -> %s', req.method, req.url, socket.filename); - req.on('end', function() { + req.on('end', () => { if (req.url !== '/') { - res.end(JSON.stringify({ - method: req.method, - url: req.url, - filename: socket.filename, - })); + res.end( + JSON.stringify({ + method: req.method, + url: req.url, + filename: socket.filename, + }), + ); return; } - res.writeHead(200, {'content-type': 'text/html'}); + res.writeHead(200, { 'content-type': 'text/html' }); res.end( - '
'+ - '
'+ - '
'+ - ''+ - '
' + '
' + + '
' + + '
' + + '' + + '
', ); }); }); -server.on('connection', function(socket) { - connections++; +server.on('connection', (socket) => { + connections += 1; socket.id = connections; - socket.filename = 'connection-' + socket.id + '.http'; + socket.filename = `connection-${socket.id}.http`; socket.file = fs.createWriteStream(socket.filename); socket.pipe(socket.file); console.log('--> %s', socket.filename); - socket.on('close', function() { + socket.on('close', () => { console.log('<-- %s', socket.filename); }); }); -var port = process.env.PORT || 8080; -server.listen(port, function() { +const port = process.env.PORT || 8080; +server.listen(port, () => { console.log('Recording connections on port %s', port); }); diff --git a/yarn.lock b/yarn.lock index 721b869d..5ec18cf9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,83 @@ # yarn lockfile v1 -ajv@^6.5.5: +"@babel/code-frame@^7.0.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== + dependencies: + "@babel/highlight" "^7.8.3" + +"@babel/highlight@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" + integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@tunnckocore/prettier-config@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@tunnckocore/prettier-config/-/prettier-config-1.2.0.tgz#4d2aab462d45353367656bc4b98b1065469bef7c" + integrity sha512-/awVnPbFD2YMNbhfrhbAA7Z3jMTPmEYhbXZsqqVoC8nsP6GGELc5CFTPHAZHPFjJrjlwIDyJB6KRo+Rn46342g== + +"@types/events@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" + integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== + +"@types/glob@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" + integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== + +"@types/node@*": + version "13.5.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.5.0.tgz#4e498dbf355795a611a87ae5ef811a8660d42662" + integrity sha512-Onhn+z72D2O2Pb2ql2xukJ55rglumsVo1H6Fmyi8mlU9SvKdBk/pUSUAiBY/d9bAOF7VVWajX3sths/+g6ZiAQ== + +acorn-jsx@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" + integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== + +acorn@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" + integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== + +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: version "6.11.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.11.0.tgz#c3607cbc8ae392d8a5a536f25b21f8e5f3f87fe9" integrity sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA== @@ -12,6 +88,59 @@ ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-escapes@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" + integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== + dependencies: + type-fest "^0.8.1" + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +array-includes@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" + integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0" + is-string "^1.0.5" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.flat@^1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" + integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -24,6 +153,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -39,6 +173,11 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -46,17 +185,68 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -"chainsaw@>=0.0.7 <0.1": - version "0.0.9" - resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.0.9.tgz#11a05102d1c4c785b6d0415d336d5a3a1612913e" - integrity sha1-EaBRAtHEx4W20EFdM21aOhYSkT4= +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: - traverse ">=0.3.0 <0.4" + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" @@ -65,11 +255,37 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +confusing-browser-globals@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd" + integrity sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw== + +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= + core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -77,11 +293,69 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= +detect-indent@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd" + integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA== + +detect-newline@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -90,11 +364,226 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +error-ex@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.17.0, es-abstract@^1.17.0-next.1: + version "1.17.4" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184" + integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ== + dependencies: + 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-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-config-airbnb-base@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.0.0.tgz#8a7bcb9643d13c55df4dd7444f138bf4efa61e17" + integrity sha512-2IDHobw97upExLmsebhtfoD3NAKhV4H0CJWP3Uprd/uk+cHuWYOczPVxQ8PxLFUAw7o3Th1RAU8u1DoUpr+cMA== + dependencies: + confusing-browser-globals "^1.0.7" + object.assign "^4.1.0" + object.entries "^1.1.0" + +eslint-config-prettier@^6.10.0: + version "6.10.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.0.tgz#7b15e303bf9c956875c948f6b21500e48ded6a7f" + integrity sha512-AtndijGte1rPILInUdHjvKEGbIV06NuvPrqlIEaEaWtbtvJh464mDeyGMdZEQMsGvC0ZVkiex1fSNcC4HAbRGg== + dependencies: + get-stdin "^6.0.0" + +eslint-import-resolver-node@^0.3.2: + version "0.3.3" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz#dbaa52b6b2816b50bc6711af75422de808e98404" + integrity sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg== + dependencies: + debug "^2.6.9" + resolve "^1.13.1" + +eslint-module-utils@^2.4.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz#7878f7504824e1b857dd2505b59a8e5eda26a708" + integrity sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q== + dependencies: + debug "^2.6.9" + pkg-dir "^2.0.0" + +eslint-plugin-import@^2.20.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.0.tgz#d749a7263fb6c29980def8e960d380a6aa6aecaa" + integrity sha512-NK42oA0mUc8Ngn4kONOPsPB1XhbUvNHqF+g307dPV28aknPoiNnKLFd9em4nkswwepdF5ouieqv5Th/63U7YJQ== + dependencies: + array-includes "^3.0.3" + array.prototype.flat "^1.2.1" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.4.1" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.0" + read-pkg-up "^2.0.0" + resolve "^1.12.0" + +eslint-plugin-prettier@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" + integrity sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-scope@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" + integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-utils@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== + +eslint@^6.8.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" + integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^5.0.0" + eslint-utils "^1.4.3" + eslint-visitor-keys "^1.1.0" + espree "^6.1.2" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.14" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.3" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" + integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== + dependencies: + acorn "^7.1.0" + acorn-jsx "^5.1.0" + eslint-visitor-keys "^1.1.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -110,17 +599,80 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.1.tgz#87ee30e9e9f3eb40d6f254a7997655da753d7c82" + integrity sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -findit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/findit/-/findit-0.1.2.tgz#ac7fe600cd6a32a35672836b74cf6f1dde2e11f8" - integrity sha1-rH/mAM1qMqNWcoNrdM9vHd4uEfg= +fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fastq@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" + integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== + dependencies: + reusify "^1.0.0" + +figures@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" + integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== dependencies: - seq ">=0.1.7" + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== forever-agent@~0.6.1: version "0.6.1" @@ -136,6 +688,26 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -143,6 +715,56 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +git-hooks-list@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/git-hooks-list/-/git-hooks-list-1.0.2.tgz#b023b76872f00d81b353efd1458fb4a165035575" + integrity sha512-C3c/FG6Pgh053+yK/CnNNYJo5mgCa3OeI+cPxPIl0tyMLm1mGfiV0NX0LrhnjVoX7dfkR78WyW2kvFVHvAlneg== + +glob-parent@^5.0.0, glob-parent@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + dependencies: + is-glob "^4.0.1" + +glob@^7.1.3: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + 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" + +globals@^12.1.0: + version "12.3.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" + integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw== + dependencies: + type-fest "^0.8.1" + +globby@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" + integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + +graceful-fs@^4.1.2: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -156,12 +778,27 @@ har-validator@~5.1.0: ajv "^6.5.5" har-schema "^2.0.0" -"hashish@>=0.0.2 <0.1", hashish@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/hashish/-/hashish-0.0.4.tgz#6d60bc6ffaf711b6afd60e426d077988014e6554" - integrity sha1-bWC8b/r3Ebav1g5CbQd5iAFOZVQ= +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-symbols@^1.0.0, has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: - traverse ">=0.2.4" + function-bind "^1.1.1" + +hosted-git-info@^2.1.4: + version "2.8.5" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" + integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== http-signature@~1.2.0: version "1.2.0" @@ -172,16 +809,167 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.1: + version "5.1.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" + integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== + +import-fresh@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" + integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inquirer@^7.0.0: + version "7.0.4" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.4.tgz#99af5bde47153abca23f5c7fc30db247f39da703" + integrity sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ== + dependencies: + ansi-escapes "^4.2.1" + chalk "^2.4.2" + cli-cursor "^3.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.15" + mute-stream "0.0.8" + run-async "^2.2.0" + rxjs "^6.5.3" + string-width "^4.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== + +is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= + +is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== + dependencies: + has "^1.0.3" + +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== + +is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +isarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -197,6 +985,11 @@ json-schema@0.2.3: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -212,6 +1005,50 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lodash@^4.17.14, lodash@^4.17.15: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +merge2@^1.2.3, merge2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + mime-db@1.43.0: version "1.43.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" @@ -224,16 +1061,257 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: mime-db "1.43.0" +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== +object-inspect@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.entries@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b" + integrity sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + +object.values@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + +optionator@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + dependencies: + pify "^2.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= +picomatch@^2.0.5: + version "2.2.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" + integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier-plugin-pkgjson@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/prettier-plugin-pkgjson/-/prettier-plugin-pkgjson-0.2.0.tgz#2011814bd44031be7ad4adcefff6859433865487" + integrity sha512-T0Cdq7mEnZOC1fNYE17udCsgo+WShthXeFf2IXXcMRTJHmOgLkHDAOwvcEUTX2U1MyrgjRdlwMUn25TZ93MJGA== + dependencies: + sort-package-json "^1.39.0" + +prettier@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + psl@^1.1.24: version "1.7.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" @@ -254,6 +1332,28 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + request@^2.11.4: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" @@ -280,23 +1380,154 @@ request@^2.11.4: tunnel-agent "^0.6.0" uuid "^3.3.2" +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1: + version "1.15.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.0.tgz#1b7ca96073ebb52e741ffd799f6b39ea462c67f5" + integrity sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw== + dependencies: + path-parse "^1.0.6" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +reusify@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= + dependencies: + is-promise "^2.1.0" + +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + +rxjs@^6.5.3: + version "6.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" + integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== + dependencies: + tslib "^1.9.0" + safe-buffer@^5.0.1, safe-buffer@^5.1.2: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== -safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -seq@>=0.1.7: - version "0.3.5" - resolved "https://registry.yarnpkg.com/seq/-/seq-0.3.5.tgz#ae02af3a424793d8ccbf212d69174e0c54dffe38" - integrity sha1-rgKvOkJHk9jMvyEtaRdODFTf/jg= +"semver@2 || 3 || 4 || 5", semver@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.1.2: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +sort-object-keys@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" + integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg== + +sort-package-json@^1.39.0: + version "1.39.1" + resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-1.39.1.tgz#ac4d8464a1bdf980aa86cd790b876fb5708b7bf0" + integrity sha512-ibynHvDF6jfSpA7tok+larZUPQ4YLm4YO6nP9Iov1NuGsMyvkYm3hmKAA6LdXxwOXzqBqJjedk0rMZ2Sbyra4Q== + dependencies: + detect-indent "^6.0.0" + detect-newline "3.1.0" + git-hooks-list "1.0.2" + globby "10.0.1" + sort-object-keys "^1.1.3" + +spdx-correct@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== dependencies: - chainsaw ">=0.0.7 <0.1" - hashish ">=0.0.2 <0.1" + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: version "1.16.1" @@ -313,6 +1544,105 @@ sshpk@^1.7.0: safer-buffer "^2.0.2" tweetnacl "~0.14.0" +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string.prototype.trimleft@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" + integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" + integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-json-comments@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" @@ -321,15 +1651,10 @@ tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.1" -traverse@>=0.2.4: - version "0.6.6" - resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" - integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= - -"traverse@>=0.3.0 <0.4": - version "0.3.9" - resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" - integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk= +tslib@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== tunnel-agent@^0.6.0: version "0.6.0" @@ -343,6 +1668,18 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" @@ -372,6 +1709,19 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +v8-compile-cache@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" + integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -380,3 +1730,27 @@ verror@1.10.0: assert-plus "^1.0.0" core-util-is "1.0.2" extsprintf "^1.2.0" + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1"